[NWD] Move EPPlus classes to a new namespace.
Also rename the assembly.
This will allow us to have both the legacy and new EPPlus version
referenced in AppSheet for a slow rollout.
Change-Id: Idf4c4d2423041d626d6e4185d7de53b7b786164f
Reviewed-on: https://gnocchi-internal-review.git.corp.google.com/c/third_party/epplus/+/229480
Reviewed-by: Hughes Hilton <hugheshilton@google.com>
diff --git a/AppsheetEpplus/AppsheetEpplus.csproj b/AppsheetEpplus/AppsheetEpplus.csproj
new file mode 100644
index 0000000..e8379f7
--- /dev/null
+++ b/AppsheetEpplus/AppsheetEpplus.csproj
@@ -0,0 +1,7 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <TargetFramework>net8.0</TargetFramework>
+ <PackageId>Appsheet.AppsheetEpplus</PackageId>
+ <Version>1.0.9</Version>
+ </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/AppsheetEpplus/CellStore.cs b/AppsheetEpplus/CellStore.cs
new file mode 100644
index 0000000..8632da5
--- /dev/null
+++ b/AppsheetEpplus/CellStore.cs
@@ -0,0 +1,1492 @@
+/*******************************************************************************
+ * 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 2012-11-25
+ *******************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+internal class IndexBase : IComparable<IndexBase> {
+ internal short Index;
+
+ public int CompareTo(IndexBase other) {
+ return Index < other.Index
+ ? -1
+ : Index > other.Index
+ ? 1
+ : 0;
+ }
+}
+
+internal class IndexItem : IndexBase {
+ internal int IndexPointer { get; set; }
+}
+
+internal class ColumnIndex : IndexBase {
+ private readonly IndexBase _searchIx = new();
+
+ internal int GetPosition(int row) {
+ var page = (short)(row >> CellStore<int>._pageBits);
+ _searchIx.Index = page;
+ var res =
+ (_pages != null
+ && page >= 0
+ && page < PageCount
+ && page < _pages.Length
+ && _pages[page] != null
+ && _pages[page].Index == page)
+ ? page
+ : Array.BinarySearch(_pages, 0, PageCount, _searchIx);
+ if (res >= 0) {
+ GetPage(row, ref res);
+ return res;
+ }
+ var p = ~res;
+
+ if (GetPage(row, ref p)) {
+ return p;
+ }
+ return res;
+ }
+
+ private bool GetPage(int row, ref int res) {
+ if (res < PageCount && _pages[res].MinIndex <= row && _pages[res].MaxIndex >= row) {
+ return true;
+ }
+ if (res + 1 < PageCount && (_pages[res + 1].MinIndex <= row)) {
+ do {
+ res++;
+ } while (res + 1 < PageCount && _pages[res + 1].MinIndex <= row);
+ //if (res + 1 < PageCount && _pages[res + 1].MaxIndex >= Row)
+ //{
+ return true;
+ //}
+ //else
+ //{
+ // return false;
+ //}
+ }
+ if (res - 1 >= 0 && _pages[res - 1].MaxIndex >= row) {
+ do {
+ res--;
+ } while (res - 1 > 0 && _pages[res - 1].MaxIndex >= row);
+ //if (res > 0)
+ //{
+ return true;
+ //}
+ //else
+ //{
+ // return false;
+ //}
+ }
+ return false;
+ }
+
+ internal int GetNextRow(int row) {
+ //var page = (int)((ulong)row >> CellStore<int>.pageBits);
+ var p = GetPosition(row);
+ if (p < 0) {
+ p = ~p;
+ if (p >= PageCount) {
+ return -1;
+ }
+ if (_pages[p].IndexOffset + _pages[p].Rows[0].Index < row) {
+ if (p + 1 >= PageCount) {
+ return -1;
+ }
+ return _pages[p + 1].IndexOffset + _pages[p].Rows[0].Index;
+ }
+ return _pages[p].IndexOffset + _pages[p].Rows[0].Index;
+ }
+ if (p < PageCount) {
+ var r = _pages[p].GetNextRow(row);
+ if (r >= 0) {
+ return _pages[p].IndexOffset + _pages[p].Rows[r].Index;
+ } else {
+ if (++p < PageCount) {
+ return _pages[p].IndexOffset + _pages[p].Rows[0].Index;
+ } else {
+ return -1;
+ }
+ }
+ }
+ return -1;
+ }
+
+ internal PageIndex[] _pages = new PageIndex[CellStore<int>._pagesPerColumnMin];
+ internal int PageCount;
+}
+
+internal class PageIndex : IndexBase {
+ private readonly IndexBase _searchIx = new();
+
+ public PageIndex() {
+ Rows = new IndexItem[CellStore<int>._pageSizeMin];
+ RowCount = 0;
+ }
+
+ public PageIndex(IndexItem[] rows, int count) {
+ Rows = rows;
+ RowCount = count;
+ }
+
+ public PageIndex(PageIndex pageItem, int start, int size)
+ : this(pageItem, start, size, pageItem.Index, pageItem.Offset) {}
+
+ public PageIndex(PageIndex pageItem, int start, int size, short index, int offset) {
+ Rows = new IndexItem[CellStore<int>.GetSize(size)];
+ Array.Copy(pageItem.Rows, start, Rows, 0, size);
+ RowCount = size;
+ Index = index;
+ Offset = offset;
+ }
+
+ internal int Offset;
+
+ internal int IndexOffset => IndexExpanded + Offset;
+
+ internal int IndexExpanded => (Index << CellStore<int>._pageBits);
+
+ internal IndexItem[] Rows { get; set; }
+
+ internal int RowCount;
+
+ internal int GetPosition(int offset) {
+ _searchIx.Index = (short)offset;
+ return (Rows != null
+ && offset > 0
+ && offset - 1 < RowCount
+ && offset - 1 < Rows.Length
+ && Rows[offset - 1] != null
+ && Rows[offset - 1].Index == offset)
+ ? offset - 1
+ : Array.BinarySearch(Rows, 0, RowCount, _searchIx);
+ }
+
+ internal int GetNextRow(int row) {
+ int offset = row - IndexOffset;
+ var o = GetPosition(offset);
+ if (o < 0) {
+ o = ~o;
+ if (o < RowCount) {
+ return o;
+ }
+ return -1;
+ }
+ return o;
+ }
+
+ public int MinIndex {
+ get {
+ if (Rows.Length > 0) {
+ return IndexOffset + Rows[0].Index;
+ }
+ return -1;
+ }
+ }
+
+ public int MaxIndex {
+ get {
+ if (RowCount > 0) {
+ return IndexOffset + Rows[RowCount - 1].Index;
+ }
+ return -1;
+ }
+ }
+
+ public int GetIndex(int pos) {
+ return IndexOffset + Rows[pos].Index;
+ }
+}
+
+/// <summary>
+/// This is the store for all Rows, Columns and Cells.
+/// It is a Dictionary implementation that allows you to change the Key (the RowID, ColumnID or CellID )
+/// </summary>
+internal class CellStore<T> {
+ /**** Size constants ****/
+ internal const int _pageBits = 10; //13bits=8192 Note: Maximum is 13 bits since short is used (PageMax=16K)
+ internal const int _pageSize = 1 << _pageBits;
+ internal const int _pageSizeMin = 1 << 10;
+ internal const int _pageSizeMax = _pageSize << 1; //Double page size
+ internal const int _colSizeMin = 32;
+ internal const int _pagesPerColumnMin = 32;
+
+ private List<T> _values = new();
+ internal ColumnIndex[] _columnIndex = new ColumnIndex[_colSizeMin];
+ internal IndexBase _searchIx = new();
+ internal int ColumnCount;
+
+ ~CellStore() {
+ if (_values != null) {
+ _values.Clear();
+ _values = null;
+ }
+ _columnIndex = null;
+ }
+
+ internal int GetPosition(int column) {
+ _searchIx.Index = (short)column;
+ return (_columnIndex != null
+ && column > 0
+ && column - 1 < ColumnCount
+ && column - 1 < _columnIndex.Length
+ && _columnIndex[column - 1] != null
+ && _columnIndex[column - 1].Index == column)
+ ? column - 1
+ : Array.BinarySearch(_columnIndex, 0, ColumnCount, _searchIx);
+ }
+
+ internal bool GetDimension(out int fromRow, out int fromCol, out int toRow, out int toCol) {
+ if (ColumnCount == 0) {
+ fromRow = fromCol = toRow = toCol = 0;
+ return false;
+ }
+ fromCol = _columnIndex[0].Index;
+ var fromIndex = 0;
+ if (fromCol <= 0 && ColumnCount > 1) {
+ fromCol = _columnIndex[1].Index;
+ fromIndex = 1;
+ } else if (ColumnCount == 1 && fromCol <= 0) {
+ fromRow = fromCol = toRow = toCol = 0;
+ return false;
+ }
+ var col = ColumnCount - 1;
+ while (col > 0) {
+ if (_columnIndex[col].PageCount == 0
+ || _columnIndex[col]._pages[0].RowCount > 1
+ || _columnIndex[col]._pages[0].Rows[0].Index > 0) {
+ break;
+ }
+ col--;
+ }
+ toCol = _columnIndex[col].Index;
+ if (toCol == 0) {
+ fromRow = fromCol = toRow = toCol = 0;
+ return false;
+ }
+ fromRow = toRow = 0;
+
+ for (int c = fromIndex; c < ColumnCount; c++) {
+ int first,
+ last;
+ if (_columnIndex[c].PageCount == 0) {
+ continue;
+ }
+ if (_columnIndex[c]._pages[0].RowCount > 0 && _columnIndex[c]._pages[0].Rows[0].Index > 0) {
+ first = _columnIndex[c]._pages[0].IndexOffset + _columnIndex[c]._pages[0].Rows[0].Index;
+ } else {
+ if (_columnIndex[c]._pages[0].RowCount > 1) {
+ first = _columnIndex[c]._pages[0].IndexOffset + _columnIndex[c]._pages[0].Rows[1].Index;
+ } else if (_columnIndex[c].PageCount > 1) {
+ first = _columnIndex[c]._pages[0].IndexOffset + _columnIndex[c]._pages[1].Rows[0].Index;
+ } else {
+ first = 0;
+ }
+ }
+ var lp = _columnIndex[c].PageCount - 1;
+ while (_columnIndex[c]._pages[lp].RowCount == 0 && lp != 0) {
+ lp--;
+ }
+ var p = _columnIndex[c]._pages[lp];
+ if (p.RowCount > 0) {
+ last = p.IndexOffset + p.Rows[p.RowCount - 1].Index;
+ } else {
+ last = first;
+ }
+ if (first > 0 && (first < fromRow || fromRow == 0)) {
+ fromRow = first;
+ }
+ if (first > 0 && (last > toRow || toRow == 0)) {
+ toRow = last;
+ }
+ }
+ if (fromRow <= 0 || toRow <= 0) {
+ fromRow = fromCol = toRow = toCol = 0;
+ return false;
+ }
+ return true;
+ }
+
+ internal int FindNext(int column) {
+ var c = GetPosition(column);
+ if (c < 0) {
+ return ~c;
+ }
+ return c;
+ }
+
+ internal T GetValue(int row, int column) {
+ int i = GetPointer(row, column);
+ if (i >= 0) {
+ return _values[i];
+ }
+ return default(T);
+ }
+
+ private int GetPointer(int row, int column) {
+ var col = GetPosition(column);
+ if (col >= 0) {
+ var pos = _columnIndex[col].GetPosition(row);
+ if (pos >= 0 && pos < _columnIndex[col].PageCount) {
+ var pageItem = _columnIndex[col]._pages[pos];
+ if (pageItem.MinIndex > row) {
+ pos--;
+ if (pos < 0) {
+ return -1;
+ }
+ pageItem = _columnIndex[col]._pages[pos];
+ }
+ short ix = (short)(row - pageItem.IndexOffset);
+ _searchIx.Index = ix;
+ var cellPos =
+ (pageItem.Rows != null
+ && ix > 0
+ && ix - 1 < pageItem.RowCount
+ && ix - 1 < pageItem.Rows.Length
+ && pageItem.Rows[ix - 1] != null
+ && pageItem.Rows[ix - 1].Index == ix)
+ ? ix - 1
+ : Array.BinarySearch(pageItem.Rows, 0, pageItem.RowCount, _searchIx);
+ if (cellPos >= 0) {
+ return pageItem.Rows[cellPos].IndexPointer;
+ } //Cell does not exist
+ return -1;
+ } //Page does not exist
+ return -1;
+ } //Column does not exist
+ return -1;
+ }
+
+ internal bool Exists(int row, int column) {
+ return GetPointer(row, column) >= 0;
+ }
+
+ internal bool Exists(int row, int column, ref T value) {
+ var p = GetPointer(row, column);
+ if (p >= 0) {
+ value = _values[p];
+ return true;
+ }
+ return false;
+ }
+
+ internal void SetValue(int row, int column, T value) {
+ var col =
+ (_columnIndex != null
+ && column > 0
+ && column - 1 < ColumnCount
+ && column - 1 < _columnIndex.Length
+ && _columnIndex[column - 1] != null
+ && _columnIndex[column - 1].Index == column)
+ ? column - 1
+ : Array.BinarySearch(
+ _columnIndex,
+ 0,
+ ColumnCount,
+ new IndexBase {
+ Index = (short)(column),
+ });
+ var page = (short)(row >> _pageBits);
+ if (col >= 0) {
+ //var pos = Array.BinarySearch(_columnIndex[col].Pages, 0, _columnIndex[col].Count, new IndexBase() { Index = page });
+ var pos = _columnIndex[col].GetPosition(row);
+ if (pos < 0) {
+ pos = ~pos;
+ if (pos - 1 < 0 || _columnIndex[col]._pages[pos - 1].IndexOffset + _pageSize - 1 < row) {
+ AddPage(_columnIndex[col], pos, page);
+ } else {
+ pos--;
+ }
+ }
+ if (pos >= _columnIndex[col].PageCount) {
+ AddPage(_columnIndex[col], pos, page);
+ }
+ var pageItem = _columnIndex[col]._pages[pos];
+ if (pageItem.IndexOffset > row) {
+ pos--;
+ page--;
+ if (pos < 0) {
+ throw (new("Unexpected error when setting value"));
+ }
+ pageItem = _columnIndex[col]._pages[pos];
+ }
+
+ short ix = (short)(row - ((pageItem.Index << _pageBits) + pageItem.Offset));
+ _searchIx.Index = ix;
+ var cellPos =
+ (pageItem.Rows != null
+ && ix >= 0
+ && ix < pageItem.RowCount
+ && ix < pageItem.Rows.Length
+ && pageItem.Rows[ix] != null
+ && pageItem.Rows[ix].Index == ix)
+ ? ix
+ : Array.BinarySearch(pageItem.Rows, 0, pageItem.RowCount, _searchIx);
+ if (cellPos < 0) {
+ cellPos = ~cellPos;
+ AddCell(_columnIndex[col], pos, cellPos, ix, value);
+ } else {
+ _values[pageItem.Rows[cellPos].IndexPointer] = value;
+ }
+ } else //Column does not exist
+ {
+ col = ~col;
+ AddColumn(col, column);
+ AddPage(_columnIndex[col], 0, page);
+ short ix = (short)(row - (page << _pageBits));
+ AddCell(_columnIndex[col], 0, 0, ix, value);
+ }
+ }
+
+ internal void Insert(int fromRow, int fromCol, int rows, int columns) {
+ if (columns > 0) {
+ var col = GetPosition(fromCol);
+ if (col < 0) {
+ col = ~col;
+ }
+ for (var c = col; c < ColumnCount; c++) {
+ _columnIndex[c].Index += (short)columns;
+ }
+ } else {
+ var page = fromRow >> _pageBits;
+ for (int c = 0; c < ColumnCount; c++) {
+ var column = _columnIndex[c];
+ var pagePos = column.GetPosition(fromRow);
+ if (pagePos >= 0) {
+ if (fromRow >= column._pages[pagePos].MinIndex
+ && fromRow
+ <= column._pages[pagePos].MaxIndex) //The row is inside the page
+ {
+ int offset = fromRow - column._pages[pagePos].IndexOffset;
+ var rowPos = column._pages[pagePos].GetPosition(offset);
+ if (rowPos < 0) {
+ rowPos = ~rowPos;
+ }
+ UpdateIndexOffset(column, pagePos, rowPos, fromRow, rows);
+ } else if (column._pages[pagePos].MinIndex > fromRow - 1
+ && pagePos
+ > 0) //The row is on the page before.
+ {
+ int offset = fromRow - ((page - 1) << _pageBits);
+ var rowPos = column._pages[pagePos - 1].GetPosition(offset);
+ if (rowPos > 0 && pagePos > 0) {
+ UpdateIndexOffset(column, pagePos - 1, rowPos, fromRow, rows);
+ }
+ } else if (column.PageCount >= pagePos + 1) {
+ int offset = fromRow - column._pages[pagePos].IndexOffset;
+ var rowPos = column._pages[pagePos].GetPosition(offset);
+ if (rowPos < 0) {
+ rowPos = ~rowPos;
+ }
+ if (column._pages[pagePos].RowCount > rowPos) {
+ UpdateIndexOffset(column, pagePos, rowPos, fromRow, rows);
+ } else {
+ UpdateIndexOffset(column, pagePos + 1, 0, fromRow, rows);
+ }
+ }
+ } else {
+ UpdateIndexOffset(column, ~pagePos, 0, fromRow, rows);
+ }
+ }
+ }
+ }
+
+ internal void Clear(int fromRow, int fromCol, int rows, int columns) {
+ Delete(fromRow, fromCol, rows, columns, false);
+ }
+
+ internal void Delete(int fromRow, int fromCol, int rows, int columns) {
+ Delete(fromRow, fromCol, rows, columns, true);
+ }
+
+ internal void Delete(int fromRow, int fromCol, int rows, int columns, bool shift) {
+ if (columns > 0 && fromRow == 1 && rows >= ExcelPackage.MaxRows) {
+ DeleteColumns(fromCol, columns, shift);
+ } else {
+ var toCol = fromCol + columns - 1;
+ var pageFromRow = fromRow >> _pageBits;
+ for (int c = 0; c < ColumnCount; c++) {
+ var column = _columnIndex[c];
+ if (column.Index >= fromCol) {
+ if (column.Index > toCol) {
+ break;
+ }
+ var pagePos = column.GetPosition(fromRow);
+ if (pagePos < 0) {
+ pagePos = ~pagePos;
+ }
+ if (pagePos < column.PageCount) {
+ var page = column._pages[pagePos];
+ if (shift
+ && page.RowCount > 0
+ && page.MinIndex > fromRow
+ && page.MaxIndex >= fromRow + rows) {
+ var o = page.MinIndex - fromRow;
+ if (o < rows) {
+ rows -= o;
+ page.Offset -= o;
+ UpdatePageOffset(column, pagePos, o);
+ } else {
+ page.Offset -= rows;
+ UpdatePageOffset(column, pagePos, rows);
+ continue;
+ }
+ }
+ if (page.RowCount > 0
+ && page.MinIndex <= fromRow + rows - 1
+ && page.MaxIndex
+ >= fromRow) //The row is inside the page
+ {
+ var endRow = fromRow + rows;
+ var delEndRow = DeleteCells(column._pages[pagePos], fromRow, endRow, shift);
+ if (shift && delEndRow != fromRow) {
+ UpdatePageOffset(column, pagePos, delEndRow - fromRow);
+ }
+ if (endRow > delEndRow
+ && pagePos < column.PageCount
+ && column._pages[pagePos].MinIndex < endRow) {
+ pagePos = (delEndRow == fromRow ? pagePos : pagePos + 1);
+ var rowsLeft = DeletePage(
+ shift ? fromRow : delEndRow,
+ endRow - delEndRow,
+ column,
+ pagePos,
+ shift);
+ //if (shift) UpdatePageOffset(column, pagePos, endRow - fromRow - rowsLeft);
+ if (rowsLeft > 0) {
+ var fr = shift ? fromRow : endRow - rowsLeft;
+ pagePos = column.GetPosition(fr);
+ DeleteCells(column._pages[pagePos], fr, shift ? fr + rowsLeft : endRow, shift);
+ if (shift) {
+ UpdatePageOffset(column, pagePos, rowsLeft);
+ }
+ }
+ }
+ } else if (pagePos > 0
+ && column._pages[pagePos].IndexOffset
+ > fromRow) //The row is on the page before.
+ {
+ int offset = fromRow + rows - 1 - ((pageFromRow - 1) << _pageBits);
+ var rowPos = column._pages[pagePos - 1].GetPosition(offset);
+ if (rowPos > 0 && pagePos > 0) {
+ if (shift) {
+ UpdateIndexOffset(column, pagePos - 1, rowPos, fromRow + rows - 1, -rows);
+ }
+ }
+ } else {
+ if (shift && pagePos + 1 < column.PageCount) {
+ UpdateIndexOffset(
+ column,
+ pagePos + 1,
+ 0,
+ column._pages[pagePos + 1].MinIndex,
+ -rows);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void UpdatePageOffset(ColumnIndex column, int pagePos, int rows) {
+ //Update Pageoffset
+
+ if (++pagePos < column.PageCount) {
+ for (int p = pagePos; p < column.PageCount; p++) {
+ if (column._pages[p].Offset - rows <= -_pageSize) {
+ column._pages[p].Index--;
+ column._pages[p].Offset -= rows - _pageSize;
+ } else {
+ column._pages[p].Offset -= rows;
+ }
+ }
+
+ if (Math.Abs(column._pages[pagePos].Offset) > _pageSize
+ || Math.Abs(column._pages[pagePos].Rows[column._pages[pagePos].RowCount - 1].Index)
+ > _pageSizeMax) //Split or Merge???
+ {
+ ResetPageOffset(column, pagePos, rows);
+ }
+ }
+ }
+
+ private void ResetPageOffset(ColumnIndex column, int pagePos, int rows) {
+ PageIndex fromPage = column._pages[pagePos];
+ PageIndex toPage;
+ short pageAdd = 0;
+ if (fromPage.Offset < -_pageSize) {
+ toPage = column._pages[pagePos - 1];
+ pageAdd = -1;
+ if (fromPage.Index - 1 == toPage.Index) {
+ if (fromPage.IndexOffset
+ + fromPage.Rows[fromPage.RowCount - 1].Index
+ - toPage.IndexOffset
+ + toPage.Rows[0].Index
+ <= _pageSizeMax) {
+ MergePage(column, pagePos - 1);
+ }
+ } else //No page after
+ {
+ fromPage.Index -= pageAdd;
+ fromPage.Offset += _pageSize;
+ }
+ } else if (fromPage.Offset > _pageSize) {
+ toPage = column._pages[pagePos + 1];
+ pageAdd = 1;
+ if (fromPage.Index + 1 == toPage.Index) {} else {
+ fromPage.Index += pageAdd;
+ fromPage.Offset += _pageSize;
+ }
+ }
+ }
+
+ private int DeletePage(int fromRow, int rows, ColumnIndex column, int pagePos, bool shift) {
+ PageIndex page = column._pages[pagePos];
+ var startRows = rows;
+ while (page != null
+ && page.MinIndex >= fromRow
+ && ((shift && page.MaxIndex < fromRow + rows)
+ || (!shift && page.MaxIndex < fromRow + startRows))) {
+ //Delete entire page.
+ var delSize = page.MaxIndex - page.MinIndex + 1;
+ rows -= delSize;
+ var prevOffset = page.Offset;
+ Array.Copy(
+ column._pages,
+ pagePos + 1,
+ column._pages,
+ pagePos,
+ column.PageCount - pagePos + 1);
+ column.PageCount--;
+ if (column.PageCount == 0) {
+ return 0;
+ }
+ if (shift) {
+ for (int i = pagePos; i < column.PageCount; i++) {
+ column._pages[i].Offset -= delSize;
+ if (column._pages[i].Offset <= -_pageSize) {
+ column._pages[i].Index--;
+ column._pages[i].Offset += _pageSize;
+ }
+ }
+ }
+ if (column.PageCount > pagePos) {
+ page = column._pages[pagePos];
+ //page.Offset = pagePos == 0 ? 1 : prevOffset; //First page can only reference to rows starting from Index == 1
+ } else {
+ //No more pages, return 0
+ return 0;
+ }
+ }
+ return rows;
+ }
+
+ private int DeleteCells(PageIndex page, int fromRow, int toRow, bool shift) {
+ var fromPos = page.GetPosition(fromRow - (page.IndexOffset));
+ if (fromPos < 0) {
+ fromPos = ~fromPos;
+ }
+ var maxRow = page.MaxIndex;
+ var offset = toRow - page.IndexOffset;
+ if (offset > _pageSizeMax) {
+ offset = _pageSizeMax;
+ }
+ var toPos = page.GetPosition(offset);
+ if (toPos < 0) {
+ toPos = ~toPos;
+ }
+
+ if (fromPos <= toPos && fromPos < page.RowCount && page.GetIndex(fromPos) < toRow) {
+ if (toRow > page.MaxIndex) {
+ if (fromRow
+ == page.MinIndex) //Delete entire page, late in the page delete method
+ {
+ return fromRow;
+ }
+ var r = page.MaxIndex;
+ var deletedRow = page.RowCount - fromPos;
+ page.RowCount -= deletedRow;
+ return r + 1;
+ }
+ var rows = toRow - fromRow;
+ if (shift) {
+ UpdateRowIndex(page, toPos, rows);
+ }
+ Array.Copy(page.Rows, toPos, page.Rows, fromPos, page.RowCount - toPos);
+ page.RowCount -= toPos - fromPos;
+
+ return toRow;
+ }
+ if (shift) {
+ UpdateRowIndex(page, toPos, toRow - fromRow);
+ }
+ return toRow < maxRow ? toRow : maxRow;
+ }
+
+ private static void UpdateRowIndex(PageIndex page, int toPos, int rows) {
+ for (int r = toPos; r < page.RowCount; r++) {
+ page.Rows[r].Index -= (short)rows;
+ }
+ }
+
+ private void DeleteColumns(int fromCol, int columns, bool shift) {
+ var fPos = GetPosition(fromCol);
+ if (fPos < 0) {
+ fPos = ~fPos;
+ }
+ int tPos = fPos;
+ for (var c = fPos; c <= ColumnCount; c++) {
+ tPos = c;
+ if (tPos == ColumnCount || _columnIndex[c].Index >= fromCol + columns) {
+ break;
+ }
+ }
+
+ if (ColumnCount <= fPos) {
+ return;
+ }
+
+ if (_columnIndex[fPos].Index >= fromCol && _columnIndex[fPos].Index <= fromCol + columns) {
+ if (tPos < ColumnCount) {
+ Array.Copy(_columnIndex, tPos, _columnIndex, fPos, ColumnCount - tPos);
+ }
+ ColumnCount -= (tPos - fPos);
+ }
+ if (shift) {
+ for (var c = fPos; c < ColumnCount; c++) {
+ _columnIndex[c].Index -= (short)columns;
+ }
+ }
+ }
+
+ private void UpdateIndexOffset(ColumnIndex column, int pagePos, int rowPos, int row, int rows) {
+ if (pagePos >= column.PageCount) {
+ return; //A page after last cell.
+ }
+ var page = column._pages[pagePos];
+ if (rows > _pageSize) {
+ short addPages = (short)(rows >> _pageBits);
+ int offset = +(rows - (_pageSize * addPages));
+ for (int p = pagePos + 1; p < column.PageCount; p++) {
+ if (column._pages[p].Offset + offset > _pageSize) {
+ column._pages[p].Index += (short)(addPages + 1);
+ column._pages[p].Offset += offset - _pageSize;
+ } else {
+ column._pages[p].Index += addPages;
+ column._pages[p].Offset += offset;
+ }
+ }
+
+ var size = page.RowCount - rowPos;
+ if (page.RowCount > rowPos) {
+ if (column.PageCount - 1
+ == pagePos) //No page after, create a new one.
+ {
+ //Copy rows to next page.
+ var newPage = CopyNew(page, rowPos, size);
+ newPage.Index = (short)((row + rows) >> _pageBits);
+ newPage.Offset = row + rows - (newPage.Index * _pageSize) - newPage.Rows[0].Index;
+ if (newPage.Offset > _pageSize) {
+ newPage.Index++;
+ newPage.Offset -= _pageSize;
+ }
+ AddPage(column, pagePos + 1, newPage);
+ page.RowCount = rowPos;
+ } else {
+ if (column._pages[pagePos + 1].RowCount + size
+ > _pageSizeMax) //Split Page
+ {
+ SplitPageInsert(column, pagePos, rowPos, rows, size, addPages);
+ } else //Copy Page.
+ {
+ CopyMergePage(page, rowPos, rows, size, column._pages[pagePos + 1]);
+ }
+ }
+ }
+ } else {
+ //Add to Pages.
+ for (int r = rowPos; r < page.RowCount; r++) {
+ page.Rows[r].Index += (short)rows;
+ }
+ if (page.Offset + page.Rows[page.RowCount - 1].Index
+ >= _pageSizeMax) //Can not be larger than the max size of the page.
+ {
+ AdjustIndex(column, pagePos);
+ if (page.Offset + page.Rows[page.RowCount - 1].Index >= _pageSizeMax) {
+ pagePos = SplitPage(column, pagePos);
+ }
+ //IndexItem[] newRows = new IndexItem[GetSize(page.RowCount - page.Rows[r].Index)];
+ //var newPage = new PageIndex(newRows, r);
+ //newPage.Index = (short)(pagePos + 1);
+ //TODO: MoveRows to next page.
+ }
+
+ for (int p = pagePos + 1; p < column.PageCount; p++) {
+ if (column._pages[p].Offset + rows < _pageSize) {
+ column._pages[p].Offset += rows;
+ } else {
+ column._pages[p].Index++;
+ column._pages[p].Offset = (column._pages[p].Offset + rows) % _pageSize;
+ }
+ }
+ }
+ }
+
+ private void SplitPageInsert(
+ ColumnIndex column,
+ int pagePos,
+ int rowPos,
+ int rows,
+ int size,
+ int addPages) {
+ var newRows = new IndexItem[GetSize(size)];
+ var page = column._pages[pagePos];
+
+ var rStart = -1;
+ for (int r = rowPos; r < page.RowCount; r++) {
+ if (page.IndexExpanded - (page.Rows[r].Index + rows) > _pageSize) {
+ rStart = r;
+ break;
+ }
+ page.Rows[r].Index += (short)rows;
+ }
+ var rc = page.RowCount - rStart;
+ page.RowCount = rStart;
+ if (rc > 0) {
+ //Copy to a new page
+ var row = page.IndexOffset;
+ var newPage = CopyNew(page, rStart, rc);
+ var ix = (short)(page.Index + addPages);
+ var offset = page.IndexOffset + rows - (ix * _pageSize);
+ if (offset > _pageSize) {
+ ix += (short)(offset / _pageSize);
+ offset %= _pageSize;
+ }
+ newPage.Index = ix;
+ newPage.Offset = offset;
+ AddPage(column, pagePos + 1, newPage);
+ }
+
+ //Copy from next Row
+ }
+
+ private void CopyMergePage(PageIndex page, int rowPos, int rows, int size, PageIndex toPage) {
+ var startRow = page.IndexOffset + page.Rows[rowPos].Index + rows;
+ var newRows = new IndexItem[GetSize(toPage.RowCount + size)];
+ page.RowCount -= size;
+ Array.Copy(page.Rows, rowPos, newRows, 0, size);
+ for (int r = 0; r < size; r++) {
+ newRows[r].Index += (short)(page.IndexOffset + rows - toPage.IndexOffset);
+ }
+
+ Array.Copy(toPage.Rows, 0, newRows, size, toPage.RowCount);
+ toPage.Rows = newRows;
+ toPage.RowCount += size;
+ }
+
+ private void MergePage(ColumnIndex column, int pagePos) {
+ PageIndex page1 = column._pages[pagePos];
+ PageIndex page2 = column._pages[pagePos + 1];
+
+ var newPage = new PageIndex(page1, 0, page1.RowCount + page2.RowCount);
+ newPage.RowCount = page1.RowCount + page2.RowCount;
+ Array.Copy(page1.Rows, 0, newPage.Rows, 0, page1.RowCount);
+ Array.Copy(page2.Rows, 0, newPage.Rows, page1.RowCount, page2.RowCount);
+ for (int r = page1.RowCount; r < newPage.RowCount; r++) {
+ newPage.Rows[r].Index += (short)(page2.IndexOffset - page1.IndexOffset);
+ }
+
+ column._pages[pagePos] = newPage;
+ column.PageCount--;
+
+ if (column.PageCount > (pagePos + 1)) {
+ Array.Copy(
+ column._pages,
+ pagePos + 2,
+ column._pages,
+ pagePos + 1,
+ column.PageCount - (pagePos + 1));
+ for (int p = pagePos + 1; p < column.PageCount; p++) {
+ column._pages[p].Index--;
+ column._pages[p].Offset += _pageSize;
+ }
+ }
+ }
+
+ private PageIndex CopyNew(PageIndex pageFrom, int rowPos, int size) {
+ IndexItem[] newRows = new IndexItem[GetSize(size)];
+ Array.Copy(pageFrom.Rows, rowPos, newRows, 0, size);
+ return new(newRows, size);
+ }
+
+ internal static int GetSize(int size) {
+ var newSize = 256;
+ while (newSize < size) {
+ newSize <<= 1;
+ }
+ return newSize;
+ }
+
+ private void AddCell(ColumnIndex columnIndex, int pagePos, int pos, short ix, T value) {
+ PageIndex pageItem = columnIndex._pages[pagePos];
+ if (pageItem.RowCount == pageItem.Rows.Length) {
+ if (pageItem.RowCount
+ == _pageSizeMax) //Max size-->Split
+ {
+ pagePos = SplitPage(columnIndex, pagePos);
+ if (columnIndex._pages[pagePos - 1].RowCount > pos) {
+ pagePos--;
+ } else {
+ pos -= columnIndex._pages[pagePos - 1].RowCount;
+ }
+ pageItem = columnIndex._pages[pagePos];
+ } else //Expand to double size.
+ {
+ var rowsTmp = new IndexItem[pageItem.Rows.Length << 1];
+ Array.Copy(pageItem.Rows, 0, rowsTmp, 0, pageItem.RowCount);
+ pageItem.Rows = rowsTmp;
+ }
+ }
+ if (pos < pageItem.RowCount) {
+ Array.Copy(pageItem.Rows, pos, pageItem.Rows, pos + 1, pageItem.RowCount - pos);
+ }
+ pageItem.Rows[pos] = new() {
+ Index = ix,
+ IndexPointer = _values.Count,
+ };
+ _values.Add(value);
+ pageItem.RowCount++;
+ }
+
+ private int SplitPage(ColumnIndex columnIndex, int pagePos) {
+ var page = columnIndex._pages[pagePos];
+ if (page.Offset != 0) {
+ var offset = page.Offset;
+ page.Offset = 0;
+ for (int r = 0; r < page.RowCount; r++) {
+ page.Rows[r].Index -= (short)offset;
+ }
+ }
+ //Find Split pos
+ int splitPos = 0;
+ for (int r = 0; r < page.RowCount; r++) {
+ if (page.Rows[r].Index > _pageSize) {
+ splitPos = r;
+ break;
+ }
+ }
+ var newPage = new PageIndex(page, 0, splitPos);
+ var nextPage = new PageIndex(
+ page,
+ splitPos,
+ page.RowCount - splitPos,
+ (short)(page.Index + 1),
+ page.Offset);
+
+ for (int r = 0; r < nextPage.RowCount; r++) {
+ nextPage.Rows[r].Index = (short)(nextPage.Rows[r].Index - _pageSize);
+ }
+
+ columnIndex._pages[pagePos] = newPage;
+ if (columnIndex.PageCount + 1 > columnIndex._pages.Length) {
+ var pageTmp = new PageIndex[columnIndex._pages.Length << 1];
+ Array.Copy(columnIndex._pages, 0, pageTmp, 0, columnIndex.PageCount);
+ columnIndex._pages = pageTmp;
+ }
+ Array.Copy(
+ columnIndex._pages,
+ pagePos + 1,
+ columnIndex._pages,
+ pagePos + 2,
+ columnIndex.PageCount - pagePos - 1);
+ columnIndex._pages[pagePos + 1] = nextPage;
+ page = nextPage;
+ //pos -= PageSize;
+ columnIndex.PageCount++;
+ return pagePos + 1;
+ }
+
+ private PageIndex AdjustIndex(ColumnIndex columnIndex, int pagePos) {
+ PageIndex page = columnIndex._pages[pagePos];
+ //First Adjust indexes
+ if (page.Offset + page.Rows[0].Index >= _pageSize
+ || page.Offset >= _pageSize
+ || page.Rows[0].Index >= _pageSize) {
+ page.Index++;
+ page.Offset -= _pageSize;
+ } else if (page.Offset + page.Rows[0].Index <= -_pageSize
+ || page.Offset <= -_pageSize
+ || page.Rows[0].Index <= -_pageSize) {
+ page.Index--;
+ page.Offset += _pageSize;
+ }
+ return page;
+ }
+
+ private void AddPage(ColumnIndex column, int pos, short index) {
+ AddPage(column, pos);
+ column._pages[pos] = new() {
+ Index = index,
+ };
+ if (pos > 0) {
+ var pp = column._pages[pos - 1];
+ if (pp.RowCount > 0 && pp.Rows[pp.RowCount - 1].Index > _pageSize) {
+ column._pages[pos].Offset = pp.Rows[pp.RowCount - 1].Index - _pageSize;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Add a new page to the collection
+ /// </summary>
+ /// <param name="column">The column</param>
+ /// <param name="pos">Position</param>
+ /// <param name="page">The new page object to add</param>
+ private void AddPage(ColumnIndex column, int pos, PageIndex page) {
+ AddPage(column, pos);
+ column._pages[pos] = page;
+ }
+
+ /// <summary>
+ /// Add a new page to the collection
+ /// </summary>
+ /// <param name="column">The column</param>
+ /// <param name="pos">Position</param>
+ private void AddPage(ColumnIndex column, int pos) {
+ if (column.PageCount == column._pages.Length) {
+ var pageTmp = new PageIndex[column._pages.Length * 2];
+ Array.Copy(column._pages, 0, pageTmp, 0, column.PageCount);
+ column._pages = pageTmp;
+ }
+ if (pos < column.PageCount) {
+ Array.Copy(column._pages, pos, column._pages, pos + 1, column.PageCount - pos);
+ }
+ column.PageCount++;
+ }
+
+ private void AddColumn(int pos, int column) {
+ if (ColumnCount == _columnIndex.Length) {
+ var colTmp = new ColumnIndex[_columnIndex.Length * 2];
+ Array.Copy(_columnIndex, 0, colTmp, 0, ColumnCount);
+ _columnIndex = colTmp;
+ }
+ if (pos < ColumnCount) {
+ Array.Copy(_columnIndex, pos, _columnIndex, pos + 1, ColumnCount - pos);
+ }
+ _columnIndex[pos] = new() {
+ Index = (short)(column),
+ };
+ ColumnCount++;
+ }
+
+ internal bool NextCell(ref int row, ref int col) {
+ return NextCell(ref row, ref col, 0, 0, ExcelPackage.MaxRows, ExcelPackage.MaxColumns);
+ }
+
+ internal bool NextCell(
+ ref int row,
+ ref int col,
+ int minRow,
+ int minColPos,
+ int maxRow,
+ int maxColPos) {
+ if (minColPos >= ColumnCount) {
+ return false;
+ }
+ if (maxColPos >= ColumnCount) {
+ maxColPos = ColumnCount - 1;
+ }
+ var c = GetPosition(col);
+ if (c >= 0) {
+ if (c > maxColPos) {
+ if (col <= minColPos) {
+ return false;
+ }
+ col = minColPos;
+ return NextCell(ref row, ref col);
+ }
+ var r = GetNextCell(ref row, ref c, minColPos, maxRow, maxColPos);
+ col = _columnIndex[c].Index;
+ return r;
+ }
+ c = ~c;
+ if (c > _columnIndex[c].Index) {
+ if (col <= minColPos) {
+ return false;
+ }
+ col = minColPos;
+ return NextCell(ref row, ref col, minRow, minColPos, maxRow, maxColPos);
+ }
+ {
+ var r = GetNextCell(ref c, ref row, minColPos, maxRow, maxColPos);
+ col = _columnIndex[c].Index;
+ return r;
+ }
+ }
+
+ internal bool GetNextCell(
+ ref int row,
+ ref int colPos,
+ int startColPos,
+ int endRow,
+ int endColPos) {
+ if (ColumnCount == 0) {
+ return false;
+ }
+ if (++colPos < ColumnCount && colPos <= endColPos) {
+ var r = _columnIndex[colPos].GetNextRow(row);
+ if (r
+ == row) //Exists next Row
+ {
+ return true;
+ }
+ int minRow,
+ minCol;
+ if (r > row) {
+ minRow = r;
+ minCol = colPos;
+ } else {
+ minRow = int.MaxValue;
+ minCol = 0;
+ }
+
+ var c = colPos + 1;
+ while (c < ColumnCount && c <= endColPos) {
+ r = _columnIndex[c].GetNextRow(row);
+ if (r
+ == row) //Exists next Row
+ {
+ colPos = c;
+ return true;
+ }
+ if (r > row && r < minRow) {
+ minRow = r;
+ minCol = c;
+ }
+ c++;
+ }
+ c = startColPos;
+ if (row < endRow) {
+ row++;
+ while (c < colPos) {
+ r = _columnIndex[c].GetNextRow(row);
+ if (r
+ == row) //Exists next Row
+ {
+ colPos = c;
+ return true;
+ }
+ if (r > row && (r < minRow || (r == minRow && c < minCol)) && r <= endRow) {
+ minRow = r;
+ minCol = c;
+ }
+ c++;
+ }
+ }
+
+ if (minRow == int.MaxValue || minRow > endRow) {
+ return false;
+ }
+ row = minRow;
+ colPos = minCol;
+ return true;
+ }
+ if (colPos <= startColPos || row >= endRow) {
+ return false;
+ }
+ colPos = startColPos - 1;
+ row++;
+ return GetNextCell(ref row, ref colPos, startColPos, endRow, endColPos);
+ }
+
+ internal bool PrevCell(ref int row, ref int col) {
+ return PrevCell(ref row, ref col, 0, 0, ExcelPackage.MaxRows, ExcelPackage.MaxColumns);
+ }
+
+ private bool PrevCell(
+ ref int row,
+ ref int col,
+ int minRow,
+ int minColPos,
+ int maxRow,
+ int maxColPos) {
+ if (minColPos >= ColumnCount) {
+ return false;
+ }
+ if (maxColPos >= ColumnCount) {
+ maxColPos = ColumnCount - 1;
+ }
+ var c = GetPosition(col);
+ if (c >= 0) {
+ if (c == 0) {
+ if (col >= maxColPos) {
+ return false;
+ }
+ if (row == minRow) {
+ return false;
+ }
+ row--;
+ col = maxColPos;
+ return PrevCell(ref row, ref col, minRow, minColPos, maxRow, maxColPos);
+ }
+ var ret = GetPrevCell(ref row, ref c, minRow, minColPos, maxColPos);
+ if (ret) {
+ col = _columnIndex[c].Index;
+ }
+ return ret;
+ }
+ c = ~c;
+ if (c == 0) {
+ if (col >= maxColPos || row <= 0) {
+ return false;
+ }
+ col = maxColPos;
+ row--;
+ return PrevCell(ref row, ref col, minRow, minColPos, maxRow, maxColPos);
+ }
+ {
+ var ret = GetPrevCell(ref row, ref c, minRow, minColPos, maxColPos);
+ if (ret) {
+ col = _columnIndex[c].Index;
+ }
+ return ret;
+ }
+ }
+
+ internal bool GetPrevCell(
+ ref int row,
+ ref int colPos,
+ int startRow,
+ int startColPos,
+ int endColPos) {
+ if (ColumnCount == 0) {
+ return false;
+ }
+ if (--colPos >= startColPos)
+ // if (++colPos < ColumnCount && colPos <= endColPos)
+ {
+ var r = _columnIndex[colPos].GetNextRow(row);
+ if (r
+ == row) //Exists next Row
+ {
+ return true;
+ }
+ int minRow,
+ minCol;
+ if (r > row && r >= startRow) {
+ minRow = r;
+ minCol = colPos;
+ } else {
+ minRow = int.MaxValue;
+ minCol = 0;
+ }
+
+ var c = colPos - 1;
+ if (c >= startColPos) {
+ while (c >= startColPos) {
+ r = _columnIndex[c].GetNextRow(row);
+ if (r
+ == row) //Exists next Row
+ {
+ colPos = c;
+ return true;
+ }
+ if (r > row && r < minRow && r >= startRow) {
+ minRow = r;
+ minCol = c;
+ }
+ c--;
+ }
+ }
+ if (row > startRow) {
+ c = endColPos;
+ row--;
+ while (c > colPos) {
+ r = _columnIndex[c].GetNextRow(row);
+ if (r
+ == row) //Exists next Row
+ {
+ colPos = c;
+ return true;
+ }
+ if (r > row && r < minRow && r >= startRow) {
+ minRow = r;
+ minCol = c;
+ }
+ c--;
+ }
+ }
+ if (minRow == int.MaxValue || startRow < minRow) {
+ return false;
+ }
+ row = minRow;
+ colPos = minCol;
+ return true;
+ }
+ colPos = ColumnCount;
+ row--;
+ if (row < startRow) {
+ return false;
+ }
+ return GetPrevCell(ref colPos, ref row, startRow, startColPos, endColPos);
+ }
+}
+
+internal class CellsStoreEnumerator<T> : IEnumerable<T>, IEnumerator<T> {
+ private readonly CellStore<T> _cellStore;
+ private int row,
+ colPos;
+ private int[] pagePos,
+ cellPos;
+ private readonly int _startRow;
+ private readonly int _startCol;
+ private readonly int _endRow;
+ private readonly int _endCol;
+ private int minRow,
+ minColPos,
+ maxRow,
+ maxColPos;
+
+ public CellsStoreEnumerator(CellStore<T> cellStore)
+ : this(cellStore, 0, 0, ExcelPackage.MaxRows, ExcelPackage.MaxColumns) {}
+
+ public CellsStoreEnumerator(
+ CellStore<T> cellStore,
+ int startRow,
+ int startCol,
+ int endRow,
+ int endCol) {
+ _cellStore = cellStore;
+
+ _startRow = startRow;
+ _startCol = startCol;
+ _endRow = endRow;
+ _endCol = endCol;
+
+ Init();
+ }
+
+ internal void Init() {
+ minRow = _startRow;
+ maxRow = _endRow;
+
+ minColPos = _cellStore.GetPosition(_startCol);
+ if (minColPos < 0) {
+ minColPos = ~minColPos;
+ }
+ maxColPos = _cellStore.GetPosition(_endCol);
+ if (maxColPos < 0) {
+ maxColPos = ~maxColPos - 1;
+ }
+ row = minRow;
+ colPos = minColPos - 1;
+
+ var cols = maxColPos - minColPos + 1;
+ pagePos = new int[cols];
+ cellPos = new int[cols];
+ for (int i = 0; i < cols; i++) {
+ pagePos[i] = -1;
+ cellPos[i] = -1;
+ }
+ }
+
+ internal int Row => row;
+
+ internal int Column {
+ get {
+ if (colPos == -1) {
+ MoveNext();
+ }
+ if (colPos == -1) {
+ return 0;
+ }
+ return _cellStore._columnIndex[colPos].Index;
+ }
+ }
+
+ internal T Value {
+ get => _cellStore.GetValue(row, Column);
+ set => _cellStore.SetValue(row, Column, value);
+ }
+
+ internal bool Next() {
+ return _cellStore.GetNextCell(ref row, ref colPos, minColPos, maxRow, maxColPos);
+ }
+
+ public string CellAddress => ExcelCellBase.GetAddress(Row, Column);
+
+ public IEnumerator<T> GetEnumerator() {
+ Reset();
+ return this;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ Reset();
+ return this;
+ }
+
+ public T Current => Value;
+
+ public void Dispose() {}
+
+ object IEnumerator.Current {
+ get {
+ Reset();
+ return this;
+ }
+ }
+
+ public bool MoveNext() {
+ return Next();
+ }
+
+ public void Reset() {
+ Init();
+ }
+}
+
+internal class FlagCellStore : CellStore<byte> {
+ internal void SetFlagValue(int row, int col, bool value, CellFlags cellFlags) {
+ CellFlags currentValue = (CellFlags)GetValue(row, col);
+ if (value) {
+ SetValue(row, col, (byte)(currentValue | cellFlags)); // add the CellFlag bit
+ } else {
+ SetValue(row, col, (byte)(currentValue & ~cellFlags)); // remove the CellFlag bit
+ }
+ }
+
+ internal bool GetFlagValue(int row, int col, CellFlags cellFlags) {
+ return !(((byte)cellFlags & GetValue(row, col)) == 0);
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingAverageGroup.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingAverageGroup.cs
new file mode 100644
index 0000000..af3a6db
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingAverageGroup.cs
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingAverageGroup
+/// </summary>
+public interface IExcelConditionalFormattingAverageGroup : IExcelConditionalFormattingRule {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBeginsWith.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBeginsWith.cs
new file mode 100644
index 0000000..9d81d07
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBeginsWith.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingBeginsWith
+/// </summary>
+public interface IExcelConditionalFormattingBeginsWith
+ : IExcelConditionalFormattingRule,
+ IExcelConditionalFormattingWithText {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBetween.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBetween.cs
new file mode 100644
index 0000000..acfaf5e
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBetween.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingBetween
+/// </summary>
+public interface IExcelConditionalFormattingBetween
+ : IExcelConditionalFormattingRule,
+ IExcelConditionalFormattingWithFormula2 {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingColorScaleGroup.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingColorScaleGroup.cs
new file mode 100644
index 0000000..085cf48
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingColorScaleGroup.cs
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingColorScaleGroup
+/// </summary>
+public interface IExcelConditionalFormattingColorScaleGroup : IExcelConditionalFormattingRule {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsBlanks.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsBlanks.cs
new file mode 100644
index 0000000..f6e38f2
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsBlanks.cs
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingContainsBlanks
+/// </summary>
+public interface IExcelConditionalFormattingContainsBlanks : IExcelConditionalFormattingRule {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsErrors.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsErrors.cs
new file mode 100644
index 0000000..58c62fd
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsErrors.cs
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingContainsErrors
+/// </summary>
+public interface IExcelConditionalFormattingContainsErrors : IExcelConditionalFormattingRule {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsText.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsText.cs
new file mode 100644
index 0000000..1472a81
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsText.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingContainsText
+/// </summary>
+public interface IExcelConditionalFormattingContainsText
+ : IExcelConditionalFormattingRule,
+ IExcelConditionalFormattingWithText {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDataBarGroup.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDataBarGroup.cs
new file mode 100644
index 0000000..f8452d0
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDataBarGroup.cs
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingDataBar
+/// </summary>
+public interface IExcelConditionalFormattingDataBarGroup : IExcelConditionalFormattingRule {
+ /// <summary>
+ /// ShowValue
+ /// </summary>
+ bool ShowValue { get; set; }
+
+ /// <summary>
+ /// Databar Low Value
+ /// </summary>
+ ExcelConditionalFormattingIconDataBarValue LowValue { get; }
+
+ /// <summary>
+ /// Databar High Value
+ /// </summary>
+ ExcelConditionalFormattingIconDataBarValue HighValue { get; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDuplicateValues.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDuplicateValues.cs
new file mode 100644
index 0000000..518f650
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDuplicateValues.cs
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingDuplicateValues
+/// </summary>
+public interface IExcelConditionalFormattingDuplicateValues : IExcelConditionalFormattingRule {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEndsWith.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEndsWith.cs
new file mode 100644
index 0000000..37df3d1
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEndsWith.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingEndsWith
+/// </summary>
+public interface IExcelConditionalFormattingEndsWith
+ : IExcelConditionalFormattingRule,
+ IExcelConditionalFormattingWithText {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEqual.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEqual.cs
new file mode 100644
index 0000000..4859bcc
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEqual.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingEqual
+/// </summary>
+public interface IExcelConditionalFormattingEqual
+ : IExcelConditionalFormattingRule,
+ IExcelConditionalFormattingWithFormula {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingExpression.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingExpression.cs
new file mode 100644
index 0000000..3e69ce6
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingExpression.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingExpression
+/// </summary>
+public interface IExcelConditionalFormattingExpression
+ : IExcelConditionalFormattingRule,
+ IExcelConditionalFormattingWithFormula {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFiveIconSet.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFiveIconSet.cs
new file mode 100644
index 0000000..fd4e8cc
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFiveIconSet.cs
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingFiveIconSet
+/// </summary>eExcelconditionalFormatting4IconsSetType
+public interface IExcelConditionalFormattingFiveIconSet
+ : IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting5IconsSetType> {
+ /// <summary>
+ /// Icon5 (part of the 5 Icon Set)
+ /// </summary>
+ ExcelConditionalFormattingIconDataBarValue Icon5 { get; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFourIconSet.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFourIconSet.cs
new file mode 100644
index 0000000..c0ec540
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFourIconSet.cs
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingFourIconSet
+/// </summary>
+public interface IExcelConditionalFormattingFourIconSet<T>
+ : IExcelConditionalFormattingThreeIconSet<T> {
+ /// <summary>
+ /// Icon4 (part of the 4 ou 5 Icon Set)
+ /// </summary>
+ ExcelConditionalFormattingIconDataBarValue Icon4 { get; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThan.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThan.cs
new file mode 100644
index 0000000..e466a6c
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThan.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingGreaterThan
+/// </summary>
+public interface IExcelConditionalFormattingGreaterThan
+ : IExcelConditionalFormattingRule,
+ IExcelConditionalFormattingWithFormula {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThanOrEqual.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThanOrEqual.cs
new file mode 100644
index 0000000..f5517df
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThanOrEqual.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingGreaterThanOrEqual
+/// </summary>
+public interface IExcelConditionalFormattingGreaterThanOrEqual
+ : IExcelConditionalFormattingRule,
+ IExcelConditionalFormattingWithFormula {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingIconSetGroup.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingIconSetGroup.cs
new file mode 100644
index 0000000..783f729
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingIconSetGroup.cs
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingIconSetGroup
+/// </summary>
+public interface IExcelConditionalFormattingIconSetGroup<T> : IExcelConditionalFormattingRule {
+ /// <summary>
+ /// Reverse
+ /// </summary>
+ bool Reverse { get; set; }
+
+ /// <summary>
+ /// ShowValue
+ /// </summary>
+ bool ShowValue { get; set; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThan.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThan.cs
new file mode 100644
index 0000000..2458a89
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThan.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingLessThan
+/// </summary>
+public interface IExcelConditionalFormattingLessThan
+ : IExcelConditionalFormattingRule,
+ IExcelConditionalFormattingWithFormula {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThanOrEqual.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThanOrEqual.cs
new file mode 100644
index 0000000..8d20da4
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThanOrEqual.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingGreaterThanOrEqual
+/// </summary>
+public interface IExcelConditionalFormattingLessThanOrEqual
+ : IExcelConditionalFormattingRule,
+ IExcelConditionalFormattingWithFormula {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotBetween.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotBetween.cs
new file mode 100644
index 0000000..496fb6e
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotBetween.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingNotBetween
+/// </summary>
+public interface IExcelConditionalFormattingNotBetween
+ : IExcelConditionalFormattingRule,
+ IExcelConditionalFormattingWithFormula2 {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsBlanks.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsBlanks.cs
new file mode 100644
index 0000000..1a07b2a
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsBlanks.cs
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingNotContainsBlanks
+/// </summary>
+public interface IExcelConditionalFormattingNotContainsBlanks : IExcelConditionalFormattingRule {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsErrors.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsErrors.cs
new file mode 100644
index 0000000..a021cd9
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsErrors.cs
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingNotContainsErrors
+/// </summary>
+public interface IExcelConditionalFormattingNotContainsErrors : IExcelConditionalFormattingRule {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsText.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsText.cs
new file mode 100644
index 0000000..aa7a884
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsText.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingNotContainsText
+/// </summary>
+public interface IExcelConditionalFormattingNotContainsText
+ : IExcelConditionalFormattingRule,
+ IExcelConditionalFormattingWithText {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotEqual.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotEqual.cs
new file mode 100644
index 0000000..cc62e8b
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotEqual.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingNotEqual
+/// </summary>
+public interface IExcelConditionalFormattingNotEqual
+ : IExcelConditionalFormattingRule,
+ IExcelConditionalFormattingWithFormula {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingRule.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingRule.cs
new file mode 100644
index 0000000..52c1f33
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingRule.cs
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Interface for conditional formatting rule
+/// </summary>
+public interface IExcelConditionalFormattingRule {
+ /// <summary>
+ /// The 'cfRule' XML node
+ /// </summary>
+ XmlNode Node { get; }
+
+ /// <summary>
+ /// Type of conditional formatting rule. ST_CfType §18.18.12.
+ /// </summary>
+ eExcelConditionalFormattingRuleType Type { get; }
+
+ /// <summary>
+ /// <para>Range over which these conditional formatting rules apply.</para>
+ /// <para>The possible values for this attribute are defined by the
+ /// ST_Sqref simple type (§18.18.76).</para>
+ /// </summary>
+ ExcelAddress Address { get; set; }
+
+ /// <summary>
+ /// The priority of this conditional formatting rule. This value is used to determine
+ /// which format should be evaluated and rendered. Lower numeric values are higher
+ /// priority than higher numeric values, where 1 is the highest priority.
+ /// </summary>
+ int Priority { get; set; }
+
+ /// <summary>
+ /// If this flag is 1, no rules with lower priority shall be applied over this rule,
+ /// when this rule evaluates to true.
+ /// </summary>
+ bool StopIfTrue { get; set; }
+
+ ///// <summary>
+ ///// <para>This is an index to a dxf element in the Styles Part indicating which cell
+ ///// formatting to apply when the conditional formatting rule criteria is met.</para>
+ ///// <para>The possible values for this attribute are defined by the ST_DxfId simple type
+ ///// (§18.18.25).</para>
+ ///// </summary>
+ // int DxfId { get; set; }
+ /// <summary>
+ /// Gives access to the differencial styling (DXF) for the rule.
+ /// </summary>
+ ExcelDxfStyleConditionalFormatting Style { get; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingStdDevGroup.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingStdDevGroup.cs
new file mode 100644
index 0000000..84c592e
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingStdDevGroup.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingStdDevGroup
+/// </summary>
+public interface IExcelConditionalFormattingStdDevGroup
+ : IExcelConditionalFormattingRule,
+ IExcelConditionalFormattingWithStdDev {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeColorScale.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeColorScale.cs
new file mode 100644
index 0000000..790f408
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeColorScale.cs
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingThreeColorScale
+/// </summary>
+public interface IExcelConditionalFormattingThreeColorScale
+ : IExcelConditionalFormattingTwoColorScale {
+ /// <summary>
+ /// Three Color Scale Middle Value
+ /// </summary>
+ ExcelConditionalFormattingColorScaleValue MiddleValue { get; set; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeIconSet.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeIconSet.cs
new file mode 100644
index 0000000..cc37c30
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeIconSet.cs
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingThreeIconSet
+/// </summary>
+public interface IExcelConditionalFormattingThreeIconSet<T>
+ : IExcelConditionalFormattingIconSetGroup<T> {
+ /// <summary>
+ /// Icon1 (part of the 3, 4 ou 5 Icon Set)
+ /// </summary>
+ ExcelConditionalFormattingIconDataBarValue Icon1 { get; }
+
+ /// <summary>
+ /// Icon2 (part of the 3, 4 ou 5 Icon Set)
+ /// </summary>
+ ExcelConditionalFormattingIconDataBarValue Icon2 { get; }
+
+ /// <summary>
+ /// Icon3 (part of the 3, 4 ou 5 Icon Set)
+ /// </summary>
+ ExcelConditionalFormattingIconDataBarValue Icon3 { get; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTimePeriodGroup.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTimePeriodGroup.cs
new file mode 100644
index 0000000..e60ec34
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTimePeriodGroup.cs
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingTimePeriod
+/// </summary>
+public interface IExcelConditionalFormattingTimePeriodGroup : IExcelConditionalFormattingRule {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTopBottomGroup.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTopBottomGroup.cs
new file mode 100644
index 0000000..58a7b7e
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTopBottomGroup.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingTopBottomGroup
+/// </summary>
+public interface IExcelConditionalFormattingTopBottomGroup
+ : IExcelConditionalFormattingRule,
+ IExcelConditionalFormattingWithRank {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTwoColorScale.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTwoColorScale.cs
new file mode 100644
index 0000000..0c0b888
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTwoColorScale.cs
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingTwoColorScale
+/// </summary>
+public interface IExcelConditionalFormattingTwoColorScale
+ : IExcelConditionalFormattingColorScaleGroup {
+ /// <summary>
+ /// Two Color Scale Low Value
+ /// </summary>
+ ExcelConditionalFormattingColorScaleValue LowValue { get; set; }
+
+ /// <summary>
+ /// Two Color Scale High Value
+ /// </summary>
+ ExcelConditionalFormattingColorScaleValue HighValue { get; set; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingUniqueValues.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingUniqueValues.cs
new file mode 100644
index 0000000..5318d5a
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingUniqueValues.cs
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingUniqueValues
+/// </summary>
+public interface IExcelConditionalFormattingUniqueValues : IExcelConditionalFormattingRule {}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula.cs
new file mode 100644
index 0000000..a834dbf
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula.cs
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingWithFormula
+/// </summary>
+public interface IExcelConditionalFormattingWithFormula {
+ /// <summary>
+ /// Formula Attribute
+ /// </summary>
+ string Formula { get; set; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula2.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula2.cs
new file mode 100644
index 0000000..da089d3
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula2.cs
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingWithFormula2
+/// </summary>
+public interface IExcelConditionalFormattingWithFormula2 : IExcelConditionalFormattingWithFormula {
+ /// <summary>
+ /// Formula2 Attribute
+ /// </summary>
+ string Formula2 { get; set; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithRank.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithRank.cs
new file mode 100644
index 0000000..01ca261
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithRank.cs
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingWithRank
+/// </summary>
+public interface IExcelConditionalFormattingWithRank {
+ /// <summary>
+ /// Rank Attribute
+ /// </summary>
+ UInt16 Rank { get; set; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithReverse.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithReverse.cs
new file mode 100644
index 0000000..81f42c0
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithReverse.cs
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingWithReverse
+/// </summary>
+public interface IExcelConditionalFormattingWithReverse {
+ /// <summary>
+ /// Reverse Attribute
+ /// </summary>
+ bool Reverse { get; set; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithShowValue.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithShowValue.cs
new file mode 100644
index 0000000..0be6a7c
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithShowValue.cs
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingWithShowValue
+/// </summary>
+public interface IExcelConditionalFormattingWithShowValue {
+ /// <summary>
+ /// ShowValue Attribute
+ /// </summary>
+ bool ShowValue { get; set; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithStdDev.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithStdDev.cs
new file mode 100644
index 0000000..cd9bc01
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithStdDev.cs
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingWithStdDev
+/// </summary>
+public interface IExcelConditionalFormattingWithStdDev {
+ /// <summary>
+ /// StdDev Attribute
+ /// </summary>
+ UInt16 StdDev { get; set; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithText.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithText.cs
new file mode 100644
index 0000000..b64e9a4
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithText.cs
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// IExcelConditionalFormattingWithText
+/// </summary>
+public interface IExcelConditionalFormattingWithText {
+ /// <summary>
+ /// Text Attribute
+ /// </summary>
+ string Text { get; set; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Contracts/IRangeConditionalFormatting.cs b/AppsheetEpplus/ConditionalFormatting/Contracts/IRangeConditionalFormatting.cs
new file mode 100644
index 0000000..02ee298
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Contracts/IRangeConditionalFormatting.cs
@@ -0,0 +1,285 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting 2012-04-03
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Provides functionality for adding Conditional Formatting to a range (<see cref="ExcelRangeBase"/>).
+/// Each method will return a configurable condtional formatting type.
+/// </summary>
+public interface IRangeConditionalFormatting {
+ /// <summary>
+ /// Adds a Above Average rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingAverageGroup AddAboveAverage();
+
+ /// <summary>
+ /// Adds a Above Or Equal Average rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingAverageGroup AddAboveOrEqualAverage();
+
+ /// <summary>
+ /// Adds a Below Average rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingAverageGroup AddBelowAverage();
+
+ /// <summary>
+ /// Adds a Below Or Equal Average rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingAverageGroup AddBelowOrEqualAverage();
+
+ /// <summary>
+ /// Adds a Above StdDev rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingStdDevGroup AddAboveStdDev();
+
+ /// <summary>
+ /// Adds a Below StdDev rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingStdDevGroup AddBelowStdDev();
+
+ /// <summary>
+ /// Adds a Bottom rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTopBottomGroup AddBottom();
+
+ /// <summary>
+ /// Adds a Bottom Percent rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTopBottomGroup AddBottomPercent();
+
+ /// <summary>
+ /// Adds a Top rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTopBottomGroup AddTop();
+
+ /// <summary>
+ /// Adds a Top Percent rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTopBottomGroup AddTopPercent();
+
+ /// <summary>
+ /// Adds a Last 7 Days rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddLast7Days();
+
+ /// <summary>
+ /// Adds a Last Month rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddLastMonth();
+
+ /// <summary>
+ /// Adds a Last Week rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddLastWeek();
+
+ /// <summary>
+ /// Adds a Next Month rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddNextMonth();
+
+ /// <summary>
+ /// Adds a Next Week rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddNextWeek();
+
+ /// <summary>
+ /// Adds a This Month rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddThisMonth();
+
+ /// <summary>
+ /// Adds a This Week rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddThisWeek();
+
+ /// <summary>
+ /// Adds a Today rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddToday();
+
+ /// <summary>
+ /// Adds a Tomorrow rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddTomorrow();
+
+ /// <summary>
+ /// Adds a Yesterday rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddYesterday();
+
+ /// <summary>
+ /// Adds a Begins With rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingBeginsWith AddBeginsWith();
+
+ /// <summary>
+ /// Adds a Between rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingBetween AddBetween();
+
+ /// <summary>
+ /// Adds a ContainsBlanks rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingContainsBlanks AddContainsBlanks();
+
+ /// <summary>
+ /// Adds a ContainsErrors rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingContainsErrors AddContainsErrors();
+
+ /// <summary>
+ /// Adds a ContainsText rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingContainsText AddContainsText();
+
+ /// <summary>
+ /// Adds a DuplicateValues rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingDuplicateValues AddDuplicateValues();
+
+ /// <summary>
+ /// Adds a EndsWith rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingEndsWith AddEndsWith();
+
+ /// <summary>
+ /// Adds a Equal rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingEqual AddEqual();
+
+ /// <summary>
+ /// Adds a Expression rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingExpression AddExpression();
+
+ /// <summary>
+ /// Adds a GreaterThan rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingGreaterThan AddGreaterThan();
+
+ /// <summary>
+ /// Adds a GreaterThanOrEqual rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingGreaterThanOrEqual AddGreaterThanOrEqual();
+
+ /// <summary>
+ /// Adds a LessThan rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingLessThan AddLessThan();
+
+ /// <summary>
+ /// Adds a LessThanOrEqual rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingLessThanOrEqual AddLessThanOrEqual();
+
+ /// <summary>
+ /// Adds a NotBetween rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingNotBetween AddNotBetween();
+
+ /// <summary>
+ /// Adds a NotContainsBlanks rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingNotContainsBlanks AddNotContainsBlanks();
+
+ /// <summary>
+ /// Adds a NotContainsErrors rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingNotContainsErrors AddNotContainsErrors();
+
+ /// <summary>
+ /// Adds a NotContainsText rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingNotContainsText AddNotContainsText();
+
+ /// <summary>
+ /// Adds a NotEqual rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingNotEqual AddNotEqual();
+
+ /// <summary>
+ /// Adds a UniqueValues rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingUniqueValues AddUniqueValues();
+
+ /// <summary>
+ /// Adds a <see cref="ExcelConditionalFormattingThreeColorScale"/> to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingThreeColorScale AddThreeColorScale();
+
+ /// <summary>
+ /// Adds a <see cref="ExcelConditionalFormattingTwoColorScale"/> to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTwoColorScale AddTwoColorScale();
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingCollection.cs b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingCollection.cs
new file mode 100644
index 0000000..fb6ad7c
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingCollection.cs
@@ -0,0 +1,770 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting 2012-04-03
+ *******************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Collection of <see cref="ExcelConditionalFormattingRule"/>.
+/// This class is providing the API for EPPlus conditional formatting.
+/// </summary>
+/// <remarks>
+/// <para>
+/// The public methods of this class (Add[...]ConditionalFormatting) will create a ConditionalFormatting/CfRule entry in the worksheet. When this
+/// Conditional Formatting has been created changes to the properties will affect the workbook immediately.
+/// </para>
+/// <para>
+/// Each type of Conditional Formatting Rule has diferente set of properties.
+/// </para>
+/// <code>
+/// // Add a Three Color Scale conditional formatting
+/// var cf = worksheet.ConditionalFormatting.AddThreeColorScale(new ExcelAddress("A1:C10"));
+/// // Set the conditional formatting properties
+/// cf.LowValue.Type = ExcelConditionalFormattingValueObjectType.Min;
+/// cf.LowValue.Color = Color.White;
+/// cf.MiddleValue.Type = ExcelConditionalFormattingValueObjectType.Percent;
+/// cf.MiddleValue.Value = 50;
+/// cf.MiddleValue.Color = Color.Blue;
+/// cf.HighValue.Type = ExcelConditionalFormattingValueObjectType.Max;
+/// cf.HighValue.Color = Color.Black;
+/// </code>
+/// </remarks>
+public class ExcelConditionalFormattingCollection
+ : XmlHelper,
+ IEnumerable<IExcelConditionalFormattingRule> {
+ private readonly List<IExcelConditionalFormattingRule> _rules = new();
+ private readonly ExcelWorksheet _worksheet;
+
+ protected override ImmutableArray<string> SchemaNodeOrder =>
+ ExcelWorksheet.WorksheetSchemaNodeOrder;
+
+ /// <summary>
+ /// Initialize the <see cref="ExcelConditionalFormattingCollection"/>
+ /// </summary>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingCollection(ExcelWorksheet worksheet)
+ : base(worksheet.NameSpaceManager, worksheet.WorksheetXml.DocumentElement) {
+ ArgumentNullException.ThrowIfNull(worksheet);
+
+ _worksheet = worksheet;
+
+ // Look for all the <conditionalFormatting>
+ var conditionalFormattingNodes = TopNode.SelectNodes(
+ "//" + ExcelConditionalFormattingConstants.Paths._conditionalFormatting,
+ _worksheet.NameSpaceManager);
+
+ // Check if we found at least 1 node
+ if ((conditionalFormattingNodes != null) && (conditionalFormattingNodes.Count > 0)) {
+ // Foreach <conditionalFormatting>
+ foreach (XmlNode conditionalFormattingNode in conditionalFormattingNodes) {
+ // Check if @sqref attribute exists
+ if (conditionalFormattingNode.Attributes[ExcelConditionalFormattingConstants
+ .Attributes
+ ._sqref] == null) {
+ throw new(ExcelConditionalFormattingConstants.Errors._missingSqrefAttribute);
+ }
+
+ // Get the @sqref attribute
+ ExcelAddress address = new ExcelAddress(
+ conditionalFormattingNode.Attributes[ExcelConditionalFormattingConstants
+ .Attributes
+ ._sqref].Value);
+
+ // Check for all the <cfRules> nodes and load them
+ var cfRuleNodes = conditionalFormattingNode.SelectNodes(
+ ExcelConditionalFormattingConstants.Paths._cfRule,
+ _worksheet.NameSpaceManager);
+
+ // Foreach <cfRule> inside the current <conditionalFormatting>
+ foreach (XmlNode cfRuleNode in cfRuleNodes) {
+ // Check if @type attribute exists
+ if (cfRuleNode.Attributes[ExcelConditionalFormattingConstants.Attributes._type] == null) {
+ throw new(ExcelConditionalFormattingConstants.Errors._missingTypeAttribute);
+ }
+
+ // Check if @priority attribute exists
+ if (cfRuleNode.Attributes[ExcelConditionalFormattingConstants.Attributes._priority]
+ == null) {
+ throw new(ExcelConditionalFormattingConstants.Errors._missingPriorityAttribute);
+ }
+
+ // Get the <cfRule> main attributes
+ string typeAttribute = ExcelConditionalFormattingHelper.GetAttributeString(
+ cfRuleNode,
+ ExcelConditionalFormattingConstants.Attributes._type);
+
+ int priority = ExcelConditionalFormattingHelper.GetAttributeInt(
+ cfRuleNode,
+ ExcelConditionalFormattingConstants.Attributes._priority);
+
+ // Transform the @type attribute to EPPlus Rule Type (slighty diferente)
+ var type = ExcelConditionalFormattingRuleType.GetTypeByAttrbiute(
+ typeAttribute,
+ cfRuleNode,
+ _worksheet.NameSpaceManager);
+
+ // Create the Rule according to the correct type, address and priority
+ var cfRule = ExcelConditionalFormattingRuleFactory.Create(
+ type,
+ address,
+ priority,
+ _worksheet,
+ cfRuleNode);
+
+ // Add the new rule to the list
+ if (cfRule != null) {
+ _rules.Add(cfRule);
+ }
+ }
+ }
+ }
+ }
+
+ private void EnsureRootElementExists() {
+ // Find the <worksheet> node
+ if (_worksheet.WorksheetXml.DocumentElement == null) {
+ throw new(ExcelConditionalFormattingConstants.Errors._missingWorksheetNode);
+ }
+ }
+
+ /// <summary>
+ /// Validates address - not empty (collisions are allowded)
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ private ExcelAddress ValidateAddress(ExcelAddress address) {
+ ArgumentNullException.ThrowIfNull(address);
+
+ //TODO: Are there any other validation we need to do?
+ return address;
+ }
+
+ /// <summary>
+ /// Get the next priority sequencial number
+ /// </summary>
+ /// <returns></returns>
+ private int GetNextPriority() {
+ // Consider zero as the last priority when we have no CF rules
+ int lastPriority = 0;
+
+ // Search for the last priority
+ foreach (var cfRule in _rules) {
+ if (cfRule.Priority > lastPriority) {
+ lastPriority = cfRule.Priority;
+ }
+ }
+
+ // Our next priority is the last plus one
+ return lastPriority + 1;
+ }
+
+ /// <summary>
+ /// Number of validations
+ /// </summary>
+ public int Count => _rules.Count;
+
+ /// <summary>
+ /// Index operator, returns by 0-based index
+ /// </summary>
+ /// <param name="index"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingRule this[int index] {
+ get => _rules[index];
+ set => _rules[index] = value;
+ }
+
+ /// <summary>
+ /// Get the 'cfRule' enumerator
+ /// </summary>
+ /// <returns></returns>
+ IEnumerator<IExcelConditionalFormattingRule> IEnumerable<IExcelConditionalFormattingRule>.GetEnumerator() {
+ return _rules.GetEnumerator();
+ }
+
+ /// <summary>
+ /// Get the 'cfRule' enumerator
+ /// </summary>
+ /// <returns></returns>
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _rules.GetEnumerator();
+ }
+
+ /// <summary>
+ /// Removes all 'cfRule' from the collection and from the XML.
+ /// <remarks>
+ /// This is the same as removing all the 'conditionalFormatting' nodes.
+ /// </remarks>
+ /// </summary>
+ public void RemoveAll() {
+ // Look for all the <conditionalFormatting> nodes
+ var conditionalFormattingNodes = TopNode.SelectNodes(
+ "//" + ExcelConditionalFormattingConstants.Paths._conditionalFormatting,
+ _worksheet.NameSpaceManager);
+
+ // Remove all the <conditionalFormatting> nodes one by one
+ foreach (XmlNode conditionalFormattingNode in conditionalFormattingNodes) {
+ conditionalFormattingNode.ParentNode.RemoveChild(conditionalFormattingNode);
+ }
+
+ // Clear the <cfRule> item list
+ _rules.Clear();
+ }
+
+ /// <summary>
+ /// Remove a Conditional Formatting Rule by its object
+ /// </summary>
+ /// <param name="item"></param>
+ public void Remove(IExcelConditionalFormattingRule item) {
+ ArgumentNullException.ThrowIfNull(item);
+
+ try {
+ // Point to the parent node
+ var oldParentNode = item.Node.ParentNode;
+
+ // Remove the <cfRule> from the old <conditionalFormatting> parent node
+ oldParentNode.RemoveChild(item.Node);
+
+ // Check if the old <conditionalFormatting> parent node has <cfRule> node inside it
+ if (!oldParentNode.HasChildNodes) {
+ // Remove the old parent node
+ oldParentNode.ParentNode.RemoveChild(oldParentNode);
+ }
+
+ _rules.Remove(item);
+ } catch {
+ throw new(ExcelConditionalFormattingConstants.Errors._invalidRemoveRuleOperation);
+ }
+ }
+
+ /// <summary>
+ /// Remove a Conditional Formatting Rule by its priority
+ /// </summary>
+ /// <param name="priority"></param>
+ public void RemoveByPriority(int priority) {
+ try {
+ Remove(RulesByPriority(priority));
+ } catch {}
+ }
+
+ /// <summary>
+ /// Get a rule by its priority
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingRule RulesByPriority(int priority) {
+ return _rules.Find(x => x.Priority == priority);
+ }
+
+ /// <summary>
+ /// Add rule (internal)
+ /// </summary>
+ /// <param name="type"></param>
+ /// <param name="address"></param>
+ /// <returns></returns>F
+ internal IExcelConditionalFormattingRule AddRule(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address) {
+ ArgumentNullException.ThrowIfNull(address);
+
+ address = ValidateAddress(address);
+ EnsureRootElementExists();
+
+ // Create the Rule according to the correct type, address and priority
+ IExcelConditionalFormattingRule cfRule = ExcelConditionalFormattingRuleFactory.Create(
+ type,
+ address,
+ GetNextPriority(),
+ _worksheet,
+ null);
+
+ // Add the newly created rule to the list
+ _rules.Add(cfRule);
+
+ // Return the newly created rule
+ return cfRule;
+ }
+
+ /// <summary>
+ /// Add AboveAverage Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingAverageGroup AddAboveAverage(ExcelAddress address) {
+ return (IExcelConditionalFormattingAverageGroup)AddRule(
+ eExcelConditionalFormattingRuleType.AboveAverage,
+ address);
+ }
+
+ /// <summary>
+ /// Add AboveOrEqualAverage Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingAverageGroup AddAboveOrEqualAverage(ExcelAddress address) {
+ return (IExcelConditionalFormattingAverageGroup)AddRule(
+ eExcelConditionalFormattingRuleType.AboveOrEqualAverage,
+ address);
+ }
+
+ /// <summary>
+ /// Add BelowAverage Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingAverageGroup AddBelowAverage(ExcelAddress address) {
+ return (IExcelConditionalFormattingAverageGroup)AddRule(
+ eExcelConditionalFormattingRuleType.BelowAverage,
+ address);
+ }
+
+ /// <summary>
+ /// Add BelowOrEqualAverage Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingAverageGroup AddBelowOrEqualAverage(ExcelAddress address) {
+ return (IExcelConditionalFormattingAverageGroup)AddRule(
+ eExcelConditionalFormattingRuleType.BelowOrEqualAverage,
+ address);
+ }
+
+ /// <summary>
+ /// Add AboveStdDev Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingStdDevGroup AddAboveStdDev(ExcelAddress address) {
+ return (IExcelConditionalFormattingStdDevGroup)AddRule(
+ eExcelConditionalFormattingRuleType.AboveStdDev,
+ address);
+ }
+
+ /// <summary>
+ /// Add BelowStdDev Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingStdDevGroup AddBelowStdDev(ExcelAddress address) {
+ return (IExcelConditionalFormattingStdDevGroup)AddRule(
+ eExcelConditionalFormattingRuleType.BelowStdDev,
+ address);
+ }
+
+ /// <summary>
+ /// Add Bottom Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTopBottomGroup AddBottom(ExcelAddress address) {
+ return (IExcelConditionalFormattingTopBottomGroup)AddRule(
+ eExcelConditionalFormattingRuleType.Bottom,
+ address);
+ }
+
+ /// <summary>
+ /// Add BottomPercent Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTopBottomGroup AddBottomPercent(ExcelAddress address) {
+ return (IExcelConditionalFormattingTopBottomGroup)AddRule(
+ eExcelConditionalFormattingRuleType.BottomPercent,
+ address);
+ }
+
+ /// <summary>
+ /// Add Top Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTopBottomGroup AddTop(ExcelAddress address) {
+ return (IExcelConditionalFormattingTopBottomGroup)AddRule(
+ eExcelConditionalFormattingRuleType.Top,
+ address);
+ }
+
+ /// <summary>
+ /// Add TopPercent Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTopBottomGroup AddTopPercent(ExcelAddress address) {
+ return (IExcelConditionalFormattingTopBottomGroup)AddRule(
+ eExcelConditionalFormattingRuleType.TopPercent,
+ address);
+ }
+
+ /// <summary>
+ /// Add Last7Days Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddLast7Days(ExcelAddress address) {
+ return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
+ eExcelConditionalFormattingRuleType.Last7Days,
+ address);
+ }
+
+ /// <summary>
+ /// Add LastMonth Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddLastMonth(ExcelAddress address) {
+ return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
+ eExcelConditionalFormattingRuleType.LastMonth,
+ address);
+ }
+
+ /// <summary>
+ /// Add LastWeek Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddLastWeek(ExcelAddress address) {
+ return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
+ eExcelConditionalFormattingRuleType.LastWeek,
+ address);
+ }
+
+ /// <summary>
+ /// Add NextMonth Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddNextMonth(ExcelAddress address) {
+ return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
+ eExcelConditionalFormattingRuleType.NextMonth,
+ address);
+ }
+
+ /// <summary>
+ /// Add NextWeek Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddNextWeek(ExcelAddress address) {
+ return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
+ eExcelConditionalFormattingRuleType.NextWeek,
+ address);
+ }
+
+ /// <summary>
+ /// Add ThisMonth Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddThisMonth(ExcelAddress address) {
+ return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
+ eExcelConditionalFormattingRuleType.ThisMonth,
+ address);
+ }
+
+ /// <summary>
+ /// Add ThisWeek Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddThisWeek(ExcelAddress address) {
+ return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
+ eExcelConditionalFormattingRuleType.ThisWeek,
+ address);
+ }
+
+ /// <summary>
+ /// Add Today Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddToday(ExcelAddress address) {
+ return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
+ eExcelConditionalFormattingRuleType.Today,
+ address);
+ }
+
+ /// <summary>
+ /// Add Tomorrow Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddTomorrow(ExcelAddress address) {
+ return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
+ eExcelConditionalFormattingRuleType.Tomorrow,
+ address);
+ }
+
+ /// <summary>
+ /// Add Yesterday Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddYesterday(ExcelAddress address) {
+ return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
+ eExcelConditionalFormattingRuleType.Yesterday,
+ address);
+ }
+
+ /// <summary>
+ /// Add BeginsWith Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingBeginsWith AddBeginsWith(ExcelAddress address) {
+ return (IExcelConditionalFormattingBeginsWith)AddRule(
+ eExcelConditionalFormattingRuleType.BeginsWith,
+ address);
+ }
+
+ /// <summary>
+ /// Add Between Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingBetween AddBetween(ExcelAddress address) {
+ return (IExcelConditionalFormattingBetween)AddRule(
+ eExcelConditionalFormattingRuleType.Between,
+ address);
+ }
+
+ /// <summary>
+ /// Add ContainsBlanks Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingContainsBlanks AddContainsBlanks(ExcelAddress address) {
+ return (IExcelConditionalFormattingContainsBlanks)AddRule(
+ eExcelConditionalFormattingRuleType.ContainsBlanks,
+ address);
+ }
+
+ /// <summary>
+ /// Add ContainsErrors Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingContainsErrors AddContainsErrors(ExcelAddress address) {
+ return (IExcelConditionalFormattingContainsErrors)AddRule(
+ eExcelConditionalFormattingRuleType.ContainsErrors,
+ address);
+ }
+
+ /// <summary>
+ /// Add ContainsText Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingContainsText AddContainsText(ExcelAddress address) {
+ return (IExcelConditionalFormattingContainsText)AddRule(
+ eExcelConditionalFormattingRuleType.ContainsText,
+ address);
+ }
+
+ /// <summary>
+ /// Add DuplicateValues Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingDuplicateValues AddDuplicateValues(ExcelAddress address) {
+ return (IExcelConditionalFormattingDuplicateValues)AddRule(
+ eExcelConditionalFormattingRuleType.DuplicateValues,
+ address);
+ }
+
+ /// <summary>
+ /// Add EndsWith Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingEndsWith AddEndsWith(ExcelAddress address) {
+ return (IExcelConditionalFormattingEndsWith)AddRule(
+ eExcelConditionalFormattingRuleType.EndsWith,
+ address);
+ }
+
+ /// <summary>
+ /// Add Equal Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingEqual AddEqual(ExcelAddress address) {
+ return (IExcelConditionalFormattingEqual)AddRule(
+ eExcelConditionalFormattingRuleType.Equal,
+ address);
+ }
+
+ /// <summary>
+ /// Add Expression Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingExpression AddExpression(ExcelAddress address) {
+ return (IExcelConditionalFormattingExpression)AddRule(
+ eExcelConditionalFormattingRuleType.Expression,
+ address);
+ }
+
+ /// <summary>
+ /// Add GreaterThan Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingGreaterThan AddGreaterThan(ExcelAddress address) {
+ return (IExcelConditionalFormattingGreaterThan)AddRule(
+ eExcelConditionalFormattingRuleType.GreaterThan,
+ address);
+ }
+
+ /// <summary>
+ /// Add GreaterThanOrEqual Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingGreaterThanOrEqual AddGreaterThanOrEqual(ExcelAddress address) {
+ return (IExcelConditionalFormattingGreaterThanOrEqual)AddRule(
+ eExcelConditionalFormattingRuleType.GreaterThanOrEqual,
+ address);
+ }
+
+ /// <summary>
+ /// Add LessThan Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingLessThan AddLessThan(ExcelAddress address) {
+ return (IExcelConditionalFormattingLessThan)AddRule(
+ eExcelConditionalFormattingRuleType.LessThan,
+ address);
+ }
+
+ /// <summary>
+ /// Add LessThanOrEqual Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingLessThanOrEqual AddLessThanOrEqual(ExcelAddress address) {
+ return (IExcelConditionalFormattingLessThanOrEqual)AddRule(
+ eExcelConditionalFormattingRuleType.LessThanOrEqual,
+ address);
+ }
+
+ /// <summary>
+ /// Add NotBetween Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingNotBetween AddNotBetween(ExcelAddress address) {
+ return (IExcelConditionalFormattingNotBetween)AddRule(
+ eExcelConditionalFormattingRuleType.NotBetween,
+ address);
+ }
+
+ /// <summary>
+ /// Add NotContainsBlanks Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingNotContainsBlanks AddNotContainsBlanks(ExcelAddress address) {
+ return (IExcelConditionalFormattingNotContainsBlanks)AddRule(
+ eExcelConditionalFormattingRuleType.NotContainsBlanks,
+ address);
+ }
+
+ /// <summary>
+ /// Add NotContainsErrors Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingNotContainsErrors AddNotContainsErrors(ExcelAddress address) {
+ return (IExcelConditionalFormattingNotContainsErrors)AddRule(
+ eExcelConditionalFormattingRuleType.NotContainsErrors,
+ address);
+ }
+
+ /// <summary>
+ /// Add NotContainsText Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingNotContainsText AddNotContainsText(ExcelAddress address) {
+ return (IExcelConditionalFormattingNotContainsText)AddRule(
+ eExcelConditionalFormattingRuleType.NotContainsText,
+ address);
+ }
+
+ /// <summary>
+ /// Add NotEqual Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingNotEqual AddNotEqual(ExcelAddress address) {
+ return (IExcelConditionalFormattingNotEqual)AddRule(
+ eExcelConditionalFormattingRuleType.NotEqual,
+ address);
+ }
+
+ /// <summary>
+ /// Add Unique Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingUniqueValues AddUniqueValues(ExcelAddress address) {
+ return (IExcelConditionalFormattingUniqueValues)AddRule(
+ eExcelConditionalFormattingRuleType.UniqueValues,
+ address);
+ }
+
+ /// <summary>
+ /// Add ThreeColorScale Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingThreeColorScale AddThreeColorScale(ExcelAddress address) {
+ return (IExcelConditionalFormattingThreeColorScale)AddRule(
+ eExcelConditionalFormattingRuleType.ThreeColorScale,
+ address);
+ }
+
+ /// <summary>
+ /// Add TwoColorScale Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTwoColorScale AddTwoColorScale(ExcelAddress address) {
+ return (IExcelConditionalFormattingTwoColorScale)AddRule(
+ eExcelConditionalFormattingRuleType.TwoColorScale,
+ address);
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingColorScaleValue.cs b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingColorScaleValue.cs
new file mode 100644
index 0000000..c1155b9
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingColorScaleValue.cs
@@ -0,0 +1,407 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Immutable;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// 18.3.1.11 cfvo (Conditional Format Value Object)
+/// Describes the values of the interpolation points in a gradient scale.
+/// </summary>
+public class ExcelConditionalFormattingColorScaleValue : XmlHelper {
+ private eExcelConditionalFormattingValueObjectPosition _position;
+ private eExcelConditionalFormattingRuleType _ruleType;
+ private readonly ExcelWorksheet _worksheet;
+
+ protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
+ ExcelConditionalFormattingConstants.Nodes._cfvo,
+ ExcelConditionalFormattingConstants.Nodes._color,
+ ];
+
+ /// <summary>
+ /// Initialize the cfvo (§18.3.1.11) node
+ /// </summary>
+ /// <param name="position"></param>
+ /// <param name="type"></param>
+ /// <param name="color"></param>
+ /// <param name="value"></param>
+ /// <param name="formula"></param>
+ /// <param name="ruleType"></param>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode">The cfvo (§18.3.1.11) node parent. Can be any of the following:
+ /// colorScale (§18.3.1.16); dataBar (§18.3.1.28); iconSet (§18.3.1.49)</param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingColorScaleValue(
+ eExcelConditionalFormattingValueObjectPosition position,
+ eExcelConditionalFormattingValueObjectType type,
+ double value,
+ string formula,
+ eExcelConditionalFormattingRuleType ruleType,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(namespaceManager, itemElementNode) {
+ ArgumentOutOfRangeException.ThrowIfLessThan(priority, 1);
+ ArgumentNullException.ThrowIfNull(address);
+ ArgumentNullException.ThrowIfNull(worksheet);
+
+ // Save the worksheet for private methods to use
+ _worksheet = worksheet;
+
+ // Check if the parent does not exists
+ if (itemElementNode == null) {
+ // Get the parent node path by the rule type
+ string parentNodePath = ExcelConditionalFormattingValueObjectType.GetParentPathByRuleType(
+ ruleType);
+
+ // Check for en error (rule type does not have <cfvo>)
+ if (parentNodePath == string.Empty) {
+ throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoParentNode);
+ }
+
+ // Point to the <cfvo> parent node
+ itemElementNode = _worksheet.WorksheetXml.SelectSingleNode(
+ string.Format(
+ "//{0}[{1}='{2}']/{3}[{4}='{5}']/{6}",
+ // {0}
+ ExcelConditionalFormattingConstants.Paths._conditionalFormatting,
+ // {1}
+ ExcelConditionalFormattingConstants.Paths._sqrefAttribute,
+ // {2}
+ address.Address,
+ // {3}
+ ExcelConditionalFormattingConstants.Paths._cfRule,
+ // {4}
+ ExcelConditionalFormattingConstants.Paths._priorityAttribute,
+ // {5}
+ priority,
+ // {6}
+ parentNodePath),
+ _worksheet.NameSpaceManager);
+
+ // Check for en error (rule type does not have <cfvo>)
+ if (itemElementNode == null) {
+ throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoParentNode);
+ }
+ }
+
+ // Point to the <cfvo> parent node (<colorScale>, <dataBar> or <iconSet>)
+ // This is different than normal, as TopNode does not point to the node itself but to
+ // its PARENT. Later, in the CreateNodeByOrdem method the TopNode will be updated.
+ TopNode = itemElementNode;
+
+ // Save the attributes
+ Position = position;
+ RuleType = ruleType;
+ Type = type;
+ Value = value;
+ Formula = formula;
+ }
+
+ /// <summary>
+ /// Initialize the <see cref="ExcelConditionalFormattingColorScaleValue"/>
+ /// </summary>
+ /// <param name="position"></param>
+ /// <param name="type"></param>
+ /// <param name="color"></param>
+ /// <param name="value"></param>
+ /// <param name="formula"></param>
+ /// <param name="ruleType"></param>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingColorScaleValue(
+ eExcelConditionalFormattingValueObjectPosition position,
+ eExcelConditionalFormattingValueObjectType type,
+ double value,
+ string formula,
+ eExcelConditionalFormattingRuleType ruleType,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNamespaceManager namespaceManager)
+ : this(
+ position,
+ type,
+ value,
+ formula,
+ ruleType,
+ address,
+ priority,
+ worksheet,
+ null,
+ namespaceManager) {}
+
+ /// <summary>
+ /// Initialize the <see cref="ExcelConditionalFormattingColorScaleValue"/>
+ /// </summary>
+ /// <param name="position"></param>
+ /// <param name="type"></param>
+ /// <param name="color"></param>
+ /// <param name="ruleType"></param>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingColorScaleValue(
+ eExcelConditionalFormattingValueObjectPosition position,
+ eExcelConditionalFormattingValueObjectType type,
+ eExcelConditionalFormattingRuleType ruleType,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNamespaceManager namespaceManager)
+ : this(
+ position,
+ type,
+ 0,
+ null,
+ ruleType,
+ address,
+ priority,
+ worksheet,
+ null,
+ namespaceManager) {}
+
+ /// <summary>
+ /// Get the node order (1, 2 ou 3) according to the Position (Low, Middle and High)
+ /// and the Rule Type (TwoColorScale ou ThreeColorScale).
+ /// </summary>
+ /// <returns></returns>
+ private int GetNodeOrder() {
+ return ExcelConditionalFormattingValueObjectType.GetOrderByPosition(Position, RuleType);
+ }
+
+ /// <summary>
+ /// Create the 'cfvo'/'color' nodes in the right order. They should appear like this:
+ /// "cfvo" --> Low Value (value object)
+ /// "cfvo" --> Middle Value (value object)
+ /// "cfvo" --> High Value (value object)
+ /// "color" --> Low Value (color)
+ /// "color" --> Middle Value (color)
+ /// "color" --> High Value (color)
+ /// </summary>
+ /// <param name="nodeType"></param>
+ /// <param name="attributePath"></param>
+ /// <param name="attributeValue"></param>
+ private void CreateNodeByOrdem(
+ eExcelConditionalFormattingValueObjectNodeType nodeType,
+ string attributePath,
+ string attributeValue) {
+ // Save the current TopNode
+ XmlNode currentTopNode = TopNode;
+
+ string nodePath = ExcelConditionalFormattingValueObjectType.GetNodePathByNodeType(nodeType);
+ int nodeOrder = GetNodeOrder();
+ eNodeInsertOrder nodeInsertOrder = eNodeInsertOrder.SchemaOrder;
+ XmlNode referenceNode = null;
+
+ if (nodeOrder > 1) {
+ // Find the node just before the one we need to include
+ referenceNode = TopNode.SelectSingleNode(
+ string.Format(
+ "{0}[position()={1}]",
+ // {0}
+ nodePath,
+ // {1}
+ nodeOrder - 1),
+ _worksheet.NameSpaceManager);
+
+ // Only if the prepend node exists than insert after
+ if (referenceNode != null) {
+ nodeInsertOrder = eNodeInsertOrder.After;
+ }
+ }
+
+ // Create the node in the right order
+ var node = CreateComplexNode(
+ TopNode,
+ string.Format(
+ "{0}[position()={1}]",
+ // {0}
+ nodePath,
+ // {1}
+ nodeOrder),
+ nodeInsertOrder,
+ referenceNode);
+
+ // Point to the new node as the temporary TopNode (we need it for the XmlHelper functions)
+ TopNode = node;
+
+ // Add/Remove the attribute (if the attributeValue is empty then it will be removed)
+ SetXmlNodeString(node, attributePath, attributeValue, true);
+
+ // Point back to the <cfvo>/<color> parent node
+ TopNode = currentTopNode;
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ internal eExcelConditionalFormattingValueObjectPosition Position {
+ get => _position;
+ set => _position = value;
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ internal eExcelConditionalFormattingRuleType RuleType {
+ get => _ruleType;
+ set => _ruleType = value;
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ public eExcelConditionalFormattingValueObjectType Type {
+ get {
+ var typeAttribute = GetXmlNodeString(
+ string.Format(
+ "{0}[position()={1}]/{2}",
+ // {0}
+ ExcelConditionalFormattingConstants.Paths._cfvo,
+ // {1}
+ GetNodeOrder(),
+ // {2}
+ ExcelConditionalFormattingConstants.Paths._typeAttribute));
+
+ return ExcelConditionalFormattingValueObjectType.GetTypeByAttrbiute(typeAttribute);
+ }
+ set {
+ CreateNodeByOrdem(
+ eExcelConditionalFormattingValueObjectNodeType.Cfvo,
+ ExcelConditionalFormattingConstants.Paths._typeAttribute,
+ ExcelConditionalFormattingValueObjectType.GetAttributeByType(value));
+
+ bool removeValAttribute = false;
+
+ // Make sure unnecessary attributes are removed (occures when we change
+ // the value object type)
+ switch (Type) {
+ case eExcelConditionalFormattingValueObjectType.Min:
+ case eExcelConditionalFormattingValueObjectType.Max:
+ removeValAttribute = true;
+ break;
+ }
+
+ // Check if we need to remove the @val attribute
+ if (removeValAttribute) {
+ string nodePath = ExcelConditionalFormattingValueObjectType.GetNodePathByNodeType(
+ eExcelConditionalFormattingValueObjectNodeType.Cfvo);
+ int nodeOrder = GetNodeOrder();
+
+ // Remove the attribute (removed when the value = '')
+ CreateComplexNode(
+ TopNode,
+ string.Format(
+ "{0}[position()={1}]/{2}=''",
+ // {0}
+ nodePath,
+ // {1}
+ nodeOrder,
+ // {2}
+ ExcelConditionalFormattingConstants.Paths._valAttribute));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Get/Set the 'cfvo' node @val attribute
+ /// </summary>
+ public Double Value {
+ get =>
+ GetXmlNodeDouble(
+ string.Format(
+ "{0}[position()={1}]/{2}",
+ // {0}
+ ExcelConditionalFormattingConstants.Paths._cfvo,
+ // {1}
+ GetNodeOrder(),
+ // {2}
+ ExcelConditionalFormattingConstants.Paths._valAttribute));
+ set {
+ string valueToStore = string.Empty;
+
+ // Only some types use the @val attribute
+ if ((Type == eExcelConditionalFormattingValueObjectType.Num)
+ || (Type == eExcelConditionalFormattingValueObjectType.Percent)
+ || (Type == eExcelConditionalFormattingValueObjectType.Percentile)) {
+ valueToStore = value.ToString();
+ }
+
+ CreateNodeByOrdem(
+ eExcelConditionalFormattingValueObjectNodeType.Cfvo,
+ ExcelConditionalFormattingConstants.Paths._valAttribute,
+ valueToStore);
+ }
+ }
+
+ /// <summary>
+ /// Get/Set the Formula of the Object Value (uses the same attribute as the Value)
+ /// </summary>
+ public string Formula {
+ get {
+ // Return empty if the Object Value type is not Formula
+ if (Type != eExcelConditionalFormattingValueObjectType.Formula) {
+ return string.Empty;
+ }
+
+ // Excel stores the formula in the @val attribute
+ return GetXmlNodeString(
+ string.Format(
+ "{0}[position()={1}]/{2}",
+ // {0}
+ ExcelConditionalFormattingConstants.Paths._cfvo,
+ // {1}
+ GetNodeOrder(),
+ // {2}
+ ExcelConditionalFormattingConstants.Paths._valAttribute));
+ }
+ set {
+ // Only store the formula if the Object Value type is Formula
+ if (Type == eExcelConditionalFormattingValueObjectType.Formula) {
+ CreateNodeByOrdem(
+ eExcelConditionalFormattingValueObjectNodeType.Cfvo,
+ ExcelConditionalFormattingConstants.Paths._valAttribute,
+ value ?? string.Empty);
+ }
+ }
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingConstants.cs b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingConstants.cs
new file mode 100644
index 0000000..b8578ec
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingConstants.cs
@@ -0,0 +1,259 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// The conditional formatting constants
+/// </summary>
+internal static class ExcelConditionalFormattingConstants {
+ internal class Errors {
+ internal const string _commaSeparatedAddresses =
+ "Multiple addresses may not be commaseparated, use space instead";
+ internal const string _invalidPriority = "Invalid priority number. Must be bigger than zero";
+ internal const string _invalidRemoveRuleOperation = "Invalid remove rule operation";
+ internal const string _missingCfvoNode = "Missing 'cfvo' node in Conditional Formatting";
+ internal const string _missingCfvoParentNode =
+ "Missing 'cfvo' parent node in Conditional Formatting";
+ internal const string _missingConditionalFormattingNode =
+ "Missing 'conditionalFormatting' node in Conditional Formatting";
+ internal const string _missingItemRuleList =
+ "Missing item with address '{0}' in Conditional Formatting Rule List";
+ internal const string _missingPriorityAttribute =
+ "Missing 'priority' attribute in Conditional Formatting Rule";
+ internal const string _missingRuleType =
+ "Missing eExcelConditionalFormattingRuleType Type in Conditional Formatting";
+ internal const string _missingSqrefAttribute =
+ "Missing 'sqref' attribute in Conditional Formatting";
+ internal const string _missingTypeAttribute =
+ "Missing 'type' attribute in Conditional Formatting Rule";
+ internal const string _missingWorksheetNode = "Missing 'worksheet' node";
+ internal const string _nonSupportedRuleType = "Non supported conditionalFormattingType: {0}";
+ internal const string _unexistentCfvoTypeAttribute =
+ "Unexistent eExcelConditionalFormattingValueObjectType attribute in Conditional Formatting";
+ internal const string _unexistentOperatorTypeAttribute =
+ "Unexistent eExcelConditionalFormattingOperatorType attribute in Conditional Formatting";
+ internal const string _unexistentTimePeriodTypeAttribute =
+ "Unexistent eExcelConditionalFormattingTimePeriodType attribute in Conditional Formatting";
+ internal const string _unexpectedRuleTypeAttribute =
+ "Unexpected eExcelConditionalFormattingRuleType attribute in Conditional Formatting Rule";
+ internal const string _wrongNumberCfvoColorNodes =
+ "Wrong number of 'cfvo'/'color' nodes in Conditional Formatting Rule";
+ }
+
+ internal class Nodes {
+ internal const string _worksheet = "worksheet";
+ internal const string _conditionalFormatting = "conditionalFormatting";
+ internal const string _cfRule = "cfRule";
+ internal const string _colorScale = "colorScale";
+ internal const string _cfvo = "cfvo";
+ internal const string _color = "color";
+ internal const string _dataBar = "dataBar";
+ internal const string _iconSet = "iconSet";
+ internal const string _formula = "formula";
+ }
+
+ internal class Attributes {
+ internal const string _aboveAverage = "aboveAverage";
+ internal const string _bottom = "bottom";
+ internal const string _dxfId = "dxfId";
+ internal const string _equalAverage = "equalAverage";
+ internal const string _iconSet = "iconSet";
+ internal const string _operator = "operator";
+ internal const string _percent = "percent";
+ internal const string _priority = "priority";
+ internal const string _rank = "rank";
+ internal const string _reverse = "reverse";
+ internal const string _rgb = "rgb";
+ internal const string _showValue = "showValue";
+ internal const string _sqref = "sqref";
+ internal const string _stdDev = "stdDev";
+ internal const string _stopIfTrue = "stopIfTrue";
+ internal const string _text = "text";
+ internal const string _theme = "theme";
+ internal const string _timePeriod = "timePeriod";
+ internal const string _tint = "tint";
+ internal const string _type = "type";
+ internal const string _val = "val";
+ }
+
+ internal class Paths {
+ // Main node and attributes
+ internal const string _worksheet = "d:" + Nodes._worksheet;
+
+ // <conditionalFormatting> §18.3.1.18 node
+ // can appear more than once in a worksheet
+ internal const string _conditionalFormatting = "d:" + Nodes._conditionalFormatting;
+
+ // <cfRule> §18.3.1.10 node
+ // can appear more than once in a <conditionalFormatting>
+ internal const string _cfRule = "d:" + Nodes._cfRule;
+
+ // <colorScale> §18.3.1.16 node
+ internal const string _colorScale = "d:" + Nodes._colorScale;
+
+ // <cfvo> §18.3.1.11 node
+ internal const string _cfvo = "d:" + Nodes._cfvo;
+
+ // <color> §18.3.1.15 node
+ internal const string _color = "d:" + Nodes._color;
+
+ // <dataBar> §18.3.1.28 node
+ internal const string _dataBar = "d:" + Nodes._dataBar;
+
+ // <iconSet> §18.3.1.49 node
+ internal const string _iconSet = "d:" + Nodes._iconSet;
+
+ // <formula> §18.3.1.43 node
+ internal const string _formula = "d:" + Nodes._formula;
+
+ // Attributes (for all the nodes)
+ internal const string _aboveAverageAttribute = "@" + Attributes._aboveAverage;
+ internal const string _bottomAttribute = "@" + Attributes._bottom;
+ internal const string _dxfIdAttribute = "@" + Attributes._dxfId;
+ internal const string _equalAverageAttribute = "@" + Attributes._equalAverage;
+ internal const string _iconSetAttribute = "@" + Attributes._iconSet;
+ internal const string _operatorAttribute = "@" + Attributes._operator;
+ internal const string _percentAttribute = "@" + Attributes._percent;
+ internal const string _priorityAttribute = "@" + Attributes._priority;
+ internal const string _rankAttribute = "@" + Attributes._rank;
+ internal const string _reverseAttribute = "@" + Attributes._reverse;
+ internal const string _rgbAttribute = "@" + Attributes._rgb;
+ internal const string _showValueAttribute = "@" + Attributes._showValue;
+ internal const string _sqrefAttribute = "@" + Attributes._sqref;
+ internal const string _stdDevAttribute = "@" + Attributes._stdDev;
+ internal const string _stopIfTrueAttribute = "@" + Attributes._stopIfTrue;
+ internal const string _textAttribute = "@" + Attributes._text;
+ internal const string _themeAttribute = "@" + Attributes._theme;
+ internal const string _timePeriodAttribute = "@" + Attributes._timePeriod;
+ internal const string _tintAttribute = "@" + Attributes._tint;
+ internal const string _typeAttribute = "@" + Attributes._type;
+ internal const string _valAttribute = "@" + Attributes._val;
+ }
+
+ internal class RuleType {
+ internal const string _aboveAverage = "aboveAverage";
+ internal const string _beginsWith = "beginsWith";
+ internal const string _cellIs = "cellIs";
+ internal const string _colorScale = "colorScale";
+ internal const string _containsBlanks = "containsBlanks";
+ internal const string _containsErrors = "containsErrors";
+ internal const string _containsText = "containsText";
+ internal const string _dataBar = "dataBar";
+ internal const string _duplicateValues = "duplicateValues";
+ internal const string _endsWith = "endsWith";
+ internal const string _expression = "expression";
+ internal const string _iconSet = "iconSet";
+ internal const string _notContainsBlanks = "notContainsBlanks";
+ internal const string _notContainsErrors = "notContainsErrors";
+ internal const string _notContainsText = "notContainsText";
+ internal const string _timePeriod = "timePeriod";
+ internal const string _top10 = "top10";
+ internal const string _uniqueValues = "uniqueValues";
+
+ // EPPlus Extended Types
+ internal const string _aboveOrEqualAverage = "aboveOrEqualAverage";
+ internal const string _aboveStdDev = "aboveStdDev";
+ internal const string _belowAverage = "belowAverage";
+ internal const string _belowOrEqualAverage = "belowOrEqualAverage";
+ internal const string _belowStdDev = "belowStdDev";
+ internal const string _between = "between";
+ internal const string _bottom = "bottom";
+ internal const string _bottomPercent = "bottomPercent";
+ internal const string _equal = "equal";
+ internal const string _greaterThan = "greaterThan";
+ internal const string _greaterThanOrEqual = "greaterThanOrEqual";
+ internal const string _iconSet3 = "iconSet3";
+ internal const string _iconSet4 = "iconSet4";
+ internal const string _iconSet5 = "iconSet5";
+ internal const string _last7Days = "last7Days";
+ internal const string _lastMonth = "lastMonth";
+ internal const string _lastWeek = "lastWeek";
+ internal const string _lessThan = "lessThan";
+ internal const string _lessThanOrEqual = "lessThanOrEqual";
+ internal const string _nextMonth = "nextMonth";
+ internal const string _nextWeek = "nextWeek";
+ internal const string _notBetween = "notBetween";
+ internal const string _notEqual = "notEqual";
+ internal const string _thisMonth = "thisMonth";
+ internal const string _thisWeek = "thisWeek";
+ internal const string _threeColorScale = "threeColorScale";
+ internal const string _today = "today";
+ internal const string _tomorrow = "tomorrow";
+ internal const string _top = "top";
+ internal const string _topPercent = "topPercent";
+ internal const string _twoColorScale = "twoColorScale";
+ internal const string _yesterday = "yesterday";
+ }
+
+ internal class CfvoType {
+ internal const string _min = "min";
+ internal const string _max = "max";
+ internal const string _num = "num";
+ internal const string _formula = "formula";
+ internal const string _percent = "percent";
+ internal const string _percentile = "percentile";
+ }
+
+ internal class Operators {
+ internal const string _beginsWith = "beginsWith";
+ internal const string _between = "between";
+ internal const string _containsText = "containsText";
+ internal const string _endsWith = "endsWith";
+ internal const string _equal = "equal";
+ internal const string _greaterThan = "greaterThan";
+ internal const string _greaterThanOrEqual = "greaterThanOrEqual";
+ internal const string _lessThan = "lessThan";
+ internal const string _lessThanOrEqual = "lessThanOrEqual";
+ internal const string _notBetween = "notBetween";
+ internal const string _notContains = "notContains";
+ internal const string _notEqual = "notEqual";
+ }
+
+ internal class TimePeriods {
+ internal const string _last7Days = "last7Days";
+ internal const string _lastMonth = "lastMonth";
+ internal const string _lastWeek = "lastWeek";
+ internal const string _nextMonth = "nextMonth";
+ internal const string _nextWeek = "nextWeek";
+ internal const string _thisMonth = "thisMonth";
+ internal const string _thisWeek = "thisWeek";
+ internal const string _today = "today";
+ internal const string _tomorrow = "tomorrow";
+ internal const string _yesterday = "yesterday";
+ }
+
+ internal class Colors {
+ internal const string _cfvoLowValue = "#FFF8696B";
+ internal const string _cfvoMiddleValue = "#FFFFEB84";
+ internal const string _cfvoHighValue = "#FF63BE7B";
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingEnums.cs b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingEnums.cs
new file mode 100644
index 0000000..a53524d
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingEnums.cs
@@ -0,0 +1,753 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Enum for Conditional Format Type ST_CfType §18.18.12. With some changes.
+/// </summary>
+public enum eExcelConditionalFormattingRuleType {
+ /// <summary>
+ /// This conditional formatting rule highlights cells that are above the average
+ /// for all values in the range.
+ /// </summary>
+ /// <remarks>AboveAverage Excel CF Rule Type</remarks>
+ AboveAverage,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells that are above or equal
+ /// the average for all values in the range.
+ /// </summary>
+ /// <remarks>AboveAverage Excel CF Rule Type</remarks>
+ AboveOrEqualAverage,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells that are below the average
+ /// for all values in the range.
+ /// </summary>
+ /// <remarks>AboveAverage Excel CF Rule Type</remarks>
+ BelowAverage,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells that are below or equal
+ /// the average for all values in the range.
+ /// </summary>
+ /// <remarks>AboveAverage Excel CF Rule Type</remarks>
+ BelowOrEqualAverage,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells that are above the standard
+ /// deviationa for all values in the range.
+ /// <remarks>AboveAverage Excel CF Rule Type</remarks>
+ /// </summary>
+ AboveStdDev,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells that are below the standard
+ /// deviationa for all values in the range.
+ /// </summary>
+ /// <remarks>AboveAverage Excel CF Rule Type</remarks>
+ BelowStdDev,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells whose values fall in the
+ /// bottom N bracket as specified.
+ /// </summary>
+ /// <remarks>Top10 Excel CF Rule Type</remarks>
+ Bottom,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells whose values fall in the
+ /// bottom N percent as specified.
+ /// </summary>
+ /// <remarks>Top10 Excel CF Rule Type</remarks>
+ BottomPercent,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells whose values fall in the
+ /// top N bracket as specified.
+ /// </summary>
+ /// <remarks>Top10 Excel CF Rule Type</remarks>
+ Top,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells whose values fall in the
+ /// top N percent as specified.
+ /// </summary>
+ /// <remarks>Top10 Excel CF Rule Type</remarks>
+ TopPercent,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing dates in the
+ /// last 7 days.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ Last7Days,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing dates in the
+ /// last month.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ LastMonth,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing dates in the
+ /// last week.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ LastWeek,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing dates in the
+ /// next month.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ NextMonth,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing dates in the
+ /// next week.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ NextWeek,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing dates in this
+ /// month.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ ThisMonth,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing dates in this
+ /// week.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ ThisWeek,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing today dates.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ Today,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing tomorrow dates.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ Tomorrow,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing yesterday dates.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ Yesterday,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells in the range that begin with
+ /// the given text.
+ /// </summary>
+ /// <remarks>
+ /// Equivalent to using the LEFT() sheet function and comparing values.
+ /// </remarks>
+ /// <remarks>BeginsWith Excel CF Rule Type</remarks>
+ BeginsWith,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells in the range between the
+ /// given two formulas.
+ /// </summary>
+ /// <remarks>CellIs Excel CF Rule Type</remarks>
+ Between,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells that are completely blank.
+ /// </summary>
+ /// <remarks>
+ /// Equivalent of using LEN(TRIM()). This means that if the cell contains only
+ /// characters that TRIM() would remove, then it is considered blank. An empty cell
+ /// is also considered blank.
+ /// </remarks>
+ /// <remarks>ContainsBlanks Excel CF Rule Type</remarks>
+ ContainsBlanks,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells with formula errors.
+ /// </summary>
+ /// <remarks>
+ /// Equivalent to using ISERROR() sheet function to determine if there is
+ /// a formula error.
+ /// </remarks>
+ /// <remarks>ContainsErrors Excel CF Rule Type</remarks>
+ ContainsErrors,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells in the range that begin with
+ /// the given text.
+ /// </summary>
+ /// <remarks>
+ /// Equivalent to using the LEFT() sheet function and comparing values.
+ /// </remarks>
+ /// <remarks>ContainsText Excel CF Rule Type</remarks>
+ ContainsText,
+
+ /// <summary>
+ /// This conditional formatting rule highlights duplicated values.
+ /// </summary>
+ /// <remarks>DuplicateValues Excel CF Rule Type</remarks>
+ DuplicateValues,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells ending with given text.
+ /// </summary>
+ /// <remarks>
+ /// Equivalent to using the RIGHT() sheet function and comparing values.
+ /// </remarks>
+ /// <remarks>EndsWith Excel CF Rule Type</remarks>
+ EndsWith,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells equals to with given formula.
+ /// </summary>
+ /// <remarks>CellIs Excel CF Rule Type</remarks>
+ Equal,
+
+ /// <summary>
+ /// This conditional formatting rule contains a formula to evaluate. When the
+ /// formula result is true, the cell is highlighted.
+ /// </summary>
+ /// <remarks>Expression Excel CF Rule Type</remarks>
+ Expression,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells greater than the given formula.
+ /// </summary>
+ /// <remarks>CellIs Excel CF Rule Type</remarks>
+ GreaterThan,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells greater than or equal the
+ /// given formula.
+ /// </summary>
+ /// <remarks>CellIs Excel CF Rule Type</remarks>
+ GreaterThanOrEqual,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells less than the given formula.
+ /// </summary>
+ /// <remarks>CellIs Excel CF Rule Type</remarks>
+ LessThan,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells less than or equal the
+ /// given formula.
+ /// </summary>
+ /// <remarks>CellIs Excel CF Rule Type</remarks>
+ LessThanOrEqual,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells outside the range in
+ /// given two formulas.
+ /// </summary>
+ /// <remarks>CellIs Excel CF Rule Type</remarks>
+ NotBetween,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells that does not contains the
+ /// given formula.
+ /// </summary>
+ /// <remarks>CellIs Excel CF Rule Type</remarks>
+ NotContains,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells that are not blank.
+ /// </summary>
+ /// <remarks>
+ /// Equivalent of using LEN(TRIM()). This means that if the cell contains only
+ /// characters that TRIM() would remove, then it is considered blank. An empty cell
+ /// is also considered blank.
+ /// </remarks>
+ /// <remarks>NotContainsBlanks Excel CF Rule Type</remarks>
+ NotContainsBlanks,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells without formula errors.
+ /// </summary>
+ /// <remarks>
+ /// Equivalent to using ISERROR() sheet function to determine if there is a
+ /// formula error.
+ /// </remarks>
+ /// <remarks>NotContainsErrors Excel CF Rule Type</remarks>
+ NotContainsErrors,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells that do not contain
+ /// the given text.
+ /// </summary>
+ /// <remarks>
+ /// Equivalent to using the SEARCH() sheet function.
+ /// </remarks>
+ /// <remarks>NotContainsText Excel CF Rule Type</remarks>
+ NotContainsText,
+
+ /// <summary>
+ /// This conditional formatting rule highlights cells not equals to with
+ /// given formula.
+ /// </summary>
+ /// <remarks>CellIs Excel CF Rule Type</remarks>
+ NotEqual,
+
+ /// <summary>
+ /// This conditional formatting rule highlights unique values in the range.
+ /// </summary>
+ /// <remarks>UniqueValues Excel CF Rule Type</remarks>
+ UniqueValues,
+
+ /// <summary>
+ /// Three Color Scale (Low, Middle and High Color Scale)
+ /// </summary>
+ /// <remarks>ColorScale Excel CF Rule Type</remarks>
+ ThreeColorScale,
+
+ /// <summary>
+ /// Two Color Scale (Low and High Color Scale)
+ /// </summary>
+ /// <remarks>ColorScale Excel CF Rule Type</remarks>
+ TwoColorScale,
+
+ /// <summary>
+ /// This conditional formatting rule applies a 3 set icons to cells according
+ /// to their values.
+ /// </summary>
+ /// <remarks>IconSet Excel CF Rule Type</remarks>
+ ThreeIconSet,
+
+ /// <summary>
+ /// This conditional formatting rule applies a 4 set icons to cells according
+ /// to their values.
+ /// </summary>
+ /// <remarks>IconSet Excel CF Rule Type</remarks>
+ FourIconSet,
+
+ /// <summary>
+ /// This conditional formatting rule applies a 5 set icons to cells according
+ /// to their values.
+ /// </summary>
+ /// <remarks>IconSet Excel CF Rule Type</remarks>
+ FiveIconSet,
+
+ /// <summary>
+ /// This conditional formatting rule displays a gradated data bar in the range of cells.
+ /// </summary>
+ /// <remarks>DataBar Excel CF Rule Type</remarks>
+ DataBar,
+}
+
+/// <summary>
+/// Enum for Conditional Format Value Object Type ST_CfvoType §18.18.13
+/// </summary>
+public enum eExcelConditionalFormattingValueObjectType {
+ /// <summary>
+ /// Formula
+ /// </summary>
+ Formula,
+
+ /// <summary>
+ /// Maximum Value
+ /// </summary>
+ Max,
+
+ /// <summary>
+ /// Minimum Value
+ /// </summary>
+ Min,
+
+ /// <summary>
+ /// Number Value
+ /// </summary>
+ Num,
+
+ /// <summary>
+ /// Percent
+ /// </summary>
+ Percent,
+
+ /// <summary>
+ /// Percentile
+ /// </summary>
+ Percentile,
+}
+
+/// <summary>
+/// Enum for Conditional Formatting Value Object Position
+/// </summary>
+public enum eExcelConditionalFormattingValueObjectPosition {
+ /// <summary>
+ /// The lower position for both TwoColorScale and ThreeColorScale
+ /// </summary>
+ Low,
+
+ /// <summary>
+ /// The middle position only for ThreeColorScale
+ /// </summary>
+ Middle,
+
+ /// <summary>
+ /// The highest position for both TwoColorScale and ThreeColorScale
+ /// </summary>
+ High,
+}
+
+/// <summary>
+/// Enum for Conditional Formatting Value Object Node Type
+/// </summary>
+public enum eExcelConditionalFormattingValueObjectNodeType {
+ /// <summary>
+ /// 'cfvo' node
+ /// </summary>
+ Cfvo,
+
+ /// <summary>
+ /// 'color' node
+ /// </summary>
+ Color,
+}
+
+/// <summary>
+/// Enum for Conditional Formatting Operartor Type ST_ConditionalFormattingOperator §18.18.15
+/// </summary>
+public enum eExcelConditionalFormattingOperatorType {
+ /// <summary>
+ /// Begins With. 'Begins with' operator
+ /// </summary>
+ BeginsWith,
+
+ /// <summary>
+ /// Between. 'Between' operator
+ /// </summary>
+ Between,
+
+ /// <summary>
+ /// Contains. 'Contains' operator
+ /// </summary>
+ ContainsText,
+
+ /// <summary>
+ /// Ends With. 'Ends with' operator
+ /// </summary>
+ EndsWith,
+
+ /// <summary>
+ /// Equal. 'Equal to' operator
+ /// </summary>
+ Equal,
+
+ /// <summary>
+ /// Greater Than. 'Greater than' operator
+ /// </summary>
+ GreaterThan,
+
+ /// <summary>
+ /// Greater Than Or Equal. 'Greater than or equal to' operator
+ /// </summary>
+ GreaterThanOrEqual,
+
+ /// <summary>
+ /// Less Than. 'Less than' operator
+ /// </summary>
+ LessThan,
+
+ /// <summary>
+ /// Less Than Or Equal. 'Less than or equal to' operator
+ /// </summary>
+ LessThanOrEqual,
+
+ /// <summary>
+ /// Not Between. 'Not between' operator
+ /// </summary>
+ NotBetween,
+
+ /// <summary>
+ /// Does Not Contain. 'Does not contain' operator
+ /// </summary>
+ NotContains,
+
+ /// <summary>
+ /// Not Equal. 'Not equal to' operator
+ /// </summary>
+ NotEqual,
+}
+
+/// <summary>
+/// Enum for Conditional Formatting Time Period Type ST_TimePeriod §18.18.82
+/// </summary>
+public enum eExcelConditionalFormattingTimePeriodType {
+ /// <summary>
+ /// Last 7 Days. A date in the last seven days.
+ /// </summary>
+ Last7Days,
+
+ /// <summary>
+ /// Last Month. A date occuring in the last calendar month.
+ /// </summary>
+ LastMonth,
+
+ /// <summary>
+ /// Last Week. A date occuring last week.
+ /// </summary>
+ LastWeek,
+
+ /// <summary>
+ /// Next Month. A date occuring in the next calendar month.
+ /// </summary>
+ NextMonth,
+
+ /// <summary>
+ /// Next Week. A date occuring next week.
+ /// </summary>
+ NextWeek,
+
+ /// <summary>
+ /// This Month. A date occuring in this calendar month.
+ /// </summary>
+ ThisMonth,
+
+ /// <summary>
+ /// This Week. A date occuring this week.
+ /// </summary>
+ ThisWeek,
+
+ /// <summary>
+ /// Today. Today's date.
+ /// </summary>
+ Today,
+
+ /// <summary>
+ /// Tomorrow. Tomorrow's date.
+ /// </summary>
+ Tomorrow,
+
+ /// <summary>
+ /// Yesterday. Yesterday's date.
+ /// </summary>
+ Yesterday,
+}
+
+/// <summary>
+/// 18.18.42 ST_IconSetType (Icon Set Type) - Only 3 icons
+/// </summary>
+public enum eExcelconditionalFormatting3IconsSetType {
+ /// <summary>
+ /// (3 Arrows) 3 arrows icon set.
+ /// </summary>
+ Arrows,
+
+ /// <summary>
+ /// (3 Arrows (Gray)) 3 gray arrows icon set.
+ /// </summary>
+ ArrowsGray,
+
+ /// <summary>
+ /// (3 Flags) 3 flags icon set.
+ /// </summary>
+ Flags,
+
+ /// <summary>
+ /// (3 Signs) 3 signs icon set.
+ /// </summary>
+ Signs,
+
+ /// <summary>
+ /// (3 Symbols Circled) 3 symbols icon set.
+ /// </summary>
+ Symbols,
+
+ /// <summary>
+ /// (3 Symbols) 3 Symbols icon set.
+ /// </summary>
+ Symbols2,
+
+ /// <summary>
+ /// (3 Traffic Lights) 3 traffic lights icon set (#1).
+ /// </summary>
+ TrafficLights1,
+
+ /// <summary>
+ /// (3 Traffic Lights Black) 3 traffic lights icon set with thick black border.
+ /// </summary>
+ TrafficLights2,
+}
+
+/// <summary>
+/// 18.18.42 ST_IconSetType (Icon Set Type) - Only 4 icons
+/// </summary>
+public enum eExcelconditionalFormatting4IconsSetType {
+ /// <summary>
+ /// (4 Arrows) 4 arrows icon set.
+ /// </summary>
+ Arrows,
+
+ /// <summary>
+ /// (4 Arrows (Gray)) 4 gray arrows icon set.
+ /// </summary>
+ ArrowsGray,
+
+ /// <summary>
+ /// (4 Ratings) 4 ratings icon set.
+ /// </summary>
+ Rating,
+
+ /// <summary>
+ /// (4 Red To Black) 4 'red to black' icon set.
+ /// </summary>
+ RedToBlack,
+
+ /// <summary>
+ /// (4 Traffic Lights) 4 traffic lights icon set.
+ /// </summary>
+ TrafficLights,
+}
+
+/// <summary>
+/// 18.18.42 ST_IconSetType (Icon Set Type) - Only 5 icons
+/// </summary>
+public enum eExcelconditionalFormatting5IconsSetType {
+ /// <summary>
+ /// (5 Arrows) 5 arrows icon set.
+ /// </summary>
+ Arrows,
+
+ /// <summary>
+ /// (5 Arrows (Gray)) 5 gray arrows icon set.
+ /// </summary>
+ ArrowsGray,
+
+ /// <summary>
+ /// (5 Quarters) 5 quarters icon set.
+ /// </summary>
+ Quarters,
+
+ /// <summary>
+ /// (5 Ratings Icon Set) 5 rating icon set.
+ /// </summary>
+ Rating,
+}
+
+/// <summary>
+/// 18.18.42 ST_IconSetType (Icon Set Type)
+/// </summary>
+public enum eExcelconditionalFormattingIconsSetType {
+ /// <summary>
+ /// (3 Arrows) 3 arrows icon set.
+ /// </summary>
+ ThreeArrows,
+
+ /// <summary>
+ /// (3 Arrows (Gray)) 3 gray arrows icon set.
+ /// </summary>
+ ThreeArrowsGray,
+
+ /// <summary>
+ /// (3 Flags) 3 flags icon set.
+ /// </summary>
+ ThreeFlags,
+
+ /// <summary>
+ /// (3 Signs) 3 signs icon set.
+ /// </summary>
+ ThreeSigns,
+
+ /// <summary>
+ /// (3 Symbols Circled) 3 symbols icon set.
+ /// </summary>
+ ThreeSymbols,
+
+ /// <summary>
+ /// (3 Symbols) 3 Symbols icon set.
+ /// </summary>
+ ThreeSymbols2,
+
+ /// <summary>
+ /// (3 Traffic Lights) 3 traffic lights icon set (#1).
+ /// </summary>
+ ThreeTrafficLights1,
+
+ /// <summary>
+ /// (3 Traffic Lights Black) 3 traffic lights icon set with thick black border.
+ /// </summary>
+ ThreeTrafficLights2,
+
+ /// <summary>
+ /// (4 Arrows) 4 arrows icon set.
+ /// </summary>
+ FourArrows,
+
+ /// <summary>
+ /// (4 Arrows (Gray)) 4 gray arrows icon set.
+ /// </summary>
+ FourArrowsGray,
+
+ /// <summary>
+ /// (4 Ratings) 4 ratings icon set.
+ /// </summary>
+ FourRating,
+
+ /// <summary>
+ /// (4 Red To Black) 4 'red to black' icon set.
+ /// </summary>
+ FourRedToBlack,
+
+ /// <summary>
+ /// (4 Traffic Lights) 4 traffic lights icon set.
+ /// </summary>
+ FourTrafficLights,
+
+ /// <summary>
+ /// (5 Arrows) 5 arrows icon set.
+ /// </summary>
+ FiveArrows,
+
+ /// <summary>
+ /// (5 Arrows (Gray)) 5 gray arrows icon set.
+ /// </summary>
+ FiveArrowsGray,
+
+ /// <summary>
+ /// (5 Quarters) 5 quarters icon set.
+ /// </summary>
+ FiveQuarters,
+
+ /// <summary>
+ /// (5 Ratings Icon Set) 5 rating icon set.
+ /// </summary>
+ FiveRating,
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingHelper.cs b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingHelper.cs
new file mode 100644
index 0000000..5947fbd
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingHelper.cs
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System;
+using System.Globalization;
+using System.Text.RegularExpressions;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Conditional formatting helper
+/// </summary>
+internal static class ExcelConditionalFormattingHelper {
+ /// <summary>
+ /// Check and fix an address (string address)
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public static string CheckAndFixRangeAddress(string address) {
+ if (address.Contains(',')) {
+ throw new FormatException(
+ ExcelConditionalFormattingConstants.Errors._commaSeparatedAddresses);
+ }
+
+ address = address.ToUpper(CultureInfo.InvariantCulture);
+
+ if (Regex.IsMatch(address, "[A-Z]+:[A-Z]+")) {
+ address = AddressUtility.ParseEntireColumnSelections(address);
+ }
+
+ return address;
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="node"></param>
+ /// <param name="attribute"></param>
+ /// <returns></returns>
+ public static string GetAttributeString(XmlNode node, string attribute) {
+ try {
+ var value = node.Attributes[attribute].Value;
+ return value ?? string.Empty;
+ } catch {
+ return string.Empty;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="node"></param>
+ /// <param name="attribute"></param>
+ /// <returns></returns>
+ public static int GetAttributeInt(XmlNode node, string attribute) {
+ try {
+ var value = node.Attributes[attribute].Value;
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ } catch {
+ return int.MinValue;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="node"></param>
+ /// <param name="attribute"></param>
+ /// <returns></returns>
+ public static int? GetAttributeIntNullable(XmlNode node, string attribute) {
+ try {
+ if (node.Attributes[attribute] == null) {
+ return null;
+ }
+ var value = node.Attributes[attribute].Value;
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ } catch {
+ return null;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="node"></param>
+ /// <param name="attribute"></param>
+ /// <returns></returns>
+ public static bool GetAttributeBool(XmlNode node, string attribute) {
+ try {
+ var value = node.Attributes[attribute].Value;
+ return (value == "1"
+ || value == "-1"
+ || value.Equals("TRUE", StringComparison.InvariantCultureIgnoreCase));
+ } catch {
+ return false;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="node"></param>
+ /// <param name="attribute"></param>
+ /// <returns></returns>
+ public static bool? GetAttributeBoolNullable(XmlNode node, string attribute) {
+ try {
+ if (node.Attributes[attribute] == null) {
+ return null;
+ }
+ var value = node.Attributes[attribute].Value;
+ return (value == "1"
+ || value == "-1"
+ || value.Equals("TRUE", StringComparison.InvariantCultureIgnoreCase));
+ } catch {
+ return null;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="node"></param>
+ /// <param name="attribute"></param>
+ /// <returns></returns>
+ public static double GetAttributeDouble(XmlNode node, string attribute) {
+ try {
+ var value = node.Attributes[attribute].Value;
+ return double.Parse(value, NumberStyles.Number, CultureInfo.InvariantCulture);
+ } catch {
+ return double.NaN;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="node"></param>
+ /// <param name="attribute"></param>
+ /// <returns></returns>
+ public static decimal GetAttributeDecimal(XmlNode node, string attribute) {
+ try {
+ var value = node.Attributes[attribute].Value;
+ return decimal.Parse(value, NumberStyles.Any, CultureInfo.InvariantCulture);
+ } catch {
+ return decimal.MinValue;
+ }
+ }
+
+ /// <summary>
+ /// Encode to XML (special characteres: ' " > < &)
+ /// </summary>
+ /// <param name="s"></param>
+ /// <returns></returns>
+ public static string EncodeXml(this string s) {
+ return s.Replace("&", "&")
+ .Replace("<", "<")
+ .Replace(">", ">")
+ .Replace("\"", """)
+ .Replace("'", "'");
+ }
+
+ /// <summary>
+ /// Decode from XML (special characteres: ' " > < &)
+ /// </summary>
+ /// <param name="s"></param>
+ /// <returns></returns>
+ public static string DecodeXml(this string s) {
+ return s.Replace("'", "'")
+ .Replace("\"", """)
+ .Replace(">", ">")
+ .Replace("<", "<")
+ .Replace("&", "&");
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingIconDatabarValue.cs b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingIconDatabarValue.cs
new file mode 100644
index 0000000..ed367b3
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingIconDatabarValue.cs
@@ -0,0 +1,289 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Immutable;
+using System.Drawing;
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// 18.3.1.11 cfvo (Conditional Format Value Object)
+/// Describes the values of the interpolation points in a gradient scale.
+/// </summary>
+public class ExcelConditionalFormattingIconDataBarValue : XmlHelper {
+ private eExcelConditionalFormattingRuleType _ruleType;
+ private readonly ExcelWorksheet _worksheet;
+
+ /// <summary>
+ /// Initialize the cfvo (§18.3.1.11) node
+ /// </summary>
+ /// <param name="type"></param>
+ /// <param name="value"></param>
+ /// <param name="formula"></param>
+ /// <param name="ruleType"></param>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode">The cfvo (§18.3.1.11) node parent. Can be any of the following:
+ /// colorScale (§18.3.1.16); dataBar (§18.3.1.28); iconSet (§18.3.1.49)</param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingIconDataBarValue(
+ eExcelConditionalFormattingValueObjectType type,
+ double value,
+ string formula,
+ eExcelConditionalFormattingRuleType ruleType,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : this(ruleType, address, worksheet, itemElementNode, namespaceManager) {
+ ArgumentOutOfRangeException.ThrowIfLessThan(priority, 1);
+
+ // Check if the parent does not exists
+ if (itemElementNode == null) {
+ // Get the parent node path by the rule type
+ string parentNodePath = ExcelConditionalFormattingValueObjectType.GetParentPathByRuleType(
+ ruleType);
+
+ // Check for en error (rule type does not have <cfvo>)
+ if (parentNodePath == string.Empty) {
+ throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoParentNode);
+ }
+
+ // Point to the <cfvo> parent node
+ itemElementNode = _worksheet.WorksheetXml.SelectSingleNode(
+ string.Format(
+ "//{0}[{1}='{2}']/{3}[{4}='{5}']/{6}",
+ // {0}
+ ExcelConditionalFormattingConstants.Paths._conditionalFormatting,
+ // {1}
+ ExcelConditionalFormattingConstants.Paths._sqrefAttribute,
+ // {2}
+ address.Address,
+ // {3}
+ ExcelConditionalFormattingConstants.Paths._cfRule,
+ // {4}
+ ExcelConditionalFormattingConstants.Paths._priorityAttribute,
+ // {5}
+ priority,
+ // {6}
+ parentNodePath),
+ _worksheet.NameSpaceManager);
+
+ // Check for en error (rule type does not have <cfvo>)
+ if (itemElementNode == null) {
+ throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoParentNode);
+ }
+ }
+
+ TopNode = itemElementNode;
+
+ // Save the attributes
+ RuleType = ruleType;
+ Type = type;
+ Value = value;
+ Formula = formula;
+ }
+
+ protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
+ ExcelConditionalFormattingConstants.Nodes._cfvo,
+ ];
+
+ /// <summary>
+ /// Initialize the cfvo (§18.3.1.11) node
+ /// </summary>
+ /// <param name="ruleType"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode">The cfvo (§18.3.1.11) node parent. Can be any of the following:
+ /// colorScale (§18.3.1.16); dataBar (§18.3.1.28); iconSet (§18.3.1.49)</param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingIconDataBarValue(
+ eExcelConditionalFormattingRuleType ruleType,
+ ExcelAddress address,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(namespaceManager, itemElementNode) {
+ ArgumentNullException.ThrowIfNull(address);
+ ArgumentNullException.ThrowIfNull(worksheet);
+
+ // Save the worksheet for private methods to use
+ _worksheet = worksheet;
+
+ //Check if the parent does not exists
+ if (itemElementNode == null) {
+ // Get the parent node path by the rule type
+ string parentNodePath = ExcelConditionalFormattingValueObjectType.GetParentPathByRuleType(
+ ruleType);
+
+ // Check for en error (rule type does not have <cfvo>)
+ if (parentNodePath == string.Empty) {
+ throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoParentNode);
+ }
+ }
+ RuleType = ruleType;
+ }
+
+ /// <summary>
+ /// Initialize the <see cref="ExcelConditionalFormattingColorScaleValue"/>
+ /// </summary>
+ /// <param name="type"></param>
+ /// <param name="value"></param>
+ /// <param name="formula"></param>
+ /// <param name="ruleType"></param>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingIconDataBarValue(
+ eExcelConditionalFormattingValueObjectType type,
+ double value,
+ string formula,
+ eExcelConditionalFormattingRuleType ruleType,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNamespaceManager namespaceManager)
+ : this(
+ type,
+ value,
+ formula,
+ ruleType,
+ address,
+ priority,
+ worksheet,
+ null,
+ namespaceManager) {}
+
+ /// <summary>
+ /// Initialize the <see cref="ExcelConditionalFormattingColorScaleValue"/>
+ /// </summary>
+ /// <param name="type"></param>
+ /// <param name="color"></param>
+ /// <param name="ruleType"></param>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingIconDataBarValue(
+ eExcelConditionalFormattingValueObjectType type,
+ Color color,
+ eExcelConditionalFormattingRuleType ruleType,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNamespaceManager namespaceManager)
+ : this(type, 0, null, ruleType, address, priority, worksheet, null, namespaceManager) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ internal eExcelConditionalFormattingRuleType RuleType {
+ get => _ruleType;
+ set => _ruleType = value;
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ public eExcelConditionalFormattingValueObjectType Type {
+ get {
+ var typeAttribute = GetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._typeAttribute);
+
+ return ExcelConditionalFormattingValueObjectType.GetTypeByAttrbiute(typeAttribute);
+ }
+ set {
+ if ((_ruleType == eExcelConditionalFormattingRuleType.ThreeIconSet
+ || _ruleType == eExcelConditionalFormattingRuleType.FourIconSet
+ || _ruleType == eExcelConditionalFormattingRuleType.FiveIconSet)
+ && (value == eExcelConditionalFormattingValueObjectType.Min
+ || value == eExcelConditionalFormattingValueObjectType.Max)) {
+ throw (new ArgumentException("Value type can't be Min or Max for icon sets"));
+ }
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._typeAttribute,
+ value.ToString().ToLower(CultureInfo.InvariantCulture));
+ }
+ }
+
+ /// <summary>
+ /// Get/Set the 'cfvo' node @val attribute
+ /// </summary>
+ public Double Value {
+ get {
+ if ((Type == eExcelConditionalFormattingValueObjectType.Num)
+ || (Type == eExcelConditionalFormattingValueObjectType.Percent)
+ || (Type == eExcelConditionalFormattingValueObjectType.Percentile)) {
+ return GetXmlNodeDouble(ExcelConditionalFormattingConstants.Paths._valAttribute);
+ }
+ return 0;
+ }
+ set {
+ string valueToStore = string.Empty;
+
+ // Only some types use the @val attribute
+ if ((Type == eExcelConditionalFormattingValueObjectType.Num)
+ || (Type == eExcelConditionalFormattingValueObjectType.Percent)
+ || (Type == eExcelConditionalFormattingValueObjectType.Percentile)) {
+ valueToStore = value.ToString(CultureInfo.InvariantCulture);
+ }
+
+ SetXmlNodeString(ExcelConditionalFormattingConstants.Paths._valAttribute, valueToStore);
+ }
+ }
+
+ /// <summary>
+ /// Get/Set the Formula of the Object Value (uses the same attribute as the Value)
+ /// </summary>
+ public string Formula {
+ get {
+ // Return empty if the Object Value type is not Formula
+ if (Type != eExcelConditionalFormattingValueObjectType.Formula) {
+ return string.Empty;
+ }
+
+ // Excel stores the formula in the @val attribute
+ return GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._valAttribute);
+ }
+ set {
+ // Only store the formula if the Object Value type is Formula
+ if (Type == eExcelConditionalFormattingValueObjectType.Formula) {
+ SetXmlNodeString(ExcelConditionalFormattingConstants.Paths._valAttribute, value);
+ }
+ }
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingOperatorType.cs b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingOperatorType.cs
new file mode 100644
index 0000000..486613b
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingOperatorType.cs
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-17
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Functions related to the <see cref="ExcelConditionalFormattingOperatorType"/>
+/// </summary>
+internal static class ExcelConditionalFormattingOperatorType {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="type"></param>
+ /// <returns></returns>
+ internal static string GetAttributeByType(eExcelConditionalFormattingOperatorType type) {
+ switch (type) {
+ case eExcelConditionalFormattingOperatorType.BeginsWith:
+ return ExcelConditionalFormattingConstants.Operators._beginsWith;
+
+ case eExcelConditionalFormattingOperatorType.Between:
+ return ExcelConditionalFormattingConstants.Operators._between;
+
+ case eExcelConditionalFormattingOperatorType.ContainsText:
+ return ExcelConditionalFormattingConstants.Operators._containsText;
+
+ case eExcelConditionalFormattingOperatorType.EndsWith:
+ return ExcelConditionalFormattingConstants.Operators._endsWith;
+
+ case eExcelConditionalFormattingOperatorType.Equal:
+ return ExcelConditionalFormattingConstants.Operators._equal;
+
+ case eExcelConditionalFormattingOperatorType.GreaterThan:
+ return ExcelConditionalFormattingConstants.Operators._greaterThan;
+
+ case eExcelConditionalFormattingOperatorType.GreaterThanOrEqual:
+ return ExcelConditionalFormattingConstants.Operators._greaterThanOrEqual;
+
+ case eExcelConditionalFormattingOperatorType.LessThan:
+ return ExcelConditionalFormattingConstants.Operators._lessThan;
+
+ case eExcelConditionalFormattingOperatorType.LessThanOrEqual:
+ return ExcelConditionalFormattingConstants.Operators._lessThanOrEqual;
+
+ case eExcelConditionalFormattingOperatorType.NotBetween:
+ return ExcelConditionalFormattingConstants.Operators._notBetween;
+
+ case eExcelConditionalFormattingOperatorType.NotContains:
+ return ExcelConditionalFormattingConstants.Operators._notContains;
+
+ case eExcelConditionalFormattingOperatorType.NotEqual:
+ return ExcelConditionalFormattingConstants.Operators._notEqual;
+ }
+
+ return string.Empty;
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// param name="attribute"
+ /// <returns></returns>
+ internal static eExcelConditionalFormattingOperatorType GetTypeByAttribute(string attribute) {
+ switch (attribute) {
+ case ExcelConditionalFormattingConstants.Operators._beginsWith:
+ return eExcelConditionalFormattingOperatorType.BeginsWith;
+
+ case ExcelConditionalFormattingConstants.Operators._between:
+ return eExcelConditionalFormattingOperatorType.Between;
+
+ case ExcelConditionalFormattingConstants.Operators._containsText:
+ return eExcelConditionalFormattingOperatorType.ContainsText;
+
+ case ExcelConditionalFormattingConstants.Operators._endsWith:
+ return eExcelConditionalFormattingOperatorType.EndsWith;
+
+ case ExcelConditionalFormattingConstants.Operators._equal:
+ return eExcelConditionalFormattingOperatorType.Equal;
+
+ case ExcelConditionalFormattingConstants.Operators._greaterThan:
+ return eExcelConditionalFormattingOperatorType.GreaterThan;
+
+ case ExcelConditionalFormattingConstants.Operators._greaterThanOrEqual:
+ return eExcelConditionalFormattingOperatorType.GreaterThanOrEqual;
+
+ case ExcelConditionalFormattingConstants.Operators._lessThan:
+ return eExcelConditionalFormattingOperatorType.LessThan;
+
+ case ExcelConditionalFormattingConstants.Operators._lessThanOrEqual:
+ return eExcelConditionalFormattingOperatorType.LessThanOrEqual;
+
+ case ExcelConditionalFormattingConstants.Operators._notBetween:
+ return eExcelConditionalFormattingOperatorType.NotBetween;
+
+ case ExcelConditionalFormattingConstants.Operators._notContains:
+ return eExcelConditionalFormattingOperatorType.NotContains;
+
+ case ExcelConditionalFormattingConstants.Operators._notEqual:
+ return eExcelConditionalFormattingOperatorType.NotEqual;
+ }
+
+ throw new(ExcelConditionalFormattingConstants.Errors._unexistentOperatorTypeAttribute);
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingRuleFactory.cs b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingRuleFactory.cs
new file mode 100644
index 0000000..a0023df
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingRuleFactory.cs
@@ -0,0 +1,357 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting 2012-04-03
+ *******************************************************************************/
+
+using System;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Factory class for ExcelConditionalFormatting.
+/// </summary>
+internal static class ExcelConditionalFormattingRuleFactory {
+ public static ExcelConditionalFormattingRule Create(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode) {
+ ArgumentNullException.ThrowIfNull(address);
+ ArgumentOutOfRangeException.ThrowIfLessThan(priority, 1);
+ ArgumentNullException.ThrowIfNull(worksheet);
+
+ // According the conditional formatting rule type
+ switch (type) {
+ case eExcelConditionalFormattingRuleType.AboveAverage:
+ return new ExcelConditionalFormattingAboveAverage(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.AboveOrEqualAverage:
+ return new ExcelConditionalFormattingAboveOrEqualAverage(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.BelowAverage:
+ return new ExcelConditionalFormattingBelowAverage(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.BelowOrEqualAverage:
+ return new ExcelConditionalFormattingBelowOrEqualAverage(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.AboveStdDev:
+ return new ExcelConditionalFormattingAboveStdDev(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.BelowStdDev:
+ return new ExcelConditionalFormattingBelowStdDev(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.Bottom:
+ return new ExcelConditionalFormattingBottom(address, priority, worksheet, itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.BottomPercent:
+ return new ExcelConditionalFormattingBottomPercent(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.Top:
+ return new ExcelConditionalFormattingTop(address, priority, worksheet, itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.TopPercent:
+ return new ExcelConditionalFormattingTopPercent(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.Last7Days:
+ return new ExcelConditionalFormattingLast7Days(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.LastMonth:
+ return new ExcelConditionalFormattingLastMonth(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.LastWeek:
+ return new ExcelConditionalFormattingLastWeek(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.NextMonth:
+ return new ExcelConditionalFormattingNextMonth(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.NextWeek:
+ return new ExcelConditionalFormattingNextWeek(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.ThisMonth:
+ return new ExcelConditionalFormattingThisMonth(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.ThisWeek:
+ return new ExcelConditionalFormattingThisWeek(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.Today:
+ return new ExcelConditionalFormattingToday(address, priority, worksheet, itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.Tomorrow:
+ return new ExcelConditionalFormattingTomorrow(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.Yesterday:
+ return new ExcelConditionalFormattingYesterday(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.BeginsWith:
+ return new ExcelConditionalFormattingBeginsWith(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.Between:
+ return new ExcelConditionalFormattingBetween(address, priority, worksheet, itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.ContainsBlanks:
+ return new ExcelConditionalFormattingContainsBlanks(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.ContainsErrors:
+ return new ExcelConditionalFormattingContainsErrors(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.ContainsText:
+ return new ExcelConditionalFormattingContainsText(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.DuplicateValues:
+ return new ExcelConditionalFormattingDuplicateValues(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.EndsWith:
+ return new ExcelConditionalFormattingEndsWith(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.Equal:
+ return new ExcelConditionalFormattingEqual(address, priority, worksheet, itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.Expression:
+ return new ExcelConditionalFormattingExpression(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.GreaterThan:
+ return new ExcelConditionalFormattingGreaterThan(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.GreaterThanOrEqual:
+ return new ExcelConditionalFormattingGreaterThanOrEqual(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.LessThan:
+ return new ExcelConditionalFormattingLessThan(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.LessThanOrEqual:
+ return new ExcelConditionalFormattingLessThanOrEqual(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.NotBetween:
+ return new ExcelConditionalFormattingNotBetween(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.NotContainsBlanks:
+ return new ExcelConditionalFormattingNotContainsBlanks(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.NotContainsErrors:
+ return new ExcelConditionalFormattingNotContainsErrors(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.NotContainsText:
+ return new ExcelConditionalFormattingNotContainsText(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.NotEqual:
+ return new ExcelConditionalFormattingNotEqual(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.UniqueValues:
+ return new ExcelConditionalFormattingUniqueValues(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.ThreeColorScale:
+ return new ExcelConditionalFormattingThreeColorScale(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.TwoColorScale:
+ return new ExcelConditionalFormattingTwoColorScale(
+ address,
+ priority,
+ worksheet,
+ itemElementNode);
+ case eExcelConditionalFormattingRuleType.ThreeIconSet:
+ return new ExcelConditionalFormattingThreeIconSet(
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ null);
+ case eExcelConditionalFormattingRuleType.FourIconSet:
+ return new ExcelConditionalFormattingFourIconSet(
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ null);
+ case eExcelConditionalFormattingRuleType.FiveIconSet:
+ return new ExcelConditionalFormattingFiveIconSet(
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ null);
+ case eExcelConditionalFormattingRuleType.DataBar:
+ return new ExcelConditionalFormattingDataBar(
+ eExcelConditionalFormattingRuleType.DataBar,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ null);
+
+ //TODO: Add DataBar
+ }
+
+ throw new InvalidOperationException(
+ string.Format(
+ ExcelConditionalFormattingConstants.Errors._nonSupportedRuleType,
+ type.ToString()));
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingRuleType.cs b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingRuleType.cs
new file mode 100644
index 0000000..62f928d
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingRuleType.cs
@@ -0,0 +1,494 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Functions related to the ExcelConditionalFormattingRule
+/// </summary>
+internal static class ExcelConditionalFormattingRuleType {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="attribute"></param>
+ /// <param name="topNode"></param>
+ /// <param name="nameSpaceManager"></param>
+ /// <returns></returns>
+ internal static eExcelConditionalFormattingRuleType GetTypeByAttrbiute(
+ string attribute,
+ XmlNode topNode,
+ XmlNamespaceManager nameSpaceManager) {
+ switch (attribute) {
+ case ExcelConditionalFormattingConstants.RuleType._aboveAverage:
+ return GetAboveAverageType(topNode, nameSpaceManager);
+
+ case ExcelConditionalFormattingConstants.RuleType._top10:
+ return GetTop10Type(topNode, nameSpaceManager);
+
+ case ExcelConditionalFormattingConstants.RuleType._timePeriod:
+ return GetTimePeriodType(topNode, nameSpaceManager);
+ case ExcelConditionalFormattingConstants.RuleType._cellIs:
+ return GetCellIs((XmlElement)topNode);
+ case ExcelConditionalFormattingConstants.RuleType._beginsWith:
+ return eExcelConditionalFormattingRuleType.BeginsWith;
+
+ //case ExcelConditionalFormattingConstants.RuleType.Between:
+ // return eExcelConditionalFormattingRuleType.Between;
+
+ case ExcelConditionalFormattingConstants.RuleType._containsBlanks:
+ return eExcelConditionalFormattingRuleType.ContainsBlanks;
+
+ case ExcelConditionalFormattingConstants.RuleType._containsErrors:
+ return eExcelConditionalFormattingRuleType.ContainsErrors;
+
+ case ExcelConditionalFormattingConstants.RuleType._containsText:
+ return eExcelConditionalFormattingRuleType.ContainsText;
+
+ case ExcelConditionalFormattingConstants.RuleType._duplicateValues:
+ return eExcelConditionalFormattingRuleType.DuplicateValues;
+
+ case ExcelConditionalFormattingConstants.RuleType._endsWith:
+ return eExcelConditionalFormattingRuleType.EndsWith;
+
+ //case ExcelConditionalFormattingConstants.RuleType.Equal:
+ // return eExcelConditionalFormattingRuleType.Equal;
+
+ case ExcelConditionalFormattingConstants.RuleType._expression:
+ return eExcelConditionalFormattingRuleType.Expression;
+
+ //case ExcelConditionalFormattingConstants.RuleType.GreaterThan:
+ // return eExcelConditionalFormattingRuleType.GreaterThan;
+
+ //case ExcelConditionalFormattingConstants.RuleType.GreaterThanOrEqual:
+ // return eExcelConditionalFormattingRuleType.GreaterThanOrEqual;
+
+ //case ExcelConditionalFormattingConstants.RuleType.LessThan:
+ // return eExcelConditionalFormattingRuleType.LessThan;
+
+ //case ExcelConditionalFormattingConstants.RuleType.LessThanOrEqual:
+ // return eExcelConditionalFormattingRuleType.LessThanOrEqual;
+
+ //case ExcelConditionalFormattingConstants.RuleType.NotBetween:
+ // return eExcelConditionalFormattingRuleType.NotBetween;
+
+ case ExcelConditionalFormattingConstants.RuleType._notContainsBlanks:
+ return eExcelConditionalFormattingRuleType.NotContainsBlanks;
+
+ case ExcelConditionalFormattingConstants.RuleType._notContainsErrors:
+ return eExcelConditionalFormattingRuleType.NotContainsErrors;
+
+ case ExcelConditionalFormattingConstants.RuleType._notContainsText:
+ return eExcelConditionalFormattingRuleType.NotContainsText;
+
+ //case ExcelConditionalFormattingConstants.RuleType.NotEqual:
+ // return eExcelConditionalFormattingRuleType.NotEqual;
+
+ case ExcelConditionalFormattingConstants.RuleType._uniqueValues:
+ return eExcelConditionalFormattingRuleType.UniqueValues;
+
+ case ExcelConditionalFormattingConstants.RuleType._colorScale:
+ return GetColorScaleType(topNode, nameSpaceManager);
+ case ExcelConditionalFormattingConstants.RuleType._iconSet:
+ return GetIconSetType(topNode, nameSpaceManager);
+ case ExcelConditionalFormattingConstants.RuleType._dataBar:
+ return eExcelConditionalFormattingRuleType.DataBar;
+ }
+
+ throw new(ExcelConditionalFormattingConstants.Errors._unexpectedRuleTypeAttribute);
+ }
+
+ private static eExcelConditionalFormattingRuleType GetCellIs(XmlElement node) {
+ switch (node.GetAttribute("operator")) {
+ case ExcelConditionalFormattingConstants.Operators._beginsWith:
+ return eExcelConditionalFormattingRuleType.BeginsWith;
+ case ExcelConditionalFormattingConstants.Operators._between:
+ return eExcelConditionalFormattingRuleType.Between;
+
+ case ExcelConditionalFormattingConstants.Operators._containsText:
+ return eExcelConditionalFormattingRuleType.ContainsText;
+
+ case ExcelConditionalFormattingConstants.Operators._endsWith:
+ return eExcelConditionalFormattingRuleType.EndsWith;
+
+ case ExcelConditionalFormattingConstants.Operators._equal:
+ return eExcelConditionalFormattingRuleType.Equal;
+
+ case ExcelConditionalFormattingConstants.Operators._greaterThan:
+ return eExcelConditionalFormattingRuleType.GreaterThan;
+
+ case ExcelConditionalFormattingConstants.Operators._greaterThanOrEqual:
+ return eExcelConditionalFormattingRuleType.GreaterThanOrEqual;
+
+ case ExcelConditionalFormattingConstants.Operators._lessThan:
+ return eExcelConditionalFormattingRuleType.LessThan;
+
+ case ExcelConditionalFormattingConstants.Operators._lessThanOrEqual:
+ return eExcelConditionalFormattingRuleType.LessThanOrEqual;
+
+ case ExcelConditionalFormattingConstants.Operators._notBetween:
+ return eExcelConditionalFormattingRuleType.NotBetween;
+
+ case ExcelConditionalFormattingConstants.Operators._notContains:
+ return eExcelConditionalFormattingRuleType.NotContains;
+
+ case ExcelConditionalFormattingConstants.Operators._notEqual:
+ return eExcelConditionalFormattingRuleType.NotEqual;
+ default:
+ throw new(ExcelConditionalFormattingConstants.Errors._unexistentOperatorTypeAttribute);
+ }
+ }
+
+ private static eExcelConditionalFormattingRuleType GetIconSetType(
+ XmlNode topNode,
+ XmlNamespaceManager nameSpaceManager) {
+ var node = topNode.SelectSingleNode("d:iconSet/@iconSet", nameSpaceManager);
+ if (node == null) {
+ return eExcelConditionalFormattingRuleType.ThreeIconSet;
+ }
+ var v = node.Value;
+
+ if (v[0] == '3') {
+ return eExcelConditionalFormattingRuleType.ThreeIconSet;
+ }
+ if (v[0] == '4') {
+ return eExcelConditionalFormattingRuleType.FourIconSet;
+ }
+ return eExcelConditionalFormattingRuleType.FiveIconSet;
+ }
+
+ /// <summary>
+ /// Get the "colorScale" rule type according to the number of "cfvo" and "color" nodes.
+ /// If we have excatly 2 "cfvo" and "color" childs, then we return "twoColorScale"
+ /// </summary>
+ /// <returns>TwoColorScale or ThreeColorScale</returns>
+ internal static eExcelConditionalFormattingRuleType GetColorScaleType(
+ XmlNode topNode,
+ XmlNamespaceManager nameSpaceManager) {
+ // Get the <cfvo> nodes
+ var cfvoNodes = topNode.SelectNodes(
+ string.Format(
+ "{0}/{1}",
+ ExcelConditionalFormattingConstants.Paths._colorScale,
+ ExcelConditionalFormattingConstants.Paths._cfvo),
+ nameSpaceManager);
+
+ // Get the <color> nodes
+ var colorNodes = topNode.SelectNodes(
+ string.Format(
+ "{0}/{1}",
+ ExcelConditionalFormattingConstants.Paths._colorScale,
+ ExcelConditionalFormattingConstants.Paths._color),
+ nameSpaceManager);
+
+ // We determine if it is "TwoColorScale" or "ThreeColorScale" by the
+ // number of <cfvo> and <color> inside the <colorScale> node
+ if ((cfvoNodes == null)
+ || (cfvoNodes.Count < 2)
+ || (cfvoNodes.Count > 3)
+ || (colorNodes == null)
+ || (colorNodes.Count < 2)
+ || (colorNodes.Count > 3)
+ || (cfvoNodes.Count != colorNodes.Count)) {
+ throw new(ExcelConditionalFormattingConstants.Errors._wrongNumberCfvoColorNodes);
+ }
+
+ // Return the corresponding rule type (TwoColorScale or ThreeColorScale)
+ return (cfvoNodes.Count == 2)
+ ? eExcelConditionalFormattingRuleType.TwoColorScale
+ : eExcelConditionalFormattingRuleType.ThreeColorScale;
+ }
+
+ /// <summary>
+ /// Get the "aboveAverage" rule type according to the follwoing attributes:
+ /// "AboveAverage", "EqualAverage" and "StdDev".
+ ///
+ /// @StdDev greater than "0" == AboveStdDev
+ /// @StdDev less than "0" == BelowStdDev
+ /// @AboveAverage = "1"/null and @EqualAverage = "0"/null == AboveAverage
+ /// @AboveAverage = "1"/null and @EqualAverage = "1" == AboveOrEqualAverage
+ /// @AboveAverage = "0" and @EqualAverage = "0"/null == BelowAverage
+ /// @AboveAverage = "0" and @EqualAverage = "1" == BelowOrEqualAverage
+ /// /// </summary>
+ /// <returns>AboveAverage, AboveOrEqualAverage, BelowAverage or BelowOrEqualAverage</returns>
+ internal static eExcelConditionalFormattingRuleType GetAboveAverageType(
+ XmlNode topNode,
+ XmlNamespaceManager nameSpaceManager) {
+ // Get @StdDev attribute
+ int? stdDev = ExcelConditionalFormattingHelper.GetAttributeIntNullable(
+ topNode,
+ ExcelConditionalFormattingConstants.Attributes._stdDev);
+
+ if (stdDev > 0) {
+ // @StdDev > "0" --> AboveStdDev
+ return eExcelConditionalFormattingRuleType.AboveStdDev;
+ }
+
+ if (stdDev < 0) {
+ // @StdDev < "0" --> BelowStdDev
+ return eExcelConditionalFormattingRuleType.BelowStdDev;
+ }
+
+ // Get @AboveAverage attribute
+ bool? isAboveAverage = ExcelConditionalFormattingHelper.GetAttributeBoolNullable(
+ topNode,
+ ExcelConditionalFormattingConstants.Attributes._aboveAverage);
+
+ // Get @EqualAverage attribute
+ bool? isEqualAverage = ExcelConditionalFormattingHelper.GetAttributeBoolNullable(
+ topNode,
+ ExcelConditionalFormattingConstants.Attributes._equalAverage);
+
+ if ((isAboveAverage == null) || (isAboveAverage == true)) {
+ if (isEqualAverage == true) {
+ // @AboveAverage = "1"/null and @EqualAverage = "1" == AboveOrEqualAverage
+ return eExcelConditionalFormattingRuleType.AboveOrEqualAverage;
+ }
+
+ // @AboveAverage = "1"/null and @EqualAverage = "0"/null == AboveAverage
+ return eExcelConditionalFormattingRuleType.AboveAverage;
+ }
+
+ if (isEqualAverage == true) {
+ // @AboveAverage = "0" and @EqualAverage = "1" == BelowOrEqualAverage
+ return eExcelConditionalFormattingRuleType.BelowOrEqualAverage;
+ }
+
+ // @AboveAverage = "0" and @EqualAverage = "0"/null == BelowAverage
+ return eExcelConditionalFormattingRuleType.BelowAverage;
+ }
+
+ /// <summary>
+ /// Get the "top10" rule type according to the follwoing attributes:
+ /// "Bottom" and "Percent"
+ ///
+ /// @Bottom = "1" and @Percent = "0"/null == Bottom
+ /// @Bottom = "1" and @Percent = "1" == BottomPercent
+ /// @Bottom = "0"/null and @Percent = "0"/null == Top
+ /// @Bottom = "0"/null and @Percent = "1" == TopPercent
+ /// /// </summary>
+ /// <returns>Top, TopPercent, Bottom or BottomPercent</returns>
+ public static eExcelConditionalFormattingRuleType GetTop10Type(
+ XmlNode topNode,
+ XmlNamespaceManager nameSpaceManager) {
+ // Get @Bottom attribute
+ bool? isBottom = ExcelConditionalFormattingHelper.GetAttributeBoolNullable(
+ topNode,
+ ExcelConditionalFormattingConstants.Attributes._bottom);
+
+ // Get @Percent attribute
+ bool? isPercent = ExcelConditionalFormattingHelper.GetAttributeBoolNullable(
+ topNode,
+ ExcelConditionalFormattingConstants.Attributes._percent);
+
+ if (isBottom == true) {
+ if (isPercent == true) {
+ // @Bottom = "1" and @Percent = "1" == BottomPercent
+ return eExcelConditionalFormattingRuleType.BottomPercent;
+ }
+
+ // @Bottom = "1" and @Percent = "0"/null == Bottom
+ return eExcelConditionalFormattingRuleType.Bottom;
+ }
+
+ if (isPercent == true) {
+ // @Bottom = "0"/null and @Percent = "1" == TopPercent
+ return eExcelConditionalFormattingRuleType.TopPercent;
+ }
+
+ // @Bottom = "0"/null and @Percent = "0"/null == Top
+ return eExcelConditionalFormattingRuleType.Top;
+ }
+
+ /// <summary>
+ /// Get the "timePeriod" rule type according to "TimePeriod" attribute.
+ /// /// </summary>
+ /// <returns>Last7Days, LastMonth etc.</returns>
+ public static eExcelConditionalFormattingRuleType GetTimePeriodType(
+ XmlNode topNode,
+ XmlNamespaceManager nameSpaceManager) {
+ eExcelConditionalFormattingTimePeriodType timePeriod =
+ ExcelConditionalFormattingTimePeriodType.GetTypeByAttribute(
+ ExcelConditionalFormattingHelper.GetAttributeString(
+ topNode,
+ ExcelConditionalFormattingConstants.Attributes._timePeriod));
+
+ switch (timePeriod) {
+ case eExcelConditionalFormattingTimePeriodType.Last7Days:
+ return eExcelConditionalFormattingRuleType.Last7Days;
+
+ case eExcelConditionalFormattingTimePeriodType.LastMonth:
+ return eExcelConditionalFormattingRuleType.LastMonth;
+
+ case eExcelConditionalFormattingTimePeriodType.LastWeek:
+ return eExcelConditionalFormattingRuleType.LastWeek;
+
+ case eExcelConditionalFormattingTimePeriodType.NextMonth:
+ return eExcelConditionalFormattingRuleType.NextMonth;
+
+ case eExcelConditionalFormattingTimePeriodType.NextWeek:
+ return eExcelConditionalFormattingRuleType.NextWeek;
+
+ case eExcelConditionalFormattingTimePeriodType.ThisMonth:
+ return eExcelConditionalFormattingRuleType.ThisMonth;
+
+ case eExcelConditionalFormattingTimePeriodType.ThisWeek:
+ return eExcelConditionalFormattingRuleType.ThisWeek;
+
+ case eExcelConditionalFormattingTimePeriodType.Today:
+ return eExcelConditionalFormattingRuleType.Today;
+
+ case eExcelConditionalFormattingTimePeriodType.Tomorrow:
+ return eExcelConditionalFormattingRuleType.Tomorrow;
+
+ case eExcelConditionalFormattingTimePeriodType.Yesterday:
+ return eExcelConditionalFormattingRuleType.Yesterday;
+ }
+
+ throw new(ExcelConditionalFormattingConstants.Errors._unexistentTimePeriodTypeAttribute);
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="type"></param>
+ /// <returns></returns>
+ public static string GetAttributeByType(eExcelConditionalFormattingRuleType type) {
+ switch (type) {
+ case eExcelConditionalFormattingRuleType.AboveAverage:
+ case eExcelConditionalFormattingRuleType.AboveOrEqualAverage:
+ case eExcelConditionalFormattingRuleType.BelowAverage:
+ case eExcelConditionalFormattingRuleType.BelowOrEqualAverage:
+ case eExcelConditionalFormattingRuleType.AboveStdDev:
+ case eExcelConditionalFormattingRuleType.BelowStdDev:
+ return ExcelConditionalFormattingConstants.RuleType._aboveAverage;
+
+ case eExcelConditionalFormattingRuleType.Bottom:
+ case eExcelConditionalFormattingRuleType.BottomPercent:
+ case eExcelConditionalFormattingRuleType.Top:
+ case eExcelConditionalFormattingRuleType.TopPercent:
+ return ExcelConditionalFormattingConstants.RuleType._top10;
+
+ case eExcelConditionalFormattingRuleType.Last7Days:
+ case eExcelConditionalFormattingRuleType.LastMonth:
+ case eExcelConditionalFormattingRuleType.LastWeek:
+ case eExcelConditionalFormattingRuleType.NextMonth:
+ case eExcelConditionalFormattingRuleType.NextWeek:
+ case eExcelConditionalFormattingRuleType.ThisMonth:
+ case eExcelConditionalFormattingRuleType.ThisWeek:
+ case eExcelConditionalFormattingRuleType.Today:
+ case eExcelConditionalFormattingRuleType.Tomorrow:
+ case eExcelConditionalFormattingRuleType.Yesterday:
+ return ExcelConditionalFormattingConstants.RuleType._timePeriod;
+
+ case eExcelConditionalFormattingRuleType.Between:
+ case eExcelConditionalFormattingRuleType.Equal:
+ case eExcelConditionalFormattingRuleType.GreaterThan:
+ case eExcelConditionalFormattingRuleType.GreaterThanOrEqual:
+ case eExcelConditionalFormattingRuleType.LessThan:
+ case eExcelConditionalFormattingRuleType.LessThanOrEqual:
+ case eExcelConditionalFormattingRuleType.NotBetween:
+ case eExcelConditionalFormattingRuleType.NotEqual:
+ return ExcelConditionalFormattingConstants.RuleType._cellIs;
+
+ case eExcelConditionalFormattingRuleType.ThreeIconSet:
+ case eExcelConditionalFormattingRuleType.FourIconSet:
+ case eExcelConditionalFormattingRuleType.FiveIconSet:
+ return ExcelConditionalFormattingConstants.RuleType._iconSet;
+
+ case eExcelConditionalFormattingRuleType.ThreeColorScale:
+ case eExcelConditionalFormattingRuleType.TwoColorScale:
+ return ExcelConditionalFormattingConstants.RuleType._colorScale;
+
+ case eExcelConditionalFormattingRuleType.BeginsWith:
+ return ExcelConditionalFormattingConstants.RuleType._beginsWith;
+
+ case eExcelConditionalFormattingRuleType.ContainsBlanks:
+ return ExcelConditionalFormattingConstants.RuleType._containsBlanks;
+
+ case eExcelConditionalFormattingRuleType.ContainsErrors:
+ return ExcelConditionalFormattingConstants.RuleType._containsErrors;
+
+ case eExcelConditionalFormattingRuleType.ContainsText:
+ return ExcelConditionalFormattingConstants.RuleType._containsText;
+
+ case eExcelConditionalFormattingRuleType.DuplicateValues:
+ return ExcelConditionalFormattingConstants.RuleType._duplicateValues;
+
+ case eExcelConditionalFormattingRuleType.EndsWith:
+ return ExcelConditionalFormattingConstants.RuleType._endsWith;
+
+ case eExcelConditionalFormattingRuleType.Expression:
+ return ExcelConditionalFormattingConstants.RuleType._expression;
+
+ case eExcelConditionalFormattingRuleType.NotContainsBlanks:
+ return ExcelConditionalFormattingConstants.RuleType._notContainsBlanks;
+
+ case eExcelConditionalFormattingRuleType.NotContainsErrors:
+ return ExcelConditionalFormattingConstants.RuleType._notContainsErrors;
+
+ case eExcelConditionalFormattingRuleType.NotContainsText:
+ return ExcelConditionalFormattingConstants.RuleType._notContainsText;
+
+ case eExcelConditionalFormattingRuleType.UniqueValues:
+ return ExcelConditionalFormattingConstants.RuleType._uniqueValues;
+
+ case eExcelConditionalFormattingRuleType.DataBar:
+ return ExcelConditionalFormattingConstants.RuleType._dataBar;
+ }
+
+ throw new(ExcelConditionalFormattingConstants.Errors._missingRuleType);
+ }
+
+ /// <summary>
+ /// Return cfvo §18.3.1.11 parent according to the rule type
+ /// </summary>
+ /// <param name="type"></param>
+ /// <returns></returns>
+ public static string GetCfvoParentPathByType(eExcelConditionalFormattingRuleType type) {
+ switch (type) {
+ case eExcelConditionalFormattingRuleType.TwoColorScale:
+ case eExcelConditionalFormattingRuleType.ThreeColorScale:
+ return ExcelConditionalFormattingConstants.Paths._colorScale;
+
+ case eExcelConditionalFormattingRuleType.ThreeIconSet:
+ case eExcelConditionalFormattingRuleType.FourIconSet:
+ case eExcelConditionalFormattingRuleType.FiveIconSet:
+ return ExcelConditionalFormattingConstants.RuleType._iconSet;
+
+ case eExcelConditionalFormattingRuleType.DataBar:
+ return ExcelConditionalFormattingConstants.RuleType._dataBar;
+ }
+
+ throw new(ExcelConditionalFormattingConstants.Errors._missingRuleType);
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingTimePeriodType.cs b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingTimePeriodType.cs
new file mode 100644
index 0000000..3959e61
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingTimePeriodType.cs
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-17
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Functions related to the <see cref="ExcelConditionalFormattingTimePeriodType"/>
+/// </summary>
+internal static class ExcelConditionalFormattingTimePeriodType {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="type"></param>
+ /// <returns></returns>
+ public static string GetAttributeByType(eExcelConditionalFormattingTimePeriodType type) {
+ switch (type) {
+ case eExcelConditionalFormattingTimePeriodType.Last7Days:
+ return ExcelConditionalFormattingConstants.TimePeriods._last7Days;
+
+ case eExcelConditionalFormattingTimePeriodType.LastMonth:
+ return ExcelConditionalFormattingConstants.TimePeriods._lastMonth;
+
+ case eExcelConditionalFormattingTimePeriodType.LastWeek:
+ return ExcelConditionalFormattingConstants.TimePeriods._lastWeek;
+
+ case eExcelConditionalFormattingTimePeriodType.NextMonth:
+ return ExcelConditionalFormattingConstants.TimePeriods._nextMonth;
+
+ case eExcelConditionalFormattingTimePeriodType.NextWeek:
+ return ExcelConditionalFormattingConstants.TimePeriods._nextWeek;
+
+ case eExcelConditionalFormattingTimePeriodType.ThisMonth:
+ return ExcelConditionalFormattingConstants.TimePeriods._thisMonth;
+
+ case eExcelConditionalFormattingTimePeriodType.ThisWeek:
+ return ExcelConditionalFormattingConstants.TimePeriods._thisWeek;
+
+ case eExcelConditionalFormattingTimePeriodType.Today:
+ return ExcelConditionalFormattingConstants.TimePeriods._today;
+
+ case eExcelConditionalFormattingTimePeriodType.Tomorrow:
+ return ExcelConditionalFormattingConstants.TimePeriods._tomorrow;
+
+ case eExcelConditionalFormattingTimePeriodType.Yesterday:
+ return ExcelConditionalFormattingConstants.TimePeriods._yesterday;
+ }
+
+ return string.Empty;
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="attribute"></param>
+ /// <returns></returns>
+ public static eExcelConditionalFormattingTimePeriodType GetTypeByAttribute(string attribute) {
+ switch (attribute) {
+ case ExcelConditionalFormattingConstants.TimePeriods._last7Days:
+ return eExcelConditionalFormattingTimePeriodType.Last7Days;
+
+ case ExcelConditionalFormattingConstants.TimePeriods._lastMonth:
+ return eExcelConditionalFormattingTimePeriodType.LastMonth;
+
+ case ExcelConditionalFormattingConstants.TimePeriods._lastWeek:
+ return eExcelConditionalFormattingTimePeriodType.LastWeek;
+
+ case ExcelConditionalFormattingConstants.TimePeriods._nextMonth:
+ return eExcelConditionalFormattingTimePeriodType.NextMonth;
+
+ case ExcelConditionalFormattingConstants.TimePeriods._nextWeek:
+ return eExcelConditionalFormattingTimePeriodType.NextWeek;
+
+ case ExcelConditionalFormattingConstants.TimePeriods._thisMonth:
+ return eExcelConditionalFormattingTimePeriodType.ThisMonth;
+
+ case ExcelConditionalFormattingConstants.TimePeriods._thisWeek:
+ return eExcelConditionalFormattingTimePeriodType.ThisWeek;
+
+ case ExcelConditionalFormattingConstants.TimePeriods._today:
+ return eExcelConditionalFormattingTimePeriodType.Today;
+
+ case ExcelConditionalFormattingConstants.TimePeriods._tomorrow:
+ return eExcelConditionalFormattingTimePeriodType.Tomorrow;
+
+ case ExcelConditionalFormattingConstants.TimePeriods._yesterday:
+ return eExcelConditionalFormattingTimePeriodType.Yesterday;
+ }
+
+ throw new(ExcelConditionalFormattingConstants.Errors._unexistentTimePeriodTypeAttribute);
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingValueObjectType.cs b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingValueObjectType.cs
new file mode 100644
index 0000000..221ec89
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/ExcelConditionalFormattingValueObjectType.cs
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting Adaption 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Functions related to the <see cref="ExcelConditionalFormattingColorScaleValue"/>
+/// </summary>
+internal static class ExcelConditionalFormattingValueObjectType {
+ /// <summary>
+ /// Get the sequencial order of a cfvo/color by its position.
+ /// </summary>
+ /// <param name="position"></param>
+ /// <param name="ruleType"></param>
+ /// <returns>1, 2 or 3</returns>
+ internal static int GetOrderByPosition(
+ eExcelConditionalFormattingValueObjectPosition position,
+ eExcelConditionalFormattingRuleType ruleType) {
+ switch (position) {
+ case eExcelConditionalFormattingValueObjectPosition.Low:
+ return 1;
+
+ case eExcelConditionalFormattingValueObjectPosition.Middle:
+ return 2;
+
+ case eExcelConditionalFormattingValueObjectPosition.High:
+ // Check if the rule type is TwoColorScale.
+ if (ruleType == eExcelConditionalFormattingRuleType.TwoColorScale) {
+ // There are only "Low" and "High". So "High" is the second
+ return 2;
+ }
+
+ // There are "Low", "Middle" and "High". So "High" is the third
+ return 3;
+ }
+
+ return 0;
+ }
+
+ /// <summary>
+ /// Get the CFVO type by its @type attribute
+ /// </summary>
+ /// <param name="attribute"></param>
+ /// <returns></returns>
+ public static eExcelConditionalFormattingValueObjectType GetTypeByAttrbiute(string attribute) {
+ switch (attribute) {
+ case ExcelConditionalFormattingConstants.CfvoType._min:
+ return eExcelConditionalFormattingValueObjectType.Min;
+
+ case ExcelConditionalFormattingConstants.CfvoType._max:
+ return eExcelConditionalFormattingValueObjectType.Max;
+
+ case ExcelConditionalFormattingConstants.CfvoType._num:
+ return eExcelConditionalFormattingValueObjectType.Num;
+
+ case ExcelConditionalFormattingConstants.CfvoType._formula:
+ return eExcelConditionalFormattingValueObjectType.Formula;
+
+ case ExcelConditionalFormattingConstants.CfvoType._percent:
+ return eExcelConditionalFormattingValueObjectType.Percent;
+
+ case ExcelConditionalFormattingConstants.CfvoType._percentile:
+ return eExcelConditionalFormattingValueObjectType.Percentile;
+ }
+
+ throw new(ExcelConditionalFormattingConstants.Errors._unexistentCfvoTypeAttribute);
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="position"></param>
+ ///<param name="ruleType"></param>
+ /// <param name="topNode"></param>
+ /// <param name="nameSpaceManager"></param>
+ /// <returns></returns>
+ public static XmlNode GetCfvoNodeByPosition(
+ eExcelConditionalFormattingValueObjectPosition position,
+ eExcelConditionalFormattingRuleType ruleType,
+ XmlNode topNode,
+ XmlNamespaceManager nameSpaceManager) {
+ // Get the corresponding <cfvo> node (by the position)
+ var node = topNode.SelectSingleNode(
+ string.Format(
+ "{0}[position()={1}]",
+ // {0}
+ ExcelConditionalFormattingConstants.Paths._cfvo,
+ // {1}
+ GetOrderByPosition(position, ruleType)),
+ nameSpaceManager);
+
+ if (node == null) {
+ throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoNode);
+ }
+
+ return node;
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="type"></param>
+ /// <returns></returns>
+ public static string GetAttributeByType(eExcelConditionalFormattingValueObjectType type) {
+ switch (type) {
+ case eExcelConditionalFormattingValueObjectType.Min:
+ return ExcelConditionalFormattingConstants.CfvoType._min;
+
+ case eExcelConditionalFormattingValueObjectType.Max:
+ return ExcelConditionalFormattingConstants.CfvoType._max;
+
+ case eExcelConditionalFormattingValueObjectType.Num:
+ return ExcelConditionalFormattingConstants.CfvoType._num;
+
+ case eExcelConditionalFormattingValueObjectType.Formula:
+ return ExcelConditionalFormattingConstants.CfvoType._formula;
+
+ case eExcelConditionalFormattingValueObjectType.Percent:
+ return ExcelConditionalFormattingConstants.CfvoType._percent;
+
+ case eExcelConditionalFormattingValueObjectType.Percentile:
+ return ExcelConditionalFormattingConstants.CfvoType._percentile;
+ }
+
+ return string.Empty;
+ }
+
+ /// <summary>
+ /// Get the cfvo (§18.3.1.11) node parent by the rule type. Can be any of the following:
+ /// "colorScale" (§18.3.1.16); "dataBar" (§18.3.1.28); "iconSet" (§18.3.1.49)
+ /// </summary>
+ /// <param name="ruleType"></param>
+ /// <returns></returns>
+ public static string GetParentPathByRuleType(eExcelConditionalFormattingRuleType ruleType) {
+ switch (ruleType) {
+ case eExcelConditionalFormattingRuleType.TwoColorScale:
+ case eExcelConditionalFormattingRuleType.ThreeColorScale:
+ return ExcelConditionalFormattingConstants.Paths._colorScale;
+
+ case eExcelConditionalFormattingRuleType.ThreeIconSet:
+ case eExcelConditionalFormattingRuleType.FourIconSet:
+ case eExcelConditionalFormattingRuleType.FiveIconSet:
+ return ExcelConditionalFormattingConstants.Paths._iconSet;
+
+ case eExcelConditionalFormattingRuleType.DataBar:
+ return ExcelConditionalFormattingConstants.Paths._dataBar;
+ }
+
+ return string.Empty;
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="nodeType"></param>
+ /// <returns></returns>
+ public static string GetNodePathByNodeType(
+ eExcelConditionalFormattingValueObjectNodeType nodeType) {
+ switch (nodeType) {
+ case eExcelConditionalFormattingValueObjectNodeType.Cfvo:
+ return ExcelConditionalFormattingConstants.Paths._cfvo;
+
+ case eExcelConditionalFormattingValueObjectNodeType.Color:
+ return ExcelConditionalFormattingConstants.Paths._color;
+ }
+
+ return string.Empty;
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/RangeConditionalFormatting.cs b/AppsheetEpplus/ConditionalFormatting/RangeConditionalFormatting.cs
new file mode 100644
index 0000000..3cb66b5
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/RangeConditionalFormatting.cs
@@ -0,0 +1,379 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Conditional Formatting 2012-04-03
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+internal class RangeConditionalFormatting : IRangeConditionalFormatting {
+ public ExcelWorksheet _worksheet;
+ public ExcelAddress _address;
+
+ public RangeConditionalFormatting(ExcelWorksheet worksheet, ExcelAddress address) {
+ ArgumentNullException.ThrowIfNull(worksheet);
+ ArgumentNullException.ThrowIfNull(address);
+
+ _worksheet = worksheet;
+ _address = address;
+ }
+
+ /// <summary>
+ /// Add AboveOrEqualAverage Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingAverageGroup AddAboveAverage() {
+ return _worksheet.ConditionalFormatting.AddAboveAverage(_address);
+ }
+
+ /// <summary>
+ /// Add AboveOrEqualAverage Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingAverageGroup AddAboveOrEqualAverage() {
+ return _worksheet.ConditionalFormatting.AddAboveOrEqualAverage(_address);
+ }
+
+ /// <summary>
+ /// Add BelowOrEqualAverage Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingAverageGroup AddBelowAverage() {
+ return _worksheet.ConditionalFormatting.AddBelowAverage(_address);
+ }
+
+ /// <summary>
+ /// Add BelowOrEqualAverage Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingAverageGroup AddBelowOrEqualAverage() {
+ return _worksheet.ConditionalFormatting.AddBelowOrEqualAverage(_address);
+ }
+
+ /// <summary>
+ /// Add AboveStdDev Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingStdDevGroup AddAboveStdDev() {
+ return _worksheet.ConditionalFormatting.AddAboveStdDev(_address);
+ }
+
+ /// <summary>
+ /// Add BelowStdDev Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingStdDevGroup AddBelowStdDev() {
+ return _worksheet.ConditionalFormatting.AddBelowStdDev(_address);
+ }
+
+ /// <summary>
+ /// Add Bottom Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTopBottomGroup AddBottom() {
+ return _worksheet.ConditionalFormatting.AddBottom(_address);
+ }
+
+ /// <summary>
+ /// Add BottomPercent Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTopBottomGroup AddBottomPercent() {
+ return _worksheet.ConditionalFormatting.AddBottomPercent(_address);
+ }
+
+ /// <summary>
+ /// Add Top Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTopBottomGroup AddTop() {
+ return _worksheet.ConditionalFormatting.AddTop(_address);
+ }
+
+ /// <summary>
+ /// Add TopPercent Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTopBottomGroup AddTopPercent() {
+ return _worksheet.ConditionalFormatting.AddTopPercent(_address);
+ }
+
+ /// <summary>
+ /// Add Last7Days Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddLast7Days() {
+ return _worksheet.ConditionalFormatting.AddLast7Days(_address);
+ }
+
+ /// <summary>
+ /// Add LastMonth Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddLastMonth() {
+ return _worksheet.ConditionalFormatting.AddLastMonth(_address);
+ }
+
+ /// <summary>
+ /// Add LastWeek Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddLastWeek() {
+ return _worksheet.ConditionalFormatting.AddLastWeek(_address);
+ }
+
+ /// <summary>
+ /// Add NextMonth Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddNextMonth() {
+ return _worksheet.ConditionalFormatting.AddNextMonth(_address);
+ }
+
+ /// <summary>
+ /// Add NextWeek Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddNextWeek() {
+ return _worksheet.ConditionalFormatting.AddNextWeek(_address);
+ }
+
+ /// <summary>
+ /// Add ThisMonth Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddThisMonth() {
+ return _worksheet.ConditionalFormatting.AddThisMonth(_address);
+ }
+
+ /// <summary>
+ /// Add ThisWeek Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddThisWeek() {
+ return _worksheet.ConditionalFormatting.AddThisWeek(_address);
+ }
+
+ /// <summary>
+ /// Add Today Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddToday() {
+ return _worksheet.ConditionalFormatting.AddToday(_address);
+ }
+
+ /// <summary>
+ /// Add Tomorrow Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddTomorrow() {
+ return _worksheet.ConditionalFormatting.AddTomorrow(_address);
+ }
+
+ /// <summary>
+ /// Add Yesterday Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddYesterday() {
+ return _worksheet.ConditionalFormatting.AddYesterday(_address);
+ }
+
+ /// <summary>
+ /// Add BeginsWith Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingBeginsWith AddBeginsWith() {
+ return _worksheet.ConditionalFormatting.AddBeginsWith(_address);
+ }
+
+ /// <summary>
+ /// Add Between Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingBetween AddBetween() {
+ return _worksheet.ConditionalFormatting.AddBetween(_address);
+ }
+
+ /// <summary>
+ /// Add ContainsBlanks Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingContainsBlanks AddContainsBlanks() {
+ return _worksheet.ConditionalFormatting.AddContainsBlanks(_address);
+ }
+
+ /// <summary>
+ /// Add ContainsErrors Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingContainsErrors AddContainsErrors() {
+ return _worksheet.ConditionalFormatting.AddContainsErrors(_address);
+ }
+
+ /// <summary>
+ /// Add ContainsText Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingContainsText AddContainsText() {
+ return _worksheet.ConditionalFormatting.AddContainsText(_address);
+ }
+
+ /// <summary>
+ /// Add DuplicateValues Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingDuplicateValues AddDuplicateValues() {
+ return _worksheet.ConditionalFormatting.AddDuplicateValues(_address);
+ }
+
+ /// <summary>
+ /// Add EndsWith Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingEndsWith AddEndsWith() {
+ return _worksheet.ConditionalFormatting.AddEndsWith(_address);
+ }
+
+ /// <summary>
+ /// Add Equal Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingEqual AddEqual() {
+ return _worksheet.ConditionalFormatting.AddEqual(_address);
+ }
+
+ /// <summary>
+ /// Add Expression Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingExpression AddExpression() {
+ return _worksheet.ConditionalFormatting.AddExpression(_address);
+ }
+
+ /// <summary>
+ /// Add GreaterThan Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingGreaterThan AddGreaterThan() {
+ return _worksheet.ConditionalFormatting.AddGreaterThan(_address);
+ }
+
+ /// <summary>
+ /// Add GreaterThanOrEqual Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingGreaterThanOrEqual AddGreaterThanOrEqual() {
+ return _worksheet.ConditionalFormatting.AddGreaterThanOrEqual(_address);
+ }
+
+ /// <summary>
+ /// Add LessThan Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingLessThan AddLessThan() {
+ return _worksheet.ConditionalFormatting.AddLessThan(_address);
+ }
+
+ /// <summary>
+ /// Add LessThanOrEqual Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingLessThanOrEqual AddLessThanOrEqual() {
+ return _worksheet.ConditionalFormatting.AddLessThanOrEqual(_address);
+ }
+
+ /// <summary>
+ /// Add NotBetween Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingNotBetween AddNotBetween() {
+ return _worksheet.ConditionalFormatting.AddNotBetween(_address);
+ }
+
+ /// <summary>
+ /// Add NotContainsBlanks Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingNotContainsBlanks AddNotContainsBlanks() {
+ return _worksheet.ConditionalFormatting.AddNotContainsBlanks(_address);
+ }
+
+ /// <summary>
+ /// Add NotContainsErrors Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingNotContainsErrors AddNotContainsErrors() {
+ return _worksheet.ConditionalFormatting.AddNotContainsErrors(_address);
+ }
+
+ /// <summary>
+ /// Add NotContainsText Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingNotContainsText AddNotContainsText() {
+ return _worksheet.ConditionalFormatting.AddNotContainsText(_address);
+ }
+
+ /// <summary>
+ /// Add NotEqual Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingNotEqual AddNotEqual() {
+ return _worksheet.ConditionalFormatting.AddNotEqual(_address);
+ }
+
+ /// <summary>
+ /// Add UniqueValues Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingUniqueValues AddUniqueValues() {
+ return _worksheet.ConditionalFormatting.AddUniqueValues(_address);
+ }
+
+ /// <summary>
+ /// Add ThreeColorScale Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingThreeColorScale AddThreeColorScale() {
+ return (IExcelConditionalFormattingThreeColorScale)(_worksheet.ConditionalFormatting.AddRule(
+ eExcelConditionalFormattingRuleType.ThreeColorScale,
+ _address));
+ }
+
+ /// <summary>
+ /// Add TwoColorScale Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTwoColorScale AddTwoColorScale() {
+ return (IExcelConditionalFormattingTwoColorScale)(_worksheet.ConditionalFormatting.AddRule(
+ eExcelConditionalFormattingRuleType.TwoColorScale,
+ _address));
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveAverage.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveAverage.cs
new file mode 100644
index 0000000..2ab1df8
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveAverage.cs
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingAboveAverage
+/// </summary>
+public class ExcelConditionalFormattingAboveAverage : ExcelConditionalFormattingAverageGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingAboveAverage(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.AboveAverage,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ AboveAverage = true;
+ EqualAverage = false;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingAboveAverage(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingAboveAverage(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveOrEqualAverage.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveOrEqualAverage.cs
new file mode 100644
index 0000000..d8e97db
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveOrEqualAverage.cs
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingAboveOrEqualAverage
+/// </summary>
+public class ExcelConditionalFormattingAboveOrEqualAverage
+ : ExcelConditionalFormattingAverageGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingAboveOrEqualAverage(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.AboveOrEqualAverage,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ AboveAverage = true;
+ EqualAverage = true;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingAboveOrEqualAverage(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingAboveOrEqualAverage(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveStdDev.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveStdDev.cs
new file mode 100644
index 0000000..fe944f7
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveStdDev.cs
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingAboveStdDev
+/// </summary>
+public class ExcelConditionalFormattingAboveStdDev
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingStdDevGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingAboveStdDev(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.AboveStdDev,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ AboveAverage = true;
+ StdDev = 1;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingAboveStdDev(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingAboveStdDev(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingAverageGroup.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingAverageGroup.cs
new file mode 100644
index 0000000..325ea97
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingAverageGroup.cs
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingAverageGroup
+/// </summary>
+public class ExcelConditionalFormattingAverageGroup
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingAverageGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="type"></param>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingAverageGroup(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ type,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ ///<param name="type"></param>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingAverageGroup(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(type, address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ ///<param name="type"></param>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingAverageGroup(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(type, address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBeginsWith.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBeginsWith.cs
new file mode 100644
index 0000000..12e10eb
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBeginsWith.cs
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingBeginsWith
+/// </summary>
+public class ExcelConditionalFormattingBeginsWith
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingBeginsWith {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingBeginsWith(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.BeginsWith,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Operator = eExcelConditionalFormattingOperatorType.BeginsWith;
+ Text = string.Empty;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingBeginsWith(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingBeginsWith(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+
+ /// <summary>
+ /// The text to search in the beginning of the cell
+ /// </summary>
+ public string Text {
+ get => GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute);
+ set {
+ SetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute, value);
+
+ Formula = string.Format(
+ "LEFT({0},LEN(\"{1}\"))=\"{1}\"",
+ Address.Start.Address,
+ value.Replace("\"", "\"\""));
+ }
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowAverage.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowAverage.cs
new file mode 100644
index 0000000..83fc5d5
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowAverage.cs
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingBelowAverage
+/// </summary>
+public class ExcelConditionalFormattingBelowAverage : ExcelConditionalFormattingAverageGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingBelowAverage(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.BelowAverage,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ AboveAverage = false;
+ EqualAverage = false;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingBelowAverage(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingBelowAverage(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowOrEqualAverage.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowOrEqualAverage.cs
new file mode 100644
index 0000000..6f8e527
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowOrEqualAverage.cs
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingBelowOrEqualAverage
+/// </summary>
+public class ExcelConditionalFormattingBelowOrEqualAverage
+ : ExcelConditionalFormattingAverageGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingBelowOrEqualAverage(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.BelowOrEqualAverage,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ AboveAverage = false;
+ EqualAverage = true;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingBelowOrEqualAverage(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingBelowOrEqualAverage(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowStdDev.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowStdDev.cs
new file mode 100644
index 0000000..7842e62
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowStdDev.cs
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingBelowStdDev
+/// </summary>
+public class ExcelConditionalFormattingBelowStdDev
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingStdDevGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingBelowStdDev(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.BelowStdDev,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ AboveAverage = false;
+ StdDev = 1;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingBelowStdDev(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingBelowStdDev(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBetween.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBetween.cs
new file mode 100644
index 0000000..ecb6a29
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBetween.cs
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingBetween
+/// </summary>
+public class ExcelConditionalFormattingBetween
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingBetween {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingBetween(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.Between,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Operator = eExcelConditionalFormattingOperatorType.Between;
+ Formula = string.Empty;
+ Formula2 = string.Empty;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingBetween(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingBetween(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottom.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottom.cs
new file mode 100644
index 0000000..41156e1
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottom.cs
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingBottom
+/// </summary>
+public class ExcelConditionalFormattingBottom
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingTopBottomGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingBottom(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.Bottom,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Bottom = true;
+ Percent = false;
+ Rank = 10; // Last 10 values
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingBottom(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingBottom(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottomPercent.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottomPercent.cs
new file mode 100644
index 0000000..9f3fe2a
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottomPercent.cs
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingBottomPercent
+/// </summary>
+public class ExcelConditionalFormattingBottomPercent
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingTopBottomGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingBottomPercent(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.BottomPercent,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Bottom = true;
+ Percent = true;
+ Rank = 10; // Last 10 percent
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingBottomPercent(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingBottomPercent(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsBlanks.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsBlanks.cs
new file mode 100644
index 0000000..86c74f4
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsBlanks.cs
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingContainsBlanks
+/// </summary>
+public class ExcelConditionalFormattingContainsBlanks
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingContainsBlanks {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingContainsBlanks(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.ContainsBlanks,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Formula = string.Format("LEN(TRIM({0}))=0", Address.Start.Address);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingContainsBlanks(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingContainsBlanks(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsErrors.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsErrors.cs
new file mode 100644
index 0000000..a3c7287
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsErrors.cs
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingContainsErrors
+/// </summary>
+public class ExcelConditionalFormattingContainsErrors
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingContainsErrors {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingContainsErrors(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.ContainsErrors,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Formula = string.Format("ISERROR({0})", Address.Start.Address);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingContainsErrors(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingContainsErrors(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsText.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsText.cs
new file mode 100644
index 0000000..80f0d0a
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsText.cs
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingContainsText
+/// </summary>
+public class ExcelConditionalFormattingContainsText
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingContainsText {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingContainsText(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.ContainsText,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Operator = eExcelConditionalFormattingOperatorType.ContainsText;
+ Text = string.Empty;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingContainsText(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingContainsText(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+
+ /// <summary>
+ /// The text to search inside the cell
+ /// </summary>
+ public string Text {
+ get => GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute);
+ set {
+ SetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute, value);
+
+ Formula = string.Format(
+ "NOT(ISERROR(SEARCH(\"{1}\",{0})))",
+ Address.Start.Address,
+ value.Replace("\"", "\"\""));
+ }
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingDataBar.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingDataBar.cs
new file mode 100644
index 0000000..fc9aca6
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingDataBar.cs
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Collections.Immutable;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Databar
+/// </summary>
+public class ExcelConditionalFormattingDataBar
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingDataBarGroup {
+ protected override ImmutableArray<string> SchemaNodeOrder { get; } = ["cfvo", "color"];
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="type"></param>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingDataBar(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ type,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ //Create the <dataBar> node inside the <cfRule> node
+ if (itemElementNode != null && itemElementNode.HasChildNodes) {
+ bool high = false;
+ foreach (XmlNode node in itemElementNode.SelectNodes("d:dataBar/d:cfvo", NameSpaceManager)) {
+ if (high == false) {
+ LowValue = new(type, address, worksheet, node, namespaceManager);
+ high = true;
+ } else {
+ HighValue = new(type, address, worksheet, node, namespaceManager);
+ }
+ }
+ } else {
+ var iconSetNode = CreateComplexNode(Node, ExcelConditionalFormattingConstants.Paths._dataBar);
+
+ var lowNode = iconSetNode.OwnerDocument.CreateElement(
+ ExcelConditionalFormattingConstants.Paths._cfvo,
+ ExcelPackage._schemaMain);
+ iconSetNode.AppendChild(lowNode);
+ LowValue = new(
+ eExcelConditionalFormattingValueObjectType.Min,
+ 0,
+ "",
+ eExcelConditionalFormattingRuleType.DataBar,
+ address,
+ priority,
+ worksheet,
+ lowNode,
+ namespaceManager);
+
+ var highNode = iconSetNode.OwnerDocument.CreateElement(
+ ExcelConditionalFormattingConstants.Paths._cfvo,
+ ExcelPackage._schemaMain);
+ iconSetNode.AppendChild(highNode);
+ HighValue = new(
+ eExcelConditionalFormattingValueObjectType.Max,
+ 0,
+ "",
+ eExcelConditionalFormattingRuleType.DataBar,
+ address,
+ priority,
+ worksheet,
+ highNode,
+ namespaceManager);
+ }
+ Type = type;
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="type"></param>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingDataBar(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(type, address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="type"></param>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingDataBar(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(type, address, priority, worksheet, null, null) {}
+
+ private const string _showValuePath = "d:dataBar/@showValue";
+
+ public bool ShowValue {
+ get => GetXmlNodeBool(_showValuePath, true);
+ set => SetXmlNodeBool(_showValuePath, value);
+ }
+
+ public ExcelConditionalFormattingIconDataBarValue LowValue { get; internal set; }
+
+ public ExcelConditionalFormattingIconDataBarValue HighValue { get; internal set; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingDuplicateValues.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingDuplicateValues.cs
new file mode 100644
index 0000000..b73f3a7
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingDuplicateValues.cs
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingDuplicateValues
+/// </summary>
+public class ExcelConditionalFormattingDuplicateValues
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingDuplicateValues {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingDuplicateValues(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.DuplicateValues,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingDuplicateValues(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingDuplicateValues(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingEndsWith.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingEndsWith.cs
new file mode 100644
index 0000000..97ea0df
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingEndsWith.cs
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingEndsWith
+/// </summary>
+public class ExcelConditionalFormattingEndsWith
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingEndsWith {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingEndsWith(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.EndsWith,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Operator = eExcelConditionalFormattingOperatorType.EndsWith;
+ Text = string.Empty;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingEndsWith(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingEndsWith(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+
+ /// <summary>
+ /// The text to search in the end of the cell
+ /// </summary>
+ public string Text {
+ get => GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute);
+ set {
+ SetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute, value);
+
+ Formula = string.Format(
+ "RIGHT({0},LEN(\"{1}\"))=\"{1}\"",
+ Address.Start.Address,
+ value.Replace("\"", "\"\""));
+ }
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingEqual.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingEqual.cs
new file mode 100644
index 0000000..7e757da
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingEqual.cs
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingEqual
+/// </summary>
+public class ExcelConditionalFormattingEqual
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingEqual {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingEqual(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.Equal,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Operator = eExcelConditionalFormattingOperatorType.Equal;
+ Formula = string.Empty;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingEqual(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingEqual(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingExpression.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingExpression.cs
new file mode 100644
index 0000000..7418688
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingExpression.cs
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingExpression
+/// </summary>
+public class ExcelConditionalFormattingExpression
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingExpression {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingExpression(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.Expression,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Formula = string.Empty;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingExpression(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingExpression(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingFiveIconSet.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingFiveIconSet.cs
new file mode 100644
index 0000000..62bdb02
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingFiveIconSet.cs
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingThreeIconSet
+/// </summary>
+public class ExcelConditionalFormattingFiveIconSet
+ : ExcelConditionalFormattingIconSetBase<eExcelconditionalFormatting5IconsSetType>,
+ IExcelConditionalFormattingFiveIconSet {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingFiveIconSet(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.FiveIconSet,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode != null && itemElementNode.HasChildNodes) {
+ XmlNode iconNode4 = TopNode.SelectSingleNode(
+ "d:iconSet/d:cfvo[position()=4]",
+ NameSpaceManager);
+ Icon4 = new(
+ eExcelConditionalFormattingRuleType.FiveIconSet,
+ address,
+ worksheet,
+ iconNode4,
+ namespaceManager);
+
+ XmlNode iconNode5 = TopNode.SelectSingleNode(
+ "d:iconSet/d:cfvo[position()=5]",
+ NameSpaceManager);
+ Icon5 = new(
+ eExcelConditionalFormattingRuleType.FiveIconSet,
+ address,
+ worksheet,
+ iconNode5,
+ namespaceManager);
+ } else {
+ XmlNode iconSetNode = TopNode.SelectSingleNode("d:iconSet", NameSpaceManager);
+ var iconNode4 = iconSetNode.OwnerDocument.CreateElement(
+ ExcelConditionalFormattingConstants.Paths._cfvo,
+ ExcelPackage._schemaMain);
+ iconSetNode.AppendChild(iconNode4);
+
+ Icon4 = new(
+ eExcelConditionalFormattingValueObjectType.Percent,
+ 60,
+ "",
+ eExcelConditionalFormattingRuleType.ThreeIconSet,
+ address,
+ priority,
+ worksheet,
+ iconNode4,
+ namespaceManager);
+
+ var iconNode5 = iconSetNode.OwnerDocument.CreateElement(
+ ExcelConditionalFormattingConstants.Paths._cfvo,
+ ExcelPackage._schemaMain);
+ iconSetNode.AppendChild(iconNode5);
+
+ Icon5 = new(
+ eExcelConditionalFormattingValueObjectType.Percent,
+ 80,
+ "",
+ eExcelConditionalFormattingRuleType.ThreeIconSet,
+ address,
+ priority,
+ worksheet,
+ iconNode5,
+ namespaceManager);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingFiveIconSet(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingFiveIconSet(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+
+ public ExcelConditionalFormattingIconDataBarValue Icon5 { get; internal set; }
+
+ public ExcelConditionalFormattingIconDataBarValue Icon4 { get; internal set; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingFourIconSet.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingFourIconSet.cs
new file mode 100644
index 0000000..f65f105
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingFourIconSet.cs
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingThreeIconSet
+/// </summary>
+public class ExcelConditionalFormattingFourIconSet
+ : ExcelConditionalFormattingIconSetBase<eExcelconditionalFormatting4IconsSetType>,
+ IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType> {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingFourIconSet(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.FourIconSet,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode != null && itemElementNode.HasChildNodes) {
+ XmlNode iconNode4 = TopNode.SelectSingleNode(
+ "d:iconSet/d:cfvo[position()=4]",
+ NameSpaceManager);
+ Icon4 = new(
+ eExcelConditionalFormattingRuleType.FourIconSet,
+ address,
+ worksheet,
+ iconNode4,
+ namespaceManager);
+ } else {
+ XmlNode iconSetNode = TopNode.SelectSingleNode("d:iconSet", NameSpaceManager);
+ var iconNode4 = iconSetNode.OwnerDocument.CreateElement(
+ ExcelConditionalFormattingConstants.Paths._cfvo,
+ ExcelPackage._schemaMain);
+ iconSetNode.AppendChild(iconNode4);
+
+ Icon4 = new(
+ eExcelConditionalFormattingValueObjectType.Percent,
+ 75,
+ "",
+ eExcelConditionalFormattingRuleType.ThreeIconSet,
+ address,
+ priority,
+ worksheet,
+ iconNode4,
+ namespaceManager);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingFourIconSet(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingFourIconSet(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+
+ public ExcelConditionalFormattingIconDataBarValue Icon4 { get; internal set; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThan.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThan.cs
new file mode 100644
index 0000000..a60f7bc
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThan.cs
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingGreaterThan
+/// </summary>
+public class ExcelConditionalFormattingGreaterThan
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingGreaterThan {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingGreaterThan(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.GreaterThan,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Operator = eExcelConditionalFormattingOperatorType.GreaterThan;
+ Formula = string.Empty;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingGreaterThan(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingGreaterThan(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThanOrEqual.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThanOrEqual.cs
new file mode 100644
index 0000000..bb47a80
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThanOrEqual.cs
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingGreaterThanOrEqual
+/// </summary>
+public class ExcelConditionalFormattingGreaterThanOrEqual
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingGreaterThanOrEqual {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingGreaterThanOrEqual(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.GreaterThanOrEqual,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Operator = eExcelConditionalFormattingOperatorType.GreaterThanOrEqual;
+ Formula = string.Empty;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingGreaterThanOrEqual(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingGreaterThanOrEqual(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingLast7Days.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingLast7Days.cs
new file mode 100644
index 0000000..6fc14d8
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingLast7Days.cs
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingLast7Days
+/// </summary>
+public class ExcelConditionalFormattingLast7Days : ExcelConditionalFormattingTimePeriodGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingLast7Days(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.Last7Days,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ TimePeriod = eExcelConditionalFormattingTimePeriodType.Last7Days;
+ Formula = string.Format(
+ "AND(TODAY()-FLOOR({0},1)<=6,FLOOR({0},1)<=TODAY())",
+ Address.Start.Address);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingLast7Days(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingLast7Days(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastMonth.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastMonth.cs
new file mode 100644
index 0000000..f0d16db
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastMonth.cs
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingLastMonth
+/// </summary>
+public class ExcelConditionalFormattingLastMonth : ExcelConditionalFormattingTimePeriodGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingLastMonth(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.LastMonth,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ TimePeriod = eExcelConditionalFormattingTimePeriodType.LastMonth;
+ Formula = string.Format(
+ "AND(MONTH({0})=MONTH(EDATE(TODAY(),0-1)),YEAR({0})=YEAR(EDATE(TODAY(),0-1)))",
+ Address.Start.Address);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingLastMonth(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingLastMonth(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastWeek.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastWeek.cs
new file mode 100644
index 0000000..be82aea
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastWeek.cs
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingLastWeek
+/// </summary>
+public class ExcelConditionalFormattingLastWeek : ExcelConditionalFormattingTimePeriodGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingLastWeek(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.LastWeek,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ TimePeriod = eExcelConditionalFormattingTimePeriodType.LastWeek;
+ Formula = string.Format(
+ "AND(TODAY()-ROUNDDOWN({0},0)>=(WEEKDAY(TODAY())),TODAY()-ROUNDDOWN({0},0)<(WEEKDAY(TODAY())+7))",
+ Address.Start.Address);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingLastWeek(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingLastWeek(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThan.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThan.cs
new file mode 100644
index 0000000..6d4e97e
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThan.cs
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingLessThan
+/// </summary>
+public class ExcelConditionalFormattingLessThan
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingLessThan {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingLessThan(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.LessThan,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Operator = eExcelConditionalFormattingOperatorType.LessThan;
+ Formula = string.Empty;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingLessThan(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingLessThan(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThanOrEqual.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThanOrEqual.cs
new file mode 100644
index 0000000..f4ff6d8
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThanOrEqual.cs
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingLessThanOrEqual
+/// </summary>
+public class ExcelConditionalFormattingLessThanOrEqual
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingLessThanOrEqual {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingLessThanOrEqual(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.LessThanOrEqual,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Operator = eExcelConditionalFormattingOperatorType.LessThanOrEqual;
+ Formula = string.Empty;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingLessThanOrEqual(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingLessThanOrEqual(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextMonth.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextMonth.cs
new file mode 100644
index 0000000..0b5dec1
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextMonth.cs
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingNextMonth
+/// </summary>
+public class ExcelConditionalFormattingNextMonth : ExcelConditionalFormattingTimePeriodGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingNextMonth(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.NextMonth,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ TimePeriod = eExcelConditionalFormattingTimePeriodType.NextMonth;
+ Formula = string.Format(
+ "AND(MONTH({0})=MONTH(EDATE(TODAY(),0+1)), YEAR({0})=YEAR(EDATE(TODAY(),0+1)))",
+ Address.Start.Address);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingNextMonth(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingNextMonth(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextWeek.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextWeek.cs
new file mode 100644
index 0000000..a2e6ffd
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextWeek.cs
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingNextWeek
+/// </summary>
+public class ExcelConditionalFormattingNextWeek : ExcelConditionalFormattingTimePeriodGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingNextWeek(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.NextWeek,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ TimePeriod = eExcelConditionalFormattingTimePeriodType.NextWeek;
+ Formula = string.Format(
+ "AND(ROUNDDOWN({0},0)-TODAY()>(7-WEEKDAY(TODAY())),ROUNDDOWN({0},0)-TODAY()<(15-WEEKDAY(TODAY())))",
+ Address.Start.Address);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingNextWeek(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingNextWeek(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotBetween.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotBetween.cs
new file mode 100644
index 0000000..011c766
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotBetween.cs
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingNotBetween
+/// </summary>
+public class ExcelConditionalFormattingNotBetween
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingNotBetween {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingNotBetween(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.NotBetween,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Operator = eExcelConditionalFormattingOperatorType.NotBetween;
+ Formula = string.Empty;
+ Formula2 = string.Empty;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingNotBetween(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingNotBetween(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsBlanks.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsBlanks.cs
new file mode 100644
index 0000000..aafe501
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsBlanks.cs
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingNotContainsBlanks
+/// </summary>
+public class ExcelConditionalFormattingNotContainsBlanks
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingNotContainsBlanks {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingNotContainsBlanks(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.NotContainsBlanks,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Formula = string.Format("LEN(TRIM({0}))>0", Address.Start.Address);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingNotContainsBlanks(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingNotContainsBlanks(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsErrors.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsErrors.cs
new file mode 100644
index 0000000..9058785
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsErrors.cs
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingNotContainsErrors
+/// </summary>
+public class ExcelConditionalFormattingNotContainsErrors
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingNotContainsErrors {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingNotContainsErrors(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.NotContainsErrors,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Formula = string.Format("NOT(ISERROR({0}))", Address.Start.Address);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingNotContainsErrors(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingNotContainsErrors(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsText.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsText.cs
new file mode 100644
index 0000000..97f0857
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsText.cs
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingNotContainsText
+/// </summary>
+public class ExcelConditionalFormattingNotContainsText
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingNotContainsText {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingNotContainsText(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.NotContainsText,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Operator = eExcelConditionalFormattingOperatorType.NotContains;
+ Text = string.Empty;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingNotContainsText(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingNotContainsText(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+
+ /// <summary>
+ /// The text to search inside the cell
+ /// </summary>
+ public string Text {
+ get => GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute);
+ set {
+ SetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute, value);
+
+ Formula = string.Format(
+ "ISERROR(SEARCH(\"{1}\",{0}))",
+ Address.Start.Address,
+ value.Replace("\"", "\"\""));
+ }
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotEqual.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotEqual.cs
new file mode 100644
index 0000000..65c1c72
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotEqual.cs
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingNotEqual
+/// </summary>
+public class ExcelConditionalFormattingNotEqual
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingNotEqual {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingNotEqual(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.NotEqual,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Operator = eExcelConditionalFormattingOperatorType.NotEqual;
+ Formula = string.Empty;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingNotEqual(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingNotEqual(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingRule.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingRule.cs
new file mode 100644
index 0000000..078f35c
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingRule.cs
@@ -0,0 +1,489 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Immutable;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+///
+/// </summary>
+public abstract class ExcelConditionalFormattingRule : XmlHelper, IExcelConditionalFormattingRule {
+ private eExcelConditionalFormattingRuleType? _type;
+ private readonly ExcelWorksheet _worksheet;
+
+ /// <summary>
+ /// Sinalize that we are in a Cnaging Priorities opeartion so that we won't enter
+ /// a recursive loop.
+ /// </summary>
+ private static bool _changingPriority;
+
+ protected override ImmutableArray<string> SchemaNodeOrder =>
+ ExcelWorksheet.WorksheetSchemaNodeOrder;
+
+ /// <summary>
+ /// Initialize the <see cref="ExcelConditionalFormattingRule"/>
+ /// </summary>
+ /// <param name="type"></param>
+ /// <param name="address"></param>
+ /// <param name="priority">Used also as the cfRule unique key</param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingRule(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(namespaceManager, itemElementNode) {
+ ArgumentNullException.ThrowIfNull(address);
+ ArgumentOutOfRangeException.ThrowIfLessThan(priority, 1);
+ ArgumentNullException.ThrowIfNull(worksheet);
+
+ _type = type;
+ _worksheet = worksheet;
+
+ if (itemElementNode == null) {
+ // Create/Get the <cfRule> inside <conditionalFormatting>
+ itemElementNode = CreateComplexNode(
+ _worksheet.WorksheetXml.DocumentElement,
+ string.Format(
+ "{0}[{1}='{2}']/{1}='{2}'/{3}[{4}='{5}']/{4}='{5}'",
+ //{0}
+ ExcelConditionalFormattingConstants.Paths._conditionalFormatting,
+ // {1}
+ ExcelConditionalFormattingConstants.Paths._sqrefAttribute,
+ // {2}
+ address.AddressSpaceSeparated, //CF node don't what to have comma between multi addresses, use space instead.
+ // {3}
+ ExcelConditionalFormattingConstants.Paths._cfRule,
+ //{4}
+ ExcelConditionalFormattingConstants.Paths._priorityAttribute,
+ //{5}
+ priority));
+ }
+
+ // Point to <cfRule>
+ TopNode = itemElementNode;
+
+ Address = address;
+ Priority = priority;
+ Type = type;
+ if (DxfId >= 0) {
+ worksheet.Workbook.Styles.Dxfs[DxfId].AllowChange = true; //This Id is referenced by CF, so we can use it when we save.
+ _style = worksheet.Workbook.Styles.Dxfs[DxfId].Clone(); //Clone, so it can be altered without effecting other dxf styles
+ }
+ }
+
+ /// <summary>
+ /// Initialize the <see cref="ExcelConditionalFormattingRule"/>
+ /// </summary>
+ /// <param name="type"></param>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingRule(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNamespaceManager namespaceManager)
+ : this(type, address, priority, worksheet, null, namespaceManager) {}
+
+ /// <summary>
+ /// Get the <cfRule> node
+ /// </summary>
+ public XmlNode Node => TopNode;
+
+ /// <summary>
+ /// Address of the conditional formatting rule
+ /// </summary>
+ /// <remarks>
+ /// The address is stores in a parent node called <conditionalFormatting> in the
+ /// @sqref attribute. Excel groups rules that have the same address inside one node.
+ /// </remarks>
+ public ExcelAddress Address {
+ get =>
+ new(Node.ParentNode.Attributes[ExcelConditionalFormattingConstants.Attributes._sqref].Value);
+ set {
+ // Check if the address is to be changed
+ if (Address.Address != value.Address) {
+ // Save the old parente node
+ XmlNode oldNode = Node;
+ XmlNode oldParentNode = Node.ParentNode;
+
+ // Create/Get the new <conditionalFormatting> parent node
+ XmlNode newParentNode = CreateComplexNode(
+ _worksheet.WorksheetXml.DocumentElement,
+ string.Format(
+ "{0}[{1}='{2}']/{1}='{2}'",
+ //{0}
+ ExcelConditionalFormattingConstants.Paths._conditionalFormatting,
+ // {1}
+ ExcelConditionalFormattingConstants.Paths._sqrefAttribute,
+ // {2}
+ value.AddressSpaceSeparated));
+
+ // Move the <cfRule> node to the new <conditionalFormatting> parent node
+ TopNode = newParentNode.AppendChild(Node);
+
+ // Check if the old <conditionalFormatting> parent node has <cfRule> node inside it
+ if (!oldParentNode.HasChildNodes) {
+ // Remove the old parent node
+ oldParentNode.ParentNode.RemoveChild(oldParentNode);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Type of conditional formatting rule. ST_CfType §18.18.12.
+ /// </summary>
+ public eExcelConditionalFormattingRuleType Type {
+ get {
+ // Transform the @type attribute to EPPlus Rule Type (slighty diferente)
+ if (_type == null) {
+ _type = ExcelConditionalFormattingRuleType.GetTypeByAttrbiute(
+ GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._typeAttribute),
+ TopNode,
+ _worksheet.NameSpaceManager);
+ }
+ return (eExcelConditionalFormattingRuleType)_type;
+ }
+ internal set {
+ _type = value;
+ // Transform the EPPlus Rule Type to @type attribute (slighty diferente)
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._typeAttribute,
+ ExcelConditionalFormattingRuleType.GetAttributeByType(value),
+ true);
+ }
+ }
+
+ /// <summary>
+ /// The priority of this conditional formatting rule. This value is used to determine
+ /// which format should be evaluated and rendered. Lower numeric values are higher
+ /// priority than higher numeric values, where 1 is the highest priority.
+ /// </summary>
+ public int Priority {
+ get => GetXmlNodeInt(ExcelConditionalFormattingConstants.Paths._priorityAttribute);
+ set {
+ // Save the current CF rule priority
+ int priority = Priority;
+
+ // Check if the @priority is to be changed
+ if (priority != value) {
+ // Check if we are not already inside a "Change Priority" operation
+ if (!_changingPriority) {
+ if (value < 1) {
+ throw new IndexOutOfRangeException(
+ ExcelConditionalFormattingConstants.Errors._invalidPriority);
+ }
+
+ // Sinalize that we are already changing cfRules priorities
+ _changingPriority = true;
+
+ // Check if we lowered the priority
+ if (priority > value) {
+ for (int i = priority - 1; i >= value; i--) {
+ var cfRule = _worksheet.ConditionalFormatting.RulesByPriority(i);
+
+ if (cfRule != null) {
+ cfRule.Priority++;
+ }
+ }
+ } else {
+ for (int i = priority + 1; i <= value; i++) {
+ var cfRule = _worksheet.ConditionalFormatting.RulesByPriority(i);
+
+ if (cfRule != null) {
+ cfRule.Priority--;
+ }
+ }
+ }
+
+ // Sinalize that we are no longer changing cfRules priorities
+ _changingPriority = false;
+ }
+
+ // Change the priority in the XML
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._priorityAttribute,
+ value.ToString(),
+ true);
+ }
+ }
+ }
+
+ /// <summary>
+ /// If this flag is true, no rules with lower priority shall be applied over this rule,
+ /// when this rule evaluates to true.
+ /// </summary>
+ public bool StopIfTrue {
+ get => GetXmlNodeBool(ExcelConditionalFormattingConstants.Paths._stopIfTrueAttribute);
+ set =>
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._stopIfTrueAttribute,
+ value ? "1" : string.Empty,
+ true);
+ }
+
+ /// <summary>
+ /// DxfId Style Attribute
+ /// </summary>
+ internal int DxfId {
+ get => GetXmlNodeInt(ExcelConditionalFormattingConstants.Paths._dxfIdAttribute);
+ set =>
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._dxfIdAttribute,
+ (value == int.MinValue) ? string.Empty : value.ToString(),
+ true);
+ }
+
+ internal ExcelDxfStyleConditionalFormatting _style;
+
+ public ExcelDxfStyleConditionalFormatting Style {
+ get {
+ if (_style == null) {
+ _style = new(NameSpaceManager, null, _worksheet.Workbook.Styles);
+ }
+ return _style;
+ }
+ }
+
+ /// <summary>
+ /// StdDev (zero is not allowed and will be converted to 1)
+ /// </summary>
+ public UInt16 StdDev {
+ get =>
+ Convert.ToUInt16(GetXmlNodeInt(ExcelConditionalFormattingConstants.Paths._stdDevAttribute));
+ set =>
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._stdDevAttribute,
+ (value == 0) ? "1" : value.ToString(),
+ true);
+ }
+
+ /// <summary>
+ /// Rank (zero is not allowed and will be converted to 1)
+ /// </summary>
+ public UInt16 Rank {
+ get =>
+ Convert.ToUInt16(GetXmlNodeInt(ExcelConditionalFormattingConstants.Paths._rankAttribute));
+ set =>
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._rankAttribute,
+ (value == 0) ? "1" : value.ToString(),
+ true);
+ }
+
+ /// <summary>
+ /// AboveAverage
+ /// </summary>
+ internal protected bool? AboveAverage {
+ get {
+ bool? aboveAverage = GetXmlNodeBoolNullable(
+ ExcelConditionalFormattingConstants.Paths._aboveAverageAttribute);
+
+ // Above Avarege if TRUE or if attribute does not exists
+ return (aboveAverage == true) || (aboveAverage == null);
+ }
+ set {
+ string aboveAverageValue = string.Empty;
+
+ // Only the types that needs the @AboveAverage
+ if ((_type == eExcelConditionalFormattingRuleType.BelowAverage)
+ || (_type == eExcelConditionalFormattingRuleType.BelowOrEqualAverage)
+ || (_type == eExcelConditionalFormattingRuleType.BelowStdDev)) {
+ aboveAverageValue = "0";
+ }
+
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._aboveAverageAttribute,
+ aboveAverageValue,
+ true);
+ }
+ }
+
+ /// <summary>
+ /// EqualAverage
+ /// </summary>
+ internal protected bool? EqualAverage {
+ get {
+ bool? equalAverage = GetXmlNodeBoolNullable(
+ ExcelConditionalFormattingConstants.Paths._equalAverageAttribute);
+
+ // Equal Avarege only if TRUE
+ return (equalAverage == true);
+ }
+ set {
+ string equalAverageValue = string.Empty;
+
+ // Only the types that needs the @EqualAverage
+ if ((_type == eExcelConditionalFormattingRuleType.AboveOrEqualAverage)
+ || (_type == eExcelConditionalFormattingRuleType.BelowOrEqualAverage)) {
+ equalAverageValue = "1";
+ }
+
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._equalAverageAttribute,
+ equalAverageValue,
+ true);
+ }
+ }
+
+ /// <summary>
+ /// Bottom attribute
+ /// </summary>
+ internal protected bool? Bottom {
+ get {
+ bool? bottom = GetXmlNodeBoolNullable(
+ ExcelConditionalFormattingConstants.Paths._bottomAttribute);
+
+ // Bottom if TRUE
+ return (bottom == true);
+ }
+ set {
+ string bottomValue = string.Empty;
+
+ // Only the types that needs the @Bottom
+ if ((_type == eExcelConditionalFormattingRuleType.Bottom)
+ || (_type == eExcelConditionalFormattingRuleType.BottomPercent)) {
+ bottomValue = "1";
+ }
+
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._bottomAttribute,
+ bottomValue,
+ true);
+ }
+ }
+
+ /// <summary>
+ /// Percent attribute
+ /// </summary>
+ internal protected bool? Percent {
+ get {
+ bool? percent = GetXmlNodeBoolNullable(
+ ExcelConditionalFormattingConstants.Paths._percentAttribute);
+
+ // Bottom if TRUE
+ return (percent == true);
+ }
+ set {
+ string percentValue = string.Empty;
+
+ // Only the types that needs the @Bottom
+ if ((_type == eExcelConditionalFormattingRuleType.BottomPercent)
+ || (_type == eExcelConditionalFormattingRuleType.TopPercent)) {
+ percentValue = "1";
+ }
+
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._percentAttribute,
+ percentValue,
+ true);
+ }
+ }
+
+ /// <summary>
+ /// TimePeriod
+ /// </summary>
+ internal protected eExcelConditionalFormattingTimePeriodType TimePeriod {
+ get =>
+ ExcelConditionalFormattingTimePeriodType.GetTypeByAttribute(
+ GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._timePeriodAttribute));
+ set =>
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._timePeriodAttribute,
+ ExcelConditionalFormattingTimePeriodType.GetAttributeByType(value),
+ true);
+ }
+
+ /// <summary>
+ /// Operator
+ /// </summary>
+ internal protected eExcelConditionalFormattingOperatorType Operator {
+ get =>
+ ExcelConditionalFormattingOperatorType.GetTypeByAttribute(
+ GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._operatorAttribute));
+ set =>
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._operatorAttribute,
+ ExcelConditionalFormattingOperatorType.GetAttributeByType(value),
+ true);
+ }
+
+ /// <summary>
+ /// Formula
+ /// </summary>
+ public string Formula {
+ get => GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._formula);
+ set => SetXmlNodeString(ExcelConditionalFormattingConstants.Paths._formula, value);
+ }
+
+ /// <summary>
+ /// Formula2
+ /// </summary>
+ public string Formula2 {
+ get =>
+ GetXmlNodeString(
+ string.Format(
+ "{0}[position()=2]",
+ // {0}
+ ExcelConditionalFormattingConstants.Paths._formula));
+ set {
+ // Create/Get the first <formula> node (ensure that it exists)
+ var firstNode = CreateComplexNode(
+ TopNode,
+ string.Format(
+ "{0}[position()=1]",
+ // {0}
+ ExcelConditionalFormattingConstants.Paths._formula));
+
+ // Create/Get the seconde <formula> node (ensure that it exists)
+ var secondNode = CreateComplexNode(
+ TopNode,
+ string.Format(
+ "{0}[position()=2]",
+ // {0}
+ ExcelConditionalFormattingConstants.Paths._formula));
+
+ // Save the formula in the second <formula> node
+ secondNode.InnerText = value;
+ }
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisMonth.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisMonth.cs
new file mode 100644
index 0000000..0b11938
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisMonth.cs
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingThisMonth
+/// </summary>
+public class ExcelConditionalFormattingThisMonth : ExcelConditionalFormattingTimePeriodGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingThisMonth(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.ThisMonth,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ TimePeriod = eExcelConditionalFormattingTimePeriodType.ThisMonth;
+ Formula = string.Format(
+ "AND(MONTH({0})=MONTH(TODAY()), YEAR({0})=YEAR(TODAY()))",
+ Address.Start.Address);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingThisMonth(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingThisMonth(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisWeek.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisWeek.cs
new file mode 100644
index 0000000..cb7833c
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisWeek.cs
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingThisWeek
+/// </summary>
+public class ExcelConditionalFormattingThisWeek : ExcelConditionalFormattingTimePeriodGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingThisWeek(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.ThisWeek,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ TimePeriod = eExcelConditionalFormattingTimePeriodType.ThisWeek;
+ Formula = string.Format(
+ "AND(TODAY()-ROUNDDOWN({0},0)<=WEEKDAY(TODAY())-1,ROUNDDOWN({0},0)-TODAY()<=7-WEEKDAY(TODAY()))",
+ Address.Start.Address);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingThisWeek(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingThisWeek(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeColorScale.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeColorScale.cs
new file mode 100644
index 0000000..9c0570e
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeColorScale.cs
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingThreeColorScale
+/// </summary>
+public class ExcelConditionalFormattingThreeColorScale
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingThreeColorScale {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingThreeColorScale(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.ThreeColorScale,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ // Create the <colorScale> node inside the <cfRule> node
+ var colorScaleNode = CreateComplexNode(
+ Node,
+ ExcelConditionalFormattingConstants.Paths._colorScale);
+
+ // LowValue default
+ LowValue = new(
+ eExcelConditionalFormattingValueObjectPosition.Low,
+ eExcelConditionalFormattingValueObjectType.Min,
+ eExcelConditionalFormattingRuleType.ThreeColorScale,
+ address,
+ priority,
+ worksheet,
+ NameSpaceManager);
+
+ // MiddleValue default
+ MiddleValue = new(
+ eExcelConditionalFormattingValueObjectPosition.Middle,
+ eExcelConditionalFormattingValueObjectType.Percent,
+ 50,
+ string.Empty,
+ eExcelConditionalFormattingRuleType.ThreeColorScale,
+ address,
+ priority,
+ worksheet,
+ NameSpaceManager);
+
+ // HighValue default
+ HighValue = new(
+ eExcelConditionalFormattingValueObjectPosition.High,
+ eExcelConditionalFormattingValueObjectType.Max,
+ eExcelConditionalFormattingRuleType.ThreeColorScale,
+ address,
+ priority,
+ worksheet,
+ NameSpaceManager);
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingThreeColorScale(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingThreeColorScale(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+
+ /// <summary>
+ /// Low Value for Three Color Scale Object Value
+ /// </summary>
+ public ExcelConditionalFormattingColorScaleValue LowValue { get; set; }
+
+ /// <summary>
+ /// Middle Value for Three Color Scale Object Value
+ /// </summary>
+ public ExcelConditionalFormattingColorScaleValue MiddleValue { get; set; }
+
+ /// <summary>
+ /// High Value for Three Color Scale Object Value
+ /// </summary>
+ public ExcelConditionalFormattingColorScaleValue HighValue { get; set; }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeIconSet.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeIconSet.cs
new file mode 100644
index 0000000..554e428
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeIconSet.cs
@@ -0,0 +1,277 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+public class ExcelConditionalFormattingThreeIconSet
+ : ExcelConditionalFormattingIconSetBase<eExcelconditionalFormatting3IconsSetType> {
+ internal ExcelConditionalFormattingThreeIconSet(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.ThreeIconSet,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {}
+}
+
+/// <summary>
+/// ExcelConditionalFormattingThreeIconSet
+/// </summary>
+public class ExcelConditionalFormattingIconSetBase<T>
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingThreeIconSet<T> {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="type"></param>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingIconSetBase(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ type,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode != null && itemElementNode.HasChildNodes) {
+ int pos = 1;
+ foreach (XmlNode node in itemElementNode.SelectNodes("d:iconSet/d:cfvo", NameSpaceManager)) {
+ if (pos == 1) {
+ Icon1 = new(type, address, worksheet, node, namespaceManager);
+ } else if (pos == 2) {
+ Icon2 = new(type, address, worksheet, node, namespaceManager);
+ } else if (pos == 3) {
+ Icon3 = new(type, address, worksheet, node, namespaceManager);
+ } else {
+ break;
+ }
+ pos++;
+ }
+ } else {
+ var iconSetNode = CreateComplexNode(Node, ExcelConditionalFormattingConstants.Paths._iconSet);
+
+ //Create the <iconSet> node inside the <cfRule> node
+ double spann;
+ if (type == eExcelConditionalFormattingRuleType.ThreeIconSet) {
+ spann = 3;
+ } else if (type == eExcelConditionalFormattingRuleType.FourIconSet) {
+ spann = 4;
+ } else {
+ spann = 5;
+ }
+
+ var iconNode1 = iconSetNode.OwnerDocument.CreateElement(
+ ExcelConditionalFormattingConstants.Paths._cfvo,
+ ExcelPackage._schemaMain);
+ iconSetNode.AppendChild(iconNode1);
+ Icon1 = new(
+ eExcelConditionalFormattingValueObjectType.Percent,
+ 0,
+ "",
+ eExcelConditionalFormattingRuleType.ThreeIconSet,
+ address,
+ priority,
+ worksheet,
+ iconNode1,
+ namespaceManager);
+
+ var iconNode2 = iconSetNode.OwnerDocument.CreateElement(
+ ExcelConditionalFormattingConstants.Paths._cfvo,
+ ExcelPackage._schemaMain);
+ iconSetNode.AppendChild(iconNode2);
+ Icon2 = new(
+ eExcelConditionalFormattingValueObjectType.Percent,
+ Math.Round(100D / spann, 0),
+ "",
+ eExcelConditionalFormattingRuleType.ThreeIconSet,
+ address,
+ priority,
+ worksheet,
+ iconNode2,
+ namespaceManager);
+
+ var iconNode3 = iconSetNode.OwnerDocument.CreateElement(
+ ExcelConditionalFormattingConstants.Paths._cfvo,
+ ExcelPackage._schemaMain);
+ iconSetNode.AppendChild(iconNode3);
+ Icon3 = new(
+ eExcelConditionalFormattingValueObjectType.Percent,
+ Math.Round(100D * (2D / spann), 0),
+ "",
+ eExcelConditionalFormattingRuleType.ThreeIconSet,
+ address,
+ priority,
+ worksheet,
+ iconNode3,
+ namespaceManager);
+ Type = type;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ ///<param name="type"></param>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingIconSetBase(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(type, address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ ///<param name="type"></param>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingIconSetBase(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(type, address, priority, worksheet, null, null) {}
+
+ /// <summary>
+ /// Settings for icon 1 in the iconset
+ /// </summary>
+ public ExcelConditionalFormattingIconDataBarValue Icon1 { get; internal set; }
+
+ /// <summary>
+ /// Settings for icon 2 in the iconset
+ /// </summary>
+ public ExcelConditionalFormattingIconDataBarValue Icon2 { get; internal set; }
+
+ /// <summary>
+ /// Settings for icon 2 in the iconset
+ /// </summary>
+ public ExcelConditionalFormattingIconDataBarValue Icon3 { get; internal set; }
+
+ private const string _reversePath = "d:iconSet/@reverse";
+
+ /// <summary>
+ /// Reverse the order of the icons
+ /// </summary>
+ public bool Reverse {
+ get => GetXmlNodeBool(_reversePath, false);
+ set => SetXmlNodeBool(_reversePath, value);
+ }
+
+ private const string _showValuePath = "d:iconSet/@showValue";
+
+ /// <summary>
+ /// If the cell values are visible
+ /// </summary>
+ public bool ShowValue {
+ get => GetXmlNodeBool(_showValuePath, true);
+ set => SetXmlNodeBool(_showValuePath, value);
+ }
+
+ private const string _iconSetPath = "d:iconSet/@iconSet";
+
+ private string GetIconSetString(T value) {
+ if (Type == eExcelConditionalFormattingRuleType.FourIconSet) {
+ switch (value.ToString()) {
+ case "Arrows":
+ return "4Arrows";
+ case "ArrowsGray":
+ return "4ArrowsGray";
+ case "Rating":
+ return "4Rating";
+ case "RedToBlack":
+ return "4RedToBlack";
+ case "TrafficLights":
+ return "4TrafficLights";
+ default:
+ throw (new ArgumentException("Invalid type"));
+ }
+ }
+ if (Type == eExcelConditionalFormattingRuleType.FiveIconSet) {
+ switch (value.ToString()) {
+ case "Arrows":
+ return "5Arrows";
+ case "ArrowsGray":
+ return "5ArrowsGray";
+ case "Quarters":
+ return "5Quarters";
+ case "Rating":
+ return "5Rating";
+ default:
+ throw (new ArgumentException("Invalid type"));
+ }
+ }
+ switch (value.ToString()) {
+ case "Arrows":
+ return "3Arrows";
+ case "ArrowsGray":
+ return "3ArrowsGray";
+ case "Flags":
+ return "3Flags";
+ case "Signs":
+ return "3Signs";
+ case "Symbols":
+ return "3Symbols";
+ case "Symbols2":
+ return "3Symbols2";
+ case "TrafficLights1":
+ return "3TrafficLights1";
+ case "TrafficLights2":
+ return "3TrafficLights2";
+ default:
+ throw (new ArgumentException("Invalid type"));
+ }
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingTimePeriodGroup.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingTimePeriodGroup.cs
new file mode 100644
index 0000000..2fc4a58
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingTimePeriodGroup.cs
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingTimePeriodGroup
+/// </summary>
+public class ExcelConditionalFormattingTimePeriodGroup
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingTimePeriodGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="type"></param>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingTimePeriodGroup(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ type,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="type"></param>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingTimePeriodGroup(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(type, address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="type"></param>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingTimePeriodGroup(
+ eExcelConditionalFormattingRuleType type,
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(type, address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingToday.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingToday.cs
new file mode 100644
index 0000000..e6bdfd6
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingToday.cs
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingToday
+/// </summary>
+public class ExcelConditionalFormattingToday : ExcelConditionalFormattingTimePeriodGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingToday(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.Today,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ TimePeriod = eExcelConditionalFormattingTimePeriodType.Today;
+ Formula = string.Format("FLOOR({0},1)=TODAY()", Address.Start.Address);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingToday(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingToday(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingTomorrow.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingTomorrow.cs
new file mode 100644
index 0000000..4169af3
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingTomorrow.cs
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingTomorrow
+/// </summary>
+public class ExcelConditionalFormattingTomorrow : ExcelConditionalFormattingTimePeriodGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingTomorrow(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.Tomorrow,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ TimePeriod = eExcelConditionalFormattingTimePeriodType.Tomorrow;
+ Formula = string.Format("FLOOR({0},1)=TODAY()+1", Address.Start.Address);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingTomorrow(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingTomorrow(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingTop.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingTop.cs
new file mode 100644
index 0000000..47bbeca
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingTop.cs
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingTop
+/// </summary>
+public class ExcelConditionalFormattingTop
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingTopBottomGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingTop(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.Top,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Bottom = false;
+ Percent = false;
+ Rank = 10; // First 10 values
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingTop(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingTop(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingTopPercent.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingTopPercent.cs
new file mode 100644
index 0000000..0fe253e
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingTopPercent.cs
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingTopPercent
+/// </summary>
+public class ExcelConditionalFormattingTopPercent
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingTopBottomGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingTopPercent(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.TopPercent,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ Bottom = false;
+ Percent = true;
+ Rank = 10; // First 10 percent
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingTopPercent(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingTopPercent(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingTwoColorScale.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingTwoColorScale.cs
new file mode 100644
index 0000000..4bc1365
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingTwoColorScale.cs
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingTwoColorScale
+/// </summary>
+public class ExcelConditionalFormattingTwoColorScale
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingTwoColorScale {
+ /// <summary>
+ /// Private Low Value
+ /// </summary>
+ private ExcelConditionalFormattingColorScaleValue _lowValue;
+
+ /// <summary>
+ /// Private High Value
+ /// </summary>
+ private ExcelConditionalFormattingColorScaleValue _highValue;
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingTwoColorScale(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.TwoColorScale,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ // Create the <colorScale> node inside the <cfRule> node
+ var colorScaleNode = CreateComplexNode(
+ Node,
+ ExcelConditionalFormattingConstants.Paths._colorScale);
+
+ // LowValue default
+ LowValue = new(
+ eExcelConditionalFormattingValueObjectPosition.Low,
+ eExcelConditionalFormattingValueObjectType.Min,
+ eExcelConditionalFormattingRuleType.TwoColorScale,
+ address,
+ priority,
+ worksheet,
+ NameSpaceManager);
+
+ // HighValue default
+ HighValue = new(
+ eExcelConditionalFormattingValueObjectPosition.High,
+ eExcelConditionalFormattingValueObjectType.Max,
+ eExcelConditionalFormattingRuleType.TwoColorScale,
+ address,
+ priority,
+ worksheet,
+ NameSpaceManager);
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingTwoColorScale(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingTwoColorScale(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+
+ /// <summary>
+ /// Low Value for Two Color Scale Object Value
+ /// </summary>
+ public ExcelConditionalFormattingColorScaleValue LowValue {
+ get => _lowValue;
+ set => _lowValue = value;
+ }
+
+ /// <summary>
+ /// High Value for Two Color Scale Object Value
+ /// </summary>
+ public ExcelConditionalFormattingColorScaleValue HighValue {
+ get => _highValue;
+ set => _highValue = value;
+ }
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingUniqueValues.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingUniqueValues.cs
new file mode 100644
index 0000000..eb2de44
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingUniqueValues.cs
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingUniqueValues
+/// </summary>
+public class ExcelConditionalFormattingUniqueValues
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingUniqueValues {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="priority"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingUniqueValues(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.UniqueValues,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingUniqueValues(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingUniqueValues(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingYesterday.cs b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingYesterday.cs
new file mode 100644
index 0000000..f6302f2
--- /dev/null
+++ b/AppsheetEpplus/ConditionalFormatting/Rules/ExcelConditionalFormattingYesterday.cs
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Eyal Seagull Added 2012-04-03
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// ExcelConditionalFormattingYesterday
+/// </summary>
+public class ExcelConditionalFormattingYesterday : ExcelConditionalFormattingTimePeriodGroup {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelConditionalFormattingYesterday(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(
+ eExcelConditionalFormattingRuleType.Yesterday,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ namespaceManager ?? worksheet.NameSpaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
+ {
+ TimePeriod = eExcelConditionalFormattingTimePeriodType.Yesterday;
+ Formula = string.Format("FLOOR({0},1)=TODAY()-1", Address.Start.Address);
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelConditionalFormattingYesterday(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet,
+ XmlNode itemElementNode)
+ : this(address, priority, worksheet, itemElementNode, null) {}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="priority"></param>
+ /// <param name="address"></param>
+ /// <param name="worksheet"></param>
+ internal ExcelConditionalFormattingYesterday(
+ ExcelAddress address,
+ int priority,
+ ExcelWorksheet worksheet)
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidation.cs b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidation.cs
new file mode 100644
index 0000000..be01429
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidation.cs
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Interface for data validation
+/// </summary>
+public interface IExcelDataValidation {
+ /// <summary>
+ /// Address of data validation
+ /// </summary>
+ ExcelAddress Address { get; }
+
+ /// <summary>
+ /// Validation type
+ /// </summary>
+ ExcelDataValidationType ValidationType { get; }
+
+ /// <summary>
+ /// Controls how Excel will handle invalid values.
+ /// </summary>
+ ExcelDataValidationWarningStyle ErrorStyle { get; }
+
+ /// <summary>
+ /// True if input message should be shown
+ /// </summary>
+ bool? AllowBlank { get; set; }
+
+ /// <summary>
+ /// True if input message should be shown
+ /// </summary>
+ bool? ShowInputMessage { get; set; }
+
+ /// <summary>
+ /// True if error message should be shown.
+ /// </summary>
+ bool? ShowErrorMessage { get; set; }
+
+ /// <summary>
+ /// Title of error message box (see property ShowErrorMessage)
+ /// </summary>
+ string ErrorTitle { get; set; }
+
+ /// <summary>
+ /// Error message box text (see property ShowErrorMessage)
+ /// </summary>
+ string Error { get; set; }
+
+ /// <summary>
+ /// Title of info box if input message should be shown (see property ShowInputMessage)
+ /// </summary>
+ string PromptTitle { get; set; }
+
+ /// <summary>
+ /// Info message text (see property ShowErrorMessage)
+ /// </summary>
+ string Prompt { get; set; }
+
+ /// <summary>
+ /// True if the current validation type allows operator.
+ /// </summary>
+ bool AllowsOperator { get; }
+
+ /// <summary>
+ /// Validates the state of the validation.
+ /// </summary>
+ void Validate();
+}
diff --git a/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationAny.cs b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationAny.cs
new file mode 100644
index 0000000..fb6e842
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationAny.cs
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Raziq York Added 2014-08-08
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Data validation interface for Any value validation.
+/// </summary>
+public interface IExcelDataValidationAny : IExcelDataValidation {}
diff --git a/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationCustom.cs b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationCustom.cs
new file mode 100644
index 0000000..88055cb
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationCustom.cs
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Data validation interface for custom validation.
+/// </summary>
+public interface IExcelDataValidationCustom
+ : IExcelDataValidationWithFormula<IExcelDataValidationFormula>,
+ IExcelDataValidationWithOperator {}
diff --git a/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationDateTime.cs b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationDateTime.cs
new file mode 100644
index 0000000..08703d0
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationDateTime.cs
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Validation interface for datetime validations
+/// </summary>
+public interface IExcelDataValidationDateTime
+ : IExcelDataValidationWithFormula2<IExcelDataValidationFormulaDateTime>,
+ IExcelDataValidationWithOperator {}
diff --git a/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationDecimal.cs b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationDecimal.cs
new file mode 100644
index 0000000..92e19cd
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationDecimal.cs
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Data validation interface for decimal values
+/// </summary>
+public interface IExcelDataValidationDecimal
+ : IExcelDataValidationWithFormula2<IExcelDataValidationFormulaDecimal>,
+ IExcelDataValidationWithOperator {}
diff --git a/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationInt.cs b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationInt.cs
new file mode 100644
index 0000000..4ec1398
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationInt.cs
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public interface IExcelDataValidationInt
+ : IExcelDataValidationWithFormula2<IExcelDataValidationFormulaInt>,
+ IExcelDataValidationWithOperator {}
diff --git a/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationList.cs b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationList.cs
new file mode 100644
index 0000000..9e8e1f4
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationList.cs
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public interface IExcelDataValidationList
+ : IExcelDataValidationWithFormula<IExcelDataValidationFormulaList> {}
diff --git a/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationTime.cs b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationTime.cs
new file mode 100644
index 0000000..d37d676
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationTime.cs
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Data validation interface for time validation.
+/// </summary>
+public interface IExcelDataValidationTime
+ : IExcelDataValidationWithFormula2<IExcelDataValidationFormulaTime>,
+ IExcelDataValidationWithOperator {}
diff --git a/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationWithFormula.cs b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationWithFormula.cs
new file mode 100644
index 0000000..60899d0
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationWithFormula.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public interface IExcelDataValidationWithFormula<T> : IExcelDataValidation
+ where T : IExcelDataValidationFormula {
+ T Formula { get; }
+}
diff --git a/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationWithFormula2.cs b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationWithFormula2.cs
new file mode 100644
index 0000000..9ba64d9
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationWithFormula2.cs
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Interface for a data validation with two formulas
+/// </summary>
+/// <typeparam name="T"></typeparam>
+public interface IExcelDataValidationWithFormula2<T> : IExcelDataValidationWithFormula<T>
+ where T : IExcelDataValidationFormula {
+ /// <summary>
+ /// Formula 2
+ /// </summary>
+ T Formula2 { get; }
+}
diff --git a/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationWithOperator.cs b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationWithOperator.cs
new file mode 100644
index 0000000..ab5c50e
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Contracts/IExcelDataValidationWithOperator.cs
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Represents a validation with an operator
+/// </summary>
+public interface IExcelDataValidationWithOperator {
+ /// <summary>
+ /// Operator type
+ /// </summary>
+ ExcelDataValidationOperator Operator { get; }
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelDataValidation.cs b/AppsheetEpplus/DataValidation/ExcelDataValidation.cs
new file mode 100644
index 0000000..4ad68e0
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelDataValidation.cs
@@ -0,0 +1,283 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Collections.Immutable;
+using System.Globalization;
+using System.Text.RegularExpressions;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Excel datavalidation
+/// </summary>
+public abstract class ExcelDataValidation : XmlHelper, IExcelDataValidation {
+ private const string _itemElementNodeName = "d:dataValidation";
+
+ private readonly string _errorStylePath = "@errorStyle";
+ private readonly string _errorTitlePath = "@errorTitle";
+ private readonly string _errorPath = "@error";
+ private readonly string _promptTitlePath = "@promptTitle";
+ private readonly string _promptPath = "@prompt";
+ private readonly string _operatorPath = "@operator";
+ private readonly string _showErrorMessagePath = "@showErrorMessage";
+ private readonly string _showInputMessagePath = "@showInputMessage";
+ private readonly string _typeMessagePath = "@type";
+ private readonly string _sqrefPath = "@sqref";
+ private readonly string _allowBlankPath = "@allowBlank";
+ protected readonly string _formula1Path = "d:formula1";
+ protected readonly string _formula2Path = "d:formula2";
+
+ protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
+ "type",
+ "errorStyle",
+ "operator",
+ "allowBlank",
+ "showInputMessage",
+ "showErrorMessage",
+ "errorTitle",
+ "error",
+ "promptTitle",
+ "prompt",
+ "sqref",
+ "formula1",
+ "formula2",
+ ];
+
+ internal ExcelDataValidation(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType)
+ : this(worksheet, address, validationType, null) {}
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet">worksheet that owns the validation</param>
+ /// <param name="itemElementNode">Xml top node (dataValidations)</param>
+ /// <param name="validationType">Data validation type</param>
+ /// <param name="address">address for data validation</param>
+ internal ExcelDataValidation(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode)
+ : this(worksheet, address, validationType, itemElementNode, null) {}
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet">worksheet that owns the validation</param>
+ /// <param name="itemElementNode">Xml top node (dataValidations) when importing xml</param>
+ /// <param name="validationType">Data validation type</param>
+ /// <param name="address">address for data validation</param>
+ /// <param name="namespaceManager">Xml Namespace manager</param>
+ internal ExcelDataValidation(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(namespaceManager ?? worksheet.NameSpaceManager) {
+ ArgumentException.ThrowIfNullOrEmpty(address);
+ address = CheckAndFixRangeAddress(address);
+ if (itemElementNode == null) {
+ //var xmlDoc = worksheet.WorksheetXml;
+ TopNode = worksheet.WorksheetXml.SelectSingleNode(
+ "//d:dataValidations",
+ worksheet.NameSpaceManager);
+ // did not succeed using the XmlHelper methods here... so I'm creating the new node using XmlDocument...
+ var nsUri = NameSpaceManager.LookupNamespace("d");
+ //itemElementNode = TopNode.OwnerDocument.CreateElement(_itemElementNodeName, nsUri);
+ itemElementNode = TopNode.OwnerDocument.CreateElement(
+ _itemElementNodeName.Split(':')[1],
+ nsUri);
+ TopNode.AppendChild(itemElementNode);
+ }
+ TopNode = itemElementNode;
+ ValidationType = validationType;
+ Address = new(address);
+ }
+
+ private string CheckAndFixRangeAddress(string address) {
+ if (address.Contains(',')) {
+ throw new FormatException("Multiple addresses may not be commaseparated, use space instead");
+ }
+ address = address.ToUpper(CultureInfo.InvariantCulture);
+ if (Regex.IsMatch(address, "[A-Z]+:[A-Z]+")) {
+ address = AddressUtility.ParseEntireColumnSelections(address);
+ }
+ return address;
+ }
+
+ private void SetNullableBoolValue(string path, bool? val) {
+ if (val.HasValue) {
+ SetXmlNodeBool(path, val.Value);
+ } else {
+ DeleteNode(path);
+ }
+ }
+
+ /// <summary>
+ /// This method will validate the state of the validation
+ /// </summary>
+ /// <exception cref="InvalidOperationException">If the state breaks the rules of the validation</exception>
+ public virtual void Validate() {
+ var address = Address.Address;
+ // validate Formula1
+ if (string.IsNullOrEmpty(Formula1Internal)) {
+ throw new InvalidOperationException(
+ "Validation of " + address + " failed: Formula1 cannot be empty");
+ }
+ }
+
+ /// <summary>
+ /// True if the validation type allows operator to be set.
+ /// </summary>
+ public bool AllowsOperator => ValidationType.AllowOperator;
+
+ /// <summary>
+ /// Address of data validation
+ /// </summary>
+ public ExcelAddress Address {
+ get => new(GetXmlNodeString(_sqrefPath));
+ private set {
+ var address = AddressUtility.ParseEntireColumnSelections(value.Address);
+ SetXmlNodeString(_sqrefPath, address);
+ }
+ }
+
+ /// <summary>
+ /// Validation type
+ /// </summary>
+ public ExcelDataValidationType ValidationType {
+ get {
+ var typeString = GetXmlNodeString(_typeMessagePath);
+ return ExcelDataValidationType.GetBySchemaName(typeString);
+ }
+ private set => SetXmlNodeString(_typeMessagePath, value.SchemaName, true);
+ }
+
+ /// <summary>
+ /// Operator for comparison between the entered value and Formula/Formulas.
+ /// </summary>
+ public ExcelDataValidationOperator Operator {
+ get {
+ var operatorString = GetXmlNodeString(_operatorPath);
+ return Enum.TryParse<ExcelDataValidationOperator>(operatorString, true, out var op)
+ ? op
+ : ExcelDataValidationOperator.Any;
+ }
+ }
+
+ /// <summary>
+ /// Warning style
+ /// </summary>
+ public ExcelDataValidationWarningStyle ErrorStyle {
+ get {
+ var errorStyleString = GetXmlNodeString(_errorStylePath);
+ return Enum.TryParse<ExcelDataValidationWarningStyle>(errorStyleString, true, out var style)
+ ? style
+ : ExcelDataValidationWarningStyle.Undefined;
+ }
+ }
+
+ /// <summary>
+ /// True if blanks should be allowed
+ /// </summary>
+ public bool? AllowBlank {
+ get => GetXmlNodeBoolNullable(_allowBlankPath);
+ set => SetNullableBoolValue(_allowBlankPath, value);
+ }
+
+ /// <summary>
+ /// True if input message should be shown
+ /// </summary>
+ public bool? ShowInputMessage {
+ get => GetXmlNodeBoolNullable(_showInputMessagePath);
+ set => SetNullableBoolValue(_showInputMessagePath, value);
+ }
+
+ /// <summary>
+ /// True if error message should be shown
+ /// </summary>
+ public bool? ShowErrorMessage {
+ get => GetXmlNodeBoolNullable(_showErrorMessagePath);
+ set => SetNullableBoolValue(_showErrorMessagePath, value);
+ }
+
+ /// <summary>
+ /// Title of error message box
+ /// </summary>
+ public string ErrorTitle {
+ get => GetXmlNodeString(_errorTitlePath);
+ set => SetXmlNodeString(_errorTitlePath, value);
+ }
+
+ /// <summary>
+ /// Error message box text
+ /// </summary>
+ public string Error {
+ get => GetXmlNodeString(_errorPath);
+ set => SetXmlNodeString(_errorPath, value);
+ }
+
+ public string PromptTitle {
+ get => GetXmlNodeString(_promptTitlePath);
+ set => SetXmlNodeString(_promptTitlePath, value);
+ }
+
+ public string Prompt {
+ get => GetXmlNodeString(_promptPath);
+ set => SetXmlNodeString(_promptPath, value);
+ }
+
+ /// <summary>
+ /// Formula 1
+ /// </summary>
+ protected string Formula1Internal => GetXmlNodeString(_formula1Path);
+
+ /// <summary>
+ /// Formula 2
+ /// </summary>
+ protected string Formula2Internal => GetXmlNodeString(_formula2Path);
+
+ protected void SetValue<T>(T? val, string path)
+ where T : struct {
+ if (!val.HasValue) {
+ DeleteNode(path);
+ }
+ var stringValue = val.Value.ToString().Replace(',', '.');
+ SetXmlNodeString(path, stringValue);
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelDataValidationAny.cs b/AppsheetEpplus/DataValidation/ExcelDataValidationAny.cs
new file mode 100644
index 0000000..4e6e34f
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelDataValidationAny.cs
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Raziq York Added 2014-08-08
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Any value validation.
+/// </summary>
+public class ExcelDataValidationAny : ExcelDataValidation, IExcelDataValidationAny {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ internal ExcelDataValidationAny(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType)
+ : base(worksheet, address, validationType) {}
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelDataValidationAny(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode)
+ : base(worksheet, address, validationType, itemElementNode) {}
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelDataValidationAny(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(worksheet, address, validationType, itemElementNode, namespaceManager) {}
+
+ /// <summary>
+ /// This method will validate the state of the validation
+ /// </summary>
+ public override void Validate() {}
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelDataValidationCollection.cs b/AppsheetEpplus/DataValidation/ExcelDataValidationCollection.cs
new file mode 100644
index 0000000..1548409
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelDataValidationCollection.cs
@@ -0,0 +1,359 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-01
+ * Mats Alm Applying patch submitted 2011-11-14
+ * by Ted Heatherington
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ * Raziq York Added support for Any type 2014-08-08
+*******************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// <para>
+/// Collection of <see cref="ExcelDataValidation"/>. This class is providing the API for EPPlus data validation.
+/// </para>
+/// <para>
+/// The public methods of this class (Add[...]Validation) will create a datavalidation entry in the worksheet. When this
+/// validation has been created changes to the properties will affect the workbook immediately.
+/// </para>
+/// <para>
+/// Each type of validation has either a formula or a typed value/values, except for custom validation which has a formula only.
+/// </para>
+/// <code>
+/// // Add a date time validation
+/// var validation = worksheet.DataValidation.AddDateTimeValidation("A1");
+/// // set validation properties
+/// validation.ShowErrorMessage = true;
+/// validation.ErrorTitle = "An invalid date was entered";
+/// validation.Error = "The date must be between 2011-01-31 and 2011-12-31";
+/// validation.Prompt = "Enter date here";
+/// validation.Formula.Value = DateTime.Parse("2011-01-01");
+/// validation.Formula2.Value = DateTime.Parse("2011-12-31");
+/// validation.Operator = ExcelDataValidationOperator.between;
+/// </code>
+/// </summary>
+public class ExcelDataValidationCollection : XmlHelper, IEnumerable<IExcelDataValidation> {
+ private readonly List<IExcelDataValidation> _validations = new();
+ private readonly ExcelWorksheet _worksheet;
+
+ private const string _dataValidationPath = "//d:dataValidations";
+ private readonly string DataValidationItemsPath = string.Format(
+ "{0}/d:dataValidation",
+ _dataValidationPath);
+
+ protected override ImmutableArray<string> SchemaNodeOrder =>
+ ExcelWorksheet.WorksheetSchemaNodeOrder;
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ internal ExcelDataValidationCollection(ExcelWorksheet worksheet)
+ : base(worksheet.NameSpaceManager, worksheet.WorksheetXml.DocumentElement) {
+ ArgumentNullException.ThrowIfNull(worksheet);
+ _worksheet = worksheet;
+
+ // check existing nodes and load them
+ var dataValidationNodes = worksheet.WorksheetXml.SelectNodes(
+ DataValidationItemsPath,
+ worksheet.NameSpaceManager);
+ if (dataValidationNodes != null && dataValidationNodes.Count > 0) {
+ foreach (XmlNode node in dataValidationNodes) {
+ if (node.Attributes["sqref"] == null) {
+ continue;
+ }
+
+ var addr = node.Attributes["sqref"].Value;
+
+ var typeSchema = node.Attributes["type"] != null ? node.Attributes["type"].Value : "";
+
+ var type = ExcelDataValidationType.GetBySchemaName(typeSchema);
+ _validations.Add(ExcelDataValidationFactory.Create(type, worksheet, addr, node));
+ }
+ }
+ }
+
+ private void EnsureRootElementExists() {
+ var node = _worksheet.WorksheetXml.SelectSingleNode(
+ _dataValidationPath,
+ _worksheet.NameSpaceManager);
+ if (node == null) {
+ CreateNode(_dataValidationPath.TrimStart('/'));
+ }
+ }
+
+ /// <summary>
+ /// Validates address - not empty, collisions
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="validatingValidation"></param>
+ private void ValidateAddress(string address, IExcelDataValidation validatingValidation) {
+ ArgumentException.ThrowIfNullOrEmpty(address);
+
+ // ensure that the new address does not collide with an existing validation.
+ var newAddress = new ExcelAddress(address);
+ if (_validations.Count > 0) {
+ foreach (var validation in _validations) {
+ if (validatingValidation != null && validatingValidation == validation) {
+ continue;
+ }
+ var result = validation.Address.Collide(newAddress);
+ if (result != ExcelAddressBase.eAddressCollition.No) {
+ throw new InvalidOperationException(
+ string.Format(
+ "The address ({0}) collides with an existing validation ({1})",
+ address,
+ validation.Address.Address));
+ }
+ }
+ }
+ }
+
+ private void ValidateAddress(string address) {
+ ValidateAddress(address, null);
+ }
+
+ /// <summary>
+ /// Validates all data validations.
+ /// </summary>
+ internal void ValidateAll() {
+ foreach (var validation in _validations) {
+ validation.Validate();
+
+ ValidateAddress(validation.Address.Address, validation);
+ }
+ }
+
+ /// <summary>
+ /// Adds a <see cref="ExcelDataValidationAny"/> to the worksheet.
+ /// </summary>
+ /// <param name="address">The range/address to validate</param>
+ /// <returns></returns>
+ public IExcelDataValidationAny AddAnyValidation(string address) {
+ ValidateAddress(address);
+ EnsureRootElementExists();
+ var item = new ExcelDataValidationAny(_worksheet, address, ExcelDataValidationType.Any);
+ _validations.Add(item);
+ return item;
+ }
+
+ /// <summary>
+ /// Adds an <see cref="IExcelDataValidationInt"/> to the worksheet. Whole means that the only accepted values
+ /// are integer values.
+ /// </summary>
+ /// <param name="address">the range/address to validate</param>
+ public IExcelDataValidationInt AddIntegerValidation(string address) {
+ ValidateAddress(address);
+ EnsureRootElementExists();
+ var item = new ExcelDataValidationInt(_worksheet, address, ExcelDataValidationType.Whole);
+ _validations.Add(item);
+ return item;
+ }
+
+ /// <summary>
+ /// Addes an <see cref="IExcelDataValidationDecimal"/> to the worksheet. The only accepted values are
+ /// decimal values.
+ /// </summary>
+ /// <param name="address">The range/address to validate</param>
+ /// <returns></returns>
+ public IExcelDataValidationDecimal AddDecimalValidation(string address) {
+ ValidateAddress(address);
+ EnsureRootElementExists();
+ var item = new ExcelDataValidationDecimal(_worksheet, address, ExcelDataValidationType.Decimal);
+ _validations.Add(item);
+ return item;
+ }
+
+ /// <summary>
+ /// Adds an <see cref="IExcelDataValidationList"/> to the worksheet. The accepted values are defined
+ /// in a list.
+ /// </summary>
+ /// <param name="address">The range/address to validate</param>
+ /// <returns></returns>
+ public IExcelDataValidationList AddListValidation(string address) {
+ ValidateAddress(address);
+ EnsureRootElementExists();
+ var item = new ExcelDataValidationList(_worksheet, address, ExcelDataValidationType.List);
+ _validations.Add(item);
+ return item;
+ }
+
+ /// <summary>
+ /// Adds an <see cref="IExcelDataValidationInt"/> regarding text length to the worksheet.
+ /// </summary>
+ /// <param name="address">The range/address to validate</param>
+ /// <returns></returns>
+ public IExcelDataValidationInt AddTextLengthValidation(string address) {
+ ValidateAddress(address);
+ EnsureRootElementExists();
+ var item = new ExcelDataValidationInt(_worksheet, address, ExcelDataValidationType.TextLength);
+ _validations.Add(item);
+ return item;
+ }
+
+ /// <summary>
+ /// Adds an <see cref="IExcelDataValidationDateTime"/> to the worksheet.
+ /// </summary>
+ /// <param name="address">The range/address to validate</param>
+ /// <returns></returns>
+ public IExcelDataValidationDateTime AddDateTimeValidation(string address) {
+ ValidateAddress(address);
+ EnsureRootElementExists();
+ var item = new ExcelDataValidationDateTime(
+ _worksheet,
+ address,
+ ExcelDataValidationType.DateTime);
+ _validations.Add(item);
+ return item;
+ }
+
+ public IExcelDataValidationTime AddTimeValidation(string address) {
+ ValidateAddress(address);
+ EnsureRootElementExists();
+ var item = new ExcelDataValidationTime(_worksheet, address, ExcelDataValidationType.Time);
+ _validations.Add(item);
+ return item;
+ }
+
+ /// <summary>
+ /// Adds a <see cref="ExcelDataValidationCustom"/> to the worksheet.
+ /// </summary>
+ /// <param name="address">The range/address to validate</param>
+ /// <returns></returns>
+ public IExcelDataValidationCustom AddCustomValidation(string address) {
+ ValidateAddress(address);
+ EnsureRootElementExists();
+ var item = new ExcelDataValidationCustom(_worksheet, address, ExcelDataValidationType.Custom);
+ _validations.Add(item);
+ return item;
+ }
+
+ /// <summary>
+ /// Removes an <see cref="ExcelDataValidation"/> from the collection.
+ /// </summary>
+ /// <param name="item">The item to remove</param>
+ /// <returns>True if remove succeeds, otherwise false</returns>
+ /// <exception cref="ArgumentNullException">if <paramref name="item"/> is null</exception>
+ public bool Remove(IExcelDataValidation item) {
+ if (!(item is ExcelDataValidation validation)) {
+ throw new InvalidCastException(
+ "The supplied item must inherit OfficeOpenXml.DataValidation.ExcelDataValidation");
+ }
+ ArgumentNullException.ThrowIfNull(item);
+ TopNode.RemoveChild(validation.TopNode);
+ return _validations.Remove(validation);
+ }
+
+ /// <summary>
+ /// Number of validations
+ /// </summary>
+ public int Count => _validations.Count;
+
+ /// <summary>
+ /// Index operator, returns by 0-based index
+ /// </summary>
+ /// <param name="index"></param>
+ /// <returns></returns>
+ public IExcelDataValidation this[int index] {
+ get => _validations[index];
+ set => _validations[index] = value;
+ }
+
+ /// <summary>
+ /// Index operator, returns a data validation which address partly or exactly matches the searched address.
+ /// </summary>
+ /// <param name="address">A cell address or range</param>
+ /// <returns>A <see cref="ExcelDataValidation"/> or null if no match</returns>
+ public IExcelDataValidation this[string address] {
+ get {
+ var searchedAddress = new ExcelAddress(address);
+ return _validations.Find(x =>
+ x.Address.Collide(searchedAddress) != ExcelAddressBase.eAddressCollition.No);
+ }
+ }
+
+ /// <summary>
+ /// Returns all validations that matches the supplied predicate <paramref name="match"/>.
+ /// </summary>
+ /// <param name="match">predicate to filter out matching validations</param>
+ /// <returns></returns>
+ public IEnumerable<IExcelDataValidation> FindAll(Predicate<IExcelDataValidation> match) {
+ return _validations.FindAll(match);
+ }
+
+ /// <summary>
+ /// Returns the first matching validation.
+ /// </summary>
+ /// <param name="match"></param>
+ /// <returns></returns>
+ public IExcelDataValidation Find(Predicate<IExcelDataValidation> match) {
+ return _validations.Find(match);
+ }
+
+ /// <summary>
+ /// Removes all validations from the collection.
+ /// </summary>
+ public void Clear() {
+ DeleteAllNode(DataValidationItemsPath.TrimStart('/'));
+ _validations.Clear();
+ }
+
+ /// <summary>
+ /// Removes the validations that matches the predicate
+ /// </summary>
+ /// <param name="match"></param>
+ public void RemoveAll(Predicate<IExcelDataValidation> match) {
+ var matches = _validations.FindAll(match);
+ foreach (var m in matches) {
+ if (!(m is ExcelDataValidation validation)) {
+ throw new InvalidCastException(
+ "The supplied item must inherit OfficeOpenXml.DataValidation.ExcelDataValidation");
+ }
+ TopNode
+ .SelectSingleNode(_dataValidationPath.TrimStart('/'), NameSpaceManager)
+ .RemoveChild(validation.TopNode);
+ }
+ _validations.RemoveAll(match);
+ }
+
+ IEnumerator<IExcelDataValidation> IEnumerable<IExcelDataValidation>.GetEnumerator() {
+ return _validations.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _validations.GetEnumerator();
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelDataValidationCustom.cs b/AppsheetEpplus/DataValidation/ExcelDataValidationCustom.cs
new file mode 100644
index 0000000..381dfd4
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelDataValidationCustom.cs
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Custom validation, i.e. a formula.
+/// </summary>
+public class ExcelDataValidationCustom
+ : ExcelDataValidationWithFormula<IExcelDataValidationFormula>,
+ IExcelDataValidationCustom {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ internal ExcelDataValidationCustom(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType)
+ : base(worksheet, address, validationType) {
+ Formula = new ExcelDataValidationFormulaCustom(NameSpaceManager, TopNode, _formula1Path);
+ }
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelDataValidationCustom(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode)
+ : base(worksheet, address, validationType, itemElementNode) {
+ Formula = new ExcelDataValidationFormulaCustom(NameSpaceManager, TopNode, _formula1Path);
+ }
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelDataValidationCustom(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(worksheet, address, validationType, itemElementNode, namespaceManager) {
+ Formula = new ExcelDataValidationFormulaCustom(NameSpaceManager, TopNode, _formula1Path);
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelDataValidationDateTime.cs b/AppsheetEpplus/DataValidation/ExcelDataValidationDateTime.cs
new file mode 100644
index 0000000..04d5428
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelDataValidationDateTime.cs
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Validation for <see cref="DateTime"/>.
+/// </summary>
+public class ExcelDataValidationDateTime
+ : ExcelDataValidationWithFormula2<IExcelDataValidationFormulaDateTime>,
+ IExcelDataValidationDateTime {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ internal ExcelDataValidationDateTime(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType)
+ : base(worksheet, address, validationType) {
+ Formula = new ExcelDataValidationFormulaDateTime(NameSpaceManager, TopNode, _formula1Path);
+ Formula2 = new ExcelDataValidationFormulaDateTime(NameSpaceManager, TopNode, _formula2Path);
+ }
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelDataValidationDateTime(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode)
+ : base(worksheet, address, validationType, itemElementNode) {
+ Formula = new ExcelDataValidationFormulaDateTime(NameSpaceManager, TopNode, _formula1Path);
+ Formula2 = new ExcelDataValidationFormulaDateTime(NameSpaceManager, TopNode, _formula2Path);
+ }
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelDataValidationDateTime(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(worksheet, address, validationType, itemElementNode, namespaceManager) {
+ Formula = new ExcelDataValidationFormulaDateTime(NameSpaceManager, TopNode, _formula1Path);
+ Formula2 = new ExcelDataValidationFormulaDateTime(NameSpaceManager, TopNode, _formula2Path);
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelDataValidationDecimal.cs b/AppsheetEpplus/DataValidation/ExcelDataValidationDecimal.cs
new file mode 100644
index 0000000..dd9afbc
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelDataValidationDecimal.cs
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Data validation for decimal values
+/// </summary>
+public class ExcelDataValidationDecimal
+ : ExcelDataValidationWithFormula2<IExcelDataValidationFormulaDecimal>,
+ IExcelDataValidationDecimal {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ internal ExcelDataValidationDecimal(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType)
+ : base(worksheet, address, validationType) {
+ Formula = new ExcelDataValidationFormulaDecimal(NameSpaceManager, TopNode, _formula1Path);
+ Formula2 = new ExcelDataValidationFormulaDecimal(NameSpaceManager, TopNode, _formula2Path);
+ }
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelDataValidationDecimal(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode)
+ : base(worksheet, address, validationType, itemElementNode) {
+ Formula = new ExcelDataValidationFormulaDecimal(NameSpaceManager, TopNode, _formula1Path);
+ Formula2 = new ExcelDataValidationFormulaDecimal(NameSpaceManager, TopNode, _formula2Path);
+ }
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager">For test purposes</param>
+ internal ExcelDataValidationDecimal(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(worksheet, address, validationType, itemElementNode, namespaceManager) {
+ Formula = new ExcelDataValidationFormulaDecimal(NameSpaceManager, TopNode, _formula1Path);
+ Formula2 = new ExcelDataValidationFormulaDecimal(NameSpaceManager, TopNode, _formula2Path);
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelDataValidationFactory.cs b/AppsheetEpplus/DataValidation/ExcelDataValidationFactory.cs
new file mode 100644
index 0000000..bf9faa1
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelDataValidationFactory.cs
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ * Raziq York Added support for Any type 2014-08-08
+ *******************************************************************************/
+
+using System;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Factory class for ExcelDataValidation.
+/// </summary>
+internal static class ExcelDataValidationFactory {
+ /// <summary>
+ /// Creates an instance of <see cref="ExcelDataValidation"/> out of the given parameters.
+ /// </summary>
+ /// <param name="type"></param>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="itemElementNode"></param>
+ /// <returns></returns>
+ public static ExcelDataValidation Create(
+ ExcelDataValidationType type,
+ ExcelWorksheet worksheet,
+ string address,
+ XmlNode itemElementNode) {
+ ArgumentNullException.ThrowIfNull(type);
+ switch (type.Type) {
+ case eDataValidationType.Any:
+ return new ExcelDataValidationAny(worksheet, address, type, itemElementNode);
+ case eDataValidationType.TextLength:
+ case eDataValidationType.Whole:
+ return new ExcelDataValidationInt(worksheet, address, type, itemElementNode);
+ case eDataValidationType.Decimal:
+ return new ExcelDataValidationDecimal(worksheet, address, type, itemElementNode);
+ case eDataValidationType.List:
+ return new ExcelDataValidationList(worksheet, address, type, itemElementNode);
+ case eDataValidationType.DateTime:
+ return new ExcelDataValidationDateTime(worksheet, address, type, itemElementNode);
+ case eDataValidationType.Time:
+ return new ExcelDataValidationTime(worksheet, address, type, itemElementNode);
+ case eDataValidationType.Custom:
+ return new ExcelDataValidationCustom(worksheet, address, type, itemElementNode);
+ default:
+ throw new InvalidOperationException("Non supported validationtype: " + type.Type);
+ }
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelDataValidationInt.cs b/AppsheetEpplus/DataValidation/ExcelDataValidationInt.cs
new file mode 100644
index 0000000..8b0c64b
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelDataValidationInt.cs
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Data validation for integer values.
+/// </summary>
+public class ExcelDataValidationInt
+ : ExcelDataValidationWithFormula2<IExcelDataValidationFormulaInt>,
+ IExcelDataValidationInt {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ internal ExcelDataValidationInt(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType)
+ : base(worksheet, address, validationType) {
+ Formula = new ExcelDataValidationFormulaInt(worksheet.NameSpaceManager, TopNode, _formula1Path);
+ Formula2 = new ExcelDataValidationFormulaInt(
+ worksheet.NameSpaceManager,
+ TopNode,
+ _formula2Path);
+ }
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelDataValidationInt(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode)
+ : base(worksheet, address, validationType, itemElementNode) {
+ Formula = new ExcelDataValidationFormulaInt(worksheet.NameSpaceManager, TopNode, _formula1Path);
+ Formula2 = new ExcelDataValidationFormulaInt(
+ worksheet.NameSpaceManager,
+ TopNode,
+ _formula2Path);
+ }
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager">For test purposes</param>
+ internal ExcelDataValidationInt(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(worksheet, address, validationType, itemElementNode, namespaceManager) {
+ Formula = new ExcelDataValidationFormulaInt(NameSpaceManager, TopNode, _formula1Path);
+ Formula2 = new ExcelDataValidationFormulaInt(NameSpaceManager, TopNode, _formula2Path);
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelDataValidationList.cs b/AppsheetEpplus/DataValidation/ExcelDataValidationList.cs
new file mode 100644
index 0000000..0d56dbb
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelDataValidationList.cs
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// This class represents an List data validation.
+/// </summary>
+public class ExcelDataValidationList
+ : ExcelDataValidationWithFormula<IExcelDataValidationFormulaList>,
+ IExcelDataValidationList {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ internal ExcelDataValidationList(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType)
+ : base(worksheet, address, validationType) {
+ Formula = new ExcelDataValidationFormulaList(NameSpaceManager, TopNode, _formula1Path);
+ }
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelDataValidationList(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode)
+ : base(worksheet, address, validationType, itemElementNode) {
+ Formula = new ExcelDataValidationFormulaList(NameSpaceManager, TopNode, _formula1Path);
+ }
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager">Namespace manager, for test purposes</param>
+ internal ExcelDataValidationList(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(worksheet, address, validationType, itemElementNode, namespaceManager) {
+ Formula = new ExcelDataValidationFormulaList(NameSpaceManager, TopNode, _formula1Path);
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelDataValidationOperator.cs b/AppsheetEpplus/DataValidation/ExcelDataValidationOperator.cs
new file mode 100644
index 0000000..7969ca6
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelDataValidationOperator.cs
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Operator for comparison between Formula and Formula2 in a validation.
+/// </summary>
+public enum ExcelDataValidationOperator {
+ Any,
+ Equal,
+ NotEqual,
+ LessThan,
+ LessThanOrEqual,
+ GreaterThan,
+ GreaterThanOrEqual,
+ Between,
+ NotBetween,
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelDataValidationTime.cs b/AppsheetEpplus/DataValidation/ExcelDataValidationTime.cs
new file mode 100644
index 0000000..c8a7081
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelDataValidationTime.cs
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Validation for times (<see cref="OfficeOpenXml.DataValidation.ExcelTime"/>).
+/// </summary>
+public class ExcelDataValidationTime
+ : ExcelDataValidationWithFormula2<IExcelDataValidationFormulaTime>,
+ IExcelDataValidationTime {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ internal ExcelDataValidationTime(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType)
+ : base(worksheet, address, validationType) {
+ Formula = new ExcelDataValidationFormulaTime(NameSpaceManager, TopNode, _formula1Path);
+ Formula2 = new ExcelDataValidationFormulaTime(NameSpaceManager, TopNode, _formula2Path);
+ }
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ /// <param name="itemElementNode"></param>
+ internal ExcelDataValidationTime(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode)
+ : base(worksheet, address, validationType, itemElementNode) {
+ Formula = new ExcelDataValidationFormulaTime(NameSpaceManager, TopNode, _formula1Path);
+ Formula2 = new ExcelDataValidationFormulaTime(NameSpaceManager, TopNode, _formula2Path);
+ }
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ /// <param name="itemElementNode"></param>
+ /// <param name="namespaceManager"></param>
+ internal ExcelDataValidationTime(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(worksheet, address, validationType, itemElementNode, namespaceManager) {
+ Formula = new ExcelDataValidationFormulaTime(NameSpaceManager, TopNode, _formula1Path);
+ Formula2 = new ExcelDataValidationFormulaTime(NameSpaceManager, TopNode, _formula2Path);
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelDataValidationType.cs b/AppsheetEpplus/DataValidation/ExcelDataValidationType.cs
new file mode 100644
index 0000000..bad0745
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelDataValidationType.cs
@@ -0,0 +1,261 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ * Raziq York Added support for Any type 2014-08-08
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Enum for available data validation types
+/// </summary>
+public enum eDataValidationType {
+ /// <summary>
+ /// Any value
+ /// </summary>
+ Any,
+
+ /// <summary>
+ /// Integer value
+ /// </summary>
+ Whole,
+
+ /// <summary>
+ /// Decimal values
+ /// </summary>
+ Decimal,
+
+ /// <summary>
+ /// List of values
+ /// </summary>
+ List,
+
+ /// <summary>
+ /// Text length validation
+ /// </summary>
+ TextLength,
+
+ /// <summary>
+ /// DateTime validation
+ /// </summary>
+ DateTime,
+
+ /// <summary>
+ /// Time validation
+ /// </summary>
+ Time,
+
+ /// <summary>
+ /// Custom validation
+ /// </summary>
+ Custom,
+}
+
+internal static class DataValidationSchemaNames {
+ public const string Any = "";
+ public const string Whole = "whole";
+ public const string Decimal = "decimal";
+ public const string List = "list";
+ public const string TextLength = "textLength";
+ public const string Date = "date";
+ public const string Time = "time";
+ public const string Custom = "custom";
+}
+
+/// <summary>
+/// Types of datavalidation
+/// </summary>
+public class ExcelDataValidationType {
+ private ExcelDataValidationType(
+ eDataValidationType validationType,
+ bool allowOperator,
+ string schemaName) {
+ Type = validationType;
+ AllowOperator = allowOperator;
+ SchemaName = schemaName;
+ }
+
+ /// <summary>
+ /// Validation type
+ /// </summary>
+ public eDataValidationType Type { get; private set; }
+
+ internal string SchemaName { get; private set; }
+
+ /// <summary>
+ /// This type allows operator to be set
+ /// </summary>
+ internal bool AllowOperator { get; private set; }
+
+ internal static ExcelDataValidationType GetBySchemaName(string schemaName) {
+ switch (schemaName) {
+ case DataValidationSchemaNames.Any:
+ return Any;
+ case DataValidationSchemaNames.Whole:
+ return Whole;
+ case DataValidationSchemaNames.Decimal:
+ return Decimal;
+ case DataValidationSchemaNames.List:
+ return List;
+ case DataValidationSchemaNames.TextLength:
+ return TextLength;
+ case DataValidationSchemaNames.Date:
+ return DateTime;
+ case DataValidationSchemaNames.Time:
+ return Time;
+ case DataValidationSchemaNames.Custom:
+ return Custom;
+ default:
+ throw new ArgumentException("Invalid schemaname: " + schemaName);
+ }
+ }
+
+ /// <summary>
+ /// Overridden Equals, compares on internal validation type
+ /// </summary>
+ /// <param name="obj"></param>
+ /// <returns></returns>
+ public override bool Equals(object obj) {
+ if (!(obj is ExcelDataValidationType type)) {
+ return false;
+ }
+ return type.Type == Type;
+ }
+
+ /// <summary>
+ /// Overrides GetHashCode()
+ /// </summary>
+ /// <returns></returns>
+ public override int GetHashCode() {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Integer values
+ /// </summary>
+ private static ExcelDataValidationType _any;
+
+ public static ExcelDataValidationType Any {
+ get {
+ if (_any == null) {
+ _any = new(eDataValidationType.Any, false, DataValidationSchemaNames.Any);
+ }
+ return _any;
+ }
+ }
+
+ /// <summary>
+ /// Integer values
+ /// </summary>
+ private static ExcelDataValidationType _whole;
+
+ public static ExcelDataValidationType Whole {
+ get {
+ if (_whole == null) {
+ _whole = new(eDataValidationType.Whole, true, DataValidationSchemaNames.Whole);
+ }
+ return _whole;
+ }
+ }
+
+ /// <summary>
+ /// List of allowed values
+ /// </summary>
+ private static ExcelDataValidationType _list;
+
+ public static ExcelDataValidationType List {
+ get {
+ if (_list == null) {
+ _list = new(eDataValidationType.List, false, DataValidationSchemaNames.List);
+ }
+ return _list;
+ }
+ }
+
+ private static ExcelDataValidationType _decimal;
+
+ public static ExcelDataValidationType Decimal {
+ get {
+ if (_decimal == null) {
+ _decimal = new(eDataValidationType.Decimal, true, DataValidationSchemaNames.Decimal);
+ }
+ return _decimal;
+ }
+ }
+
+ private static ExcelDataValidationType _textLength;
+
+ public static ExcelDataValidationType TextLength {
+ get {
+ if (_textLength == null) {
+ _textLength = new(
+ eDataValidationType.TextLength,
+ true,
+ DataValidationSchemaNames.TextLength);
+ }
+ return _textLength;
+ }
+ }
+
+ private static ExcelDataValidationType _dateTime;
+
+ public static ExcelDataValidationType DateTime {
+ get {
+ if (_dateTime == null) {
+ _dateTime = new(eDataValidationType.DateTime, true, DataValidationSchemaNames.Date);
+ }
+ return _dateTime;
+ }
+ }
+
+ private static ExcelDataValidationType _time;
+
+ public static ExcelDataValidationType Time {
+ get {
+ if (_time == null) {
+ _time = new(eDataValidationType.Time, true, DataValidationSchemaNames.Time);
+ }
+ return _time;
+ }
+ }
+
+ private static ExcelDataValidationType _custom;
+
+ public static ExcelDataValidationType Custom {
+ get {
+ if (_custom == null) {
+ _custom = new(eDataValidationType.Custom, true, DataValidationSchemaNames.Custom);
+ }
+ return _custom;
+ }
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelDataValidationWarningStyle.cs b/AppsheetEpplus/DataValidation/ExcelDataValidationWarningStyle.cs
new file mode 100644
index 0000000..17ce8dc
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelDataValidationWarningStyle.cs
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// warning style, controls how Excel will handle invalid changes.
+/// </summary>
+public enum ExcelDataValidationWarningStyle {
+ /// <summary>
+ /// warning style will be excluded
+ /// </summary>
+ Undefined,
+
+ /// <summary>
+ /// stop warning style, invalid changes will not be accepted
+ /// </summary>
+ Stop,
+
+ /// <summary>
+ /// warning will be presented when an attempt to an invalid change is done, but the change will be accepted.
+ /// </summary>
+ Warning,
+
+ /// <summary>
+ /// information warning style.
+ /// </summary>
+ Information,
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelDataValidationWithFormula.cs b/AppsheetEpplus/DataValidation/ExcelDataValidationWithFormula.cs
new file mode 100644
index 0000000..27affda
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelDataValidationWithFormula.cs
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// A validation containing a formula
+/// </summary>
+/// <typeparam name="T"></typeparam>
+public class ExcelDataValidationWithFormula<T> : ExcelDataValidation
+ where T : IExcelDataValidationFormula {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ internal ExcelDataValidationWithFormula(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType)
+ : this(worksheet, address, validationType, null) {}
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet">Worksheet that owns the validation</param>
+ /// <param name="itemElementNode">Xml top node (dataValidations)</param>
+ /// <param name="validationType">Data validation type</param>
+ /// <param name="address">address for data validation</param>
+ internal ExcelDataValidationWithFormula(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode)
+ : base(worksheet, address, validationType, itemElementNode) {}
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet">Worksheet that owns the validation</param>
+ /// <param name="itemElementNode">Xml top node (dataValidations)</param>
+ /// <param name="validationType">Data validation type</param>
+ /// <param name="address">address for data validation</param>
+ /// <param name="namespaceManager">for test purposes</param>
+ internal ExcelDataValidationWithFormula(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(worksheet, address, validationType, itemElementNode, namespaceManager) {}
+
+ /// <summary>
+ /// Formula - Either a {T} value (except for custom validation) or a spreadsheet formula
+ /// </summary>
+ public T Formula { get; protected set; }
+
+ public override void Validate() {
+ base.Validate();
+ if (Operator == ExcelDataValidationOperator.Between
+ || Operator == ExcelDataValidationOperator.NotBetween) {
+ if (string.IsNullOrEmpty(Formula2Internal)) {
+ throw new InvalidOperationException(
+ "Validation of "
+ + Address.Address
+ + " failed: Formula2 must be set if operator is 'between' or 'notBetween'");
+ }
+ }
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelDataValidationWithFormula2.cs b/AppsheetEpplus/DataValidation/ExcelDataValidationWithFormula2.cs
new file mode 100644
index 0000000..7b18cb3
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelDataValidationWithFormula2.cs
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+public class ExcelDataValidationWithFormula2<T> : ExcelDataValidationWithFormula<T>
+ where T : IExcelDataValidationFormula {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="address"></param>
+ /// <param name="validationType"></param>
+ internal ExcelDataValidationWithFormula2(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType)
+ : this(worksheet, address, validationType, null) {}
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet">Worksheet that owns the validation</param>
+ /// <param name="itemElementNode">Xml top node (dataValidations)</param>
+ /// <param name="validationType">Data validation type</param>
+ /// <param name="address">address for data validation</param>
+ internal ExcelDataValidationWithFormula2(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode)
+ : base(worksheet, address, validationType, itemElementNode) {}
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet">Worksheet that owns the validation</param>
+ /// <param name="itemElementNode">Xml top node (dataValidations)</param>
+ /// <param name="validationType">Data validation type</param>
+ /// <param name="address">address for data validation</param>
+ /// <param name="namespaceManager">for test purposes</param>
+ internal ExcelDataValidationWithFormula2(
+ ExcelWorksheet worksheet,
+ string address,
+ ExcelDataValidationType validationType,
+ XmlNode itemElementNode,
+ XmlNamespaceManager namespaceManager)
+ : base(worksheet, address, validationType, itemElementNode, namespaceManager) {}
+
+ /// <summary>
+ /// Formula - Either a {T} value or a spreadsheet formula
+ /// </summary>
+ public T Formula2 { get; protected set; }
+}
diff --git a/AppsheetEpplus/DataValidation/ExcelTime.cs b/AppsheetEpplus/DataValidation/ExcelTime.cs
new file mode 100644
index 0000000..7aa6a6e
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/ExcelTime.cs
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Globalization;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Represents a time between 00:00:00 and 23:59:59
+/// </summary>
+public class ExcelTime {
+ private event EventHandler TimeChangedEvent;
+
+ private readonly decimal SecondsPerDay = 3600 * 24;
+ private readonly decimal SecondsPerHour = 3600;
+ private readonly decimal SecondsPerMinute = 60;
+
+ /// <summary>
+ /// Max number of decimals when rounding.
+ /// </summary>
+ public const int NumberOfDecimals = 15;
+
+ /// <summary>
+ /// Default constructor
+ /// </summary>
+ public ExcelTime() {}
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="value">An existing time for initialization</param>
+ public ExcelTime(decimal value) {
+ if (value < 0M) {
+ throw new ArgumentException("Value cannot be less than 0");
+ }
+ if (value >= 1M) {
+ throw new ArgumentException("Value cannot be greater or equal to 1");
+ }
+ Init(value);
+ }
+
+ private void Init(decimal value) {
+ // handle hour
+ decimal totalSeconds = value * SecondsPerDay;
+ decimal hour = Math.Floor(totalSeconds / SecondsPerHour);
+ Hour = (int)hour;
+
+ // handle minute
+ decimal remainingSeconds = totalSeconds - (hour * SecondsPerHour);
+ decimal minute = Math.Floor(remainingSeconds / SecondsPerMinute);
+ Minute = (int)minute;
+
+ // handle second
+ remainingSeconds = totalSeconds - (hour * SecondsPerHour) - (minute * SecondsPerMinute);
+ decimal second = Math.Round(remainingSeconds, MidpointRounding.AwayFromZero);
+ // Second might be rounded to 60... the SetSecond method handles that.
+ SetSecond((int)second);
+ }
+
+ /// <summary>
+ /// If we are unlucky second might be rounded up to 60. This will have the minute to be raised and might affect the hour.
+ /// </summary>
+ /// <param name="value"></param>
+ private void SetSecond(int value) {
+ if (value == 60) {
+ Second = 0;
+ var minute = Minute + 1;
+ SetMinute(minute);
+ } else {
+ Second = value;
+ }
+ }
+
+ private void SetMinute(int value) {
+ if (value == 60) {
+ Minute = 0;
+ var hour = Hour + 1;
+ SetHour(hour);
+ } else {
+ Minute = value;
+ }
+ }
+
+ private void SetHour(int value) {
+ if (value == 24) {
+ Hour = 0;
+ }
+ }
+
+ internal event EventHandler TimeChanged {
+ add => TimeChangedEvent += value;
+ remove => TimeChangedEvent -= value;
+ }
+
+ private void OnTimeChanged() {
+ if (TimeChangedEvent != null) {
+ TimeChangedEvent(this, EventArgs.Empty);
+ }
+ }
+
+ private int _hour;
+
+ /// <summary>
+ /// Hour between 0 and 23
+ /// </summary>
+ public int Hour {
+ get => _hour;
+ set {
+ if (value < 0) {
+ throw new InvalidOperationException("Value for hour cannot be negative");
+ }
+ if (value > 23) {
+ throw new InvalidOperationException("Value for hour cannot be greater than 23");
+ }
+ _hour = value;
+ OnTimeChanged();
+ }
+ }
+
+ private int _minute;
+
+ /// <summary>
+ /// Minute between 0 and 59
+ /// </summary>
+ public int Minute {
+ get => _minute;
+ set {
+ if (value < 0) {
+ throw new InvalidOperationException("Value for minute cannot be negative");
+ }
+ if (value > 59) {
+ throw new InvalidOperationException("Value for minute cannot be greater than 59");
+ }
+ _minute = value;
+ OnTimeChanged();
+ }
+ }
+
+ private int? _second;
+
+ /// <summary>
+ /// Second between 0 and 59
+ /// </summary>
+ public int? Second {
+ get => _second;
+ set {
+ if (value < 0) {
+ throw new InvalidOperationException("Value for second cannot be negative");
+ }
+ if (value > 59) {
+ throw new InvalidOperationException("Value for second cannot be greater than 59");
+ }
+ _second = value;
+ OnTimeChanged();
+ }
+ }
+
+ private decimal Round(decimal value) {
+ return Math.Round(value, NumberOfDecimals);
+ }
+
+ private decimal ToSeconds() {
+ var result = Hour * SecondsPerHour;
+ result += Minute * SecondsPerMinute;
+ result += Second ?? 0;
+ return result;
+ }
+
+ /// <summary>
+ /// Returns the excel decimal representation of a time.
+ /// </summary>
+ /// <returns></returns>
+ public decimal ToExcelTime() {
+ var seconds = ToSeconds();
+ return Round(seconds / SecondsPerDay);
+ }
+
+ /// <summary>
+ /// Returns the excel decimal representation of a time as a string.
+ /// </summary>
+ /// <returns></returns>
+ public string ToExcelString() {
+ return ToExcelTime().ToString(CultureInfo.InvariantCulture);
+ }
+
+ public override string ToString() {
+ var second = Second ?? 0;
+ return string.Format(
+ "{0}:{1}:{2}",
+ Hour < 10 ? "0" + Hour : Hour.ToString(),
+ Minute < 10 ? "0" + Minute : Minute.ToString(),
+ second < 10 ? "0" + second : second.ToString());
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormula.cs b/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormula.cs
new file mode 100644
index 0000000..206c5fe
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormula.cs
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Interface for a data validation formula
+/// </summary>
+public interface IExcelDataValidationFormula {
+ /// <summary>
+ /// An excel formula
+ /// </summary>
+ string ExcelFormula { get; set; }
+}
diff --git a/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDateTime.cs b/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDateTime.cs
new file mode 100644
index 0000000..c15a609
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDateTime.cs
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Validation formula interface for <see cref="DateTime"/>
+/// </summary>
+public interface IExcelDataValidationFormulaDateTime
+ : IExcelDataValidationFormulaWithValue<DateTime?> {}
diff --git a/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDecimal.cs b/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDecimal.cs
new file mode 100644
index 0000000..19a9cc2
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDecimal.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Interface for a data validation formula of <see cref="System.Single">float</see> value
+/// </summary>
+public interface IExcelDataValidationFormulaDecimal
+ : IExcelDataValidationFormulaWithValue<double?> {}
diff --git a/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaInt.cs b/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaInt.cs
new file mode 100644
index 0000000..fb13e17
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaInt.cs
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Interface for a data validation formula of <see cref="System.Int32"/> value
+/// </summary>
+public interface IExcelDataValidationFormulaInt : IExcelDataValidationFormulaWithValue<int?> {}
diff --git a/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaList.cs b/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaList.cs
new file mode 100644
index 0000000..d827f9e
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaList.cs
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Interface for a data validation of list type
+/// </summary>
+public interface IExcelDataValidationFormulaList : IExcelDataValidationFormula {
+ /// <summary>
+ /// A list of value strings.
+ /// </summary>
+ IList<string> Values { get; }
+}
diff --git a/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaTime.cs b/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaTime.cs
new file mode 100644
index 0000000..1e27a6d
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaTime.cs
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public interface IExcelDataValidationFormulaTime
+ : IExcelDataValidationFormulaWithValue<ExcelTime> {}
diff --git a/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaWithValue.cs b/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaWithValue.cs
new file mode 100644
index 0000000..f508bec
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaWithValue.cs
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Interface for a formula with a value
+/// </summary>
+/// <typeparam name="T"></typeparam>
+public interface IExcelDataValidationFormulaWithValue<T> : IExcelDataValidationFormula {
+ /// <summary>
+ /// The value.
+ /// </summary>
+ T Value { get; set; }
+}
diff --git a/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormula.cs b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormula.cs
new file mode 100644
index 0000000..8554d5b
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormula.cs
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Enumeration representing the state of an <see cref="ExcelDataValidationFormulaValue{T}"/>
+/// </summary>
+internal enum FormulaState {
+ /// <summary>
+ /// Value is set
+ /// </summary>
+ Value,
+
+ /// <summary>
+ /// Formula is set
+ /// </summary>
+ Formula,
+}
+
+/// <summary>
+/// Base class for a formula
+/// </summary>
+internal abstract class ExcelDataValidationFormula : XmlHelper {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="namespaceManager">Namespacemanger of the worksheet</param>
+ /// <param name="topNode">validation top node</param>
+ /// <param name="formulaPath">xml path of the current formula</param>
+ public ExcelDataValidationFormula(
+ XmlNamespaceManager namespaceManager,
+ XmlNode topNode,
+ string formulaPath)
+ : base(namespaceManager, topNode) {
+ ArgumentException.ThrowIfNullOrEmpty(formulaPath);
+ FormulaPath = formulaPath;
+ }
+
+ private string _formula;
+
+ protected string FormulaPath { get; private set; }
+
+ /// <summary>
+ /// State of the validationformula, i.e. tells if value or formula is set
+ /// </summary>
+ protected FormulaState State { get; set; }
+
+ /// <summary>
+ /// A formula which output must match the current validation type
+ /// </summary>
+ public string ExcelFormula {
+ get => _formula;
+ set {
+ if (!string.IsNullOrEmpty(value)) {
+ ResetValue();
+ State = FormulaState.Formula;
+ }
+ if (value != null && value.Length > 255) {
+ throw new InvalidOperationException(
+ "The length of a DataValidation formula cannot exceed 255 characters");
+ }
+ //var val = SqRefUtility.ToSqRefAddress(value);
+ _formula = value;
+ SetXmlNodeString(FormulaPath, value);
+ }
+ }
+
+ internal abstract void ResetValue();
+
+ /// <summary>
+ /// This value will be stored in the xml. Can be overridden by subclasses
+ /// </summary>
+ internal virtual string GetXmlValue() {
+ if (State == FormulaState.Formula) {
+ return ExcelFormula;
+ }
+ return GetValueAsString();
+ }
+
+ /// <summary>
+ /// Returns the value as a string. Must be implemented by subclasses
+ /// </summary>
+ /// <returns></returns>
+ protected abstract string GetValueAsString();
+}
diff --git a/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaCustom.cs b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaCustom.cs
new file mode 100644
index 0000000..7f01bd9
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaCustom.cs
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+///
+/// </summary>
+internal class ExcelDataValidationFormulaCustom
+ : ExcelDataValidationFormula,
+ IExcelDataValidationFormula {
+ public ExcelDataValidationFormulaCustom(
+ XmlNamespaceManager namespaceManager,
+ XmlNode topNode,
+ string formulaPath)
+ : base(namespaceManager, topNode, formulaPath) {
+ var value = GetXmlNodeString(formulaPath);
+ if (!string.IsNullOrEmpty(value)) {
+ ExcelFormula = value;
+ }
+ State = FormulaState.Formula;
+ }
+
+ internal override string GetXmlValue() {
+ return ExcelFormula;
+ }
+
+ protected override string GetValueAsString() {
+ return ExcelFormula;
+ }
+
+ internal override void ResetValue() {
+ ExcelFormula = null;
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaDateTime.cs b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaDateTime.cs
new file mode 100644
index 0000000..3c6e6a1
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaDateTime.cs
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+internal class ExcelDataValidationFormulaDateTime
+ : ExcelDataValidationFormulaValue<DateTime?>,
+ IExcelDataValidationFormulaDateTime {
+ public ExcelDataValidationFormulaDateTime(
+ XmlNamespaceManager namespaceManager,
+ XmlNode topNode,
+ string formulaPath)
+ : base(namespaceManager, topNode, formulaPath) {
+ var value = GetXmlNodeString(formulaPath);
+ if (!string.IsNullOrEmpty(value)) {
+ if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var oADate)) {
+ Value = DateTime.FromOADate(oADate);
+ } else {
+ ExcelFormula = value;
+ }
+ }
+ }
+
+ protected override string GetValueAsString() {
+ return Value.HasValue
+ ? Value.Value.ToOADate().ToString(CultureInfo.InvariantCulture)
+ : string.Empty;
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaDecimal.cs b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaDecimal.cs
new file mode 100644
index 0000000..cfdc5fe
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaDecimal.cs
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+///
+/// </summary>
+internal class ExcelDataValidationFormulaDecimal
+ : ExcelDataValidationFormulaValue<double?>,
+ IExcelDataValidationFormulaDecimal {
+ public ExcelDataValidationFormulaDecimal(
+ XmlNamespaceManager namespaceManager,
+ XmlNode topNode,
+ string formulaPath)
+ : base(namespaceManager, topNode, formulaPath) {
+ var value = GetXmlNodeString(formulaPath);
+ if (!string.IsNullOrEmpty(value)) {
+ if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var dValue)) {
+ Value = dValue;
+ } else {
+ ExcelFormula = value;
+ }
+ }
+ }
+
+ protected override string GetValueAsString() {
+ return Value.HasValue
+ ? Value.Value.ToString("R15", CultureInfo.InvariantCulture)
+ : string.Empty;
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaInt.cs b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaInt.cs
new file mode 100644
index 0000000..0d6f916
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaInt.cs
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+internal class ExcelDataValidationFormulaInt
+ : ExcelDataValidationFormulaValue<int?>,
+ IExcelDataValidationFormulaInt {
+ public ExcelDataValidationFormulaInt(
+ XmlNamespaceManager namespaceManager,
+ XmlNode topNode,
+ string formulaPath)
+ : base(namespaceManager, topNode, formulaPath) {
+ var value = GetXmlNodeString(formulaPath);
+ if (!string.IsNullOrEmpty(value)) {
+ if (int.TryParse(value, out var intValue)) {
+ Value = intValue;
+ } else {
+ ExcelFormula = value;
+ }
+ }
+ }
+
+ protected override string GetValueAsString() {
+ return Value.HasValue ? Value.Value.ToString() : string.Empty;
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaList.cs b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaList.cs
new file mode 100644
index 0000000..8bff939
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaList.cs
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+internal class ExcelDataValidationFormulaList
+ : ExcelDataValidationFormula,
+ IExcelDataValidationFormulaList {
+ private class DataValidationList : IList<string>, ICollection {
+ private readonly IList<string> _items = new List<string>();
+ private EventHandler<EventArgs> _listChanged;
+
+ public event EventHandler<EventArgs> ListChanged {
+ add => _listChanged += value;
+ remove => _listChanged -= value;
+ }
+
+ private void OnListChanged() {
+ if (_listChanged != null) {
+ _listChanged(this, EventArgs.Empty);
+ }
+ }
+
+ int IList<string>.IndexOf(string item) {
+ return _items.IndexOf(item);
+ }
+
+ void IList<string>.Insert(int index, string item) {
+ _items.Insert(index, item);
+ OnListChanged();
+ }
+
+ void IList<string>.RemoveAt(int index) {
+ _items.RemoveAt(index);
+ OnListChanged();
+ }
+
+ string IList<string>.this[int index] {
+ get => _items[index];
+ set {
+ _items[index] = value;
+ OnListChanged();
+ }
+ }
+
+ void ICollection<string>.Add(string item) {
+ _items.Add(item);
+ OnListChanged();
+ }
+
+ void ICollection<string>.Clear() {
+ _items.Clear();
+ OnListChanged();
+ }
+
+ bool ICollection<string>.Contains(string item) {
+ return _items.Contains(item);
+ }
+
+ void ICollection<string>.CopyTo(string[] array, int arrayIndex) {
+ _items.CopyTo(array, arrayIndex);
+ }
+
+ int ICollection<string>.Count => _items.Count;
+
+ bool ICollection<string>.IsReadOnly => false;
+
+ bool ICollection<string>.Remove(string item) {
+ var retVal = _items.Remove(item);
+ OnListChanged();
+ return retVal;
+ }
+
+ IEnumerator<string> IEnumerable<string>.GetEnumerator() {
+ return _items.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _items.GetEnumerator();
+ }
+
+ public void CopyTo(Array array, int index) {
+ _items.CopyTo((string[])array, index);
+ }
+
+ int ICollection.Count => _items.Count;
+
+ public bool IsSynchronized => ((ICollection)_items).IsSynchronized;
+
+ public object SyncRoot => ((ICollection)_items).SyncRoot;
+ }
+
+ public ExcelDataValidationFormulaList(
+ XmlNamespaceManager namespaceManager,
+ XmlNode itemNode,
+ string formulaPath)
+ : base(namespaceManager, itemNode, formulaPath) {
+ ArgumentException.ThrowIfNullOrEmpty(formulaPath);
+ _formulaPath = formulaPath;
+ var values = new DataValidationList();
+ values.ListChanged += values_ListChanged;
+ Values = values;
+ SetInitialValues();
+ }
+
+ private readonly string _formulaPath;
+
+ private void SetInitialValues() {
+ var value = GetXmlNodeString(_formulaPath);
+ if (!string.IsNullOrEmpty(value)) {
+ if (value.StartsWith("\"") && value.EndsWith("\"")) {
+ value = value.TrimStart('"').TrimEnd('"');
+ var items = value.Split([','], StringSplitOptions.RemoveEmptyEntries);
+ foreach (var item in items) {
+ Values.Add(item);
+ }
+ } else {
+ ExcelFormula = value;
+ }
+ }
+ }
+
+ private void values_ListChanged(object sender, EventArgs e) {
+ if (Values.Count > 0) {
+ State = FormulaState.Value;
+ }
+ var valuesAsString = GetValueAsString();
+ // Excel supports max 255 characters in this field.
+ if (valuesAsString.Length > 255) {
+ throw new InvalidOperationException(
+ "The total length of a DataValidation list cannot exceed 255 characters");
+ }
+ SetXmlNodeString(_formulaPath, valuesAsString);
+ }
+
+ public IList<string> Values { get; private set; }
+
+ protected override string GetValueAsString() {
+ var sb = new StringBuilder();
+ foreach (var val in Values) {
+ if (sb.Length == 0) {
+ sb.Append("\"");
+ sb.Append(val);
+ } else {
+ sb.AppendFormat(",{0}", val);
+ }
+ }
+ sb.Append("\"");
+ return sb.ToString();
+ }
+
+ internal override void ResetValue() {
+ Values.Clear();
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaTime.cs b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaTime.cs
new file mode 100644
index 0000000..eb864e9
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaTime.cs
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+internal class ExcelDataValidationFormulaTime
+ : ExcelDataValidationFormulaValue<ExcelTime>,
+ IExcelDataValidationFormulaTime {
+ public ExcelDataValidationFormulaTime(
+ XmlNamespaceManager namespaceManager,
+ XmlNode topNode,
+ string formulaPath)
+ : base(namespaceManager, topNode, formulaPath) {
+ var value = GetXmlNodeString(formulaPath);
+ if (!string.IsNullOrEmpty(value)) {
+ if (decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var time)) {
+ Value = new(time);
+ } else {
+ Value = new();
+ ExcelFormula = value;
+ }
+ } else {
+ Value = new();
+ }
+ Value.TimeChanged += Value_TimeChanged;
+ }
+
+ private void Value_TimeChanged(object sender, EventArgs e) {
+ SetXmlNodeString(FormulaPath, Value.ToExcelString());
+ }
+
+ protected override string GetValueAsString() {
+ if (State == FormulaState.Value) {
+ return Value.ToExcelString();
+ }
+ return string.Empty;
+ }
+
+ internal override void ResetValue() {
+ Value = new();
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaValue.cs b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaValue.cs
new file mode 100644
index 0000000..c7194d8
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/Formulas/ExcelDataValidationFormulaValue.cs
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-08
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// This class represents a validation formula. Its value can be specified as a value of the specified datatype or as a formula.
+/// </summary>
+/// <typeparam name="T"></typeparam>
+internal abstract class ExcelDataValidationFormulaValue<T> : ExcelDataValidationFormula {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="namespaceManager">Namespacemanger of the worksheet</param>
+ /// <param name="topNode">validation top node</param>
+ /// <param name="formulaPath">xml path of the current formula</param>
+ public ExcelDataValidationFormulaValue(
+ XmlNamespaceManager namespaceManager,
+ XmlNode topNode,
+ string formulaPath)
+ : base(namespaceManager, topNode, formulaPath) {}
+
+ private T _value;
+
+ /// <summary>
+ /// Typed value
+ /// </summary>
+ public T Value {
+ get => _value;
+ set {
+ State = FormulaState.Value;
+ _value = value;
+ SetXmlNodeString(FormulaPath, GetValueAsString());
+ }
+ }
+
+ internal override void ResetValue() {
+ Value = default(T);
+ }
+}
diff --git a/AppsheetEpplus/DataValidation/IRangeDataValidation.cs b/AppsheetEpplus/DataValidation/IRangeDataValidation.cs
new file mode 100644
index 0000000..b34d626
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/IRangeDataValidation.cs
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-03-23
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Provides functionality for adding datavalidation to a range (<see cref="ExcelRangeBase"/>). Each method will
+/// return a configurable validation.
+/// </summary>
+public interface IRangeDataValidation {
+ /// <summary>
+ /// Adds a <see cref="IExcelDataValidationAny"/> to the range.
+ /// </summary>
+ /// <returns>A <see cref="ExcelDataValidationAny"/> that can be configured for any validation</returns>
+ IExcelDataValidationAny AddAnyDataValidation();
+
+ /// <summary>
+ /// Adds a <see cref="IExcelDataValidationInt"/> to the range
+ /// </summary>
+ /// <returns>A <see cref="ExcelDataValidationInt"/> that can be configured for integer data validation</returns>
+ IExcelDataValidationInt AddIntegerDataValidation();
+
+ /// <summary>
+ /// Adds a <see cref="ExcelDataValidationDecimal"/> to the range
+ /// </summary>
+ /// <returns>A <see cref="ExcelDataValidationDecimal"/> that can be configured for decimal data validation</returns>
+ IExcelDataValidationDecimal AddDecimalDataValidation();
+
+ /// <summary>
+ /// Adds a <see cref="ExcelDataValidationDateTime"/> to the range
+ /// </summary>
+ /// <returns>A <see cref="ExcelDataValidationDecimal"/> that can be configured for datetime data validation</returns>
+ IExcelDataValidationDateTime AddDateTimeDataValidation();
+
+ /// <summary>
+ /// Adds a <see cref="IExcelDataValidationList"/> to the range
+ /// </summary>
+ /// <returns>A <see cref="ExcelDataValidationList"/> that can be configured for datetime data validation</returns>
+ IExcelDataValidationList AddListDataValidation();
+
+ /// <summary>
+ /// Adds a <see cref="IExcelDataValidationInt"/> regarding text length validation to the range.
+ /// </summary>
+ /// <returns></returns>
+ IExcelDataValidationInt AddTextLengthDataValidation();
+
+ /// <summary>
+ /// Adds a <see cref="IExcelDataValidationTime"/> to the range.
+ /// </summary>
+ /// <returns>A <see cref="IExcelDataValidationTime"/> that can be configured for time data validation</returns>
+ IExcelDataValidationTime AddTimeDataValidation();
+
+ /// <summary>
+ /// Adds a <see cref="IExcelDataValidationCustom"/> to the range.
+ /// </summary>
+ /// <returns>A <see cref="IExcelDataValidationCustom"/> that can be configured for custom validation</returns>
+ IExcelDataValidationCustom AddCustomDataValidation();
+}
diff --git a/AppsheetEpplus/DataValidation/RangeDataValidation.cs b/AppsheetEpplus/DataValidation/RangeDataValidation.cs
new file mode 100644
index 0000000..48f6f21
--- /dev/null
+++ b/AppsheetEpplus/DataValidation/RangeDataValidation.cs
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-03-23
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+internal class RangeDataValidation : IRangeDataValidation {
+ public RangeDataValidation(ExcelWorksheet worksheet, string address) {
+ ArgumentNullException.ThrowIfNull(worksheet);
+ ArgumentException.ThrowIfNullOrEmpty(address);
+ _worksheet = worksheet;
+ _address = address;
+ }
+
+ private readonly ExcelWorksheet _worksheet;
+ private readonly string _address;
+
+ public IExcelDataValidationAny AddAnyDataValidation() {
+ return _worksheet.DataValidations.AddAnyValidation(_address);
+ }
+
+ public IExcelDataValidationInt AddIntegerDataValidation() {
+ return _worksheet.DataValidations.AddIntegerValidation(_address);
+ }
+
+ public IExcelDataValidationDecimal AddDecimalDataValidation() {
+ return _worksheet.DataValidations.AddDecimalValidation(_address);
+ }
+
+ public IExcelDataValidationDateTime AddDateTimeDataValidation() {
+ return _worksheet.DataValidations.AddDateTimeValidation(_address);
+ }
+
+ public IExcelDataValidationList AddListDataValidation() {
+ return _worksheet.DataValidations.AddListValidation(_address);
+ }
+
+ public IExcelDataValidationInt AddTextLengthDataValidation() {
+ return _worksheet.DataValidations.AddTextLengthValidation(_address);
+ }
+
+ public IExcelDataValidationTime AddTimeDataValidation() {
+ return _worksheet.DataValidations.AddTimeValidation(_address);
+ }
+
+ public IExcelDataValidationCustom AddCustomDataValidation() {
+ return _worksheet.DataValidations.AddCustomValidation(_address);
+ }
+}
diff --git a/AppsheetEpplus/Drawing/Vml/ExcelVmlDrawingBase.cs b/AppsheetEpplus/Drawing/Vml/ExcelVmlDrawingBase.cs
new file mode 100644
index 0000000..0ab4392
--- /dev/null
+++ b/AppsheetEpplus/Drawing/Vml/ExcelVmlDrawingBase.cs
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * 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 Initial Release 2010-06-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System.Collections.Immutable;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Horizontal Alingment
+/// </summary>
+public enum eTextAlignHorizontalVml {
+ Left,
+ Center,
+ Right,
+}
+
+/// <summary>
+/// Vertical Alingment
+/// </summary>
+public enum eTextAlignVerticalVml {
+ Top,
+ Center,
+ Bottom,
+}
+
+/// <summary>
+/// Linestyle
+/// </summary>
+public enum eLineStyleVml {
+ Solid,
+ Round,
+ Square,
+ Dash,
+ DashDot,
+ LongDash,
+ LongDashDot,
+ LongDashDotDot,
+}
+
+/// <summary>
+/// Drawing object used for comments
+/// </summary>
+public class ExcelVmlDrawingBase : XmlHelper {
+ protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
+ "fill",
+ "stroke",
+ "shadow",
+ "path",
+ "textbox",
+ "ClientData",
+ "MoveWithCells",
+ "SizeWithCells",
+ "Anchor",
+ "Locked",
+ "AutoFill",
+ "LockText",
+ "TextHAlign",
+ "TextVAlign",
+ "Row",
+ "Column",
+ "Visible",
+ ];
+
+ internal ExcelVmlDrawingBase(XmlNode topNode, XmlNamespaceManager ns)
+ : base(ns, topNode) {}
+
+ public string Id {
+ get => GetXmlNodeString("@id");
+ set => SetXmlNodeString("@id", value);
+ }
+
+ /// <summary>
+ /// Alternative text to be displayed instead of a graphic.
+ /// </summary>
+ public string AlternativeText {
+ get => GetXmlNodeString("@alt");
+ set => SetXmlNodeString("@alt", value);
+ }
+
+ protected bool GetStyle(string style, string key, out string value) {
+ string[] styles = style.Split(';');
+ foreach (string s in styles) {
+ if (s.IndexOf(':') > 0) {
+ string[] split = s.Split(':');
+ if (split[0] == key) {
+ value = split[1];
+ return true;
+ }
+ } else if (s == key) {
+ value = "";
+ return true;
+ }
+ }
+ value = "";
+ return false;
+ }
+
+ protected string SetStyle(string style, string key, string value) {
+ string[] styles = style.Split(';');
+ string newStyle = "";
+ bool changed = false;
+ foreach (string s in styles) {
+ string[] split = s.Split(':');
+ if (split[0].Trim() == key) {
+ if (value.Trim()
+ != "") //If blank remove the item
+ {
+ newStyle += key + ':' + value;
+ }
+ changed = true;
+ } else {
+ newStyle += s;
+ }
+ newStyle += ';';
+ }
+ if (!changed) {
+ newStyle += key + ':' + value;
+ } else {
+ newStyle = style.Substring(0, style.Length - 1);
+ }
+ return newStyle;
+ }
+}
diff --git a/AppsheetEpplus/Drawing/Vml/ExcelVmlDrawingBaseCollection.cs b/AppsheetEpplus/Drawing/Vml/ExcelVmlDrawingBaseCollection.cs
new file mode 100644
index 0000000..03d0e22
--- /dev/null
+++ b/AppsheetEpplus/Drawing/Vml/ExcelVmlDrawingBaseCollection.cs
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * 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 Initial Release 2010-06-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+public class ExcelVmlDrawingBaseCollection {
+ internal ExcelVmlDrawingBaseCollection(ExcelPackage pck, ExcelWorksheet ws, Uri uri) {
+ VmlDrawingXml.PreserveWhitespace = false;
+
+ NameTable nt = new NameTable();
+ NameSpaceManager = new(nt);
+ NameSpaceManager.AddNamespace("v", ExcelPackage._schemaMicrosoftVml);
+ NameSpaceManager.AddNamespace("o", ExcelPackage._schemaMicrosoftOffice);
+ NameSpaceManager.AddNamespace("x", ExcelPackage._schemaMicrosoftExcel);
+ Uri = uri;
+ if (uri == null) {
+ Part = null;
+ } else {
+ Part = pck.Package.GetPart(uri);
+ XmlHelper.LoadXmlSafe(VmlDrawingXml, Part.GetStream());
+ }
+ }
+
+ internal XmlDocument VmlDrawingXml { get; set; } = new();
+
+ internal Uri Uri { get; set; }
+ internal string RelId { get; set; }
+ internal ZipPackagePart Part { get; set; }
+ internal XmlNamespaceManager NameSpaceManager { get; set; }
+}
diff --git a/AppsheetEpplus/Drawing/Vml/ExcelVmlDrawingComment.cs b/AppsheetEpplus/Drawing/Vml/ExcelVmlDrawingComment.cs
new file mode 100644
index 0000000..51c1b2c
--- /dev/null
+++ b/AppsheetEpplus/Drawing/Vml/ExcelVmlDrawingComment.cs
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * 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 Initial Release 2010-06-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System.Collections.Immutable;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Drawing object used for comments
+/// </summary>
+public class ExcelVmlDrawingComment : ExcelVmlDrawingBase, IRangeId {
+ protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
+ "fill",
+ "stroke",
+ "shadow",
+ "path",
+ "textbox",
+ "ClientData",
+ "MoveWithCells",
+ "SizeWithCells",
+ "Anchor",
+ "Locked",
+ "AutoFill",
+ "LockText",
+ "TextHAlign",
+ "TextVAlign",
+ "Row",
+ "Column",
+ "Visible",
+ ];
+
+ internal ExcelVmlDrawingComment(XmlNode topNode, ExcelRangeBase range, XmlNamespaceManager ns)
+ : base(topNode, ns) {
+ Range = range;
+ }
+
+ internal ExcelRangeBase Range { get; set; }
+
+ /// <summary>
+ /// Address in the worksheet
+ /// </summary>
+ public string Address => Range.Address;
+
+ private const string _verticalAlignmentPath = "x:ClientData/x:TextVAlign";
+
+ /// <summary>
+ /// Vertical alignment for text
+ /// </summary>
+ public eTextAlignVerticalVml VerticalAlignment {
+ get {
+ switch (GetXmlNodeString(_verticalAlignmentPath)) {
+ case "Center":
+ return eTextAlignVerticalVml.Center;
+ case "Bottom":
+ return eTextAlignVerticalVml.Bottom;
+ default:
+ return eTextAlignVerticalVml.Top;
+ }
+ }
+ set {
+ switch (value) {
+ case eTextAlignVerticalVml.Center:
+ SetXmlNodeString(_verticalAlignmentPath, "Center");
+ break;
+ case eTextAlignVerticalVml.Bottom:
+ SetXmlNodeString(_verticalAlignmentPath, "Bottom");
+ break;
+ default:
+ DeleteNode(_verticalAlignmentPath);
+ break;
+ }
+ }
+ }
+
+ private const string _horizontalAlignmentPath = "x:ClientData/x:TextHAlign";
+
+ /// <summary>
+ /// Horizontal alignment for text
+ /// </summary>
+ public eTextAlignHorizontalVml HorizontalAlignment {
+ get {
+ switch (GetXmlNodeString(_horizontalAlignmentPath)) {
+ case "Center":
+ return eTextAlignHorizontalVml.Center;
+ case "Right":
+ return eTextAlignHorizontalVml.Right;
+ default:
+ return eTextAlignHorizontalVml.Left;
+ }
+ }
+ set {
+ switch (value) {
+ case eTextAlignHorizontalVml.Center:
+ SetXmlNodeString(_horizontalAlignmentPath, "Center");
+ break;
+ case eTextAlignHorizontalVml.Right:
+ SetXmlNodeString(_horizontalAlignmentPath, "Right");
+ break;
+ default:
+ DeleteNode(_horizontalAlignmentPath);
+ break;
+ }
+ }
+ }
+
+ private const string _visiblePath = "x:ClientData/x:Visible";
+
+ /// <summary>
+ /// If the drawing object is visible.
+ /// </summary>
+ public bool Visible {
+ get => (TopNode.SelectSingleNode(_visiblePath, NameSpaceManager) != null);
+ set {
+ if (value) {
+ CreateNode(_visiblePath);
+ Style = SetStyle(Style, "visibility", "visible");
+ } else {
+ DeleteNode(_visiblePath);
+ Style = SetStyle(Style, "visibility", "hidden");
+ }
+ }
+ }
+
+ private const string _textboxStylePath = "v:textbox/@style";
+
+ /// <summary>
+ /// Autofits the drawingobject
+ /// </summary>
+ public bool AutoFit {
+ get {
+ GetStyle(GetXmlNodeString(_textboxStylePath), "mso-fit-shape-to-text", out var value);
+ return value == "t";
+ }
+ set =>
+ SetXmlNodeString(
+ _textboxStylePath,
+ SetStyle(GetXmlNodeString(_textboxStylePath), "mso-fit-shape-to-text", value ? "t" : ""));
+ }
+
+ private const string _lockedPath = "x:ClientData/x:Locked";
+
+ /// <summary>
+ /// If the object is locked when the sheet is protected
+ /// </summary>
+ public bool Locked {
+ get => GetXmlNodeBool(_lockedPath, false);
+ set => SetXmlNodeBool(_lockedPath, value, false);
+ }
+
+ private const string _lockTextPath = "x:ClientData/x:LockText";
+
+ /// <summary>
+ /// Specifies that the object's text is locked
+ /// </summary>
+ public bool LockText {
+ get => GetXmlNodeBool(_lockTextPath, false);
+ set => SetXmlNodeBool(_lockTextPath, value, false);
+ }
+
+ private ExcelVmlDrawingPosition _from;
+
+ /// <summary>
+ /// From position. For comments only when Visible=true.
+ /// </summary>
+ public ExcelVmlDrawingPosition From {
+ get {
+ if (_from == null) {
+ _from = new(
+ NameSpaceManager,
+ TopNode.SelectSingleNode("x:ClientData", NameSpaceManager),
+ 0);
+ }
+ return _from;
+ }
+ }
+
+ private ExcelVmlDrawingPosition _to;
+
+ /// <summary>
+ /// To position. For comments only when Visible=true.
+ /// </summary>
+ public ExcelVmlDrawingPosition To {
+ get {
+ if (_to == null) {
+ _to = new(NameSpaceManager, TopNode.SelectSingleNode("x:ClientData", NameSpaceManager), 4);
+ }
+ return _to;
+ }
+ }
+
+ private const string _stylePath = "@style";
+
+ internal string Style {
+ get => GetXmlNodeString(_stylePath);
+ set => SetXmlNodeString(_stylePath, value);
+ }
+
+ ulong IRangeId.RangeID {
+ get => ExcelCellBase.GetCellId(Range.Worksheet.SheetID, Range.Start.Row, Range.Start.Column);
+ set {}
+ }
+}
diff --git a/AppsheetEpplus/Drawing/Vml/ExcelVmlDrawingCommentCollection.cs b/AppsheetEpplus/Drawing/Vml/ExcelVmlDrawingCommentCollection.cs
new file mode 100644
index 0000000..193505c
--- /dev/null
+++ b/AppsheetEpplus/Drawing/Vml/ExcelVmlDrawingCommentCollection.cs
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * 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 Initial Release 2010-06-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+internal class ExcelVmlDrawingCommentCollection : ExcelVmlDrawingBaseCollection, IEnumerable {
+ internal RangeCollection _drawings;
+
+ internal ExcelVmlDrawingCommentCollection(ExcelPackage pck, ExcelWorksheet ws, Uri uri)
+ : base(pck, ws, uri) {
+ if (uri == null) {
+ VmlDrawingXml.LoadXml(CreateVmlDrawings());
+ _drawings = new([]);
+ } else {
+ AddDrawingsFromXml(ws);
+ }
+ }
+
+ protected void AddDrawingsFromXml(ExcelWorksheet ws) {
+ var nodes = VmlDrawingXml.SelectNodes("//v:shape", NameSpaceManager);
+ var list = new List<IRangeId>();
+ foreach (XmlNode node in nodes) {
+ var rowNode = node.SelectSingleNode("x:ClientData/x:Row", NameSpaceManager);
+ var colNode = node.SelectSingleNode("x:ClientData/x:Column", NameSpaceManager);
+ if (rowNode != null && colNode != null) {
+ var row = int.Parse(rowNode.InnerText) + 1;
+ var col = int.Parse(colNode.InnerText) + 1;
+ list.Add(new ExcelVmlDrawingComment(node, ws.Cells[row, col], NameSpaceManager));
+ } else {
+ list.Add(new ExcelVmlDrawingComment(node, ws.Cells[1, 1], NameSpaceManager));
+ }
+ }
+ list.Sort((r1, r2) =>
+ (r1.RangeID < r2.RangeID
+ ? -1
+ : r1.RangeID > r2.RangeID
+ ? 1
+ : 0)); //Vml drawings are not sorted. Sort to avoid missmatches.
+ _drawings = new(list);
+ }
+
+ private string CreateVmlDrawings() {
+ string vml = string.Format(
+ "<xml xmlns:v=\"{0}\" xmlns:o=\"{1}\" xmlns:x=\"{2}\">",
+ ExcelPackage._schemaMicrosoftVml,
+ ExcelPackage._schemaMicrosoftOffice,
+ ExcelPackage._schemaMicrosoftExcel);
+
+ vml += "<o:shapelayout v:ext=\"edit\">";
+ vml += "<o:idmap v:ext=\"edit\" data=\"1\"/>";
+ vml += "</o:shapelayout>";
+
+ vml +=
+ "<v:shapetype id=\"_x0000_t202\" coordsize=\"21600,21600\" o:spt=\"202\" path=\"m,l,21600r21600,l21600,xe\">";
+ vml += "<v:stroke joinstyle=\"miter\" />";
+ vml += "<v:path gradientshapeok=\"t\" o:connecttype=\"rect\" />";
+ vml += "</v:shapetype>";
+ vml += "</xml>";
+
+ return vml;
+ }
+
+ internal ExcelVmlDrawingComment Add(ExcelRangeBase cell) {
+ XmlNode node = AddDrawing(cell);
+ var draw = new ExcelVmlDrawingComment(node, cell, NameSpaceManager);
+ _drawings.Add(draw);
+ return draw;
+ }
+
+ private XmlNode AddDrawing(ExcelRangeBase cell) {
+ int row = cell.Start.Row,
+ col = cell.Start.Column;
+ var node = VmlDrawingXml.CreateElement("v", "shape", ExcelPackage._schemaMicrosoftVml);
+
+ var id = ExcelCellBase.GetCellId(cell.Worksheet.SheetID, cell._fromRow, cell._fromCol);
+ var ix = _drawings.IndexOf(id);
+ if (ix < 0 && (~ix < _drawings.Count)) {
+ ix = ~ix;
+ var prevDraw = _drawings[ix] as ExcelVmlDrawingBase;
+ prevDraw.TopNode.ParentNode.InsertBefore(node, prevDraw.TopNode);
+ } else {
+ VmlDrawingXml.DocumentElement.AppendChild(node);
+ }
+
+ node.SetAttribute("id", GetNewId());
+ node.SetAttribute("type", "#_x0000_t202");
+ node.SetAttribute("style", "position:absolute;z-index:1; visibility:hidden");
+ //node.SetAttribute("style", "position:absolute; margin-left:59.25pt;margin-top:1.5pt;width:108pt;height:59.25pt;z-index:1; visibility:hidden");
+ node.SetAttribute("fillcolor", "#ffffe1");
+ node.SetAttribute("insetmode", ExcelPackage._schemaMicrosoftOffice, "auto");
+
+ string vml = "<v:fill color2=\"#ffffe1\" />";
+ vml += "<v:shadow on=\"t\" color=\"black\" obscured=\"t\" />";
+ vml += "<v:path o:connecttype=\"none\" />";
+ vml += "<v:textbox style=\"mso-direction-alt:auto\">";
+ vml += "<div style=\"text-align:left\" />";
+ vml += "</v:textbox>";
+ vml += "<x:ClientData ObjectType=\"Note\">";
+ vml += "<x:MoveWithCells />";
+ vml += "<x:SizeWithCells />";
+ vml += string.Format(
+ "<x:Anchor>{0}, 15, {1}, 2, {2}, 31, {3}, 1</x:Anchor>",
+ col,
+ row - 1,
+ col + 2,
+ row + 3);
+ vml += "<x:AutoFill>False</x:AutoFill>";
+ vml += string.Format("<x:Row>{0}</x:Row>", row - 1);
+ ;
+ vml += string.Format("<x:Column>{0}</x:Column>", col - 1);
+ vml += "</x:ClientData>";
+
+ node.InnerXml = vml;
+ return node;
+ }
+
+ private int _nextID;
+
+ /// <summary>
+ /// returns the next drawing id.
+ /// </summary>
+ /// <returns></returns>
+ internal string GetNewId() {
+ if (_nextID == 0) {
+ foreach (ExcelVmlDrawingComment draw in this) {
+ if (draw.Id.Length > 3 && draw.Id.StartsWith("vml")) {
+ if (int.TryParse(draw.Id.Substring(3, draw.Id.Length - 3), out var id)) {
+ if (id > _nextID) {
+ _nextID = id;
+ }
+ }
+ }
+ }
+ }
+ _nextID++;
+ return "vml" + _nextID;
+ }
+
+ internal ExcelVmlDrawingBase this[ulong rangeId] => _drawings[rangeId] as ExcelVmlDrawingComment;
+
+ internal bool ContainsKey(ulong rangeId) {
+ return _drawings.ContainsKey(rangeId);
+ }
+
+ internal int Count => _drawings.Count;
+
+ public IEnumerator GetEnumerator() {
+ return _drawings;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _drawings;
+ }
+}
diff --git a/AppsheetEpplus/Drawing/Vml/ExcelVmlDrawingPosition.cs b/AppsheetEpplus/Drawing/Vml/ExcelVmlDrawingPosition.cs
new file mode 100644
index 0000000..4d17416
--- /dev/null
+++ b/AppsheetEpplus/Drawing/Vml/ExcelVmlDrawingPosition.cs
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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 Initial Release 2010-06-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// The position of a VML drawing. Used for comments
+/// </summary>
+public class ExcelVmlDrawingPosition : XmlHelper {
+ private readonly int _startPos;
+
+ internal ExcelVmlDrawingPosition(XmlNamespaceManager ns, XmlNode topNode, int startPos)
+ : base(ns, topNode) {
+ _startPos = startPos;
+ }
+
+ /// <summary>
+ /// Row. Zero based
+ /// </summary>
+ public int Row {
+ get => GetNumber(2);
+ set => SetNumber(2, value);
+ }
+
+ /// <summary>
+ /// Row offset in pixels. Zero based
+ /// </summary>
+ public int RowOffset {
+ get => GetNumber(3);
+ set => SetNumber(3, value);
+ }
+
+ /// <summary>
+ /// Column. Zero based
+ /// </summary>
+ public int Column {
+ get => GetNumber(0);
+ set => SetNumber(0, value);
+ }
+
+ /// <summary>
+ /// Column offset. Zero based
+ /// </summary>
+ public int ColumnOffset {
+ get => GetNumber(1);
+ set => SetNumber(1, value);
+ }
+
+ private void SetNumber(int pos, int value) {
+ string anchor = GetXmlNodeString("x:Anchor");
+ string[] numbers = anchor.Split(',');
+ if (numbers.Length == 8) {
+ numbers[_startPos + pos] = value.ToString();
+ } else {
+ throw (new("Anchor element is invalid in vmlDrawing"));
+ }
+ SetXmlNodeString("x:Anchor", string.Join(",", numbers));
+ }
+
+ private int GetNumber(int pos) {
+ string anchor = GetXmlNodeString("x:Anchor");
+ string[] numbers = anchor.Split(',');
+ if (numbers.Length == 8) {
+ if (int.TryParse(numbers[_startPos + pos], out var ret)) {
+ return ret;
+ }
+ }
+ throw (new("Anchor element is invalid in vmlDrawing"));
+ }
+}
diff --git a/AppsheetEpplus/ExcelAddress.cs b/AppsheetEpplus/ExcelAddress.cs
new file mode 100644
index 0000000..494fd34
--- /dev/null
+++ b/AppsheetEpplus/ExcelAddress.cs
@@ -0,0 +1,1215 @@
+/*******************************************************************************
+ * 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 18-MAR-2010
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace AppsheetEpplus;
+
+public class ExcelTableAddress {
+ public string Name { get; set; }
+
+ public string ColumnSpan { get; set; }
+
+ public bool IsAll { get; set; }
+
+ public bool IsHeader { get; set; }
+
+ public bool IsData { get; set; }
+
+ public bool IsTotals { get; set; }
+
+ public bool IsThisRow { get; set; }
+}
+
+/// <summary>
+/// A range address
+/// </summary>
+/// <remarks>Examples of addresses are "A1" "B1:C2" "A:A" "1:1" "A1:E2,G3:G5" </remarks>
+public class ExcelAddressBase : ExcelCellBase {
+ protected internal int _fromRow = -1,
+ _toRow,
+ _fromCol,
+ _toCol;
+ protected internal bool _fromRowFixed,
+ _fromColFixed,
+ _toRowFixed,
+ _toColFixed;
+ protected internal string _wb;
+ protected internal string _ws;
+ protected internal string _address;
+
+ protected internal event EventHandler AddressChange;
+
+ internal enum eAddressCollition {
+ No,
+ Partly,
+ Inside,
+ Equal,
+ }
+
+ internal enum eShiftType {
+ Right,
+ Down,
+ EntireRow,
+ EntireColumn,
+ }
+
+ internal ExcelAddressBase() {}
+
+ /// <summary>
+ /// Creates an Address object
+ /// </summary>
+ /// <param name="fromRow">start row</param>
+ /// <param name="fromCol">start column</param>
+ /// <param name="toRow">End row</param>
+ /// <param name="toColumn">End column</param>
+ public ExcelAddressBase(int fromRow, int fromCol, int toRow, int toColumn) {
+ _fromRow = fromRow;
+ _toRow = toRow;
+ _fromCol = fromCol;
+ _toCol = toColumn;
+ Validate();
+
+ _address = GetAddress(_fromRow, _fromCol, _toRow, _toCol);
+ }
+
+ /// <summary>
+ /// Creates an Address object
+ /// </summary>
+ /// <param name="fromRow">start row</param>
+ /// <param name="fromCol">start column</param>
+ /// <param name="toRow">End row</param>
+ /// <param name="toColumn">End column</param>
+ /// <param name="fromRowFixed">start row fixed</param>
+ /// <param name="fromColFixed">start column fixed</param>
+ /// <param name="toRowFixed">End row fixed</param>
+ /// <param name="toColFixed">End column fixed</param>
+ public ExcelAddressBase(
+ int fromRow,
+ int fromCol,
+ int toRow,
+ int toColumn,
+ bool fromRowFixed,
+ bool fromColFixed,
+ bool toRowFixed,
+ bool toColFixed) {
+ _fromRow = fromRow;
+ _toRow = toRow;
+ _fromCol = fromCol;
+ _toCol = toColumn;
+ _fromRowFixed = fromRowFixed;
+ _fromColFixed = fromColFixed;
+ _toRowFixed = toRowFixed;
+ _toColFixed = toColFixed;
+ Validate();
+
+ _address = GetAddress(
+ _fromRow,
+ _fromCol,
+ _toRow,
+ _toCol,
+ _fromRowFixed,
+ fromColFixed,
+ _toRowFixed,
+ _toColFixed);
+ }
+
+ /// <summary>
+ /// Creates an Address object
+ /// </summary>
+ /// <remarks>Examples of addresses are "A1" "B1:C2" "A:A" "1:1" "A1:E2,G3:G5" </remarks>
+ /// <param name="address">The Excel Address</param>
+ public ExcelAddressBase(string address) {
+ SetAddress(address);
+ }
+
+ /// <summary>
+ /// Creates an Address object
+ /// </summary>
+ /// <remarks>Examples of addresses are "A1" "B1:C2" "A:A" "1:1" "A1:E2,G3:G5" </remarks>
+ /// <param name="address">The Excel Address</param>
+ /// <param name="pck">Reference to the package to find information about tables and names</param>
+ /// <param name="referenceAddress">The address</param>
+ protected ExcelAddressBase(
+ string address,
+ ExcelWorkbook workbook,
+ ExcelAddressBase referenceAddress) {
+ SetAddress(address);
+ SetRcFromTable(workbook, referenceAddress);
+ }
+
+ internal void SetRcFromTable(ExcelWorkbook workbook, ExcelAddressBase referenceAddress) {
+ if (string.IsNullOrEmpty(_wb) && Table != null) {
+ foreach (var ws in workbook.Worksheets) {
+ foreach (var t in ws.Tables) {
+ if (t.Name.Equals(Table.Name, StringComparison.InvariantCultureIgnoreCase)) {
+ _ws = ws.Name;
+ if (Table.IsAll) {
+ _fromRow = t.Address._fromRow;
+ _toRow = t.Address._toRow;
+ } else {
+ if (Table.IsThisRow) {
+ if (referenceAddress == null) {
+ _fromRow = -1;
+ _toRow = -1;
+ } else {
+ _fromRow = referenceAddress._fromRow;
+ _toRow = _fromRow;
+ }
+ } else if (Table.IsHeader && Table.IsData) {
+ _fromRow = t.Address._fromRow;
+ _toRow = t.ShowTotal ? t.Address._toRow - 1 : t.Address._toRow;
+ } else if (Table.IsData && Table.IsTotals) {
+ _fromRow = t.ShowHeader ? t.Address._fromRow + 1 : t.Address._fromRow;
+ _toRow = t.Address._toRow;
+ } else if (Table.IsHeader) {
+ _fromRow = t.ShowHeader ? t.Address._fromRow : -1;
+ _toRow = t.ShowHeader ? t.Address._fromRow : -1;
+ } else if (Table.IsTotals) {
+ _fromRow = t.ShowTotal ? t.Address._toRow : -1;
+ _toRow = t.ShowTotal ? t.Address._toRow : -1;
+ } else {
+ _fromRow = t.ShowHeader ? t.Address._fromRow + 1 : t.Address._fromRow;
+ _toRow = t.ShowTotal ? t.Address._toRow - 1 : t.Address._toRow;
+ }
+ }
+
+ if (string.IsNullOrEmpty(Table.ColumnSpan)) {
+ _fromCol = t.Address._fromCol;
+ _toCol = t.Address._toCol;
+ return;
+ }
+ var col = t.Address._fromCol;
+ var cols = Table.ColumnSpan.Split(':');
+ foreach (var c in t.Columns) {
+ if (_fromCol <= 0
+ && cols[0]
+ .Equals(
+ c.Name,
+ StringComparison.InvariantCultureIgnoreCase)) //Issue15063 Add invariant igore case
+ {
+ _fromCol = col;
+ if (cols.Length == 1) {
+ _toCol = _fromCol;
+ return;
+ }
+ } else if (cols.Length > 1
+ && _fromCol > 0
+ && cols[1]
+ .Equals(
+ c.Name,
+ StringComparison.InvariantCultureIgnoreCase)) //Issue15063 Add invariant igore case
+ {
+ _toCol = col;
+ return;
+ }
+
+ col++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Address is an defined name
+ /// </summary>
+ /// <param name="address">the name</param>
+ /// <param name="isName">Should always be true</param>
+ internal ExcelAddressBase(string address, bool isName) {
+ if (isName) {
+ _address = address;
+ _fromRow = -1;
+ _fromCol = -1;
+ _toRow = -1;
+ _toCol = -1;
+ _start = null;
+ _end = null;
+ } else {
+ SetAddress(address);
+ }
+ }
+
+ protected internal void SetAddress(string address) {
+ address = address.Trim();
+ if (address.StartsWith("'")) {
+ SetWbWs(address);
+ } else if (address.StartsWith(
+ "[")) //Remove any external reference
+ {
+ SetWbWs(address);
+ } else {
+ _address = address;
+ }
+ if (_address.IndexOfAny([',', '!', '[']) > -1) {
+ //Advanced address. Including Sheet or multi or table.
+ ExtractAddress(_address);
+ } else {
+ //Simple address
+ GetRowColFromAddress(
+ _address,
+ out _fromRow,
+ out _fromCol,
+ out _toRow,
+ out _toCol,
+ out _fromRowFixed,
+ out _fromColFixed,
+ out _toRowFixed,
+ out _toColFixed);
+ _addresses = null;
+ _start = null;
+ _end = null;
+ }
+ _address = address;
+ Validate();
+ }
+
+ internal void ChangeAddress() {
+ if (AddressChange != null) {
+ AddressChange(this, new());
+ }
+ }
+
+ private void SetWbWs(string address) {
+ int pos = 0;
+
+ // Get Workbook, if any
+ if (address[pos] == '[') {
+ pos = address.IndexOf("]");
+ _wb = address.Substring(1, pos - 1);
+ pos++;
+ } else {
+ _wb = "";
+ }
+
+ // Get Worksheet
+ if (address[pos] == '\'') {
+ int startPos = pos;
+ pos = address.IndexOf("'", pos + 1);
+ while (pos < address.Length && address[pos + 1] == '\'') {
+ pos = address.IndexOf("'", pos + 2);
+ }
+ _ws = address.Substring(startPos + 1, pos - startPos - 1).Replace("''", "'");
+ pos++;
+ } else {
+ int startPos = pos;
+ pos = address.IndexOf("!", pos);
+ if (pos > -1) {
+ _ws = address.Substring(startPos, pos - startPos);
+ }
+ }
+
+ // Get Address
+ pos = address.IndexOf("!", pos);
+ if (pos > -1) {
+ _address = address.Substring(pos + 1);
+ } else {
+ _address = "";
+ }
+ }
+
+ internal void ChangeWorksheet(string wsName, string newWs) {
+ if (_ws == wsName) {
+ _ws = newWs;
+ }
+ var fullAddress = GetAddress();
+
+ if (Addresses != null) {
+ foreach (var a in Addresses) {
+ if (a._ws == wsName) {
+ a._ws = newWs;
+ fullAddress += "," + a.GetAddress();
+ } else {
+ fullAddress += "," + a._address;
+ }
+ }
+ }
+ _address = fullAddress;
+ }
+
+ private string GetAddress() {
+ var adr = "";
+ if (string.IsNullOrEmpty(_wb)) {
+ adr = "[" + _wb + "]";
+ }
+
+ if (string.IsNullOrEmpty(_ws)) {
+ adr += string.Format("'{0}'!", _ws);
+ }
+ adr += GetAddress(_fromRow, _fromCol, _toRow, _toCol);
+ return adr;
+ }
+
+ private ExcelCellAddress _start;
+
+ /// <summary>
+ /// Gets the row and column of the top left cell.
+ /// </summary>
+ /// <value>The start row column.</value>
+ public ExcelCellAddress Start {
+ get {
+ if (_start == null) {
+ _start = new(_fromRow, _fromCol);
+ }
+ return _start;
+ }
+ }
+
+ private ExcelCellAddress _end;
+
+ /// <summary>
+ /// Gets the row and column of the bottom right cell.
+ /// </summary>
+ /// <value>The end row column.</value>
+ public ExcelCellAddress End {
+ get {
+ if (_end == null) {
+ _end = new(_toRow, _toCol);
+ }
+ return _end;
+ }
+ }
+
+ private ExcelTableAddress _table;
+
+ public ExcelTableAddress Table => _table;
+
+ /// <summary>
+ /// The address for the range
+ /// </summary>
+ public virtual string Address => _address;
+
+ /// <summary>
+ /// If the address is a defined name
+ /// </summary>
+ public bool IsName => _fromRow < 0;
+
+ /// <summary>
+ /// Returns the address text
+ /// </summary>
+ /// <returns></returns>
+ public override string ToString() {
+ return _address;
+ }
+
+ private string _firstAddress;
+
+ /// <summary>
+ /// returns the first address if the address is a multi address.
+ /// A1:A2,B1:B2 returns A1:A2
+ /// </summary>
+ internal string FirstAddress {
+ get {
+ if (string.IsNullOrEmpty(_firstAddress)) {
+ return _address;
+ }
+ return _firstAddress;
+ }
+ }
+
+ internal string AddressSpaceSeparated => _address.Replace(',', ' '); //Conditional formatting and a few other places use space as separator for mulit addresses.
+
+ /// <summary>
+ /// Validate the address
+ /// </summary>
+ protected void Validate() {
+ if (_fromRow > _toRow || _fromCol > _toCol) {
+ throw new ArgumentOutOfRangeException(
+ "Start cell Address must be less or equal to End cell address");
+ }
+ }
+
+ internal string WorkSheet => _ws;
+
+ protected internal List<ExcelAddress> _addresses;
+
+ internal virtual List<ExcelAddress> Addresses => _addresses;
+
+ private bool ExtractAddress(string fullAddress) {
+ var brackPos = new Stack<int>();
+ var bracketParts = new List<string>();
+ string first = "",
+ second = "";
+ bool isText = false,
+ hasSheet = false;
+ try {
+ if (fullAddress == "#REF!") {
+ SetAddress(ref fullAddress, ref second, ref hasSheet);
+ return true;
+ }
+ if (fullAddress.StartsWith("!")) {
+ // invalid address!
+ return false;
+ }
+ for (int i = 0; i < fullAddress.Length; i++) {
+ var c = fullAddress[i];
+ if (c == '\'') {
+ if (isText && i + 1 < fullAddress.Length && fullAddress[i] == '\'') {
+ if (hasSheet) {
+ second += c;
+ } else {
+ first += c;
+ }
+ }
+ isText = !isText;
+ } else {
+ if (brackPos.Count > 0) {
+ if (c == '[' && !isText) {
+ brackPos.Push(i);
+ } else if (c == ']' && !isText) {
+ if (brackPos.Count > 0) {
+ var from = brackPos.Pop();
+ bracketParts.Add(fullAddress.Substring(from + 1, i - from - 1));
+
+ if (brackPos.Count == 0) {
+ HandleBrackets(first, second, bracketParts);
+ }
+ } else {
+ //Invalid address!
+ return false;
+ }
+ }
+ } else if (c == '[' && !isText) {
+ brackPos.Push(i);
+ } else if (c == '!' && !isText && !first.EndsWith("#REF") && !second.EndsWith("#REF")) {
+ hasSheet = true;
+ } else if (c == ',' && !isText) {
+ SetAddress(ref first, ref second, ref hasSheet);
+ } else {
+ if (hasSheet) {
+ second += c;
+ } else {
+ first += c;
+ }
+ }
+ }
+ }
+ if (Table == null) {
+ SetAddress(ref first, ref second, ref hasSheet);
+ }
+ return true;
+ } catch {
+ return false;
+ }
+ }
+
+ private void HandleBrackets(string first, string second, List<string> bracketParts) {
+ if (!string.IsNullOrEmpty(first)) {
+ _table = new();
+ Table.Name = first;
+ foreach (var s in bracketParts) {
+ if (s.IndexOf("[") < 0) {
+ switch (s.ToLower(CultureInfo.InvariantCulture)) {
+ case "#all":
+ _table.IsAll = true;
+ break;
+ case "#headers":
+ _table.IsHeader = true;
+ break;
+ case "#data":
+ _table.IsData = true;
+ break;
+ case "#totals":
+ _table.IsTotals = true;
+ break;
+ case "#this row":
+ _table.IsThisRow = true;
+ break;
+ default:
+ if (string.IsNullOrEmpty(_table.ColumnSpan)) {
+ _table.ColumnSpan = s;
+ } else {
+ _table.ColumnSpan += ":" + s;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ internal eAddressCollition Collide(ExcelAddressBase address) {
+ if (address.WorkSheet != WorkSheet && address.WorkSheet != null) {
+ return eAddressCollition.No;
+ }
+
+ if (address._fromRow > _toRow
+ || address._fromCol > _toCol
+ || _fromRow > address._toRow
+ || _fromCol > address._toCol) {
+ return eAddressCollition.No;
+ }
+ if (address._fromRow == _fromRow
+ && address._fromCol == _fromCol
+ && address._toRow == _toRow
+ && address._toCol == _toCol) {
+ return eAddressCollition.Equal;
+ }
+ if (address._fromRow >= _fromRow
+ && address._toRow <= _toRow
+ && address._fromCol >= _fromCol
+ && address._toCol <= _toCol) {
+ return eAddressCollition.Inside;
+ }
+ return eAddressCollition.Partly;
+ }
+
+ internal ExcelAddressBase AddRow(int row, int rows, bool setFixed = false) {
+ if (row > _toRow) {
+ return this;
+ }
+ if (row <= _fromRow) {
+ return new(
+ (setFixed && _fromRowFixed ? _fromRow : _fromRow + rows),
+ _fromCol,
+ (setFixed && _toRowFixed ? _toRow : _toRow + rows),
+ _toCol,
+ _fromRowFixed,
+ _fromColFixed,
+ _toRowFixed,
+ _toColFixed);
+ }
+ return new(
+ _fromRow,
+ _fromCol,
+ (setFixed && _toRowFixed ? _toRow : _toRow + rows),
+ _toCol,
+ _fromRowFixed,
+ _fromColFixed,
+ _toRowFixed,
+ _toColFixed);
+ }
+
+ internal ExcelAddressBase DeleteRow(int row, int rows, bool setFixed = false) {
+ if (row
+ > _toRow) //After
+ {
+ return this;
+ }
+ if (row + rows
+ <= _fromRow) //Before
+ {
+ return new(
+ (setFixed && _fromRowFixed ? _fromRow : _fromRow - rows),
+ _fromCol,
+ (setFixed && _toRowFixed ? _toRow : _toRow - rows),
+ _toCol,
+ _fromRowFixed,
+ _fromColFixed,
+ _toRowFixed,
+ _toColFixed);
+ }
+ if (row <= _fromRow
+ && row + rows
+ > _toRow) //Inside
+ {
+ return null;
+ } //Partly
+ if (row <= _fromRow) {
+ return new(
+ row,
+ _fromCol,
+ (setFixed && _toRowFixed ? _toRow : _toRow - rows),
+ _toCol,
+ _fromRowFixed,
+ _fromColFixed,
+ _toRowFixed,
+ _toColFixed);
+ }
+ return new(
+ _fromRow,
+ _fromCol,
+ (setFixed && _toRowFixed
+ ? _toRow
+ : _toRow - rows < row
+ ? row - 1
+ : _toRow - rows),
+ _toCol,
+ _fromRowFixed,
+ _fromColFixed,
+ _toRowFixed,
+ _toColFixed);
+ }
+
+ internal ExcelAddressBase AddColumn(int col, int cols, bool setFixed = false) {
+ if (col > _toCol) {
+ return this;
+ }
+ if (col <= _fromCol) {
+ return new(
+ _fromRow,
+ (setFixed && _fromColFixed ? _fromCol : _fromCol + cols),
+ _toRow,
+ (setFixed && _toColFixed ? _toCol : _toCol + cols),
+ _fromRowFixed,
+ _fromColFixed,
+ _toRowFixed,
+ _toColFixed);
+ }
+ return new(
+ _fromRow,
+ _fromCol,
+ _toRow,
+ (setFixed && _toColFixed ? _toCol : _toCol + cols),
+ _fromRowFixed,
+ _fromColFixed,
+ _toRowFixed,
+ _toColFixed);
+ }
+
+ internal ExcelAddressBase DeleteColumn(int col, int cols, bool setFixed = false) {
+ if (col
+ > _toCol) //After
+ {
+ return this;
+ }
+ if (col + cols
+ <= _fromCol) //Before
+ {
+ return new(
+ _fromRow,
+ (setFixed && _fromColFixed ? _fromCol : _fromCol - cols),
+ _toRow,
+ (setFixed && _toColFixed ? _toCol : _toCol - cols),
+ _fromRowFixed,
+ _fromColFixed,
+ _toRowFixed,
+ _toColFixed);
+ }
+ if (col <= _fromCol
+ && col + cols
+ > _toCol) //Inside
+ {
+ return null;
+ } //Partly
+ if (col <= _fromCol) {
+ return new(
+ _fromRow,
+ col,
+ _toRow,
+ (setFixed && _toColFixed ? _toCol : _toCol - cols),
+ _fromRowFixed,
+ _fromColFixed,
+ _toRowFixed,
+ _toColFixed);
+ }
+ return new(
+ _fromRow,
+ _fromCol,
+ _toRow,
+ (setFixed && _toColFixed
+ ? _toCol
+ : _toCol - cols < col
+ ? col - 1
+ : _toCol - cols),
+ _fromRowFixed,
+ _fromColFixed,
+ _toRowFixed,
+ _toColFixed);
+ }
+
+ internal ExcelAddressBase Insert(
+ ExcelAddressBase address,
+ eShiftType shift /*, out ExcelAddressBase topAddress, out ExcelAddressBase leftAddress, out ExcelAddressBase rightAddress, out ExcelAddressBase bottomAddress*/) {
+ //Before or after, no change
+ //if ((_toRow > address._fromRow && _toCol > address.column) ||
+ // (_fromRow > address._toRow && column > address._toCol))
+ if (_toRow < address._fromRow
+ || _toCol < address._fromCol
+ || (_fromRow > address._toRow && _fromCol > address._toCol)) {
+ //topAddress = null;
+ //leftAddress = null;
+ //rightAddress = null;
+ //bottomAddress = null;
+ return this;
+ }
+
+ int rows = address.Rows;
+ int cols = address.Columns;
+ string retAddress = "";
+ if (shift == eShiftType.Right) {
+ if (address._fromRow > _fromRow) {
+ retAddress = GetAddress(
+ _fromRow,
+ _fromCol,
+ address._fromRow,
+ _toCol,
+ _fromRowFixed,
+ _fromColFixed,
+ _toRowFixed,
+ _toColFixed);
+ }
+ if (address._fromCol > _fromCol) {
+ retAddress = GetAddress(
+ _fromRow < address._fromRow ? _fromRow : address._fromRow,
+ _fromCol,
+ address._fromRow,
+ _toCol,
+ _fromRowFixed,
+ _fromColFixed,
+ _toRowFixed,
+ _toColFixed);
+ }
+ }
+ if (_toRow < address._fromRow) {
+ if (_fromRow < address._fromRow) {}
+ }
+ return null;
+ }
+
+ private void SetAddress(ref string first, ref string second, ref bool hasSheet) {
+ string ws,
+ address;
+ if (hasSheet) {
+ ws = first;
+ address = second;
+ first = "";
+ second = "";
+ } else {
+ address = first;
+ ws = "";
+ first = "";
+ }
+ hasSheet = false;
+ if (string.IsNullOrEmpty(_firstAddress)) {
+ if (string.IsNullOrEmpty(_ws) || !string.IsNullOrEmpty(ws)) {
+ _ws = ws;
+ }
+ _firstAddress = address;
+ GetRowColFromAddress(
+ address,
+ out _fromRow,
+ out _fromCol,
+ out _toRow,
+ out _toCol,
+ out _fromRowFixed,
+ out _fromColFixed,
+ out _toRowFixed,
+ out _toColFixed);
+ } else {
+ if (_addresses == null) {
+ _addresses = [];
+ }
+ _addresses.Add(new(_ws, address));
+ }
+ }
+
+ internal enum AddressType {
+ Invalid,
+ InternalAddress,
+ ExternalAddress,
+ InternalName,
+ ExternalName,
+ Formula,
+ }
+
+ internal static AddressType IsValid(string address) {
+ if (address == "#REF!") {
+ return AddressType.Invalid;
+ }
+ if (double.TryParse(
+ address,
+ NumberStyles.Any,
+ CultureInfo.InvariantCulture,
+ out _)) //A double, no valid address
+ {
+ return AddressType.Invalid;
+ }
+ if (IsFormula(address)) {
+ return AddressType.Formula;
+ }
+ if (SplitAddress(address, out var wb, out _, out var intAddress)) {
+ if (intAddress.Contains(
+ "[")) //Table reference
+ {
+ return string.IsNullOrEmpty(wb) ? AddressType.InternalAddress : AddressType.ExternalAddress;
+ }
+ if (intAddress.Contains(",")) {
+ intAddress = intAddress.Substring(0, intAddress.IndexOf(','));
+ }
+ if (IsAddress(intAddress)) {
+ return string.IsNullOrEmpty(wb) ? AddressType.InternalAddress : AddressType.ExternalAddress;
+ }
+ return string.IsNullOrEmpty(wb) ? AddressType.InternalName : AddressType.ExternalName;
+ }
+ return AddressType.Invalid;
+ }
+
+ private static bool IsAddress(string intAddress) {
+ if (string.IsNullOrEmpty(intAddress)) {
+ return false;
+ }
+ var cells = intAddress.Split(':');
+ int toRow,
+ toCol;
+
+ if (!GetRowCol(cells[0], out var fromRow, out var fromCol, false)) {
+ return false;
+ }
+ if (cells.Length > 1) {
+ if (!GetRowCol(cells[1], out toRow, out toCol, false)) {
+ return false;
+ }
+ } else {
+ toRow = fromRow;
+ toCol = fromCol;
+ }
+ if (fromRow <= toRow
+ && fromCol <= toCol
+ && fromCol > -1
+ && toCol <= ExcelPackage.MaxColumns
+ && fromRow > -1
+ && toRow <= ExcelPackage.MaxRows) {
+ return true;
+ }
+ return false;
+ }
+
+ private static bool SplitAddress(
+ string address,
+ out string wb,
+ out string ws,
+ out string intAddress) {
+ wb = "";
+ ws = "";
+ intAddress = "";
+ var text = "";
+ bool isText = false;
+ var brackPos = -1;
+ for (int i = 0; i < address.Length; i++) {
+ if (address[i] == '\'') {
+ isText = !isText;
+ if (i > 0 && address[i - 1] == '\'') {
+ text += "'";
+ }
+ } else {
+ if (address[i] == '!' && !isText) {
+ if (text.Length > 0 && text[0] == '[') {
+ wb = text.Substring(1, text.IndexOf("]") - 1);
+ ws = text.Substring(text.IndexOf("]") + 1);
+ } else {
+ ws = text;
+ }
+ intAddress = address.Substring(i + 1);
+ return true;
+ }
+ if (address[i] == '[' && !isText) {
+ if (i
+ > 0) //Table reference return full address;
+ {
+ intAddress = address;
+ return true;
+ }
+ brackPos = i;
+ } else if (address[i] == ']' && !isText) {
+ if (brackPos > -1) {
+ wb = text;
+ text = "";
+ } else {
+ return false;
+ }
+ } else {
+ text += address[i];
+ }
+ }
+ }
+ intAddress = text;
+ return true;
+ }
+
+ private static bool IsFormula(string address) {
+ var isText = false;
+ for (int i = 0; i < address.Length; i++) {
+ if (address[i] == '\'') {
+ isText = !isText;
+ } else {
+ if (isText == false
+ && address
+ .Substring(i, 1)
+ .IndexOfAny(['(', ')', '+', '-', '*', '/', '.', '=', '^', '&', '%', '\"']) > -1) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public int Rows => _toRow - _fromRow + 1;
+
+ public int Columns => _toCol - _fromCol + 1;
+
+ internal static String GetWorkbookPart(string address) {
+ int ix;
+ if (address[0] == '[') {
+ ix = address.IndexOf(']') + 1;
+ if (ix > 0) {
+ return address.Substring(1, ix - 2);
+ }
+ }
+ return "";
+ }
+
+ internal static string GetWorksheetPart(string address, string defaultWorkSheet, ref int endIx) {
+ if (address == "") {
+ return defaultWorkSheet;
+ }
+ var ix = 0;
+ if (address[0] == '[') {
+ ix = address.IndexOf(']') + 1;
+ }
+ if (ix > 0 && ix < address.Length) {
+ if (address[ix] == '\'') {
+ return GetString(address, ix, out endIx);
+ }
+ var ixEnd = address.IndexOf('!', ix);
+ if (ixEnd > ix) {
+ return address.Substring(ix, ixEnd - ix);
+ }
+ return defaultWorkSheet;
+ }
+ return defaultWorkSheet;
+ }
+
+ internal static void SplitAddress(
+ string fullAddress,
+ out string wb,
+ out string ws,
+ out string address,
+ string defaultWorksheet = "") {
+ wb = GetWorkbookPart(fullAddress);
+ int ix = 0;
+ ws = GetWorksheetPart(fullAddress, defaultWorksheet, ref ix);
+ if (ix < fullAddress.Length) {
+ if (fullAddress[ix] == '!') {
+ address = fullAddress.Substring(ix + 1);
+ } else {
+ address = fullAddress.Substring(ix);
+ }
+ } else {
+ address = "";
+ }
+ }
+
+ private static string GetString(string address, int ix, out int endIx) {
+ var strIx = address.IndexOf("''");
+ while (strIx > -1) {
+ strIx = address.IndexOf("''");
+ }
+ endIx = address.IndexOf("'");
+ return address.Substring(ix, endIx - ix).Replace("''", "'");
+ }
+
+ internal bool IsValidRowCol() {
+ return !(_fromRow > _toRow
+ || _fromCol > _toCol
+ || _fromRow < 1
+ || _fromCol < 1
+ || _toRow > ExcelPackage.MaxRows
+ || _toCol > ExcelPackage.MaxColumns);
+ }
+}
+
+/// <summary>
+/// Range address with the address property readonly
+/// </summary>
+public class ExcelAddress : ExcelAddressBase {
+ internal ExcelAddress() {}
+
+ public ExcelAddress(int fromRow, int fromCol, int toRow, int toColumn)
+ : base(fromRow, fromCol, toRow, toColumn) {
+ _ws = "";
+ }
+
+ public ExcelAddress(string address)
+ : base(address) {}
+
+ internal ExcelAddress(string ws, string address)
+ : base(address) {
+ if (string.IsNullOrEmpty(_ws)) {
+ _ws = ws;
+ }
+ }
+
+ internal ExcelAddress(string ws, string address, bool isName)
+ : base(address, isName) {
+ if (string.IsNullOrEmpty(_ws)) {
+ _ws = ws;
+ }
+ }
+
+ public ExcelAddress(string address, ExcelWorkbook workbook, ExcelAddressBase referenceAddress)
+ : base(address, workbook, referenceAddress) {}
+
+ /// <summary>
+ /// The address for the range
+ /// </summary>
+ /// <remarks>Examples of addresses are "A1" "B1:C2" "A:A" "1:1" "A1:E2,G3:G5" </remarks>
+ public new string Address {
+ get {
+ if (string.IsNullOrEmpty(_address) && _fromRow > 0) {
+ _address = GetAddress(_fromRow, _fromCol, _toRow, _toCol);
+ }
+ return _address;
+ }
+ set {
+ SetAddress(value);
+ ChangeAddress();
+ }
+ }
+}
+
+public class ExcelFormulaAddress : ExcelAddressBase {
+ private bool _fromRowFixed,
+ _toRowFixed,
+ _fromColFixed,
+ _toColFixed;
+
+ public ExcelFormulaAddress(int fromRow, int fromCol, int toRow, int toColumn)
+ : base(fromRow, fromCol, toRow, toColumn) {
+ _ws = "";
+ }
+
+ public ExcelFormulaAddress(string address)
+ : base(address) {
+ SetFixed();
+ }
+
+ private void SetFixed() {
+ if (Address.IndexOf("[") >= 0) {
+ return;
+ }
+ var address = FirstAddress;
+ if (_fromRow == _toRow && _fromCol == _toCol) {
+ GetFixed(address, out _fromRowFixed, out _fromColFixed);
+ } else {
+ var cells = address.Split(':');
+ GetFixed(cells[0], out _fromRowFixed, out _fromColFixed);
+ GetFixed(cells[1], out _toRowFixed, out _toColFixed);
+ }
+ }
+
+ private void GetFixed(string address, out bool rowFixed, out bool colFixed) {
+ rowFixed = colFixed = false;
+ var ix = address.IndexOf('$');
+ while (ix > -1) {
+ ix++;
+ if (ix < address.Length) {
+ if (address[ix] >= '0' && address[ix] <= '9') {
+ rowFixed = true;
+ break;
+ }
+ colFixed = true;
+ }
+ ix = address.IndexOf('$', ix);
+ }
+ }
+
+ /// <summary>
+ /// The address for the range
+ /// </summary>
+ /// <remarks>Examples of addresses are "A1" "B1:C2" "A:A" "1:1" "A1:E2,G3:G5" </remarks>
+ public new string Address {
+ get {
+ if (string.IsNullOrEmpty(_address) && _fromRow > 0) {
+ _address = GetAddress(
+ _fromRow,
+ _fromCol,
+ _toRow,
+ _toCol,
+ _fromRowFixed,
+ _toRowFixed,
+ _fromColFixed,
+ _toColFixed);
+ }
+ return _address;
+ }
+ set {
+ SetAddress(value);
+ ChangeAddress();
+ SetFixed();
+ }
+ }
+
+ internal new List<ExcelFormulaAddress> _addresses;
+
+ public new List<ExcelFormulaAddress> Addresses {
+ get {
+ if (_addresses == null) {
+ _addresses = [];
+ }
+ return _addresses;
+ }
+ }
+
+ internal string GetOffset(int row, int column) {
+ int fromRow = _fromRow,
+ fromCol = _fromCol,
+ toRow = _toRow,
+ tocol = _toCol;
+ var isMulti = (fromRow != toRow || fromCol != tocol);
+ if (!_fromRowFixed) {
+ fromRow += row;
+ }
+ if (!_fromColFixed) {
+ fromCol += column;
+ }
+ if (isMulti) {
+ if (!_toRowFixed) {
+ toRow += row;
+ }
+ if (!_toColFixed) {
+ tocol += column;
+ }
+ } else {
+ toRow = fromRow;
+ tocol = fromCol;
+ }
+ string a = GetAddress(
+ fromRow,
+ fromCol,
+ toRow,
+ tocol,
+ _fromRowFixed,
+ _fromColFixed,
+ _toRowFixed,
+ _toColFixed);
+ if (Addresses != null) {
+ foreach (var sa in Addresses) {
+ a += "," + sa.GetOffset(row, column);
+ }
+ }
+ return a;
+ }
+}
diff --git a/AppsheetEpplus/ExcelCellAddress.cs b/AppsheetEpplus/ExcelCellAddress.cs
new file mode 100644
index 0000000..7261766
--- /dev/null
+++ b/AppsheetEpplus/ExcelCellAddress.cs
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************
+ * Starnuto Di Topo & Jan Källman Initial Release 2010-03-14
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// A single cell address
+/// </summary>
+public class ExcelCellAddress {
+ public ExcelCellAddress()
+ : this(1, 1) {}
+
+ private int _row;
+ private int _column;
+ private string _address;
+
+ /// <summary>
+ /// Initializes a new instance of the ExcelCellAddress class.
+ /// </summary>
+ /// <param name="row">The row.</param>
+ /// <param name="column">The column.</param>
+ public ExcelCellAddress(int row, int column) {
+ Row = row;
+ Column = column;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the ExcelCellAddress class.
+ /// </summary>
+ ///<param name="address">The address</param>
+ public ExcelCellAddress(string address) {
+ Address = address;
+ }
+
+ /// <summary>
+ /// Row
+ /// </summary>
+ public int Row {
+ get => _row;
+ private set {
+ if (value <= 0) {
+ throw new ArgumentOutOfRangeException("value", "Row cannot be less than 1.");
+ }
+ _row = value;
+ if (_column > 0) {
+ _address = ExcelCellBase.GetAddress(_row, _column);
+ } else {
+ _address = "#REF!";
+ }
+ }
+ }
+
+ /// <summary>
+ /// Column
+ /// </summary>
+ public int Column {
+ get => _column;
+ private set {
+ if (value <= 0) {
+ throw new ArgumentOutOfRangeException("value", "Column cannot be less than 1.");
+ }
+ _column = value;
+ if (_row > 0) {
+ _address = ExcelCellBase.GetAddress(_row, _column);
+ } else {
+ _address = "#REF!";
+ }
+ }
+ }
+
+ /// <summary>
+ /// Celladdress
+ /// </summary>
+ public string Address {
+ get => _address;
+ internal set {
+ _address = value;
+ ExcelCellBase.GetRowColFromAddress(_address, out _row, out _column);
+ }
+ }
+
+ /// <summary>
+ /// If the address is an invalid reference (#REF!)
+ /// </summary>
+ public bool IsRef => _row <= 0;
+
+ /// <summary>
+ /// Returns the letter corresponding to the supplied 1-based column index.
+ /// </summary>
+ /// <param name="column">Index of the column (1-based)</param>
+ /// <returns>The corresponding letter, like A for 1.</returns>
+ public static string GetColumnLetter(int column) {
+ if (column > ExcelPackage.MaxColumns || column < 1) {
+ throw new InvalidOperationException(
+ "Invalid 1-based column index: "
+ + column
+ + ". Valid range is 1 to "
+ + ExcelPackage.MaxColumns);
+ }
+ return ExcelCellBase.GetColumnLetter(column);
+ }
+}
diff --git a/AppsheetEpplus/ExcelCellBase.cs b/AppsheetEpplus/ExcelCellBase.cs
new file mode 100644
index 0000000..1327a21
--- /dev/null
+++ b/AppsheetEpplus/ExcelCellBase.cs
@@ -0,0 +1,1252 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Base class containing cell address manipulating methods.
+/// </summary>
+public abstract class ExcelCellBase {
+ /// <summary>
+ /// Get the sheet, row and column from the CellID
+ /// </summary>
+ /// <param name="cellId"></param>
+ /// <param name="sheet"></param>
+ /// <param name="row"></param>
+ /// <param name="col"></param>
+ static internal void SplitCellId(ulong cellId, out int sheet, out int row, out int col) {
+ sheet = (int)(cellId % 0x8000);
+ col = ((int)(cellId >> 15) & 0x3FF);
+ row = ((int)(cellId >> 29));
+ }
+
+ /// <summary>
+ /// Get the cellID for the cell.
+ /// </summary>
+ /// <param name="sheetId"></param>
+ /// <param name="row"></param>
+ /// <param name="col"></param>
+ /// <returns></returns>
+ internal static ulong GetCellId(int sheetId, int row, int col) {
+ return ((ulong)sheetId) + (((ulong)col) << 15) + (((ulong)row) << 29);
+ }
+
+ private delegate string AddressTranslator(
+ string part,
+ int row,
+ int col,
+ int rowIncr,
+ int colIncr);
+
+ /// <summary>
+ /// Translates a R1C1 to an absolut address/Formula
+ /// </summary>
+ /// <param name="value">Address</param>
+ /// <param name="row">Current row</param>
+ /// <param name="col">Current column</param>
+ /// <returns>The RC address</returns>
+ public static string TranslateFromR1C1(string value, int row, int col) {
+ return Translate(value, ToAbs, row, col, -1, -1);
+ }
+
+ /// <summary>
+ /// Translates a R1C1 to an absolut address/Formula: Version 1
+ /// </summary>
+ /// <param name="value">Address</param>
+ /// <param name="row">Current row</param>
+ /// <param name="col">Current column</param>
+ /// <returns>The RC address</returns>
+ public static string TranslateFromR1C1_V1(string value, int row, int col) {
+ return Translate_V1(value, ToAbs_V1, row, col, -1, -1);
+ }
+
+ /// <summary>
+ /// Translates a absolut address to R1C1 Format
+ /// </summary>
+ /// <param name="value">R1C1 Address</param>
+ /// <param name="row">Current row</param>
+ /// <param name="col">Current column</param>
+ /// <returns>The absolut address/Formula</returns>
+ public static string TranslateToR1C1(string value, int row, int col) {
+ return Translate(value, ToR1C1, row, col, -1, -1);
+ }
+
+ /// <summary>
+ /// Translates a absolute address to R1C1 Format : Version 1
+ /// </summary>
+ /// <param name="value">R1C1 Address</param>
+ /// <param name="row">Current row</param>
+ /// <param name="col">Current column</param>
+ /// <returns>The absolut address/Formula</returns>
+ public static string TranslateToR1C1_V1(string value, int row, int col) {
+ return Translate_V1(value, ToR1C1_V1, row, col, -1, -1);
+ }
+
+ /// <summary>
+ /// Translates betweein R1C1 or absolute addresses : Version 1
+ /// </summary>
+ /// <param name="value">The addresss/function</param>
+ /// <param name="addressTranslator">The translating function</param>
+ /// <param name="row"></param>
+ /// <param name="col"></param>
+ /// <param name="rowIncr"></param>
+ /// <param name="colIncr"></param>
+ /// <returns></returns>
+ private static string Translate(
+ string value,
+ AddressTranslator addressTranslator,
+ int row,
+ int col,
+ int rowIncr,
+ int colIncr) {
+ if (value == "") {
+ return "";
+ }
+ bool isText = false;
+ string ret = "";
+ string part = "";
+ char prevTq = (char)0;
+ for (int pos = 0; pos < value.Length; pos++) {
+ char c = value[pos];
+ if (c == '"' || c == '\'') {
+ if (isText && prevTq != c) {
+ ret += c;
+ continue;
+ }
+
+ if (isText == false && part != "" && prevTq == c) {
+ ret += addressTranslator(part, row, col, rowIncr, colIncr);
+ part = "";
+ }
+ prevTq = c;
+ isText = !isText;
+ ret += c;
+ } else if (isText) {
+ ret += c;
+ } else {
+ if ((c == '-'
+ || c == '+'
+ || c == '*'
+ || c == '/'
+ || c == '='
+ || c == '^'
+ || c == ','
+ || c == ':'
+ || c == '<'
+ || c == '>'
+ || c == '('
+ || c == ')'
+ || c == '!'
+ || c == ' '
+ || c == '&'
+ || c == '%')
+ && (pos == 0
+ || value[pos - 1]
+ != '[')) //Last part to allow for R1C1 style [-x]
+ {
+ ret += addressTranslator(part, row, col, rowIncr, colIncr) + c;
+ part = "";
+ } else {
+ part += c;
+ }
+ }
+ }
+ if (part != "") {
+ ret += addressTranslator(part, row, col, rowIncr, colIncr);
+ }
+ return ret;
+ }
+
+ private static string Translate_V1(
+ string value,
+ AddressTranslator addressTranslator,
+ int row,
+ int col,
+ int rowIncr,
+ int colIncr) {
+ if (value == "") {
+ return "";
+ }
+ bool isText = false;
+ string ret = "";
+ string part = "";
+ char prevTq = (char)0;
+ value = value.Replace("\n", ""); // Eliminate new line characters in the formula
+ for (int pos = 0; pos < value.Length; pos++) {
+ char c = value[pos];
+ if (c == '"' || c == '\'') {
+ if (isText && prevTq != c) {
+ ret += c;
+ continue;
+ }
+
+ if (isText == false && part != "" && prevTq == c) {
+ ret += addressTranslator(part, row, col, rowIncr, colIncr);
+ part = "";
+ }
+ prevTq = c;
+ isText = !isText;
+ ret += c;
+ } else if (isText) {
+ ret += c;
+ } else if (c
+ == ':') // Keep Range expressions together
+ {
+ part += c;
+ } else {
+ if ((c == '-'
+ || c == '+'
+ || c == '*'
+ || c == '/'
+ || c == '='
+ || c == '^'
+ || c == ','
+ || c == '<'
+ || c == '>'
+ || c == '('
+ || c == ')'
+ || c == '!'
+ || c == ' '
+ || c == '&'
+ || c == '%')
+ && (pos == 0
+ || value[pos - 1]
+ != '[')) //Last part to allow for R1C1 style [-x]
+ {
+ ret += addressTranslator(part, row, col, rowIncr, colIncr) + c;
+ part = "";
+ } else {
+ part += c;
+ }
+ }
+ }
+ if (part != "") {
+ ret += addressTranslator(part, row, col, rowIncr, colIncr);
+ }
+ return ret;
+ }
+
+ /// <summary>
+ /// Translate to R1C1
+ /// </summary>
+ /// <param name="part">the value to be translated</param>
+ /// <param name="row"></param>
+ /// <param name="col"></param>
+ /// <param name="rowIncr"></param>
+ /// <param name="colIncr"></param>
+ /// <returns></returns>
+ private static string ToR1C1(string part, int row, int col, int rowIncr, int colIncr) {
+ string ret = "R";
+ if (GetRowCol(part, out var addrRow, out var addrCol, false)) {
+ if (addrRow == 0 || addrCol == 0) {
+ return part;
+ }
+ if (part.IndexOf('$', 1) > 0) {
+ ret += addrRow.ToString();
+ } else if (addrRow - row != 0) {
+ ret += string.Format("[{0}]", addrRow - row);
+ }
+
+ if (part.StartsWith("$")) {
+ return ret + "C" + addrCol;
+ }
+ if (addrCol - col != 0) {
+ return ret + "C" + string.Format("[{0}]", addrCol - col);
+ }
+ return ret + "C";
+ }
+ return part;
+ }
+
+ private static string ToR1C1_V1(string part, int row, int col, int rowIncr, int colIncr) {
+ // Handle range expressions
+ if ((part.Length > 1) && (part.IndexOf(':', 1) > 0)) {
+ return RangeToR1C1_V1(part, row, col, rowIncr, colIncr);
+ }
+
+ string ret = "R";
+ if (GetRowCol(part, out var addrRow, out var addrCol, false)) {
+ if (addrRow == 0 || addrCol == 0) {
+ return part;
+ }
+ if (part.IndexOf('$', 1) > 0) {
+ ret += addrRow.ToString();
+ } else if (addrRow - row != 0) {
+ ret += string.Format("[{0}]", addrRow - row);
+ }
+
+ if (part.StartsWith("$")) {
+ return ret + "C" + addrCol;
+ }
+ if (addrCol - col != 0) {
+ return ret + "C" + string.Format("[{0}]", addrCol - col);
+ }
+ return ret + "C";
+ }
+ return part;
+ }
+
+ private static string RangeToR1C1_V1(string part, int row, int col, int rowIncr, int colIncr) {
+ // Split range expression
+ string[] cellValues = part.Split([':'], StringSplitOptions.RemoveEmptyEntries);
+
+ // Convert range expressions
+ string result = "";
+ result += RangeCellToR1C1_V1(cellValues[0], row, col, rowIncr, colIncr);
+ result += ":";
+ result +=
+ (cellValues.Length > 1)
+ ? RangeCellToR1C1_V1(cellValues[1], row, col, rowIncr, colIncr)
+ : "";
+
+ // Return converted range expression
+ return result;
+ }
+
+ private static string RangeCellToR1C1_V1(
+ string part,
+ int row,
+ int col,
+ int rowIncr,
+ int colIncr) {
+ string result = "";
+ if (GetRowCol_V1(
+ part,
+ out var addrRow,
+ out var addrCol,
+ false,
+ out var fixedRow,
+ out var fixedCol)) {
+ if (addrRow > 0) {
+ result += "R";
+ if (fixedRow) {
+ // Absolute row
+ result += addrRow.ToString();
+ } else if (addrRow - row != 0) {
+ // Relative row
+ result += string.Format("[{0}]", addrRow - row);
+ }
+ }
+
+ if (addrCol > 0) {
+ result += "C";
+ if (fixedCol) {
+ // Absolute column
+ result += addrCol;
+ } else if (addrCol - col != 0) {
+ // Relative column
+ result += string.Format("[{0}]", addrCol - col);
+ }
+ }
+ return result;
+ }
+ return part;
+ }
+
+ /// <summary>
+ /// Translates to absolute address
+ /// </summary>
+ /// <param name="part"></param>
+ /// <param name="row"></param>
+ /// <param name="col"></param>
+ /// <param name="rowIncr"></param>
+ /// <param name="colIncr"></param>
+ /// <returns></returns>
+ ///
+ private static string ToAbs(string part, int row, int col, int rowIncr, int colIncr) {
+ string check = part.ToUpper(CultureInfo.InvariantCulture);
+
+ int rStart = check.IndexOf("R");
+ if (rStart != 0) {
+ return part;
+ }
+ if (part.Length
+ == 1) //R
+ {
+ return GetAddress(row, col);
+ }
+
+ int cStart = check.IndexOf("C");
+ bool absoluteRow;
+ if (cStart == -1) {
+ int rNum = GetRc(part, row, out absoluteRow);
+ if (rNum > int.MinValue) {
+ return GetAddress(rNum, absoluteRow, col, false);
+ }
+ return part;
+ } else {
+ int rNum = GetRc(part.Substring(1, cStart - 1), row, out absoluteRow);
+ int cNum = GetRc(
+ part.Substring(cStart + 1, part.Length - cStart - 1),
+ col,
+ out var absoluteCol);
+ if (rNum > int.MinValue && cNum > int.MinValue) {
+ return GetAddress(rNum, absoluteRow, cNum, absoluteCol);
+ }
+ return part;
+ }
+ }
+
+ private static string ToAbs_V1(string part, int row, int col, int rowIncr, int colIncr) {
+ bool absoluteCol = false;
+ bool absoluteRow = false;
+ int colNum = -1;
+ int rowNum = -1;
+ int num;
+ int numLength;
+ int pos = 0;
+
+ // Handle range expressions
+ if ((part.Length > 1) && (part.IndexOf(':', 1) > 0)) {
+ return RangeToA1_V1(part, row, col, rowIncr, colIncr);
+ }
+
+ // Ensure part is present
+ if (string.IsNullOrWhiteSpace(part)) {
+ return "";
+ }
+
+ // Convert to upper case
+ string check = part.ToUpper(CultureInfo.InvariantCulture);
+
+ // Parse "R", if any
+ if (pos < part.Length && check[pos] == 'R') {
+ pos += 1;
+
+ if (pos >= part.Length) {
+ // Only "R" present
+ absoluteRow = false;
+ rowNum = row;
+ } else if (pos < part.Length && check[pos] == 'C') {
+ // "R" followed by "C"
+ absoluteRow = false;
+ rowNum = row;
+ } else if (pos < part.Length && check[pos] == '[') {
+ // "R" followed by relative row number
+ pos += 1;
+ num = GetNumber_V1(check.Substring(pos, part.Length - pos), out numLength);
+ if (num == Int32.MinValue) {
+ return part;
+ }
+ pos += numLength;
+
+ if (pos < part.Length && check[pos] == ']') {
+ pos += 1;
+ } else {
+ return part;
+ }
+
+ absoluteRow = false;
+ rowNum = row + num;
+ } else if (pos < part.Length) {
+ // "R" followed by absolute row number
+ num = GetNumber_V1(check.Substring(pos, part.Length - pos), out numLength);
+ if (rowNum == Int32.MinValue) {
+ return part;
+ }
+ pos += numLength;
+
+ absoluteRow = true;
+ rowNum = num;
+ }
+ }
+
+ // Parse "C", if any
+ if (pos < part.Length && check[pos] == 'C') {
+ pos += 1;
+
+ if (pos >= part.Length) {
+ // Only "C" present
+ absoluteCol = false;
+ colNum = col;
+ } else if (pos < part.Length && check[pos] == '[') {
+ // "C" followed by relative column number
+ pos += 1;
+ num = GetNumber_V1(check.Substring(pos, part.Length - pos), out numLength);
+ if (num == Int32.MinValue) {
+ return part;
+ }
+ pos += numLength;
+
+ if (pos < part.Length && check[pos] == ']') {
+ pos += 1;
+ } else {
+ return part;
+ }
+
+ absoluteCol = false;
+ colNum = col + num;
+ } else if (pos < part.Length) {
+ // "C" followed by absolute column number
+ num = GetNumber_V1(check.Substring(pos, part.Length - pos), out numLength);
+ if (num == Int32.MinValue) {
+ return part;
+ }
+ pos += numLength;
+
+ absoluteCol = true;
+ colNum = num;
+ }
+ }
+
+ // Ensure nothing remains unparsed
+ if (pos < part.Length) {
+ return part;
+ }
+
+ // Exit if neither row nor column is present
+ if ((rowNum == Int32.MinValue) && (colNum == Int32.MinValue)) {
+ return part;
+ }
+
+ // Append column
+ string result = "";
+ if (colNum >= 0) {
+ if (absoluteCol) {
+ result += "$";
+ }
+ result += GetColumnLetter(colNum);
+ }
+
+ // Append row
+ if (rowNum >= 0) {
+ if (absoluteRow) {
+ result += "$";
+ }
+ result += rowNum.ToString();
+ }
+
+ // Return result
+ return result;
+ }
+
+ private static int GetNumber_V1(string value, out int length) {
+ // Get number length
+ length = 0;
+
+ // Ensure value is present
+ if (string.IsNullOrWhiteSpace(value)) {
+ return Int32.MinValue;
+ }
+
+ // Check for sign
+ if ((length < value.Length) && ((value[length] == '-') || (value[length] == '+'))) {
+ length += 1;
+ }
+
+ // Get number length
+ while (length < value.Length && value[length] >= '0' && value[length] <= '9') {
+ length += 1;
+ }
+
+ // No number found
+ if (length == 0) {
+ return Int32.MinValue;
+ }
+
+ // Return number value
+ return (int.TryParse(value.Substring(0, length), out var result)) ? result : Int32.MinValue;
+ }
+
+ private static string RangeToA1_V1(string part, int row, int col, int rowIncr, int colIncr) {
+ // Split range expression
+ string[] cellValues = part.Split([':'], StringSplitOptions.RemoveEmptyEntries);
+
+ // Convert range expressions
+ string result = "";
+ result += ToAbs_V1(cellValues[0], row, col, rowIncr, colIncr);
+ result += ":";
+ result += ToAbs_V1(cellValues[1], row, col, rowIncr, colIncr);
+
+ // Return converted range expression
+ return result;
+ }
+
+ /// <summary>
+ /// Get the offset value for RC format
+ /// </summary>
+ /// <param name="value"></param>
+ /// <param name="offsetValue"></param>
+ /// <param name="fixedAddr"></param>
+ /// <returns></returns>
+ ///
+ private static int GetRc(string value, int offsetValue, out bool fixedAddr) {
+ if (value == "") {
+ fixedAddr = false;
+ return offsetValue;
+ }
+ int num;
+ if (value[0] == '['
+ && value[value.Length - 1]
+ == ']') //Offset?
+ {
+ fixedAddr = false;
+ if (int.TryParse(value.Substring(1, value.Length - 2), out num)) {
+ return (offsetValue + num);
+ }
+ return int.MinValue;
+ }
+ // Absolute address
+ fixedAddr = true;
+ if (int.TryParse(value, out num)) {
+ return num;
+ }
+ return int.MinValue;
+ }
+
+ /// <summary>
+ /// Returns the character representation of the numbered column
+ /// </summary>
+ /// <param name="iColumnNumber">The number of the column</param>
+ /// <returns>The letter representing the column</returns>
+ protected internal static string GetColumnLetter(int iColumnNumber) {
+ return GetColumnLetter(iColumnNumber, false);
+ }
+
+ protected internal static string GetColumnLetter(int iColumnNumber, bool fixedCol) {
+ if (iColumnNumber < 1) {
+ //throw new Exception("Column number is out of range");
+ return "#REF!";
+ }
+
+ string sCol = "";
+ do {
+ sCol = ((char)('A' + ((iColumnNumber - 1) % 26))) + sCol;
+ iColumnNumber = (iColumnNumber - ((iColumnNumber - 1) % 26)) / 26;
+ } while (iColumnNumber > 0);
+ return fixedCol ? "$" + sCol : sCol;
+ }
+
+ internal static bool GetRowColFromAddress(
+ string cellAddress,
+ out int fromRow,
+ out int fromColumn,
+ out int toRow,
+ out int toColumn) {
+ bool fixedFromRow,
+ fixedFromColumn,
+ fixedToRow,
+ fixedToColumn;
+ return GetRowColFromAddress(
+ cellAddress,
+ out fromRow,
+ out fromColumn,
+ out toRow,
+ out toColumn,
+ out fixedFromRow,
+ out fixedFromColumn,
+ out fixedToRow,
+ out fixedToColumn);
+ }
+
+ /// <summary>
+ /// Get the row/columns for a Cell-address
+ /// </summary>
+ /// <param name="cellAddress">The address</param>
+ /// <param name="fromRow">Returns the to column</param>
+ /// <param name="fromColumn">Returns the from column</param>
+ /// <param name="toRow">Returns the to row</param>
+ /// <param name="toColumn">Returns the from row</param>
+ /// <param name="fixedFromRow">Is the from row fixed?</param>
+ /// <param name="fixedFromColumn">Is the from column fixed?</param>
+ /// <param name="fixedToRow">Is the to row fixed?</param>
+ /// <param name="fixedToColumn">Is the to column fixed?</param>
+ /// <returns></returns>
+ internal static bool GetRowColFromAddress(
+ string cellAddress,
+ out int fromRow,
+ out int fromColumn,
+ out int toRow,
+ out int toColumn,
+ out bool fixedFromRow,
+ out bool fixedFromColumn,
+ out bool fixedToRow,
+ out bool fixedToColumn) {
+ bool ret;
+ if (cellAddress.IndexOf('[')
+ > 0) //External reference or reference to Table or Pivottable.
+ {
+ fromRow = -1;
+ fromColumn = -1;
+ toRow = -1;
+ toColumn = -1;
+ fixedFromRow = false;
+ fixedFromColumn = false;
+ fixedToRow = false;
+ fixedToColumn = false;
+ return false;
+ }
+
+ cellAddress = cellAddress.ToUpper(CultureInfo.InvariantCulture);
+ //This one can be removed when the worksheet Select format is fixed
+ if (cellAddress.IndexOf(' ') > 0) {
+ cellAddress = cellAddress.Substring(0, cellAddress.IndexOf(' '));
+ }
+
+ if (cellAddress.IndexOf(':') < 0) {
+ ret = GetRowColFromAddress(
+ cellAddress,
+ out fromRow,
+ out fromColumn,
+ out fixedFromRow,
+ out fixedFromColumn);
+ toColumn = fromColumn;
+ toRow = fromRow;
+ fixedToRow = fixedFromRow;
+ fixedToColumn = fixedFromColumn;
+ } else {
+ string[] cells = cellAddress.Split(':');
+ ret = GetRowColFromAddress(
+ cells[0],
+ out fromRow,
+ out fromColumn,
+ out fixedFromRow,
+ out fixedFromColumn);
+ if (ret) {
+ ret = GetRowColFromAddress(
+ cells[1],
+ out toRow,
+ out toColumn,
+ out fixedToRow,
+ out fixedToColumn);
+ } else {
+ GetRowColFromAddress(cells[1], out toRow, out toColumn, out fixedToRow, out fixedToColumn);
+ }
+
+ if (fromColumn <= 0) {
+ fromColumn = 1;
+ }
+ if (fromRow <= 0) {
+ fromRow = 1;
+ }
+ if (toColumn <= 0) {
+ toColumn = ExcelPackage.MaxColumns;
+ }
+ if (toRow <= 0) {
+ toRow = ExcelPackage.MaxRows;
+ }
+ }
+ return ret;
+ }
+
+ /// <summary>
+ /// Get the row/column for n Cell-address
+ /// </summary>
+ /// <param name="cellAddress">The address</param>
+ /// <param name="row">Returns Tthe row</param>
+ /// <param name="column">Returns the column</param>
+ /// <returns>true if valid</returns>
+ internal static bool GetRowColFromAddress(string cellAddress, out int row, out int column) {
+ return GetRowCol(cellAddress, out row, out column, true);
+ }
+
+ internal static bool GetRowColFromAddress(
+ string cellAddress,
+ out int row,
+ out int col,
+ out bool fixedRow,
+ out bool fixedCol) {
+ return GetRowCol(cellAddress, out row, out col, true, out fixedRow, out fixedCol);
+ }
+
+ /// <summary>
+ /// Get the row/column for a Cell-address
+ /// </summary>
+ /// <param name="address">the address</param>
+ /// <param name="row">returns the row</param>
+ /// <param name="col">returns the column</param>
+ /// <param name="throwException">throw exception if invalid, otherwise returns false</param>
+ /// <returns></returns>
+ internal static bool GetRowCol(string address, out int row, out int col, bool throwException) {
+ bool fixedRow,
+ fixedCol;
+ return GetRowCol(address, out row, out col, throwException, out fixedRow, out fixedCol);
+ }
+
+ internal static bool GetRowCol(
+ string address,
+ out int row,
+ out int col,
+ bool throwException,
+ out bool fixedRow,
+ out bool fixedCol) {
+ bool colPart = true;
+ int colStartIx = 0;
+ int colLength = 0;
+ col = 0;
+ row = 0;
+ fixedRow = false;
+ fixedCol = false;
+
+ if (address.EndsWith("#REF!")) {
+ row = 0;
+ col = 0;
+ return true;
+ }
+
+ int sheetMarkerIndex = address.IndexOf('!');
+ if (sheetMarkerIndex >= 0) {
+ colStartIx = sheetMarkerIndex + 1;
+ }
+ address = address.ToUpper(CultureInfo.InvariantCulture);
+ for (int i = colStartIx; i < address.Length; i++) {
+ char c = address[i];
+ if (colPart && (c >= 'A' && c <= 'Z') && colLength <= 3) {
+ col *= 26;
+ col += c - 64;
+ colLength++;
+ } else if (c >= '0' && c <= '9') {
+ row *= 10;
+ row += c - 48;
+ colPart = false;
+ } else if (c == '$') {
+ if (i == colStartIx) {
+ colStartIx++;
+ fixedCol = true;
+ } else {
+ colPart = false;
+ fixedRow = true;
+ }
+ } else {
+ row = 0;
+ col = 0;
+ if (throwException) {
+ throw (new(string.Format("Invalid Address format {0}", address)));
+ }
+ return false;
+ }
+ }
+ return row != 0 || col != 0;
+ }
+
+ internal static bool GetRowCol_V1(
+ string address,
+ out int row,
+ out int col,
+ bool throwException,
+ out bool fixedRow,
+ out bool fixedCol) {
+ bool colPart = true;
+ bool isFixed = false;
+ int colStartIx = 0;
+ int colLength = 0;
+ col = 0;
+ row = 0;
+ fixedRow = false;
+ fixedCol = false;
+
+ if (address.EndsWith("#REF!")) {
+ row = 0;
+ col = 0;
+ return true;
+ }
+
+ int sheetMarkerIndex = address.IndexOf('!');
+ if (sheetMarkerIndex >= 0) {
+ colStartIx = sheetMarkerIndex + 1;
+ }
+ address = address.ToUpper(CultureInfo.InvariantCulture);
+ for (int i = colStartIx; i < address.Length; i++) {
+ char c = address[i];
+ if (c == '$') {
+ // Absolute address
+ isFixed = true;
+ } else if (colPart && (c >= 'A' && c <= 'Z') && colLength <= 3) {
+ // Column portion of address
+ if (isFixed) {
+ fixedCol = true;
+ isFixed = false;
+ }
+
+ col *= 26;
+ col += c - 64;
+ colLength++;
+ } else if (c >= '0' && c <= '9') {
+ // Row portion of address
+ if (isFixed) {
+ fixedRow = true;
+ isFixed = false;
+ }
+
+ row *= 10;
+ row += c - 48;
+ colPart = false;
+ } else {
+ row = 0;
+ col = 0;
+ if (throwException) {
+ throw (new(string.Format("Invalid Address format {0}", address)));
+ }
+ return false;
+ }
+ }
+ return row != 0 || col != 0;
+ }
+
+ private static int GetColumn(string sCol) {
+ int col = 0;
+ int len = sCol.Length - 1;
+ for (int i = len; i >= 0; i--) {
+ col += (sCol[i] - 64) * (int)(Math.Pow(26, len - i));
+ }
+ return col;
+ }
+
+ /// <summary>
+ /// Returns the AlphaNumeric representation that Excel expects for a Cell Address
+ /// </summary>
+ /// <param name="row">The number of the row</param>
+ /// <param name="column">The number of the column in the worksheet</param>
+ /// <returns>The cell address in the format A1</returns>
+ public static string GetAddress(int row, int column) {
+ return GetAddress(row, column, false);
+ }
+
+ /// <summary>
+ /// Returns the AlphaNumeric representation that Excel expects for a Cell Address
+ /// </summary>
+ /// <param name="row">The number of the row</param>
+ /// <param name="column">The number of the column in the worksheet</param>
+ /// <param name="absoluteRow">Absolute row</param>
+ /// <param name="absoluteCol">Absolute column</param>
+ /// <returns>The cell address in the format A1</returns>
+ public static string GetAddress(int row, bool absoluteRow, int column, bool absoluteCol) {
+ return (absoluteCol ? "$" : "") + GetColumnLetter(column) + (absoluteRow ? "$" : "") + row;
+ }
+
+ /// <summary>
+ /// Returns the AlphaNumeric representation that Excel expects for a Cell Address
+ /// </summary>
+ /// <param name="row">The number of the row</param>
+ /// <param name="column">The number of the column in the worksheet</param>
+ /// <param name="absolute">Get an absolute address ($A$1)</param>
+ /// <returns>The cell address in the format A1</returns>
+ public static string GetAddress(int row, int column, bool absolute) {
+ if (row == 0 || column == 0) {
+ return "#REF!";
+ }
+ if (absolute) {
+ return ("$" + GetColumnLetter(column) + "$" + row);
+ }
+ return (GetColumnLetter(column) + row);
+ }
+
+ /// <summary>
+ /// Returns the AlphaNumeric representation that Excel expects for a Cell Address
+ /// </summary>
+ /// <param name="fromRow">From row number</param>
+ /// <param name="fromColumn">From column number</param>
+ /// <param name="toRow">To row number</param>
+ /// <param name="toColumn">From column number</param>
+ /// <returns>The cell address in the format A1</returns>
+ public static string GetAddress(int fromRow, int fromColumn, int toRow, int toColumn) {
+ return GetAddress(fromRow, fromColumn, toRow, toColumn, false);
+ }
+
+ /// <summary>
+ /// Returns the AlphaNumeric representation that Excel expects for a Cell Address
+ /// </summary>
+ /// <param name="fromRow">From row number</param>
+ /// <param name="fromColumn">From column number</param>
+ /// <param name="toRow">To row number</param>
+ /// <param name="toColumn">From column number</param>
+ /// <param name="absolute">if true address is absolute (like $A$1)</param>
+ /// <returns>The cell address in the format A1</returns>
+ public static string GetAddress(
+ int fromRow,
+ int fromColumn,
+ int toRow,
+ int toColumn,
+ bool absolute) {
+ if (fromRow == toRow && fromColumn == toColumn) {
+ return GetAddress(fromRow, fromColumn, absolute);
+ }
+ if (fromRow == 1 && toRow == ExcelPackage.MaxRows) {
+ var absChar = absolute ? "$" : "";
+ return absChar + GetColumnLetter(fromColumn) + ":" + absChar + GetColumnLetter(toColumn);
+ }
+ if (fromColumn == 1 && toColumn == ExcelPackage.MaxColumns) {
+ var absChar = absolute ? "$" : "";
+ return absChar + fromRow + ":" + absChar + toRow;
+ }
+ return GetAddress(fromRow, fromColumn, absolute) + ":" + GetAddress(toRow, toColumn, absolute);
+ }
+
+ /// <summary>
+ /// Returns the AlphaNumeric representation that Excel expects for a Cell Address
+ /// </summary>
+ /// <param name="fromRow">From row number</param>
+ /// <param name="fromColumn">From column number</param>
+ /// <param name="toRow">To row number</param>
+ /// <param name="toColumn">From column number</param>
+ /// <param name="fixedFromColumn"></param>
+ /// <param name="fixedFromRow"></param>
+ /// <param name="fixedToColumn"></param>
+ /// <param name="fixedToRow"></param>
+ /// <returns>The cell address in the format A1</returns>
+ public static string GetAddress(
+ int fromRow,
+ int fromColumn,
+ int toRow,
+ int toColumn,
+ bool fixedFromRow,
+ bool fixedFromColumn,
+ bool fixedToRow,
+ bool fixedToColumn) {
+ if (fromRow == toRow && fromColumn == toColumn) {
+ return GetAddress(fromRow, fixedFromRow, fromColumn, fixedFromColumn);
+ }
+ if (fromRow == 1 && toRow == ExcelPackage.MaxRows) {
+ return GetColumnLetter(fromColumn, fixedFromColumn)
+ + ":"
+ + GetColumnLetter(toColumn, fixedToColumn);
+ }
+ if (fromColumn == 1 && toColumn == ExcelPackage.MaxColumns) {
+ return (fixedFromRow ? "$" : "") + fromRow + ":" + (fixedToRow ? "$" : "") + toRow;
+ }
+ return GetAddress(fromRow, fixedFromRow, fromColumn, fixedFromColumn)
+ + ":"
+ + GetAddress(toRow, fixedToRow, toColumn, fixedToColumn);
+ }
+
+ /// <summary>
+ /// Get the full address including the worksheet name
+ /// </summary>
+ /// <param name="worksheetName">The name of the worksheet</param>
+ /// <param name="address">The address</param>
+ /// <returns>The full address</returns>
+ public static string GetFullAddress(string worksheetName, string address) {
+ return GetFullAddress(worksheetName, address, true);
+ }
+
+ internal static string GetFullAddress(string worksheetName, string address, bool fullRowCol) {
+ if (address.IndexOf("!") == -1 || address == "#REF!") {
+ if (fullRowCol) {
+ string[] cells = address.Split(':');
+ if (cells.Length > 0) {
+ address = string.Format("'{0}'!{1}", worksheetName, cells[0]);
+ if (cells.Length > 1) {
+ address += string.Format(":{0}", cells[1]);
+ }
+ }
+ } else {
+ var a = new ExcelAddressBase(address);
+ if ((a._fromRow == 1 && a._toRow == ExcelPackage.MaxRows)
+ || (a._fromCol == 1 && a._toCol == ExcelPackage.MaxColumns)) {
+ address = string.Format(
+ "'{0}'!{1}{2}:{3}{4}",
+ worksheetName,
+ GetColumnLetter(a._fromCol),
+ a._fromRow,
+ GetColumnLetter(a._toCol),
+ a._toRow);
+ } else {
+ address = GetFullAddress(worksheetName, address, true);
+ }
+ }
+ }
+ return address;
+ }
+
+ public static bool IsValidAddress(string address) {
+ address = address.ToUpper(CultureInfo.InvariantCulture);
+ string r1 = "",
+ c1 = "",
+ r2 = "",
+ c2 = "";
+ bool isSecond = false;
+ for (int i = 0; i < address.Length; i++) {
+ if (address[i] >= 'A' && address[i] <= 'Z') {
+ if (isSecond == false) {
+ if (r1 != "") {
+ return false;
+ }
+ c1 += address[i];
+ if (c1.Length > 3) {
+ return false;
+ }
+ } else {
+ if (r2 != "") {
+ return false;
+ }
+ c2 += address[i];
+ if (c2.Length > 3) {
+ return false;
+ }
+ }
+ } else if (address[i] >= '0' && address[i] <= '9') {
+ if (isSecond == false) {
+ r1 += address[i];
+ if (r1.Length > 7) {
+ return false;
+ }
+ } else {
+ r2 += address[i];
+ if (r2.Length > 7) {
+ return false;
+ }
+ }
+ } else if (address[i] == ':') {
+ isSecond = true;
+ } else if (address[i] == '$') {
+ if (i == address.Length - 1 || address[i + 1] == ':') {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ if (r1 != ""
+ && c1 != ""
+ && r2 == ""
+ && c2
+ == "") //Single Cell
+ {
+ return (GetColumn(c1) <= ExcelPackage.MaxColumns && int.Parse(r1) <= ExcelPackage.MaxRows);
+ }
+ if (r1 != ""
+ && r2 != ""
+ && c1 != ""
+ && c2
+ != "") //Range
+ {
+ var iR2 = int.Parse(r2);
+ var iC2 = GetColumn(c2);
+
+ return GetColumn(c1) <= iC2
+ && int.Parse(r1) <= iR2
+ && iC2 <= ExcelPackage.MaxColumns
+ && iR2 <= ExcelPackage.MaxRows;
+ }
+ if (r1 == ""
+ && r2 == ""
+ && c1 != ""
+ && c2
+ != "") //Full Column
+ {
+ var c2N = GetColumn(c2);
+ return (GetColumn(c1) <= c2N && c2N <= ExcelPackage.MaxColumns);
+ }
+ if (r1 != "" && r2 != "" && c1 == "" && c2 == "") {
+ var iR2 = int.Parse(r2);
+
+ return int.Parse(r1) <= iR2 && iR2 <= ExcelPackage.MaxRows;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Checks that a cell address (e.g. A5) is valid.
+ /// </summary>
+ /// <param name="cellAddress">The alphanumeric cell address</param>
+ /// <returns>True if the cell address is valid</returns>
+ public static bool IsValidCellAddress(string cellAddress) {
+ bool result = false;
+ try {
+ if (GetRowColFromAddress(cellAddress, out var row, out var col)) {
+ if (row > 0 && col > 0 && row <= ExcelPackage.MaxRows && col <= ExcelPackage.MaxColumns) {
+ result = true;
+ } else {
+ result = false;
+ }
+ }
+ } catch {}
+ return result;
+ }
+
+ /// <summary>
+ /// Updates the Excel formula so that all the cellAddresses are incremented by the row and column increments
+ /// if they fall after the afterRow and afterColumn.
+ /// Supports inserting rows and columns into existing templates.
+ /// </summary>
+ /// <param name="formula">The Excel formula</param>
+ /// <param name="rowIncrement">The amount to increment the cell reference by</param>
+ /// <param name="colIncrement">The amount to increment the cell reference by</param>
+ /// <param name="afterRow">Only change rows after this row</param>
+ /// <param name="afterColumn">Only change columns after this column</param>
+ /// <returns></returns>
+ internal static string UpdateFormulaReferences(
+ string formula,
+ int rowIncrement,
+ int colIncrement,
+ int afterRow,
+ int afterColumn,
+ bool setFixed = false) {
+ //return Translate(Formula, AddToRowColumnTranslator, afterRow, afterColumn, rowIncrement, colIncrement);
+ var d = new Dictionary<string, object>();
+ try {
+ var sct = new SourceCodeTokenizer(FunctionNameProvider.Empty, NameValueProvider.Empty);
+ var tokens = sct.Tokenize(formula);
+ String f = "";
+ foreach (var t in tokens) {
+ if (t.TokenType == TokenType.ExcelAddress) {
+ var a = new ExcelAddressBase(t.Value);
+
+ if (!String.IsNullOrEmpty(
+ a._ws)) // Bug 15339
+ {
+ // This is from a different worksheet, thus no update is required
+ f += a.Address;
+ continue;
+ }
+
+ if (rowIncrement > 0) {
+ a = a.AddRow(afterRow, rowIncrement, setFixed);
+ } else if (rowIncrement < 0) {
+ a = a.DeleteRow(afterRow, -rowIncrement, setFixed);
+ }
+ if (colIncrement > 0) {
+ a = a.AddColumn(afterColumn, colIncrement, setFixed);
+ } else if (colIncrement < 0) {
+ a = a.DeleteColumn(afterColumn, -colIncrement, setFixed);
+ }
+ if (a == null || !a.IsValidRowCol()) {
+ f += "#REF!";
+ } else {
+ f += a.Address;
+ }
+ } else {
+ f += t.Value;
+ }
+ }
+ return f;
+ } catch //Invalid formula, skip updateing addresses
+ {
+ return formula;
+ }
+ }
+}
diff --git a/AppsheetEpplus/ExcelColumn.cs b/AppsheetEpplus/ExcelColumn.cs
new file mode 100644
index 0000000..f6f5ef8
--- /dev/null
+++ b/AppsheetEpplus/ExcelColumn.cs
@@ -0,0 +1,252 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan K�llman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Represents one or more columns within the worksheet
+/// </summary>
+public class ExcelColumn : IRangeId {
+ private readonly ExcelWorksheet _worksheet;
+ private readonly XmlElement _colElement = null;
+
+ /// <summary>
+ /// Creates a new instance of the ExcelColumn class.
+ /// For internal use only!
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <param name="col"></param>
+ protected internal ExcelColumn(ExcelWorksheet worksheet, int col) {
+ _worksheet = worksheet;
+ _columnMin = col;
+ _columnMax = col;
+ _width = _worksheet.DefaultColWidth;
+ }
+
+ internal int _columnMin;
+
+ /// <summary>
+ /// Sets the first column the definition refers to.
+ /// </summary>
+ public int ColumnMin => _columnMin;
+
+ //set { _columnMin=value; }
+ internal int _columnMax;
+
+ /// <summary>
+ /// Sets the last column the definition refers to.
+ /// </summary>
+ public int ColumnMax {
+ get => _columnMax;
+ set {
+ if (value < _columnMin && value > ExcelPackage.MaxColumns) {
+ throw new("ColumnMax out of range");
+ }
+
+ var cse = new CellsStoreEnumerator<object>(
+ _worksheet._values,
+ 0,
+ 0,
+ 0,
+ ExcelPackage.MaxColumns);
+ while (cse.Next()) {
+ var c = cse.Value as ExcelColumn;
+ if (cse.Column > _columnMin && c.ColumnMax <= value && cse.Column != _columnMin) {
+ throw new(string.Format("ColumnMax can not span over existing column {0}.", c.ColumnMin));
+ }
+ }
+ _columnMax = value;
+ }
+ }
+
+ /// <summary>
+ /// Internal range id for the column
+ /// </summary>
+ internal ulong ColumnID => GetColumnId(_worksheet.SheetID, ColumnMin);
+
+ /// <summary>
+ /// Allows the column to be hidden in the worksheet
+ /// </summary>
+ internal bool _hidden;
+ public bool Hidden {
+ get => _hidden;
+ set => _hidden = value;
+ }
+
+ internal double VisualWidth {
+ get {
+ if (_hidden || (Collapsed && OutlineLevel > 0)) {
+ return 0;
+ }
+ return _width;
+ }
+ }
+ internal double _width;
+
+ /// <summary>
+ /// Sets the width of the column in the worksheet
+ /// </summary>
+ public double Width {
+ get => _width;
+ set {
+ _width = value;
+
+ if (_hidden && value != 0) {
+ _hidden = false;
+ }
+ }
+ }
+
+ /// <summary>
+ /// If set to true a column automaticlly resize(grow wider) when a user inputs numbers in a cell.
+ /// </summary>
+ public bool BestFit { get; set; }
+
+ /// <summary>
+ /// If the column is collapsed in outline mode
+ /// </summary>
+ public bool Collapsed { get; set; }
+
+ /// <summary>
+ /// Outline level. Zero if no outline
+ /// </summary>
+ public int OutlineLevel { get; set; }
+
+ /// <summary>
+ /// Phonetic
+ /// </summary>
+ public bool Phonetic { get; set; }
+
+ /// <summary>
+ /// The Style applied to the whole column. Only effects cells with no individual style set.
+ /// Use Range object if you want to set specific styles.
+ /// </summary>
+ public ExcelStyle Style {
+ get {
+ string letter = ExcelCellBase.GetColumnLetter(ColumnMin);
+ string endLetter = ExcelCellBase.GetColumnLetter(ColumnMax);
+ return _worksheet.Workbook.Styles.GetStyleObject(
+ StyleID,
+ _worksheet.PositionID,
+ letter + ":" + endLetter);
+ }
+ }
+ internal string _styleName = "";
+
+ /// <summary>
+ /// Sets the style for the entire column using a style name.
+ /// </summary>
+ public string StyleName {
+ get => _styleName;
+ set {
+ StyleID = _worksheet.Workbook.Styles.GetStyleIdFromName(value);
+ _styleName = value;
+ }
+ }
+
+ //internal int _styleID = 0;
+ /// <summary>
+ /// Sets the style for the entire column using the style ID.
+ /// </summary>
+ public int StyleID {
+ get => _worksheet._styles.GetValue(0, ColumnMin);
+ set => _worksheet._styles.SetValue(0, ColumnMin, value);
+ }
+
+ /// <summary>
+ /// Adds a manual page break after the column.
+ /// </summary>
+ public bool PageBreak { get; set; }
+ public bool Merged {
+ get => _worksheet.MergedCells[ColumnMin, 0] != null;
+ set => _worksheet.MergedCells.Add(new(1, ColumnMin, ExcelPackage.MaxRows, ColumnMax), true);
+ }
+
+ /// <summary>
+ /// Returns the range of columns covered by the column definition.
+ /// </summary>
+ /// <returns>A string describing the range of columns covered by the column definition.</returns>
+ public override string ToString() {
+ return string.Format(
+ "Column Range: {0} to {1}",
+ _colElement.GetAttribute("min"),
+ _colElement.GetAttribute("min"));
+ }
+
+ /// <summary>
+ /// Get the internal RangeID
+ /// </summary>
+ /// <param name="sheetId">Sheet no</param>
+ /// <param name="column">Column</param>
+ /// <returns></returns>
+ internal static ulong GetColumnId(int sheetId, int column) {
+ return ((ulong)sheetId) + (((ulong)column) << 15);
+ }
+
+ ulong IRangeId.RangeID {
+ get => ColumnID;
+ set {
+ int prevColMin = _columnMin;
+ _columnMin = ((int)(value >> 15) & 0x3FF);
+ _columnMax += prevColMin - ColumnMin;
+ //Todo:More Validation
+ if (_columnMax > ExcelPackage.MaxColumns) {
+ _columnMax = ExcelPackage.MaxColumns;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Copies the current column to a new worksheet
+ /// </summary>
+ /// <param name="added">The worksheet where the copy will be created</param>
+ internal ExcelColumn Clone(ExcelWorksheet added) {
+ return Clone(added, ColumnMin);
+ }
+
+ internal ExcelColumn Clone(ExcelWorksheet added, int col) {
+ ExcelColumn newCol = added.Column(col);
+ newCol.ColumnMax = ColumnMax;
+ newCol.BestFit = BestFit;
+ newCol.Collapsed = Collapsed;
+ newCol.OutlineLevel = OutlineLevel;
+ newCol.PageBreak = PageBreak;
+ newCol.Phonetic = Phonetic;
+ newCol._styleName = _styleName;
+ newCol.StyleID = StyleID;
+ newCol.Width = Width;
+ newCol.Hidden = Hidden;
+ return newCol;
+ }
+}
diff --git a/AppsheetEpplus/ExcelComment.cs b/AppsheetEpplus/ExcelComment.cs
new file mode 100644
index 0000000..402f9a6
--- /dev/null
+++ b/AppsheetEpplus/ExcelComment.cs
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * 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 Initial Release
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// An Excel Cell Comment
+/// </summary>
+public class ExcelComment : ExcelVmlDrawingComment {
+ private readonly XmlHelper _commentHelper;
+ private readonly string _text;
+
+ internal ExcelComment(XmlNamespaceManager ns, XmlNode commentTopNode, ExcelRangeBase cell)
+ : base(null, cell, cell.Worksheet.VmlDrawingsComments.NameSpaceManager) {
+ //_commentHelper = new XmlHelper(ns, commentTopNode);
+ _commentHelper = XmlHelperFactory.Create(ns, commentTopNode);
+ var textElem = commentTopNode.SelectSingleNode("d:text", ns);
+ if (textElem == null) {
+ textElem = commentTopNode.OwnerDocument.CreateElement("text", ExcelPackage._schemaMain);
+ commentTopNode.AppendChild(textElem);
+ }
+ if (!cell.Worksheet._vmlDrawings.ContainsKey(
+ ExcelCellBase.GetCellId(cell.Worksheet.SheetID, cell.Start.Row, cell.Start.Column))) {
+ cell.Worksheet._vmlDrawings.Add(cell);
+ }
+
+ TopNode = cell.Worksheet.VmlDrawingsComments[ExcelCellBase.GetCellId(
+ cell.Worksheet.SheetID,
+ cell.Start.Row,
+ cell.Start.Column)].TopNode;
+ RichText = new(ns, textElem);
+ var tNode = textElem.SelectSingleNode("d:t", ns);
+ if (tNode != null) {
+ _text = tNode.InnerText;
+ }
+ }
+
+ private const string _authorsPath = "d:comments/d:authors";
+ private const string _authorPath = "d:comments/d:authors/d:author";
+
+ /// <summary>
+ /// Author
+ /// </summary>
+ public string Author {
+ get {
+ int authorRef = _commentHelper.GetXmlNodeInt("@authorId");
+ return _commentHelper.TopNode.OwnerDocument
+ .SelectSingleNode(
+ string.Format("{0}[{1}]", _authorPath, authorRef + 1),
+ _commentHelper.NameSpaceManager)
+ .InnerText;
+ }
+ }
+
+ private int GetAuthor(string value) {
+ int authorRef = 0;
+ bool found = false;
+ foreach (XmlElement node in _commentHelper.TopNode.OwnerDocument.SelectNodes(
+ _authorPath,
+ _commentHelper.NameSpaceManager)) {
+ if (node.InnerText == value) {
+ found = true;
+ break;
+ }
+ authorRef++;
+ }
+ if (!found) {
+ var elem = _commentHelper.TopNode.OwnerDocument.CreateElement(
+ "d",
+ "author",
+ ExcelPackage._schemaMain);
+ _commentHelper.TopNode.OwnerDocument
+ .SelectSingleNode(_authorsPath, _commentHelper.NameSpaceManager)
+ .AppendChild(elem);
+ elem.InnerText = value;
+ }
+ return authorRef;
+ }
+
+ /// <summary>
+ /// The comment text
+ /// </summary>
+ public string Text {
+ get {
+ if (!string.IsNullOrEmpty(RichText.Text)) {
+ return RichText.Text;
+ }
+ return _text;
+ }
+ }
+
+ /// <summary>
+ /// Sets the font of the first richtext item.
+ /// </summary>
+ public ExcelRichText Font {
+ get {
+ if (RichText.Count > 0) {
+ return RichText[0];
+ }
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Richtext collection
+ /// </summary>
+ internal ExcelRichTextCollection RichText { get; set; }
+}
diff --git a/AppsheetEpplus/ExcelCommentCollection.cs b/AppsheetEpplus/ExcelCommentCollection.cs
new file mode 100644
index 0000000..c12fbbc
--- /dev/null
+++ b/AppsheetEpplus/ExcelCommentCollection.cs
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * 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 License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Collection of Excelcomment objects
+/// </summary>
+public class ExcelCommentCollection : IEnumerable, IDisposable {
+ internal RangeCollection _comments;
+
+ internal ExcelCommentCollection(ExcelPackage pck, ExcelWorksheet ws, XmlNamespaceManager ns) {
+ CommentXml.PreserveWhitespace = false;
+ NameSpaceManager = ns;
+ Worksheet = ws;
+ CreateXml(pck);
+ AddCommentsFromXml();
+ }
+
+ private void CreateXml(ExcelPackage pck) {
+ var commentParts = Worksheet.Part.GetRelationshipsByType(ExcelPackage._schemaComment);
+ bool isLoaded = false;
+ CommentXml = new();
+ foreach (var commentPart in commentParts) {
+ Uri = UriHelper.ResolvePartUri(commentPart.SourceUri, commentPart.TargetUri);
+ Part = pck.Package.GetPart(Uri);
+ XmlHelper.LoadXmlSafe(CommentXml, Part.GetStream());
+ RelId = commentPart.Id;
+ isLoaded = true;
+ }
+ //Create a new document
+ if (!isLoaded) {
+ CommentXml.LoadXml(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><comments xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"><authors /><commentList /></comments>");
+ Uri = null;
+ }
+ }
+
+ private void AddCommentsFromXml() {
+ var lst = new List<IRangeId>();
+ foreach (XmlElement node in CommentXml.SelectNodes(
+ "//d:commentList/d:comment",
+ NameSpaceManager)) {
+ var comment = new ExcelComment(
+ NameSpaceManager,
+ node,
+ new(Worksheet, node.GetAttribute("ref")));
+ lst.Add(comment);
+ }
+ _comments = new(lst);
+ }
+
+ /// <summary>
+ /// Access to the comment xml document
+ /// </summary>
+ public XmlDocument CommentXml { get; set; } = new();
+
+ internal Uri Uri { get; set; }
+
+ internal string RelId { get; set; }
+
+ internal XmlNamespaceManager NameSpaceManager { get; set; }
+
+ internal ZipPackagePart Part { get; set; }
+
+ /// <summary>
+ /// A reference to the worksheet object
+ /// </summary>
+ public ExcelWorksheet Worksheet { get; set; }
+
+ /// <summary>
+ /// Number of comments in the collection
+ /// </summary>
+ public int Count => _comments.Count;
+
+ /// <summary>
+ /// Indexer for the comments collection
+ /// </summary>
+ /// <param name="index">The index</param>
+ /// <returns>The comment</returns>
+ public ExcelComment this[int index] {
+ get {
+ if (index < 0 || index >= _comments.Count) {
+ throw (new ArgumentOutOfRangeException("Comment index out of range"));
+ }
+ return _comments[index] as ExcelComment;
+ }
+ }
+
+ /// <summary>
+ /// Indexer for the comments collection
+ /// </summary>
+ /// <param name="cell">The cell</param>
+ /// <returns>The comment</returns>
+ public ExcelComment this[ExcelCellAddress cell] {
+ get {
+ ulong cellId = ExcelCellBase.GetCellId(Worksheet.SheetID, cell.Row, cell.Column);
+ if (_comments.IndexOf(cellId) >= 0) {
+ return _comments[cellId] as ExcelComment;
+ }
+ return null;
+ }
+ }
+
+ void IDisposable.Dispose() {}
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _comments;
+ }
+}
diff --git a/AppsheetEpplus/ExcelHyperLink.cs b/AppsheetEpplus/ExcelHyperLink.cs
new file mode 100644
index 0000000..34709a6
--- /dev/null
+++ b/AppsheetEpplus/ExcelHyperLink.cs
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * 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 this class 2010-01-24
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// HyperlinkClass
+/// </summary>
+public class ExcelHyperLink : Uri {
+ /// <summary>
+ /// A new hyperlink with the specified URI
+ /// </summary>
+ /// <param name="uriString">The URI</param>
+ public ExcelHyperLink(string uriString)
+ : base(uriString) {
+ OriginalUri = this;
+ }
+
+ /// <summary>
+ /// A new hyperlink with the specified URI. This syntax is obsolete
+ /// </summary>
+ /// <param name="uriString">The URI</param>
+ /// <param name="dontEscape"></param>
+ [Obsolete(
+ "base constructor 'System.Uri.Uri(string, bool)' is obsolete: 'The constructor has been deprecated. Please use new ExcelHyperLink(string). The dontEscape parameter is deprecated and is always false.")]
+ public ExcelHyperLink(string uriString, bool dontEscape)
+ : base(uriString, dontEscape) {
+ OriginalUri = this;
+ }
+
+ /// <summary>
+ /// A new hyperlink with the specified URI and kind
+ /// </summary>
+ /// <param name="uriString">The URI</param>
+ /// <param name="uriKind">Kind (absolute/relative or indeterminate)</param>
+ public ExcelHyperLink(string uriString, UriKind uriKind)
+ : base(uriString, uriKind) {
+ OriginalUri = this;
+ }
+
+ /// <summary>
+ /// Sheet internal reference
+ /// </summary>
+ /// <param name="referenceAddress">Address</param>
+ /// <param name="display">Displayed text</param>
+ public ExcelHyperLink(string referenceAddress, string display)
+ : base(
+ "xl://internal") //URI is not used on internal links so put a dummy uri here.
+ {
+ _referenceAddress = referenceAddress;
+ _display = display;
+ }
+
+ private string _referenceAddress;
+
+ /// <summary>
+ /// The Excel address for internal links.
+ /// </summary>
+ public string ReferenceAddress {
+ get => _referenceAddress;
+ set => _referenceAddress = value;
+ }
+
+ private string _display = "";
+
+ /// <summary>
+ /// Displayed text
+ /// </summary>
+ public string Display {
+ get => _display;
+ set => _display = value;
+ }
+
+ /// <summary>
+ /// Tooltip
+ /// </summary>
+ public string ToolTip { get; set; }
+
+ private int _colSpann;
+
+ /// <summary>
+ /// If the hyperlink spans multiple columns
+ /// </summary>
+ public int ColSpann {
+ get => _colSpann;
+ set => _colSpann = value;
+ }
+
+ private int _rowSpann;
+
+ /// <summary>
+ /// If the hyperlink spans multiple rows
+ /// </summary>
+ public int RowSpann {
+ get => _rowSpann;
+ set => _rowSpann = value;
+ }
+
+ /// <summary>
+ /// Used to handle non absolute URI's.
+ /// Is used if IsAblsoluteUri is true. The base URI will have a dummy value of xl://nonAbsolute.
+ /// </summary>
+ public Uri OriginalUri { get; internal set; }
+
+ internal string RId { get; set; }
+}
diff --git a/AppsheetEpplus/ExcelNamedRange.cs b/AppsheetEpplus/ExcelNamedRange.cs
new file mode 100644
index 0000000..13cb291
--- /dev/null
+++ b/AppsheetEpplus/ExcelNamedRange.cs
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * 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 this class 2010-01-28
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// A named range.
+/// </summary>
+public sealed class ExcelNamedRange : ExcelRangeBase {
+ private readonly ExcelWorksheet _sheet;
+
+ /// <summary>
+ /// A named range
+ /// </summary>
+ /// <param name="name">The name</param>
+ /// <param name="nameSheet">The sheet containing the name. null if its a global name</param>
+ /// <param name="sheet">Sheet where the address points</param>
+ /// <param name="address">The address</param>
+ /// <param name="index">The index in the collection</param>
+ public ExcelNamedRange(
+ string name,
+ ExcelWorksheet nameSheet,
+ ExcelWorksheet sheet,
+ string address,
+ int index)
+ : base(sheet, address) {
+ Name = name;
+ _sheet = nameSheet;
+ Index = index;
+ }
+
+ internal ExcelNamedRange(string name, ExcelWorkbook wb, ExcelWorksheet nameSheet, int index)
+ : base(wb, nameSheet, name, true) {
+ Name = name;
+ _sheet = nameSheet;
+ Index = index;
+ }
+
+ /// <summary>
+ /// Name of the range
+ /// </summary>
+ public string Name { get; internal set; }
+
+ /// <summary>
+ /// Is the named range local for the sheet
+ /// </summary>
+ public int LocalSheetId {
+ get {
+ if (_sheet == null) {
+ return -1;
+ }
+ return _sheet.PositionID - 1;
+ }
+ }
+
+ internal int Index { get; set; }
+
+ /// <summary>
+ /// Is the name hidden
+ /// </summary>
+ public bool IsNameHidden { get; set; }
+
+ /// <summary>
+ /// A comment for the Name
+ /// </summary>
+ public string NameComment { get; set; }
+
+ internal object NameValue { get; set; }
+
+ internal string NameFormula { get; set; }
+
+ public override string ToString() {
+ return Name;
+ }
+}
diff --git a/AppsheetEpplus/ExcelNamedRangeCollection.cs b/AppsheetEpplus/ExcelNamedRangeCollection.cs
new file mode 100644
index 0000000..79f6471
--- /dev/null
+++ b/AppsheetEpplus/ExcelNamedRangeCollection.cs
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * 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 this class 2010-01-28
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Collection for named ranges
+/// </summary>
+public class ExcelNamedRangeCollection : IEnumerable<ExcelNamedRange> {
+ internal ExcelWorksheet _ws;
+ internal ExcelWorkbook _wb;
+
+ internal ExcelNamedRangeCollection(ExcelWorkbook wb) {
+ _wb = wb;
+ _ws = null;
+ }
+
+ internal ExcelNamedRangeCollection(ExcelWorkbook wb, ExcelWorksheet ws) {
+ _wb = wb;
+ _ws = ws;
+ }
+
+ private readonly List<ExcelNamedRange> _list = new();
+ private readonly Dictionary<string, int> _dic = new(StringComparer.InvariantCultureIgnoreCase);
+
+ /// <summary>
+ /// Add a new named range
+ /// </summary>
+ /// <param name="name">The name</param>
+ /// <param name="range">The range</param>
+ /// <returns></returns>
+ public ExcelNamedRange Add(string name, ExcelRangeBase range) {
+ ExcelNamedRange item;
+ if (range.IsName) {
+ item = new(name, _wb, _ws, _dic.Count);
+ } else {
+ item = new(name, _ws, range.Worksheet, range.Address, _dic.Count);
+ }
+
+ AddName(name, item);
+
+ return item;
+ }
+
+ private void AddName(string name, ExcelNamedRange item) {
+ // Is 'Name' already present
+ if (_dic.ContainsKey(name)) {
+ int index = _dic[name];
+ if ((0 <= index) && (index < _list.Count)) {
+ ExcelNamedRange listItem = _list[index];
+ if ((listItem != null)
+ && (listItem.FullAddress != null)
+ && (listItem.FullAddress == item.FullAddress)) {
+ return;
+ }
+
+ //throw new Exception(string.Format("Name '{0}' is defined in the worksheet more than once. First as '{1}' and second as '{2}'.", Name, listItem.FullAddress, item.FullAddress));
+ return;
+ }
+
+ //throw new Exception(string.Format("Name '{0}' is defined in the worksheet more than once.", Name));
+ return;
+ }
+
+ _dic.Add(name, _list.Count);
+ _list.Add(item);
+ }
+
+ /// <summary>
+ /// Add a defined name referencing value
+ /// </summary>
+ /// <param name="name"></param>
+ /// <param name="value"></param>
+ /// <returns></returns>
+ public ExcelNamedRange AddValue(string name, object value) {
+ var item = new ExcelNamedRange(name, _wb, _ws, _dic.Count);
+ item.NameValue = value;
+ AddName(name, item);
+ return item;
+ }
+
+ /// <summary>
+ /// Add a defined name referencing a formula -- the method name contains a typo.
+ /// This method is obsolete and will be removed in the future.
+ /// Use <see cref="AddFormula"/>
+ /// </summary>
+ /// <param name="name"></param>
+ /// <param name="formula"></param>
+ /// <returns></returns>
+ [Obsolete("Call AddFormula() instead. See Issue Tracker Id #14687")]
+ public ExcelNamedRange AddFormla(string name, string formula) {
+ return AddFormula(name, formula);
+ }
+
+ /// <summary>
+ /// Add a defined name referencing a formula
+ /// </summary>
+ /// <param name="name"></param>
+ /// <param name="formula"></param>
+ /// <returns></returns>
+ public ExcelNamedRange AddFormula(string name, string formula) {
+ var item = new ExcelNamedRange(name, _wb, _ws, _dic.Count);
+ item.NameFormula = formula;
+ AddName(name, item);
+ return item;
+ }
+
+ /// <summary>
+ /// Remove a defined name from the collection
+ /// </summary>
+ /// <param name="name">The name</param>
+ public void Remove(string name) {
+ if (_dic.ContainsKey(name)) {
+ var ix = _dic[name];
+
+ for (int i = ix + 1; i < _list.Count; i++) {
+ _dic.Remove(_list[i].Name);
+ _list[i].Index--;
+ _dic.Add(_list[i].Name, _list[i].Index);
+ }
+ _dic.Remove(name);
+ _list.RemoveAt(ix);
+ }
+ }
+
+ /// <summary>
+ /// Checks collection for the presence of a key
+ /// </summary>
+ /// <param name="key">key to search for</param>
+ /// <returns>true if the key is in the collection</returns>
+ public bool ContainsKey(string key) {
+ return _dic.ContainsKey(key);
+ }
+
+ /// <summary>
+ /// The current number of items in the collection
+ /// </summary>
+ public int Count => _dic.Count;
+
+ /// <summary>
+ /// Name indexer
+ /// </summary>
+ /// <param name="name">The name (key) for a Named range</param>
+ /// <returns>a reference to the range</returns>
+ /// <remarks>
+ /// Throws a KeyNotFoundException if the key is not in the collection.
+ /// </remarks>
+ public ExcelNamedRange this[string name] => _list[_dic[name]];
+
+ public ExcelNamedRange this[int index] => _list[index];
+
+ /// <summary>
+ /// Implement interface method IEnumerator<ExcelNamedRange> GetEnumerator()
+ /// </summary>
+ /// <returns></returns>
+ public IEnumerator<ExcelNamedRange> GetEnumerator() {
+ return _list.GetEnumerator();
+ }
+
+ /// <summary>
+ /// Implement interface method IEnumeratable GetEnumerator()
+ /// </summary>
+ /// <returns></returns>
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _list.GetEnumerator();
+ }
+
+ internal void Clear() {
+ while (Count > 0) {
+ Remove(_list[0].Name);
+ }
+ }
+}
diff --git a/AppsheetEpplus/ExcelPackage.cs b/AppsheetEpplus/ExcelPackage.cs
new file mode 100644
index 0000000..68f1b59
--- /dev/null
+++ b/AppsheetEpplus/ExcelPackage.cs
@@ -0,0 +1,213 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Starnuto Di Topo & Jan Källman Added stream constructors
+ * and Load method Save as
+ * stream 2010-03-14
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.IO;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Represents an Excel XLSX file package.
+/// This is the top-level object to access all parts of the document.
+/// </summary>
+public sealed class ExcelPackage {
+ /// <summary>
+ /// Extention Schema types
+ /// </summary>
+ internal const string _schemaXmlExtension = "application/xml";
+ internal const string _schemaRelsExtension =
+ "application/vnd.openxmlformats-package.relationships+xml";
+
+ /// <summary>
+ /// Main Xml schema name
+ /// </summary>
+ internal const string _schemaMain = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
+
+ /// <summary>
+ /// Relationship schema name
+ /// </summary>
+ internal const string _schemaRelationships =
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
+
+ internal const string _schemaMicrosoftVml = "urn:schemas-microsoft-com:vml";
+ internal const string _schemaMicrosoftOffice = "urn:schemas-microsoft-com:office:office";
+ internal const string _schemaMicrosoftExcel = "urn:schemas-microsoft-com:office:excel";
+
+ internal const string _schemaChart = "http://schemas.openxmlformats.org/drawingml/2006/chart";
+ internal const string _schemaHyperlink =
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
+ internal const string _schemaComment =
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
+
+ //Office properties
+ internal const string _schemaCore =
+ "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
+ internal const string _schemaExtended =
+ "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
+ internal const string _schemaCustom =
+ "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";
+ internal const string _schemaDc = "http://purl.org/dc/elements/1.1/";
+ internal const string _schemaDcTerms = "http://purl.org/dc/terms/";
+ internal const string _schemaDcmiType = "http://purl.org/dc/dcmitype/";
+ internal const string _schemaXsi = "http://www.w3.org/2001/XMLSchema-instance";
+ internal const string _schemaVt =
+ "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes";
+
+ internal const string _contentTypeSharedString =
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml";
+
+ /// <summary>
+ /// Maximum number of columns in a worksheet (16384).
+ /// </summary>
+ public const int MaxColumns = 16384;
+
+ /// <summary>
+ /// Maximum number of rows in a worksheet (1048576).
+ /// </summary>
+ public const int MaxRows = 1048576;
+
+ /// <summary>
+ /// Create a new, empty package.
+ /// </summary>
+ public ExcelPackage() {
+ Package = new();
+ Workbook = new(this, CreateDefaultNsm());
+ }
+
+ /// <summary>
+ /// Create a new instance of the ExcelPackage class based on an existing file.
+ /// </summary>
+ public ExcelPackage(FileInfo newFile) {
+ using var inputStream = newFile.OpenRead();
+ Package = new(inputStream);
+ Workbook = new(this, CreateDefaultNsm());
+ }
+
+ /// <summary>
+ /// Create a new instance of the ExcelPackage class based on a stream.
+ /// </summary>
+ public ExcelPackage(Stream newStream) {
+ Package = new(newStream);
+ Workbook = new(this, CreateDefaultNsm());
+ }
+
+ internal ZipPackage Package { get; }
+
+ /// <summary>
+ /// Returns a reference to the workbook component within the package.
+ /// All worksheets and cells can be accessed through the workbook.
+ /// </summary>
+ public ExcelWorkbook Workbook { get; }
+
+ private XmlNamespaceManager CreateDefaultNsm() {
+ // Create a NamespaceManager to handle the default namespace,
+ // and create a prefix for the default namespace:
+ NameTable nt = new NameTable();
+ var ns = new XmlNamespaceManager(nt);
+ ns.AddNamespace(string.Empty, _schemaMain);
+ ns.AddNamespace("d", _schemaMain);
+ ns.AddNamespace("r", _schemaRelationships);
+ ns.AddNamespace("c", _schemaChart);
+ ns.AddNamespace("vt", _schemaVt);
+ // extended properties (app.xml)
+ ns.AddNamespace("xp", _schemaExtended);
+ // custom properties
+ ns.AddNamespace("ctp", _schemaCustom);
+ // core properties
+ ns.AddNamespace("cp", _schemaCore);
+ // core property namespaces
+ ns.AddNamespace("dc", _schemaDc);
+ ns.AddNamespace("dcterms", _schemaDcTerms);
+ ns.AddNamespace("dcmitype", _schemaDcmiType);
+ ns.AddNamespace("xsi", _schemaXsi);
+ return ns;
+ }
+
+ internal XmlDocument GetXmlDocument(Uri uri) {
+ var xmlDocument = new XmlDocument();
+ var part = Package.GetPart(uri);
+ XmlHelper.LoadXmlSafe(xmlDocument, part.GetStream());
+ part.SaveHandler = writer => xmlDocument.Save(writer);
+ return xmlDocument;
+ }
+
+ internal ZipPackageRelationship CreateXmlDocument(
+ Uri uri,
+ string contentType,
+ string relationship,
+ XmlDocument newDoc) {
+ Package.CreatePart(uri, contentType, newDoc.Save);
+ return Package.CreateRelationship(
+ UriHelper.GetRelativeUri(new("/xl", UriKind.Relative), uri),
+ TargetMode.Internal,
+ relationship);
+ }
+
+ internal XmlDocument GetOrCreateXmlDocument(
+ Uri uri,
+ string contentType,
+ string relationship,
+ Func<XmlDocument> createDocument) {
+ if (Package.PartExists(uri)) {
+ return GetXmlDocument(uri);
+ }
+ var newDoc = createDocument();
+ CreateXmlDocument(uri, contentType, relationship, newDoc);
+ return newDoc;
+ }
+
+ internal XmlDocument GetOrCreateXmlDocument(
+ Uri uri,
+ string contentType,
+ string relationship,
+ string initialDocumentXml) =>
+ GetOrCreateXmlDocument(
+ uri,
+ contentType,
+ relationship,
+ () => {
+ var emptyDocument = new XmlDocument();
+ emptyDocument.LoadXml(initialDocumentXml);
+ return emptyDocument;
+ });
+
+ public byte[] GetAsByteArray() {
+ var result = new MemoryStream();
+ Workbook.Save();
+ Package.Save(result);
+ return result.ToArray();
+ }
+}
diff --git a/AppsheetEpplus/ExcelProtectedRange.cs b/AppsheetEpplus/ExcelProtectedRange.cs
new file mode 100644
index 0000000..ac9a0ec
--- /dev/null
+++ b/AppsheetEpplus/ExcelProtectedRange.cs
@@ -0,0 +1,14 @@
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+public class ExcelProtectedRange : XmlHelper {
+ public string Name => GetXmlNodeString("@name");
+
+ private ExcelAddress _address;
+
+ public ExcelAddress Address => _address ??= new(GetXmlNodeString("@sqref"));
+
+ internal ExcelProtectedRange(XmlNamespaceManager ns, XmlNode topNode)
+ : base(ns, topNode) {}
+}
diff --git a/AppsheetEpplus/ExcelProtectedRangeCollection.cs b/AppsheetEpplus/ExcelProtectedRangeCollection.cs
new file mode 100644
index 0000000..71c399b
--- /dev/null
+++ b/AppsheetEpplus/ExcelProtectedRangeCollection.cs
@@ -0,0 +1,31 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+public class ExcelProtectedRangeCollection : XmlHelper, IEnumerable<ExcelProtectedRange> {
+ internal ExcelProtectedRangeCollection(XmlNamespaceManager nsm, XmlNode topNode)
+ : base(nsm, topNode) {
+ foreach (XmlNode protectedRangeNode in topNode.SelectNodes(
+ "d:protectedRanges/d:protectedRange",
+ nsm)) {
+ if (!(protectedRangeNode is XmlElement)) {
+ continue;
+ }
+ _baseList.Add(new(nsm, topNode));
+ }
+ }
+
+ private readonly List<ExcelProtectedRange> _baseList = new();
+
+ public ExcelProtectedRange this[int index] => _baseList[index];
+
+ IEnumerator<ExcelProtectedRange> IEnumerable<ExcelProtectedRange>.GetEnumerator() {
+ return _baseList.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _baseList.GetEnumerator();
+ }
+}
diff --git a/AppsheetEpplus/ExcelProtection.cs b/AppsheetEpplus/ExcelProtection.cs
new file mode 100644
index 0000000..de9ce06
--- /dev/null
+++ b/AppsheetEpplus/ExcelProtection.cs
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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 10-AUG-2010
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Collections.Immutable;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Sets protection on the workbook level
+///<seealso cref="ExcelEncryption"/>
+///<seealso cref="ExcelSheetProtection"/>
+/// </summary>
+public class ExcelProtection : XmlHelper {
+ protected override ImmutableArray<string> SchemaNodeOrder =>
+ ExcelWorkbook.WorkbookSchemaNodeOrder;
+
+ internal ExcelProtection(XmlNamespaceManager ns, XmlNode topNode)
+ : base(ns, topNode) {}
+
+ private const string _lockStructurePath = "d:workbookProtection/@lockStructure";
+
+ /// <summary>
+ /// Locks the structure,which prevents users from adding or deleting worksheets or from displaying hidden worksheets.
+ /// </summary>
+ public bool LockStructure {
+ get => GetXmlNodeBool(_lockStructurePath, false);
+ set => SetXmlNodeBool(_lockStructurePath, value, false);
+ }
+
+ private const string _lockWindowsPath = "d:workbookProtection/@lockWindows";
+
+ /// <summary>
+ /// Locks the position of the workbook window.
+ /// </summary>
+ public bool LockWindows {
+ get => GetXmlNodeBool(_lockWindowsPath, false);
+ set => SetXmlNodeBool(_lockWindowsPath, value, false);
+ }
+
+ private const string _lockRevisionPath = "d:workbookProtection/@lockRevision";
+
+ /// <summary>
+ /// Lock the workbook for revision
+ /// </summary>
+ public bool LockRevision {
+ get => GetXmlNodeBool(_lockRevisionPath, false);
+ set => SetXmlNodeBool(_lockRevisionPath, value, false);
+ }
+}
diff --git a/AppsheetEpplus/ExcelRange.cs b/AppsheetEpplus/ExcelRange.cs
new file mode 100644
index 0000000..ada2477
--- /dev/null
+++ b/AppsheetEpplus/ExcelRange.cs
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// A range of cells.
+/// </summary>
+public class ExcelRange : ExcelRangeBase {
+ internal ExcelRange(ExcelWorksheet sheet, string address)
+ : base(sheet, address) {}
+
+ internal ExcelRange(ExcelWorksheet sheet, int fromRow, int fromCol, int toRow, int toCol)
+ : base(sheet) {
+ _fromRow = fromRow;
+ _fromCol = fromCol;
+ _toRow = toRow;
+ _toCol = toCol;
+ }
+
+ /// <summary>
+ /// Access the range using an address
+ /// </summary>
+ /// <param name="address">The address</param>
+ /// <returns>A range object</returns>
+ public ExcelRange this[string address] {
+ get {
+ if (_worksheet.Names.ContainsKey(address)) {
+ if (_worksheet.Names[address].IsName) {
+ return null;
+ }
+ Address = _worksheet.Names[address].Address;
+ } else {
+ Address = address;
+ }
+ return this;
+ }
+ }
+
+ /// <summary>
+ /// Access a single cell
+ /// </summary>
+ /// <param name="row">The row</param>
+ /// <param name="col">The column</param>
+ /// <returns>A range object</returns>
+ public ExcelRange this[int row, int col] {
+ get {
+ ValidateRowCol(row, col);
+
+ _fromCol = col;
+ _fromRow = row;
+ _toCol = col;
+ _toRow = row;
+ Address = GetAddress(_fromRow, _fromCol);
+ return this;
+ }
+ }
+
+ /// <summary>
+ /// Access a range of cells
+ /// </summary>
+ /// <param name="fromRow">Start row</param>
+ /// <param name="fromCol">Start column</param>
+ /// <param name="toRow">End Row</param>
+ /// <param name="toCol">End Column</param>
+ /// <returns></returns>
+ public ExcelRange this[int fromRow, int fromCol, int toRow, int toCol] {
+ get {
+ ValidateRowCol(fromRow, fromCol);
+ ValidateRowCol(toRow, toCol);
+
+ _fromCol = fromCol;
+ _fromRow = fromRow;
+ _toCol = toCol;
+ _toRow = toRow;
+ Address = GetAddress(_fromRow, _fromCol, _toRow, _toCol);
+ return this;
+ }
+ }
+
+ private static void ValidateRowCol(int row, int col) {
+ if (row < 1 || row > ExcelPackage.MaxRows) {
+ throw (new ArgumentException("Row out of range"));
+ }
+ if (col < 1 || col > ExcelPackage.MaxColumns) {
+ throw (new ArgumentException("Column out of range"));
+ }
+ }
+}
diff --git a/AppsheetEpplus/ExcelRangeBase.cs b/AppsheetEpplus/ExcelRangeBase.cs
new file mode 100644
index 0000000..f224f1a
--- /dev/null
+++ b/AppsheetEpplus/ExcelRangeBase.cs
@@ -0,0 +1,1530 @@
+/*******************************************************************************
+ * 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 Initial Release 2010-01-28
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ * Eyal Seagull Conditional Formatting 2012-04-03
+ *******************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Security;
+using System.Text;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// A range of cells
+/// </summary>
+public class ExcelRangeBase
+ : ExcelAddress,
+ IExcelCell,
+ IDisposable,
+ IEnumerable<ExcelRangeBase>,
+ IEnumerator<ExcelRangeBase> {
+ /// <summary>
+ /// Reference to the worksheet
+ /// </summary>
+ protected ExcelWorksheet _worksheet;
+ internal ExcelWorkbook _workbook;
+
+ private delegate void ChangePropHandler(SetValueHandler method, object value);
+
+ private delegate void SetValueHandler(object value, int row, int col);
+
+ private ChangePropHandler _changePropMethod;
+ private int _styleID;
+
+ private class CopiedCell {
+ internal int Row { get; set; }
+
+ internal int Column { get; set; }
+
+ internal object Value { get; set; }
+
+ internal string Type { get; set; }
+
+ internal object Formula { get; set; }
+
+ internal int? StyleID { get; set; }
+
+ internal Uri HyperLink { get; set; }
+
+ internal ExcelComment Comment { get; set; }
+
+ internal Byte Flag { get; set; }
+ }
+
+ //private class CopiedFlag
+ //{
+ // internal int Row { get; set; }
+ // internal int Column { get; set; }
+ // internal Byte Flag { get; set; }
+ //}
+
+
+ internal ExcelRangeBase(ExcelWorksheet worksheet) {
+ _worksheet = worksheet;
+ _ws = _worksheet.Name;
+ _workbook = _worksheet.Workbook;
+ AddressChange += ExcelRangeBase_AddressChange;
+ SetDelegate();
+ }
+
+ private void ExcelRangeBase_AddressChange(object sender, EventArgs e) {
+ if (Table != null) {
+ SetRcFromTable(_workbook, null);
+ }
+ SetDelegate();
+ }
+
+ internal ExcelRangeBase(ExcelWorksheet worksheet, string address)
+ : base(worksheet == null ? "" : worksheet.Name, address) {
+ _worksheet = worksheet;
+ _workbook = worksheet.Workbook;
+ SetRcFromTable(_workbook, null);
+ if (string.IsNullOrEmpty(_ws)) {
+ _ws = _worksheet == null ? "" : _worksheet.Name;
+ }
+ AddressChange += ExcelRangeBase_AddressChange;
+ SetDelegate();
+ }
+
+ internal ExcelRangeBase(ExcelWorkbook wb, ExcelWorksheet xlWorksheet, string address, bool isName)
+ : base(xlWorksheet == null ? "" : xlWorksheet.Name, address, isName) {
+ SetRcFromTable(wb, null);
+ _worksheet = xlWorksheet;
+ _workbook = wb;
+ if (string.IsNullOrEmpty(_ws)) {
+ _ws = xlWorksheet?.Name;
+ }
+ AddressChange += ExcelRangeBase_AddressChange;
+ SetDelegate();
+ }
+
+ ~ExcelRangeBase() {
+ //this.AddressChange -= new EventHandler(ExcelRangeBase_AddressChange);
+ }
+
+ private void SetDelegate() {
+ if (_fromRow == -1) {
+ _changePropMethod = SetUnknown;
+ }
+ //Single cell
+ else if (_fromRow == _toRow && _fromCol == _toCol && Addresses == null) {
+ _changePropMethod = SetSingle;
+ }
+ //Range (ex A1:A2)
+ else if (Addresses == null) {
+ _changePropMethod = SetRange;
+ }
+ //Multi Range (ex A1:A2,C1:C2)
+ else {
+ _changePropMethod = SetMultiRange;
+ }
+ }
+
+ /// <summary>
+ /// We dont know the address yet. Set the delegate first time a property is set.
+ /// </summary>
+ /// <param name="valueMethod"></param>
+ /// <param name="value"></param>
+ private void SetUnknown(SetValueHandler valueMethod, object value) {
+ //Address is not set use, selected range
+ if (_fromRow == -1) {
+ SetToSelectedRange();
+ }
+ SetDelegate();
+ _changePropMethod(valueMethod, value);
+ }
+
+ /// <summary>
+ /// Set a single cell
+ /// </summary>
+ /// <param name="valueMethod"></param>
+ /// <param name="value"></param>
+ private void SetSingle(SetValueHandler valueMethod, object value) {
+ valueMethod(value, _fromRow, _fromCol);
+ }
+
+ /// <summary>
+ /// Set a range
+ /// </summary>
+ /// <param name="valueMethod"></param>
+ /// <param name="value"></param>
+ private void SetRange(SetValueHandler valueMethod, object value) {
+ SetValueAddress(this, valueMethod, value);
+ }
+
+ /// <summary>
+ /// Set a multirange (A1:A2,C1:C2)
+ /// </summary>
+ /// <param name="valueMethod"></param>
+ /// <param name="value"></param>
+ private void SetMultiRange(SetValueHandler valueMethod, object value) {
+ SetValueAddress(this, valueMethod, value);
+ foreach (var address in Addresses) {
+ SetValueAddress(address, valueMethod, value);
+ }
+ }
+
+ /// <summary>
+ /// Set the property for an address
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="valueMethod"></param>
+ /// <param name="value"></param>
+ private void SetValueAddress(ExcelAddress address, SetValueHandler valueMethod, object value) {
+ IsRangeValid("");
+ if (_fromRow == 1
+ && _fromCol == 1
+ && _toRow == ExcelPackage.MaxRows
+ && _toCol
+ == ExcelPackage.MaxColumns) //Full sheet (ex ws.Cells.Value=0). Set value for A1 only to avoid hanging
+ {
+ throw (new ArgumentException(
+ "Can't reference all cells. Please use the indexer to set the range"));
+ }
+ for (int col = address.Start.Column; col <= address.End.Column; col++) {
+ for (int row = address.Start.Row; row <= address.End.Row; row++) {
+ valueMethod(value, row, col);
+ }
+ }
+ }
+
+ private void Set_StyleID(object value, int row, int col) {
+ _worksheet._styles.SetValue(row, col, (int)value);
+ }
+
+ private void Set_Value(object value, int row, int col) {
+ //ExcelCell c = _worksheet.Cell(row, col);
+ var sfi = _worksheet._formulas.GetValue(row, col);
+ if (sfi is int) {
+ SplitFormulas(_worksheet.Cells[row, col]);
+ }
+ if (sfi != null) {
+ _worksheet._formulas.SetValue(row, col, string.Empty);
+ }
+ _worksheet._values.SetValue(row, col, value);
+ }
+
+ private void Set_Formula(object value, int row, int col) {
+ //ExcelCell c = _worksheet.Cell(row, col);
+ var f = _worksheet._formulas.GetValue(row, col);
+ if (f is int i && i >= 0) {
+ SplitFormulas(_worksheet.Cells[row, col]);
+ }
+
+ string formula = (value == null ? string.Empty : value.ToString());
+ if (formula == string.Empty) {
+ _worksheet._formulas.SetValue(row, col, string.Empty);
+ } else {
+ if (formula[0] == '=') {
+ value = formula.Substring(1, formula.Length - 1); // remove any starting equalsign.
+ }
+ _worksheet._formulas.SetValue(row, col, formula);
+ _worksheet._values.SetValue(row, col, null);
+ }
+ }
+
+ /// <summary>
+ /// Handles shared formulas
+ /// </summary>
+ /// <param name="value">The formula</param>
+ /// <param name="address">The address of the formula</param>
+ /// <param name="isArray">If the forumla is an array formula.</param>
+ private void Set_SharedFormula(string value, ExcelAddress address, bool isArray) {
+ if (_fromRow == 1
+ && _fromCol == 1
+ && _toRow == ExcelPackage.MaxRows
+ && _toCol
+ == ExcelPackage.MaxColumns) //Full sheet (ex ws.Cells.Value=0). Set value for A1 only to avoid hanging
+ {
+ throw (new InvalidOperationException("Can't set a formula for the entire worksheet"));
+ }
+ if (address.Start.Row == address.End.Row
+ && address.Start.Column == address.End.Column
+ && !isArray) //is it really a shared formula? Arrayformulas can be one cell only
+ {
+ //Nope, single cell. Set the formula
+ Set_Formula(value, address.Start.Row, address.Start.Column);
+ return;
+ }
+ //RemoveFormuls(address);
+ CheckAndSplitSharedFormula(address);
+ ExcelWorksheet.Formulas f = new ExcelWorksheet.Formulas(SourceCodeTokenizer.Default);
+ f.Formula = value;
+ f.Index = _worksheet.GetMaxShareFunctionIndex(isArray);
+ f.Address = address.FirstAddress;
+ f.StartCol = address.Start.Column;
+ f.StartRow = address.Start.Row;
+ f.IsArray = isArray;
+
+ _worksheet._sharedFormulas.Add(f.Index, f);
+ //_worksheet.Cell(address.Start.Row, address.Start.Column).SharedFormulaID = f.Index;
+ //_worksheet.Cell(address.Start.Row, address.Start.Column).Formula = value;
+
+ for (int col = address.Start.Column; col <= address.End.Column; col++) {
+ for (int row = address.Start.Row; row <= address.End.Row; row++) {
+ //_worksheet.Cell(row, col).SharedFormulaID = f.Index;
+ _worksheet._formulas.SetValue(row, col, f.Index);
+ _worksheet._values.SetValue(row, col, null);
+ }
+ }
+ }
+
+ private void Set_HyperLink(object value, int row, int col) {
+ //_worksheet.Cell(row, col).Hyperlink = value as Uri;
+ if (value is Uri uri) {
+ _worksheet._hyperLinks.SetValue(row, col, uri);
+
+ if (uri is ExcelHyperLink link) {
+ _worksheet._values.SetValue(row, col, link.Display);
+ } else {
+ _worksheet._values.SetValue(row, col, uri.OriginalString);
+ }
+ } else {
+ _worksheet._hyperLinks.SetValue(row, col, null);
+ _worksheet._values.SetValue(row, col, null);
+ }
+ }
+
+ private void Set_IsArrayFormula(object value, int row, int col) {
+ _worksheet._flags.SetFlagValue(row, col, (bool)value, CellFlags.ArrayFormula);
+ }
+
+ private void Set_IsRichText(object value, int row, int col) {
+ //_worksheet.Cell(row, col).IsRichText = (bool)value;
+ _worksheet._flags.SetFlagValue(row, col, (bool)value, CellFlags.RichText);
+ }
+
+ private void Exists_Comment(object value, int row, int col) {
+ ulong cellId = GetCellId(_worksheet.SheetID, row, col);
+ if (_worksheet.Comments._comments.ContainsKey(cellId)) {
+ throw (new InvalidOperationException(
+ string.Format(
+ "Cell {0} already contain a comment.",
+ new ExcelCellAddress(row, col).Address)));
+ }
+ }
+
+ private void SetToSelectedRange() {
+ if (_worksheet.View.SelectedRange == "") {
+ Address = "A1";
+ } else {
+ Address = _worksheet.View.SelectedRange;
+ }
+ }
+
+ private void IsRangeValid(string type) {
+ if (_fromRow <= 0) {
+ if (_address == "") {
+ SetToSelectedRange();
+ } else {
+ if (type == "") {
+ throw (new InvalidOperationException(
+ string.Format("Range is not valid for this operation: {0}", _address)));
+ }
+ throw (new InvalidOperationException(
+ string.Format("Range is not valid for {0} : {1}", type, _address)));
+ }
+ }
+ }
+
+ /// <summary>
+ /// The styleobject for the range.
+ /// </summary>
+ public ExcelStyle Style {
+ get {
+ IsRangeValid("styling");
+ int s = 0;
+ if (!_worksheet._styles.Exists(
+ _fromRow,
+ _fromCol,
+ ref s)) //Cell exists
+ {
+ if (!_worksheet._styles.Exists(
+ _fromRow,
+ 0,
+ ref s)) //No, check Row style
+ {
+ var c = Worksheet.GetColumn(_fromCol);
+ if (c == null) {
+ s = 0;
+ } else {
+ s = c.StyleID;
+ }
+ }
+ }
+ return _worksheet.Workbook.Styles.GetStyleObject(s, _worksheet.PositionID, Address);
+ }
+ }
+
+ /// <summary>
+ /// The named style
+ /// </summary>
+ public string StyleName {
+ get {
+ IsRangeValid("styling");
+ int xfId;
+ if (_fromRow == 1 && _toRow == ExcelPackage.MaxRows) {
+ xfId = GetColumnStyle(_fromCol);
+ } else if (_fromCol == 1 && _toCol == ExcelPackage.MaxColumns) {
+ xfId = 0;
+ if (!_worksheet._styles.Exists(_fromRow, 0, ref xfId)) {
+ xfId = GetColumnStyle(_fromCol);
+ }
+ } else {
+ xfId = 0;
+ if (!_worksheet._styles.Exists(_fromRow, _fromCol, ref xfId)) {
+ if (!_worksheet._styles.Exists(_fromRow, 0, ref xfId)) {
+ xfId = GetColumnStyle(_fromCol);
+ }
+ }
+ }
+ int nsId;
+ if (xfId <= 0) {
+ nsId = Style.Styles.CellXfs[0].XfId;
+ } else {
+ nsId = Style.Styles.CellXfs[xfId].XfId;
+ }
+ foreach (var ns in Style.Styles.NamedStyles) {
+ if (ns.StyleXfId == nsId) {
+ return ns.Name;
+ }
+ }
+
+ return "";
+ }
+ set {
+ _styleID = _worksheet.Workbook.Styles.GetStyleIdFromName(value);
+ int col = _fromCol;
+ if (_fromRow == 1
+ && _toRow
+ == ExcelPackage.MaxRows) //Full column
+ {
+ ExcelColumn column;
+ //Get the startcolumn
+ //ulong colID = ExcelColumn.GetColumnID(_worksheet.SheetID, column);
+ var c = _worksheet.GetValue(0, _fromCol);
+ if (c == null) {
+ column = _worksheet.Column(_fromCol);
+ //if (_worksheet._values.PrevCell(ref row, ref col))
+ //{
+ // var prevCol = (ExcelColumn)_worksheet._values.GetValue(row, col);
+ // column = prevCol.Clone(_worksheet, column);
+ // prevCol.ColumnMax = column - 1;
+ //}
+ } else {
+ column = (ExcelColumn)c;
+ }
+
+ column.StyleName = value;
+ column.StyleID = _styleID;
+
+ //var index = _worksheet._columns.IndexOf(colID);
+ var cols = new CellsStoreEnumerator<object>(_worksheet._values, 0, _fromCol + 1, 0, _toCol);
+ if (cols.Next()) {
+ col = _fromCol;
+ while (column.ColumnMin <= _toCol) {
+ if (column.ColumnMax > _toCol) {
+ var newCol = _worksheet.CopyColumn(column, _toCol + 1, column.ColumnMax);
+ column.ColumnMax = _toCol;
+ }
+
+ column._styleName = value;
+ column.StyleID = _styleID;
+
+ if (cols.Value == null) {
+ break;
+ }
+ var nextCol = (ExcelColumn)cols.Value;
+ if (column.ColumnMax < nextCol.ColumnMax - 1) {
+ column.ColumnMax = nextCol.ColumnMax - 1;
+ }
+ column = nextCol;
+ cols.Next();
+ }
+ }
+ if (column.ColumnMax < _toCol) {
+ column.ColumnMax = _toCol;
+ }
+ //if (column.ColumnMin == column)
+ //{
+ // column.ColumnMax = _toCol;
+ //}
+ //else if (column._columnMax < _toCol)
+ //{
+ // var newCol = _worksheet.Column(column._columnMax + 1) as ExcelColumn;
+ // newCol._columnMax = _toCol;
+
+ // newCol._styleID = _styleID;
+ // newCol._styleName = value;
+ //}
+ if (_fromCol == 1
+ && _toCol
+ == ExcelPackage.MaxColumns) //FullRow
+ {
+ var rows = new CellsStoreEnumerator<object>(
+ _worksheet._values,
+ 1,
+ 0,
+ ExcelPackage.MaxRows,
+ 0);
+ rows.Next();
+ while (rows.Value != null) {
+ _worksheet._styles.SetValue(rows.Row, 0, _styleID);
+ if (!rows.Next()) {
+ break;
+ }
+ }
+ }
+ } else if (_fromCol == 1
+ && _toCol
+ == ExcelPackage.MaxColumns) //FullRow
+ {
+ for (int r = _fromRow; r <= _toRow; r++) {
+ _worksheet.Row(r)._styleName = value;
+ _worksheet.Row(r).StyleID = _styleID;
+ }
+ }
+
+ if (!((_fromRow == 1 && _toRow == ExcelPackage.MaxRows)
+ || (_fromCol == 1
+ && _toCol
+ == ExcelPackage.MaxColumns))) //Cell specific
+ {
+ for (int c = _fromCol; c <= _toCol; c++) {
+ for (int r = _fromRow; r <= _toRow; r++) {
+ _worksheet._styles.SetValue(r, c, _styleID);
+ }
+ }
+ } else //Only set name on created cells. (uncreated cells is set on full row or full column).
+ {
+ var cells = new CellsStoreEnumerator<object>(
+ _worksheet._values,
+ _fromRow,
+ _fromCol,
+ _toRow,
+ _toCol);
+ while (cells.Next()) {
+ _worksheet._styles.SetValue(cells.Row, cells.Column, _styleID);
+ }
+ }
+ //_changePropMethod(Set_StyleName, value);
+ }
+ }
+
+ private int GetColumnStyle(int col) {
+ object c = null;
+ if (_worksheet._values.Exists(0, col, ref c)) {
+ return (c as ExcelColumn).StyleID;
+ }
+ int row = 0;
+ if (_worksheet._values.PrevCell(ref row, ref col)) {
+ var column = _worksheet._values.GetValue(row, col) as ExcelColumn;
+ if (column.ColumnMax >= col) {
+ return _worksheet._styles.GetValue(row, col);
+ }
+ }
+ return 0;
+ }
+
+ /// <summary>
+ /// The style ID.
+ /// It is not recomended to use this one. Use Named styles as an alternative.
+ /// If you do, make sure that you use the Style.UpdateXml() method to update any new styles added to the workbook.
+ /// </summary>
+ public int StyleID {
+ get {
+ int s = 0;
+ if (!_worksheet._styles.Exists(_fromRow, _fromCol, ref s)) {
+ if (!_worksheet._styles.Exists(_fromRow, 0, ref s)) {
+ s = _worksheet._styles.GetValue(0, _fromCol);
+ }
+ }
+ return s;
+ }
+ set => _changePropMethod(Set_StyleID, value);
+ }
+
+ /// <summary>
+ /// Set the range to a specific value
+ /// </summary>
+ public object Value {
+ get {
+ if (IsName) {
+ if (_worksheet == null) {
+ return _workbook._names[_address].NameValue;
+ }
+ return _worksheet.Names[_address].NameValue;
+ }
+ if (_fromRow == _toRow && _fromCol == _toCol) {
+ return _worksheet.GetValue(_fromRow, _fromCol);
+ }
+ return GetValueArray();
+ }
+ set {
+ if (IsName) {
+ if (_worksheet == null) {
+ _workbook._names[_address].NameValue = value;
+ } else {
+ _worksheet.Names[_address].NameValue = value;
+ }
+ } else {
+ _changePropMethod(Set_Value, value);
+ }
+ }
+ }
+
+ private object GetValueArray() {
+ ExcelAddressBase addr;
+ if (_fromRow == 1
+ && _fromCol == 1
+ && _toRow == ExcelPackage.MaxRows
+ && _toCol == ExcelPackage.MaxColumns) {
+ addr = _worksheet.Dimension;
+ if (addr == null) {
+ return null;
+ }
+ } else {
+ addr = this;
+ }
+ object[,] v = new object[addr._toRow - addr._fromRow + 1, addr._toCol - addr._fromCol + 1];
+
+ for (int col = addr._fromCol; col <= addr._toCol; col++) {
+ for (int row = addr._fromRow; row <= addr._toRow; row++) {
+ if (_worksheet._values.Exists(row, col)) {
+ if (_worksheet._flags.GetFlagValue(row, col, CellFlags.RichText)) {
+ v[row - addr._fromRow, col - addr._fromCol] = GetRichText(row, col).Text;
+ } else {
+ v[row - addr._fromRow, col - addr._fromCol] = _worksheet._values.GetValue(row, col);
+ }
+ }
+ }
+ }
+ return v;
+ }
+
+ /// <summary>
+ /// Returns the formatted value.
+ /// </summary>
+ public string Text => GetFormattedText(false);
+
+ private string GetFormattedText(bool forWidthCalc) {
+ object v = Value;
+ if (v == null) {
+ return "";
+ }
+ var styles = Worksheet.Workbook.Styles;
+ var nfId = styles.CellXfs[StyleID].NumberFormatId;
+ ExcelNumberFormatXml.ExcelFormatTranslator nf = null;
+ for (int i = 0; i < styles.NumberFormats.Count; i++) {
+ if (nfId == styles.NumberFormats[i].NumFmtId) {
+ nf = styles.NumberFormats[i].FormatTranslator;
+ break;
+ }
+ }
+
+ string format,
+ textFormat;
+ if (forWidthCalc) {
+ format = nf.NetFormatForWidth;
+ textFormat = nf.NetTextFormatForWidth;
+ } else {
+ format = nf.NetFormat;
+ textFormat = nf.NetTextFormat;
+ }
+
+ return FormatValue(v, nf, format, textFormat);
+ }
+
+ internal static string FormatValue(
+ object v,
+ ExcelNumberFormatXml.ExcelFormatTranslator nf,
+ string format,
+ string textFormat) {
+ if (v is decimal || v.GetType().IsPrimitive) {
+ double d;
+ try {
+ d = Convert.ToDouble(v);
+ } catch {
+ return "";
+ }
+
+ if (nf.DataType == ExcelNumberFormatXml.eFormatType.Number) {
+ if (string.IsNullOrEmpty(nf.FractionFormat)) {
+ return d.ToString(format, nf.Culture);
+ }
+ return nf.FormatFraction(d);
+ }
+ if (nf.DataType == ExcelNumberFormatXml.eFormatType.DateTime) {
+ var date = DateTime.FromOADate(d);
+ return date.ToString(format, nf.Culture);
+ }
+ } else if (v is DateTime time) {
+ if (nf.DataType == ExcelNumberFormatXml.eFormatType.DateTime) {
+ return time.ToString(format, nf.Culture);
+ }
+ double d = time.ToOADate();
+ if (string.IsNullOrEmpty(nf.FractionFormat)) {
+ return d.ToString(format, nf.Culture);
+ }
+ return nf.FormatFraction(d);
+ } else if (v is TimeSpan span) {
+ if (nf.DataType == ExcelNumberFormatXml.eFormatType.DateTime) {
+ return new DateTime(span.Ticks).ToString(format, nf.Culture);
+ }
+ double d = (new DateTime(span.Ticks)).ToOADate();
+ if (string.IsNullOrEmpty(nf.FractionFormat)) {
+ return d.ToString(format, nf.Culture);
+ }
+ return nf.FormatFraction(d);
+ } else {
+ if (textFormat == "") {
+ return v.ToString();
+ }
+ return string.Format(textFormat, v);
+ }
+ return v.ToString();
+ }
+
+ /// <summary>
+ /// Gets or sets a formula for a range.
+ /// </summary>
+ public string Formula {
+ get {
+ if (IsName) {
+ if (_worksheet == null) {
+ return _workbook._names[_address].NameFormula;
+ }
+ return _worksheet.Names[_address].NameFormula;
+ }
+ return _worksheet.GetFormula(_fromRow, _fromCol);
+ }
+ set {
+ if (IsName) {
+ if (_worksheet == null) {
+ _workbook._names[_address].NameFormula = value;
+ } else {
+ _worksheet.Names[_address].NameFormula = value;
+ }
+ } else {
+ if (value == null || value.Trim() == "") {
+ //Set the cells to null
+ Value = null;
+ } else if (_fromRow == _toRow && _fromCol == _toCol) {
+ Set_Formula(value, _fromRow, _fromCol);
+ } else {
+ Set_SharedFormula(value, this, false);
+ if (Addresses != null) {
+ foreach (var address in Addresses) {
+ Set_SharedFormula(value, address, false);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or Set a formula in R1C1 format.
+ /// </summary>
+ public string FormulaR1C1 {
+ get {
+ IsRangeValid("FormulaR1C1");
+ return _worksheet.GetFormulaR1C1(_fromRow, _fromCol);
+ }
+ set {
+ IsRangeValid("FormulaR1C1");
+ if (value.Length > 0 && value[0] == '=') {
+ value = value.Substring(1, value.Length - 1); // remove any starting equalsign.
+ }
+
+ if (value == null || value.Trim() == "") {
+ //Set the cells to null
+ _worksheet.Cells[TranslateFromR1C1(value, _fromRow, _fromCol)].Value = null;
+ } else if (Addresses == null) {
+ Set_SharedFormula(TranslateFromR1C1(value, _fromRow, _fromCol), this, false);
+ } else {
+ Set_SharedFormula(
+ TranslateFromR1C1(value, _fromRow, _fromCol),
+ new(WorkSheet, FirstAddress),
+ false);
+ foreach (var address in Addresses) {
+ Set_SharedFormula(
+ TranslateFromR1C1(value, address.Start.Row, address.Start.Column),
+ address,
+ false);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or Set a formula in R1C1 format.
+ ///
+ public string FormulaR1C1_V1 {
+ get {
+ IsRangeValid("FormulaR1C1");
+ return _worksheet.GetFormulaR1C1_V1(_fromRow, _fromCol);
+ }
+ }
+
+ public string ArrayFormulaAddress {
+ get {
+ IsRangeValid("FormulaR1C1");
+ return _worksheet.GetArrayFormulaAddress(_fromRow, _fromCol);
+ }
+ }
+
+ /// <summary>
+ /// Set the hyperlink property for a range of cells
+ /// </summary>
+ public Uri Hyperlink {
+ get {
+ IsRangeValid("formulaR1C1");
+ return _worksheet._hyperLinks.GetValue(_fromRow, _fromCol);
+ }
+ set => _changePropMethod(Set_HyperLink, value);
+ }
+
+ /// <summary>
+ /// If the cells in the range are merged.
+ /// </summary>
+ public bool Merge {
+ get {
+ IsRangeValid("merging");
+ for (int col = _fromCol; col <= _toCol; col++) {
+ for (int row = _fromRow; row <= _toRow; row++) {
+ if (_worksheet.MergedCells[row, col] == null) {
+ return false;
+ }
+ //if (!_worksheet._flags.GetFlagValue(row, col, CellFlags.Merged))
+ //{
+ // return false;
+ //}
+ }
+ }
+ return true;
+ }
+ set {
+ IsRangeValid("merging");
+ //SetMerge(value, FirstAddress);
+ if (value) {
+ _worksheet.MergedCells.Add(new(FirstAddress), true);
+ if (Addresses != null) {
+ foreach (var address in Addresses) {
+ _worksheet.MergedCells.Add(address, true);
+ //SetMerge(value, address._address);
+ }
+ }
+ } else {
+ _worksheet.MergedCells.Clear(this);
+ if (Addresses != null) {
+ foreach (var address in Addresses) {
+ _worksheet.MergedCells.Clear(address);
+ ;
+ }
+ }
+ }
+ }
+ }
+
+ //private void SetMerge(bool value, string address)
+ //{
+ // if (!value)
+ // {
+ // if (_worksheet.MergedCells.List.Contains(address))
+ // {
+ // SetCellMerge(false, address);
+ // _worksheet.MergedCells.List.Remove(address);
+ // }
+ // else if (!CheckMergeDiff(false, address))
+ // {
+ // throw (new Exception("Range is not fully merged.Specify the exact range"));
+ // }
+ // }
+ // else
+ // {
+ // if (CheckMergeDiff(false, address))
+ // {
+ // SetCellMerge(true, address);
+ // _worksheet.MergedCells.List.Add(address);
+ // }
+ // else
+ // {
+ // if (!_worksheet.MergedCells.List.Contains(address))
+ // {
+ // throw (new Exception("Cells are already merged"));
+ // }
+ // }
+ // }
+ //}
+ /// <summary>
+ /// Set an autofilter for the range
+ /// </summary>
+ public bool AutoFilter {
+ get {
+ IsRangeValid("autofilter");
+ ExcelAddressBase address = _worksheet.AutoFilterAddress;
+ if (address == null) {
+ return false;
+ }
+ if (_fromRow >= address.Start.Row
+ && _toRow <= address.End.Row
+ && _fromCol >= address.Start.Column
+ && _toCol <= address.End.Column) {
+ return true;
+ }
+ return false;
+ }
+ set {
+ IsRangeValid("autofilter");
+ _worksheet.AutoFilterAddress = this;
+ if (_worksheet.Names.ContainsKey("_xlnm._FilterDatabase")) {
+ _worksheet.Names.Remove("_xlnm._FilterDatabase");
+ }
+ var result = _worksheet.Names.Add("_xlnm._FilterDatabase", this);
+ result.IsNameHidden = true;
+ }
+ }
+
+ /// <summary>
+ /// If the value is in richtext format.
+ /// </summary>
+ public bool IsRichText {
+ get {
+ IsRangeValid("richtext");
+ return _worksheet._flags.GetFlagValue(_fromRow, _fromCol, CellFlags.RichText);
+ }
+ set => _changePropMethod(Set_IsRichText, value);
+ }
+
+ /// <summary>
+ /// Is the range a part of an Arrayformula
+ /// </summary>
+ public bool IsArrayFormula {
+ get {
+ IsRangeValid("arrayformulas");
+ return _worksheet._flags.GetFlagValue(_fromRow, _fromCol, CellFlags.ArrayFormula);
+ }
+ set => _changePropMethod(Set_IsArrayFormula, value);
+ }
+
+ private ExcelRichTextCollection _rtc;
+
+ /// <summary>
+ /// Cell value is richtext formatted.
+ /// Richtext-property only apply to the left-top cell of the range.
+ /// </summary>
+ public ExcelRichTextCollection RichText {
+ get {
+ IsRangeValid("richtext");
+ if (_rtc == null) {
+ _rtc = GetRichText(_fromRow, _fromCol);
+ }
+ return _rtc;
+ }
+ }
+
+ private ExcelRichTextCollection GetRichText(int row, int col) {
+ XmlDocument xml = new XmlDocument();
+ var v = _worksheet._values.GetValue(row, col);
+ var isRt = _worksheet._flags.GetFlagValue(row, col, CellFlags.RichText);
+ if (v != null) {
+ if (isRt) {
+ XmlHelper.LoadXmlSafe(
+ xml,
+ "<d:si xmlns:d=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" >"
+ + v
+ + "</d:si>",
+ Encoding.UTF8);
+ } else {
+ xml.LoadXml(
+ "<d:si xmlns:d=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" ><d:r><d:t>"
+ + SecurityElement.Escape(v.ToString())
+ + "</d:t></d:r></d:si>");
+ }
+ } else {
+ xml.LoadXml("<d:si xmlns:d=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" />");
+ }
+ var rtc = new ExcelRichTextCollection(
+ _worksheet.NameSpaceManager,
+ xml.SelectSingleNode("d:si", _worksheet.NameSpaceManager),
+ this);
+ return rtc;
+ }
+
+ /// <summary>
+ /// returns the comment object of the first cell in the range
+ /// </summary>
+ public ExcelComment Comment {
+ get {
+ IsRangeValid("comments");
+ ulong cellId = GetCellId(_worksheet.SheetID, _fromRow, _fromCol);
+ if (_worksheet.Comments._comments.ContainsKey(cellId)) {
+ return _worksheet._comments._comments[cellId] as ExcelComment;
+ }
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// WorkSheet object
+ /// </summary>
+ public ExcelWorksheet Worksheet => _worksheet;
+
+ /// <summary>
+ /// Address including sheetname
+ /// </summary>
+ public string FullAddress {
+ get {
+ string fullAddress = GetFullAddress(_worksheet.Name, _address);
+ if (Addresses != null) {
+ foreach (var a in Addresses) {
+ fullAddress += "," + GetFullAddress(_worksheet.Name, a.Address);
+ ;
+ }
+ }
+ return fullAddress;
+ }
+ }
+
+ /// <summary>
+ /// Address including sheetname
+ /// </summary>
+ public string FullAddressAbsolute {
+ get {
+ string wbwsRef = string.IsNullOrEmpty(_wb) ? _ws : "[" + _wb.Replace("'", "''") + "]" + _ws;
+ string fullAddress = GetFullAddress(
+ wbwsRef,
+ GetAddress(_fromRow, _fromCol, _toRow, _toCol, true));
+ if (Addresses != null) {
+ foreach (var a in Addresses) {
+ fullAddress +=
+ ","
+ + GetFullAddress(
+ wbwsRef,
+ GetAddress(a.Start.Row, a.Start.Column, a.End.Row, a.End.Column, true));
+ ;
+ }
+ }
+ return fullAddress;
+ }
+ }
+
+ /// <summary>
+ /// Address including sheetname
+ /// </summary>
+ internal string FullAddressAbsoluteNoFullRowCol {
+ get {
+ string wbwsRef = string.IsNullOrEmpty(_wb) ? _ws : "[" + _wb.Replace("'", "''") + "]" + _ws;
+ string fullAddress = GetFullAddress(
+ wbwsRef,
+ GetAddress(_fromRow, _fromCol, _toRow, _toCol, true),
+ false);
+ if (Addresses != null) {
+ foreach (var a in Addresses) {
+ fullAddress +=
+ ","
+ + GetFullAddress(
+ wbwsRef,
+ GetAddress(a.Start.Row, a.Start.Column, a.End.Row, a.End.Column, true),
+ false);
+ ;
+ }
+ }
+ return fullAddress;
+ }
+ }
+
+ /// <summary>
+ /// Set the value without altering the richtext property
+ /// </summary>
+ /// <param name="value">the value</param>
+ internal void SetValueRichText(object value) {
+ if (_fromRow == 1
+ && _fromCol == 1
+ && _toRow == ExcelPackage.MaxRows
+ && _toCol
+ == ExcelPackage.MaxColumns) //Full sheet (ex ws.Cells.Value=0). Set value for A1 only to avoid hanging
+ {
+ //_worksheet.Cell(1, 1).SetValueRichText(value);
+ SetValue(value, 1, 1);
+ } else {
+ //for (int col = _fromCol; col <= _toCol; col++)
+ //{
+ // for (int row = _fromRow; row <= _toRow; row++)
+ // {
+ //_worksheet.Cell(row, col).SetValueRichText(value);
+ SetValue(value, _fromRow, _fromCol);
+ //}
+ //}
+ }
+ }
+
+ private void SetValue(object value, int row, int col) {
+ _worksheet.SetValue(row, col, value);
+ // if (value is string) _worksheet._types.SetValue(row, col, "S"); else _worksheet._types.SetValue(row, col, "");
+ _worksheet._formulas.SetValue(row, col, "");
+ }
+
+ internal void SetSharedFormulaId(int id) {
+ for (int col = _fromCol; col <= _toCol; col++) {
+ for (int row = _fromRow; row <= _toRow; row++) {
+ _worksheet._formulas.SetValue(row, col, id);
+ }
+ }
+ }
+
+ private void CheckAndSplitSharedFormula(ExcelAddressBase address) {
+ for (int col = address._fromCol; col <= address._toCol; col++) {
+ for (int row = address._fromRow; row <= address._toRow; row++) {
+ var f = _worksheet._formulas.GetValue(row, col);
+ if (f is int i && i >= 0) {
+ SplitFormulas(address);
+ return;
+ }
+ }
+ }
+ }
+
+ private void SplitFormulas(ExcelAddressBase address) {
+ List<int> formulas = [];
+ for (int col = address._fromCol; col <= address._toCol; col++) {
+ for (int row = address._fromRow; row <= address._toRow; row++) {
+ var f = _worksheet._formulas.GetValue(row, col);
+ if (f is int id) {
+ if (id >= 0 && !formulas.Contains(id)) {
+ if (_worksheet._sharedFormulas[id].IsArray
+ && Collide(_worksheet.Cells[_worksheet._sharedFormulas[id].Address])
+ == eAddressCollition.Partly) // If the formula is an array formula and its on the inside the overwriting range throw an exception
+ {
+ throw (new InvalidOperationException("Can not overwrite a part of an array-formula"));
+ }
+ formulas.Add(id);
+ }
+ }
+ }
+ }
+
+ foreach (int ix in formulas) {
+ SplitFormula(address, ix);
+ }
+
+ ////Clear any formula references inside the refered range
+ //_worksheet._formulas.Clear(address._fromRow, address._toRow, address._toRow - address._fromRow + 1, address._toCol - address.column + 1);
+ }
+
+ private void SplitFormula(ExcelAddressBase address, int ix) {
+ var f = _worksheet._sharedFormulas[ix];
+ var fRange = _worksheet.Cells[f.Address];
+ var collide = address.Collide(fRange);
+
+ //The formula is inside the currenct range, remove it
+ if (collide == eAddressCollition.Equal || collide == eAddressCollition.Inside) {
+ _worksheet._sharedFormulas.Remove(ix);
+ return;
+ //fRange.SetSharedFormulaID(int.MinValue);
+ }
+ var firstCellCollide = address.Collide(
+ new(fRange._fromRow, fRange._fromCol, fRange._fromRow, fRange._fromCol));
+ if (collide == eAddressCollition.Partly
+ && (firstCellCollide == eAddressCollition.Inside
+ || firstCellCollide
+ == eAddressCollition.Equal)) //Do we need to split? Only if the functions first row is inside the new range.
+ {
+ //The formula partly collides with the current range
+ bool fIsSet = false;
+ string formulaR1C1 = fRange.FormulaR1C1;
+ //Top Range
+ if (fRange._fromRow < _fromRow) {
+ f.Address = GetAddress(fRange._fromRow, fRange._fromCol, _fromRow - 1, fRange._toCol);
+ fIsSet = true;
+ }
+ //Left Range
+ if (fRange._fromCol < address._fromCol) {
+ if (fIsSet) {
+ f = new(SourceCodeTokenizer.Default);
+ f.Index = _worksheet.GetMaxShareFunctionIndex(false);
+ f.StartCol = fRange._fromCol;
+ f.IsArray = false;
+ _worksheet._sharedFormulas.Add(f.Index, f);
+ } else {
+ fIsSet = true;
+ }
+ if (fRange._fromRow < address._fromRow) {
+ f.StartRow = address._fromRow;
+ } else {
+ f.StartRow = fRange._fromRow;
+ }
+ if (fRange._toRow < address._toRow) {
+ f.Address = GetAddress(f.StartRow, f.StartCol, fRange._toRow, address._fromCol - 1);
+ } else {
+ f.Address = GetAddress(f.StartRow, f.StartCol, address._toRow, address._fromCol - 1);
+ }
+ f.Formula = TranslateFromR1C1(formulaR1C1, f.StartRow, f.StartCol);
+ _worksheet.Cells[f.Address].SetSharedFormulaId(f.Index);
+ }
+ //Right Range
+ if (fRange._toCol > address._toCol) {
+ if (fIsSet) {
+ f = new(SourceCodeTokenizer.Default);
+ f.Index = _worksheet.GetMaxShareFunctionIndex(false);
+ f.IsArray = false;
+ _worksheet._sharedFormulas.Add(f.Index, f);
+ } else {
+ fIsSet = true;
+ }
+ f.StartCol = address._toCol + 1;
+ if (address._fromRow < fRange._fromRow) {
+ f.StartRow = fRange._fromRow;
+ } else {
+ f.StartRow = address._fromRow;
+ }
+
+ if (fRange._toRow < address._toRow) {
+ f.Address = GetAddress(f.StartRow, f.StartCol, fRange._toRow, fRange._toCol);
+ } else {
+ f.Address = GetAddress(f.StartRow, f.StartCol, address._toRow, fRange._toCol);
+ }
+ f.Formula = TranslateFromR1C1(formulaR1C1, f.StartRow, f.StartCol);
+ _worksheet.Cells[f.Address].SetSharedFormulaId(f.Index);
+ }
+ //Bottom Range
+ if (fRange._toRow > address._toRow) {
+ if (fIsSet) {
+ f = new(SourceCodeTokenizer.Default);
+ f.Index = _worksheet.GetMaxShareFunctionIndex(false);
+ f.IsArray = false;
+ _worksheet._sharedFormulas.Add(f.Index, f);
+ }
+
+ f.StartCol = fRange._fromCol;
+ f.StartRow = _toRow + 1;
+
+ f.Formula = TranslateFromR1C1(formulaR1C1, f.StartRow, f.StartCol);
+
+ f.Address = GetAddress(f.StartRow, f.StartCol, fRange._toRow, fRange._toCol);
+ _worksheet.Cells[f.Address].SetSharedFormulaId(f.Index);
+ }
+ }
+ }
+
+ private object ConvertData(ExcelTextFormat format, string v, int col, bool isText) {
+ if (isText && (format.DataTypes == null || format.DataTypes.Length < col)) {
+ return v;
+ }
+
+ double d;
+ DateTime dt;
+ if (format.DataTypes == null
+ || format.DataTypes.Length <= col
+ || format.DataTypes[col] == eDataTypes.Unknown) {
+ string v2 = v.EndsWith("%") ? v.Substring(0, v.Length - 1) : v;
+ if (double.TryParse(v2, NumberStyles.Any, format.Culture, out d)) {
+ if (v2 == v) {
+ return d;
+ }
+ return d / 100;
+ }
+ if (DateTime.TryParse(v, format.Culture, DateTimeStyles.None, out dt)) {
+ return dt;
+ }
+ return v;
+ }
+ switch (format.DataTypes[col]) {
+ case eDataTypes.Number:
+ if (double.TryParse(v, NumberStyles.Any, format.Culture, out d)) {
+ return d;
+ }
+ return v;
+ case eDataTypes.DateTime:
+ if (DateTime.TryParse(v, format.Culture, DateTimeStyles.None, out dt)) {
+ return dt;
+ }
+ return v;
+ case eDataTypes.Percent:
+ string v2 = v.EndsWith("%") ? v.Substring(0, v.Length - 1) : v;
+ if (double.TryParse(v2, NumberStyles.Any, format.Culture, out d)) {
+ return d / 100;
+ }
+ return v;
+
+ default:
+ return v;
+ }
+ }
+
+ /// <summary>
+ /// Conditional Formatting for this range.
+ /// </summary>
+ public IRangeConditionalFormatting ConditionalFormatting =>
+ new RangeConditionalFormatting(_worksheet, new(Address));
+
+ /// <summary>
+ /// Data validation for this range.
+ /// </summary>
+ public IRangeDataValidation DataValidation => new RangeDataValidation(_worksheet, Address);
+
+ /// <summary>
+ /// Get the strongly typed value of the cell.
+ /// </summary>
+ /// <typeparam name="T">The type</typeparam>
+ /// <returns>The value. If the value can't be converted to the specified type, the default value will be returned</returns>
+ public T GetValue<T>() {
+ return _worksheet.GetTypedValue<T>(Value);
+ }
+
+ /// <summary>
+ /// Get a range with an offset from the top left cell.
+ /// The new range has the same dimensions as the current range
+ /// </summary>
+ /// <param name="rowOffset">Row Offset</param>
+ /// <param name="columnOffset">Column Offset</param>
+ /// <returns></returns>
+ public ExcelRangeBase Offset(int rowOffset, int columnOffset) {
+ if (_fromRow + rowOffset < 1
+ || _fromCol + columnOffset < 1
+ || _fromRow + rowOffset > ExcelPackage.MaxRows
+ || _fromCol + columnOffset > ExcelPackage.MaxColumns) {
+ throw (new ArgumentOutOfRangeException("Offset value out of range"));
+ }
+ string address = GetAddress(
+ _fromRow + rowOffset,
+ _fromCol + columnOffset,
+ _toRow + rowOffset,
+ _toCol + columnOffset);
+ return new(_worksheet, address);
+ }
+
+ /// <summary>
+ /// Get a range with an offset from the top left cell.
+ /// </summary>
+ /// <param name="rowOffset">Row Offset</param>
+ /// <param name="columnOffset">Column Offset</param>
+ /// <param name="numberOfRows">Number of rows. Minimum 1</param>
+ /// <param name="numberOfColumns">Number of colums. Minimum 1</param>
+ /// <returns></returns>
+ public ExcelRangeBase Offset(
+ int rowOffset,
+ int columnOffset,
+ int numberOfRows,
+ int numberOfColumns) {
+ if (numberOfRows < 1 || numberOfColumns < 1) {
+ throw (new("Number of rows/columns must be greater than 0"));
+ }
+ numberOfRows--;
+ numberOfColumns--;
+ if (_fromRow + rowOffset < 1
+ || _fromCol + columnOffset < 1
+ || _fromRow + rowOffset > ExcelPackage.MaxRows
+ || _fromCol + columnOffset > ExcelPackage.MaxColumns
+ || _fromRow + rowOffset + numberOfRows < 1
+ || _fromCol + columnOffset + numberOfColumns < 1
+ || _fromRow + rowOffset + numberOfRows > ExcelPackage.MaxRows
+ || _fromCol + columnOffset + numberOfColumns > ExcelPackage.MaxColumns) {
+ throw (new ArgumentOutOfRangeException("Offset value out of range"));
+ }
+ string address = GetAddress(
+ _fromRow + rowOffset,
+ _fromCol + columnOffset,
+ _fromRow + rowOffset + numberOfRows,
+ _fromCol + columnOffset + numberOfColumns);
+ return new(_worksheet, address);
+ }
+
+ /// <summary>
+ /// Clear all cells
+ /// </summary>
+ public void Clear() {
+ Delete(this, false);
+ }
+
+ /// <summary>
+ /// Creates an array-formula.
+ /// </summary>
+ /// <param name="arrayFormula">The formula</param>
+ public void CreateArrayFormula(string arrayFormula) {
+ if (Addresses != null) {
+ throw (new("An Arrayformula can not have more than one address"));
+ }
+ Set_SharedFormula(arrayFormula, this, true);
+ }
+
+ //private void Clear(ExcelAddressBase Range)
+ //{
+ // Clear(Range, true);
+ //}
+ internal void Delete(ExcelAddressBase range, bool shift) {
+ //DeleteCheckMergedCells(Range);
+ _worksheet.MergedCells.Clear(range);
+ //First find the start cell
+ int fromRow,
+ fromCol;
+ var d = Worksheet.Dimension;
+ if (d != null
+ && range._fromRow <= d._fromRow
+ && range._toRow
+ >= d._toRow) //EntireRow?
+ {
+ fromRow = 0;
+ } else {
+ fromRow = range._fromRow;
+ }
+ if (d != null
+ && range._fromCol <= d._fromCol
+ && range._toCol
+ >= d._toCol) //EntireRow?
+ {
+ fromCol = 0;
+ } else {
+ fromCol = range._fromCol;
+ }
+
+ var rows = range._toRow - fromRow + 1;
+ var cols = range._toCol - fromCol + 1;
+
+ _worksheet._values.Delete(fromRow, fromCol, rows, cols, shift);
+ _worksheet._types.Delete(fromRow, fromCol, rows, cols, shift);
+ _worksheet._styles.Delete(fromRow, fromCol, rows, cols, shift);
+ _worksheet._formulas.Delete(fromRow, fromCol, rows, cols, shift);
+ _worksheet._hyperLinks.Delete(fromRow, fromCol, rows, cols, shift);
+ _worksheet._flags.Delete(fromRow, fromCol, rows, cols, shift);
+ _worksheet._commentsStore.Delete(fromRow, fromCol, rows, cols, shift);
+
+ //if(shift)
+ //{
+ // _worksheet.AdjustFormulasRow(fromRow, rows);
+ //}
+
+ //Clear multi addresses as well
+ if (Addresses != null) {
+ foreach (var sub in Addresses) {
+ Delete(sub, shift);
+ }
+ }
+ }
+
+ public void Dispose() {}
+
+ //int _index;
+ //ulong _toCellId;
+ //int _enumAddressIx;
+ private CellsStoreEnumerator<object> cellEnum;
+
+ public IEnumerator<ExcelRangeBase> GetEnumerator() {
+ Reset();
+ return this;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ Reset();
+ return this;
+ }
+
+ /// <summary>
+ /// The current range when enumerating
+ /// </summary>
+ public ExcelRangeBase Current => new(_worksheet, GetAddress(cellEnum.Row, cellEnum.Column));
+
+ /// <summary>
+ /// The current range when enumerating
+ /// </summary>
+ object IEnumerator.Current =>
+ new ExcelRangeBase(_worksheet, GetAddress(cellEnum.Row, cellEnum.Column));
+
+ private int _enumAddressIx = -1;
+
+ public bool MoveNext() {
+ if (cellEnum.Next()) {
+ return true;
+ }
+ if (_addresses != null) {
+ _enumAddressIx++;
+ if (_enumAddressIx < _addresses.Count) {
+ cellEnum = new(
+ _worksheet._values,
+ _addresses[_enumAddressIx]._fromRow,
+ _addresses[_enumAddressIx]._fromCol,
+ _addresses[_enumAddressIx]._toRow,
+ _addresses[_enumAddressIx]._toCol);
+ return MoveNext();
+ }
+ return false;
+ }
+ return false;
+ }
+
+ public void Reset() {
+ _enumAddressIx = -1;
+ cellEnum = new(_worksheet._values, _fromRow, _fromCol, _toRow, _toCol);
+ }
+
+ //private void GetNextIndexEnum(int fromRow, int fromCol, int toRow, int toCol)
+ //{
+ // if (_index >= _worksheet._cells.Count) return;
+ // ExcelCell cell = _worksheet._cells[_index] as ExcelCell;
+ // while (cell.Column > toCol || cell.Column < fromCol)
+ // {
+ // if (cell.Column < fromCol)
+ // {
+ // _index = _worksheet._cells.IndexOf(ExcelAddress.GetCellID(_worksheet.SheetID, cell.Row, fromCol));
+ // }
+ // else
+ // {
+ // _index = _worksheet._cells.IndexOf(ExcelAddress.GetCellID(_worksheet.SheetID, cell.Row + 1, fromCol));
+ // }
+
+ // if (_index < 0)
+ // {
+ // _index = ~_index;
+ // }
+ // if (_index >= _worksheet._cells.Count || _worksheet._cells[_index].RangeID > _toCellId)
+ // {
+ // break;
+ // }
+ // cell = _worksheet._cells[_index] as ExcelCell;
+ // }
+ //}
+
+ //private void GetStartIndexEnum(int fromRow, int fromCol, int toRow, int toCol)
+ //{
+ // _index = _worksheet._cells.IndexOf(ExcelCellBase.GetCellID(_worksheet.SheetID, fromRow, fromCol));
+ // _toCellId = ExcelCellBase.GetCellID(_worksheet.SheetID, toRow, toCol);
+ // if (_index < 0)
+ // {
+ // _index = ~_index;
+ // }
+ // _index--;
+ //}
+}
diff --git a/AppsheetEpplus/ExcelRangeCopyOptionFlags.cs b/AppsheetEpplus/ExcelRangeCopyOptionFlags.cs
new file mode 100644
index 0000000..25f478c
--- /dev/null
+++ b/AppsheetEpplus/ExcelRangeCopyOptionFlags.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Flag enum, specify all flags that you want to exclude from the copy.
+/// </summary>
+[Flags]
+public enum ExcelRangeCopyOptionFlags {
+ /// <summary>
+ /// Exclude formulas from being copied
+ /// </summary>
+ ExcludeFormulas = 0x1,
+}
diff --git a/AppsheetEpplus/ExcelRow.cs b/AppsheetEpplus/ExcelRow.cs
new file mode 100644
index 0000000..d8069b0
--- /dev/null
+++ b/AppsheetEpplus/ExcelRow.cs
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan K�llman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+internal class RowInternal {
+ internal double Height = -1;
+ internal bool Hidden;
+ internal bool Collapsed;
+ internal short OutlineLevel;
+ internal bool PageBreak;
+ internal bool Phonetic;
+ internal bool CustomHeight;
+}
+
+/// <summary>
+/// Represents an individual row in the spreadsheet.
+/// </summary>
+public class ExcelRow : IRangeId {
+ private readonly ExcelWorksheet _worksheet;
+ private readonly XmlElement _rowElement = null;
+
+ /// <summary>
+ /// Internal RowID.
+ /// </summary>
+ [Obsolete]
+ public ulong RowID => GetRowId(_worksheet.SheetID, Row);
+
+ /// <summary>
+ /// Creates a new instance of the ExcelRow class.
+ /// For internal use only!
+ /// </summary>
+ /// <param name="worksheet">The parent worksheet</param>
+ /// <param name="row">The row number</param>
+ internal ExcelRow(ExcelWorksheet worksheet, int row) {
+ _worksheet = worksheet;
+ Row = row;
+ }
+
+ /// <summary>
+ /// Provides access to the node representing the row.
+ /// </summary>
+ internal XmlNode Node => (_rowElement);
+
+ /// <summary>
+ /// Allows the row to be hidden in the worksheet
+ /// </summary>
+ public bool Hidden {
+ get {
+ var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
+ if (r == null) {
+ return false;
+ }
+ return r.Hidden;
+ }
+ set {
+ var r = GetRowInternal();
+ r.Hidden = value;
+ }
+ }
+
+ /// <summary>
+ /// Sets the height of the row
+ /// </summary>
+ public double Height {
+ get {
+ var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
+ if (r == null || r.Height < 0) {
+ return _worksheet.DefaultRowHeight;
+ }
+ return r.Height;
+ }
+ set {
+ var r = GetRowInternal();
+ r.Height = value;
+
+ if (r.Hidden && value != 0) {
+ Hidden = false;
+ }
+ r.CustomHeight = (value != _worksheet.DefaultRowHeight);
+ }
+ }
+
+ /// <summary>
+ /// Set to true if You don't want the row to Autosize
+ /// </summary>
+ public bool CustomHeight {
+ get {
+ var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
+ if (r == null) {
+ return false;
+ }
+ return r.CustomHeight;
+ }
+ set {
+ var r = GetRowInternal();
+ r.CustomHeight = value;
+ }
+ }
+
+ internal string _styleName = "";
+
+ /// <summary>
+ /// Sets the style for the entire column using a style name.
+ /// </summary>
+ public string StyleName {
+ get => _styleName;
+ set {
+ StyleID = _worksheet.Workbook.Styles.GetStyleIdFromName(value);
+ _styleName = value;
+ }
+ }
+
+ /// <summary>
+ /// Sets the style for the entire row using the style ID.
+ /// </summary>
+ public int StyleID {
+ get => _worksheet._styles.GetValue(Row, 0);
+ set => _worksheet._styles.SetValue(Row, 0, value);
+ }
+
+ /// <summary>
+ /// Rownumber
+ /// </summary>
+ public int Row { get; set; }
+
+ /// <summary>
+ /// If outline level is set this tells that the row is collapsed
+ /// </summary>
+ public bool Collapsed {
+ get {
+ var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
+ if (r == null) {
+ return false;
+ }
+ return r.Collapsed;
+ }
+ set {
+ var r = GetRowInternal();
+ r.Collapsed = value;
+ }
+ }
+
+ /// <summary>
+ /// Outline level.
+ /// </summary>
+ public int OutlineLevel {
+ get {
+ var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
+ if (r == null) {
+ return 0;
+ }
+ return r.OutlineLevel;
+ }
+ set {
+ var r = GetRowInternal();
+ r.OutlineLevel = (short)value;
+ }
+ }
+
+ private RowInternal GetRowInternal() {
+ var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
+ if (r == null) {
+ r = new();
+ _worksheet._values.SetValue(Row, 0, r);
+ }
+ return r;
+ }
+
+ /// <summary>
+ /// Show phonetic Information
+ /// </summary>
+ public bool Phonetic {
+ get {
+ var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
+ if (r == null) {
+ return false;
+ }
+ return r.Phonetic;
+ }
+ set {
+ var r = GetRowInternal();
+ r.Phonetic = value;
+ }
+ }
+
+ /// <summary>
+ /// The Style applied to the whole row. Only effekt cells with no individual style set.
+ /// Use ExcelRange object if you want to set specific styles.
+ /// </summary>
+ public ExcelStyle Style =>
+ _worksheet.Workbook.Styles.GetStyleObject(StyleID, _worksheet.PositionID, Row + ":" + Row);
+
+ /// <summary>
+ /// Adds a manual page break after the row.
+ /// </summary>
+ public bool PageBreak {
+ get {
+ var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
+ if (r == null) {
+ return false;
+ }
+ return r.PageBreak;
+ }
+ set {
+ var r = GetRowInternal();
+ r.PageBreak = value;
+ }
+ }
+
+ public bool Merged {
+ get => _worksheet.MergedCells[Row, 0] != null;
+ set => _worksheet.MergedCells.Add(new(Row, 1, Row, ExcelPackage.MaxColumns), true);
+ }
+
+ internal static ulong GetRowId(int sheetId, int row) {
+ return ((ulong)sheetId) + (((ulong)row) << 29);
+ }
+
+ [Obsolete]
+ ulong IRangeId.RangeID {
+ get => RowID;
+ set => Row = ((int)(value >> 29));
+ }
+}
diff --git a/AppsheetEpplus/ExcelSheetProtection.cs b/AppsheetEpplus/ExcelSheetProtection.cs
new file mode 100644
index 0000000..a538666
--- /dev/null
+++ b/AppsheetEpplus/ExcelSheetProtection.cs
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ * 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 Initial Release 2010-03-14
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Collections.Immutable;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Sheet protection
+///<seealso cref="ExcelEncryption"/>
+///<seealso cref="ExcelProtection"/>
+/// </summary>
+public sealed class ExcelSheetProtection : XmlHelper {
+ protected override ImmutableArray<string> SchemaNodeOrder =>
+ ExcelWorksheet.WorksheetSchemaNodeOrder;
+
+ internal ExcelSheetProtection(XmlNamespaceManager nsm, XmlNode topNode)
+ : base(nsm, topNode) {}
+
+ private const string _isProtectedPath = "d:sheetProtection/@sheet";
+
+ /// <summary>
+ /// If the worksheet is protected.
+ /// </summary>
+ public bool IsProtected {
+ get => GetXmlNodeBool(_isProtectedPath, false);
+ set {
+ SetXmlNodeBool(_isProtectedPath, value, false);
+ if (value) {
+ AllowEditObject = true;
+ AllowEditScenarios = true;
+ } else {
+ DeleteAllNode(_isProtectedPath); //delete the whole sheetprotection node
+ }
+ }
+ }
+
+ private const string _allowSelectLockedCellsPath = "d:sheetProtection/@selectLockedCells";
+
+ /// <summary>
+ /// Allow users to select locked cells
+ /// </summary>
+ public bool AllowSelectLockedCells {
+ get => !GetXmlNodeBool(_allowSelectLockedCellsPath, false);
+ set => SetXmlNodeBool(_allowSelectLockedCellsPath, !value, false);
+ }
+
+ private const string _allowSelectUnlockedCellsPath = "d:sheetProtection/@selectUnlockedCells";
+
+ /// <summary>
+ /// Allow users to select unlocked cells
+ /// </summary>
+ public bool AllowSelectUnlockedCells {
+ get => !GetXmlNodeBool(_allowSelectUnlockedCellsPath, false);
+ set => SetXmlNodeBool(_allowSelectUnlockedCellsPath, !value, false);
+ }
+
+ private const string _allowObjectPath = "d:sheetProtection/@objects";
+
+ /// <summary>
+ /// Allow users to edit objects
+ /// </summary>
+ public bool AllowEditObject {
+ get => !GetXmlNodeBool(_allowObjectPath, false);
+ set => SetXmlNodeBool(_allowObjectPath, !value, false);
+ }
+
+ private const string _allowScenariosPath = "d:sheetProtection/@scenarios";
+
+ /// <summary>
+ /// Allow users to edit senarios
+ /// </summary>
+ public bool AllowEditScenarios {
+ get => !GetXmlNodeBool(_allowScenariosPath, false);
+ set => SetXmlNodeBool(_allowScenariosPath, !value, false);
+ }
+
+ private const string _allowFormatCellsPath = "d:sheetProtection/@formatCells";
+
+ /// <summary>
+ /// Allow users to format cells
+ /// </summary>
+ public bool AllowFormatCells {
+ get => !GetXmlNodeBool(_allowFormatCellsPath, true);
+ set => SetXmlNodeBool(_allowFormatCellsPath, !value, true);
+ }
+
+ private const string _allowFormatColumnsPath = "d:sheetProtection/@formatColumns";
+
+ /// <summary>
+ /// Allow users to Format columns
+ /// </summary>
+ public bool AllowFormatColumns {
+ get => !GetXmlNodeBool(_allowFormatColumnsPath, true);
+ set => SetXmlNodeBool(_allowFormatColumnsPath, !value, true);
+ }
+
+ private const string _allowFormatRowsPath = "d:sheetProtection/@formatRows";
+
+ /// <summary>
+ /// Allow users to Format rows
+ /// </summary>
+ public bool AllowFormatRows {
+ get => !GetXmlNodeBool(_allowFormatRowsPath, true);
+ set => SetXmlNodeBool(_allowFormatRowsPath, !value, true);
+ }
+
+ private const string _allowInsertColumnsPath = "d:sheetProtection/@insertColumns";
+
+ /// <summary>
+ /// Allow users to insert columns
+ /// </summary>
+ public bool AllowInsertColumns {
+ get => !GetXmlNodeBool(_allowInsertColumnsPath, true);
+ set => SetXmlNodeBool(_allowInsertColumnsPath, !value, true);
+ }
+
+ private const string _allowInsertRowsPath = "d:sheetProtection/@insertRows";
+
+ /// <summary>
+ /// Allow users to Format rows
+ /// </summary>
+ public bool AllowInsertRows {
+ get => !GetXmlNodeBool(_allowInsertRowsPath, true);
+ set => SetXmlNodeBool(_allowInsertRowsPath, !value, true);
+ }
+
+ private const string _allowInsertHyperlinksPath = "d:sheetProtection/@insertHyperlinks";
+
+ /// <summary>
+ /// Allow users to insert hyperlinks
+ /// </summary>
+ public bool AllowInsertHyperlinks {
+ get => !GetXmlNodeBool(_allowInsertHyperlinksPath, true);
+ set => SetXmlNodeBool(_allowInsertHyperlinksPath, !value, true);
+ }
+
+ private const string _allowDeleteColumns = "d:sheetProtection/@deleteColumns";
+
+ /// <summary>
+ /// Allow users to delete columns
+ /// </summary>
+ public bool AllowDeleteColumns {
+ get => !GetXmlNodeBool(_allowDeleteColumns, true);
+ set => SetXmlNodeBool(_allowDeleteColumns, !value, true);
+ }
+
+ private const string _allowDeleteRowsPath = "d:sheetProtection/@deleteRows";
+
+ /// <summary>
+ /// Allow users to delete rows
+ /// </summary>
+ public bool AllowDeleteRows {
+ get => !GetXmlNodeBool(_allowDeleteRowsPath, true);
+ set => SetXmlNodeBool(_allowDeleteRowsPath, !value, true);
+ }
+
+ private const string _allowSortPath = "d:sheetProtection/@sort";
+
+ /// <summary>
+ /// Allow users to sort a range
+ /// </summary>
+ public bool AllowSort {
+ get => !GetXmlNodeBool(_allowSortPath, true);
+ set => SetXmlNodeBool(_allowSortPath, !value, true);
+ }
+
+ private const string _allowAutoFilterPath = "d:sheetProtection/@autoFilter";
+
+ /// <summary>
+ /// Allow users to use autofilters
+ /// </summary>
+ public bool AllowAutoFilter {
+ get => !GetXmlNodeBool(_allowAutoFilterPath, true);
+ set => SetXmlNodeBool(_allowAutoFilterPath, !value, true);
+ }
+
+ private const string _allowPivotTablesPath = "d:sheetProtection/@pivotTables";
+
+ /// <summary>
+ /// Allow users to use pivottables
+ /// </summary>
+ public bool AllowPivotTables {
+ get => !GetXmlNodeBool(_allowPivotTablesPath, true);
+ set => SetXmlNodeBool(_allowPivotTablesPath, !value, true);
+ }
+}
diff --git a/AppsheetEpplus/ExcelStyleCollection.cs b/AppsheetEpplus/ExcelStyleCollection.cs
new file mode 100644
index 0000000..788e6c0
--- /dev/null
+++ b/AppsheetEpplus/ExcelStyleCollection.cs
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Base collection class for styles.
+/// </summary>
+/// <typeparam name="T">The style type</typeparam>
+public class ExcelStyleCollection<T> : IEnumerable<T> {
+ public ExcelStyleCollection() {
+ _setNextIdManual = false;
+ }
+
+ private readonly bool _setNextIdManual;
+
+ public ExcelStyleCollection(bool setNextIdManual) {
+ _setNextIdManual = setNextIdManual;
+ }
+
+ public XmlNode TopNode { get; set; }
+
+ internal List<T> _list = new();
+ private readonly Dictionary<string, int> _dic = new(StringComparer.InvariantCultureIgnoreCase);
+ internal int NextId;
+
+ public IEnumerator<T> GetEnumerator() {
+ return _list.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _list.GetEnumerator();
+ }
+
+ public T this[int positionId] => _list[positionId];
+
+ public int Count => _list.Count;
+
+ //internal int Add(T item)
+ //{
+ // _list.Add(item);
+ // if (_setNextIdManual) NextId++;
+ // return _list.Count-1;
+ //}
+ internal int Add(string key, T item) {
+ _list.Add(item);
+ if (!_dic.ContainsKey(key.ToLower(CultureInfo.InvariantCulture))) {
+ _dic.Add(key.ToLower(CultureInfo.InvariantCulture), _list.Count - 1);
+ }
+ if (_setNextIdManual) {
+ NextId++;
+ }
+ return _list.Count - 1;
+ }
+
+ /// <summary>
+ /// Finds the key
+ /// </summary>
+ /// <param name="key">the key to be found</param>
+ /// <param name="obj">The found object.</param>
+ /// <returns>True if found</returns>
+ internal bool FindById(string key, ref T obj) {
+ if (_dic.ContainsKey(key)) {
+ obj = _list[_dic[key.ToLower(CultureInfo.InvariantCulture)]];
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Find Index
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
+ internal int FindIndexById(string key) {
+ if (_dic.ContainsKey(key)) {
+ return _dic[key];
+ }
+ return int.MinValue;
+ }
+
+ internal bool ExistsKey(string key) {
+ return _dic.ContainsKey(key);
+ }
+
+ internal void Sort(Comparison<T> c) {
+ _list.Sort(c);
+ }
+}
diff --git a/AppsheetEpplus/ExcelStyles.cs b/AppsheetEpplus/ExcelStyles.cs
new file mode 100644
index 0000000..dc169ed
--- /dev/null
+++ b/AppsheetEpplus/ExcelStyles.cs
@@ -0,0 +1,870 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan K�llman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Containts all shared cell styles for a workbook
+/// </summary>
+public sealed class ExcelStyles : XmlHelper {
+ private const string _numberFormatsPath = "d:styleSheet/d:numFmts";
+ private const string _fontsPath = "d:styleSheet/d:fonts";
+ private const string _fillsPath = "d:styleSheet/d:fills";
+ private const string _bordersPath = "d:styleSheet/d:borders";
+ private const string _cellStyleXfsPath = "d:styleSheet/d:cellStyleXfs";
+ private const string _cellXfsPath = "d:styleSheet/d:cellXfs";
+ private const string _cellStylesPath = "d:styleSheet/d:cellStyles";
+ private const string _dxfsPath = "d:styleSheet/d:dxfs";
+
+ //internal Dictionary<int, ExcelXfs> Styles = new Dictionary<int, ExcelXfs>();
+ private readonly XmlDocument _styleXml;
+ private readonly ExcelWorkbook _wb;
+ private readonly XmlNamespaceManager _nameSpaceManager;
+ internal int _nextDfxNumFmtID = 164;
+
+ protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
+ "numFmts",
+ "fonts",
+ "fills",
+ "borders",
+ "cellStyleXfs",
+ "cellXfs",
+ "cellStyles",
+ "dxfs",
+ ];
+
+ internal ExcelStyles(XmlNamespaceManager nameSpaceManager, XmlDocument xml, ExcelWorkbook wb)
+ : base(nameSpaceManager, xml) {
+ _styleXml = xml;
+ _wb = wb;
+ _nameSpaceManager = nameSpaceManager;
+ LoadFromDocument();
+ }
+
+ /// <summary>
+ /// Loads the style XML to memory
+ /// </summary>
+ private void LoadFromDocument() {
+ //NumberFormats
+ ExcelNumberFormatXml.AddBuildIn(NameSpaceManager, NumberFormats);
+ XmlNode numNode = _styleXml.SelectSingleNode(_numberFormatsPath, _nameSpaceManager);
+ if (numNode != null) {
+ foreach (XmlNode n in numNode) {
+ ExcelNumberFormatXml nf = new ExcelNumberFormatXml(_nameSpaceManager, n);
+ NumberFormats.Add(nf.Id, nf);
+ if (nf.NumFmtId >= NumberFormats.NextId) {
+ NumberFormats.NextId = nf.NumFmtId + 1;
+ }
+ }
+ }
+
+ //Fonts
+ XmlNode fontNode = _styleXml.SelectSingleNode(_fontsPath, _nameSpaceManager);
+ foreach (XmlNode n in fontNode) {
+ ExcelFontXml f = new ExcelFontXml(_nameSpaceManager, n);
+ Fonts.Add(f.Id, f);
+ }
+
+ //Fills
+ XmlNode fillNode = _styleXml.SelectSingleNode(_fillsPath, _nameSpaceManager);
+ foreach (XmlNode n in fillNode) {
+ ExcelFillXml f;
+ if (n.FirstChild != null && n.FirstChild.LocalName == "gradientFill") {
+ f = new ExcelGradientFillXml(_nameSpaceManager, n);
+ } else {
+ f = new(_nameSpaceManager, n);
+ }
+ Fills.Add(f.Id, f);
+ }
+
+ //Borders
+ XmlNode borderNode = _styleXml.SelectSingleNode(_bordersPath, _nameSpaceManager);
+ foreach (XmlNode n in borderNode) {
+ ExcelBorderXml b = new ExcelBorderXml(_nameSpaceManager, n);
+ Borders.Add(b.Id, b);
+ }
+
+ //cellStyleXfs
+ XmlNode styleXfsNode = _styleXml.SelectSingleNode(_cellStyleXfsPath, _nameSpaceManager);
+ if (styleXfsNode != null) {
+ foreach (XmlNode n in styleXfsNode) {
+ ExcelXfs item = new ExcelXfs(_nameSpaceManager, n, this);
+ CellStyleXfs.Add(item.Id, item);
+ }
+ }
+
+ XmlNode styleNode = _styleXml.SelectSingleNode(_cellXfsPath, _nameSpaceManager);
+ for (int i = 0; i < styleNode.ChildNodes.Count; i++) {
+ XmlNode n = styleNode.ChildNodes[i];
+ ExcelXfs item = new ExcelXfs(_nameSpaceManager, n, this);
+ CellXfs.Add(item.Id, item);
+ }
+
+ //cellStyle
+ XmlNode namedStyleNode = _styleXml.SelectSingleNode(_cellStylesPath, _nameSpaceManager);
+ if (namedStyleNode != null) {
+ foreach (XmlNode n in namedStyleNode) {
+ ExcelNamedStyleXml item = new ExcelNamedStyleXml(_nameSpaceManager, n, this);
+ NamedStyles.Add(item.Name, item);
+ }
+ }
+
+ //dxfsPath
+ XmlNode dxfsNode = _styleXml.SelectSingleNode(_dxfsPath, _nameSpaceManager);
+ if (dxfsNode != null) {
+ foreach (XmlNode x in dxfsNode) {
+ ExcelDxfStyleConditionalFormatting item = new ExcelDxfStyleConditionalFormatting(
+ _nameSpaceManager,
+ x,
+ this);
+ Dxfs.Add(item.Id, item);
+ }
+ }
+ }
+
+ internal ExcelStyle GetStyleObject(int id, int positionId, string address) {
+ if (id < 0) {
+ id = 0;
+ }
+ return new(this, PropertyChange, positionId, address, id);
+ }
+
+ /// <summary>
+ /// Handels changes of properties on the style objects
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ /// <returns></returns>
+ internal int PropertyChange(StyleBase sender, StyleChangeEventArgs e) {
+ var address = new ExcelAddressBase(e.Address);
+ var ws = _wb.Worksheets[e.PositionID];
+ Dictionary<int, int> styleCashe = new Dictionary<int, int>();
+ //Set single address
+ SetStyleAddress(sender, e, address, ws, ref styleCashe);
+ if (address.Addresses != null) {
+ //Handle multiaddresses
+ foreach (var innerAddress in address.Addresses) {
+ SetStyleAddress(sender, e, innerAddress, ws, ref styleCashe);
+ }
+ }
+ return 0;
+ }
+
+ private void SetStyleAddress(
+ StyleBase sender,
+ StyleChangeEventArgs e,
+ ExcelAddressBase address,
+ ExcelWorksheet ws,
+ ref Dictionary<int, int> styleCashe) {
+ if (address.Start.Column == 0 || address.Start.Row == 0) {
+ throw (new("error address"));
+ }
+ //Columns
+ if (address.Start.Row == 1 && address.End.Row == ExcelPackage.MaxRows) {
+ ExcelColumn column;
+ int col = address.Start.Column,
+ row = 0;
+ //Get the startcolumn
+ if (!ws._values.Exists(0, address.Start.Column)) {
+ column = ws.Column(address.Start.Column);
+ } else {
+ column = (ExcelColumn)ws._values.GetValue(0, address.Start.Column);
+ }
+
+ while (column.ColumnMin <= address.End.Column) {
+ if (column.ColumnMax > address.End.Column) {
+ var newCol = ws.CopyColumn(column, address.End.Column + 1, column.ColumnMax);
+ column.ColumnMax = address.End.Column;
+ }
+ var s = ws._styles.GetValue(0, column.ColumnMin);
+ if (styleCashe.ContainsKey(s)) {
+ ws.SetStyle(0, column.ColumnMin, styleCashe[s]);
+ } else {
+ ExcelXfs st = CellXfs[s];
+ int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
+ styleCashe.Add(s, newId);
+ ws.SetStyle(0, column.ColumnMin, newId);
+ }
+
+ //index++;
+
+ if (!ws._values.NextCell(ref row, ref col) || row > 0) {
+ column._columnMax = address.End.Column;
+ break;
+ }
+ column = (ws._values.GetValue(0, col) as ExcelColumn);
+ }
+
+ if (column._columnMax < address.End.Column) {
+ var newCol = ws.Column(column._columnMax + 1);
+ newCol._columnMax = address.End.Column;
+
+ var s = ws._styles.GetValue(0, column.ColumnMin);
+ if (styleCashe.ContainsKey(s)) {
+ ws.SetStyle(0, column.ColumnMin, styleCashe[s]);
+ } else {
+ ExcelXfs st = CellXfs[s];
+ int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
+ styleCashe.Add(s, newId);
+ ws.SetStyle(0, column.ColumnMin, newId);
+ }
+
+ column._columnMax = address.End.Column;
+ }
+
+ //Set for individual cells in the span. We loop all cells here since the cells are sorted with columns first.
+ var cse = new CellsStoreEnumerator<int>(
+ ws._styles,
+ 1,
+ address._fromCol,
+ address._toRow,
+ address._toCol);
+ while (cse.Next()) {
+ if (cse.Column >= address.Start.Column && cse.Column <= address.End.Column) {
+ if (styleCashe.ContainsKey(cse.Value)) {
+ ws.SetStyle(cse.Row, cse.Column, styleCashe[cse.Value]);
+ } else {
+ ExcelXfs st = CellXfs[cse.Value];
+ int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
+ styleCashe.Add(cse.Value, newId);
+ cse.Value = newId;
+ //ws.SetStyle(cse.Row, cse.Column, newId);
+ }
+ }
+ }
+
+ //Update cells with styled columns
+ cse = new(ws._styles, 1, 0, address._toRow, 0);
+ while (cse.Next()) {
+ for (int c = address._fromRow; c <= address._toCol; c++) {
+ if (!ws._styles.Exists(cse.Row, c)) {
+ if (styleCashe.ContainsKey(cse.Value)) {
+ ws.SetStyle(cse.Row, c, styleCashe[cse.Value]);
+ } else {
+ ExcelXfs st = CellXfs[cse.Value];
+ int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
+ styleCashe.Add(cse.Value, newId);
+ ws.SetStyle(cse.Row, c, newId);
+ }
+ }
+ }
+ }
+ }
+ //Rows
+ else if (address.Start.Column == 1 && address.End.Column == ExcelPackage.MaxColumns) {
+ for (int rowNum = address.Start.Row; rowNum <= address.End.Row; rowNum++) {
+ var s = ws._styles.GetValue(rowNum, 0);
+ if (s == 0) {
+ //iterate all columns and set the row to the style of the last column
+ var cse = new CellsStoreEnumerator<int>(ws._styles, 0, 1, 0, ExcelPackage.MaxColumns);
+ while (cse.Next()) {
+ s = cse.Value;
+ var c = ws._values.GetValue(cse.Row, cse.Column) as ExcelColumn;
+ if (c != null && c.ColumnMax < ExcelPackage.MaxColumns) {
+ for (int col = c.ColumnMin; col < c.ColumnMax; col++) {
+ if (!ws._styles.Exists(rowNum, col)) {
+ ws._styles.SetValue(rowNum, col, s);
+ }
+ }
+ }
+ }
+ ws.SetStyle(rowNum, 0, s);
+ }
+ if (styleCashe.ContainsKey(s)) {
+ ws.SetStyle(rowNum, 0, styleCashe[s]);
+ } else {
+ ExcelXfs st = CellXfs[s];
+ int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
+ styleCashe.Add(s, newId);
+ ws._styles.SetValue(rowNum, 0, newId);
+ ws.SetStyle(rowNum, 0, newId);
+ }
+ }
+
+ //Update individual cells
+ var cse2 = new CellsStoreEnumerator<int>(
+ ws._styles,
+ address._fromRow,
+ address._fromCol,
+ address._toRow,
+ address._toCol);
+ while (cse2.Next()) {
+ var s = cse2.Value;
+ if (styleCashe.ContainsKey(s)) {
+ ws.SetStyle(cse2.Row, cse2.Column, styleCashe[s]);
+ } else {
+ ExcelXfs st = CellXfs[s];
+ int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
+ styleCashe.Add(s, newId);
+ cse2.Value = newId;
+ }
+ }
+
+ //Update cells with styled rows
+ cse2 = new(ws._styles, 0, 1, 0, address._toCol);
+ while (cse2.Next()) {
+ for (int r = address._fromRow; r <= address._toRow; r++) {
+ if (!ws._styles.Exists(r, cse2.Column)) {
+ var s = cse2.Value;
+ if (styleCashe.ContainsKey(s)) {
+ ws.SetStyle(r, cse2.Column, styleCashe[s]);
+ } else {
+ ExcelXfs st = CellXfs[s];
+ int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
+ styleCashe.Add(s, newId);
+ ws.SetStyle(r, cse2.Column, newId);
+ }
+ }
+ }
+ }
+ } else //Cellrange
+ {
+ for (int col = address.Start.Column; col <= address.End.Column; col++) {
+ for (int row = address.Start.Row; row <= address.End.Row; row++) {
+ var s = GetStyleId(ws, row, col);
+ if (styleCashe.ContainsKey(s)) {
+ ws.SetStyle(row, col, styleCashe[s]);
+ } else {
+ ExcelXfs st = CellXfs[s];
+ int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
+ styleCashe.Add(s, newId);
+ ws.SetStyle(row, col, newId);
+ }
+ }
+ }
+ }
+ }
+
+ internal int GetStyleId(ExcelWorksheet ws, int row, int col) {
+ int v = 0;
+ if (ws._styles.Exists(row, col, ref v)) {
+ return v;
+ }
+ if (ws._styles.Exists(
+ row,
+ 0,
+ ref v)) //First Row
+ {
+ return v;
+ } // then column
+ if (ws._styles.Exists(0, col, ref v)) {
+ return v;
+ }
+ int r = 0,
+ c = col;
+ if (ws._values.PrevCell(ref r, ref c)) {
+ var column = ws._values.GetValue(0, c) as ExcelColumn;
+ if (column != null
+ && column.ColumnMax
+ >= col) //Fixes issue 15174
+ {
+ return ws._styles.GetValue(0, c);
+ }
+ return 0;
+ }
+ return 0;
+ }
+
+ /// <summary>
+ /// Handles property changes on Named styles.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ /// <returns></returns>
+ internal int NamedStylePropertyChange(StyleBase sender, StyleChangeEventArgs e) {
+ int index = NamedStyles.FindIndexById(e.Address);
+ if (index >= 0) {
+ int newId = CellStyleXfs[NamedStyles[index].StyleXfId]
+ .GetNewId(CellStyleXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
+ int prevIx = NamedStyles[index].StyleXfId;
+ NamedStyles[index].StyleXfId = newId;
+ NamedStyles[index].Style.Index = newId;
+
+ NamedStyles[index].XfId = int.MinValue;
+ foreach (var style in CellXfs) {
+ if (style.XfId == prevIx) {
+ style.XfId = newId;
+ }
+ }
+ }
+ return 0;
+ }
+
+ public ExcelStyleCollection<ExcelNumberFormatXml> NumberFormats = new();
+ public ExcelStyleCollection<ExcelFontXml> Fonts = new();
+ public ExcelStyleCollection<ExcelFillXml> Fills = new();
+ public ExcelStyleCollection<ExcelBorderXml> Borders = new();
+ public ExcelStyleCollection<ExcelXfs> CellStyleXfs = new();
+ public ExcelStyleCollection<ExcelXfs> CellXfs = new();
+ public ExcelStyleCollection<ExcelNamedStyleXml> NamedStyles = new();
+ public ExcelStyleCollection<ExcelDxfStyleConditionalFormatting> Dxfs = new();
+
+ internal string Id => "";
+
+ public ExcelNamedStyleXml CreateNamedStyle(string name) {
+ return CreateNamedStyle(name, null);
+ }
+
+ public ExcelNamedStyleXml CreateNamedStyle(string name, ExcelStyle template) {
+ if (_wb.Styles.NamedStyles.ExistsKey(name)) {
+ throw new(string.Format("Key {0} already exists in collection", name));
+ }
+
+ ExcelNamedStyleXml style;
+ style = new(NameSpaceManager, this);
+ int xfIdCopy,
+ positionId;
+ ExcelStyles styles;
+ if (template == null) {
+ // style.Style = new ExcelStyle(this, NamedStylePropertyChange, -1, name, 0);
+ xfIdCopy = 0;
+ positionId = -1;
+ styles = this;
+ } else {
+ if (template.PositionID < 0 && template.Styles == this) {
+ xfIdCopy = template.Index;
+ positionId = template.PositionID;
+ styles = this;
+ //style.Style = new ExcelStyle(this, NamedStylePropertyChange, Template.PositionID, name, Template.Index);
+ //style.StyleXfId = Template.Index;
+ } else {
+ xfIdCopy = template.XfId;
+ positionId = -1;
+ styles = template.Styles;
+ }
+ }
+ //Clone namedstyle
+ int styleXfId = CloneStyle(styles, xfIdCopy, true);
+ //Close cells style
+ CellStyleXfs[styleXfId].XfId = CellStyleXfs.Count - 1;
+ int xfid = CloneStyle(styles, xfIdCopy, false, true); //Always add a new style (We create a new named style here)
+ CellXfs[xfid].XfId = styleXfId;
+ style.Style = new(this, NamedStylePropertyChange, positionId, name, styleXfId);
+ style.StyleXfId = styleXfId;
+
+ style.Name = name;
+ int ix = _wb.Styles.NamedStyles.Add(style.Name, style);
+ style.Style.SetIndex(ix);
+ //style.Style.XfId = ix;
+ return style;
+ }
+
+ public void UpdateXml() {
+ RemoveUnusedStyles();
+
+ //NumberFormat
+ XmlNode nfNode = _styleXml.SelectSingleNode(_numberFormatsPath, _nameSpaceManager);
+ if (nfNode == null) {
+ CreateNode(_numberFormatsPath, true);
+ nfNode = _styleXml.SelectSingleNode(_numberFormatsPath, _nameSpaceManager);
+ } else {
+ nfNode.RemoveAll();
+ }
+
+ int count = 0;
+ int normalIx = NamedStyles.FindIndexById("Normal");
+ if (NamedStyles.Count > 0
+ && normalIx >= 0
+ && NamedStyles[normalIx].Style.Numberformat.NumFmtID >= 164) {
+ ExcelNumberFormatXml nf = NumberFormats[NumberFormats.FindIndexById(
+ NamedStyles[normalIx].Style.Numberformat.Id)];
+ nfNode.AppendChild(
+ nf.CreateXmlNode(_styleXml.CreateElement("numFmt", ExcelPackage._schemaMain)));
+ nf.newID = count++;
+ }
+ foreach (ExcelNumberFormatXml nf in NumberFormats) {
+ if (!nf.BuildIn /*&& nf.newID<0*/) //Buildin formats are not updated.
+ {
+ nfNode.AppendChild(
+ nf.CreateXmlNode(_styleXml.CreateElement("numFmt", ExcelPackage._schemaMain)));
+ nf.newID = count;
+ count++;
+ }
+ }
+ (nfNode as XmlElement).SetAttribute("count", count.ToString());
+
+ //Font
+ count = 0;
+ XmlNode fntNode = _styleXml.SelectSingleNode(_fontsPath, _nameSpaceManager);
+ fntNode.RemoveAll();
+
+ //Normal should be first in the collection
+ if (NamedStyles.Count > 0 && normalIx >= 0 && NamedStyles[normalIx].Style.Font.Index > 0) {
+ ExcelFontXml fnt = Fonts[NamedStyles[normalIx].Style.Font.Index];
+ fntNode.AppendChild(
+ fnt.CreateXmlNode(_styleXml.CreateElement("font", ExcelPackage._schemaMain)));
+ fnt.newID = count++;
+ }
+
+ foreach (ExcelFontXml fnt in Fonts) {
+ if (fnt.useCnt
+ > 0 /* && fnt.newID<0*/) {
+ fntNode.AppendChild(
+ fnt.CreateXmlNode(_styleXml.CreateElement("font", ExcelPackage._schemaMain)));
+ fnt.newID = count;
+ count++;
+ }
+ }
+ (fntNode as XmlElement).SetAttribute("count", count.ToString());
+
+ //Fills
+ count = 0;
+ XmlNode fillsNode = _styleXml.SelectSingleNode(_fillsPath, _nameSpaceManager);
+ fillsNode.RemoveAll();
+ Fills[0].useCnt = 1; //Must exist (none);
+ Fills[1].useCnt = 1; //Must exist (gray125);
+ foreach (ExcelFillXml fill in Fills) {
+ if (fill.useCnt > 0) {
+ fillsNode.AppendChild(
+ fill.CreateXmlNode(_styleXml.CreateElement("fill", ExcelPackage._schemaMain)));
+ fill.newID = count;
+ count++;
+ }
+ }
+
+ (fillsNode as XmlElement).SetAttribute("count", count.ToString());
+
+ //Borders
+ count = 0;
+ XmlNode bordersNode = _styleXml.SelectSingleNode(_bordersPath, _nameSpaceManager);
+ bordersNode.RemoveAll();
+ Borders[0].useCnt = 1; //Must exist blank;
+ foreach (ExcelBorderXml border in Borders) {
+ if (border.useCnt > 0) {
+ bordersNode.AppendChild(
+ border.CreateXmlNode(_styleXml.CreateElement("border", ExcelPackage._schemaMain)));
+ border.newID = count;
+ count++;
+ }
+ }
+ (bordersNode as XmlElement).SetAttribute("count", count.ToString());
+
+ XmlNode styleXfsNode = _styleXml.SelectSingleNode(_cellStyleXfsPath, _nameSpaceManager);
+ if (styleXfsNode == null && NamedStyles.Count > 0) {
+ CreateNode(_cellStyleXfsPath);
+ styleXfsNode = _styleXml.SelectSingleNode(_cellStyleXfsPath, _nameSpaceManager);
+ }
+ if (NamedStyles.Count > 0) {
+ styleXfsNode.RemoveAll();
+ }
+ //NamedStyles
+ count = normalIx > -1 ? 1 : 0; //If we have a normal style, we make sure it's added first.
+
+ XmlNode cellStyleNode = _styleXml.SelectSingleNode(_cellStylesPath, _nameSpaceManager);
+ if (cellStyleNode != null) {
+ cellStyleNode.RemoveAll();
+ }
+ XmlNode cellXfsNode = _styleXml.SelectSingleNode(_cellXfsPath, _nameSpaceManager);
+ cellXfsNode.RemoveAll();
+
+ if (NamedStyles.Count > 0 && normalIx >= 0) {
+ NamedStyles[normalIx].newID = 0;
+ AddNamedStyle(0, styleXfsNode, cellXfsNode, NamedStyles[normalIx]);
+ }
+ foreach (ExcelNamedStyleXml style in NamedStyles) {
+ if (!style.Name.Equals("normal", StringComparison.InvariantCultureIgnoreCase)) {
+ AddNamedStyle(count++, styleXfsNode, cellXfsNode, style);
+ } else {
+ style.newID = 0;
+ }
+ cellStyleNode.AppendChild(
+ style.CreateXmlNode(_styleXml.CreateElement("cellStyle", ExcelPackage._schemaMain)));
+ }
+ if (cellStyleNode != null) {
+ (cellStyleNode as XmlElement).SetAttribute("count", count.ToString());
+ }
+ if (styleXfsNode != null) {
+ (styleXfsNode as XmlElement).SetAttribute("count", count.ToString());
+ }
+
+ //CellStyle
+ int xfix = 0;
+ foreach (ExcelXfs xf in CellXfs) {
+ if (xf.useCnt > 0 && !(normalIx >= 0 && NamedStyles[normalIx].XfId == xfix)) {
+ cellXfsNode.AppendChild(
+ xf.CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage._schemaMain)));
+ xf.newID = count;
+ count++;
+ }
+ xfix++;
+ }
+ (cellXfsNode as XmlElement).SetAttribute("count", count.ToString());
+
+ //Set dxf styling for conditional Formatting
+ XmlNode dxfsNode = _styleXml.SelectSingleNode(_dxfsPath, _nameSpaceManager);
+ foreach (var ws in _wb.Worksheets) {
+ if (ws is ExcelChartsheet) {
+ continue;
+ }
+ foreach (var cf in ws.ConditionalFormatting) {
+ if (cf.Style.HasValue) {
+ int ix = Dxfs.FindIndexById(cf.Style.Id);
+ if (ix < 0) {
+ ((ExcelConditionalFormattingRule)cf).DxfId = Dxfs.Count;
+ Dxfs.Add(cf.Style.Id, cf.Style);
+ var elem = ((XmlDocument)TopNode).CreateElement("d", "dxf", ExcelPackage._schemaMain);
+ cf.Style.CreateNodes(new XmlHelperInstance(NameSpaceManager, elem), "");
+ dxfsNode.AppendChild(elem);
+ } else {
+ ((ExcelConditionalFormattingRule)cf).DxfId = ix;
+ }
+ }
+ }
+ }
+ if (dxfsNode != null) {
+ (dxfsNode as XmlElement).SetAttribute("count", Dxfs.Count.ToString());
+ }
+ }
+
+ private void AddNamedStyle(
+ int id,
+ XmlNode styleXfsNode,
+ XmlNode cellXfsNode,
+ ExcelNamedStyleXml style) {
+ var styleXfs = CellStyleXfs[style.StyleXfId];
+ styleXfsNode.AppendChild(
+ styleXfs.CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage._schemaMain), true));
+ styleXfs.newID = id;
+ styleXfs.XfId = style.StyleXfId;
+
+ var ix = CellXfs.FindIndexById(styleXfs.Id);
+ if (ix < 0) {
+ cellXfsNode.AppendChild(
+ styleXfs.CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage._schemaMain)));
+ } else {
+ if (id < 0) {
+ CellXfs[ix].XfId = id;
+ }
+ cellXfsNode.AppendChild(
+ CellXfs[ix].CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage._schemaMain)));
+ CellXfs[ix].useCnt = 0;
+ CellXfs[ix].newID = id;
+ }
+
+ if (style.XfId >= 0) {
+ style.XfId = CellXfs[style.XfId].newID;
+ } else {
+ style.XfId = 0;
+ }
+ }
+
+ private void RemoveUnusedStyles() {
+ CellXfs[0].useCnt = 1; //First item is allways used.
+ foreach (ExcelWorksheet sheet in _wb.Worksheets) {
+ var cse = new CellsStoreEnumerator<int>(sheet._styles);
+ while (cse.Next()) {
+ var v = cse.Value;
+ if (v >= 0) {
+ CellXfs[v].useCnt++;
+ }
+ }
+ }
+ foreach (ExcelNamedStyleXml ns in NamedStyles) {
+ CellStyleXfs[ns.StyleXfId].useCnt++;
+ }
+
+ foreach (ExcelXfs xf in CellXfs) {
+ if (xf.useCnt > 0) {
+ if (xf.FontId >= 0) {
+ Fonts[xf.FontId].useCnt++;
+ }
+ if (xf.FillId >= 0) {
+ Fills[xf.FillId].useCnt++;
+ }
+ if (xf.BorderId >= 0) {
+ Borders[xf.BorderId].useCnt++;
+ }
+ }
+ }
+ foreach (ExcelXfs xf in CellStyleXfs) {
+ if (xf.useCnt > 0) {
+ if (xf.FontId >= 0) {
+ Fonts[xf.FontId].useCnt++;
+ }
+ if (xf.FillId >= 0) {
+ Fills[xf.FillId].useCnt++;
+ }
+ if (xf.BorderId >= 0) {
+ Borders[xf.BorderId].useCnt++;
+ }
+ }
+ }
+ }
+
+ internal int GetStyleIdFromName(string name) {
+ int i = NamedStyles.FindIndexById(name);
+ if (i >= 0) {
+ int id = NamedStyles[i].XfId;
+ if (id < 0) {
+ int styleXfId = NamedStyles[i].StyleXfId;
+ ExcelXfs newStyle = CellStyleXfs[styleXfId].Copy();
+ newStyle.XfId = styleXfId;
+ id = CellXfs.FindIndexById(newStyle.Id);
+ if (id < 0) {
+ id = CellXfs.Add(newStyle.Id, newStyle);
+ }
+ NamedStyles[i].XfId = id;
+ }
+ return id;
+ }
+ return 0;
+ //throw(new Exception("Named style does not exist"));
+ }
+
+ private string GetXmlNode(XmlNode node) {
+ if (node == null) {
+ return "";
+ }
+ if (node.Value != null) {
+ return node.Value;
+ }
+ return "";
+ }
+
+ internal int CloneStyle(ExcelStyles style, int styleId) {
+ return CloneStyle(style, styleId, false, false);
+ }
+
+ internal int CloneStyle(ExcelStyles style, int styleId, bool isNamedStyle) {
+ return CloneStyle(style, styleId, isNamedStyle, false);
+ }
+
+ internal int CloneStyle(ExcelStyles style, int styleId, bool isNamedStyle, bool allwaysAdd) {
+ var xfs = isNamedStyle ? style.CellStyleXfs[styleId] : style.CellXfs[styleId];
+ ExcelXfs newXfs = xfs.Copy(this);
+ //Numberformat
+ if (xfs.NumberFormatId > 0) {
+ //rake36: Two problems here...
+ //rake36: 1. the first time through when format stays equal to String.Empty, it adds a string.empty to the list of Number Formats
+ //rake36: 2. when adding a second sheet, if the numberformatid == 164, it finds the 164 added by previous sheets but was using the array index
+ //rake36: for the numberformatid
+
+ string format = string.Empty;
+ foreach (var fmt in style.NumberFormats) {
+ if (fmt.NumFmtId == xfs.NumberFormatId) {
+ format = fmt.Format;
+ break;
+ }
+ }
+ //rake36: Don't add another format if it's blank
+ if (!String.IsNullOrEmpty(format)) {
+ int ix = NumberFormats.FindIndexById(format);
+ if (ix < 0) {
+ var item = new ExcelNumberFormatXml(NameSpaceManager) {
+ Format = format,
+ NumFmtId = NumberFormats.NextId++,
+ };
+ NumberFormats.Add(format, item);
+ //rake36: Use the just added format id
+ newXfs.NumberFormatId = item.NumFmtId;
+ } else {
+ //rake36: Use the format id defined by the index... not the index itself
+ newXfs.NumberFormatId = NumberFormats[ix].NumFmtId;
+ }
+ }
+ }
+
+ //Font
+ if (xfs.FontId > -1) {
+ int ix = Fonts.FindIndexById(xfs.Font.Id);
+ if (ix < 0) {
+ ExcelFontXml item = style.Fonts[xfs.FontId].Copy();
+ ix = Fonts.Add(xfs.Font.Id, item);
+ }
+ newXfs.FontId = ix;
+ }
+
+ //Border
+ if (xfs.BorderId > -1) {
+ int ix = Borders.FindIndexById(xfs.Border.Id);
+ if (ix < 0) {
+ ExcelBorderXml item = style.Borders[xfs.BorderId].Copy();
+ ix = Borders.Add(xfs.Border.Id, item);
+ }
+ newXfs.BorderId = ix;
+ }
+
+ //Fill
+ if (xfs.FillId > -1) {
+ int ix = Fills.FindIndexById(xfs.Fill.Id);
+ if (ix < 0) {
+ var item = style.Fills[xfs.FillId].Copy();
+ ix = Fills.Add(xfs.Fill.Id, item);
+ }
+ newXfs.FillId = ix;
+ }
+
+ //Named style reference
+ if (xfs.XfId > 0) {
+ var id = style.CellStyleXfs[xfs.XfId].Id;
+ var newId = CellStyleXfs.FindIndexById(id);
+ if (newId >= 0) {
+ newXfs.XfId = newId;
+ } else if (style._wb != _wb
+ && allwaysAdd
+ == false) //Not the same workbook, copy the namedstyle to the workbook or match the id
+ {
+ var nsFind = style.NamedStyles.ToDictionary(d => (d.StyleXfId));
+ if (nsFind.ContainsKey(xfs.XfId)) {
+ var st = nsFind[xfs.XfId];
+ if (NamedStyles.ExistsKey(st.Name)) {
+ newXfs.XfId = NamedStyles.FindIndexById(st.Name);
+ } else {
+ var ns = CreateNamedStyle(st.Name, st.Style);
+ newXfs.XfId = NamedStyles.Count - 1;
+ }
+ }
+ }
+ }
+
+ int index;
+ if (isNamedStyle) {
+ index = CellStyleXfs.Add(newXfs.Id, newXfs);
+ } else {
+ if (allwaysAdd) {
+ index = CellXfs.Add(newXfs.Id, newXfs);
+ } else {
+ index = CellXfs.FindIndexById(newXfs.Id);
+ if (index < 0) {
+ index = CellXfs.Add(newXfs.Id, newXfs);
+ }
+ }
+ }
+ return index;
+ }
+}
diff --git a/AppsheetEpplus/ExcelTextFormat.cs b/AppsheetEpplus/ExcelTextFormat.cs
new file mode 100644
index 0000000..8c46b1e
--- /dev/null
+++ b/AppsheetEpplus/ExcelTextFormat.cs
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * 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 Initial Release 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Globalization;
+using System.Text;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Discribes a column when reading a text using the ExcelRangeBase.LoadFromText method
+/// </summary>
+public enum eDataTypes {
+ /// <summary>
+ /// Let the the import decide.
+ /// </summary>
+ Unknown,
+
+ /// <summary>
+ /// Always a string.
+ /// </summary>
+ String,
+
+ /// <summary>
+ /// Try to convert it to a number. If it fails then add it as a string.
+ /// </summary>
+ Number,
+
+ /// <summary>
+ /// Try to convert it to a date. If it fails then add it as a string.
+ /// </summary>
+ DateTime,
+
+ /// <summary>
+ /// Try to convert it to a number and divide with 100.
+ /// Removes any tailing percent sign (%). If it fails then add it as a string.
+ /// </summary>
+ Percent,
+}
+
+/// <summary>
+/// Describes how to split a CSV text. Used by the ExcelRange.LoadFromText method
+/// </summary>
+public class ExcelTextFormat {
+ /// <summary>
+ /// Describes how to split a CSV text
+ ///
+ /// Default values
+ /// <list>
+ /// <listheader><term>Property</term><description>Value</description></listheader>
+ /// <item><term>Delimiter</term><description>,</description></item>
+ /// <item><term>TextQualifier</term><description>None (\0)</description></item>
+ /// <item><term>EOL</term><description>CRLF</description></item>
+ /// <item><term>Culture</term><description>CultureInfo.InvariantCulture</description></item>
+ /// <item><term>DataTypes</term><description>End of line default CRLF</description></item>
+ /// <item><term>SkipLinesBeginning</term><description>0</description></item>
+ /// <item><term>SkipLinesEnd</term><description>0</description></item>
+ /// <item><term>Encoding</term><description>Encoding.ASCII</description></item>
+ /// </list>
+ /// </summary>
+ public ExcelTextFormat() {}
+
+ /// <summary>
+ /// Delimiter character
+ /// </summary>
+ public char Delimiter { get; set; } = ',';
+
+ /// <summary>
+ /// Text qualifier character
+ /// </summary>
+ public char TextQualifier { get; set; } = '\0';
+
+ /// <summary>
+ /// End of line characters. Default CRLF
+ /// </summary>
+ public string EOL { get; set; } = "\r\n";
+
+ /// <summary>
+ /// Datatypes list for each column (if column is not present Unknown is assumed)
+ /// </summary>
+ public eDataTypes[] DataTypes { get; set; } = null;
+
+ /// <summary>
+ /// Culture used when parsing. Default CultureInfo.InvariantCulture
+ /// </summary>
+ public CultureInfo Culture { get; set; } = CultureInfo.InvariantCulture;
+
+ /// <summary>
+ /// Number of lines skiped in the begining of the file. Default 0.
+ /// </summary>
+ public int SkipLinesBeginning { get; set; } = 0;
+
+ /// <summary>
+ /// Number of lines skiped at the end of the file. Default 0.
+ /// </summary>
+ public int SkipLinesEnd { get; set; } = 0;
+
+ /// <summary>
+ /// Only used when reading files from disk using a FileInfo object. Default AscII
+ /// </summary>
+ public Encoding Encoding { get; set; } = Encoding.ASCII;
+}
diff --git a/AppsheetEpplus/ExcelWorkbook.cs b/AppsheetEpplus/ExcelWorkbook.cs
new file mode 100644
index 0000000..c98142d
--- /dev/null
+++ b/AppsheetEpplus/ExcelWorkbook.cs
@@ -0,0 +1,781 @@
+/*******************************************************************************
+ * 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 Initial Release 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ * Richard Tallent Fix escaping of quotes 2012-10-31
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Globalization;
+using System.IO;
+using System.Text;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// How the application should calculate formulas in the workbook
+/// </summary>
+public enum ExcelCalcMode {
+ /// <summary>
+ /// Indicates that calculations in the workbook are performed automatically when cell values change.
+ /// The application recalculates those cells that are dependent on other cells that contain changed values.
+ /// This mode of calculation helps to avoid unnecessary calculations.
+ /// </summary>
+ Automatic,
+
+ /// <summary>
+ /// Indicates tables be excluded during automatic calculation
+ /// </summary>
+ AutomaticNoTable,
+
+ /// <summary>
+ /// Indicates that calculations in the workbook be triggered manually by the user.
+ /// </summary>
+ Manual,
+}
+
+/// <summary>
+/// Represents the Excel workbook and provides access to all the
+/// document properties and worksheets within the workbook.
+/// </summary>
+public sealed class ExcelWorkbook : XmlHelper {
+ internal class SharedStringItem {
+ internal int pos;
+ internal string Text;
+ internal bool isRichText;
+ }
+
+ private readonly ExcelPackage _package;
+ private ExcelWorksheets _worksheets;
+ private OfficeProperties _properties;
+
+ private ExcelStyles _styles;
+
+ internal static ImmutableArray<string> WorkbookSchemaNodeOrder = [
+ "fileVersion",
+ "fileSharing",
+ "workbookPr",
+ "workbookProtection",
+ "bookViews",
+ "sheets",
+ "functionGroups",
+ "functionPrototypes",
+ "externalReferences",
+ "definedNames",
+ "calcPr",
+ "oleSize",
+ "customWorkbookViews",
+ "pivotCaches",
+ "smartTagPr",
+ "smartTagTypes",
+ "webPublishing",
+ "fileRecoveryPr",
+ ];
+
+ protected override ImmutableArray<string> SchemaNodeOrder => WorkbookSchemaNodeOrder;
+
+ internal ExcelWorkbook(ExcelPackage package, XmlNamespaceManager namespaceManager)
+ : base(namespaceManager) {
+ _package = package;
+ _names = new(this);
+ _namespaceManager = namespaceManager;
+
+ WorkbookXml = package.GetOrCreateXmlDocument(
+ WorkbookUri,
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
+ ExcelPackage._schemaRelationships + "/officeDocument",
+ () => CreateEmptyWorkbookXml(namespaceManager));
+ _stylesXml = package.GetOrCreateXmlDocument(
+ StylesUri,
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
+ ExcelPackage._schemaRelationships + "/styles",
+ CreateEmptyStylesXml);
+
+ TopNode = WorkbookXml.DocumentElement;
+ FullCalcOnLoad = true; //Full calculation on load by default, for both new workbooks and templates.
+
+ GetSharedStrings();
+ GetExternalReferences();
+ GetDefinedNames();
+ }
+
+ private static XmlDocument CreateEmptyWorkbookXml(XmlNamespaceManager namespaceManager) {
+ var result = new XmlDocument(namespaceManager.NameTable);
+ var wbElem = result.CreateElement("workbook", ExcelPackage._schemaMain);
+
+ // Add the relationships namespace
+ wbElem.SetAttribute("xmlns:r", ExcelPackage._schemaRelationships);
+ result.AppendChild(wbElem);
+
+ // Create the bookViews and workbooks element
+ var bookViews = result.CreateElement("bookViews", ExcelPackage._schemaMain);
+ wbElem.AppendChild(bookViews);
+ var workbookView = result.CreateElement("workbookView", ExcelPackage._schemaMain);
+ bookViews.AppendChild(workbookView);
+
+ return result;
+ }
+
+ private static XmlDocument CreateEmptyStylesXml() {
+ StringBuilder xml = new StringBuilder(
+ "<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">");
+ xml.Append("<numFmts />");
+ xml.Append("<fonts count=\"1\"><font><sz val=\"11\" /><name val=\"Calibri\" /></font></fonts>");
+ xml.Append(
+ "<fills><fill><patternFill patternType=\"none\" /></fill><fill><patternFill patternType=\"gray125\" /></fill></fills>");
+ xml.Append(
+ "<borders><border><left /><right /><top /><bottom /><diagonal /></border></borders>");
+ xml.Append("<cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" /></cellStyleXfs>");
+ xml.Append("<cellXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" xfId=\"0\" /></cellXfs>");
+ xml.Append("<cellStyles><cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\" /></cellStyles>");
+ xml.Append("<dxfs count=\"0\" />");
+ xml.Append("</styleSheet>");
+
+ var result = new XmlDocument();
+ result.LoadXml(xml.ToString());
+ return result;
+ }
+
+ internal readonly Dictionary<string, SharedStringItem> _sharedStrings = new(); //Used when reading cells.
+ internal List<SharedStringItem> _sharedStringsList = new(); //Used when reading cells.
+ internal ExcelNamedRangeCollection _names;
+ internal int _nextTableID = int.MinValue;
+ internal int _nextPivotTableID = int.MinValue;
+ private readonly XmlNamespaceManager _namespaceManager;
+ private FormulaParser _formulaParser;
+ private FormulaParserManager _parserManager;
+ internal CellStore<List<Token>> _formulaTokens;
+
+ /// <summary>
+ /// Read shared strings to list
+ /// </summary>
+ private void GetSharedStrings() {
+ if (_package.Package.PartExists(SharedStringsUri)) {
+ var xml = _package.GetXmlDocument(SharedStringsUri);
+ XmlNodeList nl = xml.SelectNodes("//d:sst/d:si", NameSpaceManager);
+ _sharedStringsList = new();
+ if (nl != null) {
+ foreach (XmlNode node in nl) {
+ XmlNode n = node.SelectSingleNode("d:t", NameSpaceManager);
+ if (n != null) {
+ _sharedStringsList.Add(
+ new() {
+ Text = ConvertUtil.ExcelDecodeString(n.InnerText),
+ });
+ } else {
+ _sharedStringsList.Add(
+ new() {
+ Text = node.InnerXml,
+ isRichText = true,
+ });
+ }
+ }
+ }
+ //Delete the shared string part, it will be recreated when the package is saved.
+ foreach (var rel in Part.GetRelationships()) {
+ if (rel.TargetUri.OriginalString.EndsWith(
+ "sharedstrings.xml",
+ StringComparison.InvariantCultureIgnoreCase)) {
+ Part.DeleteRelationship(rel.Id);
+ break;
+ }
+ }
+ _package.Package.DeletePart(SharedStringsUri); //Remove the part, it is recreated when saved.
+ }
+ }
+
+ internal void GetDefinedNames() {
+ XmlNodeList nl = WorkbookXml.SelectNodes("//d:definedNames/d:definedName", NameSpaceManager);
+ if (nl != null) {
+ foreach (XmlElement elem in nl) {
+ string fullAddress = elem.InnerText;
+
+ ExcelWorksheet nameWorksheet;
+ if (!int.TryParse(elem.GetAttribute("localSheetId"), out var localSheetId)) {
+ localSheetId = -1;
+ nameWorksheet = null;
+ } else {
+ nameWorksheet = Worksheets[localSheetId + 1];
+ }
+ var addressType = ExcelAddressBase.IsValid(fullAddress);
+ ExcelRangeBase range;
+ ExcelNamedRange namedRange;
+
+ if (fullAddress.IndexOf("[") == 0) {
+ int start = fullAddress.IndexOf("[");
+ int end = fullAddress.IndexOf("]", start);
+ if (start >= 0 && end >= 0) {
+ string externalIndex = fullAddress.Substring(start + 1, end - start - 1);
+ if (int.TryParse(externalIndex, out var index)) {
+ if (index > 0 && index <= _externalReferences.Count) {
+ fullAddress =
+ fullAddress.Substring(0, start)
+ + "["
+ + _externalReferences[index - 1]
+ + "]"
+ + fullAddress.Substring(end + 1);
+ }
+ }
+ }
+ }
+
+ if (addressType == ExcelAddressBase.AddressType.Invalid
+ || addressType == ExcelAddressBase.AddressType.InternalName
+ || addressType == ExcelAddressBase.AddressType.ExternalName
+ || addressType == ExcelAddressBase.AddressType.Formula
+ || addressType
+ == ExcelAddressBase
+ .AddressType
+ .ExternalAddress) //A value or a formula
+ {
+ range = new(this, nameWorksheet, elem.GetAttribute("name"), true);
+ if (nameWorksheet == null) {
+ namedRange = _names.Add(elem.GetAttribute("name"), range);
+ } else {
+ namedRange = nameWorksheet.Names.Add(elem.GetAttribute("name"), range);
+ }
+
+ if (fullAddress.StartsWith(
+ "\"")) //String value
+ {
+ namedRange.NameValue = fullAddress.Substring(1, fullAddress.Length - 2);
+ } else if (double.TryParse(
+ fullAddress,
+ NumberStyles.Any,
+ CultureInfo.InvariantCulture,
+ out var value)) {
+ namedRange.NameValue = value;
+ } else {
+ //if (addressType == ExcelAddressBase.AddressType.ExternalAddress || addressType == ExcelAddressBase.AddressType.ExternalName)
+ //{
+ // var r = new ExcelAddress(fullAddress);
+ // namedRange.NameFormula = '\'[' + r._wb
+ //}
+ //else
+ //{
+ namedRange.NameFormula = fullAddress;
+ //}
+ }
+ } else {
+ ExcelAddress addr = new ExcelAddress(fullAddress, this, null);
+ if (localSheetId > -1) {
+ if (string.IsNullOrEmpty(addr._ws)) {
+ namedRange = Worksheets[localSheetId + 1].Names.Add(
+ elem.GetAttribute("name"),
+ new(this, Worksheets[localSheetId + 1], fullAddress, false));
+ } else {
+ namedRange = Worksheets[localSheetId + 1].Names.Add(
+ elem.GetAttribute("name"),
+ new(this, Worksheets[addr._ws], fullAddress, false));
+ }
+ } else {
+ var ws = Worksheets[addr._ws];
+ namedRange = _names.Add(elem.GetAttribute("name"), new(this, ws, fullAddress, false));
+ }
+ }
+ if (elem.GetAttribute("hidden") == "1" && namedRange != null) {
+ namedRange.IsNameHidden = true;
+ }
+ if (!string.IsNullOrEmpty(elem.GetAttribute("comment"))) {
+ namedRange.NameComment = elem.GetAttribute("comment");
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Provides access to all the worksheets in the workbook.
+ /// </summary>
+ public ExcelWorksheets Worksheets {
+ get {
+ if (_worksheets == null) {
+ var sheetsNode = WorkbookXml.DocumentElement.SelectSingleNode(
+ "d:sheets",
+ _namespaceManager);
+ if (sheetsNode == null) {
+ sheetsNode = CreateNode("d:sheets");
+ }
+
+ _worksheets = new(_package, this, _namespaceManager, sheetsNode);
+ }
+ return (_worksheets);
+ }
+ }
+
+ /// <summary>
+ /// Provides access to named ranges
+ /// </summary>
+ public ExcelNamedRangeCollection Names => _names;
+
+ internal FormulaParser FormulaParser {
+ get {
+ if (_formulaParser == null) {
+ _formulaParser = new(new EpplusExcelDataProvider(this));
+ }
+ return _formulaParser;
+ }
+ }
+
+ public FormulaParserManager FormulaParserManager {
+ get {
+ if (_parserManager == null) {
+ _parserManager = new(FormulaParser);
+ }
+ return _parserManager;
+ }
+ }
+
+ private ExcelProtection _protection;
+
+ /// <summary>
+ /// Access properties to protect or unprotect a workbook
+ /// </summary>
+ public ExcelProtection Protection => _protection ??= new(NameSpaceManager, TopNode);
+
+ private ExcelWorkbookView _view;
+
+ /// <summary>
+ /// Access to workbook view properties
+ /// </summary>
+ public ExcelWorkbookView View {
+ get {
+ if (_view == null) {
+ _view = new(NameSpaceManager, TopNode, this);
+ }
+ return _view;
+ }
+ }
+
+ /// <summary>
+ /// URI to the workbook inside the package
+ /// </summary>
+ internal static Uri WorkbookUri { get; } = new("/xl/workbook.xml", UriKind.Relative);
+
+ /// <summary>
+ /// URI to the styles inside the package
+ /// </summary>
+ private static Uri StylesUri { get; } = new("/xl/styles.xml", UriKind.Relative);
+
+ /// <summary>
+ /// URI to the shared strings inside the package
+ /// </summary>
+ private static Uri SharedStringsUri { get; } = new("/xl/sharedStrings.xml", UriKind.Relative);
+
+ /// <summary>
+ /// Returns a reference to the workbook's part within the package
+ /// </summary>
+ internal ZipPackagePart Part => (_package.Package.GetPart(WorkbookUri));
+
+ /// <summary>
+ /// Provides access to the XML data representing the workbook in the package.
+ /// </summary>
+ internal XmlDocument WorkbookXml { get; }
+
+ private const string _codeModuleNamePath = "d:workbookPr/@codeName";
+
+ internal string CodeModuleName {
+ get => GetXmlNodeString(_codeModuleNamePath);
+ set => SetXmlNodeString(_codeModuleNamePath, value);
+ }
+
+ internal void CodeNameChange(string value) {
+ CodeModuleName = value;
+ }
+
+ private const string _date1904Path = "d:workbookPr/@date1904";
+ internal const double _date1904Offset = 365.5 * 4; // offset to fix 1900 and 1904 differences, 4 OLE years
+
+ /// <summary>
+ /// The date systems used by Microsoft Excel can be based on one of two different dates. By default, a serial number of 1 in Microsoft Excel represents January 1, 1900.
+ /// The default for the serial number 1 can be changed to represent January 2, 1904.
+ /// This option was included in Microsoft Excel for Windows to make it compatible with Excel for the Macintosh, which defaults to January 2, 1904.
+ /// </summary>
+ public bool Date1904 {
+ get => GetXmlNodeBool(_date1904Path, false);
+ set {
+ if (Date1904 != value) {
+ // Like Excel when the option it's changed update it all cells with Date format
+ foreach (var item in Worksheets) {
+ item.UpdateCellsWithDate1904Setting();
+ }
+ }
+
+ SetXmlNodeBool(_date1904Path, value, false);
+ }
+ }
+
+ private readonly XmlDocument _stylesXml;
+
+ /// <summary>
+ /// Package styles collection. Used internally to access style data.
+ /// </summary>
+ public ExcelStyles Styles {
+ get {
+ if (_styles == null) {
+ _styles = new(NameSpaceManager, _stylesXml, this);
+ }
+ return _styles;
+ }
+ }
+
+ /// <summary>
+ /// The office document properties
+ /// </summary>
+ public OfficeProperties Properties {
+ get {
+ if (_properties == null) {
+ // Create a NamespaceManager to handle the default namespace,
+ // and create a prefix for the default namespace:
+ _properties = new(_package, NameSpaceManager);
+ }
+ return _properties;
+ }
+ }
+
+ private readonly string _calcModePath = "d:calcPr/@calcMode";
+
+ /// <summary>
+ /// Calculation mode for the workbook.
+ /// </summary>
+ public ExcelCalcMode CalcMode {
+ get {
+ string calcMode = GetXmlNodeString(_calcModePath);
+ switch (calcMode) {
+ case "autoNoTable":
+ return ExcelCalcMode.AutomaticNoTable;
+ case "manual":
+ return ExcelCalcMode.Manual;
+ default:
+ return ExcelCalcMode.Automatic;
+ }
+ }
+ set {
+ switch (value) {
+ case ExcelCalcMode.AutomaticNoTable:
+ SetXmlNodeString(_calcModePath, "autoNoTable");
+ break;
+ case ExcelCalcMode.Manual:
+ SetXmlNodeString(_calcModePath, "manual");
+ break;
+ default:
+ SetXmlNodeString(_calcModePath, "auto");
+ break;
+ }
+ }
+ }
+
+ private const string _fullCalcOnLoadPath = "d:calcPr/@fullCalcOnLoad";
+
+ /// <summary>
+ /// Should Excel do a full calculation after the workbook has been loaded?
+ /// <remarks>This property is always true for both new workbooks and loaded templates(on load). If this is not the wanted behavior set this property to false.</remarks>
+ /// </summary>
+ public bool FullCalcOnLoad {
+ get => GetXmlNodeBool(_fullCalcOnLoadPath);
+ set => SetXmlNodeBool(_fullCalcOnLoadPath, value);
+ }
+
+ internal void Save() {
+ if (Worksheets.Count == 0) {
+ throw new InvalidOperationException("The workbook must contain at least one worksheet");
+ }
+
+ DeleteCalcChain();
+ UpdateDefinedNamesXml();
+
+ // save the style sheet
+ Styles.UpdateXml();
+
+ // save all the open worksheets
+ var isProtected = Protection.LockWindows || Protection.LockStructure;
+ foreach (ExcelWorksheet worksheet in Worksheets) {
+ if (isProtected && Protection.LockWindows) {
+ worksheet.View.WindowProtection = true;
+ }
+ worksheet.Save();
+ }
+
+ _package.Package.CreatePart(
+ SharedStringsUri,
+ ExcelPackage._contentTypeSharedString,
+ SaveSharedStringHandler);
+ Part.CreateRelationship(
+ UriHelper.GetRelativeUri(WorkbookUri, SharedStringsUri),
+ TargetMode.Internal,
+ ExcelPackage._schemaRelationships + "/sharedStrings");
+
+ // Data validation
+ ValidateDataValidations();
+ }
+
+ private void DeleteCalcChain() {
+ //Remove the calc chain if it exists.
+ Uri uriCalcChain = new Uri("/xl/calcChain.xml", UriKind.Relative);
+ if (_package.Package.PartExists(uriCalcChain)) {
+ Uri calcChain = new Uri("calcChain.xml", UriKind.Relative);
+ foreach (var relationship in Part.GetRelationships()) {
+ if (relationship.TargetUri == calcChain) {
+ Part.DeleteRelationship(relationship.Id);
+ break;
+ }
+ }
+ // delete the calcChain part
+ _package.Package.DeletePart(uriCalcChain);
+ }
+ }
+
+ private void ValidateDataValidations() {
+ foreach (var sheet in Worksheets) {
+ if (!(sheet is ExcelChartsheet)) {
+ sheet.DataValidations.ValidateAll();
+ }
+ }
+ }
+
+ private void SaveSharedStringHandler(StreamWriter sw) {
+ var cache = new StringBuilder();
+ cache.AppendFormat(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><sst xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" count=\"{0}\" uniqueCount=\"{0}\">",
+ _sharedStrings.Count);
+ foreach (string t in _sharedStrings.Keys) {
+ SharedStringItem ssi = _sharedStrings[t];
+ if (ssi.isRichText) {
+ cache.Append("<si>");
+ ConvertUtil.ExcelEncodeString(cache, t);
+ cache.Append("</si>");
+ } else {
+ if (t.Length > 0
+ && (t[0] == ' '
+ || t[t.Length - 1] == ' '
+ || t.Contains(" ")
+ || t.Contains("\t")
+ || t.Contains("\n")
+ || t.Contains(
+ "\n"))) //Fixes issue 14849
+ {
+ cache.Append("<si><t xml:space=\"preserve\">");
+ } else {
+ cache.Append("<si><t>");
+ }
+ ConvertUtil.ExcelEncodeString(cache, ConvertUtil.ExcelEscapeString(t));
+ cache.Append("</t></si>");
+ }
+ if (cache.Length > 0x600000) {
+ sw.Write(cache.ToString());
+ cache = new();
+ }
+ }
+ cache.Append("</sst>");
+ sw.Write(cache.ToString());
+ sw.Flush();
+ Part.CreateRelationship(
+ UriHelper.GetRelativeUri(WorkbookUri, SharedStringsUri),
+ TargetMode.Internal,
+ ExcelPackage._schemaRelationships + "/sharedStrings");
+ }
+
+ private void UpdateDefinedNamesXml() {
+ try {
+ XmlNode top = WorkbookXml.SelectSingleNode("//d:definedNames", NameSpaceManager);
+ if (!ExistsNames()) {
+ if (top != null) {
+ TopNode.RemoveChild(top);
+ }
+ return;
+ }
+ if (top == null) {
+ CreateNode("d:definedNames");
+ top = WorkbookXml.SelectSingleNode("//d:definedNames", NameSpaceManager);
+ } else {
+ top.RemoveAll();
+ }
+ foreach (ExcelNamedRange name in _names) {
+ XmlElement elem = WorkbookXml.CreateElement("definedName", ExcelPackage._schemaMain);
+ top.AppendChild(elem);
+ elem.SetAttribute("name", name.Name);
+ if (name.IsNameHidden) {
+ elem.SetAttribute("hidden", "1");
+ }
+ if (!string.IsNullOrEmpty(name.NameComment)) {
+ elem.SetAttribute("comment", name.NameComment);
+ }
+ SetNameElement(name, elem);
+ }
+ foreach (ExcelWorksheet ws in _worksheets) {
+ if (!(ws is ExcelChartsheet)) {
+ foreach (ExcelNamedRange name in ws.Names) {
+ XmlElement elem = WorkbookXml.CreateElement("definedName", ExcelPackage._schemaMain);
+ top.AppendChild(elem);
+ elem.SetAttribute("name", name.Name);
+ elem.SetAttribute("localSheetId", name.LocalSheetId.ToString());
+ if (name.IsNameHidden) {
+ elem.SetAttribute("hidden", "1");
+ }
+ if (!string.IsNullOrEmpty(name.NameComment)) {
+ elem.SetAttribute("comment", name.NameComment);
+ }
+ SetNameElement(name, elem);
+ }
+ }
+ }
+ } catch (Exception ex) {
+ throw new("Internal error updating named ranges ", ex);
+ }
+ }
+
+ private void SetNameElement(ExcelNamedRange name, XmlElement elem) {
+ if (name.IsName) {
+ if (string.IsNullOrEmpty(name.NameFormula)) {
+ if ((name.NameValue.GetType().IsPrimitive
+ || name.NameValue is double
+ || name.NameValue is decimal)) {
+ elem.InnerText = Convert
+ .ToDouble(name.NameValue, CultureInfo.InvariantCulture)
+ .ToString("R15", CultureInfo.InvariantCulture);
+ } else if (name.NameValue is DateTime time) {
+ elem.InnerText = time.ToOADate().ToString(CultureInfo.InvariantCulture);
+ } else {
+ elem.InnerText = "\"" + name.NameValue + "\"";
+ }
+ } else {
+ elem.InnerText = name.NameFormula;
+ }
+ } else {
+ elem.InnerText = name.FullAddressAbsolute;
+ }
+ }
+
+ /// <summary>
+ /// Is their any names in the workbook or in the sheets.
+ /// </summary>
+ /// <returns>?</returns>
+ private bool ExistsNames() {
+ if (_names.Count == 0) {
+ foreach (ExcelWorksheet ws in Worksheets) {
+ if (ws is ExcelChartsheet) {
+ continue;
+ }
+ if (ws.Names.Count > 0) {
+ return true;
+ }
+ }
+ } else {
+ return true;
+ }
+ return false;
+ }
+
+ internal bool ExistsTableName(string name) {
+ foreach (var ws in Worksheets) {
+ if (ws.Tables._tableNames.ContainsKey(name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ internal bool ExistsPivotTableName(string name) {
+ foreach (var ws in Worksheets) {
+ if (ws.PivotTables._pivotTableNames.ContainsKey(name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ internal void AddPivotTable(string cacheId, Uri defUri) {
+ CreateNode("d:pivotCaches");
+
+ XmlElement item = WorkbookXml.CreateElement("pivotCache", ExcelPackage._schemaMain);
+ item.SetAttribute("cacheId", cacheId);
+ var rel = Part.CreateRelationship(
+ UriHelper.ResolvePartUri(WorkbookUri, defUri),
+ TargetMode.Internal,
+ ExcelPackage._schemaRelationships + "/pivotCacheDefinition");
+ item.SetAttribute("id", ExcelPackage._schemaRelationships, rel.Id);
+
+ var pivotCaches = WorkbookXml.SelectSingleNode("//d:pivotCaches", NameSpaceManager);
+ pivotCaches.AppendChild(item);
+ }
+
+ internal List<string> _externalReferences = new();
+
+ //internal bool _isCalculated=false;
+ internal void GetExternalReferences() {
+ XmlNodeList nl = WorkbookXml.SelectNodes(
+ "//d:externalReferences/d:externalReference",
+ NameSpaceManager);
+ if (nl != null) {
+ foreach (XmlElement elem in nl) {
+ string rId = elem.GetAttribute("r:id");
+ var rel = Part.GetRelationship(rId);
+ var part = _package.Package.GetPart(UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri));
+ XmlDocument xmlExtRef = new XmlDocument();
+ LoadXmlSafe(xmlExtRef, part.GetStream());
+
+ XmlElement book =
+ xmlExtRef.SelectSingleNode("//d:externalBook", NameSpaceManager) as XmlElement;
+ if (book != null) {
+ string rIdExtRef = book.GetAttribute("r:id");
+ var relExtRef = part.GetRelationship(rIdExtRef);
+ if (relExtRef != null) {
+ _externalReferences.Add(relExtRef.TargetUri.OriginalString);
+ }
+ }
+ }
+ }
+ }
+
+ internal void ReadAllTables() {
+ if (_nextTableID > 0) {
+ return;
+ }
+ _nextTableID = 1;
+ _nextPivotTableID = 1;
+ foreach (var ws in Worksheets) {
+ if (!(ws
+ is ExcelChartsheet)) //Fixes 15273. Chartsheets should be ignored.
+ {
+ foreach (var tbl in ws.Tables) {
+ if (tbl.Id >= _nextTableID) {
+ _nextTableID = tbl.Id + 1;
+ }
+ }
+ foreach (var pt in ws.PivotTables) {
+ if (pt.CacheID >= _nextPivotTableID) {
+ _nextPivotTableID = pt.CacheID + 1;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/AppsheetEpplus/ExcelWorkbookView.cs b/AppsheetEpplus/ExcelWorkbookView.cs
new file mode 100644
index 0000000..263bddb
--- /dev/null
+++ b/AppsheetEpplus/ExcelWorkbookView.cs
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * 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 Initial Release 2011-11-02
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Collections.Immutable;
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Access to workbook view properties
+/// </summary>
+public class ExcelWorkbookView : XmlHelper {
+ protected override ImmutableArray<string> SchemaNodeOrder =>
+ ExcelWorkbook.WorkbookSchemaNodeOrder;
+
+ /// <summary>
+ /// Creates a new ExcelWorkbookView which provides access to all the
+ /// view states of the worksheet.
+ /// </summary>
+ /// <param name="ns"></param>
+ /// <param name="node"></param>
+ /// <param name="wb"></param>
+ internal ExcelWorkbookView(XmlNamespaceManager ns, XmlNode node, ExcelWorkbook wb)
+ : base(ns, node) {}
+
+ private const string _leftPath = "d:bookViews/d:workbookView/@xWindow";
+
+ /// <summary>
+ /// Position of the upper left corner of the workbook window. In twips.
+ /// </summary>
+ public int Left {
+ get => GetXmlNodeInt(_leftPath);
+ internal set => SetXmlNodeString(_leftPath, value.ToString());
+ }
+
+ private const string _topPath = "d:bookViews/d:workbookView/@yWindow";
+
+ /// <summary>
+ /// Position of the upper left corner of the workbook window. In twips.
+ /// </summary>
+ public int Top {
+ get => GetXmlNodeInt(_topPath);
+ internal set => SetXmlNodeString(_topPath, value.ToString());
+ }
+
+ private const string _widthPath = "d:bookViews/d:workbookView/@windowWidth";
+
+ /// <summary>
+ /// Width of the workbook window. In twips.
+ /// </summary>
+ public int Width {
+ get => GetXmlNodeInt(_widthPath);
+ internal set => SetXmlNodeString(_widthPath, value.ToString());
+ }
+
+ private const string _heightPath = "d:bookViews/d:workbookView/@windowHeight";
+
+ /// <summary>
+ /// Height of the workbook window. In twips.
+ /// </summary>
+ public int Height {
+ get => GetXmlNodeInt(_heightPath);
+ internal set => SetXmlNodeString(_heightPath, value.ToString());
+ }
+
+ private const string _minimizedPath = "d:bookViews/d:workbookView/@minimized";
+
+ /// <summary>
+ /// If true the the workbook window is minimized.
+ /// </summary>
+ public bool Minimized {
+ get => GetXmlNodeBool(_minimizedPath);
+ set => SetXmlNodeString(_minimizedPath, value.ToString());
+ }
+
+ private const string _showverticalscrollPath = "d:bookViews/d:workbookView/@showVerticalScroll";
+
+ /// <summary>
+ /// Show the vertical scrollbar
+ /// </summary>
+ public bool ShowVerticalScrollBar {
+ get => GetXmlNodeBool(_showverticalscrollPath, true);
+ set => SetXmlNodeBool(_showverticalscrollPath, value, true);
+ }
+
+ private const string _showhorizontalscrPath = "d:bookViews/d:workbookView/@showHorizontalScroll";
+
+ /// <summary>
+ /// Show the horizontal scrollbar
+ /// </summary>
+ public bool ShowHorizontalScrollBar {
+ get => GetXmlNodeBool(_showhorizontalscrPath, true);
+ set => SetXmlNodeBool(_showhorizontalscrPath, value, true);
+ }
+
+ private const string _showsheettabsPath = "d:bookViews/d:workbookView/@showSheetTabs";
+
+ /// <summary>
+ /// Show the sheet tabs
+ /// </summary>
+ public bool ShowSheetTabs {
+ get => GetXmlNodeBool(_showsheettabsPath, true);
+ set => SetXmlNodeBool(_showsheettabsPath, value, true);
+ }
+
+ /// <summary>
+ /// Set the window position in twips
+ /// </summary>
+ /// <param name="left"></param>
+ /// <param name="top"></param>
+ /// <param name="width"></param>
+ /// <param name="height"></param>
+ public void SetWindowSize(int left, int top, int width, int height) {
+ Left = left;
+ Top = top;
+ Width = width;
+ Height = height;
+ }
+
+ private const string _activetabPath = "d:bookViews/d:workbookView/@activeTab";
+
+ public int ActiveTab {
+ get {
+ var v = GetXmlNodeInt(_activetabPath);
+ if (v < 0) {
+ return 0;
+ }
+ return v;
+ }
+ set => SetXmlNodeString(_activetabPath, value.ToString(CultureInfo.InvariantCulture));
+ }
+}
diff --git a/AppsheetEpplus/ExcelWorksheet.cs b/AppsheetEpplus/ExcelWorksheet.cs
new file mode 100644
index 0000000..2031fe3
--- /dev/null
+++ b/AppsheetEpplus/ExcelWorksheet.cs
@@ -0,0 +1,3227 @@
+/*******************************************************************************
+* 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 Initial Release 2011-11-02
+* Jan Källman Total rewrite 2010-03-01
+* Jan Källman License changed GPL-->LGPL 2011-12-27
+*******************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.ComponentModel;
+using System.Globalization;
+using System.IO;
+using System.Security;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Worksheet hidden enumeration
+/// </summary>
+public enum eWorkSheetHidden {
+ /// <summary>
+ /// The worksheet is visible
+ /// </summary>
+ Visible,
+
+ /// <summary>
+ /// The worksheet is hidden but can be shown by the user via the user interface
+ /// </summary>
+ Hidden,
+
+ /// <summary>
+ /// The worksheet is hidden and cannot be shown by the user via the user interface
+ /// </summary>
+ VeryHidden,
+}
+
+[Flags]
+internal enum CellFlags {
+ //Merged = 0x1,
+ RichText = 0x2,
+ SharedFormula = 0x4,
+ ArrayFormula = 0x8,
+}
+
+/// <summary>
+/// Represents an Excel Chartsheet and provides access to its properties and methods
+/// </summary>
+public class ExcelChartsheet : ExcelWorksheet {
+ public ExcelChartsheet(
+ XmlNamespaceManager ns,
+ ExcelPackage pck,
+ ExcelWorkbook workbook,
+ Uri worksheetUri,
+ string name,
+ int sheetId,
+ int positionId,
+ eWorkSheetHidden hidden)
+ : base(ns, pck, workbook, worksheetUri, name, sheetId, positionId, hidden) {}
+}
+
+/// <summary>
+/// Represents an Excel worksheet and provides access to its properties and methods
+/// </summary>
+public class ExcelWorksheet : XmlHelper, IEqualityComparer<ExcelWorksheet> {
+ internal class Formulas {
+ public Formulas(ISourceCodeTokenizer tokenizer) {
+ _tokenizer = tokenizer;
+ }
+
+ public static string RemoveDummyFunction(string formula) {
+ const string dummyFunctionConcatenate = "\"&\"";
+ const string dummyFunctionPrefix = "IFERROR(__xludf.DUMMYFUNCTION(\"";
+ const string dummyFunctionSuffix = "\"),";
+
+ if (string.IsNullOrEmpty(formula)) {
+ return formula;
+ }
+
+ // Look for Prefix
+ if (!formula.StartsWith(dummyFunctionPrefix)) {
+ return formula;
+ }
+
+ // Look for Suffix
+ int index = formula.LastIndexOf(dummyFunctionSuffix);
+ if (index < 0) {
+ return formula;
+ }
+
+ // Trim Suffix
+ formula = formula.Substring(0, index);
+
+ // Trim Prefix
+ formula = formula.Replace(dummyFunctionPrefix, "");
+
+ // Remove string concatentations from long formulas.
+ // Google break the quoted string into 254 character segments which are concatenated.
+ if (formula.Length >= 254) {
+ formula = formula.Replace(dummyFunctionConcatenate, "");
+ }
+
+ // Replace doubled quotes with single quote
+ formula = formula.Replace("\"\"", "\"");
+
+ // Return formula
+ return formula;
+ }
+
+ private readonly ISourceCodeTokenizer _tokenizer;
+
+ internal int Index { get; set; }
+
+ internal string Address { get; set; }
+
+ internal bool IsArray { get; set; }
+
+ public string Formula { get; set; }
+
+ public int StartRow { get; set; }
+
+ public int StartCol { get; set; }
+
+ private IEnumerable<Token> Tokens { get; set; }
+
+ internal string GetFormula(int row, int column, string worksheet) {
+ if ((StartRow == row && StartCol == column) || IsArray) {
+ return RemoveDummyFunction(Formula);
+ }
+
+ if (Tokens == null) {
+ Tokens = _tokenizer.Tokenize(RemoveDummyFunction(Formula), worksheet);
+ }
+
+ string f = "";
+ foreach (var token in Tokens) {
+ if (token.TokenType == TokenType.ExcelAddress) {
+ var a = new ExcelFormulaAddress(token.Value);
+ f += a.GetOffset(row - StartRow, column - StartCol);
+ } else {
+ f += token.Value;
+ }
+ }
+ return f;
+ }
+ }
+
+ /// <summary>
+ /// Collection containing merged cell addresses
+ /// </summary>
+ public class MergeCellsCollection : IEnumerable<string> {
+ internal MergeCellsCollection() {}
+
+ internal readonly CellStore<int> _cells = new();
+ private readonly List<string> _list = [];
+
+ internal List<string> List => _list;
+
+ public string this[int row, int column] {
+ get {
+ int ix = -1;
+ if (_cells.Exists(row, column, ref ix)
+ && ix >= 0
+ && ix
+ < List.Count) //Fixes issue 15075
+ {
+ return List[ix];
+ }
+ return null;
+ }
+ }
+
+ public string this[int index] => _list[index];
+
+ internal void Add(ExcelAddressBase address, bool doValidate) {
+ //Validate
+ if (doValidate && Validate(address) == false) {
+ throw (new ArgumentException("Can't merge and already merged range"));
+ }
+ var ix = _list.Count;
+ _list.Add(address.Address);
+ SetIndex(address, ix);
+ }
+
+ private bool Validate(ExcelAddressBase address) {
+ int ix = 0;
+ if (_cells.Exists(address._fromRow, address._fromCol, ref ix)) {
+ if (ix >= 0 && ix < _list.Count && _list[ix] != null && address.Address == _list[ix]) {
+ return true;
+ }
+ return false;
+ }
+
+ var cse = new CellsStoreEnumerator<int>(
+ _cells,
+ address._fromRow,
+ address._fromCol,
+ address._toRow,
+ address._toCol);
+ //cells
+ while (cse.Next()) {
+ return false;
+ }
+ //Entire column
+ cse = new(_cells, 0, address._fromCol, 0, address._toCol);
+ while (cse.Next()) {
+ return false;
+ }
+ //Entire row
+ cse = new(_cells, address._fromRow, 0, address._toRow, 0);
+ while (cse.Next()) {
+ return false;
+ }
+ return true;
+ }
+
+ internal void SetIndex(ExcelAddressBase address, int ix) {
+ if (address._fromRow == 1
+ && address._toRow
+ == ExcelPackage.MaxRows) //Entire row
+ {
+ for (int col = address._fromCol; col <= address._toCol; col++) {
+ _cells.SetValue(0, col, ix);
+ }
+ } else if (address._fromCol == 1
+ && address._toCol
+ == ExcelPackage.MaxColumns) //Entire row
+ {
+ for (int row = address._fromRow; row <= address._toRow; row++) {
+ _cells.SetValue(row, 0, ix);
+ }
+ } else {
+ for (int col = address._fromCol; col <= address._toCol; col++) {
+ for (int row = address._fromRow; row <= address._toRow; row++) {
+ _cells.SetValue(row, col, ix);
+ }
+ }
+ }
+ }
+
+ public int Count => _list.Count;
+
+ internal void Remove(string item) {
+ _list.Remove(item);
+ }
+
+ public IEnumerator<string> GetEnumerator() {
+ return _list.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _list.GetEnumerator();
+ }
+
+ internal void Clear(ExcelAddressBase destination) {
+ var cse = new CellsStoreEnumerator<int>(
+ _cells,
+ destination._fromRow,
+ destination._fromCol,
+ destination._toRow,
+ destination._toCol);
+ var used = new HashSet<int>();
+ while (cse.Next()) {
+ var v = cse.Value;
+ if (!used.Contains(v) && _list[v] != null) {
+ var adr = new ExcelAddressBase(_list[v]);
+ if (!(destination.Collide(adr) == ExcelAddressBase.eAddressCollition.Inside
+ || destination.Collide(adr) == ExcelAddressBase.eAddressCollition.Equal)) {
+ throw (new InvalidOperationException(
+ string.Format(
+ "Can't delete merged cells. A range is partly merged with the deleted range. {0}",
+ adr._address)));
+ }
+ used.Add(v);
+ }
+ }
+
+ _cells.Clear(
+ destination._fromRow,
+ destination._fromCol,
+ destination._toRow - destination._fromRow + 1,
+ destination._toCol - destination._fromCol + 1);
+ foreach (var i in used) {
+ _list[i] = null;
+ }
+ }
+ }
+
+ internal readonly CellStore<object> _values = new();
+ internal readonly CellStore<string> _types = new();
+ internal readonly CellStore<int> _styles = new();
+ internal readonly CellStore<object> _formulas = new();
+ internal readonly FlagCellStore _flags = new();
+ internal CellStore<List<Token>> _formulaTokens;
+
+ internal readonly CellStore<Uri> _hyperLinks = new();
+ internal readonly CellStore<ExcelComment> _commentsStore = new();
+
+ internal readonly Dictionary<int, Formulas> _sharedFormulas = new();
+
+ internal readonly ExcelPackage _package;
+ private readonly ExcelWorkbook _workbook;
+ private ExcelWorksheetView _sheetView;
+
+ internal static ImmutableArray<string> WorksheetSchemaNodeOrder = [
+ "sheetPr",
+ "tabColor",
+ "outlinePr",
+ "pageSetUpPr",
+ "dimension",
+ "sheetViews",
+ "sheetFormatPr",
+ "cols",
+ "sheetData",
+ "sheetProtection",
+ "protectedRanges",
+ "scenarios",
+ "autoFilter",
+ "sortState",
+ "dataConsolidate",
+ "customSheetViews",
+ "customSheetViews",
+ "mergeCells",
+ "phoneticPr",
+ "conditionalFormatting",
+ "dataValidations",
+ "hyperlinks",
+ "printOptions",
+ "pageMargins",
+ "pageSetup",
+ "headerFooter",
+ "linePrint",
+ "rowBreaks",
+ "colBreaks",
+ "customProperties",
+ "cellWatches",
+ "ignoredErrors",
+ "smartTags",
+ "drawing",
+ "legacyDrawing",
+ "legacyDrawingHF",
+ "picture",
+ "oleObjects",
+ "activeXControls",
+ "webPublishItems",
+ "tableParts",
+ "extLst",
+ ];
+
+ protected override ImmutableArray<string> SchemaNodeOrder => WorksheetSchemaNodeOrder;
+
+ internal ExcelWorksheet(
+ XmlNamespaceManager ns,
+ ExcelPackage excelPackage,
+ ExcelWorkbook workbook,
+ Uri worksheetUri,
+ string name,
+ int sheetId,
+ int positionId,
+ eWorkSheetHidden hidden)
+ : base(ns, null) {
+ _workbook = workbook;
+ _package = excelPackage;
+ _names = new(Workbook, this);
+
+ Hidden = hidden;
+ Name = name;
+ PositionID = positionId;
+ SheetID = sheetId;
+
+ Part = _package.Package.GetPart(worksheetUri);
+ Part.SaveHandler = SaveHandler;
+
+ // First Columns, rows, cells, mergecells, hyperlinks and pagebreakes are loaded from an
+ // XmlTextReader to optimize speed.
+ using var stream = Part.GetStream();
+ var xr = new XmlTextReader(stream);
+ xr.ProhibitDtd = true;
+ xr.WhitespaceHandling = WhitespaceHandling.None;
+ LoadColumns(xr); //columnXml
+ long start = stream.Position;
+ LoadCells(xr);
+ var nextElementLength = GetAttributeLength(xr);
+ long end = stream.Position - nextElementLength;
+ LoadMergeCells(xr);
+ LoadHyperLinks(xr);
+ LoadRowPageBreakes(xr);
+ LoadColPageBreakes(xr);
+
+ // Then the rest of the XML is extracted and loaded into the WorksheetXml document.
+ stream.Seek(0, SeekOrigin.Begin);
+ var xml = GetWorkSheetXml(stream, start, end, out var encoding);
+
+ //first char is invalid sometimes??
+ if (xml[0] != '<') {
+ LoadXmlSafe(WorksheetXml, xml.Substring(1, xml.Length - 1), encoding);
+ } else {
+ LoadXmlSafe(WorksheetXml, xml, encoding);
+ }
+ ClearNodes();
+
+ TopNode = WorksheetXml.DocumentElement;
+ }
+
+ /// <summary>
+ /// The Zip.ZipPackagePart for the worksheet within the package
+ /// </summary>
+ internal ZipPackagePart Part { get; }
+
+ /// <summary>
+ /// The unique identifier for the worksheet.
+ /// </summary>
+ internal int SheetID { get; }
+
+ /// <summary>
+ /// The position of the worksheet.
+ /// </summary>
+ internal int PositionID { get; }
+
+ /// <summary>
+ /// Address for autofilter
+ /// <seealso cref="ExcelRangeBase.AutoFilter" />
+ /// </summary>
+ public ExcelAddressBase AutoFilterAddress {
+ get {
+ CheckSheetType();
+ string address = GetXmlNodeString("d:autoFilter/@ref");
+ if (address == "") {
+ return null;
+ }
+ return new(address);
+ }
+ internal set {
+ CheckSheetType();
+ SetXmlNodeString("d:autoFilter/@ref", value.Address);
+ }
+ }
+
+ internal void CheckSheetType() {
+ if (this is ExcelChartsheet) {
+ throw (new NotSupportedException(
+ "This property or method is not supported for a Chartsheet"));
+ }
+ }
+
+ /// <summary>
+ /// Returns a ExcelWorksheetView object that allows you to set the view state properties of the worksheet
+ /// </summary>
+ public ExcelWorksheetView View {
+ get {
+ if (_sheetView == null) {
+ XmlNode node = TopNode.SelectSingleNode("d:sheetViews/d:sheetView", NameSpaceManager);
+ if (node == null) {
+ CreateNode("d:sheetViews/d:sheetView"); //this one shouls always exist. but check anyway
+ node = TopNode.SelectSingleNode("d:sheetViews/d:sheetView", NameSpaceManager);
+ }
+ _sheetView = new(NameSpaceManager, node, this);
+ }
+ return (_sheetView);
+ }
+ }
+
+ /// <summary>
+ /// The worksheet's display name as it appears on the tab
+ /// </summary>
+ public string Name { get; }
+
+ private readonly ExcelNamedRangeCollection _names;
+
+ /// <summary>
+ /// Provides access to named ranges
+ /// </summary>
+ public ExcelNamedRangeCollection Names {
+ get {
+ CheckSheetType();
+ return _names;
+ }
+ }
+
+ /// <summary>
+ /// Indicates if the worksheet is hidden in the workbook
+ /// </summary>
+ public eWorkSheetHidden Hidden {
+ get {
+ string state = _workbook.GetXmlNodeString(
+ string.Format("d:sheets/d:sheet[@sheetId={0}]/@state", SheetID));
+ if (state == "hidden") {
+ return eWorkSheetHidden.Hidden;
+ }
+ if (state == "veryHidden") {
+ return eWorkSheetHidden.VeryHidden;
+ }
+ return eWorkSheetHidden.Visible;
+ }
+ set {
+ if (value == eWorkSheetHidden.Visible) {
+ _workbook.DeleteNode(string.Format("d:sheets/d:sheet[@sheetId={0}]/@state", SheetID));
+ } else {
+ string v;
+ v = value.ToString();
+ v = v.Substring(0, 1).ToLower(CultureInfo.InvariantCulture) + v.Substring(1);
+ _workbook.SetXmlNodeString(
+ string.Format("d:sheets/d:sheet[@sheetId={0}]/@state", SheetID),
+ v);
+ }
+ }
+ }
+
+ private double _defaultRowHeight = double.NaN;
+
+ /// <summary>
+ /// Get/set the default height of all rows in the worksheet
+ /// </summary>
+ public double DefaultRowHeight {
+ get {
+ CheckSheetType();
+ if (double.IsNaN(_defaultRowHeight)) {
+ _defaultRowHeight = GetXmlNodeDouble("d:sheetFormatPr/@defaultRowHeight");
+ if (double.IsNaN(_defaultRowHeight)) {
+ _defaultRowHeight = 15; // Excel default height
+ }
+ }
+ return _defaultRowHeight;
+ }
+ set {
+ CheckSheetType();
+ _defaultRowHeight = value;
+ SetXmlNodeString(
+ "d:sheetFormatPr/@defaultRowHeight",
+ value.ToString(CultureInfo.InvariantCulture));
+ SetXmlNodeBool("d:sheetFormatPr/@customHeight", value != 15);
+
+ if (double.IsNaN(GetXmlNodeDouble("d:sheetFormatPr/@defaultColWidth"))) {
+ DefaultColWidth = 9.140625;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Get/set the default width of all rows in the worksheet
+ /// </summary>
+ public double DefaultColWidth {
+ get {
+ CheckSheetType();
+ double ret = GetXmlNodeDouble("d:sheetFormatPr/@defaultColWidth");
+ if (double.IsNaN(ret)) {
+ ret = 9.140625; // Excel's default width
+ }
+ return ret;
+ }
+ set {
+ CheckSheetType();
+ SetXmlNodeString(
+ "d:sheetFormatPr/@defaultColWidth",
+ value.ToString(CultureInfo.InvariantCulture));
+
+ if (double.IsNaN(GetXmlNodeDouble("d:sheetFormatPr/@defaultRowHeight"))) {
+ DefaultRowHeight = 15;
+ }
+ }
+ }
+
+ /** <outlinePr applyStyles="1" summaryBelow="0" summaryRight="0" /> **/
+ private const string _outLineSummaryBelowPath = "d:sheetPr/d:outlinePr/@summaryBelow";
+
+ /// <summary>
+ /// Summary rows below details
+ /// </summary>
+ public bool OutLineSummaryBelow {
+ get {
+ CheckSheetType();
+ return GetXmlNodeBool(_outLineSummaryBelowPath);
+ }
+ set {
+ CheckSheetType();
+ SetXmlNodeString(_outLineSummaryBelowPath, value ? "1" : "0");
+ }
+ }
+
+ private const string _outLineSummaryRightPath = "d:sheetPr/d:outlinePr/@summaryRight";
+
+ /// <summary>
+ /// Summary rows to right of details
+ /// </summary>
+ public bool OutLineSummaryRight {
+ get {
+ CheckSheetType();
+ return GetXmlNodeBool(_outLineSummaryRightPath);
+ }
+ set {
+ CheckSheetType();
+ SetXmlNodeString(_outLineSummaryRightPath, value ? "1" : "0");
+ }
+ }
+
+ private const string _outLineApplyStylePath = "d:sheetPr/d:outlinePr/@applyStyles";
+
+ /// <summary>
+ /// Automatic styles
+ /// </summary>
+ public bool OutLineApplyStyle {
+ get {
+ CheckSheetType();
+ return GetXmlNodeBool(_outLineApplyStylePath);
+ }
+ set {
+ CheckSheetType();
+ SetXmlNodeString(_outLineApplyStylePath, value ? "1" : "0");
+ }
+ }
+
+ private const string _codeModuleNamePath = "d:sheetPr/@codeName";
+
+ internal string CodeModuleName {
+ get => GetXmlNodeString(_codeModuleNamePath);
+ set => SetXmlNodeString(_codeModuleNamePath, value);
+ }
+
+ /// <summary>
+ /// The XML document holding the worksheet data.
+ /// All column, row, cell, pagebreak, merged cell and hyperlink-data are loaded into memory and removed from the document when loading the document.
+ /// </summary>
+ internal XmlDocument WorksheetXml { get; } = new();
+
+ internal ExcelVmlDrawingCommentCollection _vmlDrawings;
+
+ /// <summary>
+ /// Vml drawings. underlaying object for comments
+ /// </summary>
+ internal ExcelVmlDrawingCommentCollection VmlDrawingsComments {
+ get {
+ if (_vmlDrawings == null) {
+ CreateVmlCollection();
+ }
+ return _vmlDrawings;
+ }
+ }
+
+ internal ExcelCommentCollection _comments;
+
+ /// <summary>
+ /// Collection of comments
+ /// </summary>
+ public ExcelCommentCollection Comments {
+ get {
+ CheckSheetType();
+ if (_comments == null) {
+ CreateVmlCollection();
+ _comments = new(_package, this, NameSpaceManager);
+ }
+ return _comments;
+ }
+ }
+
+ private void CreateVmlCollection() {
+ var vmlNode = WorksheetXml.DocumentElement.SelectSingleNode(
+ "d:legacyDrawing/@r:id",
+ NameSpaceManager);
+ if (vmlNode == null) {
+ _vmlDrawings = new(_package, this, null);
+ } else {
+ if (Part.RelationshipExists(vmlNode.Value)) {
+ var rel = Part.GetRelationship(vmlNode.Value);
+ var vmlUri = UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri);
+
+ _vmlDrawings = new(_package, this, vmlUri);
+ _vmlDrawings.RelId = rel.Id;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Get the lenth of the attributes
+ /// Conditional formatting attributes can be extremly long som get length of the attributes to finetune position.
+ /// </summary>
+ /// <param name="xr"></param>
+ /// <returns></returns>
+ private int GetAttributeLength(XmlTextReader xr) {
+ if (xr.NodeType != XmlNodeType.Element) {
+ return 0;
+ }
+ var length = 0;
+
+ for (int i = 0; i < xr.AttributeCount; i++) {
+ var a = xr.GetAttribute(i);
+ length += string.IsNullOrEmpty(a) ? 0 : a.Length;
+ }
+ return length;
+ }
+
+ private void LoadRowPageBreakes(XmlTextReader xr) {
+ if (!ReadUntil(xr, "rowBreaks", "colBreaks")) {
+ return;
+ }
+ while (xr.Read()) {
+ if (xr.LocalName == "brk") {
+ if (xr.NodeType == XmlNodeType.Element) {
+ if (int.TryParse(xr.GetAttribute("id"), out var id)) {
+ Row(id).PageBreak = true;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ private void LoadColPageBreakes(XmlTextReader xr) {
+ if (!ReadUntil(xr, "colBreaks")) {
+ return;
+ }
+ while (xr.Read()) {
+ if (xr.LocalName == "brk") {
+ if (xr.NodeType == XmlNodeType.Element) {
+ if (int.TryParse(xr.GetAttribute("id"), out var id)) {
+ Column(id).PageBreak = true;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ private void ClearNodes() {
+ if (WorksheetXml.SelectSingleNode("//d:cols", NameSpaceManager) != null) {
+ WorksheetXml.SelectSingleNode("//d:cols", NameSpaceManager).RemoveAll();
+ }
+ if (WorksheetXml.SelectSingleNode("//d:mergeCells", NameSpaceManager) != null) {
+ WorksheetXml.SelectSingleNode("//d:mergeCells", NameSpaceManager).RemoveAll();
+ }
+ if (WorksheetXml.SelectSingleNode("//d:hyperlinks", NameSpaceManager) != null) {
+ WorksheetXml.SelectSingleNode("//d:hyperlinks", NameSpaceManager).RemoveAll();
+ }
+ if (WorksheetXml.SelectSingleNode("//d:rowBreaks", NameSpaceManager) != null) {
+ WorksheetXml.SelectSingleNode("//d:rowBreaks", NameSpaceManager).RemoveAll();
+ }
+ if (WorksheetXml.SelectSingleNode("//d:colBreaks", NameSpaceManager) != null) {
+ WorksheetXml.SelectSingleNode("//d:colBreaks", NameSpaceManager).RemoveAll();
+ }
+ }
+
+ private const int _blocksize = 8192;
+
+ private string GetWorkSheetXml(Stream stream, long start, long end, out Encoding encoding) {
+ StreamReader sr = new StreamReader(stream);
+ int length = 0;
+ char[] block;
+ int pos;
+ StringBuilder sb = new StringBuilder();
+ Match startmMatch,
+ endMatch;
+ do {
+ int size = stream.Length < _blocksize ? (int)stream.Length : _blocksize;
+ block = new char[size];
+ pos = sr.ReadBlock(block, 0, size);
+ sb.Append(block, 0, pos);
+ length += size;
+ } while (length < start + 20 && length < end);
+ startmMatch = Regex.Match(sb.ToString(), string.Format("(<[^>]*{0}[^>]*>)", "sheetData"));
+ if (!startmMatch.Success) //Not found
+ {
+ encoding = sr.CurrentEncoding;
+ return sb.ToString();
+ }
+ string s = sb.ToString();
+ string xml = s.Substring(0, startmMatch.Index);
+ if (startmMatch.Value.EndsWith("/>")) {
+ xml += s.Substring(startmMatch.Index, s.Length - startmMatch.Index);
+ } else {
+ if (sr.Peek() != -1) {
+ /**** Fixes issue 14788. Fix by Philip Garrett ****/
+ long endSeekStart = end;
+
+ while (endSeekStart >= 0) {
+ endSeekStart = Math.Max(endSeekStart - _blocksize, 0);
+ int size = (int)(end - endSeekStart);
+ stream.Seek(endSeekStart, SeekOrigin.Begin);
+ block = new char[size];
+ sr = new(stream);
+ pos = sr.ReadBlock(block, 0, size);
+ sb = new();
+ sb.Append(block, 0, pos);
+ s = sb.ToString();
+ endMatch = Regex.Match(s, string.Format("(</[^>]*{0}[^>]*>)", "sheetData"));
+ if (endMatch.Success) {
+ break;
+ }
+ }
+ }
+ endMatch = Regex.Match(s, string.Format("(</[^>]*{0}[^>]*>)", "sheetData"));
+ xml +=
+ "<sheetData/>"
+ + s.Substring(
+ endMatch.Index + endMatch.Length,
+ s.Length - (endMatch.Index + endMatch.Length));
+ }
+ if (sr.Peek() > -1) {
+ xml += sr.ReadToEnd();
+ }
+
+ encoding = sr.CurrentEncoding;
+ return xml;
+ }
+
+ private void GetBlockPos(string xml, string tag, ref int start, ref int end) {
+ Match startmMatch,
+ endMatch;
+ startmMatch = Regex.Match(xml.Substring(start), string.Format("(<[^>]*{0}[^>]*>)", tag)); //"<[a-zA-Z:]*" + tag + "[?]*>");
+
+ if (!startmMatch.Success) //Not found
+ {
+ start = -1;
+ end = -1;
+ return;
+ }
+ var startPos = startmMatch.Index + start;
+ if (startmMatch.Value.Substring(startmMatch.Value.Length - 2, 1) == "/") {
+ end = startPos + startmMatch.Length;
+ } else {
+ endMatch = Regex.Match(xml.Substring(start), string.Format("(</[^>]*{0}[^>]*>)", tag));
+ if (endMatch.Success) {
+ end = endMatch.Index + endMatch.Length + start;
+ }
+ }
+ start = startPos;
+ }
+
+ private bool ReadUntil(XmlTextReader xr, params string[] tagName) {
+ if (xr.EOF) {
+ return false;
+ }
+ while (!Array.Exists(tagName, tag => xr.LocalName.EndsWith(tag))) {
+ xr.Read();
+ if (xr.EOF) {
+ return false;
+ }
+ }
+ return (xr.LocalName.EndsWith(tagName[0]));
+ }
+
+ private void LoadColumns(
+ XmlTextReader xr) //(string xml)
+ {
+ var colList = new List<IRangeId>();
+ if (ReadUntil(xr, "cols", "sheetData")) {
+ //if (xml != "")
+ //{
+ //var xr=new XmlTextReader(new StringReader(xml));
+ while (xr.Read()) {
+ if (xr.NodeType == XmlNodeType.Whitespace) {
+ continue;
+ }
+ if (xr.LocalName != "col") {
+ break;
+ }
+ if (xr.NodeType == XmlNodeType.Element) {
+ int min = int.Parse(xr.GetAttribute("min"));
+
+ ExcelColumn col = new ExcelColumn(this, min);
+
+ col.ColumnMax = int.Parse(xr.GetAttribute("max"));
+ col.Width =
+ xr.GetAttribute("width") == null
+ ? 0
+ : double.Parse(xr.GetAttribute("width"), CultureInfo.InvariantCulture);
+ col.BestFit =
+ xr.GetAttribute("bestFit") != null && xr.GetAttribute("bestFit") == "1"
+ ? true
+ : false;
+ col.Collapsed =
+ xr.GetAttribute("collapsed") != null && xr.GetAttribute("collapsed") == "1"
+ ? true
+ : false;
+ col.Phonetic =
+ xr.GetAttribute("phonetic") != null && xr.GetAttribute("phonetic") == "1"
+ ? true
+ : false;
+ col.OutlineLevel = (short)(xr.GetAttribute("outlineLevel") == null
+ ? 0
+ : int.Parse(xr.GetAttribute("outlineLevel"), CultureInfo.InvariantCulture));
+ col.Hidden =
+ xr.GetAttribute("hidden") != null && xr.GetAttribute("hidden") == "1" ? true : false;
+ _values.SetValue(0, min, col);
+
+ if (!(xr.GetAttribute("style") == null
+ || !int.TryParse(xr.GetAttribute("style"), out var style))) {
+ _styles.SetValue(0, min, style);
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Load Hyperlinks
+ /// </summary>
+ /// <param name="xr">The reader</param>
+ private void LoadHyperLinks(XmlTextReader xr) {
+ if (!ReadUntil(xr, "hyperlinks", "rowBreaks", "colBreaks")) {
+ return;
+ }
+ while (xr.Read()) {
+ if (xr.LocalName == "hyperlink") {
+ ExcelCellBase.GetRowColFromAddress(
+ xr.GetAttribute("ref"),
+ out var fromRow,
+ out var fromCol,
+ out int toRow,
+ out var toCol);
+ ExcelHyperLink hl = null;
+ if (xr.GetAttribute("id", ExcelPackage._schemaRelationships) != null) {
+ var rId = xr.GetAttribute("id", ExcelPackage._schemaRelationships);
+ var uri = Part.GetRelationship(rId).TargetUri;
+
+ // Get Location, if any. EPPlus Bug 15517
+ var location = xr.GetAttribute("location");
+ location = (string.IsNullOrEmpty(location)) ? "" : "#" + location;
+
+ if (uri.IsAbsoluteUri) {
+ try {
+ hl = new(uri.AbsoluteUri + location);
+ } catch {
+ hl = new(uri.OriginalString + location, UriKind.Absolute);
+ }
+ } else {
+ hl = new(uri.OriginalString + location, UriKind.Relative);
+ }
+
+ hl.RId = rId;
+ Part.DeleteRelationship(rId); //Delete the relationship, it is recreated when we save the package.
+ } else if (xr.GetAttribute("location") != null) {
+ hl = new(xr.GetAttribute("location"), xr.GetAttribute("display"));
+ hl.RowSpann = toRow - fromRow;
+ hl.ColSpann = toCol - fromCol;
+ }
+
+ string tt = xr.GetAttribute("tooltip");
+ if (!string.IsNullOrEmpty(tt)) {
+ hl.ToolTip = tt;
+ }
+ _hyperLinks.SetValue(fromRow, fromCol, hl);
+ } else {
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Load cells
+ /// </summary>
+ /// <param name="xr">The reader</param>
+ private void LoadCells(XmlTextReader xr) {
+ //var cellList=new List<IRangeID>();
+ //var rowList = new List<IRangeID>();
+ //var formulaList = new List<IRangeID>();
+ ReadUntil(xr, "sheetData", "mergeCells", "hyperlinks", "rowBreaks", "colBreaks");
+ ExcelAddressBase address = null;
+ string type = "";
+ int style = 0;
+ int row = 0;
+ int col = 0;
+ xr.Read();
+
+ while (!xr.EOF) {
+ while (xr.NodeType == XmlNodeType.EndElement) {
+ xr.Read();
+ }
+ if (xr.LocalName == "row") {
+ var r = xr.GetAttribute("r");
+ if (r == null) {
+ row++;
+ } else {
+ row = Convert.ToInt32(r);
+ }
+
+ if (DoAddRow(xr)) {
+ _values.SetValue(row, 0, AddRow(xr, row));
+ if (xr.GetAttribute("s") != null) {
+ _styles.SetValue(row, 0, int.Parse(xr.GetAttribute("s"), CultureInfo.InvariantCulture));
+ }
+ }
+ xr.Read();
+ } else if (xr.LocalName == "c") {
+ //if (cell != null) cellList.Add(cell);
+ //cell = new ExcelCell(this, xr.GetAttribute("r"));
+ var r = xr.GetAttribute("r");
+ if (r == null) {
+ //Handle cells with no reference
+ col++;
+ address = new(row, col, row, col);
+ } else {
+ address = new(r);
+ col = address._fromCol;
+ }
+
+ //Datetype
+ if (xr.GetAttribute("t") != null) {
+ type = xr.GetAttribute("t");
+ _types.SetValue(address._fromRow, address._fromCol, type);
+ } else {
+ type = "";
+ }
+ //Style
+ if (xr.GetAttribute("s") != null) {
+ style = int.Parse(xr.GetAttribute("s"));
+ _styles.SetValue(address._fromRow, address._fromCol, style);
+ _values.SetValue(address._fromRow, address._fromCol, null); //TODO:Better Performance ??
+ } else {
+ style = 0;
+ }
+ xr.Read();
+ } else if (xr.LocalName == "v") {
+ SetValueFromXml(xr, type, style, address._fromRow, address._fromCol);
+
+ xr.Read();
+ } else if (xr.LocalName == "f") {
+ string t = xr.GetAttribute("t");
+ if (t == null) {
+ _formulas.SetValue(address._fromRow, address._fromCol, xr.ReadElementContentAsString());
+ _values.SetValue(address._fromRow, address._fromCol, null);
+ //formulaList.Add(cell);
+ } else if (t == "shared") {
+ string si = xr.GetAttribute("si");
+ if (si != null) {
+ var sfIndex = int.Parse(si);
+ _formulas.SetValue(address._fromRow, address._fromCol, sfIndex);
+ _values.SetValue(address._fromRow, address._fromCol, null);
+ string fAddress = xr.GetAttribute("ref");
+ string formula = ConvertUtil.ExcelDecodeString(xr.ReadElementContentAsString());
+ if (formula != "") {
+ _sharedFormulas.Add(
+ sfIndex,
+ new(SourceCodeTokenizer.Default) {
+ Index = sfIndex,
+ Formula = formula,
+ Address = fAddress,
+ StartRow = address._fromRow,
+ StartCol = address._fromCol,
+ });
+ }
+ } else {
+ xr.Read(); //Something is wrong in the sheet, read next
+ }
+ } else if (t
+ == "array") //TODO: Array functions are not support yet. Read the formula for the start cell only.
+ {
+ string aAddress = xr.GetAttribute("ref");
+ ExcelRange addressRange = new ExcelRange(this, aAddress);
+ string formula = xr.ReadElementContentAsString();
+ bool isIndexMatchFormula =
+ Regex.IsMatch(formula, @"INDEX\(", RegexOptions.IgnoreCase)
+ && Regex.IsMatch(formula, @"MATCH\(", RegexOptions.IgnoreCase)
+ && !aAddress.Contains(":");
+ if (isIndexMatchFormula) {
+ addressRange.IsArrayFormula = false;
+ for (int colIndex = addressRange.Start.Column;
+ colIndex <= addressRange.End.Column;
+ colIndex++) {
+ for (int rowIndex = addressRange.Start.Row;
+ rowIndex <= addressRange.End.Row;
+ rowIndex++) {
+ var afIndex = GetMaxShareFunctionIndex(true);
+ _formulas.SetValue(rowIndex, colIndex, afIndex);
+ _values.SetValue(rowIndex, colIndex, null);
+ _sharedFormulas.Add(
+ afIndex,
+ new(SourceCodeTokenizer.Default) {
+ Index = afIndex,
+ Formula = formula,
+ Address = aAddress,
+ StartRow = address._fromRow,
+ StartCol = address._fromCol,
+ IsArray = false,
+ });
+ }
+ }
+ } else {
+ addressRange.IsArrayFormula = true;
+ var afIndex = GetMaxShareFunctionIndex(true);
+ for (int colIndex = addressRange.Start.Column;
+ colIndex <= addressRange.End.Column;
+ colIndex++) {
+ for (int rowIndex = addressRange.Start.Row;
+ rowIndex <= addressRange.End.Row;
+ rowIndex++) {
+ _formulas.SetValue(rowIndex, colIndex, afIndex);
+ _values.SetValue(rowIndex, colIndex, null);
+ }
+ }
+ _sharedFormulas.Add(
+ afIndex,
+ new(SourceCodeTokenizer.Default) {
+ Index = afIndex,
+ Formula = formula,
+ Address = aAddress,
+ StartRow = address._fromRow,
+ StartCol = address._fromCol,
+ IsArray = true,
+ });
+ }
+ } else // ??? some other type
+ {
+ xr.Read(); //Something is wrong in the sheet, read next
+ }
+ } else if (xr.LocalName
+ == "is") //Inline string
+ {
+ xr.Read();
+ if (xr.LocalName == "t") {
+ _values.SetValue(
+ address._fromRow,
+ address._fromCol,
+ ConvertUtil.ExcelDecodeString(xr.ReadElementContentAsString()));
+ //cell._value = xr.ReadInnerXml();
+ } else {
+ _values.SetValue(address._fromRow, address._fromCol, xr.ReadOuterXml());
+ _types.SetValue(address._fromRow, address._fromCol, "rt");
+ _flags.SetFlagValue(address._fromRow, address._fromCol, true, CellFlags.RichText);
+ //cell.IsRichText = true;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ private bool DoAddRow(XmlTextReader xr) {
+ var c = xr.GetAttribute("r") == null ? 0 : 1;
+ if (xr.GetAttribute("spans") != null) {
+ c++;
+ }
+ return xr.AttributeCount > c;
+ }
+
+ /// <summary>
+ /// Load merged cells
+ /// </summary>
+ /// <param name="xr"></param>
+ private void LoadMergeCells(XmlTextReader xr) {
+ if (ReadUntil(xr, "mergeCells", "hyperlinks", "rowBreaks", "colBreaks") && !xr.EOF) {
+ while (xr.Read()) {
+ if (xr.LocalName != "mergeCell") {
+ break;
+ }
+ if (xr.NodeType == XmlNodeType.Element) {
+ string address = xr.GetAttribute("ref");
+ _mergedCells.Add(new ExcelAddress(address), false);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Update merged cells
+ /// </summary>
+ /// <param name="sw">The writer</param>
+ private void UpdateMergedCells(StreamWriter sw) {
+ sw.Write("<mergeCells>");
+ foreach (string address in _mergedCells) {
+ sw.Write("<mergeCell ref=\"{0}\" />", address);
+ }
+ sw.Write("</mergeCells>");
+ }
+
+ /// <summary>
+ /// Reads a row from the XML reader
+ /// </summary>
+ /// <param name="xr">The reader</param>
+ /// <param name="row">The row number</param>
+ /// <returns></returns>
+ private RowInternal AddRow(XmlTextReader xr, int row) {
+ return new() {
+ Collapsed =
+ (xr.GetAttribute("collapsed") != null && xr.GetAttribute("collapsed") == "1"
+ ? true
+ : false),
+ OutlineLevel =
+ (xr.GetAttribute("outlineLevel") == null
+ ? (short)0
+ : short.Parse(xr.GetAttribute("outlineLevel"), CultureInfo.InvariantCulture)),
+ Height =
+ (xr.GetAttribute("ht") == null
+ ? -1
+ : double.Parse(xr.GetAttribute("ht"), CultureInfo.InvariantCulture)),
+ Hidden =
+ (xr.GetAttribute("hidden") != null && xr.GetAttribute("hidden") == "1" ? true : false),
+ Phonetic = xr.GetAttribute("ph") != null && xr.GetAttribute("ph") == "1" ? true : false,
+ CustomHeight =
+ xr.GetAttribute("customHeight") == null ? false : xr.GetAttribute("customHeight") == "1",
+ };
+ }
+
+ private static readonly DateTime _excelEpoch = new(1899, 12, 30);
+
+ public static DateTime IncorrectDurationFromOaDate(double value) {
+ // This behavior is wrong. Real OADate values have a discontinuity on 30 December 1899.
+ // For real OADate values, the negative sign applies only to the integer portion of
+ // the float, *not* to the decimal portion. For example, -0.5 and 0.5 both refer to the
+ // same date, and -1.5 is actually 1899-12-29 12:00 (1 day before 1899-12-30 00:00
+ // plus 0.5 days), *not* 1899-12-28 12:00 (1.5 days before 1899-12-30 00:00).
+ //
+ // Unfortunately, AppSheet's duration-handling code gets this very wrong, and treats the
+ // duration as the offset from 1899-12-30 00:00. This is correct for positive durations,
+ // but it's wrong for negative durations. This code tries to fix the bug that exists in
+ // AppSheet's duration-handling code here, and it succeeds in some cases and fails in
+ // others.
+ //
+ // This code also breaks date/time handling for dates before 1899-12-30 00:00 in some
+ // cases. Specifically, dates end up being offset by one day.
+ //
+ // Regardless, changing this behavior is risky, so this code simply replicates the
+ // existing behavior for
+ if (value >= 0) {
+ return DateTime.FromOADate(value);
+ }
+ // This looks like a very complicated way to call TimeSpan.FromDays(value), but
+ // TimeSpan.FromDays actually only guarantees millisecond precision, and critically
+ // rounding is different on .NET Core, resulting in values like (e.g.) 3:15:00 being
+ // incorrectly rounded.
+ var offset = DateTime.FromOADate(-value) - _excelEpoch;
+ return _excelEpoch - offset;
+ }
+
+ private void SetValueFromXml(XmlTextReader xr, string type, int styleId, int row, int col) {
+ //XmlNode vnode = colNode.SelectSingleNode("d:v", NameSpaceManager);
+ //if (vnode == null) return null;
+ if (type == "s") {
+ int ix = xr.ReadElementContentAsInt();
+
+ // Temporary debugging code to locate intermittent 'Index was out of range' exception.
+ if (ix < 0) {
+ throw new(
+ string.Format(
+ "ReadElementContentAsInt returned value '{0}' which is less than zero.",
+ ix));
+ }
+ if (ix >= _workbook._sharedStringsList.Count) {
+ throw new(
+ string.Format(
+ "ReadElementContentAsInt returned index value '{0}' which is greater than _sharedStringsList count of {1}.",
+ ix,
+ _workbook._sharedStringsList.Count));
+ }
+
+ _values.SetValue(row, col, _workbook._sharedStringsList[ix].Text);
+ if (_workbook._sharedStringsList[ix].isRichText) {
+ _flags.SetFlagValue(row, col, true, CellFlags.RichText);
+ }
+ } else if (type == "str") {
+ _values.SetValue(row, col, ConvertUtil.ExcelDecodeString(xr.ReadElementContentAsString()));
+ } else if (type == "b") {
+ _values.SetValue(row, col, (xr.ReadElementContentAsString() != "0"));
+ } else if (type == "e") {
+ _values.SetValue(row, col, GetErrorType(xr.ReadElementContentAsString()));
+ } else {
+ string v = xr.ReadElementContentAsString();
+ var nf = Workbook.Styles.CellXfs[styleId].NumberFormatId;
+ if ((nf >= 20 && nf <= 21)
+ || (nf >= 45
+ && nf
+ <= 47)) // Duration
+ {
+ if (double.TryParse(v, NumberStyles.Any, CultureInfo.InvariantCulture, out var res)) {
+ if (Workbook.Date1904) {
+ res += ExcelWorkbook._date1904Offset;
+ }
+ if (res >= -657435.0 && res < 2958465.9999999) {
+ // Get the Duration value expressed as a DateTime.
+ _values.SetValue(row, col, IncorrectDurationFromOaDate(res));
+ } else {
+ // Cope with Google Sheets export of cells having a formula.
+ // Rather than exporting the native value, they export the formatted value.
+ _values.SetValue(row, col, v);
+ }
+ } else {
+ // Cope with Google Sheets export of cells having a formula.
+ // Rather than exporting the native value, they export the formatted value.
+ _values.SetValue(row, col, v);
+ }
+ } else if ((nf >= 14 && nf <= 19)
+ || (nf
+ == 22)) // DateTime
+ {
+ if (double.TryParse(v, NumberStyles.Any, CultureInfo.InvariantCulture, out var res)) {
+ if (Workbook.Date1904) {
+ res += ExcelWorkbook._date1904Offset;
+ }
+ if (res >= -657435.0 && res < 2958465.9999999) {
+ _values.SetValue(row, col, DateTime.FromOADate(res));
+ } else {
+ // Cope with Google Sheets export of cells having a formula.
+ // Rather than exporting the native value, they export the formatted value.
+ _values.SetValue(row, col, v);
+ }
+ } else {
+ // Cope with Google Sheets export of cells having a formula.
+ // Rather than exporting the native value, they export the formatted value.
+ _values.SetValue(row, col, v);
+ }
+ } else {
+ if (double.TryParse(v, NumberStyles.Any, CultureInfo.InvariantCulture, out var d)) {
+ _values.SetValue(row, col, d);
+ } else {
+ // Cope with Google Sheets export of cells having a formula.
+ // Rather than exporting the native value, they export the formatted value.
+ _values.SetValue(row, col, v);
+
+ //_values.SetValue(row, col, double.NaN);
+ }
+ }
+ }
+ }
+
+ private object GetErrorType(string v) {
+ return ExcelErrorValue.Parse(v.ToUpper(CultureInfo.InvariantCulture));
+ //switch(v.ToUpper())
+ //{
+ // case "#DIV/0!":
+ // return new ExcelErrorValue.cre(eErrorType.Div0);
+ // case "#REF!":
+ // return new ExcelErrorValue(eErrorType.Ref);
+ // case "#N/A":
+ // return new ExcelErrorValue(eErrorType.NA);
+ // case "#NAME?":
+ // return new ExcelErrorValue(eErrorType.Name);
+ // case "#NULL!":
+ // return new ExcelErrorValue(eErrorType.Null);
+ // case "#NUM!":
+ // return new ExcelErrorValue(eErrorType.Num);
+ // default:
+ // return new ExcelErrorValue(eErrorType.Value);
+ //}
+ }
+
+ ///// <summary>
+ ///// Provides access to an individual cell within the worksheet.
+ ///// </summary>
+ ///// <param name="row">The row number in the worksheet</param>
+ ///// <param name="col">The column number in the worksheet</param>
+ ///// <returns></returns>
+ //internal ExcelCell Cell(int row, int col)
+ //{
+ // return new ExcelCell(_values, row, col);
+ //}
+ /// <summary>
+ /// Provides access to a range of cells
+ /// </summary>
+ public ExcelRange Cells {
+ get {
+ CheckSheetType();
+ return new(this, 1, 1, ExcelPackage.MaxRows, ExcelPackage.MaxColumns);
+ }
+ }
+
+ /// <summary>
+ /// Provides access to the selected range of cells
+ /// </summary>
+ public ExcelRange SelectedRange {
+ get {
+ CheckSheetType();
+ return new(this, View.SelectedRange);
+ }
+ }
+
+ private readonly MergeCellsCollection _mergedCells = new();
+
+ /// <summary>
+ /// Addresses to merged ranges
+ /// </summary>
+ public MergeCellsCollection MergedCells {
+ get {
+ CheckSheetType();
+ return _mergedCells;
+ }
+ }
+
+ /// <summary>
+ /// Provides access to an individual row within the worksheet so you can set its properties.
+ /// </summary>
+ /// <param name="row">The row number in the worksheet</param>
+ /// <returns></returns>
+ public ExcelRow Row(int row) {
+ //ExcelRow r;
+ //ulong id = ExcelRow.GetRowID(_sheetID, row);
+ //TODO: Fixa.
+ //var v = _values.GetValue(row, 0);
+ //if (v!=null)
+ //{
+ // var ri=(RowInternal)v;
+ // r = new ExcelRow(this, row)
+ //}
+ //else
+ //{
+ //r = new ExcelRow(this, row);
+ //_values.SetValue(row, 0, r);
+ //_rows.Add(r);
+ //}
+ CheckSheetType();
+ if (row < 1 || row > ExcelPackage.MaxRows) {
+ throw (new ArgumentException("Row number out of bounds"));
+ }
+ return new(this, row);
+ //return r;
+ }
+
+ /// <summary>
+ /// Provides access to an individual column within the worksheet so you can set its properties.
+ /// </summary>
+ /// <param name="col">The column number in the worksheet</param>
+ /// <returns></returns>
+ public ExcelColumn Column(int col) {
+ CheckSheetType();
+ if (col < 1 || col > ExcelPackage.MaxColumns) {
+ throw (new ArgumentException("Column number out of bounds"));
+ }
+ var column = _values.GetValue(0, col) as ExcelColumn;
+ if (column != null) {
+ if (column.ColumnMin != column.ColumnMax) {
+ int maxCol = column.ColumnMax;
+ column.ColumnMax = col;
+ ExcelColumn copy = CopyColumn(column, col + 1, maxCol);
+ }
+ } else {
+ int r = 0,
+ c = col;
+ if (_values.PrevCell(ref r, ref c)) {
+ column = _values.GetValue(0, c) as ExcelColumn;
+ int maxCol = column.ColumnMax;
+ if (maxCol >= col) {
+ column.ColumnMax = col - 1;
+ if (maxCol > col) {
+ ExcelColumn newC = CopyColumn(column, col + 1, maxCol);
+ }
+ return CopyColumn(column, col, col);
+ }
+ }
+ //foreach (ExcelColumn checkColumn in _columns)
+ //{
+ // if (col > checkColumn.ColumnMin && col <= checkColumn.ColumnMax)
+ // {
+ // int maxCol = checkColumn.ColumnMax;
+ // checkColumn.ColumnMax = col - 1;
+ // if (maxCol > col)
+ // {
+ // ExcelColumn newC = CopyColumn(checkColumn, col + 1, maxCol);
+ // }
+ // return CopyColumn(checkColumn, col,col);
+ // }
+ //}
+ column = new(this, col);
+ _values.SetValue(0, col, column);
+ //_columns.Add(column);
+ }
+ return column;
+ }
+
+ /// <summary>
+ /// Returns the name of the worksheet
+ /// </summary>
+ /// <returns>The name of the worksheet</returns>
+ public override string ToString() {
+ return Name;
+ }
+
+ internal ExcelColumn CopyColumn(ExcelColumn c, int col, int maxCol) {
+ ExcelColumn newC = new ExcelColumn(this, col);
+ newC.ColumnMax = maxCol < ExcelPackage.MaxColumns ? maxCol : ExcelPackage.MaxColumns;
+ if (c.StyleName != "") {
+ newC.StyleName = c.StyleName;
+ } else {
+ newC.StyleID = c.StyleID;
+ }
+
+ newC.OutlineLevel = c.OutlineLevel;
+ newC.Phonetic = c.Phonetic;
+ newC.BestFit = c.BestFit;
+ //_columns.Add(newC);
+ _values.SetValue(0, col, newC);
+ newC._width = c._width;
+ newC._hidden = c._hidden;
+ return newC;
+ }
+
+ /// <summary>
+ /// Make the current worksheet active.
+ /// </summary>
+ public void Select() {
+ View.TabSelected = true;
+ //Select(Address, true);
+ }
+
+ /// <summary>
+ /// Selects a range in the worksheet. The active cell is the topmost cell.
+ /// Make the current worksheet active.
+ /// </summary>
+ /// <param name="address">An address range</param>
+ public void Select(string address) {
+ Select(address, true);
+ }
+
+ /// <summary>
+ /// Selects a range in the worksheet. The actice cell is the topmost cell.
+ /// </summary>
+ /// <param name="address">A range of cells</param>
+ /// <param name="selectSheet">Make the sheet active</param>
+ public void Select(string address, bool selectSheet) {
+ CheckSheetType();
+ int toCol,
+ toRow;
+ //Get rows and columns and validate as well
+ ExcelCellBase.GetRowColFromAddress(
+ address,
+ out var fromRow,
+ out var fromCol,
+ out toRow,
+ out toCol);
+
+ if (selectSheet) {
+ View.TabSelected = true;
+ }
+ View.SelectedRange = address;
+ View.ActiveCell = ExcelCellBase.GetAddress(fromRow, fromCol);
+ }
+
+ /// <summary>
+ /// Selects a range in the worksheet. The active cell is the topmost cell of the first address.
+ /// Make the current worksheet active.
+ /// </summary>
+ /// <param name="address">An address range</param>
+ public void Select(ExcelAddress address) {
+ CheckSheetType();
+ Select(address, true);
+ }
+
+ /// <summary>
+ /// Selects a range in the worksheet. The active cell is the topmost cell of the first address.
+ /// </summary>
+ /// <param name="address">A range of cells</param>
+ /// <param name="selectSheet">Make the sheet active</param>
+ public void Select(ExcelAddress address, bool selectSheet) {
+ CheckSheetType();
+ if (selectSheet) {
+ View.TabSelected = true;
+ }
+ string selAddress =
+ ExcelCellBase.GetAddress(address.Start.Row, address.Start.Column)
+ + ":"
+ + ExcelCellBase.GetAddress(address.End.Row, address.End.Column);
+ if (address.Addresses != null) {
+ foreach (var a in address.Addresses) {
+ selAddress +=
+ " "
+ + ExcelCellBase.GetAddress(a.Start.Row, a.Start.Column)
+ + ":"
+ + ExcelCellBase.GetAddress(a.End.Row, a.End.Column);
+ }
+ }
+ View.SelectedRange = selAddress;
+ View.ActiveCell = ExcelCellBase.GetAddress(address.Start.Row, address.Start.Column);
+ }
+
+ /// <summary>
+ /// Inserts a new row into the spreadsheet. Existing rows below the position are
+ /// shifted down. All formula are updated to take account of the new row.
+ /// </summary>
+ /// <param name="rowFrom">The position of the new row</param>
+ /// <param name="rows">Number of rows to insert</param>
+ public void InsertRow(int rowFrom, int rows) {
+ InsertRow(rowFrom, rows, 0);
+ }
+
+ /// <summary>
+ /// Inserts a new row into the spreadsheet. Existing rows below the position are
+ /// shifted down. All formula are updated to take account of the new row.
+ /// </summary>
+ /// <param name="rowFrom">The position of the new row</param>
+ /// <param name="rows">Number of rows to insert.</param>
+ /// <param name="copyStylesFromRow">Copy Styles from this row. Applied to all inserted rows</param>
+ public void InsertRow(int rowFrom, int rows, int copyStylesFromRow) {
+ CheckSheetType();
+ var d = Dimension;
+
+ if (rowFrom < 1) {
+ throw (new ArgumentOutOfRangeException("rowFrom can't be lesser that 1"));
+ }
+
+ //Check that cells aren't shifted outside the boundries
+ if (d != null && d.End.Row > rowFrom && d.End.Row + rows > ExcelPackage.MaxRows) {
+ throw (new ArgumentOutOfRangeException(
+ "Can't insert. Rows will be shifted outside the boundries of the worksheet."));
+ }
+
+ _values.Insert(rowFrom, 0, rows, 0);
+ _formulas.Insert(rowFrom, 0, rows, 0);
+ _styles.Insert(rowFrom, 0, rows, 0);
+ _types.Insert(rowFrom, 0, rows, 0);
+ _commentsStore.Insert(rowFrom, 0, rows, 0);
+ _hyperLinks.Insert(rowFrom, 0, rows, 0);
+ _flags.Insert(rowFrom, 0, rows, 0);
+
+ foreach (var f in _sharedFormulas.Values) {
+ if (f.StartRow >= rowFrom) {
+ f.StartRow += rows;
+ }
+ var a = new ExcelAddressBase(f.Address);
+ if (a._fromRow >= rowFrom) {
+ a._fromRow += rows;
+ a._toRow += rows;
+ } else if (a._toRow >= rowFrom) {
+ a._toRow += rows;
+ }
+ f.Address = ExcelCellBase.GetAddress(a._fromRow, a._fromCol, a._toRow, a._toCol);
+ f.Formula = ExcelCellBase.UpdateFormulaReferences(f.Formula, rows, 0, rowFrom, 0);
+ }
+ var cse = new CellsStoreEnumerator<object>(_formulas);
+ while (cse.Next()) {
+ if (cse.Value is string) {
+ cse.Value = ExcelCellBase.UpdateFormulaReferences(
+ cse.Value.ToString(),
+ rows,
+ 0,
+ rowFrom,
+ 0);
+ }
+ }
+
+ FixMergedCellsRow(rowFrom, rows, false);
+ if (copyStylesFromRow > 0) {
+ var cseS = new CellsStoreEnumerator<int>(
+ _styles,
+ copyStylesFromRow,
+ 0,
+ copyStylesFromRow,
+ ExcelPackage.MaxColumns); //Fixes issue 15068 , 15090
+ while (cseS.Next()) {
+ for (var r = 0; r < rows; r++) {
+ _styles.SetValue(rowFrom + r, cseS.Column, cseS.Value);
+ }
+ }
+ }
+ foreach (var tbl in Tables) {
+ tbl.Address = tbl.Address.AddRow(rowFrom, rows);
+ }
+ }
+
+ /// <summary>
+ /// Inserts a new column into the spreadsheet. Existing columns below the position are
+ /// shifted down. All formula are updated to take account of the new column.
+ /// </summary>
+ /// <param name="columnFrom">The position of the new column</param>
+ /// <param name="columns">Number of columns to insert</param>
+ public void InsertColumn(int columnFrom, int columns) {
+ InsertColumn(columnFrom, columns, 0);
+ }
+
+ ///<summary>
+ /// Inserts a new column into the spreadsheet. Existing column to the left are
+ /// shifted. All formula are updated to take account of the new column.
+ /// </summary>
+ /// <param name="columnFrom">The position of the new column</param>
+ /// <param name="columns">Number of columns to insert.</param>
+ /// <param name="copyStylesFromColumn">Copy Styles from this column. Applied to all inserted columns</param>
+ public void InsertColumn(int columnFrom, int columns, int copyStylesFromColumn) {
+ CheckSheetType();
+ var d = Dimension;
+
+ if (columnFrom < 1) {
+ throw (new ArgumentOutOfRangeException("columnFrom can't be lesser that 1"));
+ }
+ //Check that cells aren't shifted outside the boundries
+ if (d != null
+ && d.End.Column > columnFrom
+ && d.End.Column + columns > ExcelPackage.MaxColumns) {
+ throw (new ArgumentOutOfRangeException(
+ "Can't insert. Columns will be shifted outside the boundries of the worksheet."));
+ }
+
+ _values.Insert(0, columnFrom, 0, columns);
+ _formulas.Insert(0, columnFrom, 0, columns);
+ _styles.Insert(0, columnFrom, 0, columns);
+ _types.Insert(0, columnFrom, 0, columns);
+ _commentsStore.Insert(0, columnFrom, 0, columns);
+ _hyperLinks.Insert(0, columnFrom, 0, columns);
+ _flags.Insert(0, columnFrom, 0, columns);
+
+ foreach (var f in _sharedFormulas.Values) {
+ if (f.StartCol >= columnFrom) {
+ f.StartCol += columns;
+ }
+ var a = new ExcelAddressBase(f.Address);
+ if (a._fromCol >= columnFrom) {
+ a._fromCol += columns;
+ a._toCol += columns;
+ } else if (a._toCol >= columnFrom) {
+ a._toCol += columns;
+ }
+ f.Address = ExcelCellBase.GetAddress(a._fromRow, a._fromCol, a._toRow, a._toCol);
+ f.Formula = ExcelCellBase.UpdateFormulaReferences(f.Formula, 0, columns, 0, columnFrom);
+ }
+
+ var cse = new CellsStoreEnumerator<object>(_formulas);
+ while (cse.Next()) {
+ if (cse.Value is string) {
+ cse.Value = ExcelCellBase.UpdateFormulaReferences(
+ cse.Value.ToString(),
+ 0,
+ columns,
+ 0,
+ columnFrom);
+ }
+ }
+
+ FixMergedCellsColumn(columnFrom, columns, false);
+
+ var csec = new CellsStoreEnumerator<object>(_values, 0, 1, 0, ExcelPackage.MaxColumns);
+ var lst = new List<ExcelColumn>();
+ foreach (var col in csec) {
+ if (col is ExcelColumn column) {
+ lst.Add(column);
+ }
+ }
+
+ for (int i = lst.Count - 1; i >= 0; i--) {
+ var c = lst[i];
+ if (c._columnMin >= columnFrom) {
+ if (c._columnMin + columns <= ExcelPackage.MaxColumns) {
+ c._columnMin += columns;
+ } else {
+ c._columnMin = ExcelPackage.MaxColumns;
+ }
+
+ if (c._columnMax + columns <= ExcelPackage.MaxColumns) {
+ c._columnMax += columns;
+ } else {
+ c._columnMax = ExcelPackage.MaxColumns;
+ }
+ } else if (c._columnMax >= columnFrom) {
+ var cc = c._columnMax - columnFrom;
+ c._columnMax = columnFrom - 1;
+ CopyColumn(c, columnFrom + columns, columnFrom + columns + cc);
+ }
+ }
+
+ if (copyStylesFromColumn > 0) {
+ for (var c = 0; c < columns; c++) {
+ var col = Column(columnFrom + c);
+ col.StyleID = Column(copyStylesFromColumn).StyleID;
+ }
+ }
+ //Adjust tables
+ foreach (var tbl in Tables) {
+ if (columnFrom > tbl.Address.Start.Column && columnFrom <= tbl.Address.End.Column) {
+ InsertTableColumns(columnFrom, columns, tbl);
+ }
+
+ tbl.Address = tbl.Address.AddColumn(columnFrom, columns);
+ }
+ }
+
+ private static void InsertTableColumns(int columnFrom, int columns, ExcelTable tbl) {
+ var node = tbl.Columns[0].TopNode.ParentNode;
+ var ix = columnFrom - tbl.Address.Start.Column - 1;
+ var insPos = node.ChildNodes[ix];
+ ix += 2;
+ for (int i = 0; i < columns; i++) {
+ var name = tbl.Columns.GetUniqueName(
+ string.Format("Column{0}", (ix++).ToString(CultureInfo.InvariantCulture)));
+ XmlElement tableColumn = (XmlElement)
+ tbl.TableXml.CreateNode(XmlNodeType.Element, "tableColumn", ExcelPackage._schemaMain);
+ tableColumn.SetAttribute(
+ "id",
+ (tbl.Columns.Count + i + 1).ToString(CultureInfo.InvariantCulture));
+ tableColumn.SetAttribute("name", name);
+ insPos = node.InsertAfter(tableColumn, insPos);
+ } //Create tbl Column
+ tbl._cols = new(tbl);
+ }
+
+ /// <summary>
+ /// Adds a value to the row of merged cells to fix for inserts or deletes
+ /// </summary>
+ /// <param name="row"></param>
+ /// <param name="rows"></param>
+ /// <param name="delete"></param>
+ private void FixMergedCellsRow(int row, int rows, bool delete) {
+ if (delete) {
+ _mergedCells._cells.Delete(row, 0, rows, 0);
+ } else {
+ _mergedCells._cells.Insert(row, 0, rows, 0);
+ }
+
+ List<int> removeIndex = [];
+ for (int i = 0; i < _mergedCells.Count; i++) {
+ if (!string.IsNullOrEmpty(_mergedCells[i])) {
+ ExcelAddressBase addr = new(_mergedCells[i]),
+ newAddr;
+ if (delete) {
+ newAddr = addr.DeleteRow(row, rows);
+ if (newAddr == null) {
+ removeIndex.Add(i);
+ continue;
+ }
+ } else {
+ newAddr = addr.AddRow(row, rows);
+ if (newAddr.Address != addr.Address) {
+ // _mergedCells._cells.Insert(row, 0, rows, 0);
+ _mergedCells.SetIndex(newAddr, i);
+ }
+ }
+
+ if (newAddr.Address != addr.Address) {
+ _mergedCells.List[i] = newAddr._address;
+ }
+ }
+ }
+ for (int i = removeIndex.Count - 1; i >= 0; i--) {
+ _mergedCells.List.RemoveAt(removeIndex[i]);
+ }
+ }
+
+ /// <summary>
+ /// Adds a value to the row of merged cells to fix for inserts or deletes
+ /// </summary>
+ /// <param name="column"></param>
+ /// <param name="columns"></param>
+ /// <param name="delete"></param>
+ private void FixMergedCellsColumn(int column, int columns, bool delete) {
+ if (delete) {
+ _mergedCells._cells.Delete(0, column, 0, columns);
+ } else {
+ _mergedCells._cells.Insert(0, column, 0, columns);
+ }
+ List<int> removeIndex = [];
+ for (int i = 0; i < _mergedCells.Count; i++) {
+ if (!string.IsNullOrEmpty(_mergedCells[i])) {
+ ExcelAddressBase addr = new(_mergedCells[i]),
+ newAddr;
+ if (delete) {
+ newAddr = addr.DeleteColumn(column, columns);
+ if (newAddr == null) {
+ removeIndex.Add(i);
+ continue;
+ }
+ } else {
+ newAddr = addr.AddColumn(column, columns);
+ if (newAddr.Address != addr.Address) {
+ _mergedCells.SetIndex(newAddr, i);
+ }
+ }
+
+ if (newAddr.Address != addr.Address) {
+ _mergedCells.List[i] = newAddr._address;
+ }
+ }
+ }
+ for (int i = removeIndex.Count - 1; i >= 0; i--) {
+ _mergedCells.List.RemoveAt(removeIndex[i]);
+ }
+ }
+
+ /// <summary>
+ /// Delete the specified row from the worksheet.
+ /// </summary>
+ /// <param name="row">A row to be deleted</param>
+ public void DeleteRow(int row) {
+ DeleteRow(row, 1);
+ }
+
+ /// <summary>
+ /// Delete the specified row from the worksheet.
+ /// </summary>
+ /// <param name="rowFrom">The start row</param>
+ /// <param name="rows">Number of rows to delete</param>
+ public void DeleteRow(int rowFrom, int rows) {
+ CheckSheetType();
+ if (rowFrom < 1 || rowFrom + rows > ExcelPackage.MaxRows) {
+ throw (new ArgumentException(
+ "Row out of range. Spans from 1 to "
+ + ExcelPackage.MaxRows.ToString(CultureInfo.InvariantCulture)));
+ }
+ _values.Delete(rowFrom, 0, rows, ExcelPackage.MaxColumns);
+ _types.Delete(rowFrom, 0, rows, ExcelPackage.MaxColumns);
+ _formulas.Delete(rowFrom, 0, rows, ExcelPackage.MaxColumns);
+ _styles.Delete(rowFrom, 0, rows, ExcelPackage.MaxColumns);
+ _flags.Delete(rowFrom, 0, rows, ExcelPackage.MaxColumns);
+ _commentsStore.Delete(rowFrom, 0, rows, ExcelPackage.MaxColumns);
+ _hyperLinks.Delete(rowFrom, 0, rows, ExcelPackage.MaxColumns);
+
+ AdjustFormulasRow(rowFrom, rows);
+ FixMergedCellsRow(rowFrom, rows, true);
+
+ foreach (var tbl in Tables) {
+ tbl.Address = tbl.Address.DeleteRow(rowFrom, rows);
+ }
+ }
+
+ /// <summary>
+ /// Delete the specified column from the worksheet.
+ /// </summary>
+ /// <param name="column">The column to be deleted</param>
+ public void DeleteColumn(int column) {
+ DeleteColumn(column, 1);
+ }
+
+ /// <summary>
+ /// Delete the specified column from the worksheet.
+ /// </summary>
+ /// <param name="columnFrom">The start column</param>
+ /// <param name="columns">Number of columns to delete</param>
+ public void DeleteColumn(int columnFrom, int columns) {
+ if (columnFrom < 1 || columnFrom + columns > ExcelPackage.MaxColumns) {
+ throw (new ArgumentException(
+ "Column out of range. Spans from 1 to "
+ + ExcelPackage.MaxColumns.ToString(CultureInfo.InvariantCulture)));
+ }
+ var col = _values.GetValue(0, columnFrom) as ExcelColumn;
+ if (col == null) {
+ var r = 0;
+ var c = columnFrom;
+ if (_values.PrevCell(ref r, ref c)) {
+ col = _values.GetValue(0, c) as ExcelColumn;
+ if (col._columnMax >= columnFrom) {
+ col.ColumnMax = columnFrom - 1;
+ }
+ }
+ }
+
+ _values.Delete(0, columnFrom, ExcelPackage.MaxRows, columns);
+ _types.Delete(0, columnFrom, ExcelPackage.MaxRows, columns);
+ _formulas.Delete(0, columnFrom, ExcelPackage.MaxRows, columns);
+ _styles.Delete(0, columnFrom, ExcelPackage.MaxRows, columns);
+ _flags.Delete(0, columnFrom, ExcelPackage.MaxRows, columns);
+ _commentsStore.Delete(0, columnFrom, ExcelPackage.MaxRows, columns);
+ _hyperLinks.Delete(0, columnFrom, ExcelPackage.MaxRows, columns);
+
+ AdjustFormulasColumn(columnFrom, columns);
+ FixMergedCellsColumn(columnFrom, columns, true);
+
+ var csec = new CellsStoreEnumerator<object>(_values, 0, columnFrom, 0, ExcelPackage.MaxColumns);
+ foreach (var column in csec) {
+ if (column is ExcelColumn excelColumn) {
+ if (excelColumn._columnMin >= columnFrom) {
+ excelColumn._columnMin -= columns;
+ excelColumn._columnMax -= columns;
+ }
+ }
+ }
+
+ foreach (var tbl in Tables) {
+ if (columnFrom >= tbl.Address.Start.Column && columnFrom <= tbl.Address.End.Column) {
+ var node = tbl.Columns[0].TopNode.ParentNode;
+ var ix = columnFrom - tbl.Address.Start.Column;
+ for (int i = 0; i < columns; i++) {
+ if (node.ChildNodes.Count > ix) {
+ node.RemoveChild(node.ChildNodes[ix]);
+ }
+ }
+ tbl._cols = new(tbl);
+ }
+
+ tbl.Address = tbl.Address.DeleteColumn(columnFrom, columns);
+ }
+ }
+
+ internal void AdjustFormulasRow(int rowFrom, int rows) {
+ var delSf = new List<int>();
+ foreach (var sf in _sharedFormulas.Values) {
+ var a = new ExcelAddress(sf.Address).DeleteRow(rowFrom, rows);
+ if (a == null) {
+ delSf.Add(sf.Index);
+ } else {
+ sf.Address = a.Address;
+ if (sf.StartRow > rowFrom) {
+ var r = Math.Min(sf.StartRow - rowFrom, rows);
+ sf.Formula = ExcelCellBase.UpdateFormulaReferences(sf.Formula, -r, 0, rowFrom, 0);
+ sf.StartRow -= r;
+ }
+ }
+ }
+ foreach (var ix in delSf) {
+ _sharedFormulas.Remove(ix);
+ }
+ var cse = new CellsStoreEnumerator<object>(
+ _formulas,
+ 1,
+ 1,
+ ExcelPackage.MaxRows,
+ ExcelPackage.MaxColumns);
+ while (cse.Next()) {
+ if (cse.Value is string) {
+ cse.Value = ExcelCellBase.UpdateFormulaReferences(
+ cse.Value.ToString(),
+ -rows,
+ 0,
+ rowFrom,
+ 0);
+ }
+ }
+ }
+
+ internal void AdjustFormulasColumn(int columnFrom, int columns) {
+ var delSf = new List<int>();
+ foreach (var sf in _sharedFormulas.Values) {
+ var a = new ExcelAddress(sf.Address).DeleteColumn(columnFrom, columns);
+ if (a == null) {
+ delSf.Add(sf.Index);
+ } else {
+ sf.Address = a.Address;
+ if (sf.StartCol > columnFrom) {
+ var c = Math.Min(sf.StartCol - columnFrom, columns);
+ sf.Formula = ExcelCellBase.UpdateFormulaReferences(sf.Formula, 0, -c, 0, 1);
+ sf.StartCol -= c;
+ }
+ }
+ }
+ foreach (var ix in delSf) {
+ _sharedFormulas.Remove(ix);
+ }
+ var cse = new CellsStoreEnumerator<object>(
+ _formulas,
+ 1,
+ 1,
+ ExcelPackage.MaxRows,
+ ExcelPackage.MaxColumns);
+ while (cse.Next()) {
+ if (cse.Value is string) {
+ cse.Value = ExcelCellBase.UpdateFormulaReferences(
+ cse.Value.ToString(),
+ 0,
+ -columns,
+ 0,
+ columnFrom);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Deletes the specified row from the worksheet.
+ /// </summary>
+ /// <param name="rowFrom">The number of the start row to be deleted</param>
+ /// <param name="rows">Number of rows to delete</param>
+ /// <param name="shiftOtherRowsUp">Not used. Rows are always shifted</param>
+ public void DeleteRow(int rowFrom, int rows, bool shiftOtherRowsUp) {
+ DeleteRow(rowFrom, rows);
+ }
+
+ /// <summary>
+ /// Get the cell value from thw worksheet
+ /// </summary>
+ /// <param name="row">The row number</param>
+ /// <param name="column">The row number</param>
+ /// <returns>The value</returns>
+ public object GetValue(int row, int column) {
+ CheckSheetType();
+ var v = _values.GetValue(row, column);
+ if (v != null) {
+ if (_flags.GetFlagValue(row, column, CellFlags.RichText)) {
+ return Cells[row, column].RichText.Text;
+ }
+ return v;
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Get a strongly typed cell value from the worksheet
+ /// </summary>
+ /// <typeparam name="T">The type</typeparam>
+ /// <param name="row">The row number</param>
+ /// <param name="column">The row number</param>
+ /// <returns>The value. If the value can't be converted to the specified type, the default value will be returned</returns>
+ public T GetValue<T>(int row, int column) {
+ CheckSheetType();
+ //ulong cellID=ExcelCellBase.GetCellID(SheetID, Row, Column);
+ var v = _values.GetValue(row, column);
+ if (v == null) {
+ return default(T);
+ }
+
+ //var cell=((ExcelCell)_cells[cellID]);
+ if (_flags.GetFlagValue(row, column, CellFlags.RichText)) {
+ return (T)(object)Cells[row, column].RichText.Text;
+ }
+ return GetTypedValue<T>(v);
+ }
+
+ //Thanks to Michael Tran for parts of this method
+ internal T GetTypedValue<T>(object v) {
+ if (v == null) {
+ return default(T);
+ }
+ Type fromType = v.GetType();
+ Type toType = typeof(T);
+ if (fromType == toType) {
+ return (T)v;
+ }
+ var cnv = TypeDescriptor.GetConverter(fromType);
+ if (toType
+ == typeof(DateTime)) //Handle dates
+ {
+ if (fromType == typeof(TimeSpan)) {
+ return ((T)(object)(new DateTime(((TimeSpan)v).Ticks)));
+ }
+ if (fromType == typeof(string)) {
+ if (DateTime.TryParse(v.ToString(), out var dt)) {
+ return (T)(object)(dt);
+ }
+ return default(T);
+ }
+ if (cnv.CanConvertTo(typeof(double))) {
+ return (T)(object)(DateTime.FromOADate((double)cnv.ConvertTo(v, typeof(double))));
+ }
+ return default(T);
+ }
+ if (toType
+ == typeof(TimeSpan)) //Handle timespan
+ {
+ if (fromType == typeof(DateTime)) {
+ return ((T)(object)(new TimeSpan(((DateTime)v).Ticks)));
+ }
+ if (fromType == typeof(string)) {
+ if (TimeSpan.TryParse(v.ToString(), out var ts)) {
+ return (T)(object)(ts);
+ }
+ return default(T);
+ }
+ if (cnv.CanConvertTo(typeof(double))) {
+ return (T)
+ (object)(new TimeSpan(
+ DateTime.FromOADate((double)cnv.ConvertTo(v, typeof(double))).Ticks));
+ }
+ try {
+ // Issue 14682 -- "GetValue<decimal>() won't convert strings"
+ // As suggested, after all special cases, all .NET to do it's
+ // preferred conversion rather than simply returning the default
+ return (T)Convert.ChangeType(v, typeof(T));
+ } catch (Exception) {
+ // This was the previous behaviour -- no conversion is available.
+ return default(T);
+ }
+ }
+ if (cnv.CanConvertTo(toType)) {
+ return (T)cnv.ConvertTo(v, typeof(T));
+ }
+ if (toType.IsGenericType && toType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
+ toType = Nullable.GetUnderlyingType(toType);
+ if (cnv.CanConvertTo(toType)) {
+ return (T)cnv.ConvertTo(v, typeof(T));
+ }
+ }
+
+ if (fromType == typeof(double) && toType == typeof(decimal)) {
+ return (T)(object)Convert.ToDecimal(v);
+ }
+ if (fromType == typeof(decimal) && toType == typeof(double)) {
+ return (T)(object)Convert.ToDouble(v);
+ }
+ return default(T);
+ }
+
+ /// <summary>
+ /// Set the value of a cell
+ /// </summary>
+ /// <param name="row">The row number</param>
+ /// <param name="column">The column number</param>
+ /// <param name="value">The value</param>
+ public void SetValue(int row, int column, object value) {
+ CheckSheetType();
+ if (row < 1 || column < 1 || row > ExcelPackage.MaxRows && column > ExcelPackage.MaxColumns) {
+ throw new ArgumentOutOfRangeException("Row or Column out of range");
+ }
+ _values.SetValue(row, column, value);
+ }
+
+ /// <summary>
+ /// Set the value of a cell
+ /// </summary>
+ /// <param name="address">The Excel address</param>
+ /// <param name="value">The value</param>
+ public void SetValue(string address, object value) {
+ CheckSheetType();
+ ExcelCellBase.GetRowCol(address, out var row, out var col, true);
+ if (row < 1 || col < 1 || row > ExcelPackage.MaxRows && col > ExcelPackage.MaxColumns) {
+ throw new ArgumentOutOfRangeException("Address is invalid or out of range");
+ }
+ _values.SetValue(row, col, value);
+ }
+
+ /// <summary>
+ /// Get MergeCell Index No
+ /// </summary>
+ /// <param name="row"></param>
+ /// <param name="column"></param>
+ /// <returns></returns>
+ public int GetMergeCellId(int row, int column) {
+ for (int i = 0; i < _mergedCells.Count; i++) {
+ if (!string.IsNullOrEmpty(_mergedCells[i])) {
+ ExcelRange range = Cells[_mergedCells[i]];
+
+ if (range.Start.Row <= row && row <= range.End.Row) {
+ if (range.Start.Column <= column && column <= range.End.Column) {
+ return i + 1;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ internal void Save() {
+ DeletePrinterSettings();
+ if (!(this is ExcelChartsheet)) {
+ var d = Dimension;
+ if (d == null) {
+ DeleteAllNode("d:dimension/@ref");
+ } else {
+ SetXmlNodeString("d:dimension/@ref", d.Address);
+ }
+ SaveTables();
+ SavePivotTables();
+ }
+ }
+
+ internal void SaveHandler(StreamWriter streamWriter) {
+ //Create the nodes if they do not exist.
+ if (this is ExcelChartsheet) {
+ streamWriter.Write(WorksheetXml.OuterXml);
+ } else {
+ CreateNode("d:cols");
+ CreateNode("d:sheetData");
+ CreateNode("d:mergeCells");
+ CreateNode("d:hyperlinks");
+ CreateNode("d:rowBreaks");
+ CreateNode("d:colBreaks");
+
+ //StreamWriter sw=new StreamWriter(Part.GetStream(FileMode.Create, FileAccess.Write));
+ var xml = WorksheetXml.OuterXml;
+ int colStart = 0,
+ colEnd = 0;
+ GetBlockPos(xml, "cols", ref colStart, ref colEnd);
+
+ streamWriter.Write(xml.Substring(0, colStart));
+ UpdateColumnData(streamWriter);
+
+ int cellStart = colEnd,
+ cellEnd = colEnd;
+ GetBlockPos(xml, "sheetData", ref cellStart, ref cellEnd);
+
+ streamWriter.Write(xml.Substring(colEnd, cellStart - colEnd));
+ UpdateRowCellData(streamWriter);
+
+ int mergeStart = cellEnd,
+ mergeEnd = cellEnd;
+
+ GetBlockPos(xml, "mergeCells", ref mergeStart, ref mergeEnd);
+ streamWriter.Write(xml.Substring(cellEnd, mergeStart - cellEnd));
+
+ CleanupMergedCells(_mergedCells);
+ if (_mergedCells.Count > 0) {
+ UpdateMergedCells(streamWriter);
+ }
+
+ int hyperStart = mergeEnd,
+ hyperEnd = mergeEnd;
+ GetBlockPos(xml, "hyperlinks", ref hyperStart, ref hyperEnd);
+ streamWriter.Write(xml.Substring(mergeEnd, hyperStart - mergeEnd));
+ UpdateHyperLinks(streamWriter);
+
+ int rowBreakStart = hyperEnd,
+ rowBreakEnd = hyperEnd;
+ GetBlockPos(xml, "rowBreaks", ref rowBreakStart, ref rowBreakEnd);
+ streamWriter.Write(xml.Substring(hyperEnd, rowBreakStart - hyperEnd));
+ UpdateRowBreaks(streamWriter);
+
+ int colBreakStart = rowBreakEnd,
+ colBreakEnd = rowBreakEnd;
+ GetBlockPos(xml, "colBreaks", ref colBreakStart, ref colBreakEnd);
+ streamWriter.Write(xml.Substring(rowBreakEnd, colBreakStart - rowBreakEnd));
+ UpdateColBreaks(streamWriter);
+ streamWriter.Write(xml.Substring(colBreakEnd, xml.Length - colBreakEnd));
+ }
+ }
+
+ /// <summary>
+ /// Delete the printersettings relationship and part.
+ /// </summary>
+ private void DeletePrinterSettings() {
+ //Delete the relationship from the pageSetup tag
+ XmlAttribute attr = (XmlAttribute)
+ WorksheetXml.SelectSingleNode("//d:pageSetup/@r:id", NameSpaceManager);
+ if (attr != null) {
+ string relId = attr.Value;
+ //First delete the attribute from the XML
+ attr.OwnerElement.Attributes.Remove(attr);
+ if (Part.RelationshipExists(relId)) {
+ var rel = Part.GetRelationship(relId);
+ Uri printerSettingsUri = UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri);
+ Part.DeleteRelationship(rel.Id);
+
+ //Delete the part from the package
+ if (_package.Package.PartExists(printerSettingsUri)) {
+ _package.Package.DeletePart(printerSettingsUri);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Save all table data
+ /// </summary>
+ private void SaveTables() {
+ foreach (var tbl in Tables) {
+ if (tbl.ShowHeader || tbl.ShowTotal) {
+ int colNum = tbl.Address._fromCol;
+ var colVal = new HashSet<string>();
+ foreach (var col in tbl.Columns) {
+ string n = col.Name.ToLower(CultureInfo.InvariantCulture);
+ if (tbl.ShowHeader) {
+ n = tbl.WorkSheet.GetValue<string>(
+ tbl.Address._fromRow,
+ tbl.Address._fromCol + col.Position);
+ if (string.IsNullOrEmpty(n)) {
+ n = col.Name.ToLower(CultureInfo.InvariantCulture);
+ } else {
+ col.Name = n;
+ }
+ } else {
+ n = col.Name.ToLower(CultureInfo.InvariantCulture);
+ }
+
+ if (colVal.Contains(n)) {
+ throw (new InvalidDataException(
+ string.Format(
+ "Table {0} Column {1} does not have a unique name.",
+ tbl.Name,
+ col.Name)));
+ }
+ colVal.Add(n);
+ col.Name = ConvertUtil.ExcelEncodeString(col.Name);
+ if (tbl.ShowHeader) {
+ _values.SetValue(tbl.Address._fromRow, colNum, col.Name);
+ }
+ if (tbl.ShowTotal) {
+ SetTableTotalFunction(tbl, col, colNum);
+ }
+ if (!string.IsNullOrEmpty(col.CalculatedColumnFormula)) {
+ int fromRow = tbl.ShowHeader ? tbl.Address._fromRow + 1 : tbl.Address._fromRow;
+ int toRow = tbl.ShowTotal ? tbl.Address._toRow - 1 : tbl.Address._toRow;
+ for (int row = fromRow; row <= toRow; row++) {
+ //Cell(row, colNum).Formula = col.CalculatedColumnFormula;
+ SetFormula(row, colNum, col.CalculatedColumnFormula);
+ }
+ }
+ colNum++;
+ }
+ }
+ }
+ }
+
+ internal void SetTableTotalFunction(ExcelTable tbl, ExcelTableColumn col, int colNum = -1) {
+ if (tbl.ShowTotal == false) {
+ return;
+ }
+ if (colNum == -1) {
+ for (int i = 0; i < tbl.Columns.Count; i++) {
+ if (tbl.Columns[i].Name == col.Name) {
+ colNum = tbl.Address._fromCol + i;
+ }
+ }
+ }
+ if (col.TotalsRowFunction == RowFunctions.Custom) {
+ SetFormula(tbl.Address._toRow, colNum, col.TotalsRowFormula);
+ } else if (col.TotalsRowFunction != RowFunctions.None) {
+ switch (col.TotalsRowFunction) {
+ case RowFunctions.Average:
+ SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "101"));
+ break;
+ case RowFunctions.Count:
+ SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "102"));
+ break;
+ case RowFunctions.CountNums:
+ SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "103"));
+ break;
+ case RowFunctions.Max:
+ SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "104"));
+ break;
+ case RowFunctions.Min:
+ SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "105"));
+ break;
+ case RowFunctions.StdDev:
+ SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "107"));
+ break;
+ case RowFunctions.Var:
+ SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "110"));
+ break;
+ case RowFunctions.Sum:
+ SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "109"));
+ break;
+ default:
+ throw (new("Unknown RowFunction enum"));
+ }
+ } else {
+ _values.SetValue(tbl.Address._toRow, colNum, col.TotalsRowLabel);
+ }
+ }
+
+ internal void SetFormula(int row, int col, object value) {
+ _formulas.SetValue(row, col, value);
+ if (!_values.Exists(row, col)) {
+ _values.SetValue(row, col, null);
+ }
+ }
+
+ internal void SetStyle(int row, int col, int value) {
+ _styles.SetValue(row, col, value);
+ if (!_values.Exists(row, col)) {
+ _values.SetValue(row, col, null);
+ }
+ }
+
+ private void SavePivotTables() {
+ foreach (var pt in PivotTables) {
+ if (pt.DataFields.Count > 1) {
+ XmlElement parentNode;
+ if (pt.DataOnRows) {
+ parentNode =
+ pt.PivotTableXml.SelectSingleNode("//d:rowFields", pt.NameSpaceManager) as XmlElement;
+ if (parentNode == null) {
+ pt.CreateNode("d:rowFields");
+ parentNode =
+ pt.PivotTableXml.SelectSingleNode("//d:rowFields", pt.NameSpaceManager)
+ as XmlElement;
+ }
+ } else {
+ parentNode =
+ pt.PivotTableXml.SelectSingleNode("//d:colFields", pt.NameSpaceManager) as XmlElement;
+ if (parentNode == null) {
+ pt.CreateNode("d:colFields");
+ parentNode =
+ pt.PivotTableXml.SelectSingleNode("//d:colFields", pt.NameSpaceManager)
+ as XmlElement;
+ }
+ }
+
+ if (parentNode.SelectSingleNode("d:field[@ x= \"-2\"]", pt.NameSpaceManager) == null) {
+ XmlElement fieldNode = pt.PivotTableXml.CreateElement("field", ExcelPackage._schemaMain);
+ fieldNode.SetAttribute("x", "-2");
+ parentNode.AppendChild(fieldNode);
+ }
+ }
+ var ws = Workbook.Worksheets[pt.CacheDefinition.SourceRange.WorkSheet];
+ var t = ws.Tables.GetFromRange(pt.CacheDefinition.SourceRange);
+ var fields = pt.CacheDefinition.CacheDefinitionXml.SelectNodes(
+ "d:pivotCacheDefinition/d:cacheFields/d:cacheField",
+ NameSpaceManager);
+ int ix = 0;
+ if (fields != null) {
+ var flds = new HashSet<string>();
+ foreach (XmlElement node in fields) {
+ if (ix >= pt.CacheDefinition.SourceRange.Columns) {
+ break;
+ }
+ var fldName = node.GetAttribute("name"); //Fixes issue 15295 dup name error
+ if (string.IsNullOrEmpty(fldName)) {
+ fldName =
+ (t == null
+ ? pt.CacheDefinition.SourceRange.Offset(0, ix++, 1, 1).Value.ToString()
+ : t.Columns[ix++].Name);
+ }
+ if (flds.Contains(fldName)) {
+ fldName = GetNewName(flds, fldName);
+ }
+ flds.Add(fldName);
+ node.SetAttribute("name", fldName);
+ }
+ foreach (var df in pt.DataFields) {
+ if (string.IsNullOrEmpty(df.Name)) {
+ string name;
+ if (df.Function == DataFieldFunctions.None) {
+ name = df.Field.Name; //Name must be set or Excel will crash on rename.
+ } else {
+ name = df.Function + " of " + df.Field.Name; //Name must be set or Excel will crash on rename.
+ }
+ //Make sure name is unique
+ var newName = name;
+ var i = 2;
+ while (pt.DataFields.ExistsDfName(newName, df)) {
+ newName = name + (i++).ToString(CultureInfo.InvariantCulture);
+ }
+ df.Name = newName;
+ }
+ }
+ }
+ }
+ }
+
+ private string GetNewName(HashSet<string> flds, string fldName) {
+ int ix = 2;
+ while (flds.Contains(fldName + ix.ToString(CultureInfo.InvariantCulture))) {
+ ix++;
+ }
+ return fldName + ix.ToString(CultureInfo.InvariantCulture);
+ }
+
+ private static string GetTotalFunction(ExcelTableColumn col, string functionNum) {
+ return string.Format("SUBTOTAL({0},{1}[{2}])", functionNum, col._tbl.Name, col.Name);
+ }
+
+ private void CleanupMergedCells(MergeCellsCollection mergedCells) {
+ int i = 0;
+ while (i < mergedCells.List.Count) {
+ if (mergedCells[i] == null) {
+ mergedCells.List.RemoveAt(i);
+ } else {
+ i++;
+ }
+ }
+ }
+
+ private void UpdateColBreaks(StreamWriter sw) {
+ StringBuilder breaks = new StringBuilder();
+ int count = 0;
+ var cse = new CellsStoreEnumerator<object>(_values, 0, 0, 0, ExcelPackage.MaxColumns);
+ while (cse.Next()) {
+ var col = cse.Value as ExcelColumn;
+ if (col != null && col.PageBreak) {
+ breaks.AppendFormat("<brk id=\"{0}\" max=\"16383\" man=\"1\" />", cse.Column);
+ count++;
+ }
+ }
+ if (count > 0) {
+ sw.Write("<colBreaks count=\"{0}\" manualBreakCount=\"{0}\">{1}</colBreaks>", count, breaks);
+ }
+ }
+
+ private void UpdateRowBreaks(StreamWriter sw) {
+ StringBuilder breaks = new StringBuilder();
+ int count = 0;
+ var cse = new CellsStoreEnumerator<object>(_values, 0, 0, ExcelPackage.MaxRows, 0);
+ //foreach(ExcelRow row in _rows)
+ while (cse.Next()) {
+ var row = cse.Value as RowInternal;
+ if (row != null && row.PageBreak) {
+ breaks.AppendFormat("<brk id=\"{0}\" max=\"1048575\" man=\"1\" />", cse.Row);
+ count++;
+ }
+ }
+ if (count > 0) {
+ sw.Write("<rowBreaks count=\"{0}\" manualBreakCount=\"{0}\">{1}</rowBreaks>", count, breaks);
+ }
+ }
+
+ /// <summary>
+ /// Inserts the cols collection into the XML document
+ /// </summary>
+ private void UpdateColumnData(StreamWriter sw) {
+ var cse = new CellsStoreEnumerator<object>(_values, 0, 1, 0, ExcelPackage.MaxColumns);
+ bool first = true;
+ while (cse.Next()) {
+ if (first) {
+ sw.Write("<cols>");
+ first = false;
+ }
+ var col = cse.Value as ExcelColumn;
+ ExcelStyleCollection<ExcelXfs> cellXfs = _workbook.Styles.CellXfs;
+
+ sw.Write("<col min=\"{0}\" max=\"{1}\"", col.ColumnMin, col.ColumnMax);
+ if (col.Hidden) {
+ //sbXml.Append(" width=\"0\" hidden=\"1\" customWidth=\"1\"");
+ sw.Write(" hidden=\"1\"");
+ } else if (col.BestFit) {
+ sw.Write(" bestFit=\"1\"");
+ }
+ sw.Write(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ " width=\"{0}\" customWidth=\"1\"",
+ col.Width));
+ if (col.OutlineLevel > 0) {
+ sw.Write(" outlineLevel=\"{0}\" ", col.OutlineLevel);
+ if (col.Collapsed) {
+ if (col.Hidden) {
+ sw.Write(" collapsed=\"1\"");
+ } else {
+ sw.Write(" collapsed=\"1\" hidden=\"1\""); //Always hidden
+ }
+ }
+ }
+ if (col.Phonetic) {
+ sw.Write(" phonetic=\"1\"");
+ }
+
+ var styleId = col.StyleID >= 0 ? cellXfs[col.StyleID].newID : col.StyleID;
+ if (styleId > 0) {
+ sw.Write(" style=\"{0}\"", styleId);
+ }
+ sw.Write(" />");
+ }
+ if (!first) {
+ sw.Write("</cols>");
+ }
+ }
+
+ /// <summary>
+ /// Insert row and cells into the XML document
+ /// </summary>
+ private void UpdateRowCellData(StreamWriter sw) {
+ ExcelStyleCollection<ExcelXfs> cellXfs = _workbook.Styles.CellXfs;
+
+ int row = -1;
+
+ var ss = _workbook._sharedStrings;
+ var styles = _workbook.Styles;
+ var cache = new StringBuilder();
+ cache.Append("<sheetData>");
+
+ //Set a value for cells with style and no value set.
+ var cseStyle = new CellsStoreEnumerator<int>(
+ _styles,
+ 0,
+ 0,
+ ExcelPackage.MaxRows,
+ ExcelPackage.MaxColumns);
+ foreach (var s in cseStyle) {
+ if (!_values.Exists(cseStyle.Row, cseStyle.Column)) {
+ _values.SetValue(cseStyle.Row, cseStyle.Column, null);
+ }
+ }
+
+ var cse = new CellsStoreEnumerator<object>(
+ _values,
+ 1,
+ 0,
+ ExcelPackage.MaxRows,
+ ExcelPackage.MaxColumns);
+ //foreach (IRangeID r in _cells)
+ while (cse.Next()) {
+ if (cse.Column > 0) {
+ int styleId = cellXfs[styles.GetStyleId(this, cse.Row, cse.Column)].newID;
+ //Add the row element if it's a new row
+ if (cse.Row != row) {
+ WriteRow(cache, cellXfs, row, cse.Row);
+ row = cse.Row;
+ }
+ object v = cse.Value;
+ object formula = _formulas.GetValue(cse.Row, cse.Column);
+ if (formula is int sfId) {
+ var f = _sharedFormulas[sfId];
+ if (f.Address.IndexOf(':') > 0) {
+ if (f.StartCol == cse.Column && f.StartRow == cse.Row) {
+ if (f.IsArray) {
+ cache.AppendFormat(
+ "<c r=\"{0}\" s=\"{1}\"{5}><f ref=\"{2}\" t=\"array\">{3}</f>{4}</c>",
+ cse.CellAddress,
+ styleId < 0 ? 0 : styleId,
+ f.Address,
+ SecurityElement.Escape(f.Formula),
+ GetFormulaValue(v),
+ GetCellType(v, true));
+ } else {
+ cache.AppendFormat(
+ "<c r=\"{0}\" s=\"{1}\"{6}><f ref=\"{2}\" t=\"shared\" si=\"{3}\">{4}</f>{5}</c>",
+ cse.CellAddress,
+ styleId < 0 ? 0 : styleId,
+ f.Address,
+ sfId,
+ SecurityElement.Escape(f.Formula),
+ GetFormulaValue(v),
+ GetCellType(v, true));
+ }
+ } else if (f.IsArray) {
+ cache.AppendFormat(
+ "<c r=\"{0}\" s=\"{1}\" />",
+ cse.CellAddress,
+ styleId < 0 ? 0 : styleId);
+ } else {
+ cache.AppendFormat(
+ "<c r=\"{0}\" s=\"{1}\"{4}><f t=\"shared\" si=\"{2}\" />{3}</c>",
+ cse.CellAddress,
+ styleId < 0 ? 0 : styleId,
+ sfId,
+ GetFormulaValue(v),
+ GetCellType(v, true));
+ }
+ } else {
+ // We can also have a single cell array formula
+ if (f.IsArray) {
+ cache.AppendFormat(
+ "<c r=\"{0}\" s=\"{1}\"{5}><f ref=\"{2}\" t=\"array\">{3}</f>{4}</c>",
+ cse.CellAddress,
+ styleId < 0 ? 0 : styleId,
+ string.Format("{0}:{1}", f.Address, f.Address),
+ SecurityElement.Escape(f.Formula),
+ GetFormulaValue(v),
+ GetCellType(v, true));
+ } else {
+ cache.AppendFormat("<c r=\"{0}\" s=\"{1}\">", f.Address, styleId < 0 ? 0 : styleId);
+ cache.AppendFormat(
+ "<f>{0}</f>{1}</c>",
+ SecurityElement.Escape(f.Formula),
+ GetFormulaValue(v));
+ }
+ }
+ } else if (formula != null && formula.ToString() != "") {
+ cache.AppendFormat(
+ "<c r=\"{0}\" s=\"{1}\"{2}>",
+ cse.CellAddress,
+ styleId < 0 ? 0 : styleId,
+ GetCellType(v, true));
+ cache.AppendFormat(
+ "<f>{0}</f>{1}</c>",
+ SecurityElement.Escape(formula.ToString()),
+ GetFormulaValue(v));
+ } else {
+ if (v == null && styleId > 0) {
+ cache.AppendFormat(
+ "<c r=\"{0}\" s=\"{1}\" />",
+ cse.CellAddress,
+ styleId < 0 ? 0 : styleId);
+ } else if (v != null) {
+ if ((v.GetType().IsPrimitive
+ || v is double
+ || v is decimal
+ || v is DateTime
+ || v is TimeSpan)) {
+ //string sv = GetValueForXml(v);
+ cache.AppendFormat(
+ "<c r=\"{0}\" s=\"{1}\" {2}>",
+ cse.CellAddress,
+ styleId < 0 ? 0 : styleId,
+ GetCellType(v));
+ cache.AppendFormat("{0}</c>", GetFormulaValue(v));
+ } else {
+ int ix;
+ if (!ss.ContainsKey(v.ToString())) {
+ ix = ss.Count;
+ ss.Add(
+ v.ToString(),
+ new() {
+ isRichText = _flags.GetFlagValue(cse.Row, cse.Column, CellFlags.RichText),
+ pos = ix,
+ });
+ } else {
+ ix = ss[v.ToString()].pos;
+ }
+ cache.AppendFormat(
+ "<c r=\"{0}\" s=\"{1}\" t=\"s\">",
+ cse.CellAddress,
+ styleId < 0 ? 0 : styleId);
+ cache.AppendFormat("<v>{0}</v></c>", ix);
+ }
+ }
+ }
+ } else //ExcelRow
+ {
+ WriteRow(cache, cellXfs, row, cse.Row);
+ row = cse.Row;
+ }
+ if (cache.Length > 0x600000) {
+ sw.Write(cache.ToString());
+ cache = new();
+ }
+ }
+
+ if (row != -1) {
+ cache.Append("</row>");
+ }
+ cache.Append("</sheetData>");
+ sw.Write(cache.ToString());
+ sw.Flush();
+ }
+
+ private object GetFormulaValue(object v) {
+ if (v != null && v.ToString() != "") {
+ return "<v>" + SecurityElement.Escape(GetValueForXml(v)) + "</v>"; //Fixes issue 15071
+ }
+ return "";
+ }
+
+ private string GetCellType(object v, bool allowStr = false) {
+ if (v is bool) {
+ return " t=\"b\"";
+ }
+ if ((v is double d && double.IsInfinity(d)) || v is ExcelErrorValue) {
+ return " t=\"e\"";
+ }
+ if (allowStr
+ && v != null
+ && !(v.GetType().IsPrimitive
+ || v is double
+ || v is decimal
+ || v is DateTime
+ || v is TimeSpan)) {
+ return " t=\"str\"";
+ }
+ return "";
+ }
+
+ private string GetValueForXml(object v) {
+ string s;
+ try {
+ if (v is DateTime time) {
+ double sdv = time.ToOADate();
+
+ if (Workbook.Date1904) {
+ sdv -= ExcelWorkbook._date1904Offset;
+ }
+
+ s = sdv.ToString(CultureInfo.InvariantCulture);
+ } else if (v is TimeSpan span) {
+ s = new DateTime(span.Ticks).ToOADate().ToString(CultureInfo.InvariantCulture);
+ ;
+ } else if (v.GetType().IsPrimitive || v is double || v is decimal) {
+ if (v is double d && double.IsNaN(d)) {
+ s = "";
+ } else if (v is double d1 && double.IsInfinity(d1)) {
+ s = "#NUM!";
+ } else {
+ s = Convert
+ .ToDouble(v, CultureInfo.InvariantCulture)
+ .ToString("R15", CultureInfo.InvariantCulture);
+ }
+ } else {
+ s = v.ToString();
+ }
+ } catch {
+ s = "0";
+ }
+ return s;
+ }
+
+ private void WriteRow(
+ StringBuilder cache,
+ ExcelStyleCollection<ExcelXfs> cellXfs,
+ int prevRow,
+ int row) {
+ if (prevRow != -1) {
+ cache.Append("</row>");
+ }
+ //ulong rowID = ExcelRow.GetRowID(SheetID, row);
+ cache.AppendFormat("<row r=\"{0}\" ", row);
+ RowInternal currRow = _values.GetValue(row, 0) as RowInternal;
+ if (currRow != null) {
+ if (currRow.Hidden) {
+ cache.Append("ht=\"0\" hidden=\"1\" ");
+ } else if (currRow.Height != DefaultRowHeight && currRow.Height >= 0) {
+ cache.AppendFormat(CultureInfo.InvariantCulture, "ht=\"{0}\" ", currRow.Height);
+ if (currRow.CustomHeight) {
+ cache.Append("customHeight=\"1\" ");
+ }
+ }
+
+ if (currRow.OutlineLevel > 0) {
+ cache.AppendFormat("outlineLevel =\"{0}\" ", currRow.OutlineLevel);
+ if (currRow.Collapsed) {
+ if (currRow.Hidden) {
+ cache.Append(" collapsed=\"1\" ");
+ } else {
+ cache.Append(" collapsed=\"1\" hidden=\"1\" "); //Always hidden
+ }
+ }
+ }
+ if (currRow.Phonetic) {
+ cache.Append("ph=\"1\" ");
+ }
+ }
+ var s = _styles.GetValue(row, 0);
+ if (s > 0) {
+ cache.AppendFormat("s=\"{0}\" customFormat=\"1\"", cellXfs[s].newID);
+ }
+ cache.Append(">");
+ }
+
+ /// <summary>
+ /// Update xml with hyperlinks
+ /// </summary>
+ /// <param name="sw">The stream</param>
+ private void UpdateHyperLinks(StreamWriter sw) {
+ Dictionary<string, string> hyps = new Dictionary<string, string>();
+ var cse = new CellsStoreEnumerator<Uri>(_hyperLinks);
+ bool first = true;
+ //foreach (ulong cell in _hyperLinks)
+ while (cse.Next()) {
+ if (first) {
+ sw.Write("<hyperlinks>");
+ first = false;
+ }
+ //int row, col;
+ var uri = _hyperLinks.GetValue(cse.Row, cse.Column);
+ //ExcelCell cell = _cells[cellId] as ExcelCell;
+ if (uri is ExcelHyperLink link && !string.IsNullOrEmpty(link.ReferenceAddress)) {
+ sw.Write(
+ "<hyperlink ref=\"{0}\" location=\"{1}\" {2}{3}/>",
+ Cells[cse.Row, cse.Column, cse.Row + link.RowSpann, cse.Column + link.ColSpann].Address,
+ ExcelCellBase.GetFullAddress(
+ SecurityElement.Escape(Name),
+ SecurityElement.Escape(link.ReferenceAddress)),
+ string.IsNullOrEmpty(link.Display)
+ ? ""
+ : "display=\"" + SecurityElement.Escape(link.Display) + "\" ",
+ string.IsNullOrEmpty(link.ToolTip)
+ ? ""
+ : "tooltip=\"" + SecurityElement.Escape(link.ToolTip) + "\" ");
+ } else if (uri != null) {
+ Uri hyp;
+ if (uri is ExcelHyperLink hyperLink) {
+ hyp = hyperLink.OriginalUri;
+ } else {
+ hyp = uri;
+ }
+ if (!hyps.ContainsKey(hyp.OriginalString)) {
+ var relationship = Part.CreateRelationship(
+ hyp,
+ TargetMode.External,
+ ExcelPackage._schemaHyperlink);
+ if (uri is ExcelHyperLink hl) {
+ sw.Write(
+ "<hyperlink ref=\"{0}\" {2}{3}r:id=\"{1}\" />",
+ ExcelCellBase.GetAddress(cse.Row, cse.Column),
+ relationship.Id,
+ string.IsNullOrEmpty(hl.Display)
+ ? ""
+ : "display=\"" + SecurityElement.Escape(hl.Display) + "\" ",
+ string.IsNullOrEmpty(hl.ToolTip)
+ ? ""
+ : "tooltip=\"" + SecurityElement.Escape(hl.ToolTip) + "\" ");
+ } else {
+ sw.Write(
+ "<hyperlink ref=\"{0}\" r:id=\"{1}\" />",
+ ExcelCellBase.GetAddress(cse.Row, cse.Column),
+ relationship.Id);
+ }
+ }
+ }
+ }
+ if (!first) {
+ sw.Write("</hyperlinks>");
+ }
+ }
+
+ /// <summary>
+ /// Dimension address for the worksheet.
+ /// Top left cell to Bottom right.
+ /// If the worksheet has no cells, null is returned
+ /// </summary>
+ public ExcelAddressBase Dimension {
+ get {
+ CheckSheetType();
+ if (_values.GetDimension(out var fromRow, out var fromCol, out var toRow, out var toCol)) {
+ var addr = new ExcelAddressBase(fromRow, fromCol, toRow, toCol);
+ addr._ws = Name;
+ return addr;
+ }
+ return null;
+ }
+ }
+
+ private ExcelSheetProtection _protection;
+
+ /// <summary>
+ /// Access to sheet protection properties
+ /// </summary>
+ public ExcelSheetProtection Protection {
+ get {
+ if (_protection == null) {
+ _protection = new(NameSpaceManager, TopNode);
+ }
+ return _protection;
+ }
+ }
+
+ private ExcelProtectedRangeCollection _protectedRanges;
+
+ public ExcelProtectedRangeCollection ProtectedRanges {
+ get {
+ if (_protectedRanges == null) {
+ _protectedRanges = new(NameSpaceManager, TopNode);
+ }
+ return _protectedRanges;
+ }
+ }
+
+ private ExcelTableCollection _tables;
+
+ /// <summary>
+ /// Tables defined in the worksheet.
+ /// </summary>
+ public ExcelTableCollection Tables {
+ get {
+ CheckSheetType();
+ if (Workbook._nextTableID == int.MinValue) {
+ Workbook.ReadAllTables();
+ }
+ if (_tables == null) {
+ _tables = new(this);
+ }
+ return _tables;
+ }
+ }
+
+ private ExcelPivotTableCollection _pivotTables;
+
+ /// <summary>
+ /// Pivottables defined in the worksheet.
+ /// </summary>
+ public ExcelPivotTableCollection PivotTables {
+ get {
+ CheckSheetType();
+ if (_pivotTables == null) {
+ if (Workbook._nextPivotTableID == int.MinValue) {
+ Workbook.ReadAllTables();
+ }
+ _pivotTables = new(this);
+ }
+ return _pivotTables;
+ }
+ }
+
+ private ExcelConditionalFormattingCollection _conditionalFormatting;
+
+ /// <summary>
+ /// ConditionalFormatting defined in the worksheet. Use the Add methods to create ConditionalFormatting and add them to the worksheet. Then
+ /// set the properties on the instance returned.
+ /// </summary>
+ /// <seealso cref="ExcelConditionalFormattingCollection"/>
+ public ExcelConditionalFormattingCollection ConditionalFormatting {
+ get {
+ CheckSheetType();
+ if (_conditionalFormatting == null) {
+ _conditionalFormatting = new(this);
+ }
+ return _conditionalFormatting;
+ }
+ }
+
+ private ExcelDataValidationCollection _dataValidation;
+
+ /// <summary>
+ /// DataValidation defined in the worksheet. Use the Add methods to create DataValidations and add them to the worksheet. Then
+ /// set the properties on the instance returned.
+ /// </summary>
+ /// <seealso cref="ExcelDataValidationCollection"/>
+ public ExcelDataValidationCollection DataValidations {
+ get {
+ CheckSheetType();
+ if (_dataValidation == null) {
+ _dataValidation = new(this);
+ }
+ return _dataValidation;
+ }
+ }
+
+ /// <summary>
+ /// Returns the style ID given a style name.
+ /// The style ID will be created if not found, but only if the style name exists!
+ /// </summary>
+ /// <param name="styleName"></param>
+ /// <returns></returns>
+ internal int GetStyleId(string styleName) {
+ ExcelNamedStyleXml namedStyle = null;
+ Workbook.Styles.NamedStyles.FindById(styleName, ref namedStyle);
+ if (namedStyle.XfId == int.MinValue) {
+ namedStyle.XfId = Workbook.Styles.CellXfs.FindIndexById(namedStyle.Style.Id);
+ }
+ return namedStyle.XfId;
+ }
+
+ /// <summary>
+ /// The workbook object
+ /// </summary>
+ public ExcelWorkbook Workbook => _workbook;
+
+ /// <summary>
+ /// Get the next ID from a shared formula or an Array formula
+ /// Sharedforumlas will have an id from 0-x. Array formula ids start from 0x4000001-.
+ /// </summary>
+ /// <param name="isArray">If the formula is an array formula</param>
+ /// <returns></returns>
+ internal int GetMaxShareFunctionIndex(bool isArray) {
+ int i = _sharedFormulas.Count + 1;
+ if (isArray) {
+ i |= 0x40000000;
+ }
+
+ while (_sharedFormulas.ContainsKey(i)) {
+ i++;
+ }
+ return i;
+ }
+
+ internal void UpdateCellsWithDate1904Setting() {
+ var cse = new CellsStoreEnumerator<object>(_values);
+ var offset = Workbook.Date1904 ? -ExcelWorkbook._date1904Offset : ExcelWorkbook._date1904Offset;
+ while (cse.MoveNext()) {
+ if (cse.Value is DateTime time) {
+ try {
+ double sdv = time.ToOADate();
+ sdv += offset;
+
+ cse.Value = DateTime.FromOADate(sdv);
+ } catch {}
+ }
+ }
+ }
+
+ public string GetFormula(int row, int col) {
+ var v = _formulas.GetValue(row, col);
+ if (v is int i) {
+ return _sharedFormulas[i].GetFormula(row, col, Name);
+ }
+ if (v != null) {
+ return v.ToString();
+ }
+ return "";
+ }
+
+ public string GetFormulaR1C1(int row, int col) {
+ var v = _formulas.GetValue(row, col);
+ if (v is int i) {
+ var sf = _sharedFormulas[i];
+ return ExcelCellBase.TranslateToR1C1(
+ Formulas.RemoveDummyFunction(sf.Formula),
+ sf.StartRow,
+ sf.StartCol);
+ }
+ if (v != null) {
+ return ExcelCellBase.TranslateToR1C1(Formulas.RemoveDummyFunction(v.ToString()), row, col);
+ }
+ return "";
+ }
+
+ public string GetFormulaR1C1_V1(int row, int col) {
+ var v = _formulas.GetValue(row, col);
+ if (v is int i) {
+ var sf = _sharedFormulas[i];
+ return ExcelCellBase.TranslateToR1C1_V1(
+ Formulas.RemoveDummyFunction(sf.Formula),
+ sf.StartRow,
+ sf.StartCol);
+ }
+ if (v != null) {
+ return ExcelCellBase.TranslateToR1C1_V1(Formulas.RemoveDummyFunction(v.ToString()), row, col);
+ }
+ return "";
+ }
+
+ public bool IsArrayFormula(int row, int col) =>
+ _flags.GetFlagValue(row, col, CellFlags.ArrayFormula);
+
+ public string GetArrayFormulaAddress(int row, int col) {
+ var v = _formulas.GetValue(row, col);
+ if ((v is int i) && (_sharedFormulas[i].IsArray)) {
+ return _sharedFormulas[i].Address;
+ }
+ return "";
+ }
+
+ public int GetStyleId(int row, int col) {
+ int styleId = 0;
+ if (!_styles.Exists(row, col, ref styleId) && !_styles.Exists(row, 0, ref styleId)) {
+ styleId = _styles.GetValue(0, col);
+ }
+ return styleId;
+ }
+
+ /// <summary>
+ /// Get the ExcelColumn for column (span ColumnMin and ColumnMax)
+ /// </summary>
+ /// <param name="column"></param>
+ /// <returns></returns>
+ internal ExcelColumn GetColumn(int column) {
+ var c = _values.GetValue(0, column) as ExcelColumn;
+ if (c == null) {
+ int row = 0,
+ col = column;
+ if (_values.PrevCell(ref row, ref col)) {
+ c = _values.GetValue(0, col) as ExcelColumn;
+ if (c != null && c.ColumnMax >= column) {
+ return c;
+ }
+ return null;
+ }
+ }
+ return c;
+ }
+
+ public bool Equals(ExcelWorksheet x, ExcelWorksheet y) {
+ return x.Name == y.Name
+ && x.SheetID == y.SheetID
+ && x.WorksheetXml.OuterXml == y.WorksheetXml.OuterXml;
+ }
+
+ public int GetHashCode(ExcelWorksheet obj) {
+ return obj.WorksheetXml.OuterXml.GetHashCode();
+ }
+}
diff --git a/AppsheetEpplus/ExcelWorksheetView.cs b/AppsheetEpplus/ExcelWorksheetView.cs
new file mode 100644
index 0000000..9dde8f6
--- /dev/null
+++ b/AppsheetEpplus/ExcelWorksheetView.cs
@@ -0,0 +1,396 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan K�llman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Collections.Immutable;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Represents the different view states of the worksheet
+/// </summary>
+public class ExcelWorksheetView : XmlHelper {
+ /// <summary>
+ /// The worksheet panes after a freeze or split.
+ /// </summary>
+ public class ExcelWorksheetPanes : XmlHelper {
+ private XmlElement _selectionNode;
+
+ internal ExcelWorksheetPanes(XmlNamespaceManager ns, XmlNode topNode)
+ : base(ns, topNode) {
+ if (topNode.Name == "selection") {
+ _selectionNode = topNode as XmlElement;
+ }
+ }
+
+ private const string _activeCellPath = "@activeCell";
+
+ /// <summary>
+ /// Set the active cell. Must be set within the SelectedRange.
+ /// </summary>
+ public string ActiveCell {
+ get {
+ string address = GetXmlNodeString(_activeCellPath);
+ if (address == "") {
+ return "A1";
+ }
+ return address;
+ }
+ set {
+ int toCol,
+ toRow;
+ if (_selectionNode == null) {
+ CreateSelectionElement();
+ }
+ ExcelCellBase.GetRowColFromAddress(
+ value,
+ out var fromRow,
+ out var fromCol,
+ out toRow,
+ out toCol);
+ SetXmlNodeString(_activeCellPath, value);
+ if (((XmlElement)TopNode).GetAttribute("sqref") == "") {
+ SelectedRange = ExcelCellBase.GetAddress(fromRow, fromCol);
+ }
+ //TODO:Add fix for out of range here
+ }
+ }
+
+ private void CreateSelectionElement() {
+ _selectionNode = TopNode.OwnerDocument.CreateElement("selection", ExcelPackage._schemaMain);
+ TopNode.AppendChild(_selectionNode);
+ TopNode = _selectionNode;
+ }
+
+ private const string _selectionRangePath = "@sqref";
+
+ /// <summary>
+ /// Selected Cells.Used in combination with ActiveCell
+ /// </summary>
+ public string SelectedRange {
+ get {
+ string address = GetXmlNodeString(_selectionRangePath);
+ if (address == "") {
+ return "A1";
+ }
+ return address;
+ }
+ set {
+ int toCol,
+ toRow;
+ if (_selectionNode == null) {
+ CreateSelectionElement();
+ }
+ ExcelCellBase.GetRowColFromAddress(
+ value,
+ out var fromRow,
+ out var fromCol,
+ out toRow,
+ out toCol);
+ SetXmlNodeString(_selectionRangePath, value);
+ if (((XmlElement)TopNode).GetAttribute("activeCell") == "") {
+ ActiveCell = ExcelCellBase.GetAddress(fromRow, fromCol);
+ }
+ //TODO:Add fix for out of range here
+ }
+ }
+ }
+
+ private readonly ExcelWorksheet _worksheet;
+
+ protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
+ "sheetViews",
+ "sheetView",
+ "pane",
+ "selection",
+ ];
+
+ /// <summary>
+ /// Creates a new ExcelWorksheetView which provides access to all the view states of the worksheet.
+ /// </summary>
+ /// <param name="ns"></param>
+ /// <param name="node"></param>
+ /// <param name="xlWorksheet"></param>
+ internal ExcelWorksheetView(XmlNamespaceManager ns, XmlNode node, ExcelWorksheet xlWorksheet)
+ : base(ns, node) {
+ _worksheet = xlWorksheet;
+ Panes = LoadPanes();
+ }
+
+ private ExcelWorksheetPanes[] LoadPanes() {
+ XmlNodeList nodes = TopNode.SelectNodes("//d:selection", NameSpaceManager);
+ if (nodes.Count == 0) {
+ return [new ExcelWorksheetPanes(NameSpaceManager, TopNode)];
+ }
+ ExcelWorksheetPanes[] panes = new ExcelWorksheetPanes[nodes.Count];
+ int i = 0;
+ foreach (XmlElement elem in nodes) {
+ panes[i++] = new(NameSpaceManager, elem);
+ }
+ return panes;
+ }
+
+ /// <summary>
+ /// Returns a reference to the sheetView element
+ /// </summary>
+ protected internal XmlElement SheetViewElement => (XmlElement)TopNode;
+
+ /// <summary>
+ /// The active cell.
+ /// </summary>
+ public string ActiveCell {
+ get => Panes[Panes.GetUpperBound(0)].ActiveCell;
+ set => Panes[Panes.GetUpperBound(0)].ActiveCell = value;
+ }
+
+ /// <summary>
+ /// Selected Cells in the worksheet.Used in combination with ActiveCell
+ /// </summary>
+ public string SelectedRange {
+ get => Panes[Panes.GetUpperBound(0)].SelectedRange;
+ set => Panes[Panes.GetUpperBound(0)].SelectedRange = value;
+ }
+
+ /// <summary>
+ /// Indicates if the worksheet is selected within the workbook
+ /// </summary>
+ public bool TabSelected {
+ get => GetXmlNodeBool("@tabSelected");
+ set {
+ if (value) {
+ // // ensure no other worksheet has its tabSelected attribute set to 1
+ foreach (ExcelWorksheet sheet in _worksheet.Workbook.Worksheets) {
+ sheet.View.TabSelected = false;
+ }
+
+ SheetViewElement.SetAttribute("tabSelected", "1");
+ XmlElement bookView =
+ _worksheet.Workbook.WorkbookXml.SelectSingleNode(
+ "//d:workbookView",
+ _worksheet.NameSpaceManager) as XmlElement;
+ if (bookView != null) {
+ bookView.SetAttribute("activeTab", (_worksheet.PositionID - 1).ToString());
+ }
+ } else {
+ SetXmlNodeString("@tabSelected", "0");
+ }
+ }
+ }
+
+ /// <summary>
+ /// Sets the view mode of the worksheet to pagelayout
+ /// </summary>
+ public bool PageLayoutView {
+ get => GetXmlNodeString("@view") == "pageLayout";
+ set {
+ if (value) {
+ SetXmlNodeString("@view", "pageLayout");
+ } else {
+ SheetViewElement.RemoveAttribute("view");
+ }
+ }
+ }
+
+ /// <summary>
+ /// Sets the view mode of the worksheet to pagebreak
+ /// </summary>
+ public bool PageBreakView {
+ get => GetXmlNodeString("@view") == "pageBreakPreview";
+ set {
+ if (value) {
+ SetXmlNodeString("@view", "pageBreakPreview");
+ } else {
+ SheetViewElement.RemoveAttribute("view");
+ }
+ }
+ }
+
+ /// <summary>
+ /// Show gridlines in the worksheet
+ /// </summary>
+ public bool ShowGridLines {
+ get => GetXmlNodeBool("@showGridLines");
+ set => SetXmlNodeString("@showGridLines", value ? "1" : "0");
+ }
+
+ /// <summary>
+ /// Show the Column/Row headers (containg column letters and row numbers)
+ /// </summary>
+ public bool ShowHeaders {
+ get => GetXmlNodeBool("@showRowColHeaders");
+ set => SetXmlNodeString("@showRowColHeaders", value ? "1" : "0");
+ }
+
+ /// <summary>
+ /// Window zoom magnification for current view representing percent values.
+ /// </summary>
+ public int ZoomScale {
+ get => GetXmlNodeInt("@zoomScale");
+ set {
+ if (value < 10 || value > 400) {
+ throw new ArgumentOutOfRangeException("Zoome scale out of range (10-400)");
+ }
+ SetXmlNodeString("@zoomScale", value.ToString());
+ }
+ }
+
+ /// <summary>
+ /// Flag indicating whether the sheet is in 'right to left' display mode. When in this mode,Column A is on the far right, Column B ;is one column left of Column A, and so on. Also,information in cells is displayed in the Right to Left format.
+ /// </summary>
+ public bool RightToLeft {
+ get => GetXmlNodeBool("@rightToLeft");
+ set => SetXmlNodeString("@rightToLeft", value ? "1" : "0");
+ }
+
+ internal bool WindowProtection {
+ get => GetXmlNodeBool("@windowProtection", false);
+ set => SetXmlNodeBool("@windowProtection", value, false);
+ }
+
+ /// <summary>
+ /// Reference to the panes
+ /// </summary>
+ public ExcelWorksheetPanes[] Panes { get; internal set; }
+
+ private readonly string _paneNodePath = "d:pane";
+ private readonly string _selectionNodePath = "d:selection";
+
+ /// <summary>
+ /// Freeze the columns/rows to left and above the cell
+ /// </summary>
+ /// <param name="row"></param>
+ /// <param name="column"></param>
+ public void FreezePanes(int row, int column) {
+ //TODO:fix this method to handle splits as well.
+ if (row == 1 && column == 1) {
+ UnFreezePanes();
+ }
+ string sqRef = SelectedRange,
+ activeCell = ActiveCell;
+
+ XmlElement paneNode = TopNode.SelectSingleNode(_paneNodePath, NameSpaceManager) as XmlElement;
+ if (paneNode == null) {
+ CreateNode(_paneNodePath);
+ paneNode = TopNode.SelectSingleNode(_paneNodePath, NameSpaceManager) as XmlElement;
+ }
+ paneNode.RemoveAll(); //Clear all attributes
+ if (column > 1) {
+ paneNode.SetAttribute("xSplit", (column - 1).ToString());
+ }
+ if (row > 1) {
+ paneNode.SetAttribute("ySplit", (row - 1).ToString());
+ }
+ paneNode.SetAttribute("topLeftCell", ExcelCellBase.GetAddress(row, column));
+ paneNode.SetAttribute("state", "frozen");
+
+ RemoveSelection();
+
+ if (row > 1 && column == 1) {
+ paneNode.SetAttribute("activePane", "bottomLeft");
+ XmlElement sel = TopNode.OwnerDocument.CreateElement("selection", ExcelPackage._schemaMain);
+ sel.SetAttribute("pane", "bottomLeft");
+ if (activeCell != "") {
+ sel.SetAttribute("activeCell", activeCell);
+ }
+ if (sqRef != "") {
+ sel.SetAttribute("sqref", sqRef);
+ }
+ sel.SetAttribute("sqref", sqRef);
+ TopNode.InsertAfter(sel, paneNode);
+ } else if (column > 1 && row == 1) {
+ paneNode.SetAttribute("activePane", "topRight");
+ XmlElement sel = TopNode.OwnerDocument.CreateElement("selection", ExcelPackage._schemaMain);
+ sel.SetAttribute("pane", "topRight");
+ if (activeCell != "") {
+ sel.SetAttribute("activeCell", activeCell);
+ }
+ if (sqRef != "") {
+ sel.SetAttribute("sqref", sqRef);
+ }
+ TopNode.InsertAfter(sel, paneNode);
+ } else {
+ paneNode.SetAttribute("activePane", "bottomRight");
+ XmlElement sel1 = TopNode.OwnerDocument.CreateElement("selection", ExcelPackage._schemaMain);
+ sel1.SetAttribute("pane", "topRight");
+ string cell = ExcelCellBase.GetAddress(1, column);
+ sel1.SetAttribute("activeCell", cell);
+ sel1.SetAttribute("sqref", cell);
+ paneNode.ParentNode.InsertAfter(sel1, paneNode);
+
+ XmlElement sel2 = TopNode.OwnerDocument.CreateElement("selection", ExcelPackage._schemaMain);
+ cell = ExcelCellBase.GetAddress(row, 1);
+ sel2.SetAttribute("pane", "bottomLeft");
+ sel2.SetAttribute("activeCell", cell);
+ sel2.SetAttribute("sqref", cell);
+ sel1.ParentNode.InsertAfter(sel2, sel1);
+
+ XmlElement sel3 = TopNode.OwnerDocument.CreateElement("selection", ExcelPackage._schemaMain);
+ sel3.SetAttribute("pane", "bottomRight");
+ if (activeCell != "") {
+ sel3.SetAttribute("activeCell", activeCell);
+ }
+ if (sqRef != "") {
+ sel3.SetAttribute("sqref", sqRef);
+ }
+ sel2.ParentNode.InsertAfter(sel3, sel2);
+ }
+ Panes = LoadPanes();
+ }
+
+ private void RemoveSelection() {
+ //Find selection nodes and remove them
+ XmlNodeList selections = TopNode.SelectNodes(_selectionNodePath, NameSpaceManager);
+ foreach (XmlNode sel in selections) {
+ sel.ParentNode.RemoveChild(sel);
+ }
+ }
+
+ /// <summary>
+ /// Unlock all rows and columns to scroll freely
+ /// /// </summary>
+ public void UnFreezePanes() {
+ string sqRef = SelectedRange,
+ activeCell = ActiveCell;
+
+ XmlElement paneNode = TopNode.SelectSingleNode(_paneNodePath, NameSpaceManager) as XmlElement;
+ if (paneNode != null) {
+ paneNode.ParentNode.RemoveChild(paneNode);
+ }
+ RemoveSelection();
+
+ Panes = LoadPanes();
+
+ SelectedRange = sqRef;
+ ActiveCell = activeCell;
+ }
+}
diff --git a/AppsheetEpplus/ExcelWorksheets.cs b/AppsheetEpplus/ExcelWorksheets.cs
new file mode 100644
index 0000000..bb4e672
--- /dev/null
+++ b/AppsheetEpplus/ExcelWorksheets.cs
@@ -0,0 +1,335 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// The collection of worksheets for the workbook
+/// </summary>
+public class ExcelWorksheets : XmlHelper, IEnumerable<ExcelWorksheet> {
+ private readonly ExcelPackage _pck;
+ private readonly ExcelWorkbook _workbook;
+ private Dictionary<int, ExcelWorksheet> _worksheets = new();
+ private readonly XmlNamespaceManager _namespaceManager;
+
+ internal ExcelWorksheets(
+ ExcelPackage pck,
+ ExcelWorkbook workbook,
+ XmlNamespaceManager nsm,
+ XmlNode topNode)
+ : base(nsm, topNode) {
+ _pck = pck;
+ _workbook = workbook;
+ _namespaceManager = nsm;
+ int positionId = 1;
+
+ foreach (XmlNode sheetNode in topNode.ChildNodes) {
+ if (sheetNode.NodeType == XmlNodeType.Element) {
+ string name = sheetNode.Attributes["name"].Value;
+ //Get the relationship id
+ string relId = sheetNode.Attributes["r:id"].Value;
+ int sheetId = Convert.ToInt32(sheetNode.Attributes["sheetId"].Value);
+
+ //Hidden property
+ eWorkSheetHidden hidden = eWorkSheetHidden.Visible;
+ XmlNode attr = sheetNode.Attributes["state"];
+ if (attr != null) {
+ hidden = TranslateHidden(attr.Value);
+ }
+
+ var sheetRelation = _workbook.Part.GetRelationship(relId);
+ Uri uriWorksheet = UriHelper.ResolvePartUri(
+ ExcelWorkbook.WorkbookUri,
+ sheetRelation.TargetUri);
+
+ //add the worksheet
+ if (sheetRelation.RelationshipType.EndsWith("chartsheet")) {
+ _worksheets.Add(
+ positionId,
+ new ExcelChartsheet(
+ _namespaceManager,
+ pck,
+ _workbook,
+ uriWorksheet,
+ name,
+ sheetId,
+ positionId,
+ hidden));
+ } else {
+ _worksheets.Add(
+ positionId,
+ new(
+ _namespaceManager,
+ pck,
+ _workbook,
+ uriWorksheet,
+ name,
+ sheetId,
+ positionId,
+ hidden));
+ }
+ positionId++;
+ }
+ }
+ }
+
+ private eWorkSheetHidden TranslateHidden(string value) {
+ switch (value) {
+ case "hidden":
+ return eWorkSheetHidden.Hidden;
+ case "veryHidden":
+ return eWorkSheetHidden.VeryHidden;
+ default:
+ return eWorkSheetHidden.Visible;
+ }
+ }
+
+ /// <summary>
+ /// Returns the number of worksheets in the workbook
+ /// </summary>
+ public int Count => (_worksheets.Count);
+
+ private const string _errDupWorksheet =
+ "A worksheet with this name already exists in the workbook";
+ internal const string _worksheetContentType =
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml";
+
+ /// <summary>
+ /// Foreach support
+ /// </summary>
+ /// <returns>An enumerator</returns>
+ public IEnumerator<ExcelWorksheet> GetEnumerator() {
+ return (_worksheets.Values.GetEnumerator());
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return (_worksheets.Values.GetEnumerator());
+ }
+
+ /// <summary>
+ /// Adds a new blank worksheet.
+ /// </summary>
+ /// <param name="name">The name of the workbook</param>
+ public ExcelWorksheet Add(string name) {
+ name = ValidateFixSheetName(name);
+ if (GetByName(name) != null) {
+ throw (new InvalidOperationException(_errDupWorksheet + " : " + name));
+ }
+ GetSheetUri(ref name, out var sheetId, out var uriWorksheet, false);
+
+ // Create the new worksheet
+ var rel = _pck.CreateXmlDocument(
+ uriWorksheet,
+ _worksheetContentType,
+ ExcelPackage._schemaRelationships + "/worksheet",
+ CreateNewWorksheet(false));
+
+ // Add worksheet to the workbook
+ XmlElement worksheetNode = _workbook.WorkbookXml.CreateElement(
+ "sheet",
+ ExcelPackage._schemaMain);
+ worksheetNode.SetAttribute("name", name);
+ worksheetNode.SetAttribute("sheetId", sheetId.ToString());
+ worksheetNode.SetAttribute("id", ExcelPackage._schemaRelationships, rel.Id);
+ TopNode.AppendChild(worksheetNode);
+
+ int positionId = _worksheets.Count + 1;
+
+ ExcelWorksheet worksheet = new(
+ _namespaceManager,
+ _pck,
+ _workbook,
+ uriWorksheet,
+ name,
+ sheetId,
+ positionId,
+ eWorkSheetHidden.Visible);
+
+ _worksheets.Add(positionId, worksheet);
+ return worksheet;
+ }
+
+ private void GetSheetUri(ref string name, out int sheetId, out Uri uriWorksheet, bool isChart) {
+ name = ValidateFixSheetName(name);
+
+ //First find maximum existing sheetID
+ sheetId = 0;
+ foreach (var ws in this) {
+ if (ws.SheetID > sheetId) {
+ sheetId = ws.SheetID;
+ }
+ }
+ // we now have the max existing values, so add one
+ sheetId++;
+
+ // add the new worksheet to the package
+ if (isChart) {
+ uriWorksheet = new("/xl/chartsheets/chartsheet" + sheetId + ".xml", UriKind.Relative);
+ } else {
+ uriWorksheet = new("/xl/worksheets/sheet" + sheetId + ".xml", UriKind.Relative);
+ }
+ }
+
+ internal string ValidateFixSheetName(string name) {
+ //remove invalid characters
+ if (ValidateName(name)) {
+ if (name.IndexOf(':') > -1) {
+ name = name.Replace(":", " ");
+ }
+ if (name.IndexOf('/') > -1) {
+ name = name.Replace("/", " ");
+ }
+ if (name.IndexOf('\\') > -1) {
+ name = name.Replace("\\", " ");
+ }
+ if (name.IndexOf('?') > -1) {
+ name = name.Replace("?", " ");
+ }
+ if (name.IndexOf('[') > -1) {
+ name = name.Replace("[", " ");
+ }
+ if (name.IndexOf(']') > -1) {
+ name = name.Replace("]", " ");
+ }
+ }
+
+ if (name.Trim() == "") {
+ throw new ArgumentException("The worksheet can not have an empty name");
+ }
+ if (name.Length > 31) {
+ name = name.Substring(0, 31); //A sheet can have max 31 char's
+ }
+ return name;
+ }
+
+ /// <summary>
+ /// Validate the sheetname
+ /// </summary>
+ /// <param name="name">The Name</param>
+ /// <returns>True if valid</returns>
+ private bool ValidateName(string name) {
+ return Regex.IsMatch(name, @":|\?|/|\\|\[|\]");
+ }
+
+ /// <summary>
+ /// Creates the XML document representing a new empty worksheet
+ /// </summary>
+ /// <returns></returns>
+ internal XmlDocument CreateNewWorksheet(bool isChart) {
+ XmlDocument xmlDoc = new XmlDocument();
+ XmlElement elemWs = xmlDoc.CreateElement(
+ isChart ? "chartsheet" : "worksheet",
+ ExcelPackage._schemaMain);
+ elemWs.SetAttribute("xmlns:r", ExcelPackage._schemaRelationships);
+ xmlDoc.AppendChild(elemWs);
+
+ if (isChart) {
+ XmlElement elemSheetPr = xmlDoc.CreateElement("sheetPr", ExcelPackage._schemaMain);
+ elemWs.AppendChild(elemSheetPr);
+
+ XmlElement elemSheetViews = xmlDoc.CreateElement("sheetViews", ExcelPackage._schemaMain);
+ elemWs.AppendChild(elemSheetViews);
+
+ XmlElement elemSheetView = xmlDoc.CreateElement("sheetView", ExcelPackage._schemaMain);
+ elemSheetView.SetAttribute("workbookViewId", "0");
+ elemSheetView.SetAttribute("zoomToFit", "1");
+
+ elemSheetViews.AppendChild(elemSheetView);
+ } else {
+ XmlElement elemSheetViews = xmlDoc.CreateElement("sheetViews", ExcelPackage._schemaMain);
+ elemWs.AppendChild(elemSheetViews);
+
+ XmlElement elemSheetView = xmlDoc.CreateElement("sheetView", ExcelPackage._schemaMain);
+ elemSheetView.SetAttribute("workbookViewId", "0");
+ elemSheetViews.AppendChild(elemSheetView);
+
+ XmlElement elemSheetFormatPr = xmlDoc.CreateElement(
+ "sheetFormatPr",
+ ExcelPackage._schemaMain);
+ elemSheetFormatPr.SetAttribute("defaultRowHeight", "15");
+ elemWs.AppendChild(elemSheetFormatPr);
+
+ XmlElement elemSheetData = xmlDoc.CreateElement("sheetData", ExcelPackage._schemaMain);
+ elemWs.AppendChild(elemSheetData);
+ }
+ return xmlDoc;
+ }
+
+ /// <summary>
+ /// Returns the worksheet at the specified position.
+ /// </summary>
+ /// <param name="positionId">The position of the worksheet. 1-base</param>
+ /// <returns></returns>
+ public ExcelWorksheet this[int positionId] {
+ get {
+ if (_worksheets.ContainsKey(positionId)) {
+ return _worksheets[positionId];
+ }
+ throw (new IndexOutOfRangeException("Worksheet position out of range."));
+ }
+ }
+
+ /// <summary>
+ /// Returns the worksheet matching the specified name
+ /// </summary>
+ /// <param name="name">The name of the worksheet</param>
+ /// <returns></returns>
+ public ExcelWorksheet this[string name] => GetByName(name);
+
+ internal ExcelWorksheet GetBySheetId(int localSheetId) {
+ foreach (ExcelWorksheet ws in this) {
+ if (ws.SheetID == localSheetId) {
+ return ws;
+ }
+ }
+ return null;
+ }
+
+ private ExcelWorksheet GetByName(string name) {
+ if (string.IsNullOrEmpty(name)) {
+ return null;
+ }
+ ExcelWorksheet xlWorksheet = null;
+ foreach (ExcelWorksheet worksheet in _worksheets.Values) {
+ if (worksheet.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)) {
+ xlWorksheet = worksheet;
+ }
+ }
+ return (xlWorksheet);
+ }
+} // end class Worksheets
diff --git a/AppsheetEpplus/FormulaParsing/CalculateExtentions.cs b/AppsheetEpplus/FormulaParsing/CalculateExtentions.cs
new file mode 100644
index 0000000..0d6c5b0
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/CalculateExtentions.cs
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * 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 2012-03-04
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+public static class CalculationExtension {
+ public static void Calculate(this ExcelWorkbook workbook) {
+ Calculate(
+ workbook,
+ new() {
+ AllowCirculareReferences = false,
+ });
+ }
+
+ public static void Calculate(this ExcelWorkbook workbook, ExcelCalculationOption options) {
+ Init(workbook);
+
+ var dc = DependencyChainFactory.Create(workbook, options);
+ workbook.FormulaParser.InitNewCalc();
+ CalcChain(workbook, workbook.FormulaParser, dc);
+ }
+
+ public static void Calculate(this ExcelWorksheet worksheet) {
+ Calculate(worksheet, new ExcelCalculationOption());
+ }
+
+ public static void Calculate(this ExcelWorksheet worksheet, ExcelCalculationOption options) {
+ Init(worksheet.Workbook);
+ //worksheet.Workbook._formulaParser = null; TODO:Cant reset. Don't work with userdefined or overrided worksheet functions
+ var dc = DependencyChainFactory.Create(worksheet, options);
+
+ // Display Calc Chain to determine why formula calculation is taking so long.
+ // Uncomment the following line to display the Calc Chain.
+ // DisplayCalcChain(worksheet, dc);
+
+ var parser = worksheet.Workbook.FormulaParser;
+ parser.InitNewCalc();
+ CalcChain(worksheet.Workbook, parser, dc);
+ }
+
+ public static void Calculate(this ExcelRangeBase range) {
+ Calculate(range, new());
+ }
+
+ public static void Calculate(this ExcelRangeBase range, ExcelCalculationOption options) {
+ Init(range._workbook);
+ var parser = range._workbook.FormulaParser;
+ parser.InitNewCalc();
+ var dc = DependencyChainFactory.Create(range, options);
+ CalcChain(range._workbook, parser, dc);
+ }
+
+ public static object Calculate(this ExcelWorksheet worksheet, string formula) {
+ return Calculate(worksheet, formula, new());
+ }
+
+ public static object Calculate(
+ this ExcelWorksheet worksheet,
+ string formula,
+ ExcelCalculationOption options) {
+ try {
+ worksheet.CheckSheetType();
+ if (string.IsNullOrEmpty(formula.Trim())) {
+ return null;
+ }
+ Init(worksheet.Workbook);
+ var parser = worksheet.Workbook.FormulaParser;
+ parser.InitNewCalc();
+ if (formula[0] == '=') {
+ formula = formula.Substring(1); //Remove any starting equal sign
+ }
+ var dc = DependencyChainFactory.Create(worksheet, formula, options);
+ var f = dc.list[0];
+ dc.CalcOrder.RemoveAt(dc.CalcOrder.Count - 1);
+
+ CalcChain(worksheet.Workbook, parser, dc);
+
+ return parser.ParseCell(f.Tokens, worksheet.Name, -1, -1);
+ } catch (Exception ex) {
+ return new ExcelErrorValueException(ex.Message, ExcelErrorValue.Create(eErrorType.Value));
+ }
+ }
+
+ private static void CalcChain(ExcelWorkbook wb, FormulaParser parser, DependencyChain dc) {
+ foreach (var ix in dc.CalcOrder) {
+ var item = dc.list[ix];
+ try {
+ var ws = wb.Worksheets.GetBySheetId(item.SheetID);
+ var v = parser.ParseCell(item.Tokens, ws == null ? "" : ws.Name, item.Row, item.Column);
+ SetValue(wb, item, v);
+ } catch (FunctionException) {
+ // Excel function is not supported by EPPlus
+ throw;
+ } catch (FormatException) {
+ throw;
+ } catch (Exception) {
+ var error = ExcelErrorValue.Parse(ExcelErrorValue.Values.Value);
+ SetValue(wb, item, error);
+ }
+ }
+ }
+
+ private static void Init(ExcelWorkbook workbook) {
+ workbook._formulaTokens = new();
+ ;
+ foreach (var ws in workbook.Worksheets) {
+ if (!(ws is ExcelChartsheet)) {
+ ws._formulaTokens = new();
+ }
+ }
+ }
+
+ private static void SetValue(ExcelWorkbook workbook, FormulaCell item, object v) {
+ if (item.Column == 0) {
+ if (item.SheetID <= 0) {
+ workbook.Names[item.Row].NameValue = v;
+ } else {
+ var sh = workbook.Worksheets.GetBySheetId(item.SheetID);
+ sh.Names[item.Row].NameValue = v;
+ }
+ } else {
+ var sheet = workbook.Worksheets.GetBySheetId(item.SheetID);
+ sheet._values.SetValue(item.Row, item.Column, v);
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/DependencyChain/DependencyChain.cs b/AppsheetEpplus/FormulaParsing/DependencyChain/DependencyChain.cs
new file mode 100644
index 0000000..14545d8
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/DependencyChain/DependencyChain.cs
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+internal class DependencyChain {
+ internal List<FormulaCell> list = new();
+ internal Dictionary<ulong, int> index = new();
+ internal List<int> CalcOrder = new();
+
+ internal void Add(FormulaCell f) {
+ list.Add(f);
+ f.Index = list.Count - 1;
+ index.Add(ExcelCellBase.GetCellId(f.SheetID, f.Row, f.Column), f.Index);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/DependencyChain/DependenyChainFactory.cs b/AppsheetEpplus/FormulaParsing/DependencyChain/DependenyChainFactory.cs
new file mode 100644
index 0000000..6deb844
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/DependencyChain/DependenyChainFactory.cs
@@ -0,0 +1,371 @@
+/*******************************************************************************
+ * 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 2012-03-04
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+internal static class DependencyChainFactory {
+ internal static DependencyChain Create(ExcelWorkbook wb, ExcelCalculationOption options) {
+ var depChain = new DependencyChain();
+ foreach (var ws in wb.Worksheets) {
+ if (!(ws is ExcelChartsheet)) {
+ GetChain(depChain, wb.FormulaParser.Lexer, ws.Cells, options);
+ GetWorksheetNames(ws, depChain, options);
+ }
+ }
+ foreach (var name in wb.Names) {
+ if (name.NameValue == null) {
+ GetChain(depChain, wb.FormulaParser.Lexer, name, options);
+ }
+ }
+ return depChain;
+ }
+
+ internal static DependencyChain Create(ExcelWorksheet ws, ExcelCalculationOption options) {
+ ws.CheckSheetType();
+ var depChain = new DependencyChain();
+
+ GetChain(depChain, ws.Workbook.FormulaParser.Lexer, ws.Cells, options);
+
+ GetWorksheetNames(ws, depChain, options);
+
+ return depChain;
+ }
+
+ internal static DependencyChain Create(
+ ExcelWorksheet ws,
+ string formula,
+ ExcelCalculationOption options) {
+ ws.CheckSheetType();
+ var depChain = new DependencyChain();
+
+ GetChain(depChain, ws.Workbook.FormulaParser.Lexer, ws, formula, options);
+
+ return depChain;
+ }
+
+ private static void GetWorksheetNames(
+ ExcelWorksheet ws,
+ DependencyChain depChain,
+ ExcelCalculationOption options) {
+ foreach (var name in ws.Names) {
+ if (!string.IsNullOrEmpty(name.NameFormula)) {
+ GetChain(depChain, ws.Workbook.FormulaParser.Lexer, name, options);
+ }
+ }
+ }
+
+ internal static DependencyChain Create(ExcelRangeBase range, ExcelCalculationOption options) {
+ var depChain = new DependencyChain();
+
+ GetChain(depChain, range.Worksheet.Workbook.FormulaParser.Lexer, range, options);
+
+ return depChain;
+ }
+
+ private static void GetChain(
+ DependencyChain depChain,
+ ILexer lexer,
+ ExcelNamedRange name,
+ ExcelCalculationOption options) {
+ var ws = name.Worksheet;
+ var id = ExcelCellBase.GetCellId(ws?.SheetID ?? 0, name.Index, 0);
+ if (!depChain.index.ContainsKey(id)) {
+ var f = new FormulaCell {
+ SheetID = ws?.SheetID ?? 0,
+ Row = name.Index,
+ Column = 0,
+ Formula = name.NameFormula,
+ };
+ if (!string.IsNullOrEmpty(f.Formula)) {
+ f.Tokens = lexer.Tokenize(f.Formula, ws?.Name).ToList();
+ if (ws == null) {
+ name._workbook._formulaTokens.SetValue(name.Index, 0, f.Tokens);
+ } else {
+ ws._formulaTokens.SetValue(name.Index, 0, f.Tokens);
+ }
+ depChain.Add(f);
+ FollowChain(depChain, lexer, name._workbook, ws, f, options);
+ }
+ }
+ }
+
+ private static void GetChain(
+ DependencyChain depChain,
+ ILexer lexer,
+ ExcelWorksheet ws,
+ string formula,
+ ExcelCalculationOption options) {
+ var f = new FormulaCell {
+ SheetID = ws.SheetID,
+ Row = -1,
+ Column = -1,
+ };
+ f.Formula = formula;
+ if (!string.IsNullOrEmpty(f.Formula)) {
+ f.Tokens = lexer.Tokenize(f.Formula, ws.Name).ToList();
+ depChain.Add(f);
+ FollowChain(depChain, lexer, ws.Workbook, ws, f, options);
+ }
+ }
+
+ private static void GetChain(
+ DependencyChain depChain,
+ ILexer lexer,
+ ExcelRangeBase range,
+ ExcelCalculationOption options) {
+ var ws = range.Worksheet;
+ var fs = new CellsStoreEnumerator<object>(
+ ws._formulas,
+ range.Start.Row,
+ range.Start.Column,
+ range.End.Row,
+ range.End.Column);
+ while (fs.Next()) {
+ if (fs.Value == null || fs.Value.ToString().Trim() == "") {
+ continue;
+ }
+ var id = ExcelCellBase.GetCellId(ws.SheetID, fs.Row, fs.Column);
+ if (!depChain.index.ContainsKey(id)) {
+ var f = new FormulaCell {
+ SheetID = ws.SheetID,
+ Row = fs.Row,
+ Column = fs.Column,
+ };
+ if (fs.Value is int value) {
+ f.Formula = ws._sharedFormulas[value].GetFormula(fs.Row, fs.Column, ws.Name);
+ } else {
+ f.Formula = fs.Value.ToString();
+ }
+ if (!string.IsNullOrEmpty(f.Formula)) {
+ f.Tokens = lexer.Tokenize(f.Formula, range.Worksheet.Name).ToList();
+ ws._formulaTokens.SetValue(fs.Row, fs.Column, f.Tokens);
+ depChain.Add(f);
+ FollowChain(depChain, lexer, ws.Workbook, ws, f, options);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// This method follows the calculation chain to get the order of the calculation
+ /// Goto (!) is used internally to prevent stackoverflow on extremly larget dependency trees (that is, many recursive formulas).
+ /// </summary>
+ /// <param name="depChain">The dependency chain object</param>
+ /// <param name="lexer">The formula tokenizer</param>
+ /// <param name="wb">The workbook where the formula comes from</param>
+ /// <param name="ws">The worksheet where the formula comes from</param>
+ /// <param name="f">The cell function object</param>
+ /// <param name="options">Calcultaiton options</param>
+ private static void FollowChain(
+ DependencyChain depChain,
+ ILexer lexer,
+ ExcelWorkbook wb,
+ ExcelWorksheet ws,
+ FormulaCell f,
+ ExcelCalculationOption options) {
+ Stack<FormulaCell> stack = new Stack<FormulaCell>();
+ iterateToken:
+ while (f.tokenIx < f.Tokens.Count) {
+ var t = f.Tokens[f.tokenIx];
+ if (t.TokenType == TokenType.ExcelAddress) {
+ var adr = new ExcelFormulaAddress(t.Value);
+ if (adr.Table != null) {
+ adr.SetRcFromTable(ws.Workbook, new(f.Row, f.Column, f.Row, f.Column));
+ }
+
+ if (adr.WorkSheet == null
+ && adr.Collide(new(f.Row, f.Column, f.Row, f.Column))
+ != ExcelAddressBase.eAddressCollition.No) {
+ throw (new CircularReferenceException(
+ string.Format(
+ "Circular Reference in cell {0}",
+ ExcelCellBase.GetAddress(f.Row, f.Column))));
+ }
+
+ if (adr._fromRow > 0 && adr._fromCol > 0) {
+ if (string.IsNullOrEmpty(adr.WorkSheet)) {
+ if (f.ws == null) {
+ f.ws = ws;
+ } else if (f.ws.SheetID != f.SheetID) {
+ f.ws = wb.Worksheets.GetBySheetId(f.SheetID);
+ }
+ } else {
+ f.ws = wb.Worksheets[adr.WorkSheet];
+ }
+
+ if (f.ws != null) {
+ f.iterator = new(
+ f.ws._formulas,
+ adr.Start.Row,
+ adr.Start.Column,
+ adr.End.Row,
+ adr.End.Column);
+ goto iterateCells;
+ }
+ }
+ } else if (t.TokenType == TokenType.NameValue) {
+ string adrWb;
+ ExcelNamedRange name;
+ ExcelAddressBase.SplitAddress(
+ t.Value,
+ out adrWb,
+ out var adrWs,
+ out var adrName,
+ f.ws == null ? "" : f.ws.Name);
+ if (!string.IsNullOrEmpty(adrWs)) {
+ if (f.ws == null) {
+ f.ws = wb.Worksheets[adrWs];
+ }
+ if (f.ws.Names.ContainsKey(t.Value)) {
+ name = f.ws.Names[adrName];
+ } else if (wb.Names.ContainsKey(adrName)) {
+ name = wb.Names[adrName];
+ } else {
+ name = null;
+ }
+ if (name != null) {
+ f.ws = name.Worksheet;
+ }
+ } else if (wb.Names.ContainsKey(adrName)) {
+ name = wb.Names[t.Value];
+ if (string.IsNullOrEmpty(adrWs)) {
+ f.ws = name.Worksheet;
+ }
+ } else {
+ name = null;
+ }
+
+ if (name != null) {
+ if (string.IsNullOrEmpty(name.NameFormula)) {
+ if (name.NameValue == null) {
+ f.iterator = new(
+ f.ws._formulas,
+ name.Start.Row,
+ name.Start.Column,
+ name.End.Row,
+ name.End.Column);
+ goto iterateCells;
+ }
+ } else {
+ var id = ExcelCellBase.GetCellId(name.LocalSheetId, name.Index, 0);
+
+ if (!depChain.index.ContainsKey(id)) {
+ var rf = new FormulaCell {
+ SheetID = name.LocalSheetId,
+ Row = name.Index,
+ Column = 0,
+ };
+ rf.Formula = name.NameFormula;
+ rf.Tokens =
+ name.LocalSheetId == -1
+ ? lexer.Tokenize(rf.Formula).ToList()
+ : lexer
+ .Tokenize(rf.Formula, wb.Worksheets.GetBySheetId(name.LocalSheetId).Name)
+ .ToList();
+
+ depChain.Add(rf);
+ stack.Push(f);
+ f = rf;
+ goto iterateToken;
+ }
+ if (stack.Count > 0) {
+ //Check for circular references
+ foreach (var par in stack) {
+ if (ExcelCellBase.GetCellId(par.SheetID, par.Row, par.Column) == id) {
+ throw (new CircularReferenceException(
+ string.Format("Circular Reference in name {0}", name.Name)));
+ }
+ }
+ }
+ }
+ }
+ }
+ f.tokenIx++;
+ }
+ depChain.CalcOrder.Add(f.Index);
+ if (stack.Count > 0) {
+ f = stack.Pop();
+ goto iterateCells;
+ }
+ return;
+ iterateCells:
+
+ while (f.iterator != null && f.iterator.Next()) {
+ var v = f.iterator.Value;
+ if (v == null || v.ToString().Trim() == "") {
+ continue;
+ }
+ var id = ExcelCellBase.GetCellId(f.ws.SheetID, f.iterator.Row, f.iterator.Column);
+ if (!depChain.index.ContainsKey(id)) {
+ var rf = new FormulaCell {
+ SheetID = f.ws.SheetID,
+ Row = f.iterator.Row,
+ Column = f.iterator.Column,
+ };
+ if (f.iterator.Value is int) {
+ rf.Formula = f.ws._sharedFormulas[(int)v]
+ .GetFormula(f.iterator.Row, f.iterator.Column, ws.Name);
+ } else {
+ rf.Formula = v.ToString();
+ }
+ rf.ws = f.ws;
+ rf.Tokens = lexer.Tokenize(rf.Formula, f.ws.Name).ToList();
+ ws._formulaTokens.SetValue(rf.Row, rf.Column, rf.Tokens);
+ depChain.Add(rf);
+ stack.Push(f);
+ f = rf;
+ goto iterateToken;
+ }
+ if (stack.Count > 0) {
+ //Check for circular references
+ foreach (var par in stack) {
+ if (ExcelCellBase.GetCellId(par.ws.SheetID, par.iterator.Row, par.iterator.Column)
+ == id) {
+ if (options.AllowCirculareReferences == false) {
+ throw (new CircularReferenceException(
+ string.Format(
+ "Circular Reference in cell {0}!{1}",
+ par.ws.Name,
+ ExcelCellBase.GetAddress(f.Row, f.Column))));
+ }
+ f = stack.Pop();
+ goto iterateCells;
+ }
+ }
+ }
+ }
+ f.tokenIx++;
+ goto iterateToken;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/DependencyChain/FormulaCell.cs b/AppsheetEpplus/FormulaParsing/DependencyChain/FormulaCell.cs
new file mode 100644
index 0000000..50ceb10
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/DependencyChain/FormulaCell.cs
@@ -0,0 +1,47 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+internal class FormulaCell {
+ internal int Index { get; set; }
+
+ internal int SheetID { get; set; }
+
+ internal int Row { get; set; }
+
+ internal int Column { get; set; }
+
+ internal string Formula { get; set; }
+
+ internal List<Token> Tokens { get; set; }
+
+ internal int tokenIx = 0;
+ internal int addressIx = 0;
+ internal CellsStoreEnumerator<object> iterator;
+ internal ExcelWorksheet ws;
+}
diff --git a/AppsheetEpplus/FormulaParsing/EpplusExcelDataProvider.cs b/AppsheetEpplus/FormulaParsing/EpplusExcelDataProvider.cs
new file mode 100644
index 0000000..b6feb98
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/EpplusExcelDataProvider.cs
@@ -0,0 +1,355 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class EpplusExcelDataProvider : ExcelDataProvider {
+ public class RangeInfo : IRangeInfo {
+ internal ExcelWorksheet _ws;
+ private readonly CellsStoreEnumerator<object> _values;
+ private readonly int _fromRow;
+ private readonly int _toRow;
+ private readonly int _fromCol;
+ private readonly int _toCol;
+ private int _cellCount;
+ private readonly ExcelAddressBase _address;
+ private readonly ICellInfo _cell;
+
+ public RangeInfo(ExcelWorksheet ws, int fromRow, int fromCol, int toRow, int toCol) {
+ _ws = ws;
+ _fromRow = fromRow;
+ _fromCol = fromCol;
+ _toRow = toRow;
+ _toCol = toCol;
+ _address = new(_fromRow, _fromCol, _toRow, _toCol);
+ _address._ws = ws.Name;
+ _values = new(ws._values, _fromRow, _fromCol, _toRow, _toCol);
+ _cell = new CellInfo(_ws, _values);
+ }
+
+ public int GetNCells() {
+ return ((_toRow - _fromRow) + 1) * ((_toCol - _fromCol) + 1);
+ }
+
+ public bool IsEmpty {
+ get {
+ if (_cellCount > 0) {
+ return false;
+ }
+ if (_values.Next()) {
+ _values.Reset();
+ return false;
+ }
+ return true;
+ }
+ }
+
+ public bool IsMulti {
+ get {
+ if (_cellCount == 0) {
+ if (_values.Next() && _values.Next()) {
+ _values.Reset();
+ return true;
+ }
+ _values.Reset();
+ return false;
+ }
+ if (_cellCount > 1) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ public ICellInfo Current => _cell;
+
+ public ExcelWorksheet Worksheet => _ws;
+
+ public void Dispose() {}
+
+ object IEnumerator.Current => this;
+
+ public bool MoveNext() {
+ _cellCount++;
+ return _values.MoveNext();
+ }
+
+ public void Reset() {
+ _values.Init();
+ }
+
+ public bool NextCell() {
+ _cellCount++;
+ return _values.MoveNext();
+ }
+
+ public IEnumerator<ICellInfo> GetEnumerator() {
+ Reset();
+ return this;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return this;
+ }
+
+ public ExcelAddressBase Address => _address;
+
+ public object GetValue(int row, int col) {
+ return _ws.GetValue(row, col);
+ }
+
+ public object GetOffset(int rowOffset, int colOffset) {
+ if (_values.Row < _fromRow || _values.Column < _fromCol) {
+ return _ws.GetValue(_fromRow + rowOffset, _fromCol + colOffset);
+ }
+ return _ws.GetValue(_values.Row + rowOffset, _values.Column + colOffset);
+ }
+ }
+
+ public class CellInfo : ICellInfo {
+ private readonly ExcelWorksheet _ws;
+ private readonly CellsStoreEnumerator<object> _values;
+
+ internal CellInfo(ExcelWorksheet ws, CellsStoreEnumerator<object> values) {
+ _ws = ws;
+ _values = values;
+ }
+
+ public string Address => _values.CellAddress;
+
+ public int Row => _values.Row;
+
+ public int Column => _values.Column;
+
+ public string Formula => _ws.GetFormula(_values.Row, _values.Column);
+
+ public object Value => _values.Value;
+
+ public double ValueDouble => ConvertUtil.GetValueDouble(_values.Value, true);
+
+ public double ValueDoubleLogical => ConvertUtil.GetValueDouble(_values.Value);
+
+ public bool IsHiddenRow {
+ get {
+ var row = _ws._values.GetValue(_values.Row, 0) as RowInternal;
+ if (row != null) {
+ return row.Hidden || row.Height == 0;
+ }
+ return false;
+ }
+ }
+
+ public bool IsExcelError => ExcelErrorValue.Values.IsErrorValue(_values.Value);
+
+ public IList<Token> Tokens => _ws._formulaTokens.GetValue(_values.Row, _values.Column);
+ }
+
+ public class NameInfo : INameInfo {
+ public ulong Id { get; set; }
+
+ public string Worksheet { get; set; }
+
+ public string Name { get; set; }
+
+ public string Formula { get; set; }
+
+ public IList<Token> Tokens { get; internal set; }
+
+ public object Value { get; set; }
+ }
+
+ private readonly ExcelWorkbook _workbook;
+ private ExcelWorksheet _currentWorksheet;
+ private Dictionary<ulong, INameInfo> _names = new();
+
+ public EpplusExcelDataProvider(ExcelWorkbook workbook) {
+ _workbook = workbook;
+ }
+
+ public override ExcelNamedRangeCollection GetWorksheetNames(string worksheet) {
+ var ws = _workbook.Worksheets[worksheet];
+ if (ws != null) {
+ return ws.Names;
+ }
+ return null;
+ }
+
+ public override ExcelNamedRangeCollection GetWorkbookNameValues() {
+ return _workbook.Names;
+ }
+
+ public override IRangeInfo GetRange(
+ string worksheet,
+ int fromRow,
+ int fromCol,
+ int toRow,
+ int toCol) {
+ SetCurrentWorksheet(worksheet);
+ var wsName = string.IsNullOrEmpty(worksheet) ? _currentWorksheet.Name : worksheet;
+ var ws = _workbook.Worksheets[wsName];
+ return new RangeInfo(ws, fromRow, fromCol, toRow, toCol);
+ }
+
+ public override IRangeInfo GetRange(string worksheet, int row, int column, string address) {
+ var addr = new ExcelAddress(worksheet, address);
+ if (addr.Table != null) {
+ addr.SetRcFromTable(_workbook, new(row, column, row, column));
+ }
+ //SetCurrentWorksheet(addr.WorkSheet);
+ var wsName = string.IsNullOrEmpty(addr.WorkSheet) ? _currentWorksheet.Name : addr.WorkSheet;
+ var ws = _workbook.Worksheets[wsName];
+ //return new CellsStoreEnumerator<object>(ws._values, addr._fromRow, addr._fromCol, addr._toRow, addr._toCol);
+ return new RangeInfo(ws, addr._fromRow, addr._fromCol, addr._toRow, addr._toCol);
+ }
+
+ public override INameInfo GetName(string worksheet, string name) {
+ ExcelNamedRange nameItem;
+ ulong id;
+ ExcelWorksheet ws;
+ if (string.IsNullOrEmpty(worksheet)) {
+ if (_workbook.Names.ContainsKey(name)) {
+ nameItem = _workbook.Names[name];
+ } else {
+ return null;
+ }
+ ws = null;
+ } else {
+ ws = _workbook.Worksheets[worksheet];
+ if (ws != null && ws.Names.ContainsKey(name)) {
+ nameItem = ws.Names[name];
+ } else if (_workbook.Names.ContainsKey(name)) {
+ nameItem = _workbook.Names[name];
+ } else {
+ return null;
+ }
+ }
+ id = ExcelCellBase.GetCellId(nameItem.LocalSheetId, nameItem.Index, 0);
+
+ if (_names.ContainsKey(id)) {
+ return _names[id];
+ }
+ var ni = new NameInfo {
+ Id = id,
+ Name = name,
+ Worksheet = nameItem.Worksheet == null ? nameItem._ws : nameItem.Worksheet.Name,
+ Formula = nameItem.Formula,
+ };
+ if (nameItem._fromRow > 0) {
+ ni.Value = new RangeInfo(
+ nameItem.Worksheet ?? ws,
+ nameItem._fromRow,
+ nameItem._fromCol,
+ nameItem._toRow,
+ nameItem._toCol);
+ } else {
+ ni.Value = nameItem.Value;
+ }
+ _names.Add(id, ni);
+ return ni;
+ }
+
+ public override IEnumerable<object> GetRangeValues(string address) {
+ SetCurrentWorksheet(ExcelAddressInfo.Parse(address));
+ var addr = new ExcelAddress(address);
+ var wsName = string.IsNullOrEmpty(addr.WorkSheet) ? _currentWorksheet.Name : addr.WorkSheet;
+ var ws = _workbook.Worksheets[wsName];
+ return (new CellsStoreEnumerator<object>(
+ ws._values,
+ addr._fromRow,
+ addr._fromCol,
+ addr._toRow,
+ addr._toCol));
+ }
+
+ public object GetValue(int row, int column) {
+ return _currentWorksheet._values.GetValue(row, column);
+ }
+
+ public bool IsMerged(int row, int column) {
+ //return _currentWorksheet._flags.GetFlagValue(row, column, CellFlags.Merged);
+ return _currentWorksheet.MergedCells[row, column] != null;
+ }
+
+ public bool IsHidden(int row, int column) {
+ return _currentWorksheet.Column(column).Hidden
+ || _currentWorksheet.Column(column).Width == 0
+ || _currentWorksheet.Row(row).Hidden
+ || _currentWorksheet.Row(column).Height == 0;
+ }
+
+ public override object GetCellValue(string sheetName, int row, int col) {
+ SetCurrentWorksheet(sheetName);
+ return _currentWorksheet._values.GetValue(row, col);
+ }
+
+ public override ExcelCellAddress GetDimensionEnd(string worksheet) {
+ ExcelCellAddress address = null;
+ try {
+ address = _workbook.Worksheets[worksheet].Dimension.End;
+ } catch {}
+
+ return address;
+ }
+
+ private void SetCurrentWorksheet(ExcelAddressInfo addressInfo) {
+ if (addressInfo.WorksheetIsSpecified) {
+ _currentWorksheet = _workbook.Worksheets[addressInfo.Worksheet];
+ } else if (_currentWorksheet == null) {
+ _currentWorksheet = _workbook.Worksheets.First();
+ }
+ }
+
+ private void SetCurrentWorksheet(string worksheetName) {
+ if (!string.IsNullOrEmpty(worksheetName)) {
+ _currentWorksheet = _workbook.Worksheets[worksheetName];
+ } else {
+ _currentWorksheet = _workbook.Worksheets.First();
+ }
+ }
+
+ public override int ExcelMaxColumns => ExcelPackage.MaxColumns;
+
+ public override int ExcelMaxRows => ExcelPackage.MaxRows;
+
+ public override string GetRangeFormula(string worksheetName, int row, int column) {
+ SetCurrentWorksheet(worksheetName);
+ return _currentWorksheet.GetFormula(row, column);
+ }
+
+ public override object GetRangeValue(string worksheetName, int row, int column) {
+ SetCurrentWorksheet(worksheetName);
+ return _currentWorksheet.GetValue(row, column);
+ }
+
+ public override string GetFormat(object value, string format) {
+ var styles = _workbook.Styles;
+ ExcelNumberFormatXml.ExcelFormatTranslator ft = null;
+ foreach (var f in styles.NumberFormats) {
+ if (f.Format == format) {
+ ft = f.FormatTranslator;
+ break;
+ }
+ }
+ if (ft == null) {
+ ft = new(format, -1);
+ }
+ return ExcelRangeBase.FormatValue(value, ft, format, ft.NetFormat);
+ }
+
+ public override List<Token> GetRangeFormulaTokens(string worksheetName, int row, int column) {
+ return _workbook.Worksheets[worksheetName]._formulaTokens.GetValue(row, column);
+ }
+
+ public override bool IsRowHidden(string worksheetName, int row) {
+ var b =
+ _workbook.Worksheets[worksheetName].Row(row).Height == 0
+ || _workbook.Worksheets[worksheetName].Row(row).Hidden;
+
+ return b;
+ }
+
+ public override void Reset() {
+ _names = new(); //Reset name cache.
+ }
+}
diff --git a/EPPlus/FormulaParsing/EpplusExcelDataProvider.cs.orig b/AppsheetEpplus/FormulaParsing/EpplusExcelDataProvider.cs.orig
similarity index 100%
rename from EPPlus/FormulaParsing/EpplusExcelDataProvider.cs.orig
rename to AppsheetEpplus/FormulaParsing/EpplusExcelDataProvider.cs.orig
diff --git a/AppsheetEpplus/FormulaParsing/EpplusNameValueProvider.cs b/AppsheetEpplus/FormulaParsing/EpplusNameValueProvider.cs
new file mode 100644
index 0000000..18403de
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/EpplusNameValueProvider.cs
@@ -0,0 +1,29 @@
+namespace AppsheetEpplus;
+
+public class EpplusNameValueProvider : INameValueProvider {
+ private readonly ExcelDataProvider _excelDataProvider;
+ private ExcelNamedRangeCollection _values;
+
+ public EpplusNameValueProvider(ExcelDataProvider excelDataProvider) {
+ _excelDataProvider = excelDataProvider;
+ _values = _excelDataProvider.GetWorkbookNameValues();
+ }
+
+ public virtual bool IsNamedValue(string key, string ws) {
+ if (ws != null) {
+ var wsNames = _excelDataProvider.GetWorksheetNames(ws);
+ if (wsNames != null && wsNames.ContainsKey(key)) {
+ return true;
+ }
+ }
+ return _values != null && _values.ContainsKey(key);
+ }
+
+ public virtual object GetNamedValue(string key) {
+ return _values[key];
+ }
+
+ public virtual void Reload() {
+ _values = _excelDataProvider.GetWorkbookNameValues();
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/ExcelCellState.cs b/AppsheetEpplus/FormulaParsing/Excel/ExcelCellState.cs
new file mode 100644
index 0000000..fdb52c9
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/ExcelCellState.cs
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+[Flags]
+public enum ExcelCellState {
+ HiddenCell = 1,
+ ContainsError = 2,
+ IsResultOfSubtotal = 4,
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/ArgumentCollectionUtil.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/ArgumentCollectionUtil.cs
new file mode 100644
index 0000000..abd3c34
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/ArgumentCollectionUtil.cs
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class ArgumentCollectionUtil {
+ private readonly DoubleEnumerableArgConverter _doubleEnumerableArgConverter;
+ private readonly ObjectEnumerableArgConverter _objectEnumerableArgConverter;
+
+ public ArgumentCollectionUtil()
+ : this(new(), new()) {}
+
+ public ArgumentCollectionUtil(
+ DoubleEnumerableArgConverter doubleEnumerableArgConverter,
+ ObjectEnumerableArgConverter objectEnumerableArgConverter) {
+ _doubleEnumerableArgConverter = doubleEnumerableArgConverter;
+ _objectEnumerableArgConverter = objectEnumerableArgConverter;
+ }
+
+ public virtual IEnumerable<double> ArgsToDoubleEnumerable(
+ bool ignoreHidden,
+ bool ignoreErrors,
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ return _doubleEnumerableArgConverter.ConvertArgs(
+ ignoreHidden,
+ ignoreErrors,
+ arguments,
+ context);
+ }
+
+ public virtual IEnumerable<object> ArgsToObjectEnumerable(
+ bool ignoreHidden,
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ return _objectEnumerableArgConverter.ConvertArgs(ignoreHidden, arguments, context);
+ }
+
+ public virtual double CalculateCollection(
+ IEnumerable<FunctionArgument> collection,
+ double result,
+ Func<FunctionArgument, double, double> action) {
+ foreach (var item in collection) {
+ if (item.Value is IEnumerable<FunctionArgument> value) {
+ result = CalculateCollection(value, result, action);
+ } else {
+ result = action(item, result);
+ }
+ }
+ return result;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/ArgumentParser.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/ArgumentParser.cs
new file mode 100644
index 0000000..40967c5
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/ArgumentParser.cs
@@ -0,0 +1,30 @@
+/* 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
+*******************************************************************************
+* Mats Alm Added 2013-12-03
+*******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public abstract class ArgumentParser {
+ public abstract object Parse(object obj);
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/ArgumentParserFactory.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/ArgumentParserFactory.cs
new file mode 100644
index 0000000..ef68066
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/ArgumentParserFactory.cs
@@ -0,0 +1,43 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+public class ArgumentParserFactory {
+ public virtual ArgumentParser CreateArgumentParser(DataType dataType) {
+ switch (dataType) {
+ case DataType.Integer:
+ return new IntArgumentParser();
+ case DataType.Boolean:
+ return new BoolArgumentParser();
+ case DataType.Decimal:
+ return new DoubleArgumentParser();
+ default:
+ throw new InvalidOperationException("non supported argument parser type " + dataType);
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/ArgumentParsers.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/ArgumentParsers.cs
new file mode 100644
index 0000000..17a2f78
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/ArgumentParsers.cs
@@ -0,0 +1,50 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class ArgumentParsers {
+ private readonly Dictionary<DataType, ArgumentParser> _parsers = new();
+ private readonly ArgumentParserFactory _parserFactory;
+
+ public ArgumentParsers()
+ : this(new()) {}
+
+ public ArgumentParsers(ArgumentParserFactory factory) {
+ Require.That(factory).Named("argumentParserfactory").IsNotNull();
+ _parserFactory = factory;
+ }
+
+ public ArgumentParser GetParser(DataType dataType) {
+ if (!_parsers.ContainsKey(dataType)) {
+ if (!_parsers.ContainsKey(dataType)) {
+ _parsers.Add(dataType, _parserFactory.CreateArgumentParser(dataType));
+ }
+ }
+ return _parsers[dataType];
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/BoolArgumentParser.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/BoolArgumentParser.cs
new file mode 100644
index 0000000..b8fcf9d
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/BoolArgumentParser.cs
@@ -0,0 +1,51 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class BoolArgumentParser : ArgumentParser {
+ public override object Parse(object obj) {
+ if (obj is ExcelDataProvider.IRangeInfo info) {
+ var r = info.FirstOrDefault();
+ obj = r?.Value;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (obj is bool b) {
+ return b;
+ }
+ if (obj.IsNumeric()) {
+ return Convert.ToBoolean(obj);
+ }
+ if (bool.TryParse(obj.ToString(), out var result)) {
+ return result;
+ }
+ return result;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/BuiltInFunctions.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/BuiltInFunctions.cs
new file mode 100644
index 0000000..eaa2ec0
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/BuiltInFunctions.cs
@@ -0,0 +1,194 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public class BuiltInFunctions : FunctionsModule {
+ public BuiltInFunctions() {
+ // Text
+ Functions["len"] = new Len();
+ Functions["lower"] = new Lower();
+ Functions["upper"] = new Upper();
+ Functions["left"] = new Left();
+ Functions["right"] = new Right();
+ Functions["mid"] = new Mid();
+ Functions["replace"] = new Replace();
+ Functions["rept"] = new Rept();
+ Functions["substitute"] = new Substitute();
+ Functions["concatenate"] = new Concatenate();
+ Functions["char"] = new CharFunction();
+ Functions["exact"] = new Exact();
+ Functions["find"] = new Find();
+ Functions["fixed"] = new Fixed();
+ Functions["proper"] = new Proper();
+ Functions["text"] = new Text();
+ Functions["t"] = new T();
+ Functions["hyperlink"] = new Hyperlink();
+ // Numbers
+ Functions["int"] = new CInt();
+ // Math
+ Functions["abs"] = new Abs();
+ Functions["asin"] = new Asin();
+ Functions["asinh"] = new Asinh();
+ Functions["cos"] = new Cos();
+ Functions["cosh"] = new Cosh();
+ Functions["power"] = new Power();
+ Functions["sign"] = new Sign();
+ Functions["sqrt"] = new Sqrt();
+ Functions["sqrtpi"] = new SqrtPi();
+ Functions["pi"] = new Pi();
+ Functions["product"] = new Product();
+ Functions["ceiling"] = new Ceiling();
+ Functions["count"] = new Count();
+ Functions["counta"] = new CountA();
+ Functions["countblank"] = new CountBlank();
+ Functions["countif"] = new CountIf();
+ Functions["countifs"] = new CountIfs();
+ Functions["fact"] = new Fact();
+ Functions["floor"] = new Floor();
+ Functions["sin"] = new Sin();
+ Functions["sinh"] = new Sinh();
+ Functions["sum"] = new Sum();
+ Functions["sumif"] = new SumIf();
+ Functions["sumifs"] = new SumIfs();
+ Functions["sumproduct"] = new SumProduct();
+ Functions["sumsq"] = new Sumsq();
+ Functions["stdev"] = new Stdev();
+ Functions["stdevp"] = new StdevP();
+ Functions["stdev.s"] = new Stdev();
+ Functions["stdev.p"] = new StdevP();
+ Functions["subtotal"] = new Subtotal();
+ Functions["exp"] = new Exp();
+ Functions["log"] = new Log();
+ Functions["log10"] = new Log10();
+ Functions["ln"] = new Ln();
+ Functions["max"] = new Max();
+ Functions["maxa"] = new Maxa();
+ Functions["median"] = new Median();
+ Functions["min"] = new Min();
+ Functions["mina"] = new Mina();
+ Functions["mod"] = new Mod();
+ Functions["average"] = new Average();
+ Functions["averagea"] = new AverageA();
+ Functions["averageif"] = new AverageIf();
+ Functions["averageifs"] = new AverageIfs();
+ Functions["round"] = new Round();
+ Functions["rounddown"] = new Rounddown();
+ Functions["roundup"] = new Roundup();
+ Functions["rand"] = new Rand();
+ Functions["randbetween"] = new RandBetween();
+ Functions["quotient"] = new Quotient();
+ Functions["trunc"] = new Trunc();
+ Functions["tan"] = new Tan();
+ Functions["tanh"] = new Tanh();
+ Functions["atan"] = new Atan();
+ Functions["atan2"] = new Atan2();
+ Functions["atanh"] = new Atanh();
+ Functions["acos"] = new Acos();
+ Functions["acosh"] = new Acosh();
+ Functions["var"] = new Var();
+ Functions["varp"] = new VarP();
+ Functions["large"] = new Large();
+ Functions["small"] = new Small();
+ Functions["degrees"] = new Degrees();
+ // Information
+ Functions["isblank"] = new IsBlank();
+ Functions["isnumber"] = new IsNumber();
+ Functions["istext"] = new IsText();
+ Functions["isnontext"] = new IsNonText();
+ Functions["iserror"] = new IsError();
+ Functions["iserr"] = new IsErr();
+ Functions["error.type"] = new ErrorType();
+ Functions["iseven"] = new IsEven();
+ Functions["isodd"] = new IsOdd();
+ Functions["islogical"] = new IsLogical();
+ Functions["isna"] = new IsNa();
+ Functions["na"] = new Na();
+ Functions["n"] = new N();
+ // Logical
+ Functions["if"] = new If();
+ Functions["iferror"] = new IfError();
+ Functions["ifna"] = new IfNa();
+ Functions["not"] = new Not();
+ Functions["and"] = new And();
+ Functions["or"] = new Or();
+ Functions["true"] = new True();
+ Functions["false"] = new False();
+ // Reference and lookup
+ Functions["address"] = new Address();
+ Functions["hlookup"] = new HLookup();
+ Functions["vlookup"] = new VLookup();
+ Functions["lookup"] = new Lookup();
+ Functions["match"] = new ExcelMatch();
+ Functions["row"] = new Row {
+ SkipArgumentEvaluation = true,
+ };
+ Functions["rows"] = new Rows {
+ SkipArgumentEvaluation = true,
+ };
+ Functions["column"] = new Column {
+ SkipArgumentEvaluation = true,
+ };
+ Functions["columns"] = new Columns {
+ SkipArgumentEvaluation = true,
+ };
+ Functions["choose"] = new Choose();
+ Functions["index"] = new Index();
+ Functions["indirect"] = new Indirect();
+ Functions["offset"] = new Offset {
+ SkipArgumentEvaluation = true,
+ };
+ // Date
+ Functions["date"] = new Date();
+ Functions["today"] = new Today();
+ Functions["now"] = new Now();
+ Functions["day"] = new Day();
+ Functions["month"] = new Month();
+ Functions["year"] = new Year();
+ Functions["time"] = new Time();
+ Functions["hour"] = new Hour();
+ Functions["minute"] = new Minute();
+ Functions["second"] = new Second();
+ Functions["weeknum"] = new Weeknum();
+ Functions["weekday"] = new Weekday();
+ Functions["days360"] = new Days360();
+ Functions["yearfrac"] = new Yearfrac();
+ Functions["edate"] = new Edate();
+ Functions["eomonth"] = new Eomonth();
+ Functions["isoweeknum"] = new IsoWeekNum();
+ Functions["workday"] = new Workday();
+ // Database
+ Functions["dget"] = new Dget();
+ Functions["dcount"] = new Dcount();
+ Functions["dcounta"] = new DcountA();
+ Functions["dmax"] = new Dmax();
+ Functions["dmin"] = new Dmin();
+ Functions["dsum"] = new Dsum();
+ Functions["daverage"] = new Daverage();
+ Functions["dvar"] = new Dvar();
+ Functions["dvarp"] = new Dvarp();
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/CellStateHelper.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/CellStateHelper.cs
new file mode 100644
index 0000000..96be95e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/CellStateHelper.cs
@@ -0,0 +1,56 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+internal static class CellStateHelper {
+ private static bool IsSubTotal(ExcelDataProvider.ICellInfo c) {
+ var tokens = c.Tokens;
+ if (tokens == null) {
+ return false;
+ }
+ return c.Tokens.Any(token =>
+ token.TokenType == TokenType.Function
+ && token.Value.Equals("SUBTOTAL", StringComparison.InvariantCultureIgnoreCase));
+ }
+
+ internal static bool ShouldIgnore(
+ bool ignoreHiddenValues,
+ ExcelDataProvider.ICellInfo c,
+ ParsingContext context) {
+ return (ignoreHiddenValues && c.IsHiddenRow)
+ || (context.Scopes.Current.IsSubtotal && IsSubTotal(c));
+ }
+
+ internal static bool ShouldIgnore(
+ bool ignoreHiddenValues,
+ FunctionArgument arg,
+ ParsingContext context) {
+ return (ignoreHiddenValues && arg.ExcelStateFlagIsSet(ExcelCellState.HiddenCell));
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/CollectionFlattener.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/CollectionFlattener.cs
new file mode 100644
index 0000000..247a452
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/CollectionFlattener.cs
@@ -0,0 +1,52 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public abstract class CollectionFlattener<T> {
+ public virtual IEnumerable<T> FuncArgsToFlatEnumerable(
+ IEnumerable<FunctionArgument> arguments,
+ Action<FunctionArgument, IList<T>> convertFunc) {
+ var argList = new List<T>();
+ FuncArgsToFlatEnumerable(arguments, argList, convertFunc);
+ return argList;
+ }
+
+ private void FuncArgsToFlatEnumerable(
+ IEnumerable<FunctionArgument> arguments,
+ List<T> argList,
+ Action<FunctionArgument, IList<T>> convertFunc) {
+ foreach (var arg in arguments) {
+ if (arg.Value is IEnumerable<FunctionArgument> value) {
+ FuncArgsToFlatEnumerable(value, argList, convertFunc);
+ } else {
+ convertFunc(arg, argList);
+ }
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/CompileResultValidator.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/CompileResultValidator.cs
new file mode 100644
index 0000000..0a5c36f
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/CompileResultValidator.cs
@@ -0,0 +1,41 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-26
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public abstract class CompileResultValidator {
+ public abstract void Validate(object obj);
+
+ private static CompileResultValidator _empty;
+
+ public static CompileResultValidator Empty =>
+ _empty ?? (_empty = new EmptyCompileResultValidator());
+}
+
+internal class EmptyCompileResultValidator : CompileResultValidator {
+ public override void Validate(object obj) {
+ // empty validator - do nothing
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/CompileResultValidators.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/CompileResultValidators.cs
new file mode 100644
index 0000000..e9e22a3
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/CompileResultValidators.cs
@@ -0,0 +1,46 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-26
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class CompileResultValidators {
+ private readonly Dictionary<DataType, CompileResultValidator> _validators = new();
+
+ private CompileResultValidator CreateOrGet(DataType dataType) {
+ if (_validators.ContainsKey(dataType)) {
+ return _validators[dataType];
+ }
+ if (dataType == DataType.Decimal) {
+ return _validators[DataType.Decimal] = new DecimalCompileResultValidator();
+ }
+ return CompileResultValidator.Empty;
+ }
+
+ public CompileResultValidator GetValidator(DataType dataType) {
+ return CreateOrGet(dataType);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/DSum.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/DSum.cs
new file mode 100644
index 0000000..b54ce0f
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/DSum.cs
@@ -0,0 +1,48 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-19
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Dsum : DatabaseFunction {
+ public Dsum()
+ : this(new()) {}
+
+ public Dsum(RowMatcher rowMatcher)
+ : base(rowMatcher) {}
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 3);
+ var values = GetMatchingValues(arguments, context);
+ if (!values.Any()) {
+ return CreateResult(0d, DataType.Integer);
+ }
+ return CreateResult(values.Sum(), DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/DatabaseFunction.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/DatabaseFunction.cs
new file mode 100644
index 0000000..5fdd70a
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/DatabaseFunction.cs
@@ -0,0 +1,68 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-19
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public abstract class DatabaseFunction : ExcelFunction {
+ protected RowMatcher RowMatcher { get; private set; }
+
+ public DatabaseFunction()
+ : this(new()) {}
+
+ public DatabaseFunction(RowMatcher rowMatcher) {
+ RowMatcher = rowMatcher;
+ }
+
+ protected IEnumerable<double> GetMatchingValues(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var dbAddress = arguments.ElementAt(0).ValueAsRangeInfo.Address.Address;
+ //var field = ArgToString(arguments, 1).ToLower(CultureInfo.InvariantCulture);
+ var field = arguments.ElementAt(1).Value;
+ var criteriaRange = arguments.ElementAt(2).ValueAsRangeInfo.Address.Address;
+
+ var db = new ExcelDatabase(context.ExcelDataProvider, dbAddress);
+ var criteria = new ExcelDatabaseCriteria(context.ExcelDataProvider, criteriaRange);
+ var values = new List<double>();
+
+ while (db.HasMoreRows) {
+ var dataRow = db.Read();
+ if (!RowMatcher.IsMatch(dataRow, criteria)) {
+ continue;
+ }
+ var candidate = ConvertUtil.IsNumeric(field)
+ ? dataRow[(int)ConvertUtil.GetValueDouble(field)]
+ : dataRow[field.ToString().ToLower(CultureInfo.InvariantCulture)];
+ if (ConvertUtil.IsNumeric(candidate)) {
+ values.Add(ConvertUtil.GetValueDouble(candidate));
+ }
+ }
+ return values;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Daverage.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Daverage.cs
new file mode 100644
index 0000000..251aa9b
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Daverage.cs
@@ -0,0 +1,48 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-19
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Daverage : DatabaseFunction {
+ public Daverage()
+ : this(new()) {}
+
+ public Daverage(RowMatcher rowMatcher)
+ : base(rowMatcher) {}
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 3);
+ var values = GetMatchingValues(arguments, context);
+ if (!values.Any()) {
+ return CreateResult(0d, DataType.Integer);
+ }
+ return CreateResult(values.Average(), DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dcount.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dcount.cs
new file mode 100644
index 0000000..b9d8e6e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dcount.cs
@@ -0,0 +1,77 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-06
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Dcount : ExcelFunction {
+ private readonly RowMatcher _rowMatcher;
+
+ public Dcount()
+ : this(new()) {}
+
+ public Dcount(RowMatcher rowMatcher) {
+ _rowMatcher = rowMatcher;
+ }
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var dbAddress = arguments.ElementAt(0).ValueAsRangeInfo.Address.Address;
+ string field = null;
+ string criteriaRange = null;
+ if (arguments.Count() == 2) {
+ criteriaRange = arguments.ElementAt(1).ValueAsRangeInfo.Address.Address;
+ } else {
+ field = ArgToString(arguments, 1).ToLower(CultureInfo.InvariantCulture);
+ criteriaRange = arguments.ElementAt(2).ValueAsRangeInfo.Address.Address;
+ }
+ var db = new ExcelDatabase(context.ExcelDataProvider, dbAddress);
+ var criteria = new ExcelDatabaseCriteria(context.ExcelDataProvider, criteriaRange);
+
+ var nHits = 0;
+ while (db.HasMoreRows) {
+ var dataRow = db.Read();
+ if (_rowMatcher.IsMatch(dataRow, criteria)) {
+ // if a fieldname is supplied, count only this row if the value
+ // of the supplied field is numeric.
+ if (!string.IsNullOrEmpty(field)) {
+ var candidate = dataRow[field];
+ if (ConvertUtil.IsNumeric(candidate)) {
+ nHits++;
+ }
+ } else {
+ // no fieldname was supplied, always count matching row.
+ nHits++;
+ }
+ }
+ }
+ return CreateResult(nHits, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/DcountA.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/DcountA.cs
new file mode 100644
index 0000000..8f6bd9b
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/DcountA.cs
@@ -0,0 +1,81 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-06
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class DcountA : DatabaseFunction {
+ public DcountA()
+ : this(new()) {}
+
+ public DcountA(RowMatcher rowMatcher)
+ : base(rowMatcher) {}
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var dbAddress = arguments.ElementAt(0).ValueAsRangeInfo.Address.Address;
+ string field = null;
+ string criteriaRange;
+ if (arguments.Count() == 2) {
+ criteriaRange = arguments.ElementAt(1).ValueAsRangeInfo.Address.Address;
+ } else {
+ field = ArgToString(arguments, 1).ToLower(CultureInfo.InvariantCulture);
+ criteriaRange = arguments.ElementAt(2).ValueAsRangeInfo.Address.Address;
+ }
+ var db = new ExcelDatabase(context.ExcelDataProvider, dbAddress);
+ var criteria = new ExcelDatabaseCriteria(context.ExcelDataProvider, criteriaRange);
+
+ var nHits = 0;
+ while (db.HasMoreRows) {
+ var dataRow = db.Read();
+ if (RowMatcher.IsMatch(dataRow, criteria)) {
+ // if a fieldname is supplied, count only this row if the value
+ // of the supplied field is not blank.
+ if (!string.IsNullOrEmpty(field)) {
+ var candidate = dataRow[field];
+ if (ShouldCount(candidate)) {
+ nHits++;
+ }
+ } else {
+ // no fieldname was supplied, always count matching row.
+ nHits++;
+ }
+ }
+ }
+ return CreateResult(nHits, DataType.Integer);
+ }
+
+ private bool ShouldCount(object value) {
+ if (value == null) {
+ return false;
+ }
+ return (!string.IsNullOrEmpty(value.ToString()));
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dget.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dget.cs
new file mode 100644
index 0000000..204fcfd
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dget.cs
@@ -0,0 +1,64 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-06
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Dget : DatabaseFunction {
+ public Dget()
+ : this(new()) {}
+
+ public Dget(RowMatcher rowMatcher)
+ : base(rowMatcher) {}
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 3);
+ var dbAddress = arguments.ElementAt(0).ValueAsRangeInfo.Address.Address;
+ var field = ArgToString(arguments, 1).ToLower(CultureInfo.InvariantCulture);
+ var criteriaRange = arguments.ElementAt(2).ValueAsRangeInfo.Address.Address;
+
+ var db = new ExcelDatabase(context.ExcelDataProvider, dbAddress);
+ var criteria = new ExcelDatabaseCriteria(context.ExcelDataProvider, criteriaRange);
+
+ var nHits = 0;
+ object retVal = null;
+ while (db.HasMoreRows) {
+ var dataRow = db.Read();
+ if (!RowMatcher.IsMatch(dataRow, criteria)) {
+ continue;
+ }
+ if (++nHits > 1) {
+ return CreateResult(ExcelErrorValue.Values.Num, DataType.ExcelError);
+ }
+ retVal = dataRow[field];
+ }
+ return new CompileResultFactory().Create(retVal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dmax.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dmax.cs
new file mode 100644
index 0000000..c87e23d
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dmax.cs
@@ -0,0 +1,48 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-19
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Dmax : DatabaseFunction {
+ public Dmax()
+ : this(new()) {}
+
+ public Dmax(RowMatcher rowMatcher)
+ : base(rowMatcher) {}
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 3);
+ var values = GetMatchingValues(arguments, context);
+ if (!values.Any()) {
+ return CreateResult(0d, DataType.Integer);
+ }
+ return CreateResult(values.Max(), DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dmin.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dmin.cs
new file mode 100644
index 0000000..df9f8a9
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dmin.cs
@@ -0,0 +1,48 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-19
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Dmin : DatabaseFunction {
+ public Dmin()
+ : this(new()) {}
+
+ public Dmin(RowMatcher rowMatcher)
+ : base(rowMatcher) {}
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 3);
+ var values = GetMatchingValues(arguments, context);
+ if (!values.Any()) {
+ return CreateResult(0d, DataType.Integer);
+ }
+ return CreateResult(values.Min(), DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dvar.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dvar.cs
new file mode 100644
index 0000000..feb1265
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dvar.cs
@@ -0,0 +1,48 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-19
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Dvar : DatabaseFunction {
+ public Dvar()
+ : this(new()) {}
+
+ public Dvar(RowMatcher rowMatcher)
+ : base(rowMatcher) {}
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 3);
+ var values = GetMatchingValues(arguments, context);
+ if (!values.Any()) {
+ return CreateResult(0d, DataType.Integer);
+ }
+ return CreateResult(VarMethods.Var(values), DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dvarp.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dvarp.cs
new file mode 100644
index 0000000..9484b71
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/Dvarp.cs
@@ -0,0 +1,48 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-19
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Dvarp : DatabaseFunction {
+ public Dvarp()
+ : this(new()) {}
+
+ public Dvarp(RowMatcher rowMatcher)
+ : base(rowMatcher) {}
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 3);
+ var values = GetMatchingValues(arguments, context);
+ if (!values.Any()) {
+ return CreateResult(0d, DataType.Integer);
+ }
+ return CreateResult(VarMethods.VarP(values), DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/ExcelDatabase.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/ExcelDatabase.cs
new file mode 100644
index 0000000..2c9cf12
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/ExcelDatabase.cs
@@ -0,0 +1,81 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-06
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace AppsheetEpplus;
+
+public class ExcelDatabase {
+ private readonly ExcelDataProvider _dataProvider;
+ private readonly int _fromCol;
+ private readonly int _toCol;
+ private readonly int _fieldRow;
+ private readonly int _endRow;
+ private readonly string _worksheet;
+ private int _rowIndex;
+ private readonly List<ExcelDatabaseField> _fields = new();
+
+ public IEnumerable<ExcelDatabaseField> Fields => _fields;
+
+ public ExcelDatabase(ExcelDataProvider dataProvider, string range) {
+ _dataProvider = dataProvider;
+ var address = new ExcelAddressBase(range);
+ _fromCol = address._fromCol;
+ _toCol = address._toCol;
+ _fieldRow = address._fromRow;
+ _endRow = address._toRow;
+ _worksheet = address.WorkSheet;
+ _rowIndex = _fieldRow;
+ Initialize();
+ }
+
+ private void Initialize() {
+ var fieldIx = 0;
+ for (var colIndex = _fromCol; colIndex <= _toCol; colIndex++) {
+ var nameObj = GetCellValue(_fieldRow, colIndex);
+ var name =
+ nameObj != null ? nameObj.ToString().ToLower(CultureInfo.InvariantCulture) : string.Empty;
+ _fields.Add(new(name, fieldIx++));
+ }
+ }
+
+ private object GetCellValue(int row, int col) {
+ return _dataProvider.GetRangeValue(_worksheet, row, col);
+ }
+
+ public bool HasMoreRows => _rowIndex < _endRow;
+
+ public ExcelDatabaseRow Read() {
+ var retVal = new ExcelDatabaseRow();
+ _rowIndex++;
+ foreach (var field in Fields) {
+ var colIndex = _fromCol + field.ColIndex;
+ var val = GetCellValue(_rowIndex, colIndex);
+ retVal[field.FieldName] = val;
+ }
+ return retVal;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteria.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteria.cs
new file mode 100644
index 0000000..1859c8c
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteria.cs
@@ -0,0 +1,67 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-06
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace AppsheetEpplus;
+
+public class ExcelDatabaseCriteria {
+ private readonly ExcelDataProvider _dataProvider;
+ private readonly int _fromCol;
+ private readonly int _toCol;
+ private readonly string _worksheet;
+ private readonly int _fieldRow;
+ private readonly Dictionary<ExcelDatabaseCriteriaField, object> _criterias = new();
+
+ public ExcelDatabaseCriteria(ExcelDataProvider dataProvider, string range) {
+ _dataProvider = dataProvider;
+ var address = new ExcelAddressBase(range);
+ _fromCol = address._fromCol;
+ _toCol = address._toCol;
+ _worksheet = address.WorkSheet;
+ _fieldRow = address._fromRow;
+ Initialize();
+ }
+
+ private void Initialize() {
+ for (var x = _fromCol; x <= _toCol; x++) {
+ var fieldObj = _dataProvider.GetCellValue(_worksheet, _fieldRow, x);
+ var val = _dataProvider.GetCellValue(_worksheet, _fieldRow + 1, x);
+ if (fieldObj != null && val != null) {
+ if (fieldObj is string) {
+ var field = new ExcelDatabaseCriteriaField(
+ fieldObj.ToString().ToLower(CultureInfo.InvariantCulture));
+ _criterias.Add(field, val);
+ } else if (ConvertUtil.IsNumeric(fieldObj)) {
+ var field = new ExcelDatabaseCriteriaField((int)fieldObj);
+ _criterias.Add(field, val);
+ }
+ }
+ }
+ }
+
+ public virtual IDictionary<ExcelDatabaseCriteriaField, object> Items => _criterias;
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteriaField.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteriaField.cs
new file mode 100644
index 0000000..9fa2d2b
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteriaField.cs
@@ -0,0 +1,47 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-19
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class ExcelDatabaseCriteriaField {
+ public ExcelDatabaseCriteriaField(string fieldName) {
+ FieldName = fieldName;
+ }
+
+ public ExcelDatabaseCriteriaField(int fieldIndex) {
+ FieldIndex = fieldIndex;
+ }
+
+ public override string ToString() {
+ if (!string.IsNullOrEmpty(FieldName)) {
+ return FieldName;
+ }
+ return base.ToString();
+ }
+
+ public string FieldName { get; private set; }
+
+ public int? FieldIndex { get; private set; }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseField.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseField.cs
new file mode 100644
index 0000000..8472a99
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseField.cs
@@ -0,0 +1,37 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-06
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class ExcelDatabaseField {
+ public string FieldName { get; private set; }
+
+ public int ColIndex { get; private set; }
+
+ public ExcelDatabaseField(string fieldName, int colIndex) {
+ FieldName = fieldName;
+ ColIndex = colIndex;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseRow.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseRow.cs
new file mode 100644
index 0000000..c948477
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseRow.cs
@@ -0,0 +1,49 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-19
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class ExcelDatabaseRow {
+ private readonly Dictionary<int, string> _fieldIndexes = new();
+ private readonly Dictionary<string, object> _items = new();
+ private int _colIndex = 1;
+
+ public object this[string field] {
+ get => _items[field];
+ set {
+ _items[field] = value;
+ _fieldIndexes[_colIndex++] = field;
+ }
+ }
+
+ public object this[int index] {
+ get {
+ var field = _fieldIndexes[index];
+ return _items[field];
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/RowMatcher.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/RowMatcher.cs
new file mode 100644
index 0000000..71ff077
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Database/RowMatcher.cs
@@ -0,0 +1,79 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-06
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public class RowMatcher {
+ private readonly WildCardValueMatcher _wildCardValueMatcher;
+ private readonly NumericExpressionEvaluator _numericExpressionEvaluator;
+
+ public RowMatcher()
+ : this(new(), new()) {}
+
+ public RowMatcher(
+ WildCardValueMatcher wildCardValueMatcher,
+ NumericExpressionEvaluator numericExpressionEvaluator) {
+ _wildCardValueMatcher = wildCardValueMatcher;
+ _numericExpressionEvaluator = numericExpressionEvaluator;
+ }
+
+ public bool IsMatch(ExcelDatabaseRow row, ExcelDatabaseCriteria criteria) {
+ var retVal = true;
+ foreach (var c in criteria.Items) {
+ var candidate = c.Key.FieldIndex.HasValue
+ ? row[c.Key.FieldIndex.Value]
+ : row[c.Key.FieldName];
+ var crit = c.Value;
+ if (candidate.IsNumeric() && crit.IsNumeric()) {
+ if (System.Math.Abs(
+ ConvertUtil.GetValueDouble(candidate) - ConvertUtil.GetValueDouble(crit))
+ > double.Epsilon) {
+ return false;
+ }
+ } else {
+ var criteriaString = crit.ToString();
+ if (!Evaluate(candidate, criteriaString)) {
+ return false;
+ }
+ }
+ }
+ return retVal;
+ }
+
+ private bool Evaluate(object obj, string expression) {
+ if (obj == null) {
+ return false;
+ }
+ double? candidate = default(double?);
+ if (ConvertUtil.IsNumeric(obj)) {
+ candidate = ConvertUtil.GetValueDouble(obj);
+ }
+ if (candidate.HasValue) {
+ return _numericExpressionEvaluator.Evaluate(candidate.Value, expression);
+ }
+ return _wildCardValueMatcher.IsMatch(expression, obj.ToString()) == 0;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Date.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Date.cs
new file mode 100644
index 0000000..fe43877
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Date.cs
@@ -0,0 +1,44 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Date : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 3);
+ var year = ArgToInt(arguments, 0);
+ var month = ArgToInt(arguments, 1);
+ var day = ArgToInt(arguments, 2);
+ var date = new System.DateTime(year, 1, 1);
+ month -= 1;
+ date = date.AddMonths(month);
+ date = date.AddDays(day - 1);
+ return CreateResult(date.ToOADate(), DataType.Date);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/DateParsingFunction.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/DateParsingFunction.cs
new file mode 100644
index 0000000..a30bb49
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/DateParsingFunction.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace AppsheetEpplus;
+
+public abstract class DateParsingFunction : ExcelFunction {
+ protected System.DateTime ParseDate(IEnumerable<FunctionArgument> arguments, object dateObj) {
+ System.DateTime date;
+ if (dateObj is string) {
+ date = System.DateTime.Parse(dateObj.ToString(), CultureInfo.InvariantCulture);
+ } else {
+ var d = ArgToDecimal(arguments, 0);
+ date = System.DateTime.FromOADate(d);
+ }
+ return date;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/DateStringParser.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/DateStringParser.cs
new file mode 100644
index 0000000..c3e4618
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/DateStringParser.cs
@@ -0,0 +1,28 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class DateStringParser {}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/DateValue.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/DateValue.cs
new file mode 100644
index 0000000..8f97f83
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/DateValue.cs
@@ -0,0 +1,24 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Simple implementation of DateValue function, just using .NET built-in
+/// function System.DateTime.TryParse, based on current culture
+/// </summary>
+public class DateValue : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var dateString = ArgToString(arguments, 0);
+ return Execute(dateString);
+ }
+
+ internal CompileResult Execute(string dateString) {
+ System.DateTime.TryParse(dateString, out var result);
+ return result != System.DateTime.MinValue
+ ? CreateResult(result.ToOADate(), DataType.Date)
+ : CreateResult(ExcelErrorValue.Create(eErrorType.Value), DataType.ExcelError);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Day.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Day.cs
new file mode 100644
index 0000000..b226b31
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Day.cs
@@ -0,0 +1,40 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Day : DateParsingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var dateObj = GetFirstValue(arguments);
+ var date = ParseDate(arguments, dateObj);
+
+ return CreateResult(date.Day, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Days360.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Days360.cs
new file mode 100644
index 0000000..a797688
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Days360.cs
@@ -0,0 +1,70 @@
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Days360 : ExcelFunction {
+ private enum Days360Calctype {
+ European,
+ Us,
+ }
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var numDate1 = ArgToDecimal(arguments, 0);
+ var numDate2 = ArgToDecimal(arguments, 1);
+ var dt1 = System.DateTime.FromOADate(numDate1);
+ var dt2 = System.DateTime.FromOADate(numDate2);
+
+ var calcType = Days360Calctype.Us;
+ if (arguments.Count() > 2) {
+ var european = ArgToBool(arguments, 2);
+ if (european) {
+ calcType = Days360Calctype.European;
+ }
+ }
+
+ var startYear = dt1.Year;
+ var startMonth = dt1.Month;
+ var startDay = dt1.Day;
+ var endYear = dt2.Year;
+ var endMonth = dt2.Month;
+ var endDay = dt2.Day;
+
+ if (calcType == Days360Calctype.European) {
+ if (startDay == 31) {
+ startDay = 30;
+ }
+ if (endDay == 31) {
+ endDay = 30;
+ }
+ } else {
+ var calendar = new GregorianCalendar();
+ var nDaysInFeb = calendar.IsLeapYear(dt1.Year) ? 29 : 28;
+
+ // If the investment is EOM and (Date1 is the last day of February) and (Date2 is the last day of February), then change D2 to 30.
+ if (startMonth == 2 && startDay == nDaysInFeb && endMonth == 2 && endDay == nDaysInFeb) {
+ endDay = 30;
+ }
+ // If the investment is EOM and (Date1 is the last day of February), then change D1 to 30.
+ if (startMonth == 2 && startDay == nDaysInFeb) {
+ startDay = 30;
+ }
+ // If D2 is 31 and D1 is 30 or 31, then change D2 to 30.
+ if (endDay == 31 && (startDay == 30 || startDay == 31)) {
+ endDay = 30;
+ }
+ // If D1 is 31, then change D1 to 30.
+ if (startDay == 31) {
+ startDay = 30;
+ }
+ }
+ var result =
+ (endYear * 12 * 30 + endMonth * 30 + endDay)
+ - (startYear * 12 * 30 + startMonth * 30 + startDay);
+ return CreateResult(result, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Edate.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Edate.cs
new file mode 100644
index 0000000..530a13c
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Edate.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Edate : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2, eErrorType.Value);
+ var dateSerial = ArgToDecimal(arguments, 0);
+ var date = System.DateTime.FromOADate(dateSerial);
+ var nMonthsToAdd = ArgToInt(arguments, 1);
+ var resultDate = date.AddMonths(nMonthsToAdd);
+ return CreateResult(resultDate.ToOADate(), DataType.Date);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Eomonth.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Eomonth.cs
new file mode 100644
index 0000000..cae6cbb
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Eomonth.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Eomonth : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var date = System.DateTime.FromOADate(ArgToDecimal(arguments, 0));
+ var monthsToAdd = ArgToInt(arguments, 1);
+ var resultDate = new System.DateTime(date.Year, date.Month, 1)
+ .AddMonths(monthsToAdd + 1)
+ .AddDays(-1);
+ return CreateResult(resultDate.ToOADate(), DataType.Date);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Hour.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Hour.cs
new file mode 100644
index 0000000..ecdc1a8
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Hour.cs
@@ -0,0 +1,40 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Hour : DateParsingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var dateObj = arguments.ElementAt(0).Value;
+ var date = ParseDate(arguments, dateObj);
+ return CreateResult(date.Hour, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/IsoWeekNum.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/IsoWeekNum.cs
new file mode 100644
index 0000000..0ef8c4f
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/IsoWeekNum.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class IsoWeekNum : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var dateInt = ArgToInt(arguments, 0);
+ var date = System.DateTime.FromOADate(dateInt);
+ return CreateResult(WeekNumber(date), DataType.Integer);
+ }
+
+ /// <summary>
+ /// This implementation was found on http://stackoverflow.com/questions/1285191/get-week-of-date-from-linq-query
+ /// </summary>
+ /// <param name="fromDate"></param>
+ /// <returns></returns>
+ private int WeekNumber(System.DateTime fromDate) {
+ // Get jan 1st of the year
+ var startOfYear = fromDate.AddDays(-fromDate.Day + 1).AddMonths(-fromDate.Month + 1);
+ // Get dec 31st of the year
+ var endOfYear = startOfYear.AddYears(1).AddDays(-1);
+ // ISO 8601 weeks start with Monday
+ // The first week of a year includes the first Thursday
+ // DayOfWeek returns 0 for sunday up to 6 for saterday
+ int[] iso8601Correction = [6, 7, 8, 9, 10, 4, 5];
+ int nds = fromDate.Subtract(startOfYear).Days + iso8601Correction[(int)startOfYear.DayOfWeek];
+ int wk = nds / 7;
+ switch (wk) {
+ case 0:
+ // Return weeknumber of dec 31st of the previous year
+ return WeekNumber(startOfYear.AddDays(-1));
+ case 53:
+ // If dec 31st falls before thursday it is week 01 of next year
+ if (endOfYear.DayOfWeek < DayOfWeek.Thursday) {
+ return 1;
+ }
+ return wk;
+ default:
+ return wk;
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Minute.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Minute.cs
new file mode 100644
index 0000000..6b67254
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Minute.cs
@@ -0,0 +1,46 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Minute : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var dateObj = arguments.ElementAt(0).Value;
+ System.DateTime date;
+ if (dateObj is string) {
+ date = System.DateTime.Parse(dateObj.ToString());
+ } else {
+ var d = ArgToDecimal(arguments, 0);
+ date = System.DateTime.FromOADate(d);
+ }
+ return CreateResult(date.Minute, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Month.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Month.cs
new file mode 100644
index 0000000..361615e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Month.cs
@@ -0,0 +1,40 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Month : DateParsingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var dateObj = arguments.ElementAt(0).Value;
+ var date = ParseDate(arguments, dateObj);
+ return CreateResult(date.Month, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Networkdays.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Networkdays.cs
new file mode 100644
index 0000000..3ba7a10
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Networkdays.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Networkdays : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
+ ValidateArguments(functionArguments, 2);
+ var startDate = System.DateTime.FromOADate(ArgToInt(functionArguments, 0));
+ var endDate = System.DateTime.FromOADate(ArgToInt(functionArguments, 1));
+ var calculator = new WorkdayCalculator();
+ var result = calculator.CalculateNumberOfWorkdays(startDate, endDate);
+ if (functionArguments.Length > 2) {
+ result = calculator.ReduceWorkdaysWithHolidays(result, functionArguments[2]);
+ }
+
+ return new(result.NumberOfWorkdays, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/NetworkdaysIntl.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/NetworkdaysIntl.cs
new file mode 100644
index 0000000..96fd71c
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/NetworkdaysIntl.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AppsheetEpplus;
+
+public class NetworkdaysIntl : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
+ ValidateArguments(functionArguments, 2);
+ var startDate = System.DateTime.FromOADate(ArgToInt(functionArguments, 0));
+ var endDate = System.DateTime.FromOADate(ArgToInt(functionArguments, 1));
+ WorkdayCalculator calculator = new WorkdayCalculator();
+ var weekdayFactory = new HolidayWeekdaysFactory();
+ if (functionArguments.Length > 2) {
+ var holidayArg = functionArguments[2].Value;
+ if (Regex.IsMatch(holidayArg.ToString(), "^[01]{7}")) {
+ calculator = new(weekdayFactory.Create(holidayArg.ToString()));
+ } else if (IsNumeric(holidayArg)) {
+ var holidayCode = Convert.ToInt32(holidayArg);
+ calculator = new(weekdayFactory.Create(holidayCode));
+ } else {
+ return new(eErrorType.Value);
+ }
+ }
+ var result = calculator.CalculateNumberOfWorkdays(startDate, endDate);
+ if (functionArguments.Length > 3) {
+ result = calculator.ReduceWorkdaysWithHolidays(result, functionArguments[3]);
+ }
+ return new(result.NumberOfWorkdays, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Now.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Now.cs
new file mode 100644
index 0000000..c78c2f4
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Now.cs
@@ -0,0 +1,36 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Now : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ return CreateResult(System.DateTime.Now.ToOADate(), DataType.Date);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Second.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Second.cs
new file mode 100644
index 0000000..353d043
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Second.cs
@@ -0,0 +1,40 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Second : DateParsingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var dateObj = arguments.ElementAt(0).Value;
+ System.DateTime date = ParseDate(arguments, dateObj);
+ return CreateResult(date.Second, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Time.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Time.cs
new file mode 100644
index 0000000..4a38142
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Time.cs
@@ -0,0 +1,53 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Time : TimeBaseFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var firstArg = arguments.ElementAt(0).Value.ToString();
+ if (arguments.Count() == 1 && TimeStringParser.CanParse(firstArg)) {
+ var result = TimeStringParser.Parse(firstArg);
+ return new(result, DataType.Time);
+ }
+ ValidateArguments(arguments, 3);
+ var hour = ArgToInt(arguments, 0);
+ var min = ArgToInt(arguments, 1);
+ var sec = ArgToInt(arguments, 2);
+
+ ThrowArgumentExceptionIf(() => sec < 0 || sec > 59, "Invalid second: " + sec);
+ ThrowArgumentExceptionIf(() => min < 0 || min > 59, "Invalid minute: " + min);
+ ThrowArgumentExceptionIf(() => min < 0 || hour > 23, "Invalid hour: " + hour);
+
+ var secondsOfThisTime = (double)(hour * 60 * 60 + min * 60 + sec);
+ return CreateResult(GetTimeSerialNumber(secondsOfThisTime), DataType.Time);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/TimeBaseFunction.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/TimeBaseFunction.cs
new file mode 100644
index 0000000..557154e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/TimeBaseFunction.cs
@@ -0,0 +1,64 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public abstract class TimeBaseFunction : ExcelFunction {
+ protected TimeStringParser TimeStringParser { get; private set; } = new();
+
+ protected double SerialNumber { get; private set; }
+
+ public void ValidateAndInitSerialNumber(IEnumerable<FunctionArgument> arguments) {
+ ValidateArguments(arguments, 1);
+ SerialNumber = ArgToDecimal(arguments, 0);
+ }
+
+ protected double SecondsInADay => 24 * 60 * 60;
+
+ protected double GetTimeSerialNumber(double seconds) {
+ return seconds / SecondsInADay;
+ }
+
+ protected double GetSeconds(double serialNumber) {
+ return serialNumber * SecondsInADay;
+ }
+
+ protected double GetHour(double serialNumber) {
+ var seconds = GetSeconds(serialNumber);
+ return (int)seconds / (60 * 60);
+ }
+
+ protected double GetMinute(double serialNumber) {
+ var seconds = GetSeconds(serialNumber);
+ seconds -= GetHour(serialNumber) * 60 * 60;
+ return (seconds - (seconds % 60)) / 60;
+ }
+
+ protected double GetSecond(double serialNumber) {
+ return GetSeconds(serialNumber) % 60;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/TimeStringParser.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/TimeStringParser.cs
new file mode 100644
index 0000000..a94809c
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/TimeStringParser.cs
@@ -0,0 +1,109 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Text.RegularExpressions;
+
+namespace AppsheetEpplus;
+
+public class TimeStringParser {
+ private const string _regEx24 = @"^[0-9]{1,2}(\:[0-9]{1,2}){0,2}$";
+ private const string _regEx12 = @"^[0-9]{1,2}(\:[0-9]{1,2}){0,2}( PM| AM)$";
+
+ private double GetSerialNumber(int hour, int minute, int second) {
+ var secondsInADay = 24d * 60d * 60d;
+ return ((double)hour * 60 * 60 + (double)minute * 60 + second) / secondsInADay;
+ }
+
+ private void ValidateValues(int hour, int minute, int second) {
+ if (second < 0 || second > 59) {
+ throw new FormatException("Illegal value for second: " + second);
+ }
+ if (minute < 0 || minute > 59) {
+ throw new FormatException("Illegal value for minute: " + minute);
+ }
+ }
+
+ public virtual double Parse(string input) {
+ return InternalParse(input);
+ }
+
+ public virtual bool CanParse(string input) {
+ System.DateTime dt;
+ return Regex.IsMatch(input, _regEx24)
+ || Regex.IsMatch(input, _regEx12)
+ || System.DateTime.TryParse(input, out dt);
+ }
+
+ private double InternalParse(string input) {
+ if (Regex.IsMatch(input, _regEx24)) {
+ return Parse24HourTimeString(input);
+ }
+ if (Regex.IsMatch(input, _regEx12)) {
+ return Parse12HourTimeString(input);
+ }
+ if (System.DateTime.TryParse(input, out var dateTime)) {
+ return GetSerialNumber(dateTime.Hour, dateTime.Minute, dateTime.Second);
+ }
+ return -1;
+ }
+
+ private double Parse12HourTimeString(string input) {
+ var dayPart = input.Substring(input.Length - 2, 2);
+ GetValuesFromString(input, out var hour, out var minute, out var second);
+ if (dayPart == "PM") {
+ hour += 12;
+ }
+ ValidateValues(hour, minute, second);
+ return GetSerialNumber(hour, minute, second);
+ }
+
+ private double Parse24HourTimeString(string input) {
+ GetValuesFromString(input, out var hour, out var minute, out var second);
+ ValidateValues(hour, minute, second);
+ return GetSerialNumber(hour, minute, second);
+ }
+
+ private static void GetValuesFromString(
+ string input,
+ out int hour,
+ out int minute,
+ out int second) {
+ hour = 0;
+ minute = 0;
+ second = 0;
+
+ var items = input.Split(':');
+ hour = int.Parse(items[0]);
+ if (items.Length > 1) {
+ minute = int.Parse(items[1]);
+ }
+ if (items.Length > 2) {
+ var val = items[2];
+ val = Regex.Replace(val, "[^0-9]+$", string.Empty);
+ second = int.Parse(val);
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/TimeValue.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/TimeValue.cs
new file mode 100644
index 0000000..dcdc584
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/TimeValue.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Simple implementation of TimeValue function, just using .NET built-in
+/// function System.DateTime.TryParse, based on current culture
+/// </summary>
+public class TimeValue : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var dateString = ArgToString(arguments, 0);
+ return Execute(dateString);
+ }
+
+ internal CompileResult Execute(string dateString) {
+ System.DateTime.TryParse(dateString, out var result);
+ return result != System.DateTime.MinValue
+ ? CreateResult(GetTimeValue(result), DataType.Date)
+ : CreateResult(ExcelErrorValue.Create(eErrorType.Value), DataType.ExcelError);
+ }
+
+ private double GetTimeValue(System.DateTime result) {
+ return (int)result.TimeOfDay.TotalSeconds == 0
+ ? 0d
+ : result.TimeOfDay.TotalSeconds / (3600 * 24);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Today.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Today.cs
new file mode 100644
index 0000000..8a899e0
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Today.cs
@@ -0,0 +1,36 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Today : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ return CreateResult(System.DateTime.Today.ToOADate(), DataType.Date);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Weekday.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Weekday.cs
new file mode 100644
index 0000000..e62fba7
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Weekday.cs
@@ -0,0 +1,60 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Weekday : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var serialNumber = ArgToDecimal(arguments, 0);
+ var returnType = arguments.Count() > 1 ? ArgToInt(arguments, 1) : 1;
+ return CreateResult(
+ CalculateDayOfWeek(System.DateTime.FromOADate(serialNumber), returnType),
+ DataType.Integer);
+ }
+
+ private static readonly List<int> _oneBasedStartOnSunday = [1, 2, 3, 4, 5, 6, 7];
+ private static readonly List<int> _oneBasedStartOnMonday = [7, 1, 2, 3, 4, 5, 6];
+ private static readonly List<int> _zeroBasedStartOnSunday = [6, 0, 1, 2, 3, 4, 5];
+
+ private int CalculateDayOfWeek(System.DateTime dateTime, int returnType) {
+ var dayIx = (int)dateTime.DayOfWeek;
+ switch (returnType) {
+ case 1:
+ return _oneBasedStartOnSunday[dayIx];
+ case 2:
+ return _oneBasedStartOnMonday[dayIx];
+ case 3:
+ return _zeroBasedStartOnSunday[dayIx];
+ default:
+ throw new ExcelErrorValueException(eErrorType.Num);
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Weeknum.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Weeknum.cs
new file mode 100644
index 0000000..4706399
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Weeknum.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Weeknum : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1, eErrorType.Value);
+ var dateSerial = ArgToDecimal(arguments, 0);
+ var date = System.DateTime.FromOADate(dateSerial);
+ var startDay = DayOfWeek.Sunday;
+ if (arguments.Count() > 1) {
+ var argStartDay = ArgToInt(arguments, 1);
+ switch (argStartDay) {
+ case 1:
+ startDay = DayOfWeek.Sunday;
+ break;
+ case 2:
+ case 11:
+ startDay = DayOfWeek.Monday;
+ break;
+ case 12:
+ startDay = DayOfWeek.Tuesday;
+ break;
+ case 13:
+ startDay = DayOfWeek.Wednesday;
+ break;
+ case 14:
+ startDay = DayOfWeek.Thursday;
+ break;
+ case 15:
+ startDay = DayOfWeek.Friday;
+ break;
+ case 16:
+ startDay = DayOfWeek.Saturday;
+ break;
+ default:
+ // Not supported
+ ThrowExcelErrorValueException(eErrorType.Num);
+ break;
+ }
+ }
+ if (DateTimeFormatInfo.CurrentInfo == null) {
+ throw new InvalidOperationException(
+ "Could not execute Weeknum function because DateTimeFormatInfo.CurrentInfo was null");
+ }
+ var week = DateTimeFormatInfo.CurrentInfo.Calendar.GetWeekOfYear(
+ date,
+ CalendarWeekRule.FirstDay,
+ startDay);
+ return CreateResult(week, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workday.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workday.cs
new file mode 100644
index 0000000..a5649b8
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workday.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Workday : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var startDate = System.DateTime.FromOADate(ArgToInt(arguments, 0));
+ var nWorkDays = ArgToInt(arguments, 1);
+ var resultDate = System.DateTime.MinValue;
+ var workdaysCounted = 0;
+ var tmpDate = startDate;
+ // first move forward to the first monday
+ while (tmpDate.DayOfWeek != DayOfWeek.Monday && (nWorkDays - workdaysCounted) > 0) {
+ if (!IsHoliday(tmpDate)) {
+ workdaysCounted++;
+ }
+ tmpDate = tmpDate.AddDays(1);
+ }
+ // then calculate whole weeks
+ var nWholeWeeks = (nWorkDays - workdaysCounted) / 5;
+ tmpDate = tmpDate.AddDays(nWholeWeeks * 7);
+ workdaysCounted += nWholeWeeks * 5;
+
+ // calculate the rest
+ while (workdaysCounted < nWorkDays) {
+ tmpDate = tmpDate.AddDays(1);
+ if (!IsHoliday(tmpDate)) {
+ workdaysCounted++;
+ }
+ }
+ resultDate = AdjustResultWithHolidays(tmpDate, arguments);
+ return CreateResult(resultDate.ToOADate(), DataType.Date);
+ }
+
+ private System.DateTime AdjustResultWithHolidays(
+ System.DateTime resultDate,
+ IEnumerable<FunctionArgument> arguments) {
+ if (arguments.Count() == 2) {
+ return resultDate;
+ }
+ var holidays = arguments.ElementAt(2).Value as IEnumerable<FunctionArgument>;
+ if (holidays != null) {
+ foreach (var arg in holidays) {
+ if (ConvertUtil.IsNumeric(arg.Value)) {
+ var dateSerial = ConvertUtil.GetValueDouble(arg.Value);
+ var holidayDate = System.DateTime.FromOADate(dateSerial);
+ if (!IsHoliday(holidayDate)) {
+ resultDate = resultDate.AddDays(1);
+ }
+ }
+ }
+ } else {
+ var range = arguments.ElementAt(2).Value as ExcelDataProvider.IRangeInfo;
+ if (range != null) {
+ foreach (var cell in range) {
+ if (ConvertUtil.IsNumeric(cell.Value)) {
+ var dateSerial = ConvertUtil.GetValueDouble(cell.Value);
+ var holidayDate = System.DateTime.FromOADate(dateSerial);
+ if (!IsHoliday(holidayDate)) {
+ resultDate = resultDate.AddDays(1);
+ }
+ }
+ }
+ }
+ }
+ return resultDate;
+ }
+
+ private bool IsHoliday(System.DateTime date) {
+ return date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/AdditionalHolidayDays.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/AdditionalHolidayDays.cs
new file mode 100644
index 0000000..7aef11b
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/AdditionalHolidayDays.cs
@@ -0,0 +1,40 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class AdditionalHolidayDays {
+ private readonly FunctionArgument _holidayArg;
+ private readonly List<System.DateTime> _holidayDates = new();
+
+ public AdditionalHolidayDays(FunctionArgument holidayArg) {
+ _holidayArg = holidayArg;
+ Initialize();
+ }
+
+ public IEnumerable<System.DateTime> AdditionalDates => _holidayDates;
+
+ private void Initialize() {
+ var holidays = _holidayArg.Value as IEnumerable<FunctionArgument>;
+ if (holidays != null) {
+ foreach (var holidayDate in from arg in holidays
+ where ConvertUtil.IsNumeric(arg.Value)
+ select ConvertUtil.GetValueDouble(arg.Value) into dateSerial
+ select System.DateTime.FromOADate(dateSerial)) {
+ _holidayDates.Add(holidayDate);
+ }
+ }
+ var range = _holidayArg.Value as ExcelDataProvider.IRangeInfo;
+ if (range != null) {
+ foreach (var holidayDate in from cell in range
+ where ConvertUtil.IsNumeric(cell.Value)
+ select ConvertUtil.GetValueDouble(cell.Value) into dateSerial
+ select System.DateTime.FromOADate(dateSerial)) {
+ _holidayDates.Add(holidayDate);
+ }
+ }
+ if (ConvertUtil.IsNumeric(_holidayArg.Value)) {
+ _holidayDates.Add(System.DateTime.FromOADate(ConvertUtil.GetValueDouble(_holidayArg.Value)));
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdays.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdays.cs
new file mode 100644
index 0000000..0beea5a
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdays.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class HolidayWeekdays {
+ private readonly List<DayOfWeek> _holidayDays = new();
+
+ public HolidayWeekdays()
+ : this(DayOfWeek.Saturday, DayOfWeek.Sunday) {}
+
+ public int NumberOfWorkdaysPerWeek => 7 - _holidayDays.Count;
+
+ public HolidayWeekdays(params DayOfWeek[] holidayDays) {
+ foreach (var dayOfWeek in holidayDays) {
+ _holidayDays.Add(dayOfWeek);
+ }
+ }
+
+ public bool IsHolidayWeekday(System.DateTime dateTime) {
+ return _holidayDays.Contains(dateTime.DayOfWeek);
+ }
+
+ public System.DateTime AdjustResultWithHolidays(
+ System.DateTime resultDate,
+ IEnumerable<FunctionArgument> arguments) {
+ if (arguments.Count() == 2) {
+ return resultDate;
+ }
+ var holidays = arguments.ElementAt(2).Value as IEnumerable<FunctionArgument>;
+ if (holidays != null) {
+ foreach (var arg in holidays) {
+ if (ConvertUtil.IsNumeric(arg.Value)) {
+ var dateSerial = ConvertUtil.GetValueDouble(arg.Value);
+ var holidayDate = System.DateTime.FromOADate(dateSerial);
+ if (!IsHolidayWeekday(holidayDate)) {
+ resultDate = resultDate.AddDays(1);
+ }
+ }
+ }
+ } else {
+ var range = arguments.ElementAt(2).Value as ExcelDataProvider.IRangeInfo;
+ if (range != null) {
+ foreach (var cell in range) {
+ if (ConvertUtil.IsNumeric(cell.Value)) {
+ var dateSerial = ConvertUtil.GetValueDouble(cell.Value);
+ var holidayDate = System.DateTime.FromOADate(dateSerial);
+ if (!IsHolidayWeekday(holidayDate)) {
+ resultDate = resultDate.AddDays(1);
+ }
+ }
+ }
+ }
+ }
+ return resultDate;
+ }
+
+ public System.DateTime GetNextWorkday(
+ System.DateTime date,
+ WorkdayCalculationDirection direction = WorkdayCalculationDirection.Forward) {
+ var changeParam = (int)direction;
+ var tmpDate = date.AddDays(changeParam);
+ while (IsHolidayWeekday(tmpDate)) {
+ tmpDate = tmpDate.AddDays(changeParam);
+ }
+ return tmpDate;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdaysFactory.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdaysFactory.cs
new file mode 100644
index 0000000..60b3177
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdaysFactory.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class HolidayWeekdaysFactory {
+ private readonly DayOfWeek[] _dayOfWeekArray = [
+ DayOfWeek.Monday,
+ DayOfWeek.Tuesday,
+ DayOfWeek.Wednesday,
+ DayOfWeek.Thursday,
+ DayOfWeek.Friday,
+ DayOfWeek.Saturday,
+ DayOfWeek.Sunday,
+ ];
+
+ public HolidayWeekdays Create(string weekdays) {
+ if (string.IsNullOrEmpty(weekdays) || weekdays.Length != 7) {
+ throw new ArgumentException("Illegal weekday string", nameof(Weekday));
+ }
+
+ var retVal = new List<DayOfWeek>();
+ var arr = weekdays.ToCharArray();
+ for (var i = 0; i < arr.Length; i++) {
+ var ch = arr[i];
+ if (ch == '1') {
+ retVal.Add(_dayOfWeekArray[i]);
+ }
+ }
+ return new(retVal.ToArray());
+ }
+
+ public HolidayWeekdays Create(int code) {
+ switch (code) {
+ case 1:
+ return new(DayOfWeek.Saturday, DayOfWeek.Sunday);
+ case 2:
+ return new(DayOfWeek.Sunday, DayOfWeek.Monday);
+ case 3:
+ return new(DayOfWeek.Monday, DayOfWeek.Tuesday);
+ case 4:
+ return new(DayOfWeek.Tuesday, DayOfWeek.Wednesday);
+ case 5:
+ return new(DayOfWeek.Wednesday, DayOfWeek.Thursday);
+ case 6:
+ return new(DayOfWeek.Thursday, DayOfWeek.Friday);
+ case 7:
+ return new(DayOfWeek.Friday, DayOfWeek.Saturday);
+ case 11:
+ return new(DayOfWeek.Sunday);
+ case 12:
+ return new(DayOfWeek.Monday);
+ case 13:
+ return new(DayOfWeek.Tuesday);
+ case 14:
+ return new(DayOfWeek.Wednesday);
+ case 15:
+ return new(DayOfWeek.Thursday);
+ case 16:
+ return new(DayOfWeek.Friday);
+ case 17:
+ return new(DayOfWeek.Saturday);
+ default:
+ throw new ArgumentException("Invalid code supplied to HolidayWeekdaysFactory: " + code);
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculationDirection.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculationDirection.cs
new file mode 100644
index 0000000..1eaf0d3
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculationDirection.cs
@@ -0,0 +1,6 @@
+namespace AppsheetEpplus;
+
+public enum WorkdayCalculationDirection {
+ Forward = 1,
+ Backward = -1,
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculator.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculator.cs
new file mode 100644
index 0000000..b9c031e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculator.cs
@@ -0,0 +1,123 @@
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class WorkdayCalculator {
+ private readonly HolidayWeekdays _holidayWeekdays;
+
+ public WorkdayCalculator()
+ : this(new()) {}
+
+ public WorkdayCalculator(HolidayWeekdays holidayWeekdays) {
+ _holidayWeekdays = holidayWeekdays;
+ }
+
+ public WorkdayCalculatorResult CalculateNumberOfWorkdays(
+ System.DateTime startDate,
+ System.DateTime endDate) {
+ var calcDirection =
+ startDate < endDate
+ ? WorkdayCalculationDirection.Forward
+ : WorkdayCalculationDirection.Backward;
+ System.DateTime calcStartDate;
+ System.DateTime calcEndDate;
+ if (calcDirection == WorkdayCalculationDirection.Forward) {
+ calcStartDate = startDate.Date;
+ calcEndDate = endDate.Date;
+ } else {
+ calcStartDate = endDate.Date;
+ calcEndDate = startDate.Date;
+ }
+ var nWholeWeeks = (int)calcEndDate.Subtract(calcStartDate).TotalDays / 7;
+ var workdaysCounted = nWholeWeeks * _holidayWeekdays.NumberOfWorkdaysPerWeek;
+ if (!_holidayWeekdays.IsHolidayWeekday(calcStartDate)) {
+ workdaysCounted++;
+ }
+ var tmpDate = calcStartDate.AddDays(nWholeWeeks * 7);
+ while (tmpDate < calcEndDate) {
+ tmpDate = tmpDate.AddDays(1);
+ if (!_holidayWeekdays.IsHolidayWeekday(tmpDate)) {
+ workdaysCounted++;
+ }
+ }
+ return new(workdaysCounted, startDate, endDate, calcDirection);
+ }
+
+ public WorkdayCalculatorResult CalculateWorkday(System.DateTime startDate, int nWorkDays) {
+ var calcDirection =
+ nWorkDays > 0 ? WorkdayCalculationDirection.Forward : WorkdayCalculationDirection.Backward;
+ var direction = (int)calcDirection;
+ nWorkDays *= direction;
+ var workdaysCounted = 0;
+ var tmpDate = startDate;
+
+ // calculate whole weeks
+ var nWholeWeeks = nWorkDays / _holidayWeekdays.NumberOfWorkdaysPerWeek;
+ tmpDate = tmpDate.AddDays(nWholeWeeks * 7 * direction);
+ workdaysCounted += nWholeWeeks * _holidayWeekdays.NumberOfWorkdaysPerWeek;
+
+ // calculate the rest
+ while (workdaysCounted < nWorkDays) {
+ tmpDate = tmpDate.AddDays(direction);
+ if (!_holidayWeekdays.IsHolidayWeekday(tmpDate)) {
+ workdaysCounted++;
+ }
+ }
+ return new(workdaysCounted, startDate, tmpDate, calcDirection);
+ }
+
+ public WorkdayCalculatorResult ReduceWorkdaysWithHolidays(
+ WorkdayCalculatorResult calculatedResult,
+ FunctionArgument holidayArgument) {
+ var startDate = calculatedResult.StartDate;
+ var endDate = calculatedResult.EndDate;
+ var additionalDays = new AdditionalHolidayDays(holidayArgument);
+ System.DateTime calcStartDate;
+ System.DateTime calcEndDate;
+ if (startDate < endDate) {
+ calcStartDate = startDate;
+ calcEndDate = endDate;
+ } else {
+ calcStartDate = endDate;
+ calcEndDate = startDate;
+ }
+ var nAdditionalHolidayDays = additionalDays.AdditionalDates.Count(x =>
+ x >= calcStartDate && x <= calcEndDate && !_holidayWeekdays.IsHolidayWeekday(x));
+ return new(
+ calculatedResult.NumberOfWorkdays - nAdditionalHolidayDays,
+ startDate,
+ endDate,
+ calculatedResult.Direction);
+ }
+
+ public WorkdayCalculatorResult AdjustResultWithHolidays(
+ WorkdayCalculatorResult calculatedResult,
+ FunctionArgument holidayArgument) {
+ var startDate = calculatedResult.StartDate;
+ var endDate = calculatedResult.EndDate;
+ var direction = calculatedResult.Direction;
+ var workdaysCounted = calculatedResult.NumberOfWorkdays;
+ var additionalDays = new AdditionalHolidayDays(holidayArgument);
+ foreach (var date in additionalDays.AdditionalDates) {
+ if (direction == WorkdayCalculationDirection.Forward
+ && (date < startDate || date > endDate)) {
+ continue;
+ }
+ if (direction == WorkdayCalculationDirection.Backward
+ && (date > startDate || date < endDate)) {
+ continue;
+ }
+ if (_holidayWeekdays.IsHolidayWeekday(date)) {
+ continue;
+ }
+ var tmpDate = _holidayWeekdays.GetNextWorkday(endDate, direction);
+ while (additionalDays.AdditionalDates.Contains(tmpDate)) {
+ tmpDate = _holidayWeekdays.GetNextWorkday(tmpDate, direction);
+ }
+ workdaysCounted++;
+ endDate = tmpDate;
+ }
+
+ return new(workdaysCounted, calculatedResult.StartDate, endDate, direction);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculatorResult.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculatorResult.cs
new file mode 100644
index 0000000..9583d95
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculatorResult.cs
@@ -0,0 +1,22 @@
+namespace AppsheetEpplus;
+
+public class WorkdayCalculatorResult {
+ public WorkdayCalculatorResult(
+ int numberOfWorkdays,
+ System.DateTime startDate,
+ System.DateTime endDate,
+ WorkdayCalculationDirection direction) {
+ NumberOfWorkdays = numberOfWorkdays;
+ StartDate = startDate;
+ EndDate = endDate;
+ Direction = direction;
+ }
+
+ public int NumberOfWorkdays { get; }
+
+ public System.DateTime StartDate { get; }
+
+ public System.DateTime EndDate { get; }
+
+ public WorkdayCalculationDirection Direction { get; set; }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Year.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Year.cs
new file mode 100644
index 0000000..d719bff
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Year.cs
@@ -0,0 +1,46 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Year : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var dateObj = arguments.ElementAt(0).Value;
+ System.DateTime date = System.DateTime.MinValue;
+ if (dateObj is string) {
+ date = System.DateTime.Parse(dateObj.ToString());
+ } else {
+ var d = ArgToDecimal(arguments, 0);
+ date = System.DateTime.FromOADate(d);
+ }
+ return CreateResult(date.Year, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Yearfrac.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Yearfrac.cs
new file mode 100644
index 0000000..b59fcf0
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DateTime/Yearfrac.cs
@@ -0,0 +1,84 @@
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Yearfrac : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
+ ValidateArguments(functionArguments, 2);
+ var date1Num = ArgToDecimal(functionArguments, 0);
+ var date2Num = ArgToDecimal(functionArguments, 1);
+ if (date1Num
+ > date2Num) //Switch to make date1 the lowest date
+ {
+ var t = date1Num;
+ date1Num = date2Num;
+ date2Num = t;
+ var fa = functionArguments[1];
+ functionArguments[1] = functionArguments[0];
+ functionArguments[0] = fa;
+ }
+ var date1 = System.DateTime.FromOADate(date1Num);
+ var date2 = System.DateTime.FromOADate(date2Num);
+
+ var basis = 0;
+ if (functionArguments.Count() > 2) {
+ basis = ArgToInt(functionArguments, 2);
+ ThrowExcelErrorValueExceptionIf(() => basis < 0 || basis > 4, eErrorType.Num);
+ }
+ var func = context.Configuration.FunctionRepository.GetFunction("days360");
+ var calendar = new GregorianCalendar();
+ switch (basis) {
+ case 0:
+ var d360Result = System.Math.Abs(func.Execute(functionArguments, context).ResultNumeric);
+ // reproducing excels behaviour
+ if (date1.Month == 2 && date2.Day == 31) {
+ var daysInFeb = calendar.IsLeapYear(date1.Year) ? 29 : 28;
+ if (date1.Day == daysInFeb) {
+ d360Result++;
+ }
+ }
+ return CreateResult(d360Result / 360d, DataType.Decimal);
+ case 1:
+ return CreateResult(
+ System.Math.Abs((date2 - date1).TotalDays / CalculateAcutalYear(date1, date2)),
+ DataType.Decimal);
+ case 2:
+ return CreateResult(System.Math.Abs((date2 - date1).TotalDays / 360d), DataType.Decimal);
+ case 3:
+ return CreateResult(System.Math.Abs((date2 - date1).TotalDays / 365d), DataType.Decimal);
+ case 4:
+ var args = functionArguments.ToList();
+ args.Add(new(true));
+ double? result = System.Math.Abs(func.Execute(args, context).ResultNumeric / 360d);
+ return CreateResult(result.Value, DataType.Decimal);
+ default:
+ return null;
+ }
+ }
+
+ private double CalculateAcutalYear(System.DateTime dt1, System.DateTime dt2) {
+ var calendar = new GregorianCalendar();
+ var perYear = 0d;
+ var nYears = dt2.Year - dt1.Year + 1;
+ for (var y = dt1.Year; y <= dt2.Year; ++y) {
+ perYear += calendar.IsLeapYear(y) ? 366 : 365;
+ }
+ if (new System.DateTime(dt1.Year + 1, dt1.Month, dt1.Day) >= dt2) {
+ nYears = 1;
+ perYear = 365;
+ if (calendar.IsLeapYear(dt1.Year) && dt1.Month <= 2) {
+ perYear = 366;
+ } else if (calendar.IsLeapYear(dt2.Year) && dt2.Month > 2) {
+ perYear = 366;
+ } else if (dt2.Month == 2 && dt2.Day == 29) {
+ perYear = 366;
+ }
+ }
+ return perYear / nYears;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DecimalCompileResultValidator.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DecimalCompileResultValidator.cs
new file mode 100644
index 0000000..8ef9011
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DecimalCompileResultValidator.cs
@@ -0,0 +1,36 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-26
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public class DecimalCompileResultValidator : CompileResultValidator {
+ public override void Validate(object obj) {
+ var num = ConvertUtil.GetValueDouble(obj);
+ if (double.IsNaN(num) || double.IsInfinity(num)) {
+ throw new ExcelErrorValueException(eErrorType.Num);
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DoubleArgumentParser.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DoubleArgumentParser.cs
new file mode 100644
index 0000000..ea04b67
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DoubleArgumentParser.cs
@@ -0,0 +1,52 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Globalization;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class DoubleArgumentParser : ArgumentParser {
+ public override object Parse(object obj) {
+ Require.That(obj).Named("argument").IsNotNull();
+ if (obj is ExcelDataProvider.IRangeInfo info) {
+ var r = info.FirstOrDefault();
+ return r?.ValueDouble ?? 0;
+ }
+ if (obj is double) {
+ return obj;
+ }
+ if (obj.IsNumeric()) {
+ return ConvertUtil.GetValueDouble(obj);
+ }
+ var str = obj != null ? obj.ToString() : string.Empty;
+ try {
+ return double.Parse(str, CultureInfo.InvariantCulture);
+ } catch // (Exception e)
+ {
+ throw new ExcelErrorValueException(ExcelErrorValue.Create(eErrorType.Value));
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/DoubleEnumerableArgConverter.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/DoubleEnumerableArgConverter.cs
new file mode 100644
index 0000000..fcf6908
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/DoubleEnumerableArgConverter.cs
@@ -0,0 +1,82 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class DoubleEnumerableArgConverter : CollectionFlattener<double> {
+ public virtual IEnumerable<double> ConvertArgs(
+ bool ignoreHidden,
+ bool ignoreErrors,
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ return base.FuncArgsToFlatEnumerable(
+ arguments,
+ (arg, argList) => {
+ if (arg.IsExcelRange) {
+ foreach (var cell in arg.ValueAsRangeInfo) {
+ if (!ignoreErrors && cell.IsExcelError) {
+ throw new ExcelErrorValueException(ExcelErrorValue.Parse(cell.Value.ToString()));
+ }
+ if (!CellStateHelper.ShouldIgnore(ignoreHidden, cell, context)
+ && ConvertUtil.IsNumeric(cell.Value)) {
+ argList.Add(cell.ValueDouble);
+ }
+ }
+ } else {
+ if (!ignoreErrors && arg.ValueIsExcelError) {
+ throw new ExcelErrorValueException(arg.ValueAsExcelErrorValue);
+ }
+ if (ConvertUtil.IsNumeric(arg.Value)
+ && !CellStateHelper.ShouldIgnore(ignoreHidden, arg, context)) {
+ argList.Add(ConvertUtil.GetValueDouble(arg.Value));
+ }
+ }
+ });
+ }
+
+ public virtual IEnumerable<double> ConvertArgsIncludingOtherTypes(
+ IEnumerable<FunctionArgument> arguments) {
+ return base.FuncArgsToFlatEnumerable(
+ arguments,
+ (arg, argList) => {
+ //var cellInfo = arg.Value as EpplusExcelDataProvider.CellInfo;
+ //var value = cellInfo != null ? cellInfo.Value : arg.Value;
+ if (arg.Value is ExcelDataProvider.IRangeInfo info) {
+ foreach (var cell in info) {
+ argList.Add(cell.ValueDoubleLogical);
+ }
+ } else {
+ if (arg.Value is double || arg.Value is int || arg.Value is bool) {
+ argList.Add(Convert.ToDouble(arg.Value));
+ } else if (arg.Value is string) {
+ argList.Add(0d);
+ }
+ }
+ });
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/ErrorHandlingFunction.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/ErrorHandlingFunction.cs
new file mode 100644
index 0000000..c63545b
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/ErrorHandlingFunction.cs
@@ -0,0 +1,47 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Base class for functions that handles an error that occurs during the
+/// normal execution of the function.
+/// If an exception occurs during the Execute-call that exception will be
+/// caught by the compiler, then the HandleError-method will be called.
+/// </summary>
+public abstract class ErrorHandlingFunction : ExcelFunction {
+ /// <summary>
+ /// Indicates that the function is an ErrorHandlingFunction.
+ /// </summary>
+ public override bool IsErrorHandlingFunction => true;
+
+ /// <summary>
+ /// Method that should be implemented to handle the error.
+ /// </summary>
+ /// <param name="errorCode"></param>
+ /// <returns></returns>
+ public abstract CompileResult HandleError(string errorCode);
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/ExcelFunction.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/ExcelFunction.cs
new file mode 100644
index 0000000..3a359ae
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/ExcelFunction.cs
@@ -0,0 +1,436 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Base class for Excel function implementations.
+/// </summary>
+public abstract class ExcelFunction {
+ public ExcelFunction()
+ : this(new(), new(), new()) {}
+
+ public ExcelFunction(
+ ArgumentCollectionUtil argumentCollectionUtil,
+ ArgumentParsers argumentParsers,
+ CompileResultValidators compileResultValidators) {
+ _argumentCollectionUtil = argumentCollectionUtil;
+ _argumentParsers = argumentParsers;
+ _compileResultValidators = compileResultValidators;
+ }
+
+ private readonly ArgumentCollectionUtil _argumentCollectionUtil;
+ private readonly ArgumentParsers _argumentParsers;
+ private readonly CompileResultValidators _compileResultValidators;
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="arguments">Arguments to the function, each argument can contain primitive types, lists or <see cref="ExcelDataProvider.IRangeInfo">Excel ranges</see></param>
+ /// <param name="context">The <see cref="ParsingContext"/> contains various data that can be useful in functions.</param>
+ /// <returns>A <see cref="CompileResult"/> containing the calculated value</returns>
+ public abstract CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context);
+
+ /// <summary>
+ /// If overridden, this method is called before Execute is called.
+ /// </summary>
+ /// <param name="context"></param>
+ public virtual void BeforeInvoke(ParsingContext context) {}
+
+ public virtual bool IsLookupFuction => false;
+
+ public virtual bool IsErrorHandlingFunction => false;
+
+ /// <summary>
+ /// Used for some Lookupfunctions to indicate that function arguments should
+ /// not be compiled before the function is called.
+ /// </summary>
+ public bool SkipArgumentEvaluation { get; set; }
+
+ protected object GetFirstValue(IEnumerable<FunctionArgument> val) {
+ var arg = val.FirstOrDefault();
+ if (arg.Value is ExcelDataProvider.IRangeInfo) {
+ //var r=((ExcelDataProvider.IRangeInfo)arg);
+ var r = arg.ValueAsRangeInfo;
+ return r.GetValue(r.Address._fromRow, r.Address._fromCol);
+ }
+ return arg?.Value;
+ }
+
+ /// <summary>
+ /// This functions validates that the supplied <paramref name="arguments"/> contains at least
+ /// (the value of) <paramref name="minLength"/> elements. If one of the arguments is an
+ /// <see cref="ExcelDataProvider.IRangeInfo">Excel range</see> the number of cells in
+ /// that range will be counted as well.
+ /// </summary>
+ /// <param name="arguments"></param>
+ /// <param name="minLength"></param>
+ /// <param name="errorTypeToThrow">The <see cref="eErrorType"/> of the <see cref="ExcelErrorValueException"/> that will be thrown if <paramref name="minLength"/> is not met.</param>
+ protected void ValidateArguments(
+ IEnumerable<FunctionArgument> arguments,
+ int minLength,
+ eErrorType errorTypeToThrow) {
+ Require.That(arguments).Named("arguments").IsNotNull();
+ ThrowExcelErrorValueExceptionIf(
+ () => {
+ var nArgs = 0;
+ if (arguments.Any()) {
+ foreach (var arg in arguments) {
+ nArgs++;
+ if (nArgs >= minLength) {
+ return false;
+ }
+ if (arg.IsExcelRange) {
+ nArgs += arg.ValueAsRangeInfo.GetNCells();
+ if (nArgs >= minLength) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ },
+ errorTypeToThrow);
+ }
+
+ /// <summary>
+ /// This functions validates that the supplied <paramref name="arguments"/> contains at least
+ /// (the value of) <paramref name="minLength"/> elements. If one of the arguments is an
+ /// <see cref="ExcelDataProvider.IRangeInfo">Excel range</see> the number of cells in
+ /// that range will be counted as well.
+ /// </summary>
+ /// <param name="arguments"></param>
+ /// <param name="minLength"></param>
+ /// <exception cref="ArgumentException"></exception>
+ protected void ValidateArguments(IEnumerable<FunctionArgument> arguments, int minLength) {
+ Require.That(arguments).Named("arguments").IsNotNull();
+ ThrowArgumentExceptionIf(
+ () => {
+ var nArgs = 0;
+ if (arguments.Any()) {
+ foreach (var arg in arguments) {
+ nArgs++;
+ if (nArgs >= minLength) {
+ return false;
+ }
+ if (arg.IsExcelRange) {
+ nArgs += arg.ValueAsRangeInfo.GetNCells();
+ if (nArgs >= minLength) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ },
+ "Expecting at least {0} arguments",
+ minLength.ToString());
+ }
+
+ /// <summary>
+ /// Returns the value of the argument att the position of the 0-based
+ /// <paramref name="index"/> as an integer.
+ /// </summary>
+ /// <param name="arguments"></param>
+ /// <param name="index"></param>
+ /// <returns>Value of the argument as an integer.</returns>
+ /// <exception cref="ExcelErrorValueException"></exception>
+ protected int ArgToInt(IEnumerable<FunctionArgument> arguments, int index) {
+ var val = arguments.ElementAt(index).ValueFirst;
+ return (int)_argumentParsers.GetParser(DataType.Integer).Parse(val);
+ }
+
+ /// <summary>
+ /// Returns the value of the argument att the position of the 0-based
+ /// <paramref name="index"/> as a string.
+ /// </summary>
+ /// <param name="arguments"></param>
+ /// <param name="index"></param>
+ /// <returns>Value of the argument as a string.</returns>
+ protected string ArgToString(IEnumerable<FunctionArgument> arguments, int index) {
+ var obj = arguments.ElementAt(index).ValueFirst;
+ return obj != null ? obj.ToString() : string.Empty;
+ }
+
+ /// <summary>
+ /// Returns the value of the argument att the position of the 0-based
+ /// </summary>
+ /// <param name="obj"></param>
+ /// <returns>Value of the argument as a double.</returns>
+ /// <exception cref="ExcelErrorValueException"></exception>
+ protected double ArgToDecimal(object obj) {
+ return (double)_argumentParsers.GetParser(DataType.Decimal).Parse(obj);
+ }
+
+ /// <summary>
+ /// Returns the value of the argument att the position of the 0-based
+ /// <paramref name="index"/> as a <see cref="System.Double"/>.
+ /// </summary>
+ /// <param name="arguments"></param>
+ /// <param name="index"></param>
+ /// <returns>Value of the argument as an integer.</returns>
+ /// <exception cref="ExcelErrorValueException"></exception>
+ protected double ArgToDecimal(IEnumerable<FunctionArgument> arguments, int index) {
+ return ArgToDecimal(arguments.ElementAt(index).Value);
+ }
+
+ protected double Divide(double left, double right) {
+ if (System.Math.Abs(right - 0d) < double.Epsilon) {
+ throw new ExcelErrorValueException(eErrorType.Div0);
+ }
+ return left / right;
+ }
+
+ protected bool IsNumericString(object value) {
+ if (value == null || string.IsNullOrEmpty(value.ToString())) {
+ return false;
+ }
+ return Regex.IsMatch(value.ToString(), @"^[\d]+(\,[\d])?");
+ }
+
+ /// <summary>
+ /// If the argument is a boolean value its value will be returned.
+ /// If the argument is an integer value, true will be returned if its
+ /// value is not 0, otherwise false.
+ /// </summary>
+ /// <param name="arguments"></param>
+ /// <param name="index"></param>
+ /// <returns></returns>
+ protected bool ArgToBool(IEnumerable<FunctionArgument> arguments, int index) {
+ var obj = arguments.ElementAt(index).Value ?? string.Empty;
+ return (bool)_argumentParsers.GetParser(DataType.Boolean).Parse(obj);
+ }
+
+ /// <summary>
+ /// Throws an <see cref="ArgumentException"/> if <paramref name="condition"/> evaluates to true.
+ /// </summary>
+ /// <param name="condition"></param>
+ /// <param name="message"></param>
+ /// <exception cref="ArgumentException"></exception>
+ protected void ThrowArgumentExceptionIf(Func<bool> condition, string message) {
+ if (condition()) {
+ throw new ArgumentException(message);
+ }
+ }
+
+ /// <summary>
+ /// Throws an <see cref="ArgumentException"/> if <paramref name="condition"/> evaluates to true.
+ /// </summary>
+ /// <param name="condition"></param>
+ /// <param name="message"></param>
+ /// <param name="formats">Formats to the message string.</param>
+ protected void ThrowArgumentExceptionIf(
+ Func<bool> condition,
+ string message,
+ params object[] formats) {
+ message = string.Format(message, formats);
+ ThrowArgumentExceptionIf(condition, message);
+ }
+
+ /// <summary>
+ /// Throws an <see cref="ExcelErrorValueException"/> with the given <paramref name="errorType"/> set.
+ /// </summary>
+ /// <param name="errorType"></param>
+ protected void ThrowExcelErrorValueException(eErrorType errorType) {
+ throw new ExcelErrorValueException(
+ "An excel function error occurred",
+ ExcelErrorValue.Create(errorType));
+ }
+
+ /// <summary>
+ /// Throws an <see cref="ArgumentException"/> if <paramref name="condition"/> evaluates to true.
+ /// </summary>
+ /// <param name="condition"></param>
+ /// <param name="errorType"></param>
+ /// <exception cref="ExcelErrorValueException"></exception>
+ protected void ThrowExcelErrorValueExceptionIf(Func<bool> condition, eErrorType errorType) {
+ if (condition()) {
+ throw new ExcelErrorValueException(
+ "An excel function error occurred",
+ ExcelErrorValue.Create(errorType));
+ }
+ }
+
+ protected bool IsNumeric(object val) {
+ if (val == null) {
+ return false;
+ }
+ return (val.GetType().IsPrimitive
+ || val is double
+ || val is decimal
+ || val is System.DateTime
+ || val is TimeSpan);
+ }
+
+ //protected virtual bool IsNumber(object obj)
+ //{
+ // if (obj == null) return false;
+ // return (obj is int || obj is double || obj is short || obj is decimal || obj is long);
+ //}
+
+ /// <summary>
+ /// Helper method for comparison of two doubles.
+ /// </summary>
+ /// <param name="d1"></param>
+ /// <param name="d2"></param>
+ /// <returns></returns>
+ protected bool AreEqual(double d1, double d2) {
+ return System.Math.Abs(d1 - d2) < double.Epsilon;
+ }
+
+ /// <summary>
+ /// Will return the arguments as an enumerable of doubles.
+ /// </summary>
+ /// <param name="arguments"></param>
+ /// <param name="context"></param>
+ /// <returns></returns>
+ protected virtual IEnumerable<double> ArgsToDoubleEnumerable(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ return ArgsToDoubleEnumerable(false, arguments, context);
+ }
+
+ /// <summary>
+ /// Will return the arguments as an enumerable of doubles.
+ /// </summary>
+ /// <param name="ignoreHiddenCells">If a cell is hidden and this value is true the value of that cell will be ignored</param>
+ /// <param name="ignoreErrors">If a cell contains an error, that error will be ignored if this method is set to true</param>
+ /// <param name="arguments"></param>
+ /// <param name="context"></param>
+ /// <returns></returns>
+ protected virtual IEnumerable<double> ArgsToDoubleEnumerable(
+ bool ignoreHiddenCells,
+ bool ignoreErrors,
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ return _argumentCollectionUtil.ArgsToDoubleEnumerable(
+ ignoreHiddenCells,
+ ignoreErrors,
+ arguments,
+ context);
+ }
+
+ /// <summary>
+ /// Will return the arguments as an enumerable of doubles.
+ /// </summary>
+ /// <param name="ignoreHiddenCells">If a cell is hidden and this value is true the value of that cell will be ignored</param>
+ /// <param name="arguments"></param>
+ /// <param name="context"></param>
+ /// <returns></returns>
+ protected virtual IEnumerable<double> ArgsToDoubleEnumerable(
+ bool ignoreHiddenCells,
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ return ArgsToDoubleEnumerable(ignoreHiddenCells, true, arguments, context);
+ }
+
+ /// <summary>
+ /// Will return the arguments as an enumerable of objects.
+ /// </summary>
+ /// <param name="ignoreHiddenCells">If a cell is hidden and this value is true the value of that cell will be ignored</param>
+ /// <param name="arguments"></param>
+ /// <param name="context"></param>
+ /// <returns></returns>
+ protected virtual IEnumerable<object> ArgsToObjectEnumerable(
+ bool ignoreHiddenCells,
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ return _argumentCollectionUtil.ArgsToObjectEnumerable(ignoreHiddenCells, arguments, context);
+ }
+
+ /// <summary>
+ /// Use this method to create a result to return from Excel functions.
+ /// </summary>
+ /// <param name="result"></param>
+ /// <param name="dataType"></param>
+ /// <returns></returns>
+ protected CompileResult CreateResult(object result, DataType dataType) {
+ var validator = _compileResultValidators.GetValidator(dataType);
+ validator.Validate(result);
+ return new(result, dataType);
+ }
+
+ /// <summary>
+ /// Use this method to apply a function on a collection of arguments. The <paramref name="result"/>
+ /// should be modifyed in the supplied <paramref name="action"/> and will contain the result
+ /// after this operation has been performed.
+ /// </summary>
+ /// <param name="collection"></param>
+ /// <param name="result"></param>
+ /// <param name="action"></param>
+ /// <returns></returns>
+ protected virtual double CalculateCollection(
+ IEnumerable<FunctionArgument> collection,
+ double result,
+ Func<FunctionArgument, double, double> action) {
+ return _argumentCollectionUtil.CalculateCollection(collection, result, action);
+ }
+
+ /// <summary>
+ /// if the supplied <paramref name="arg">argument</paramref> contains an Excel error
+ /// an <see cref="ExcelErrorValueException"/> with that errorcode will be thrown
+ /// </summary>
+ /// <param name="arg"></param>
+ /// <exception cref="ExcelErrorValueException"></exception>
+ protected void CheckForAndHandleExcelError(FunctionArgument arg) {
+ if (arg.ValueIsExcelError) {
+ throw (new ExcelErrorValueException(arg.ValueAsExcelErrorValue));
+ }
+ }
+
+ /// <summary>
+ /// If the supplied <paramref name="cell"/> contains an Excel error
+ /// an <see cref="ExcelErrorValueException"/> with that errorcode will be thrown
+ /// </summary>
+ /// <param name="cell"></param>
+ protected void CheckForAndHandleExcelError(ExcelDataProvider.ICellInfo cell) {
+ if (cell.IsExcelError) {
+ throw (new ExcelErrorValueException(ExcelErrorValue.Parse(cell.Value.ToString())));
+ }
+ }
+
+ protected CompileResult GetResultByObject(object result) {
+ if (IsNumeric(result)) {
+ return CreateResult(result, DataType.Decimal);
+ }
+ if (result is string) {
+ return CreateResult(result, DataType.String);
+ }
+ if (ExcelErrorValue.Values.IsErrorValue(result)) {
+ return CreateResult(result, DataType.ExcelAddress);
+ }
+ if (result == null) {
+ return CompileResult.Empty;
+ }
+ return CreateResult(result, DataType.Enumerable);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/FunctionArgument.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/FunctionArgument.cs
new file mode 100644
index 0000000..3d93f48
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/FunctionArgument.cs
@@ -0,0 +1,69 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+public class FunctionArgument {
+ public FunctionArgument(object val) {
+ Value = val;
+ }
+
+ private ExcelCellState _excelCellState;
+
+ public void SetExcelStateFlag(ExcelCellState state) {
+ _excelCellState |= state;
+ }
+
+ public bool ExcelStateFlagIsSet(ExcelCellState state) {
+ return (_excelCellState & state) != 0;
+ }
+
+ public object Value { get; private set; }
+
+ public Type Type => Value?.GetType();
+
+ public bool IsExcelRange => Value != null && Value is ExcelDataProvider.IRangeInfo;
+
+ public bool ValueIsExcelError => ExcelErrorValue.Values.IsErrorValue(Value);
+
+ public ExcelErrorValue ValueAsExcelErrorValue => ExcelErrorValue.Parse(Value.ToString());
+
+ public ExcelDataProvider.IRangeInfo ValueAsRangeInfo => Value as ExcelDataProvider.IRangeInfo;
+
+ public object ValueFirst {
+ get {
+ if (Value is ExcelDataProvider.INameInfo info) {
+ Value = info.Value;
+ }
+ var v = Value as ExcelDataProvider.IRangeInfo;
+ if (v == null) {
+ return Value;
+ }
+ return v.GetValue(v.Address._fromRow, v.Address._fromCol);
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/FunctionNameProvider.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/FunctionNameProvider.cs
new file mode 100644
index 0000000..87ec87d
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/FunctionNameProvider.cs
@@ -0,0 +1,36 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class FunctionNameProvider : IFunctionNameProvider {
+ private FunctionNameProvider() {}
+
+ public static FunctionNameProvider Empty => new();
+
+ public virtual bool IsFunctionName(string name) {
+ return false;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/FunctionRepository.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/FunctionRepository.cs
new file mode 100644
index 0000000..5927624
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/FunctionRepository.cs
@@ -0,0 +1,120 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace AppsheetEpplus;
+
+// Used to report the names of Excel functions that are not supported by EPPlus
+public class FunctionException : SystemException {
+ // Summary:
+ // Initializes a new instance of the System.FunctionException class.
+ public FunctionException() {}
+
+ //
+ // Summary:
+ // Initializes a new instance of the System.FunctionException class with a specified
+ // error message.
+ //
+ // Parameters:
+ // message:
+ // The message that describes the error.
+ public FunctionException(string message)
+ : base(message) {}
+}
+
+/// <summary>
+/// This class provides methods for accessing/modifying VBA Functions.
+/// </summary>
+public class FunctionRepository : IFunctionNameProvider {
+ private readonly Dictionary<string, ExcelFunction> _functions = new(
+ StringComparer.InvariantCulture);
+
+ private FunctionRepository() {}
+
+ public static FunctionRepository Create() {
+ var repo = new FunctionRepository();
+ repo.LoadModule(new BuiltInFunctions());
+ return repo;
+ }
+
+ /// <summary>
+ /// Loads a module of <see cref="ExcelFunction"/>s to the function repository.
+ /// </summary>
+ /// <param name="module">A <see cref="IFunctionModule"/> that can be used for adding functions</param>
+ public virtual void LoadModule(IFunctionModule module) {
+ foreach (var key in module.Functions.Keys) {
+ var lowerKey = key.ToLower(CultureInfo.InvariantCulture);
+ _functions[lowerKey] = module.Functions[key];
+ }
+ }
+
+ public virtual ExcelFunction GetFunction(string name) {
+ if (!_functions.ContainsKey(name.ToLower(CultureInfo.InvariantCulture))) {
+ // Report that Excel function is not supported by EPPlus
+ throw new FunctionException(
+ string.Format("Excel function '{0}' is not supported in formulas.", name));
+ }
+ return _functions[name.ToLower(CultureInfo.InvariantCulture)];
+ }
+
+ /// <summary>
+ /// Removes all functions from the repository
+ /// </summary>
+ public virtual void Clear() {
+ _functions.Clear();
+ }
+
+ /// <summary>
+ /// Returns true if the the supplied <paramref name="name"/> exists in the repository.
+ /// </summary>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ public bool IsFunctionName(string name) {
+ return _functions.ContainsKey(name.ToLower(CultureInfo.InvariantCulture));
+ }
+
+ /// <summary>
+ /// Returns the names of all implemented functions.
+ /// </summary>
+ public IEnumerable<string> FunctionNames => _functions.Keys;
+
+ /// <summary>
+ /// Adds or replaces a function.
+ /// </summary>
+ /// <param name="functionName"> Case-insensitive name of the function that should be added or replaced.</param>
+ /// <param name="functionImpl">An implementation of an <see cref="ExcelFunction"/>.</param>
+ public void AddOrReplaceFunction(string functionName, ExcelFunction functionImpl) {
+ Require.That(functionName).Named("functionName").IsNotNullOrEmpty();
+ Require.That(functionImpl).Named("functionImpl").IsNotNull();
+ var fName = functionName.ToLower(CultureInfo.InvariantCulture);
+ if (_functions.ContainsKey(fName)) {
+ _functions.Remove(fName);
+ }
+ _functions[fName] = functionImpl;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/FunctionsModule.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/FunctionsModule.cs
new file mode 100644
index 0000000..6ea6d70
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/FunctionsModule.cs
@@ -0,0 +1,37 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Base class
+/// </summary>
+public abstract class FunctionsModule : IFunctionModule {
+ private readonly Dictionary<string, ExcelFunction> _functions = new();
+
+ public IDictionary<string, ExcelFunction> Functions => _functions;
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/HiddenValuesHandlingFunction.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/HiddenValuesHandlingFunction.cs
new file mode 100644
index 0000000..9941304
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/HiddenValuesHandlingFunction.cs
@@ -0,0 +1,70 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Base class for functions that needs to handle cells that is not visible.
+/// </summary>
+public abstract class HiddenValuesHandlingFunction : ExcelFunction {
+ /// <summary>
+ /// Set to true or false to indicate whether the function should ignore hidden values.
+ /// </summary>
+ public bool IgnoreHiddenValues { get; set; }
+
+ protected override IEnumerable<double> ArgsToDoubleEnumerable(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ return ArgsToDoubleEnumerable(arguments, context, true);
+ }
+
+ protected IEnumerable<double> ArgsToDoubleEnumerable(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context,
+ bool ignoreErrors) {
+ if (!arguments.Any()) {
+ return [];
+ }
+ if (IgnoreHiddenValues) {
+ var nonHidden = arguments.Where(x => !x.ExcelStateFlagIsSet(ExcelCellState.HiddenCell));
+ return base.ArgsToDoubleEnumerable(IgnoreHiddenValues, nonHidden, context);
+ }
+ return base.ArgsToDoubleEnumerable(IgnoreHiddenValues, ignoreErrors, arguments, context);
+ }
+
+ protected bool ShouldIgnore(ExcelDataProvider.ICellInfo c, ParsingContext context) {
+ return CellStateHelper.ShouldIgnore(IgnoreHiddenValues, c, context);
+ }
+
+ protected bool ShouldIgnore(FunctionArgument arg) {
+ if (IgnoreHiddenValues && arg.ExcelStateFlagIsSet(ExcelCellState.HiddenCell)) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/IFunctionModule.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/IFunctionModule.cs
new file mode 100644
index 0000000..025cbfd
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/IFunctionModule.cs
@@ -0,0 +1,32 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public interface IFunctionModule {
+ IDictionary<string, ExcelFunction> Functions { get; }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/IFunctionNameProvider.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/IFunctionNameProvider.cs
new file mode 100644
index 0000000..59d5871
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/IFunctionNameProvider.cs
@@ -0,0 +1,30 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public interface IFunctionNameProvider {
+ bool IsFunctionName(string name);
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/ErrorType.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/ErrorType.cs
new file mode 100644
index 0000000..f028b4e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/ErrorType.cs
@@ -0,0 +1,64 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-15
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class ErrorType : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var error = arguments.ElementAt(0);
+ var isErrorFunc = context.Configuration.FunctionRepository.GetFunction("iserror");
+ var isErrorResult = isErrorFunc.Execute(arguments, context);
+ if (!(bool)isErrorResult.Result) {
+ return CreateResult(ExcelErrorValue.Create(eErrorType.Na), DataType.ExcelError);
+ }
+ var errorType = error.ValueAsExcelErrorValue;
+ switch (errorType.Type) {
+ case eErrorType.Null:
+ return CreateResult(1, DataType.Integer);
+ case eErrorType.Div0:
+ return CreateResult(2, DataType.Integer);
+ case eErrorType.Value:
+ return CreateResult(3, DataType.Integer);
+ case eErrorType.Ref:
+ return CreateResult(4, DataType.Integer);
+ case eErrorType.Name:
+ return CreateResult(5, DataType.Integer);
+ case eErrorType.Num:
+ return CreateResult(6, DataType.Integer);
+ case eErrorType.Na:
+ return CreateResult(7, DataType.Integer);
+ // Bug G0004
+ case eErrorType.Error:
+ return CreateResult(8, DataType.Integer);
+ }
+ return CreateResult(ExcelErrorValue.Create(eErrorType.Na), DataType.ExcelError);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsBlank.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsBlank.cs
new file mode 100644
index 0000000..568d757
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsBlank.cs
@@ -0,0 +1,53 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class IsBlank : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ if (arguments == null || arguments.Count() == 0) {
+ return CreateResult(true, DataType.Boolean);
+ }
+ var result = true;
+ foreach (var arg in arguments) {
+ if (arg.Value is ExcelDataProvider.IRangeInfo info) {
+ if (info.GetValue(info.Address._fromRow, info.Address._fromCol) != null) {
+ result = false;
+ }
+ } else {
+ if (arg.Value != null && (arg.Value.ToString() != string.Empty)) {
+ result = false;
+ break;
+ }
+ }
+ }
+ return CreateResult(result, DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsErr.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsErr.cs
new file mode 100644
index 0000000..91346ca
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsErr.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class IsErr : ErrorHandlingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var isError = new IsError();
+ var result = isError.Execute(arguments, context);
+ if ((bool)result.Result) {
+ var arg = GetFirstValue(arguments);
+ if (arg is ExcelDataProvider.IRangeInfo info) {
+ var e = info.GetValue(info.Address._fromRow, info.Address._fromCol) as ExcelErrorValue;
+ if (e != null && e.Type == eErrorType.Na) {
+ return CreateResult(false, DataType.Boolean);
+ }
+ } else {
+ if (arg is ExcelErrorValue value && value.Type == eErrorType.Na) {
+ return CreateResult(false, DataType.Boolean);
+ }
+ }
+ }
+ return result;
+ }
+
+ public override CompileResult HandleError(string errorCode) {
+ return CreateResult(true, DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsError.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsError.cs
new file mode 100644
index 0000000..9147876
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsError.cs
@@ -0,0 +1,56 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class IsError : ErrorHandlingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ if (arguments == null || arguments.Count() == 0) {
+ return CreateResult(false, DataType.Boolean);
+ }
+ foreach (var argument in arguments) {
+ if (argument.Value is ExcelDataProvider.IRangeInfo info) {
+ if (ExcelErrorValue.Values.IsErrorValue(
+ info.GetValue(info.Address._fromRow, info.Address._fromCol))) {
+ return CreateResult(true, DataType.Boolean);
+ }
+ } else {
+ if (ExcelErrorValue.Values.IsErrorValue(argument.Value)) {
+ return CreateResult(true, DataType.Boolean);
+ }
+ }
+ }
+ return CreateResult(false, DataType.Boolean);
+ }
+
+ public override CompileResult HandleError(string errorCode) {
+ return CreateResult(true, DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsEven.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsEven.cs
new file mode 100644
index 0000000..9bed4f7
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsEven.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class IsEven : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg1 = GetFirstValue(arguments); //arguments.ElementAt(0);
+ if (!ConvertUtil.IsNumeric(arg1)) {
+ ThrowExcelErrorValueException(eErrorType.Value);
+ }
+ var number = (int)System.Math.Floor(ConvertUtil.GetValueDouble(arg1));
+ return CreateResult(number % 2 == 0, DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsLogical.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsLogical.cs
new file mode 100644
index 0000000..94f4628
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsLogical.cs
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class IsLogical : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
+ ValidateArguments(functionArguments, 1);
+ var v = GetFirstValue(arguments);
+ return CreateResult(v is bool, DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsNa.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsNa.cs
new file mode 100644
index 0000000..fecaabb
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsNa.cs
@@ -0,0 +1,46 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-15
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class IsNa : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ if (arguments == null || arguments.Count() == 0) {
+ return CreateResult(false, DataType.Boolean);
+ }
+
+ var v = GetFirstValue(arguments);
+
+ if (v is ExcelErrorValue value && value.Type == eErrorType.Na) {
+ return CreateResult(true, DataType.Boolean);
+ }
+ return CreateResult(false, DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsNonText.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsNonText.cs
new file mode 100644
index 0000000..ad7700d
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsNonText.cs
@@ -0,0 +1,42 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-15
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class IsNonText : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var firstArg = arguments.ElementAt(0);
+ if (firstArg.Value == null || firstArg.ValueIsExcelError) {
+ return CreateResult(false, DataType.Boolean);
+ }
+ return CreateResult(!(firstArg.Value is string), DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsNumber.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsNumber.cs
new file mode 100644
index 0000000..fd049cf
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsNumber.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class IsNumber : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = GetFirstValue(arguments);
+ return CreateResult(IsNumeric(arg), DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsOdd.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsOdd.cs
new file mode 100644
index 0000000..b69524e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsOdd.cs
@@ -0,0 +1,42 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-15
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class IsOdd : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg1 = GetFirstValue(arguments); //arguments.ElementAt(0);
+ if (!ConvertUtil.IsNumeric(arg1)) {
+ ThrowExcelErrorValueException(eErrorType.Value);
+ }
+ var number = (int)System.Math.Floor(ConvertUtil.GetValueDouble(arg1));
+ return CreateResult(number % 2 == 1, DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsText.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsText.cs
new file mode 100644
index 0000000..d4e4e31
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/IsText.cs
@@ -0,0 +1,41 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class IsText : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ if (arguments.Count() == 1 && arguments.ElementAt(0).Value != null) {
+ return CreateResult((GetFirstValue(arguments) is string), DataType.Boolean);
+ }
+ return CreateResult(false, DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/N.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/N.cs
new file mode 100644
index 0000000..1544445
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/N.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class N : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = GetFirstValue(arguments);
+
+ if (arg is bool b) {
+ var val = b ? 1d : 0d;
+ return CreateResult(val, DataType.Decimal);
+ }
+ if (IsNumeric(arg)) {
+ var val = ConvertUtil.GetValueDouble(arg);
+ return CreateResult(val, DataType.Decimal);
+ }
+ if (arg is string) {
+ return CreateResult(0d, DataType.Decimal);
+ }
+ if (arg is ExcelErrorValue) {
+ return CreateResult(arg, DataType.ExcelError);
+ }
+ throw new ExcelErrorValueException(eErrorType.Value);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/Na.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/Na.cs
new file mode 100644
index 0000000..6247dc4
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Information/Na.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Na : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ return CreateResult(ExcelErrorValue.Create(eErrorType.Na), DataType.ExcelError);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/IntArgumentParser.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/IntArgumentParser.cs
new file mode 100644
index 0000000..e5e8a99
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/IntArgumentParser.cs
@@ -0,0 +1,50 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class IntArgumentParser : ArgumentParser {
+ public override object Parse(object obj) {
+ Require.That(obj).Named("argument").IsNotNull();
+ if (obj is ExcelDataProvider.IRangeInfo info) {
+ var r = info.FirstOrDefault();
+ return r == null ? 0 : Convert.ToInt32(r.ValueDouble);
+ }
+ var objType = obj.GetType();
+ if (objType == typeof(int)) {
+ return (int)obj;
+ }
+ if (objType == typeof(double) || objType == typeof(decimal)) {
+ return Convert.ToInt32(obj);
+ }
+ if (!int.TryParse(obj.ToString(), out var result)) {
+ throw new ExcelErrorValueException(ExcelErrorValue.Create(eErrorType.Value));
+ }
+ return result;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/And.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/And.cs
new file mode 100644
index 0000000..311a2b3
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/And.cs
@@ -0,0 +1,43 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class And : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ for (var x = 0; x < arguments.Count(); x++) {
+ if (!ArgToBool(arguments, x)) {
+ return new(false, DataType.Boolean);
+ }
+ }
+ return new(true, DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/False.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/False.cs
new file mode 100644
index 0000000..89aa4e8
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/False.cs
@@ -0,0 +1,36 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class False : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ return CreateResult(false, DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/If.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/If.cs
new file mode 100644
index 0000000..31c0d50
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/If.cs
@@ -0,0 +1,42 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class If : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 3);
+ var condition = ArgToBool(arguments, 0);
+ var firstStatement = arguments.ElementAt(1).Value;
+ var secondStatement = arguments.ElementAt(2).Value;
+ var factory = new CompileResultFactory();
+ return condition ? factory.Create(firstStatement) : factory.Create(secondStatement);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/IfError.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/IfError.cs
new file mode 100644
index 0000000..e71272d
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/IfError.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class IfError : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var firstArg = arguments.First();
+ return GetResultByObject(firstArg.Value);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/IfNa.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/IfNa.cs
new file mode 100644
index 0000000..05cd85e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/IfNa.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class IfNa : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var firstArg = arguments.First();
+ return GetResultByObject(firstArg.Value);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/Not.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/Not.cs
new file mode 100644
index 0000000..eece7e4
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/Not.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Not : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var result = !ArgToBool(arguments, 0);
+ return new(result, DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/Or.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/Or.cs
new file mode 100644
index 0000000..44e2694
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/Or.cs
@@ -0,0 +1,43 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Or : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ for (var x = 0; x < arguments.Count(); x++) {
+ if (ArgToBool(arguments, x)) {
+ return new(true, DataType.Boolean);
+ }
+ }
+ return new(false, DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/True.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/True.cs
new file mode 100644
index 0000000..7888cfe
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Logical/True.cs
@@ -0,0 +1,36 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class True : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ return CreateResult(true, DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Abs.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Abs.cs
new file mode 100644
index 0000000..cc17860
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Abs.cs
@@ -0,0 +1,41 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Abs : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var val = ArgToDecimal(arguments, 0);
+ if (val < 0) {
+ val *= -1;
+ }
+ return CreateResult(val, DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Acos.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Acos.cs
new file mode 100644
index 0000000..2cf2499
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Acos.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-11
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Acos : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = ArgToDecimal(arguments, 0);
+ return CreateResult(MathHelper.Arccos(arg), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Acosh.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Acosh.cs
new file mode 100644
index 0000000..ee728e0
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Acosh.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-11
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Acosh : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = ArgToDecimal(arguments, 0);
+ return CreateResult(MathHelper.HArccos(arg), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Asin.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Asin.cs
new file mode 100644
index 0000000..25dcd74
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Asin.cs
@@ -0,0 +1,38 @@
+using System.Collections.Generic;
+
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-11
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class Asin : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = ArgToDecimal(arguments, 0);
+ return CreateResult(System.Math.Asin(arg), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Asinh.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Asinh.cs
new file mode 100644
index 0000000..685cb82
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Asinh.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-11
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Asinh : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = ArgToDecimal(arguments, 0);
+ return CreateResult(MathHelper.HArcsin(arg), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Atan.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Atan.cs
new file mode 100644
index 0000000..d7300fd
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Atan.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Atan : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = ArgToDecimal(arguments, 0);
+ return CreateResult(System.Math.Atan(arg), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Atan2.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Atan2.cs
new file mode 100644
index 0000000..a0ff906
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Atan2.cs
@@ -0,0 +1,40 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Atan2 : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var arg1 = ArgToDecimal(arguments, 0);
+ var arg2 = ArgToDecimal(arguments, 1);
+ // Had to switch order of the arguments to get the same result as in excel /MA
+ return CreateResult(System.Math.Atan2(arg2, arg1), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Atanh.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Atanh.cs
new file mode 100644
index 0000000..256125a
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Atanh.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-11
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Atanh : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = ArgToDecimal(arguments, 0);
+ return CreateResult(MathHelper.HArctan(arg), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Average.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Average.cs
new file mode 100644
index 0000000..9ec1ec3
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Average.cs
@@ -0,0 +1,95 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace AppsheetEpplus;
+
+public class Average : HiddenValuesHandlingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1, eErrorType.Div0);
+ double nValues = 0d,
+ result = 0d;
+ foreach (var arg in arguments) {
+ Calculate(arg, context, ref result, ref nValues);
+ }
+ return CreateResult(Divide(result, nValues), DataType.Decimal);
+ }
+
+ private void Calculate(
+ FunctionArgument arg,
+ ParsingContext context,
+ ref double retVal,
+ ref double nValues,
+ bool isInArray = false) {
+ if (ShouldIgnore(arg)) {
+ return;
+ }
+ if (arg.Value is IEnumerable<FunctionArgument> value) {
+ foreach (var item in value) {
+ Calculate(item, context, ref retVal, ref nValues, true);
+ }
+ } else if (arg.IsExcelRange) {
+ foreach (var c in arg.ValueAsRangeInfo) {
+ if (ShouldIgnore(c, context)) {
+ continue;
+ }
+ CheckForAndHandleExcelError(c);
+ if (!IsNumeric(c.Value)) {
+ continue;
+ }
+ nValues++;
+ retVal += c.ValueDouble;
+ }
+ } else {
+ var numericValue = GetNumericValue(arg.Value, isInArray);
+ if (numericValue.HasValue) {
+ nValues++;
+ retVal += numericValue.Value;
+ } else if ((arg.Value is string) && !ConvertUtil.IsNumericString(arg.Value)) {
+ if (!isInArray) {
+ ThrowExcelErrorValueException(eErrorType.Value);
+ }
+ }
+ }
+ CheckForAndHandleExcelError(arg);
+ }
+
+ private double? GetNumericValue(object obj, bool isInArray) {
+ if (IsNumeric(obj)) {
+ return ConvertUtil.GetValueDouble(obj);
+ }
+ if ((obj is bool) && !isInArray) {
+ return ConvertUtil.GetValueDouble(obj);
+ }
+ if (ConvertUtil.IsNumericString(obj)) {
+ return double.Parse(obj.ToString(), CultureInfo.InvariantCulture);
+ }
+ return default(double?);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/AverageA.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/AverageA.cs
new file mode 100644
index 0000000..567a8ef
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/AverageA.cs
@@ -0,0 +1,104 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2014-01-06
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace AppsheetEpplus;
+
+public class AverageA : HiddenValuesHandlingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1, eErrorType.Div0);
+ double nValues = 0d,
+ result = 0d;
+ foreach (var arg in arguments) {
+ Calculate(arg, context, ref result, ref nValues);
+ }
+ return CreateResult(Divide(result, nValues), DataType.Decimal);
+ }
+
+ private void Calculate(
+ FunctionArgument arg,
+ ParsingContext context,
+ ref double retVal,
+ ref double nValues,
+ bool isInArray = false) {
+ if (ShouldIgnore(arg)) {
+ return;
+ }
+ if (arg.Value is IEnumerable<FunctionArgument> value) {
+ foreach (var item in value) {
+ Calculate(item, context, ref retVal, ref nValues, true);
+ }
+ } else if (arg.IsExcelRange) {
+ foreach (var c in arg.ValueAsRangeInfo) {
+ if (ShouldIgnore(c, context)) {
+ continue;
+ }
+ CheckForAndHandleExcelError(c);
+ if (IsNumeric(c.Value)) {
+ nValues++;
+ retVal += c.ValueDouble;
+ } else if (c.Value is bool cValue) {
+ nValues++;
+ retVal += cValue ? 1 : 0;
+ } else if (c.Value is string) {
+ nValues++;
+ }
+ }
+ } else {
+ var numericValue = GetNumericValue(arg.Value, isInArray);
+ if (numericValue.HasValue) {
+ nValues++;
+ retVal += numericValue.Value;
+ } else if ((arg.Value is string) && !ConvertUtil.IsNumericString(arg.Value)) {
+ if (isInArray) {
+ nValues++;
+ } else {
+ ThrowExcelErrorValueException(eErrorType.Value);
+ }
+ }
+ }
+ CheckForAndHandleExcelError(arg);
+ }
+
+ private double? GetNumericValue(object obj, bool isInArray) {
+ if (IsNumeric(obj)) {
+ return ConvertUtil.GetValueDouble(obj);
+ }
+ if (obj is bool) {
+ if (isInArray) {
+ return default(double?);
+ }
+ return ConvertUtil.GetValueDouble(obj);
+ }
+ if (ConvertUtil.IsNumericString(obj)) {
+ return double.Parse(obj.ToString(), CultureInfo.InvariantCulture);
+ }
+ return default(double?);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/AverageIf.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/AverageIf.cs
new file mode 100644
index 0000000..92c698d
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/AverageIf.cs
@@ -0,0 +1,123 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class AverageIf : HiddenValuesHandlingFunction {
+ private readonly NumericExpressionEvaluator _numericExpressionEvaluator;
+ private readonly WildCardValueMatcher _wildCardValueMatcher;
+
+ public AverageIf()
+ : this(new(), new()) {}
+
+ public AverageIf(
+ NumericExpressionEvaluator evaluator,
+ WildCardValueMatcher wildCardValueMatcher) {
+ Require.That(evaluator).Named("evaluator").IsNotNull();
+ Require.That(evaluator).Named("wildCardValueMatcher").IsNotNull();
+ _numericExpressionEvaluator = evaluator;
+ _wildCardValueMatcher = wildCardValueMatcher;
+ }
+
+ private bool Evaluate(object obj, string expression) {
+ double? candidate = default(double?);
+ if (IsNumeric(obj)) {
+ candidate = ConvertUtil.GetValueDouble(obj);
+ }
+ if (candidate.HasValue) {
+ return _numericExpressionEvaluator.Evaluate(candidate.Value, expression);
+ }
+ if (obj == null) {
+ return false;
+ }
+ return _wildCardValueMatcher.IsMatch(expression, obj.ToString()) == 0;
+ }
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var firstArg = arguments.ElementAt(0);
+ var args = firstArg.Value as IEnumerable<FunctionArgument>;
+ if (args == null && firstArg.IsExcelRange) {
+ args = new List<FunctionArgument> { firstArg };
+ }
+ var criteria = arguments.ElementAt(1).Value;
+ ThrowExcelErrorValueExceptionIf(
+ () => criteria == null || criteria.ToString().Length > 255,
+ eErrorType.Value);
+ double retVal;
+ if (arguments.Count() > 2) {
+ var secondArg = arguments.ElementAt(2);
+ var lookupRange = secondArg.Value as IEnumerable<FunctionArgument>;
+ if (lookupRange == null && secondArg.IsExcelRange) {
+ lookupRange = new List<FunctionArgument> { secondArg };
+ }
+ retVal = CalculateWithLookupRange(args, criteria.ToString(), lookupRange, context);
+ } else {
+ retVal = CalculateSingleRange(args, criteria.ToString(), context);
+ }
+ return CreateResult(retVal, DataType.Decimal);
+ }
+
+ private double CalculateWithLookupRange(
+ IEnumerable<FunctionArgument> range,
+ string criteria,
+ IEnumerable<FunctionArgument> sumRange,
+ ParsingContext context) {
+ var retVal = 0d;
+ var nMatches = 0;
+ var flattenedRange = ArgsToObjectEnumerable(false, range, context);
+ var flattenedSumRange = ArgsToDoubleEnumerable(sumRange, context);
+ for (var x = 0; x < flattenedRange.Count(); x++) {
+ var candidate = flattenedSumRange.ElementAt(x);
+ if (Evaluate(flattenedRange.ElementAt(x), criteria)) {
+ nMatches++;
+ retVal += candidate;
+ }
+ }
+ return Divide(retVal, nMatches);
+ }
+
+ private double CalculateSingleRange(
+ IEnumerable<FunctionArgument> args,
+ string expression,
+ ParsingContext context) {
+ var retVal = 0d;
+ var nMatches = 0;
+ var flattendedRange = ArgsToDoubleEnumerable(args, context);
+ var candidates = flattendedRange as double[] ?? flattendedRange.ToArray();
+ foreach (var candidate in candidates) {
+ if (Evaluate(candidate, expression)) {
+ retVal += candidate;
+ nMatches++;
+ }
+ }
+ return Divide(retVal, nMatches);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/AverageIfs.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/AverageIfs.cs
new file mode 100644
index 0000000..af7e25f
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/AverageIfs.cs
@@ -0,0 +1,68 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-02-01
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class AverageIfs : MultipleRangeCriteriasFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
+ ValidateArguments(functionArguments, 3);
+ var sumRange = ArgsToDoubleEnumerable(
+ true,
+ new List<FunctionArgument> { functionArguments[0] },
+ context)
+ .ToList();
+ var argRanges = new List<ExcelDataProvider.IRangeInfo>();
+ var criterias = new List<object>();
+ for (var ix = 1; ix < 31; ix += 2) {
+ if (functionArguments.Length <= ix) {
+ break;
+ }
+ var rangeInfo = functionArguments[ix].ValueAsRangeInfo;
+ argRanges.Add(rangeInfo);
+ if (ix > 1) {
+ ThrowExcelErrorValueExceptionIf(
+ () => rangeInfo.GetNCells() != argRanges[0].GetNCells(),
+ eErrorType.Value);
+ }
+ criterias.Add(functionArguments[ix + 1].Value);
+ }
+ IEnumerable<int> matchIndexes = GetMatchIndexes(argRanges[0], criterias[0]);
+ var enumerable = matchIndexes as IList<int> ?? matchIndexes.ToList();
+ for (var ix = 1; ix < argRanges.Count && enumerable.Any(); ix++) {
+ var indexes = GetMatchIndexes(argRanges[ix], criterias[ix]);
+ matchIndexes = enumerable.Intersect(indexes);
+ }
+
+ var result = matchIndexes.Average(index => sumRange[index]);
+
+ return CreateResult(result, DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Ceiling.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Ceiling.cs
new file mode 100644
index 0000000..6a2e4b2
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Ceiling.cs
@@ -0,0 +1,59 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Ceiling : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var number = ArgToDecimal(arguments, 0);
+ var significance = ArgToDecimal(arguments, 1);
+ ValidateNumberAndSign(number, significance);
+ if (significance < 1 && significance > 0) {
+ var floor = System.Math.Floor(number);
+ var rest = number - floor;
+ var nSign = (int)(rest / significance) + 1;
+ return CreateResult(floor + (nSign * significance), DataType.Decimal);
+ }
+ if (significance == 1) {
+ return CreateResult(System.Math.Ceiling(number), DataType.Decimal);
+ }
+ var result = number - (number % significance) + significance;
+ return CreateResult(result, DataType.Decimal);
+ }
+
+ private void ValidateNumberAndSign(double number, double sign) {
+ if (number > 0d && sign < 0) {
+ var values = string.Format("num: {0}, sign: {1}", number, sign);
+ throw new InvalidOperationException(
+ "Ceiling cannot handle a negative significance when the number is positive" + values);
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Cos.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Cos.cs
new file mode 100644
index 0000000..d936044
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Cos.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Cos : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = ArgToDecimal(arguments, 0);
+ return CreateResult(System.Math.Cos(arg), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Cosh.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Cosh.cs
new file mode 100644
index 0000000..b4271fc
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Cosh.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Cosh : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = ArgToDecimal(arguments, 0);
+ return CreateResult(System.Math.Cosh(arg), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Count.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Count.cs
new file mode 100644
index 0000000..cf9d0ae
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Count.cs
@@ -0,0 +1,103 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Count : HiddenValuesHandlingFunction {
+ private enum ItemContext {
+ InRange,
+ InArray,
+ SingleArg,
+ }
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var nItems = 0d;
+ Calculate(arguments, ref nItems, context, ItemContext.SingleArg);
+ return CreateResult(nItems, DataType.Integer);
+ }
+
+ private void Calculate(
+ IEnumerable<FunctionArgument> items,
+ ref double nItems,
+ ParsingContext context,
+ ItemContext itemContext) {
+ foreach (var item in items) {
+ var cs = item.Value as ExcelDataProvider.IRangeInfo;
+ if (cs != null) {
+ foreach (var c in cs) {
+ _CheckForAndHandleExcelError(c, context);
+ if (ShouldIgnore(c, context) == false && ShouldCount(c.Value, ItemContext.InRange)) {
+ nItems++;
+ }
+ }
+ } else {
+ var value = item.Value as IEnumerable<FunctionArgument>;
+ if (value != null) {
+ Calculate(value, ref nItems, context, ItemContext.InArray);
+ } else {
+ _CheckForAndHandleExcelError(item, context);
+ if (ShouldIgnore(item) == false && ShouldCount(item.Value, itemContext)) {
+ nItems++;
+ }
+ }
+ }
+ }
+ }
+
+ private void _CheckForAndHandleExcelError(FunctionArgument arg, ParsingContext context) {
+ //if (context.Scopes.Current.IsSubtotal)
+ //{
+ // CheckForAndHandleExcelError(arg);
+ //}
+ }
+
+ private void _CheckForAndHandleExcelError(
+ ExcelDataProvider.ICellInfo cell,
+ ParsingContext context) {
+ //if (context.Scopes.Current.IsSubtotal)
+ //{
+ // CheckForAndHandleExcelError(cell);
+ //}
+ }
+
+ private bool ShouldCount(object value, ItemContext context) {
+ switch (context) {
+ case ItemContext.SingleArg:
+ return IsNumeric(value) || IsNumericString(value);
+ case ItemContext.InRange:
+ return IsNumeric(value);
+ case ItemContext.InArray:
+ return IsNumeric(value) || IsNumericString(value);
+ default:
+ throw new ArgumentException("Unknown ItemContext:" + context);
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/CountA.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/CountA.cs
new file mode 100644
index 0000000..3055aa0
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/CountA.cs
@@ -0,0 +1,84 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class CountA : HiddenValuesHandlingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var nItems = 0d;
+ Calculate(arguments, context, ref nItems);
+ return CreateResult(nItems, DataType.Integer);
+ }
+
+ private void Calculate(
+ IEnumerable<FunctionArgument> items,
+ ParsingContext context,
+ ref double nItems) {
+ foreach (var item in items) {
+ var cs = item.Value as ExcelDataProvider.IRangeInfo;
+ if (cs != null) {
+ foreach (var c in cs) {
+ _CheckForAndHandleExcelError(c, context);
+ if (!ShouldIgnore(c, context) && ShouldCount(c.Value)) {
+ nItems++;
+ }
+ }
+ } else if (item.Value is IEnumerable<FunctionArgument> value) {
+ Calculate(value, context, ref nItems);
+ } else {
+ _CheckForAndHandleExcelError(item, context);
+ if (!ShouldIgnore(item) && ShouldCount(item.Value)) {
+ nItems++;
+ }
+ }
+ }
+ }
+
+ private void _CheckForAndHandleExcelError(FunctionArgument arg, ParsingContext context) {
+ if (context.Scopes.Current.IsSubtotal) {
+ CheckForAndHandleExcelError(arg);
+ }
+ }
+
+ private void _CheckForAndHandleExcelError(
+ ExcelDataProvider.ICellInfo cell,
+ ParsingContext context) {
+ if (context.Scopes.Current.IsSubtotal) {
+ CheckForAndHandleExcelError(cell);
+ }
+ }
+
+ private bool ShouldCount(object value) {
+ if (value == null) {
+ return false;
+ }
+ return (!string.IsNullOrEmpty(value.ToString()));
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/CountBlank.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/CountBlank.cs
new file mode 100644
index 0000000..bb851bb
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/CountBlank.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class CountBlank : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = arguments.First();
+ if (!arg.IsExcelRange) {
+ throw new InvalidOperationException("CountBlank only support ranges as arguments");
+ }
+ var result = arg.ValueAsRangeInfo.GetNCells();
+ foreach (var cell in arg.ValueAsRangeInfo) {
+ if (cell.Value is not (null or string { Length: 0 })) {
+ result--;
+ }
+ }
+ return CreateResult(result, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/CountIf.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/CountIf.cs
new file mode 100644
index 0000000..f38c224
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/CountIf.cs
@@ -0,0 +1,61 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class CountIf : ExcelFunction {
+ private readonly NumericExpressionEvaluator _numericExpressionEvaluator;
+ private readonly WildCardValueMatcher _wildCardValueMatcher;
+
+ public CountIf()
+ : this(new(), new()) {}
+
+ public CountIf(NumericExpressionEvaluator evaluator, WildCardValueMatcher wildCardValueMatcher) {
+ Require.That(evaluator).Named("evaluator").IsNotNull();
+ Require.That(wildCardValueMatcher).Named("wildCardValueMatcher").IsNotNull();
+ _numericExpressionEvaluator = evaluator;
+ _wildCardValueMatcher = wildCardValueMatcher;
+ }
+
+ private bool Evaluate(object obj, string expression) {
+ double? candidate = default(double?);
+ if (IsNumeric(obj)) {
+ candidate = ConvertUtil.GetValueDouble(obj);
+ }
+ if (candidate.HasValue) {
+ return _numericExpressionEvaluator.Evaluate(candidate.Value, expression);
+ }
+ if (obj == null) {
+ return false;
+ }
+ return _wildCardValueMatcher.IsMatch(expression, obj.ToString()) == 0;
+ }
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
+ ValidateArguments(functionArguments, 2);
+ var range = functionArguments.ElementAt(0);
+ var criteria = ArgToString(functionArguments, 1);
+ double result = 0d;
+ if (range.IsExcelRange) {
+ foreach (var cell in range.ValueAsRangeInfo) {
+ if (Evaluate(cell.Value, criteria)) {
+ result++;
+ }
+ }
+ } else if (range.Value is IEnumerable<FunctionArgument> value) {
+ foreach (var arg in value) {
+ if (Evaluate(arg.Value, criteria)) {
+ result++;
+ }
+ }
+ } else {
+ if (Evaluate(range.Value, criteria)) {
+ result++;
+ }
+ }
+ return CreateResult(result, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/CountIfs.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/CountIfs.cs
new file mode 100644
index 0000000..9159e24
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/CountIfs.cs
@@ -0,0 +1,61 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-11
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class CountIfs : MultipleRangeCriteriasFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
+ ValidateArguments(functionArguments, 2);
+ var argRanges = new List<ExcelDataProvider.IRangeInfo>();
+ var criterias = new List<object>();
+ for (var ix = 0; ix < 30; ix += 2) {
+ if (functionArguments.Length <= ix) {
+ break;
+ }
+ var rangeInfo = functionArguments[ix].ValueAsRangeInfo;
+ argRanges.Add(rangeInfo);
+ if (ix > 0) {
+ ThrowExcelErrorValueExceptionIf(
+ () => rangeInfo.GetNCells() != argRanges[0].GetNCells(),
+ eErrorType.Value);
+ }
+ criterias.Add(functionArguments[ix + 1].Value);
+ }
+ IEnumerable<int> matchIndexes = GetMatchIndexes(argRanges[0], criterias[0]);
+ var enumerable = matchIndexes as IList<int> ?? matchIndexes.ToList();
+ for (var ix = 1; ix < argRanges.Count && enumerable.Any(); ix++) {
+ var indexes = GetMatchIndexes(argRanges[ix], criterias[ix]);
+ matchIndexes = enumerable.Intersect(indexes);
+ }
+
+ return CreateResult((double)matchIndexes.Count(), DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Degrees.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Degrees.cs
new file mode 100644
index 0000000..e06ea6a
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Degrees.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Degrees : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var angle = ArgToDecimal(arguments, 0);
+ var result = (angle * 180) / System.Math.PI;
+ return CreateResult(result, DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Exp.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Exp.cs
new file mode 100644
index 0000000..b76f489
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Exp.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Exp : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var number = ArgToDecimal(arguments, 0);
+ return CreateResult(System.Math.Exp(number), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Fact.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Fact.cs
new file mode 100644
index 0000000..53372f0
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Fact.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Fact : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var number = ArgToDecimal(arguments, 0);
+ ThrowExcelErrorValueExceptionIf(() => number < 0, eErrorType.Na);
+ var result = 1d;
+ for (var x = 1; x < number; x++) {
+ result *= x;
+ }
+ return CreateResult(result, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Floor.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Floor.cs
new file mode 100644
index 0000000..ff3bca7
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Floor.cs
@@ -0,0 +1,64 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Floor : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var number = ArgToDecimal(arguments, 0);
+ var significance = ArgToDecimal(arguments, 1);
+ ValidateNumberAndSign(number, significance);
+ if (significance < 1 && significance > 0) {
+ var floor = System.Math.Floor(number);
+ var rest = number - floor;
+ var nSign = (int)(rest / significance);
+ return CreateResult(floor + (nSign * significance), DataType.Decimal);
+ }
+ if (significance == 1) {
+ return CreateResult(System.Math.Floor(number), DataType.Decimal);
+ }
+ double result;
+ if (number > 1) {
+ result = number - (number % significance) + significance;
+ } else {
+ result = number - (number % significance);
+ }
+ return CreateResult(result, DataType.Decimal);
+ }
+
+ private void ValidateNumberAndSign(double number, double sign) {
+ if (number > 0d && sign < 0) {
+ var values = string.Format("num: {0}, sign: {1}", number, sign);
+ throw new InvalidOperationException(
+ "Floor cannot handle a negative significance when the number is positive" + values);
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Large.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Large.cs
new file mode 100644
index 0000000..dd5786b
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Large.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Large : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var args = arguments.ElementAt(0);
+ var index = ArgToInt(arguments, 1) - 1;
+ var values = ArgsToDoubleEnumerable(new List<FunctionArgument> { args }, context);
+ ThrowExcelErrorValueExceptionIf(() => index < 0 || index >= values.Count(), eErrorType.Num);
+ var result = values.OrderByDescending(x => x).ElementAt(index);
+ return CreateResult(result, DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Ln.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Ln.cs
new file mode 100644
index 0000000..f0705a0
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Ln.cs
@@ -0,0 +1,13 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Ln : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = ArgToDecimal(arguments, 0);
+ return CreateResult(System.Math.Log(arg, System.Math.E), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Log.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Log.cs
new file mode 100644
index 0000000..203d773
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Log.cs
@@ -0,0 +1,43 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Log : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var number = ArgToDecimal(arguments, 0);
+ if (arguments.Count() == 1) {
+ return CreateResult(System.Math.Log(number, 10d), DataType.Decimal);
+ }
+ var newBase = ArgToDecimal(arguments, 1);
+ return CreateResult(System.Math.Log(number, newBase), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Log10.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Log10.cs
new file mode 100644
index 0000000..0333f09
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Log10.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Log10 : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var number = ArgToDecimal(arguments, 0);
+ return CreateResult(System.Math.Log10(number), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/MathHelper.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/MathHelper.cs
new file mode 100644
index 0000000..2d6f69f
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/MathHelper.cs
@@ -0,0 +1,138 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-11
+ *******************************************************************************/
+
+using MathObj = System.Math;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Thanks to the guys in this thread: http://stackoverflow.com/questions/2840798/c-sharp-math-class-question
+/// </summary>
+public static class MathHelper {
+ // Secant
+ public static double Sec(double x) {
+ return 1 / MathObj.Cos(x);
+ }
+
+ // Cosecant
+ public static double Cosec(double x) {
+ return 1 / MathObj.Sin(x);
+ }
+
+ // Cotangent
+ public static double Cotan(double x) {
+ return 1 / MathObj.Tan(x);
+ }
+
+ // Inverse Sine
+ public static double Arcsin(double x) {
+ return MathObj.Atan(x / MathObj.Sqrt(-x * x + 1));
+ }
+
+ // Inverse Cosine
+ public static double Arccos(double x) {
+ return MathObj.Atan(-x / MathObj.Sqrt(-x * x + 1)) + 2 * MathObj.Atan(1);
+ }
+
+ // Inverse Secant
+ public static double Arcsec(double x) {
+ return 2 * MathObj.Atan(1) - MathObj.Atan(MathObj.Sign(x) / MathObj.Sqrt(x * x - 1));
+ }
+
+ // Inverse Cosecant
+ public static double Arccosec(double x) {
+ return MathObj.Atan(MathObj.Sign(x) / MathObj.Sqrt(x * x - 1));
+ }
+
+ // Inverse Cotangent
+ public static double Arccotan(double x) {
+ return 2 * MathObj.Atan(1) - MathObj.Atan(x);
+ }
+
+ // Hyperbolic Sine
+ public static double HSin(double x) {
+ return (MathObj.Exp(x) - MathObj.Exp(-x)) / 2;
+ }
+
+ // Hyperbolic Cosine
+ public static double HCos(double x) {
+ return (MathObj.Exp(x) + MathObj.Exp(-x)) / 2;
+ }
+
+ // Hyperbolic Tangent
+ public static double HTan(double x) {
+ return (MathObj.Exp(x) - MathObj.Exp(-x)) / (MathObj.Exp(x) + MathObj.Exp(-x));
+ }
+
+ // Hyperbolic Secant
+ public static double HSec(double x) {
+ return 2 / (MathObj.Exp(x) + MathObj.Exp(-x));
+ }
+
+ // Hyperbolic Cosecant
+ public static double HCosec(double x) {
+ return 2 / (MathObj.Exp(x) - MathObj.Exp(-x));
+ }
+
+ // Hyperbolic Cotangent
+ public static double HCotan(double x) {
+ return (MathObj.Exp(x) + MathObj.Exp(-x)) / (MathObj.Exp(x) - MathObj.Exp(-x));
+ }
+
+ // Inverse Hyperbolic Sine
+ public static double HArcsin(double x) {
+ return MathObj.Log(x + MathObj.Sqrt(x * x + 1));
+ }
+
+ // Inverse Hyperbolic Cosine
+ public static double HArccos(double x) {
+ return MathObj.Log(x + MathObj.Sqrt(x * x - 1));
+ }
+
+ // Inverse Hyperbolic Tangent
+ public static double HArctan(double x) {
+ return MathObj.Log((1 + x) / (1 - x)) / 2;
+ }
+
+ // Inverse Hyperbolic Secant
+ public static double HArcsec(double x) {
+ return MathObj.Log((MathObj.Sqrt(-x * x + 1) + 1) / x);
+ }
+
+ // Inverse Hyperbolic Cosecant
+ public static double HArccosec(double x) {
+ return MathObj.Log((MathObj.Sign(x) * MathObj.Sqrt(x * x + 1) + 1) / x);
+ }
+
+ // Inverse Hyperbolic Cotangent
+ public static double HArccotan(double x) {
+ return MathObj.Log((x + 1) / (x - 1)) / 2;
+ }
+
+ // Logarithm to base N
+ public static double LogN(double x, double n) {
+ return MathObj.Log(x) / MathObj.Log(n);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Max.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Max.cs
new file mode 100644
index 0000000..cf490ac
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Max.cs
@@ -0,0 +1,39 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Max : HiddenValuesHandlingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var values = ArgsToDoubleEnumerable(IgnoreHiddenValues, false, arguments, context);
+ return CreateResult(values.Max(), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Maxa.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Maxa.cs
new file mode 100644
index 0000000..a65e13a
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Maxa.cs
@@ -0,0 +1,49 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Maxa : ExcelFunction {
+ private readonly DoubleEnumerableArgConverter _argConverter;
+
+ public Maxa()
+ : this(new()) {}
+
+ public Maxa(DoubleEnumerableArgConverter argConverter) {
+ Require.That(argConverter).Named("argConverter").IsNotNull();
+ _argConverter = argConverter;
+ }
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var values = _argConverter.ConvertArgsIncludingOtherTypes(arguments);
+ return CreateResult(values.Max(), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Median.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Median.cs
new file mode 100644
index 0000000..dc39636
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Median.cs
@@ -0,0 +1,49 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-10
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Median : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var nums = ArgsToDoubleEnumerable(arguments, context);
+ var arr = nums.ToArray();
+ Array.Sort(arr);
+ ThrowExcelErrorValueExceptionIf(() => arr.Length == 0, eErrorType.Num);
+ double result;
+ if (arr.Length % 2 == 1) {
+ result = arr[arr.Length / 2];
+ } else {
+ var startIndex = arr.Length / 2 - 1;
+ result = (arr[startIndex] + arr[startIndex + 1]) / 2d;
+ }
+ return CreateResult(result, DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Min.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Min.cs
new file mode 100644
index 0000000..850ceeb
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Min.cs
@@ -0,0 +1,39 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Min : HiddenValuesHandlingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var values = ArgsToDoubleEnumerable(IgnoreHiddenValues, false, arguments, context);
+ return CreateResult(values.Min(), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Mina.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Mina.cs
new file mode 100644
index 0000000..3321d65
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Mina.cs
@@ -0,0 +1,49 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Mina : ExcelFunction {
+ private readonly DoubleEnumerableArgConverter _argConverter;
+
+ public Mina()
+ : this(new()) {}
+
+ public Mina(DoubleEnumerableArgConverter argConverter) {
+ Require.That(argConverter).Named("argConverter").IsNotNull();
+ _argConverter = argConverter;
+ }
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var values = _argConverter.ConvertArgsIncludingOtherTypes(arguments);
+ return CreateResult(values.Min(), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Mod.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Mod.cs
new file mode 100644
index 0000000..ff0c907
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Mod.cs
@@ -0,0 +1,39 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Mod : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var n1 = ArgToDecimal(arguments, 0);
+ var n2 = ArgToDecimal(arguments, 1);
+ return new(n1 % n2, DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/MultipleRangeCriteriasFunction.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/MultipleRangeCriteriasFunction.cs
new file mode 100644
index 0000000..dead9a8
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/MultipleRangeCriteriasFunction.cs
@@ -0,0 +1,74 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-15
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public abstract class MultipleRangeCriteriasFunction : ExcelFunction {
+ private readonly NumericExpressionEvaluator _numericExpressionEvaluator;
+ private readonly WildCardValueMatcher _wildCardValueMatcher;
+
+ protected MultipleRangeCriteriasFunction()
+ : this(new(), new()) {}
+
+ protected MultipleRangeCriteriasFunction(
+ NumericExpressionEvaluator evaluator,
+ WildCardValueMatcher wildCardValueMatcher) {
+ Require.That(evaluator).Named("evaluator").IsNotNull();
+ Require.That(wildCardValueMatcher).Named("wildCardValueMatcher").IsNotNull();
+ _numericExpressionEvaluator = evaluator;
+ _wildCardValueMatcher = wildCardValueMatcher;
+ }
+
+ protected bool Evaluate(object obj, object expression) {
+ double? candidate = default(double?);
+ if (IsNumeric(obj)) {
+ candidate = ConvertUtil.GetValueDouble(obj);
+ }
+ if (candidate.HasValue && expression is string) {
+ return _numericExpressionEvaluator.Evaluate(candidate.Value, expression.ToString());
+ }
+ if (obj == null) {
+ return false;
+ }
+ return _wildCardValueMatcher.IsMatch(expression, obj.ToString()) == 0;
+ }
+
+ protected List<int> GetMatchIndexes(ExcelDataProvider.IRangeInfo rangeInfo, object searched) {
+ var result = new List<int>();
+ var internalIndex = 0;
+ for (var row = rangeInfo.Address._fromRow; row <= rangeInfo.Address._toRow; row++) {
+ for (var col = rangeInfo.Address._fromCol; col <= rangeInfo.Address._toCol; col++) {
+ var candidate = rangeInfo.GetValue(row, col);
+ if (Evaluate(candidate, searched)) {
+ result.Add(internalIndex);
+ }
+ internalIndex++;
+ }
+ }
+ return result;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Pi.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Pi.cs
new file mode 100644
index 0000000..476824e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Pi.cs
@@ -0,0 +1,37 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Pi : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var result = System.Math.Round(System.Math.PI, 14);
+ return CreateResult(result, DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Power.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Power.cs
new file mode 100644
index 0000000..78b8887
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Power.cs
@@ -0,0 +1,40 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Power : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var number = ArgToDecimal(arguments, 0);
+ var power = ArgToDecimal(arguments, 1);
+ var result = System.Math.Pow(number, power);
+ return CreateResult(result, DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Product.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Product.cs
new file mode 100644
index 0000000..64e1821
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Product.cs
@@ -0,0 +1,88 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Product : HiddenValuesHandlingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var result = 0d;
+ var index = 0;
+ while (AreEqual(result, 0d) && index < arguments.Count()) {
+ result = CalculateFirstItem(arguments, index++, context);
+ }
+ result = CalculateCollection(
+ arguments.Skip(index),
+ result,
+ (arg, current) => {
+ if (ShouldIgnore(arg)) {
+ return current;
+ }
+ if (arg.ValueIsExcelError) {
+ ThrowExcelErrorValueException(arg.ValueAsExcelErrorValue.Type);
+ }
+ if (arg.IsExcelRange) {
+ foreach (var cell in arg.ValueAsRangeInfo) {
+ if (ShouldIgnore(cell, context)) {
+ return current;
+ }
+ current *= cell.ValueDouble;
+ }
+ return current;
+ }
+ var obj = arg.Value;
+ if (obj != null && IsNumeric(obj)) {
+ var val = Convert.ToDouble(obj);
+ current *= val;
+ }
+ return current;
+ });
+ return CreateResult(result, DataType.Decimal);
+ }
+
+ private double CalculateFirstItem(
+ IEnumerable<FunctionArgument> arguments,
+ int index,
+ ParsingContext context) {
+ var element = arguments.ElementAt(index);
+ var argList = new List<FunctionArgument> { element };
+ var valueList = ArgsToDoubleEnumerable(false, false, argList, context);
+ var result = 0d;
+ foreach (var value in valueList) {
+ if (result == 0d && value > 0d) {
+ result = value;
+ } else {
+ result *= value;
+ }
+ }
+ return result;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Quotient.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Quotient.cs
new file mode 100644
index 0000000..052856f
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Quotient.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Quotient : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var num = ArgToDecimal(arguments, 0);
+ var denom = ArgToDecimal(arguments, 1);
+ ThrowExcelErrorValueExceptionIf(() => (int)denom == 0, eErrorType.Div0);
+ var result = (int)(num / denom);
+ return CreateResult(result, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Rand.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Rand.cs
new file mode 100644
index 0000000..2687e7c
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Rand.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Rand : ExcelFunction {
+ private static int Seed { get; set; }
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ Seed = Seed > 50 ? 0 : Seed + 5;
+ var val = new Random(System.DateTime.Now.Millisecond + Seed).NextDouble();
+ return CreateResult(val, DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/RandBetween.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/RandBetween.cs
new file mode 100644
index 0000000..8821710
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/RandBetween.cs
@@ -0,0 +1,52 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class RandBetween : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var low = ArgToDecimal(arguments, 0);
+ var high = ArgToDecimal(arguments, 1);
+ var rand = new Rand().Execute(new FunctionArgument[0], context).Result;
+ var randPart = (CalulateDiff(high, low) * (double)rand) + 1;
+ randPart = System.Math.Floor(randPart);
+ return CreateResult(low + randPart, DataType.Integer);
+ }
+
+ private double CalulateDiff(double high, double low) {
+ if (high > 0 && low < 0) {
+ return high + low * -1;
+ }
+ if (high < 0 && low < 0) {
+ return high * -1 - low * -1;
+ }
+ return high - low;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Round.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Round.cs
new file mode 100644
index 0000000..0a95cc7
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Round.cs
@@ -0,0 +1,43 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Round : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var number = ArgToDecimal(arguments, 0);
+ var nDigits = ArgToInt(arguments, 1);
+ if (nDigits < 0) {
+ nDigits *= -1;
+ return CreateResult(number - (number % (System.Math.Pow(10, nDigits))), DataType.Integer);
+ }
+ return CreateResult(System.Math.Round(number, nDigits), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Rounddown.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Rounddown.cs
new file mode 100644
index 0000000..6d1c3ab
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Rounddown.cs
@@ -0,0 +1,59 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2014-01-06
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Rounddown : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var number = ArgToDecimal(arguments, 0);
+ var nDecimals = ArgToInt(arguments, 1);
+
+ var nFactor = number < 0 ? -1 : 1;
+ number *= nFactor;
+
+ double result;
+ if (nDecimals > 0) {
+ result = RoundDownDecimalNumber(number, nDecimals);
+ } else {
+ result = (int)System.Math.Floor(number);
+ result = result - (result % System.Math.Pow(10, (nDecimals * -1)));
+ }
+ return CreateResult(result * nFactor, DataType.Decimal);
+ }
+
+ private static double RoundDownDecimalNumber(double number, int nDecimals) {
+ var integerPart = System.Math.Floor(number);
+ var decimalPart = number - integerPart;
+ decimalPart = System.Math.Pow(10d, nDecimals) * decimalPart;
+ decimalPart = System.Math.Truncate(decimalPart) / System.Math.Pow(10d, nDecimals);
+ var result = integerPart + decimalPart;
+ return result;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Roundup.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Roundup.cs
new file mode 100644
index 0000000..c98d577
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Roundup.cs
@@ -0,0 +1,45 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2014-01-06
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Roundup : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var number = ArgToDecimal(arguments, 0);
+ var nDigits = ArgToInt(arguments, 1);
+ double result =
+ (number >= 0)
+ ? System.Math.Ceiling(number * System.Math.Pow(10, nDigits))
+ / System.Math.Pow(10, nDigits)
+ : System.Math.Floor(number * System.Math.Pow(10, nDigits))
+ / System.Math.Pow(10, nDigits);
+ return CreateResult(result, DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sign.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sign.cs
new file mode 100644
index 0000000..2f40664
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sign.cs
@@ -0,0 +1,44 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Sign : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var result = 0d;
+ var val = ArgToDecimal(arguments, 0);
+ if (val < 0) {
+ result = -1;
+ } else if (val > 0) {
+ result = 1;
+ }
+ return CreateResult(result, DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sin.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sin.cs
new file mode 100644
index 0000000..292bdc1
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sin.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Sin : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = ArgToDecimal(arguments, 0);
+ return CreateResult(System.Math.Sin(arg), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sinh.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sinh.cs
new file mode 100644
index 0000000..5b4bece
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sinh.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Sinh : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = ArgToDecimal(arguments, 0);
+ return CreateResult(System.Math.Sinh(arg), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Small.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Small.cs
new file mode 100644
index 0000000..f39ceb4
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Small.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Small : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var args = arguments.ElementAt(0);
+ var index = ArgToInt(arguments, 1) - 1;
+ var values = ArgsToDoubleEnumerable(new List<FunctionArgument> { args }, context);
+ ThrowExcelErrorValueExceptionIf(() => index < 0 || index >= values.Count(), eErrorType.Num);
+ var result = values.OrderBy(x => x).ElementAt(index);
+ return CreateResult(result, DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sqrt.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sqrt.cs
new file mode 100644
index 0000000..636a12e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sqrt.cs
@@ -0,0 +1,39 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Sqrt : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = ArgToDecimal(arguments, 0);
+ var result = System.Math.Sqrt(arg);
+ return CreateResult(result, DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/SqrtPi.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/SqrtPi.cs
new file mode 100644
index 0000000..bca7531
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/SqrtPi.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class SqrtPi : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var number = ArgToDecimal(arguments, 0);
+ return CreateResult(System.Math.Sqrt(number * System.Math.PI), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Stdev.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Stdev.cs
new file mode 100644
index 0000000..96165c2
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Stdev.cs
@@ -0,0 +1,57 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+using MathObj = System.Math;
+
+namespace AppsheetEpplus;
+
+public class Stdev : HiddenValuesHandlingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var values = ArgsToDoubleEnumerable(arguments, context, false);
+ return CreateResult(StandardDeviation(values), DataType.Decimal);
+ }
+
+ private double StandardDeviation(IEnumerable<double> values) {
+ double ret = 0;
+ if (values.Any()) {
+ var nValues = values.Count();
+ if (nValues == 1) {
+ throw new ExcelErrorValueException(eErrorType.Div0);
+ }
+ //Compute the Average
+ double avg = values.Average();
+ //Perform the Sum of (value-avg)_2_2
+ double sum = values.Sum(d => MathObj.Pow(d - avg, 2));
+ //Put it all together
+ ret = MathObj.Sqrt(Divide(sum, (values.Count() - 1)));
+ }
+ return ret;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/StdevP.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/StdevP.cs
new file mode 100644
index 0000000..92ec913
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/StdevP.cs
@@ -0,0 +1,44 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+using MathObj = System.Math;
+
+namespace AppsheetEpplus;
+
+public class StdevP : HiddenValuesHandlingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var args = ArgsToDoubleEnumerable(IgnoreHiddenValues, false, arguments, context);
+ return CreateResult(StandardDeviation(args), DataType.Decimal);
+ }
+
+ private static double StandardDeviation(IEnumerable<double> values) {
+ double avg = values.Average();
+ return MathObj.Sqrt(values.Average(v => MathObj.Pow(v - avg, 2)));
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Subtotal.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Subtotal.cs
new file mode 100644
index 0000000..eedd06a
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Subtotal.cs
@@ -0,0 +1,96 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Subtotal : ExcelFunction {
+ private readonly Dictionary<int, HiddenValuesHandlingFunction> _functions = new();
+
+ public Subtotal() {
+ Initialize();
+ }
+
+ private void Initialize() {
+ _functions[1] = new Average();
+ _functions[2] = new Count();
+ _functions[3] = new CountA();
+ _functions[4] = new Max();
+ _functions[5] = new Min();
+ _functions[6] = new Product();
+ _functions[7] = new Stdev();
+ _functions[8] = new StdevP();
+ _functions[9] = new Sum();
+ _functions[10] = new Var();
+ _functions[11] = new VarP();
+
+ AddHiddenValueHandlingFunction(new Average(), 101);
+ AddHiddenValueHandlingFunction(new Count(), 102);
+ AddHiddenValueHandlingFunction(new CountA(), 103);
+ AddHiddenValueHandlingFunction(new Max(), 104);
+ AddHiddenValueHandlingFunction(new Min(), 105);
+ AddHiddenValueHandlingFunction(new Product(), 106);
+ AddHiddenValueHandlingFunction(new Stdev(), 107);
+ AddHiddenValueHandlingFunction(new StdevP(), 108);
+ AddHiddenValueHandlingFunction(new Sum(), 109);
+ AddHiddenValueHandlingFunction(new Var(), 110);
+ AddHiddenValueHandlingFunction(new VarP(), 111);
+ }
+
+ private void AddHiddenValueHandlingFunction(HiddenValuesHandlingFunction func, int funcNum) {
+ func.IgnoreHiddenValues = true;
+ _functions[funcNum] = func;
+ }
+
+ public override void BeforeInvoke(ParsingContext context) {
+ base.BeforeInvoke(context);
+ context.Scopes.Current.IsSubtotal = true;
+ }
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var funcNum = ArgToInt(arguments, 0);
+ if (context.Scopes.Current.Parent != null && context.Scopes.Current.Parent.IsSubtotal) {
+ return CreateResult(0d, DataType.Decimal);
+ }
+ var actualArgs = arguments.Skip(1);
+ var function = GetFunctionByCalcType(funcNum);
+ var compileResult = function.Execute(actualArgs, context);
+ compileResult.IsResultOfSubtotal = true;
+ return compileResult;
+ }
+
+ private ExcelFunction GetFunctionByCalcType(int funcNum) {
+ if (!_functions.ContainsKey(funcNum)) {
+ ThrowExcelErrorValueException(eErrorType.Value);
+ //throw new ArgumentException("Invalid funcNum " + funcNum + ", valid ranges are 1-11 and 101-111");
+ }
+ return _functions[funcNum];
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sum.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sum.cs
new file mode 100644
index 0000000..5f15170
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sum.cs
@@ -0,0 +1,65 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Sum : HiddenValuesHandlingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var retVal = 0d;
+ if (arguments != null) {
+ foreach (var arg in arguments) {
+ retVal += Calculate(arg, context);
+ }
+ }
+ return CreateResult(retVal, DataType.Decimal);
+ }
+
+ private double Calculate(FunctionArgument arg, ParsingContext context) {
+ var retVal = 0d;
+ if (ShouldIgnore(arg)) {
+ return retVal;
+ }
+ if (arg.Value is IEnumerable<FunctionArgument> value) {
+ foreach (var item in value) {
+ retVal += Calculate(item, context);
+ }
+ } else if (arg.Value is ExcelDataProvider.IRangeInfo info) {
+ foreach (var c in info) {
+ if (ShouldIgnore(c, context) == false) {
+ CheckForAndHandleExcelError(c);
+ retVal += c.ValueDouble;
+ }
+ }
+ } else {
+ CheckForAndHandleExcelError(arg);
+ retVal += ConvertUtil.GetValueDouble(arg.Value, true);
+ }
+ return retVal;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/SumIf.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/SumIf.cs
new file mode 100644
index 0000000..fc930b3
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/SumIf.cs
@@ -0,0 +1,145 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class SumIf : HiddenValuesHandlingFunction {
+ private readonly NumericExpressionEvaluator _evaluator;
+
+ public SumIf()
+ : this(new()) {}
+
+ public SumIf(NumericExpressionEvaluator evaluator) {
+ Require.That(evaluator).Named("evaluator").IsNotNull();
+ _evaluator = evaluator;
+ }
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var args = arguments.ElementAt(0).Value as ExcelDataProvider.IRangeInfo; //IEnumerable<FunctionArgument>;
+ var criteria = arguments.ElementAt(1).Value;
+ ThrowExcelErrorValueExceptionIf(
+ () => criteria == null || criteria.ToString().Length > 255,
+ eErrorType.Value);
+ double retVal;
+ if (arguments.Count() > 2) {
+ var sumRange = arguments.ElementAt(2).Value as ExcelDataProvider.IRangeInfo; //IEnumerable<FunctionArgument>;
+ retVal = CalculateWithSumRange(args, criteria.ToString(), sumRange, context);
+ } else {
+ if (args != null) {
+ retVal = CalculateSingleRange(args, criteria.ToString(), context);
+ } else {
+ retVal = CalculateSingleRange(
+ (arguments.ElementAt(0).Value as IEnumerable<FunctionArgument>),
+ criteria.ToString(),
+ context);
+ }
+ }
+ return CreateResult(retVal, DataType.Decimal);
+ }
+
+ private double CalculateWithSumRange(
+ ExcelDataProvider.IRangeInfo range,
+ string criteria,
+ ExcelDataProvider.IRangeInfo sumRange,
+ ParsingContext context) {
+ var retVal = 0d;
+ foreach (var cell in range) {
+ if (_evaluator.Evaluate(cell.Value, criteria)) {
+ var or = cell.Row - range.Address._fromRow;
+ var oc = cell.Column - range.Address._fromCol;
+ if (sumRange.Address._fromRow + or <= sumRange.Address._toRow
+ && sumRange.Address._fromCol + oc <= sumRange.Address._toCol) {
+ var v = sumRange.GetOffset(or, oc);
+ if (v is ExcelErrorValue value) {
+ throw (new ExcelErrorValueException(value));
+ }
+ retVal += ConvertUtil.GetValueDouble(v, true);
+ }
+ }
+ }
+ return retVal;
+ }
+
+ private double CalculateSingleRange(
+ IEnumerable<FunctionArgument> args,
+ string expression,
+ ParsingContext context) {
+ var retVal = 0d;
+ var flattendedRange = ArgsToDoubleEnumerable(args, context);
+ foreach (var candidate in flattendedRange) {
+ if (_evaluator.Evaluate(candidate, expression)) {
+ retVal += candidate;
+ }
+ }
+ return retVal;
+ }
+
+ private double CalculateSingleRange(
+ ExcelDataProvider.IRangeInfo range,
+ string expression,
+ ParsingContext context) {
+ var retVal = 0d;
+ foreach (var candidate in range) {
+ if (_evaluator.Evaluate(candidate.Value, expression)) {
+ if (candidate.IsExcelError) {
+ throw (new ExcelErrorValueException((ExcelErrorValue)candidate.Value));
+ }
+ retVal += candidate.ValueDouble;
+ }
+ }
+ return retVal;
+ }
+
+ //private double Calculate(FunctionArgument arg, string expression)
+ //{
+ // var retVal = 0d;
+ // if (ShouldIgnore(arg) || !_evaluator.Evaluate(arg.Value, expression))
+ // {
+ // return retVal;
+ // }
+ // if (arg.Value is double || arg.Value is int)
+ // {
+ // retVal += Convert.ToDouble(arg.Value);
+ // }
+ // else if (arg.Value is System.DateTime)
+ // {
+ // retVal += Convert.ToDateTime(arg.Value).ToOADate();
+ // }
+ // else if (arg.Value is IEnumerable<FunctionArgument>)
+ // {
+ // foreach (var item in (IEnumerable<FunctionArgument>)arg.Value)
+ // {
+ // retVal += Calculate(item, expression);
+ // }
+ // }
+ // return retVal;
+ //}
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/SumIfs.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/SumIfs.cs
new file mode 100644
index 0000000..6cd29bb
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/SumIfs.cs
@@ -0,0 +1,68 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-15
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class SumIfs : MultipleRangeCriteriasFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
+ ValidateArguments(functionArguments, 3);
+ var sumRange = ArgsToDoubleEnumerable(
+ true,
+ new List<FunctionArgument> { functionArguments[0] },
+ context)
+ .ToList();
+ var argRanges = new List<ExcelDataProvider.IRangeInfo>();
+ var criterias = new List<object>();
+ for (var ix = 1; ix < 31; ix += 2) {
+ if (functionArguments.Length <= ix) {
+ break;
+ }
+ var rangeInfo = functionArguments[ix].ValueAsRangeInfo;
+ argRanges.Add(rangeInfo);
+ if (ix > 1) {
+ ThrowExcelErrorValueExceptionIf(
+ () => rangeInfo.GetNCells() != argRanges[0].GetNCells(),
+ eErrorType.Value);
+ }
+ criterias.Add(functionArguments[ix + 1].Value);
+ }
+ IEnumerable<int> matchIndexes = GetMatchIndexes(argRanges[0], criterias[0]);
+ var enumerable = matchIndexes as IList<int> ?? matchIndexes.ToList();
+ for (var ix = 1; ix < argRanges.Count && enumerable.Any(); ix++) {
+ var indexes = GetMatchIndexes(argRanges[ix], criterias[ix]);
+ matchIndexes = enumerable.Intersect(indexes);
+ }
+
+ var result = matchIndexes.Sum(index => sumRange[index]);
+
+ return CreateResult(result, DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/SumProduct.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/SumProduct.cs
new file mode 100644
index 0000000..b0ef6c1
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/SumProduct.cs
@@ -0,0 +1,84 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class SumProduct : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ double result = 0d;
+ List<List<double>> results = new List<List<double>>();
+ foreach (var arg in arguments) {
+ results.Add(new());
+ var currentResult = results.Last();
+ if (arg.Value is IEnumerable<FunctionArgument> value) {
+ foreach (var val in value) {
+ AddValue(val.Value, currentResult);
+ }
+ } else if (arg.Value is FunctionArgument) {
+ AddValue(arg.Value, currentResult);
+ } else if (arg.IsExcelRange) {
+ var r = arg.ValueAsRangeInfo;
+ for (int col = r.Address._fromCol; col <= r.Address._toCol; col++) {
+ for (int row = r.Address._fromRow; row <= r.Address._toRow; row++) {
+ AddValue(r.GetValue(row, col), currentResult);
+ }
+ }
+ }
+ }
+ // Validate that all supplied lists have the same length
+ var arrayLength = results.First().Count;
+ foreach (var list in results) {
+ if (list.Count != arrayLength) {
+ throw new ExcelErrorValueException(ExcelErrorValue.Create(eErrorType.Value));
+ //throw new ExcelFunctionException("All supplied arrays must have the same length", ExcelErrorCodes.Value);
+ }
+ }
+ for (var rowIndex = 0; rowIndex < arrayLength; rowIndex++) {
+ double rowResult = 1;
+ for (var colIndex = 0; colIndex < results.Count; colIndex++) {
+ rowResult *= results[colIndex][rowIndex];
+ }
+ result += rowResult;
+ }
+ return CreateResult(result, DataType.Decimal);
+ }
+
+ private void AddValue(object convertVal, List<double> currentResult) {
+ if (IsNumeric(convertVal)) {
+ currentResult.Add(Convert.ToDouble(convertVal));
+ } else if (convertVal is ExcelErrorValue val) {
+ throw (new ExcelErrorValueException(val));
+ } else {
+ currentResult.Add(0d);
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sumsq.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sumsq.cs
new file mode 100644
index 0000000..6ef28b2
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Sumsq.cs
@@ -0,0 +1,48 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Sumsq : HiddenValuesHandlingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var retVal = 0d;
+ if (arguments != null) {
+ foreach (var arg in arguments) {
+ retVal += Calculate(arg, context);
+ }
+ }
+ return CreateResult(retVal, DataType.Decimal);
+ }
+
+ private double Calculate(FunctionArgument arg, ParsingContext context, bool isInArray = false) {
+ var retVal = 0d;
+ if (ShouldIgnore(arg)) {
+ return retVal;
+ }
+ if (arg.Value is IEnumerable<FunctionArgument> arguments) {
+ foreach (var item in arguments) {
+ retVal += Calculate(item, context, true);
+ }
+ } else {
+ var cs = arg.Value as ExcelDataProvider.IRangeInfo;
+ if (cs != null) {
+ foreach (var c in cs) {
+ if (ShouldIgnore(c, context) == false) {
+ CheckForAndHandleExcelError(c);
+ retVal += System.Math.Pow(c.ValueDouble, 2);
+ }
+ }
+ } else {
+ CheckForAndHandleExcelError(arg);
+ if (IsNumericString(arg.Value) && !isInArray) {
+ var value = ConvertUtil.GetValueDouble(arg.Value);
+ return System.Math.Pow(value, 2);
+ }
+ var ignoreBool = isInArray;
+ retVal += System.Math.Pow(ConvertUtil.GetValueDouble(arg.Value, ignoreBool), 2);
+ }
+ }
+ return retVal;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Tan.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Tan.cs
new file mode 100644
index 0000000..badfbba
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Tan.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Tan : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = ArgToDecimal(arguments, 0);
+ return CreateResult(System.Math.Tan(arg), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Tanh.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Tanh.cs
new file mode 100644
index 0000000..bc07d93
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Tanh.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Tanh : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var arg = ArgToDecimal(arguments, 0);
+ return CreateResult(System.Math.Tanh(arg), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Trunc.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Trunc.cs
new file mode 100644
index 0000000..09adcb1
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Trunc.cs
@@ -0,0 +1,44 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2014-01-06
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Trunc : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var number = ArgToDecimal(arguments, 0);
+ if (arguments.Count() == 1) {
+ return CreateResult(System.Math.Truncate(number), DataType.Decimal);
+ }
+ var nDigits = ArgToInt(arguments, 1);
+ var func = context.Configuration.FunctionRepository.GetFunction("rounddown");
+ return func.Execute(arguments, context);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Var.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Var.cs
new file mode 100644
index 0000000..d7e1d5e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/Var.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Var : HiddenValuesHandlingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var args = ArgsToDoubleEnumerable(IgnoreHiddenValues, false, arguments, context);
+ return new(VarMethods.Var(args), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/VarMethods.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/VarMethods.cs
new file mode 100644
index 0000000..f16b902
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/VarMethods.cs
@@ -0,0 +1,50 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-04-19
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+internal static class VarMethods {
+ private static double Divide(double left, double right) {
+ if (System.Math.Abs(right - 0d) < double.Epsilon) {
+ throw new ExcelErrorValueException(eErrorType.Div0);
+ }
+ return left / right;
+ }
+
+ public static double Var(IEnumerable<double> args) {
+ double avg = args.Average();
+ double d = args.Aggregate(0.0, (total, next) => total + System.Math.Pow(next - avg, 2));
+ return Divide(d, (args.Count() - 1));
+ }
+
+ public static double VarP(IEnumerable<double> args) {
+ double avg = args.Average();
+ double d = args.Aggregate(0.0, (total, next) => total + System.Math.Pow(next - avg, 2));
+ return Divide(d, args.Count());
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/VarP.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/VarP.cs
new file mode 100644
index 0000000..9ee6bb0
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Math/VarP.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class VarP : HiddenValuesHandlingFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var args = ArgsToDoubleEnumerable(IgnoreHiddenValues, false, arguments, context);
+ return new(VarMethods.VarP(args), DataType.Decimal);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Numeric/CInt.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Numeric/CInt.cs
new file mode 100644
index 0000000..1f11dc7
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Numeric/CInt.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class CInt : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var num = ArgToDecimal(arguments, 0);
+ return CreateResult((int)System.Math.Floor(num), DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/ObjectEnumerableArgConverter.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/ObjectEnumerableArgConverter.cs
new file mode 100644
index 0000000..8db3856
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/ObjectEnumerableArgConverter.cs
@@ -0,0 +1,49 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class ObjectEnumerableArgConverter : CollectionFlattener<object> {
+ public virtual IEnumerable<object> ConvertArgs(
+ bool ignoreHidden,
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ return base.FuncArgsToFlatEnumerable(
+ arguments,
+ (arg, argList) => {
+ if (arg.Value is ExcelDataProvider.IRangeInfo info) {
+ foreach (var cell in info) {
+ if (!CellStateHelper.ShouldIgnore(ignoreHidden, cell, context)) {
+ argList.Add(cell.Value);
+ }
+ }
+ } else {
+ argList.Add(arg.Value);
+ }
+ });
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Address.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Address.cs
new file mode 100644
index 0000000..76fc916
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Address.cs
@@ -0,0 +1,62 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Address : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var row = ArgToInt(arguments, 0);
+ var col = ArgToInt(arguments, 1);
+ ThrowExcelErrorValueExceptionIf(() => row < 0 && col < 0, eErrorType.Value);
+ var referenceType = ExcelReferenceType.AbsoluteRowAndColumn;
+ var worksheetSpec = string.Empty;
+ if (arguments.Count() > 2) {
+ var arg3 = ArgToInt(arguments, 2);
+ ThrowExcelErrorValueExceptionIf(() => arg3 < 1 || arg3 > 4, eErrorType.Value);
+ referenceType = (ExcelReferenceType)ArgToInt(arguments, 2);
+ }
+ if (arguments.Count() > 3) {
+ var fourthArg = arguments.ElementAt(3).Value;
+ if (fourthArg is bool arg && !arg) {
+ throw new InvalidOperationException("Excelformulaparser does not support the R1C1 format!");
+ }
+ }
+ if (arguments.Count() > 4) {
+ var fifthArg = arguments.ElementAt(4).Value;
+ if (fifthArg is string && !string.IsNullOrEmpty(fifthArg.ToString())) {
+ worksheetSpec = fifthArg + "!";
+ }
+ }
+ var translator = new IndexToAddressTranslator(context.ExcelDataProvider, referenceType);
+ return CreateResult(worksheetSpec + translator.ToAddress(col, row), DataType.ExcelAddress);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/ArrayLookupNavigator.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/ArrayLookupNavigator.cs
new file mode 100644
index 0000000..59cc919
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/ArrayLookupNavigator.cs
@@ -0,0 +1,57 @@
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class ArrayLookupNavigator : LookupNavigator {
+ private readonly FunctionArgument[] _arrayData;
+ private int _index;
+ private object _currentValue;
+
+ public ArrayLookupNavigator(
+ LookupDirection direction,
+ LookupArguments arguments,
+ ParsingContext parsingContext)
+ : base(direction, arguments, parsingContext) {
+ Require.That(arguments).Named("arguments").IsNotNull();
+ Require.That(arguments.DataArray).Named("arguments.DataArray").IsNotNull();
+ _arrayData = arguments.DataArray.ToArray();
+ Initialize();
+ }
+
+ private void Initialize() {
+ if (Arguments.LookupIndex >= _arrayData.Length) {
+ throw new ExcelErrorValueException(eErrorType.Ref);
+ }
+ SetCurrentValue();
+ }
+
+ public override int Index => _index;
+
+ private void SetCurrentValue() {
+ _currentValue = _arrayData[_index];
+ }
+
+ private bool HasNext() {
+ if (Direction == LookupDirection.Vertical) {
+ return _index < (_arrayData.Length - 1);
+ }
+ return false;
+ }
+
+ public override bool MoveNext() {
+ if (!HasNext()) {
+ return false;
+ }
+ if (Direction == LookupDirection.Vertical) {
+ _index++;
+ }
+ SetCurrentValue();
+ return true;
+ }
+
+ public override object CurrentValue => _arrayData[_index].Value;
+
+ public override object GetLookupValue() {
+ return _arrayData[_index].Value;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Choose.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Choose.cs
new file mode 100644
index 0000000..ea80916
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Choose.cs
@@ -0,0 +1,43 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Choose : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var index = ArgToInt(arguments, 0);
+ var items = new List<string>();
+ for (int x = 0; x < arguments.Count(); x++) {
+ items.Add(arguments.ElementAt(x).ValueFirst.ToString());
+ }
+ return CreateResult(items[index], DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Column.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Column.cs
new file mode 100644
index 0000000..810d1e4
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Column.cs
@@ -0,0 +1,47 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Column : LookupFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ if (arguments == null || arguments.Count() == 0) {
+ return CreateResult(context.Scopes.Current.Address.FromCol, DataType.Integer);
+ }
+ var rangeAddress = ArgToString(arguments, 0);
+ if (!ExcelAddressUtil.IsValidAddress(rangeAddress)) {
+ throw new ArgumentException("An invalid argument was supplied");
+ }
+ var factory = new RangeAddressFactory(context.ExcelDataProvider);
+ var address = factory.Create(rangeAddress);
+ return CreateResult(address.FromCol, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Columns.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Columns.cs
new file mode 100644
index 0000000..5e92d1a
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Columns.cs
@@ -0,0 +1,49 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Columns : LookupFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var r = arguments.ElementAt(0).ValueAsRangeInfo;
+ if (r != null) {
+ return CreateResult(r.Address._toCol - r.Address._fromCol + 1, DataType.Integer);
+ }
+ var range = ArgToString(arguments, 0);
+ if (ExcelAddressUtil.IsValidAddress(range)) {
+ var factory = new RangeAddressFactory(context.ExcelDataProvider);
+ var address = factory.Create(range);
+ return CreateResult(address.ToCol - address.FromCol + 1, DataType.Integer);
+ }
+ throw new ArgumentException("Invalid range supplied");
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/ExcelLookupNavigator.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/ExcelLookupNavigator.cs
new file mode 100644
index 0000000..c843742
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/ExcelLookupNavigator.cs
@@ -0,0 +1,105 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public class ExcelLookupNavigator : LookupNavigator {
+ private int _currentRow;
+ private int _currentCol;
+ private object _currentValue;
+ private RangeAddress _rangeAddress;
+ private int _index;
+
+ public ExcelLookupNavigator(
+ LookupDirection direction,
+ LookupArguments arguments,
+ ParsingContext parsingContext)
+ : base(direction, arguments, parsingContext) {
+ Initialize();
+ }
+
+ private void Initialize() {
+ _index = 0;
+ var factory = new RangeAddressFactory(ParsingContext.ExcelDataProvider);
+ if (Arguments.RangeInfo == null) {
+ _rangeAddress = factory.Create(
+ ParsingContext.Scopes.Current.Address.Worksheet,
+ Arguments.RangeAddress);
+ } else {
+ _rangeAddress = factory.Create(
+ Arguments.RangeInfo.Address.WorkSheet,
+ Arguments.RangeInfo.Address.Address);
+ }
+ _currentCol = _rangeAddress.FromCol;
+ _currentRow = _rangeAddress.FromRow;
+ SetCurrentValue();
+ }
+
+ private void SetCurrentValue() {
+ _currentValue = ParsingContext.ExcelDataProvider.GetCellValue(
+ _rangeAddress.Worksheet,
+ _currentRow,
+ _currentCol);
+ }
+
+ private bool HasNext() {
+ if (Direction == LookupDirection.Vertical) {
+ return _currentRow < _rangeAddress.ToRow;
+ }
+ return _currentCol < _rangeAddress.ToCol;
+ }
+
+ public override int Index => _index;
+
+ public override bool MoveNext() {
+ if (!HasNext()) {
+ return false;
+ }
+ if (Direction == LookupDirection.Vertical) {
+ _currentRow++;
+ } else {
+ _currentCol++;
+ }
+ _index++;
+ SetCurrentValue();
+ return true;
+ }
+
+ public override object CurrentValue => _currentValue;
+
+ public override object GetLookupValue() {
+ var row = _currentRow;
+ var col = _currentCol;
+ if (Direction == LookupDirection.Vertical) {
+ col += Arguments.LookupIndex - 1;
+ row += Arguments.LookupOffset;
+ } else {
+ row += Arguments.LookupIndex - 1;
+ col += Arguments.LookupOffset;
+ }
+ return ParsingContext.ExcelDataProvider.GetCellValue(_rangeAddress.Worksheet, row, col);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/ExcelMatch.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/ExcelMatch.cs
new file mode 100644
index 0000000..7bd3e4b
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/ExcelMatch.cs
@@ -0,0 +1,88 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class ExcelMatch : LookupFunction {
+ private enum MatchType {
+ ClosestAbove = -1,
+ ExactMatch = 0,
+ ClosestBelow = 1,
+ }
+
+ public ExcelMatch()
+ : base(new WildCardValueMatcher(), new()) {}
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+
+ var searchedValue = arguments.ElementAt(0).Value;
+ var address = ArgToString(arguments, 1);
+ var rangeAddressFactory = new RangeAddressFactory(context.ExcelDataProvider);
+ var rangeAddress = rangeAddressFactory.Create(address);
+ var matchType = GetMatchType(arguments);
+ var args = new LookupArguments(searchedValue, address, 0, 0, false);
+ var lookupDirection = GetLookupDirection(rangeAddress);
+ var navigator = LookupNavigatorFactory.Create(lookupDirection, args, context);
+ int? lastMatchResult = default(int?);
+ do {
+ var matchResult = IsMatch(navigator.CurrentValue, searchedValue);
+ if (matchType == MatchType.ClosestBelow && matchResult >= 0) {
+ if (!lastMatchResult.HasValue && matchResult > 0) {
+ // TODO: error handling. This happens only if the first item is
+ // below the searched value.
+ }
+ var index = matchResult == 0 ? navigator.Index + 1 : navigator.Index;
+ return CreateResult(index, DataType.Integer);
+ }
+ if (matchType == MatchType.ClosestAbove && matchResult <= 0) {
+ if (!lastMatchResult.HasValue && matchResult < 0) {
+ // TODO: error handling. This happens only if the first item is
+ // above the searched value
+ }
+ var index = matchResult == 0 ? navigator.Index + 1 : navigator.Index;
+ return CreateResult(index, DataType.Integer);
+ }
+ if (matchType == MatchType.ExactMatch && matchResult == 0) {
+ return CreateResult(navigator.Index + 1, DataType.Integer);
+ }
+ lastMatchResult = matchResult;
+ } while (navigator.MoveNext());
+ return CreateResult(null, DataType.Integer);
+ }
+
+ private MatchType GetMatchType(IEnumerable<FunctionArgument> arguments) {
+ var matchType = MatchType.ClosestBelow;
+ if (arguments.Count() > 2) {
+ matchType = (MatchType)ArgToInt(arguments, 2);
+ }
+ return matchType;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/HLookup.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/HLookup.cs
new file mode 100644
index 0000000..abd2484
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/HLookup.cs
@@ -0,0 +1,40 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class HLookup : LookupFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 3);
+ var lookupArgs = new LookupArguments(arguments);
+ ThrowExcelErrorValueExceptionIf(() => lookupArgs.LookupIndex < 1, eErrorType.Value);
+ var navigator = LookupNavigatorFactory.Create(LookupDirection.Horizontal, lookupArgs, context);
+ return Lookup(navigator, lookupArgs);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Index.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Index.cs
new file mode 100644
index 0000000..3629f4d
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Index.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Index : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var arg1 = arguments.ElementAt(0);
+ var args = arg1.Value as IEnumerable<FunctionArgument>;
+ var crf = new CompileResultFactory();
+ if (args != null) {
+ var index = ArgToInt(arguments, 1);
+ if (index > args.Count()) {
+ throw new ExcelErrorValueException(eErrorType.Ref);
+ }
+ var candidate = args.ElementAt(index - 1);
+ //Commented JK-Can be any data type
+ //if (!IsNumber(candidate.Value))
+ //{
+ // throw new ExcelErrorValueException(eErrorType.Value);
+ //}
+ //return CreateResult(ConvertUtil.GetValueDouble(candidate.Value), DataType.Decimal);
+ return crf.Create(candidate.Value);
+ }
+ if (arg1.IsExcelRange) {
+ var row = ArgToInt(arguments, 1);
+ var col = arguments.Count() > 2 ? ArgToInt(arguments, 2) : 1;
+ var ri = arg1.ValueAsRangeInfo;
+ if (row > ri.Address._toRow - ri.Address._fromRow + 1
+ || col > ri.Address._toCol - ri.Address._fromCol + 1) {
+ ThrowExcelErrorValueException(eErrorType.Ref);
+ }
+ var candidate = ri.GetOffset(row - 1, col - 1);
+ //Commented JK-Can be any data type
+ //if (!IsNumber(candidate.Value))
+ //{
+ // throw new ExcelErrorValueException(eErrorType.Value);
+ //}
+ return crf.Create(candidate);
+ }
+ throw new NotImplementedException();
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Indirect.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Indirect.cs
new file mode 100644
index 0000000..68319d6
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Indirect.cs
@@ -0,0 +1,49 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2014-04-13
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Indirect : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var address = ArgToString(arguments, 0);
+ var adr = new ExcelAddress(address);
+ var ws = adr.WorkSheet;
+ if (string.IsNullOrEmpty(ws)) {
+ ws = context.Scopes.Current.Address.Worksheet;
+ }
+ var result = context.ExcelDataProvider.GetRange(ws, adr._fromRow, adr._fromCol, address);
+ if (result.IsEmpty) {
+ // Bug 15290
+ var namedValueExpr = new NamedValueExpression(address, context);
+ return namedValueExpr.Compile();
+ }
+ return new(result, DataType.Enumerable);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Lookup.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Lookup.cs
new file mode 100644
index 0000000..7b1dbad
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Lookup.cs
@@ -0,0 +1,97 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Lookup : LookupFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ if (HaveTwoRanges(arguments)) {
+ return HandleTwoRanges(arguments, context);
+ }
+ return HandleSingleRange(arguments, context);
+ }
+
+ private bool HaveTwoRanges(IEnumerable<FunctionArgument> arguments) {
+ if (arguments.Count() == 2) {
+ return false;
+ }
+ return (ExcelAddressUtil.IsValidAddress(arguments.ElementAt(2).Value.ToString()));
+ }
+
+ private CompileResult HandleSingleRange(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var searchedValue = arguments.ElementAt(0).Value;
+ Require.That(arguments.ElementAt(1).Value).Named("firstAddress").IsNotNull();
+ var firstAddress = ArgToString(arguments, 1);
+ var rangeAddressFactory = new RangeAddressFactory(context.ExcelDataProvider);
+ var address = rangeAddressFactory.Create(firstAddress);
+ var nRows = address.ToRow - address.FromRow;
+ var nCols = address.ToCol - address.FromCol;
+ var lookupIndex = nCols + 1;
+ var lookupDirection = LookupDirection.Vertical;
+ if (nCols > nRows) {
+ lookupIndex = nRows + 1;
+ lookupDirection = LookupDirection.Horizontal;
+ }
+ var lookupArgs = new LookupArguments(searchedValue, firstAddress, lookupIndex, 0, true);
+ var navigator = LookupNavigatorFactory.Create(lookupDirection, lookupArgs, context);
+ return Lookup(navigator, lookupArgs);
+ }
+
+ private CompileResult HandleTwoRanges(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var searchedValue = arguments.ElementAt(0).Value;
+ Require.That(arguments.ElementAt(1).Value).Named("firstAddress").IsNotNull();
+ Require.That(arguments.ElementAt(2).Value).Named("secondAddress").IsNotNull();
+ var firstAddress = ArgToString(arguments, 1);
+ var secondAddress = ArgToString(arguments, 2);
+ var rangeAddressFactory = new RangeAddressFactory(context.ExcelDataProvider);
+ var address1 = rangeAddressFactory.Create(firstAddress);
+ var address2 = rangeAddressFactory.Create(secondAddress);
+ var lookupIndex = (address2.FromCol - address1.FromCol) + 1;
+ var lookupOffset = address2.FromRow - address1.FromRow;
+ var lookupDirection = GetLookupDirection(address1);
+ if (lookupDirection == LookupDirection.Horizontal) {
+ lookupIndex = (address2.FromRow - address1.FromRow) + 1;
+ lookupOffset = address2.FromCol - address1.FromCol;
+ }
+ var lookupArgs = new LookupArguments(
+ searchedValue,
+ firstAddress,
+ lookupIndex,
+ lookupOffset,
+ true);
+ var navigator = LookupNavigatorFactory.Create(lookupDirection, lookupArgs, context);
+ return Lookup(navigator, lookupArgs);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/LookupArguments.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/LookupArguments.cs
new file mode 100644
index 0000000..05933b5
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/LookupArguments.cs
@@ -0,0 +1,102 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class LookupArguments {
+ public enum LookupArgumentDataType {
+ ExcelRange,
+ DataArray,
+ }
+
+ public LookupArguments(IEnumerable<FunctionArgument> arguments)
+ : this(arguments, new()) {}
+
+ public LookupArguments(IEnumerable<FunctionArgument> arguments, ArgumentParsers argumentParsers) {
+ _argumentParsers = argumentParsers;
+ SearchedValue = arguments.ElementAt(0).Value;
+ var arg1 = arguments.ElementAt(1).Value;
+ var dataArray = arg1 as IEnumerable<FunctionArgument>;
+ if (dataArray != null) {
+ DataArray = dataArray;
+ ArgumentDataType = LookupArgumentDataType.DataArray;
+ } else {
+ //if (arg1 is ExcelDataProvider.INameInfo) arg1 = ((ExcelDataProvider.INameInfo) arg1).Value;
+ var rangeInfo = arg1 as ExcelDataProvider.IRangeInfo;
+ if (rangeInfo != null) {
+ RangeAddress = string.IsNullOrEmpty(rangeInfo.Address.WorkSheet)
+ ? rangeInfo.Address.Address
+ : "'" + rangeInfo.Address.WorkSheet + "'!" + rangeInfo.Address.Address;
+ RangeInfo = rangeInfo;
+ ArgumentDataType = LookupArgumentDataType.ExcelRange;
+ } else {
+ RangeAddress = arg1.ToString();
+ ArgumentDataType = LookupArgumentDataType.ExcelRange;
+ }
+ }
+ LookupIndex = (int)
+ _argumentParsers.GetParser(DataType.Integer).Parse(arguments.ElementAt(2).Value);
+ if (arguments.Count() > 3) {
+ RangeLookup = (bool)
+ _argumentParsers.GetParser(DataType.Boolean).Parse(arguments.ElementAt(3).Value);
+ } else {
+ RangeLookup = true;
+ }
+ }
+
+ public LookupArguments(
+ object searchedValue,
+ string rangeAddress,
+ int lookupIndex,
+ int lookupOffset,
+ bool rangeLookup) {
+ SearchedValue = searchedValue;
+ RangeAddress = rangeAddress;
+ LookupIndex = lookupIndex;
+ LookupOffset = lookupOffset;
+ RangeLookup = rangeLookup;
+ }
+
+ private readonly ArgumentParsers _argumentParsers;
+
+ public object SearchedValue { get; private set; }
+
+ public string RangeAddress { get; private set; }
+
+ public int LookupIndex { get; private set; }
+
+ public int LookupOffset { get; private set; }
+
+ public bool RangeLookup { get; private set; }
+
+ public IEnumerable<FunctionArgument> DataArray { get; private set; }
+
+ public ExcelDataProvider.IRangeInfo RangeInfo { get; private set; }
+
+ public LookupArgumentDataType ArgumentDataType { get; private set; }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/LookupDirection.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/LookupDirection.cs
new file mode 100644
index 0000000..416d087
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/LookupDirection.cs
@@ -0,0 +1,31 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public enum LookupDirection {
+ Vertical,
+ Horizontal,
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/LookupFunction.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/LookupFunction.cs
new file mode 100644
index 0000000..e376443
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/LookupFunction.cs
@@ -0,0 +1,88 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public abstract class LookupFunction : ExcelFunction {
+ private readonly ValueMatcher _valueMatcher;
+ private readonly CompileResultFactory _compileResultFactory;
+
+ public LookupFunction()
+ : this(new LookupValueMatcher(), new()) {}
+
+ public LookupFunction(ValueMatcher valueMatcher, CompileResultFactory compileResultFactory) {
+ _valueMatcher = valueMatcher;
+ _compileResultFactory = compileResultFactory;
+ }
+
+ public override bool IsLookupFuction => true;
+
+ protected int IsMatch(object o1, object o2) {
+ return _valueMatcher.IsMatch(o1, o2);
+ }
+
+ protected LookupDirection GetLookupDirection(RangeAddress rangeAddress) {
+ var nRows = rangeAddress.ToRow - rangeAddress.FromRow;
+ var nCols = rangeAddress.ToCol - rangeAddress.FromCol;
+ return nCols > nRows ? LookupDirection.Horizontal : LookupDirection.Vertical;
+ }
+
+ protected CompileResult Lookup(LookupNavigator navigator, LookupArguments lookupArgs) {
+ object lastValue = null;
+ object lastLookupValue = null;
+ int? lastMatchResult = null;
+ if (lookupArgs.SearchedValue == null) {
+ return new(ExcelErrorValue.Create(eErrorType.Na), DataType.ExcelError);
+ }
+ do {
+ var matchResult = IsMatch(navigator.CurrentValue, lookupArgs.SearchedValue);
+ if (matchResult != 0) {
+ if (lastValue != null && navigator.CurrentValue == null) {
+ break;
+ }
+
+ if (lookupArgs.RangeLookup) {
+ if (lastValue == null && matchResult > 0) {
+ ThrowExcelErrorValueException(eErrorType.Na);
+ }
+ if (lastValue != null && matchResult > 0 && lastMatchResult < 0) {
+ return _compileResultFactory.Create(lastLookupValue);
+ }
+ lastMatchResult = matchResult;
+ lastValue = navigator.CurrentValue;
+ lastLookupValue = navigator.GetLookupValue();
+ }
+ } else {
+ return _compileResultFactory.Create(navigator.GetLookupValue());
+ }
+ } while (navigator.MoveNext());
+
+ if (lookupArgs.RangeLookup) {
+ return _compileResultFactory.Create(lastLookupValue);
+ }
+ return new(ExcelErrorValue.Create(eErrorType.Na), DataType.ExcelError);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigator.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigator.cs
new file mode 100644
index 0000000..b29eabe
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigator.cs
@@ -0,0 +1,56 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public abstract class LookupNavigator {
+ protected readonly LookupDirection Direction;
+ protected readonly LookupArguments Arguments;
+ protected readonly ParsingContext ParsingContext;
+
+ public LookupNavigator(
+ LookupDirection direction,
+ LookupArguments arguments,
+ ParsingContext parsingContext) {
+ Require.That(arguments).Named("arguments").IsNotNull();
+ Require.That(parsingContext).Named("parsingContext").IsNotNull();
+ Require
+ .That(parsingContext.ExcelDataProvider)
+ .Named("parsingContext.ExcelDataProvider")
+ .IsNotNull();
+ Direction = direction;
+ Arguments = arguments;
+ ParsingContext = parsingContext;
+ }
+
+ public abstract int Index { get; }
+
+ public abstract bool MoveNext();
+
+ public abstract object CurrentValue { get; }
+
+ public abstract object GetLookupValue();
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigatorFactory.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigatorFactory.cs
new file mode 100644
index 0000000..be63cde
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigatorFactory.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace AppsheetEpplus;
+
+public static class LookupNavigatorFactory {
+ public static LookupNavigator Create(
+ LookupDirection direction,
+ LookupArguments args,
+ ParsingContext parsingContext) {
+ if (args.ArgumentDataType == LookupArguments.LookupArgumentDataType.ExcelRange) {
+ return new ExcelLookupNavigator(direction, args, parsingContext);
+ }
+ if (args.ArgumentDataType == LookupArguments.LookupArgumentDataType.DataArray) {
+ return new ArrayLookupNavigator(direction, args, parsingContext);
+ }
+ throw new NotSupportedException("Invalid argument datatype");
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Offset.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Offset.cs
new file mode 100644
index 0000000..9229232
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Offset.cs
@@ -0,0 +1,75 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-11
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Offset : LookupFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
+ ValidateArguments(functionArguments, 3);
+ var startRange = ArgToString(functionArguments, 0);
+ var rowOffset = ArgToInt(functionArguments, 1);
+ var colOffset = ArgToInt(functionArguments, 2);
+ int width = 0,
+ height = 0;
+ if (functionArguments.Length > 3) {
+ height = ArgToInt(functionArguments, 3);
+ ThrowExcelErrorValueExceptionIf(() => height == 0, eErrorType.Ref);
+ }
+ if (functionArguments.Length > 4) {
+ width = ArgToInt(functionArguments, 4);
+ ThrowExcelErrorValueExceptionIf(() => width == 0, eErrorType.Ref);
+ }
+
+ var adr = new ExcelAddress(startRange);
+ var ws = adr.WorkSheet;
+
+ var fromRow = adr._fromRow + rowOffset;
+ var fromCol = adr._fromCol + colOffset;
+ var toRow = (height != 0 ? height : adr._toRow) + rowOffset;
+ var toCol = (width != 0 ? width : adr._toCol) + colOffset;
+
+ var newRange = context.ExcelDataProvider.GetRange(ws, fromRow, fromCol, toRow, toCol);
+ if (!newRange.IsMulti) {
+ if (newRange.IsEmpty) {
+ return CompileResult.Empty;
+ }
+ var val = newRange.GetValue(fromRow, fromCol);
+ if (IsNumeric(val)) {
+ return CreateResult(val, DataType.Decimal);
+ }
+ if (val is ExcelErrorValue) {
+ return CreateResult(val, DataType.ExcelError);
+ }
+ return CreateResult(val, DataType.String);
+ }
+ return CreateResult(newRange, DataType.Enumerable);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Row.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Row.cs
new file mode 100644
index 0000000..2cc481f
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Row.cs
@@ -0,0 +1,47 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Row : LookupFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ if (arguments == null || arguments.Count() == 0) {
+ return CreateResult(context.Scopes.Current.Address.FromRow, DataType.Integer);
+ }
+ var rangeAddress = ArgToString(arguments, 0);
+ if (!ExcelAddressUtil.IsValidAddress(rangeAddress)) {
+ throw new ArgumentException("An invalid argument was supplied");
+ }
+ var factory = new RangeAddressFactory(context.ExcelDataProvider);
+ var address = factory.Create(rangeAddress);
+ return CreateResult(address.FromRow, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Rows.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Rows.cs
new file mode 100644
index 0000000..31668a8
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/Rows.cs
@@ -0,0 +1,49 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Rows : LookupFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var r = arguments.ElementAt(0).ValueAsRangeInfo;
+ if (r != null) {
+ return CreateResult(r.Address._toRow - r.Address._fromRow + 1, DataType.Integer);
+ }
+ var range = ArgToString(arguments, 0);
+ if (ExcelAddressUtil.IsValidAddress(range)) {
+ var factory = new RangeAddressFactory(context.ExcelDataProvider);
+ var address = factory.Create(range);
+ return CreateResult(address.ToRow - address.FromRow + 1, DataType.Integer);
+ }
+ throw new ArgumentException("Invalid range supplied");
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/VLookup.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/VLookup.cs
new file mode 100644
index 0000000..aad86f3
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/RefAndLookup/VLookup.cs
@@ -0,0 +1,50 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace AppsheetEpplus;
+
+public class VLookup : LookupFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ Stopwatch sw = null;
+ if (context.Debug) {
+ sw = new();
+ sw.Start();
+ }
+ ValidateArguments(arguments, 3);
+ var lookupArgs = new LookupArguments(arguments);
+ var navigator = LookupNavigatorFactory.Create(LookupDirection.Vertical, lookupArgs, context);
+ var result = Lookup(navigator, lookupArgs);
+ if (context.Debug) {
+ sw.Stop();
+ context.Configuration.Logger.LogFunction("VLOOKUP", sw.ElapsedMilliseconds);
+ }
+ return result;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/CStr.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/CStr.cs
new file mode 100644
index 0000000..b95d76d
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/CStr.cs
@@ -0,0 +1,37 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class CStr : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ return CreateResult(ArgToString(arguments, 0), DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/CharFunction.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/CharFunction.cs
new file mode 100644
index 0000000..412762b
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/CharFunction.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class CharFunction : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var number = ArgToInt(arguments, 0);
+ ThrowExcelErrorValueExceptionIf(() => number < 1 || number > 255, eErrorType.Value);
+ return CreateResult(((char)number).ToString(), DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Concatenate.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Concatenate.cs
new file mode 100644
index 0000000..0518a1e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Concatenate.cs
@@ -0,0 +1,47 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Text;
+
+namespace AppsheetEpplus;
+
+public class Concatenate : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ if (arguments == null) {
+ return CreateResult(string.Empty, DataType.String);
+ }
+ var sb = new StringBuilder();
+ foreach (var arg in arguments) {
+ var v = arg.ValueFirst;
+ if (v != null) {
+ sb.Append(v);
+ }
+ }
+ return CreateResult(sb.ToString(), DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Exact.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Exact.cs
new file mode 100644
index 0000000..75d1fad
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Exact.cs
@@ -0,0 +1,53 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Exact : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var val1 = arguments.ElementAt(0).ValueFirst;
+ var val2 = arguments.ElementAt(1).ValueFirst;
+
+ if (val1 == null && val2 == null) {
+ return CreateResult(true, DataType.Boolean);
+ }
+ if ((val1 == null && val2 != null) || (val1 != null && val2 == null)) {
+ return CreateResult(false, DataType.Boolean);
+ }
+
+ var result = string.Compare(
+ val1.ToString(),
+ val2.ToString(),
+ StringComparison.InvariantCulture);
+ return CreateResult(result == 0, DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Find.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Find.cs
new file mode 100644
index 0000000..a0b7583
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Find.cs
@@ -0,0 +1,51 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Find : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
+ ValidateArguments(functionArguments, 2);
+ var search = ArgToString(functionArguments, 0);
+ var searchIn = ArgToString(functionArguments, 1);
+ var startIndex = 0;
+ if (functionArguments.Count() > 2) {
+ startIndex = ArgToInt(functionArguments, 2);
+ }
+ var result = searchIn.IndexOf(search, startIndex, StringComparison.Ordinal);
+ if (result == -1) {
+ throw new ExcelErrorValueException(ExcelErrorValue.Create(eErrorType.Value));
+ }
+ // Adding 1 because Excel uses 1-based index
+ return CreateResult(result + 1, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Fixed.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Fixed.cs
new file mode 100644
index 0000000..7acf199
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Fixed.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Fixed : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var number = ArgToDecimal(arguments, 0);
+ var nDecimals = 2;
+ var noCommas = false;
+ if (arguments.Count() > 1) {
+ nDecimals = ArgToInt(arguments, 1);
+ }
+ if (arguments.Count() > 2) {
+ noCommas = ArgToBool(arguments, 2);
+ }
+ var format = (noCommas ? "F" : "N") + nDecimals.ToString(CultureInfo.InvariantCulture);
+ if (nDecimals < 0) {
+ number = number - (number % (System.Math.Pow(10, nDecimals * -1)));
+ number = System.Math.Floor(number);
+ format = noCommas ? "F0" : "N0";
+ }
+ var retVal = number.ToString(format);
+ return CreateResult(retVal, DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Hyperlink.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Hyperlink.cs
new file mode 100644
index 0000000..ccc86ed
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Hyperlink.cs
@@ -0,0 +1,41 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-10
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Hyperlink : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ if (arguments.Count() > 1) {
+ return CreateResult(ArgToString(arguments, 1), DataType.String);
+ }
+ return CreateResult(ArgToString(arguments, 0), DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Left.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Left.cs
new file mode 100644
index 0000000..37c89cf
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Left.cs
@@ -0,0 +1,39 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Left : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var str = ArgToString(arguments, 0);
+ var length = ArgToInt(arguments, 1);
+ return CreateResult(str.Substring(0, length), DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Len.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Len.cs
new file mode 100644
index 0000000..4e701f2
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Len.cs
@@ -0,0 +1,40 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Len : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var length = arguments.First().ValueFirst.ToString().Length;
+ return CreateResult(Convert.ToDouble(length), DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Lower.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Lower.cs
new file mode 100644
index 0000000..1cb9b8e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Lower.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Lower : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ return CreateResult(arguments.First().ValueFirst.ToString().ToLower(), DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Mid.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Mid.cs
new file mode 100644
index 0000000..92bb6bb
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Mid.cs
@@ -0,0 +1,51 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Mid : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 3);
+ var text = ArgToString(arguments, 0);
+ var startIx = ArgToInt(arguments, 1);
+ var length = ArgToInt(arguments, 2);
+ if (startIx <= 0) {
+ throw (new ArgumentException("Argument start can't be less than 1"));
+ }
+ //Allow overflowing start and length
+ if (startIx > text.Length) {
+ return CreateResult("", DataType.String);
+ }
+ var result = text.Substring(
+ startIx - 1,
+ startIx - 1 + length < text.Length ? length : text.Length - startIx + 1);
+ return CreateResult(result, DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Proper.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Proper.cs
new file mode 100644
index 0000000..8595e4c
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Proper.cs
@@ -0,0 +1,50 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+
+namespace AppsheetEpplus;
+
+public class Proper : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var text = ArgToString(arguments, 0).ToLower(CultureInfo.InvariantCulture);
+ var sb = new StringBuilder();
+ var previousChar = '.';
+ foreach (var ch in text) {
+ if (!char.IsLetter(previousChar)) {
+ sb.Append(ch.ToString(CultureInfo.InvariantCulture).ToUpperInvariant());
+ } else {
+ sb.Append(ch);
+ }
+ previousChar = ch;
+ }
+ return CreateResult(sb.ToString(), DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Replace.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Replace.cs
new file mode 100644
index 0000000..3888ab0
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Replace.cs
@@ -0,0 +1,54 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Replace : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 4);
+ var oldText = ArgToString(arguments, 0);
+ var startPos = ArgToInt(arguments, 1);
+ var nCharsToReplace = ArgToInt(arguments, 2);
+ var newText = ArgToString(arguments, 3);
+ var firstPart = GetFirstPart(oldText, startPos);
+ var lastPart = GetLastPart(oldText, startPos, nCharsToReplace);
+ var result = string.Concat(firstPart, newText, lastPart);
+ return CreateResult(result, DataType.String);
+ }
+
+ private string GetFirstPart(string text, int startPos) {
+ return text.Substring(0, startPos - 1);
+ }
+
+ private string GetLastPart(string text, int startPos, int nCharactersToReplace) {
+ int startIx = startPos - 1;
+ startIx += nCharactersToReplace;
+ return text.Substring(startIx, text.Length - startIx);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Rept.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Rept.cs
new file mode 100644
index 0000000..f31ffcf
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Rept.cs
@@ -0,0 +1,44 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2015-01-10
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Text;
+
+namespace AppsheetEpplus;
+
+public class Rept : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var str = ArgToString(arguments, 0);
+ var n = ArgToInt(arguments, 1);
+ var sb = new StringBuilder();
+ for (var x = 0; x < n; x++) {
+ sb.Append(str);
+ }
+ return CreateResult(sb.ToString(), DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Right.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Right.cs
new file mode 100644
index 0000000..9b86495
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Right.cs
@@ -0,0 +1,40 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Right : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var str = ArgToString(arguments, 0);
+ var length = ArgToInt(arguments, 1);
+ var startIx = str.Length - length;
+ return CreateResult(str.Substring(startIx, str.Length - startIx), DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Search.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Search.cs
new file mode 100644
index 0000000..37533a0
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Search.cs
@@ -0,0 +1,51 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2016-03-28
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Search : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
+ ValidateArguments(functionArguments, 2);
+ var search = ArgToString(functionArguments, 0);
+ var searchIn = ArgToString(functionArguments, 1);
+ var startIndex = 0;
+ if (functionArguments.Count() > 2) {
+ startIndex = ArgToInt(functionArguments, 2);
+ }
+ var result = searchIn.IndexOf(search, startIndex, StringComparison.OrdinalIgnoreCase);
+ if (result == -1) {
+ return CreateResult(ExcelErrorValue.Create(eErrorType.Value), DataType.ExcelError);
+ }
+ // Adding 1 because Excel uses 1-based index
+ return CreateResult(result + 1, DataType.Integer);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Substitute.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Substitute.cs
new file mode 100644
index 0000000..b6077c7
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Substitute.cs
@@ -0,0 +1,41 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class Substitute : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 3);
+ var text = ArgToString(arguments, 0);
+ var find = ArgToString(arguments, 1);
+ var replaceWith = ArgToString(arguments, 2);
+ var result = text.Replace(find, replaceWith);
+ return CreateResult(result, DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/T.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/T.cs
new file mode 100644
index 0000000..cf6e23f
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/T.cs
@@ -0,0 +1,42 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class T : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var val = arguments.ElementAt(0).ValueFirst;
+ if (val is string) {
+ return CreateResult(val, DataType.String);
+ }
+ return CreateResult(string.Empty, DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Text.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Text.cs
new file mode 100644
index 0000000..2116a91
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Text.cs
@@ -0,0 +1,48 @@
+/* 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 2014-01-17
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Text : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var value = arguments.First().ValueFirst;
+ var format = ArgToString(arguments, 1);
+ format = format.Replace(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, ".");
+ format = format.Replace(
+ CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator.Replace((char)160, ' '),
+ ","); //Special handling for No-Break Space
+
+ var result = context.ExcelDataProvider.GetFormat(value, format);
+
+ return CreateResult(result, DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Upper.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Upper.cs
new file mode 100644
index 0000000..e7fa69b
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Upper.cs
@@ -0,0 +1,38 @@
+/* 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
+ *******************************************************************************
+ * Mats Alm Added 2013-12-03
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class Upper : ExcelFunction {
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ return CreateResult(arguments.First().ValueFirst.ToString().ToUpper(), DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Value.cs b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Value.cs
new file mode 100644
index 0000000..5faebe7
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Functions/Text/Value.cs
@@ -0,0 +1,56 @@
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text.RegularExpressions;
+
+namespace AppsheetEpplus;
+
+public class Value : ExcelFunction {
+ private readonly string _groupSeparator = CultureInfo
+ .CurrentCulture
+ .NumberFormat
+ .NumberGroupSeparator;
+ private readonly string _decimalSeparator = CultureInfo
+ .CurrentCulture
+ .NumberFormat
+ .NumberDecimalSeparator;
+ private readonly string _timeSeparator = CultureInfo.CurrentCulture.DateTimeFormat.TimeSeparator;
+ private readonly DateValue _dateValueFunc = new();
+ private readonly TimeValue _timeValueFunc = new();
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 1);
+ var val = ArgToString(arguments, 0).TrimEnd(' ');
+ double result;
+ if (Regex.IsMatch(
+ val,
+ $"^[\\d]*({Regex.Escape(_groupSeparator)}?[\\d]*)?({Regex.Escape(_decimalSeparator)
+ }[\\d]*)?[ ?% ?]?$")) {
+ if (val.EndsWith("%")) {
+ val = val.TrimEnd('%');
+ result = double.Parse(val) / 100;
+ } else {
+ result = double.Parse(val);
+ }
+ return CreateResult(result, DataType.Decimal);
+ }
+ if (double.TryParse(val, NumberStyles.Float, CultureInfo.CurrentCulture, out result)) {
+ return CreateResult(result, DataType.Decimal);
+ }
+ var timeSeparator = Regex.Escape(_timeSeparator);
+ if (Regex.IsMatch(
+ val,
+ @"^[\d]{1,2}" + timeSeparator + @"[\d]{2}(" + timeSeparator + @"[\d]{2})?$")) {
+ var timeResult = _timeValueFunc.Execute(val);
+ if (timeResult.DataType == DataType.Date) {
+ return timeResult;
+ }
+ }
+ var dateResult = _dateValueFunc.Execute(val);
+ if (dateResult.DataType == DataType.Date) {
+ return dateResult;
+ }
+ return CreateResult(ExcelErrorValue.Create(eErrorType.Value), DataType.ExcelError);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Operators/IOperator.cs b/AppsheetEpplus/FormulaParsing/Excel/Operators/IOperator.cs
new file mode 100644
index 0000000..d5e8e86
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Operators/IOperator.cs
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public interface IOperator {
+ Operators Operator { get; }
+
+ CompileResult Apply(CompileResult left, CompileResult right);
+
+ int Precedence { get; }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Operators/Operator.cs b/AppsheetEpplus/FormulaParsing/Excel/Operators/Operator.cs
new file mode 100644
index 0000000..0f8626c
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Operators/Operator.cs
@@ -0,0 +1,388 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+public class Operator : IOperator {
+ private const int _precedencePercent = 2;
+ private const int _precedenceExp = 4;
+ private const int _precedenceMultiplyDevide = 6;
+ private const int _precedenceAddSubtract = 12;
+ private const int _precedenceConcat = 15;
+ private const int _precedenceComparison = 25;
+
+ private Operator(
+ Operators @operator,
+ int precedence,
+ Func<CompileResult, CompileResult, CompileResult> implementation) {
+ _implementation = implementation;
+ _precedence = precedence;
+ _operator = @operator;
+ }
+
+ private readonly Func<CompileResult, CompileResult, CompileResult> _implementation;
+ private readonly int _precedence;
+ private readonly Operators _operator;
+
+ int IOperator.Precedence => _precedence;
+
+ Operators IOperator.Operator => _operator;
+
+ public CompileResult Apply(CompileResult left, CompileResult right) {
+ if (left.Result is ExcelErrorValue) {
+ return new(left.Result, DataType.ExcelError);
+ //throw(new ExcelErrorValueException((ExcelErrorValue)left.Result));
+ }
+ if (right.Result is ExcelErrorValue) {
+ return new(right.Result, DataType.ExcelError);
+ //throw(new ExcelErrorValueException((ExcelErrorValue)right.Result));
+ }
+ return _implementation(left, right);
+ }
+
+ public override string ToString() {
+ return "Operator: " + _operator;
+ }
+
+ private static IOperator _plus;
+
+ public static IOperator Plus {
+ get {
+ return _plus
+ ?? (_plus = new Operator(
+ Operators.Plus,
+ _precedenceAddSubtract,
+ (l, r) => {
+ l = l == null || l.Result == null ? new(0, DataType.Integer) : l;
+ r = r == null || r.Result == null ? new(0, DataType.Integer) : r;
+ if (EitherIsError(l, r, out var errorVal)) {
+ return new(errorVal);
+ }
+ if (l.DataType == DataType.Integer && r.DataType == DataType.Integer) {
+ return new(l.ResultNumeric + r.ResultNumeric, DataType.Integer);
+ }
+ if ((l.IsNumeric
+ || l.IsNumericString
+ || l.Result is ExcelDataProvider.IRangeInfo)
+ && (r.IsNumeric
+ || r.IsNumericString
+ || r.Result is ExcelDataProvider.IRangeInfo)) {
+ return new(l.ResultNumeric + r.ResultNumeric, DataType.Decimal);
+ }
+ return new(eErrorType.Value);
+ }));
+ }
+ }
+
+ private static IOperator _minus;
+
+ public static IOperator Minus {
+ get {
+ return _minus
+ ?? (_minus = new Operator(
+ Operators.Minus,
+ _precedenceAddSubtract,
+ (l, r) => {
+ l = l == null || l.Result == null ? new(0, DataType.Integer) : l;
+ r = r == null || r.Result == null ? new(0, DataType.Integer) : r;
+ if (l.DataType == DataType.Integer && r.DataType == DataType.Integer) {
+ return new(l.ResultNumeric - r.ResultNumeric, DataType.Integer);
+ }
+ if ((l.IsNumeric
+ || l.IsNumericString
+ || l.Result is ExcelDataProvider.IRangeInfo)
+ && (r.IsNumeric
+ || r.IsNumericString
+ || r.Result is ExcelDataProvider.IRangeInfo)) {
+ return new(l.ResultNumeric - r.ResultNumeric, DataType.Decimal);
+ }
+
+ return new(eErrorType.Value);
+ }));
+ }
+ }
+
+ private static IOperator _multiply;
+
+ public static IOperator Multiply {
+ get {
+ return _multiply
+ ?? (_multiply = new Operator(
+ Operators.Multiply,
+ _precedenceMultiplyDevide,
+ (l, r) => {
+ l = l ?? new CompileResult(0, DataType.Integer);
+ r = r ?? new CompileResult(0, DataType.Integer);
+ if (l.DataType == DataType.Integer && r.DataType == DataType.Integer) {
+ return new(l.ResultNumeric * r.ResultNumeric, DataType.Integer);
+ }
+ if ((l.IsNumeric
+ || l.IsNumericString
+ || l.Result is ExcelDataProvider.IRangeInfo)
+ && (r.IsNumeric
+ || r.IsNumericString
+ || r.Result is ExcelDataProvider.IRangeInfo)) {
+ return new(l.ResultNumeric * r.ResultNumeric, DataType.Decimal);
+ }
+ return new(eErrorType.Value);
+ }));
+ }
+ }
+
+ private static IOperator _divide;
+
+ public static IOperator Divide {
+ get {
+ return _divide
+ ?? (_divide = new Operator(
+ Operators.Divide,
+ _precedenceMultiplyDevide,
+ (l, r) => {
+ if (!(l.IsNumeric
+ || l.IsNumericString
+ || l.Result is ExcelDataProvider.IRangeInfo)
+ || !(r.IsNumeric
+ || r.IsNumericString
+ || r.Result is ExcelDataProvider.IRangeInfo)) {
+ return new(eErrorType.Value);
+ }
+ var left = l.ResultNumeric;
+ var right = r.ResultNumeric;
+ if (Math.Abs(right - 0d) < double.Epsilon) {
+ return new(eErrorType.Div0);
+ }
+ if ((l.IsNumeric
+ || l.IsNumericString
+ || l.Result is ExcelDataProvider.IRangeInfo)
+ && (r.IsNumeric
+ || r.IsNumericString
+ || r.Result is ExcelDataProvider.IRangeInfo)) {
+ return new(left / right, DataType.Decimal);
+ }
+ return new(eErrorType.Value);
+ }));
+ }
+ }
+
+ public static IOperator Exp {
+ get {
+ return new Operator(
+ Operators.Exponentiation,
+ _precedenceExp,
+ (l, r) => {
+ if (l == null && r == null) {
+ return new(eErrorType.Value);
+ }
+ l = l ?? new CompileResult(0, DataType.Integer);
+ r = r ?? new CompileResult(0, DataType.Integer);
+ if ((l.IsNumeric || l.Result is ExcelDataProvider.IRangeInfo)
+ && (r.IsNumeric || r.Result is ExcelDataProvider.IRangeInfo)) {
+ return new(Math.Pow(l.ResultNumeric, r.ResultNumeric), DataType.Decimal);
+ }
+ return new(0d, DataType.Decimal);
+ });
+ }
+ }
+
+ public static IOperator Concat {
+ get {
+ return new Operator(
+ Operators.Concat,
+ _precedenceConcat,
+ (l, r) => {
+ l = l ?? new CompileResult(string.Empty, DataType.String);
+ r = r ?? new CompileResult(string.Empty, DataType.String);
+ var lStr = l.Result != null ? l.ResultValue.ToString() : string.Empty;
+ var rStr = r.Result != null ? r.ResultValue.ToString() : string.Empty;
+ return new(string.Concat(lStr, rStr), DataType.String);
+ });
+ }
+ }
+
+ private static IOperator _greaterThan;
+
+ public static IOperator GreaterThan {
+ get {
+ //return new Operator(Operators.GreaterThan, PrecedenceComparison, (l, r) => new CompileResult(Compare(l, r) > 0, DataType.Boolean));
+ return _greaterThan
+ ?? (_greaterThan = new Operator(
+ Operators.LessThanOrEqual,
+ _precedenceComparison,
+ (l, r) => Compare(l, r, compRes => compRes > 0)));
+ }
+ }
+
+ private static IOperator _eq;
+
+ public static IOperator Eq {
+ get {
+ //return new Operator(Operators.Equals, PrecedenceComparison, (l, r) => new CompileResult(Compare(l, r) == 0, DataType.Boolean));
+ return _eq
+ ?? (_eq = new Operator(
+ Operators.LessThanOrEqual,
+ _precedenceComparison,
+ (l, r) => Compare(l, r, compRes => compRes == 0)));
+ }
+ }
+
+ private static IOperator _notEqualsTo;
+
+ public static IOperator NotEqualsTo {
+ get {
+ //return new Operator(Operators.NotEqualTo, PrecedenceComparison, (l, r) => new CompileResult(Compare(l, r) != 0, DataType.Boolean));
+ return _notEqualsTo
+ ?? (_notEqualsTo = new Operator(
+ Operators.LessThanOrEqual,
+ _precedenceComparison,
+ (l, r) => Compare(l, r, compRes => compRes != 0)));
+ }
+ }
+
+ private static IOperator _greaterThanOrEqual;
+
+ public static IOperator GreaterThanOrEqual {
+ get {
+ //return new Operator(Operators.GreaterThanOrEqual, PrecedenceComparison, (l, r) => new CompileResult(Compare(l, r) >= 0, DataType.Boolean));
+ return _greaterThanOrEqual
+ ?? (_greaterThanOrEqual = new Operator(
+ Operators.LessThanOrEqual,
+ _precedenceComparison,
+ (l, r) => Compare(l, r, compRes => compRes >= 0)));
+ }
+ }
+
+ private static IOperator _lessThan;
+
+ public static IOperator LessThan {
+ get {
+ //return new Operator(Operators.LessThan, PrecedenceComparison, (l, r) => new CompileResult(Compare(l, r) < 0, DataType.Boolean));
+ return _lessThan
+ ?? (_lessThan = new Operator(
+ Operators.LessThanOrEqual,
+ _precedenceComparison,
+ (l, r) => Compare(l, r, compRes => compRes < 0)));
+ }
+ }
+
+ public static IOperator LessThanOrEqual {
+ get {
+ //return new Operator(Operators.LessThanOrEqual, PrecedenceComparison, (l, r) => new CompileResult(Compare(l, r) <= 0, DataType.Boolean));
+ return new Operator(
+ Operators.LessThanOrEqual,
+ _precedenceComparison,
+ (l, r) => Compare(l, r, compRes => compRes <= 0));
+ }
+ }
+
+ private static IOperator _percent;
+
+ public static IOperator Percent {
+ get {
+ if (_percent == null) {
+ _percent = new Operator(
+ Operators.Percent,
+ _precedencePercent,
+ (l, r) => {
+ l = l ?? new CompileResult(0, DataType.Integer);
+ r = r ?? new CompileResult(0, DataType.Integer);
+ if (l.DataType == DataType.Integer && r.DataType == DataType.Integer) {
+ return new(l.ResultNumeric * r.ResultNumeric, DataType.Integer);
+ }
+ if ((l.IsNumeric || l.Result is ExcelDataProvider.IRangeInfo)
+ && (r.IsNumeric || r.Result is ExcelDataProvider.IRangeInfo)) {
+ return new(l.ResultNumeric * r.ResultNumeric, DataType.Decimal);
+ }
+ return new(eErrorType.Value);
+ });
+ }
+ return _percent;
+ }
+ }
+
+ private static object GetObjFromOther(CompileResult obj, CompileResult other) {
+ if (obj.Result == null) {
+ if (other.DataType == DataType.String) {
+ return string.Empty;
+ }
+ return 0d;
+ }
+ return obj.ResultValue;
+ }
+
+ private static CompileResult Compare(
+ CompileResult l,
+ CompileResult r,
+ Func<int, bool> comparison) {
+ if (EitherIsError(l, r, out var errorVal)) {
+ return new(errorVal);
+ }
+ object left,
+ right;
+ left = GetObjFromOther(l, r);
+ right = GetObjFromOther(r, l);
+ if (ConvertUtil.IsNumeric(left) && ConvertUtil.IsNumeric(right)) {
+ var lnum = ConvertUtil.GetValueDouble(left);
+ var rnum = ConvertUtil.GetValueDouble(right);
+ if (Math.Abs(lnum - rnum) < double.Epsilon) {
+ return new(comparison(0), DataType.Boolean);
+ }
+ var comparisonResult = lnum.CompareTo(rnum);
+ return new(comparison(comparisonResult), DataType.Boolean);
+ } else {
+ var comparisonResult = CompareString(left, right);
+ return new(comparison(comparisonResult), DataType.Boolean);
+ }
+ }
+
+ private static int CompareString(object l, object r) {
+ var sl = (l ?? "").ToString();
+ var sr = (r ?? "").ToString();
+ return String.Compare(sl, sr, StringComparison.Ordinal);
+ }
+
+ private static bool EitherIsError(
+ CompileResult l,
+ CompileResult r,
+ out ExcelErrorValue errorVal) {
+ if (l.DataType == DataType.ExcelError) {
+ errorVal = (ExcelErrorValue)l.Result;
+ return true;
+ }
+ if (r.DataType == DataType.ExcelError) {
+ errorVal = (ExcelErrorValue)r.Result;
+ return true;
+ }
+ errorVal = null;
+ return false;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Operators/Operators.cs b/AppsheetEpplus/FormulaParsing/Excel/Operators/Operators.cs
new file mode 100644
index 0000000..cd26312
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Operators/Operators.cs
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public enum Operators {
+ Undefined,
+ Concat,
+ Plus,
+ Minus,
+ Multiply,
+ Divide,
+ Modulus,
+ Percent,
+ Equals,
+ GreaterThan,
+ GreaterThanOrEqual,
+ LessThan,
+ LessThanOrEqual,
+ NotEqualTo,
+ IntegerDivision,
+ Exponentiation,
+}
diff --git a/AppsheetEpplus/FormulaParsing/Excel/Operators/OperatorsDict.cs b/AppsheetEpplus/FormulaParsing/Excel/Operators/OperatorsDict.cs
new file mode 100644
index 0000000..9b063f6
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Excel/Operators/OperatorsDict.cs
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class OperatorsDict : Dictionary<string, IOperator> {
+ public OperatorsDict() {
+ Add("+", Operator.Plus);
+ Add("-", Operator.Minus);
+ Add("*", Operator.Multiply);
+ Add("/", Operator.Divide);
+ Add("^", Operator.Exp);
+ Add("=", Operator.Eq);
+ Add(">", Operator.GreaterThan);
+ Add(">=", Operator.GreaterThanOrEqual);
+ Add("<", Operator.LessThan);
+ Add("<=", Operator.LessThanOrEqual);
+ Add("<>", Operator.NotEqualsTo);
+ Add("&", Operator.Concat);
+ }
+
+ private static IDictionary<string, IOperator> _instance;
+
+ public static IDictionary<string, IOperator> Instance {
+ get {
+ if (_instance == null) {
+ _instance = new OperatorsDict();
+ }
+ return _instance;
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelCalculationOption.cs b/AppsheetEpplus/FormulaParsing/ExcelCalculationOption.cs
new file mode 100644
index 0000000..d6d94a7
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelCalculationOption.cs
@@ -0,0 +1,5 @@
+namespace AppsheetEpplus;
+
+public class ExcelCalculationOption {
+ public bool AllowCirculareReferences { get; set; } = false;
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelDataProvider.cs b/AppsheetEpplus/FormulaParsing/ExcelDataProvider.cs
new file mode 100644
index 0000000..1400caf
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelDataProvider.cs
@@ -0,0 +1,152 @@
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// This class should be implemented to be able to deliver excel data
+/// to the formula parser.
+/// </summary>
+public abstract class ExcelDataProvider {
+ /// <summary>
+ /// A range of cells in a worksheet.
+ /// </summary>
+ public interface IRangeInfo : IEnumerator<ICellInfo>, IEnumerable<ICellInfo> {
+ bool IsEmpty { get; }
+
+ bool IsMulti { get; }
+
+ int GetNCells();
+
+ ExcelAddressBase Address { get; }
+
+ object GetValue(int row, int col);
+
+ object GetOffset(int rowOffset, int colOffset);
+
+ ExcelWorksheet Worksheet { get; }
+ }
+
+ /// <summary>
+ /// Information and help methods about a cell
+ /// </summary>
+ public interface ICellInfo {
+ string Address { get; }
+
+ int Row { get; }
+
+ int Column { get; }
+
+ string Formula { get; }
+
+ object Value { get; }
+
+ double ValueDouble { get; }
+
+ double ValueDoubleLogical { get; }
+
+ bool IsHiddenRow { get; }
+
+ bool IsExcelError { get; }
+
+ IList<Token> Tokens { get; }
+ }
+
+ public interface INameInfo {
+ ulong Id { get; set; }
+
+ string Worksheet { get; set; }
+
+ string Name { get; set; }
+
+ string Formula { get; set; }
+
+ IList<Token> Tokens { get; }
+
+ object Value { get; set; }
+ }
+
+ /// <summary>
+ /// Returns the names of all worksheet names
+ /// </summary>
+ /// <returns></returns>
+ public abstract ExcelNamedRangeCollection GetWorksheetNames(string worksheet);
+
+ /// <summary>
+ /// Returns all defined names in a workbook
+ /// </summary>
+ /// <returns></returns>
+ public abstract ExcelNamedRangeCollection GetWorkbookNameValues();
+
+ /// <summary>
+ /// Returns values from the required range.
+ /// </summary>
+ /// <param name="worksheetName">The name of the worksheet</param>
+ /// <param name="row">Row</param>
+ /// <param name="column">Column</param>
+ /// <param name="address">The reference address</param>
+ /// <returns></returns>
+ public abstract IRangeInfo GetRange(string worksheetName, int row, int column, string address);
+
+ public abstract INameInfo GetName(string worksheet, string name);
+
+ public abstract IEnumerable<object> GetRangeValues(string address);
+
+ public abstract string GetRangeFormula(string worksheetName, int row, int column);
+
+ public abstract List<Token> GetRangeFormulaTokens(string worksheetName, int row, int column);
+
+ public abstract bool IsRowHidden(string worksheetName, int row);
+
+ ///// <summary>
+ ///// Returns a single cell value
+ ///// </summary>
+ ///// <param name="address"></param>
+ ///// <returns></returns>
+ //public abstract object GetCellValue(int sheetID, string address);
+
+ /// <summary>
+ /// Returns a single cell value
+ /// </summary>
+ /// <param name="sheetName"></param>
+ /// <param name="row"></param>
+ /// <param name="col"></param>
+ /// <returns></returns>
+ public abstract object GetCellValue(string sheetName, int row, int col);
+
+ ///// <summary>
+ ///// Sets the value on the cell
+ ///// </summary>
+ ///// <param name="address"></param>
+ ///// <param name="value"></param>
+ //public abstract void SetCellValue(string address, object value);
+
+ /// <summary>
+ /// Returns the address of the lowest rightmost cell on the worksheet.
+ /// </summary>
+ /// <param name="worksheet"></param>
+ /// <returns></returns>
+ public abstract ExcelCellAddress GetDimensionEnd(string worksheet);
+
+ /// <summary>
+ /// Max number of columns in a worksheet that the Excel data provider can handle.
+ /// </summary>
+ public abstract int ExcelMaxColumns { get; }
+
+ /// <summary>
+ /// Max number of rows in a worksheet that the Excel data provider can handle
+ /// </summary>
+ public abstract int ExcelMaxRows { get; }
+
+ public abstract object GetRangeValue(string worksheetName, int row, int column);
+
+ public abstract string GetFormat(object value, string format);
+
+ public abstract void Reset();
+
+ public abstract IRangeInfo GetRange(
+ string worksheet,
+ int fromRow,
+ int fromCol,
+ int toRow,
+ int toCol);
+}
diff --git a/EPPlus/FormulaParsing/ExcelDataProvider.cs.orig b/AppsheetEpplus/FormulaParsing/ExcelDataProvider.cs.orig
similarity index 100%
rename from EPPlus/FormulaParsing/ExcelDataProvider.cs.orig
rename to AppsheetEpplus/FormulaParsing/ExcelDataProvider.cs.orig
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/AddressTranslator.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/AddressTranslator.cs
new file mode 100644
index 0000000..70e548e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/AddressTranslator.cs
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Globalization;
+using System.Text.RegularExpressions;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Handles translations from Spreadsheet addresses to 0-based numeric index.
+/// </summary>
+public class AddressTranslator {
+ public enum RangeCalculationBehaviour {
+ FirstPart,
+ LastPart,
+ }
+
+ private readonly ExcelDataProvider _excelDataProvider;
+
+ public AddressTranslator(ExcelDataProvider excelDataProvider) {
+ Require.That(excelDataProvider).Named("excelDataProvider").IsNotNull();
+ _excelDataProvider = excelDataProvider;
+ }
+
+ /// <summary>
+ /// Translates an address in format "A1" to col- and rowindex.
+ ///
+ /// If the supplied address is a range, the address of the first part will be calculated.
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="col"></param>
+ /// <param name="row"></param>
+ public virtual void ToColAndRow(string address, out int col, out int row) {
+ ToColAndRow(address, out col, out row, RangeCalculationBehaviour.FirstPart);
+ }
+
+ /// <summary>
+ /// Translates an address in format "A1" to col- and rowindex.
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="col"></param>
+ /// <param name="row"></param>
+ /// <param name="behaviour"></param>
+ public virtual void ToColAndRow(
+ string address,
+ out int col,
+ out int row,
+ RangeCalculationBehaviour behaviour) {
+ address = address.ToUpper(CultureInfo.InvariantCulture);
+ var alphaPart = GetAlphaPart(address);
+ col = 0;
+ var nLettersInAlphabet = 26;
+ for (int x = 0; x < alphaPart.Length; x++) {
+ var pos = alphaPart.Length - x - 1;
+ var currentNumericValue = GetNumericAlphaValue(alphaPart[x]);
+ col += (nLettersInAlphabet * pos * currentNumericValue);
+ if (pos == 0) {
+ col += currentNumericValue;
+ }
+ }
+ //col--;
+ //row = GetIntPart(address) - 1 ?? GetRowIndexByBehaviour(behaviour);
+ row = GetIntPart(address) ?? GetRowIndexByBehaviour(behaviour);
+ }
+
+ private int GetRowIndexByBehaviour(RangeCalculationBehaviour behaviour) {
+ if (behaviour == RangeCalculationBehaviour.FirstPart) {
+ return 1;
+ }
+ return _excelDataProvider.ExcelMaxRows;
+ }
+
+ private int GetNumericAlphaValue(char c) {
+ return c - 64;
+ }
+
+ private string GetAlphaPart(string address) {
+ return Regex.Match(address, "[A-Z]+").Value;
+ }
+
+ private int? GetIntPart(string address) {
+ if (Regex.IsMatch(address, "[0-9]+")) {
+ return int.Parse(Regex.Match(address, "[0-9]+").Value);
+ }
+ return null;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/CellReferenceProvider.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/CellReferenceProvider.cs
new file mode 100644
index 0000000..071c43a
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/CellReferenceProvider.cs
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class CellReferenceProvider {
+ public virtual IEnumerable<string> GetReferencedAddresses(
+ string cellFormula,
+ ParsingContext context) {
+ var resultCells = new List<string>();
+ var r = context.Configuration.Lexer.Tokenize(
+ cellFormula,
+ context.Scopes.Current.Address.Worksheet);
+ var toAddresses = r.Where(x => x.TokenType == TokenType.ExcelAddress);
+ foreach (var toAddress in toAddresses) {
+ var rangeAddress = context.RangeAddressFactory.Create(toAddress.Value);
+ var rangeCells = new List<string>();
+ if (rangeAddress.FromRow < rangeAddress.ToRow || rangeAddress.FromCol < rangeAddress.ToCol) {
+ for (var col = rangeAddress.FromCol; col <= rangeAddress.ToCol; col++) {
+ for (var row = rangeAddress.FromRow; row <= rangeAddress.ToRow; row++) {
+ resultCells.Add(context.RangeAddressFactory.Create(col, row).Address);
+ }
+ }
+ } else {
+ rangeCells.Add(toAddress.Value);
+ }
+ resultCells.AddRange(rangeCells);
+ }
+ return resultCells;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/ExcelAddressInfo.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/ExcelAddressInfo.cs
new file mode 100644
index 0000000..e481f4c
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/ExcelAddressInfo.cs
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public class ExcelAddressInfo {
+ private ExcelAddressInfo(string address) {
+ var addressOnSheet = address;
+ if (address.Contains("!")) {
+ var worksheetArr = address.Split('!');
+ Worksheet = worksheetArr[0];
+ addressOnSheet = worksheetArr[1];
+ }
+ if (addressOnSheet.Contains(":")) {
+ var rangeArr = addressOnSheet.Split(':');
+ StartCell = rangeArr[0];
+ EndCell = rangeArr[1];
+ } else {
+ StartCell = addressOnSheet;
+ }
+ AddressOnSheet = addressOnSheet;
+ }
+
+ public static ExcelAddressInfo Parse(string address) {
+ Require.That(address).Named("address").IsNotNullOrEmpty();
+ return new(address);
+ }
+
+ public string Worksheet { get; private set; } = string.Empty;
+
+ public bool WorksheetIsSpecified => !string.IsNullOrEmpty(Worksheet);
+
+ public bool IsMultipleCells => !string.IsNullOrEmpty(EndCell);
+
+ public string StartCell { get; private set; }
+
+ public string EndCell { get; private set; }
+
+ public string AddressOnSheet { get; private set; }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/ExcelAddressUtil.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/ExcelAddressUtil.cs
new file mode 100644
index 0000000..6fd5fe6
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/ExcelAddressUtil.cs
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public static class ExcelAddressUtil {
+ private static readonly char[] SheetNameInvalidChars = ['?', ':', '*', '/', '\\'];
+
+ public static bool IsValidAddress(string token) {
+ int ix;
+ if (token[0] == '\'') {
+ ix = token.LastIndexOf('\'');
+ if (ix > 0 && ix < token.Length - 1 && token[ix + 1] == '!') {
+ if (token.IndexOfAny(SheetNameInvalidChars, 1, ix - 1) > 0) {
+ return false;
+ }
+ token = token.Substring(ix + 2);
+ } else {
+ return false;
+ }
+ } else if ((ix = token.IndexOf('!')) > 1) {
+ if (token.IndexOfAny(SheetNameInvalidChars, 0, token.IndexOf('!')) > 0) {
+ return false;
+ }
+ token = token.Substring(token.IndexOf('!') + 1);
+ }
+ return ExcelCellBase.IsValidAddress(token);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/ExcelReferenceType.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/ExcelReferenceType.cs
new file mode 100644
index 0000000..0b33171
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/ExcelReferenceType.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public enum ExcelReferenceType {
+ AbsoluteRowAndColumn = 1,
+ AbsoluteRowRelativeColumn = 2,
+ RelativeRowAbsolutColumn = 3,
+ RelativeRowAndColumn = 4,
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/ExpressionEvaluator.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/ExpressionEvaluator.cs
new file mode 100644
index 0000000..3377ef6
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/ExpressionEvaluator.cs
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+using System.Text.RegularExpressions;
+
+namespace AppsheetEpplus;
+
+public class ExpressionEvaluator {
+ private readonly WildCardValueMatcher _wildCardValueMatcher;
+ private readonly CompileResultFactory _compileResultFactory;
+
+ public ExpressionEvaluator()
+ : this(new(), new()) {}
+
+ public ExpressionEvaluator(
+ WildCardValueMatcher wildCardValueMatcher,
+ CompileResultFactory compileResultFactory) {
+ _wildCardValueMatcher = wildCardValueMatcher;
+ _compileResultFactory = compileResultFactory;
+ }
+
+ private string GetNonAlphanumericStartChars(string expression) {
+ if (!string.IsNullOrEmpty(expression)) {
+ if (Regex.IsMatch(expression, "^([^a-zA-Z0-9]{2})")) {
+ return expression.Substring(0, 2);
+ }
+ if (Regex.IsMatch(expression, "^([^a-zA-Z0-9]{1})")) {
+ return expression.Substring(0, 1);
+ }
+ }
+ return null;
+ }
+
+ private bool EvaluateOperator(object left, object right, IOperator op) {
+ var leftResult = _compileResultFactory.Create(left);
+ var rightResult = _compileResultFactory.Create(right);
+ var result = op.Apply(leftResult, rightResult);
+ if (result.DataType != DataType.Boolean) {
+ throw new ArgumentException("Illegal operator in expression");
+ }
+ return (bool)result.Result;
+ }
+
+ public bool TryConvertToDouble(object op, out double d) {
+ if (op is double || op is int) {
+ d = Convert.ToDouble(op);
+ return true;
+ }
+ if (op is DateTime time) {
+ d = time.ToOADate();
+ return true;
+ }
+ if (op != null) {
+ if (double.TryParse(op.ToString(), out d)) {
+ return true;
+ }
+ }
+ d = 0;
+ return false;
+ }
+
+ public bool Evaluate(object left, string expression) {
+ if (expression == string.Empty) {
+ return left == null;
+ }
+ var operatorCandidate = GetNonAlphanumericStartChars(expression);
+ if (!string.IsNullOrEmpty(operatorCandidate) && operatorCandidate != "-") {
+ if (OperatorsDict.Instance.TryGetValue(operatorCandidate, out var op)) {
+ var right = expression.Replace(operatorCandidate, string.Empty);
+ if (left == null && right == string.Empty) {
+ return op.Operator == Operators.Equals;
+ }
+ if (left == null ^ right == string.Empty) {
+ return op.Operator == Operators.NotEqualTo;
+ }
+ bool leftIsNumeric = TryConvertToDouble(left, out var leftNum);
+ bool rightIsNumeric = double.TryParse(right, out var rightNum);
+ bool rightIsDate = DateTime.TryParse(right, out var date);
+ if (leftIsNumeric && rightIsNumeric) {
+ return EvaluateOperator(leftNum, rightNum, op);
+ }
+ if (leftIsNumeric && rightIsDate) {
+ return EvaluateOperator(leftNum, date.ToOADate(), op);
+ }
+ if (leftIsNumeric != rightIsNumeric) {
+ return op.Operator == Operators.NotEqualTo;
+ }
+ return EvaluateOperator(left, right, op);
+ }
+ }
+ return _wildCardValueMatcher.IsMatch(expression, left) == 0;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/FormulaDependencies.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/FormulaDependencies.cs
new file mode 100644
index 0000000..1e41ab7
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/FormulaDependencies.cs
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class FormulaDependencies {
+ public FormulaDependencies()
+ : this(new()) {}
+
+ public FormulaDependencies(FormulaDependencyFactory formulaDependencyFactory) {
+ _formulaDependencyFactory = formulaDependencyFactory;
+ }
+
+ private readonly FormulaDependencyFactory _formulaDependencyFactory;
+ private readonly Dictionary<string, FormulaDependency> _dependencies = new();
+
+ public IEnumerable<KeyValuePair<string, FormulaDependency>> Dependencies => _dependencies;
+
+ public void AddFormulaScope(ParsingScope parsingScope) {
+ //var dependency = _formulaDependencyFactory.Create(parsingScope);
+ //var address = parsingScope.Address.ToString();
+ //if (!_dependencies.ContainsKey(address))
+ //{
+ // _dependencies.Add(address, dependency);
+ //}
+ //if (parsingScope.Parent != null)
+ //{
+ // var parentAddress = parsingScope.Parent.Address.ToString();
+ // if (_dependencies.ContainsKey(parentAddress))
+ // {
+ // var parent = _dependencies[parentAddress];
+ // parent.AddReferenceTo(parsingScope.Address);
+ // dependency.AddReferenceFrom(parent.Address);
+ // }
+ //}
+ }
+
+ public void Clear() {
+ _dependencies.Clear();
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/FormulaDependency.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/FormulaDependency.cs
new file mode 100644
index 0000000..8c5d9cc
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/FormulaDependency.cs
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class FormulaDependency {
+ public FormulaDependency(ParsingScope scope) {
+ ScopeId = scope.ScopeId;
+ Address = scope.Address;
+ }
+
+ public Guid ScopeId { get; private set; }
+
+ public RangeAddress Address { get; private set; }
+
+ private readonly List<RangeAddress> _referencedBy = new();
+
+ private readonly List<RangeAddress> _references = new();
+
+ public virtual void AddReferenceFrom(RangeAddress rangeAddress) {
+ if (Address.CollidesWith(rangeAddress)
+ || _references.Exists(x => x.CollidesWith(rangeAddress))) {
+ throw new CircularReferenceException("Circular reference detected at " + rangeAddress);
+ }
+ _referencedBy.Add(rangeAddress);
+ }
+
+ public virtual void AddReferenceTo(RangeAddress rangeAddress) {
+ if (Address.CollidesWith(rangeAddress)
+ || _referencedBy.Exists(x => x.CollidesWith(rangeAddress))) {
+ throw new CircularReferenceException("Circular reference detected at " + rangeAddress);
+ }
+ _references.Add(rangeAddress);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/FormulaDependencyFactory.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/FormulaDependencyFactory.cs
new file mode 100644
index 0000000..54bc1c5
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/FormulaDependencyFactory.cs
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class FormulaDependencyFactory {
+ public virtual FormulaDependency Create(ParsingScope scope) {
+ return new(scope);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/IndexToAddressTranslator.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/IndexToAddressTranslator.cs
new file mode 100644
index 0000000..5f702e9
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/IndexToAddressTranslator.cs
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public class IndexToAddressTranslator {
+ public IndexToAddressTranslator(ExcelDataProvider excelDataProvider)
+ : this(excelDataProvider, ExcelReferenceType.AbsoluteRowAndColumn) {}
+
+ public IndexToAddressTranslator(
+ ExcelDataProvider excelDataProvider,
+ ExcelReferenceType referenceType) {
+ Require.That(excelDataProvider).Named("excelDataProvider").IsNotNull();
+ _excelDataProvider = excelDataProvider;
+ _excelReferenceType = referenceType;
+ }
+
+ private readonly ExcelDataProvider _excelDataProvider;
+ private readonly ExcelReferenceType _excelReferenceType;
+
+ protected internal static string GetColumnLetter(int iColumnNumber, bool fixedCol) {
+ if (iColumnNumber < 1) {
+ //throw new Exception("Column number is out of range");
+ return "#REF!";
+ }
+
+ string sCol = "";
+ do {
+ sCol = ((char)('A' + ((iColumnNumber - 1) % 26))) + sCol;
+ iColumnNumber = (iColumnNumber - ((iColumnNumber - 1) % 26)) / 26;
+ } while (iColumnNumber > 0);
+ return fixedCol ? "$" + sCol : sCol;
+ }
+
+ public string ToAddress(int col, int row) {
+ var fixedCol =
+ _excelReferenceType == ExcelReferenceType.AbsoluteRowAndColumn
+ || _excelReferenceType == ExcelReferenceType.RelativeRowAbsolutColumn;
+ var colString = GetColumnLetter(col, fixedCol);
+ return colString + GetRowNumber(row);
+ }
+
+ private string GetRowNumber(int rowNo) {
+ var retVal = rowNo < (_excelDataProvider.ExcelMaxRows) ? rowNo.ToString() : string.Empty;
+ if (!string.IsNullOrEmpty(retVal)) {
+ switch (_excelReferenceType) {
+ case ExcelReferenceType.AbsoluteRowAndColumn:
+ case ExcelReferenceType.AbsoluteRowRelativeColumn:
+ return "$" + retVal;
+ default:
+ return retVal;
+ }
+ }
+ return retVal;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/LookupValueMatcher.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/LookupValueMatcher.cs
new file mode 100644
index 0000000..b2c8828
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/LookupValueMatcher.cs
@@ -0,0 +1,7 @@
+namespace AppsheetEpplus;
+
+public class LookupValueMatcher : ValueMatcher {
+ protected override int CompareObjectToString(object o1, string o2) {
+ return IncompatibleOperands;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/NumericExpressionEvaluator.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/NumericExpressionEvaluator.cs
new file mode 100644
index 0000000..2591948
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/NumericExpressionEvaluator.cs
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+using System.Text.RegularExpressions;
+
+namespace AppsheetEpplus;
+
+public class NumericExpressionEvaluator {
+ private readonly ValueMatcher _valueMatcher;
+ private readonly CompileResultFactory _compileResultFactory;
+
+ public NumericExpressionEvaluator()
+ : this(new(), new()) {}
+
+ public NumericExpressionEvaluator(
+ ValueMatcher valueMatcher,
+ CompileResultFactory compileResultFactory) {
+ _valueMatcher = valueMatcher;
+ _compileResultFactory = compileResultFactory;
+ }
+
+ private string GetNonNumericStartChars(string expression) {
+ if (!string.IsNullOrEmpty(expression)) {
+ if (Regex.IsMatch(expression, @"^([^\d]{2})")) {
+ return expression.Substring(0, 2);
+ }
+ if (Regex.IsMatch(expression, @"^([^\d]{1})")) {
+ return expression.Substring(0, 1);
+ }
+ }
+ return null;
+ }
+
+ public double? OperandAsDouble(object op) {
+ if (op is double || op is int) {
+ return Convert.ToDouble(op);
+ }
+ if (op != null) {
+ if (double.TryParse(op.ToString(), out var output)) {
+ return output;
+ }
+ }
+ return null;
+ }
+
+ public bool Evaluate(object left, string expression) {
+ var operatorCandidate = GetNonNumericStartChars(expression);
+ var leftNum = OperandAsDouble(left);
+ if (!string.IsNullOrEmpty(operatorCandidate) && leftNum != null) {
+ if (OperatorsDict.Instance.TryGetValue(operatorCandidate, out var op)) {
+ var numericCandidate = expression.Replace(operatorCandidate, string.Empty);
+ if (double.TryParse(numericCandidate, out var d)) {
+ var leftResult = _compileResultFactory.Create(leftNum);
+ var rightResult = _compileResultFactory.Create(d);
+ var result = op.Apply(leftResult, rightResult);
+ if (result.DataType != DataType.Boolean) {
+ throw new ArgumentException("Illegal operator in expression");
+ }
+ return (bool)result.Result;
+ }
+ }
+ }
+ return _valueMatcher.IsMatch(left, expression) == 0;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/RangeAddress.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/RangeAddress.cs
new file mode 100644
index 0000000..77e6e89
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/RangeAddress.cs
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class RangeAddress {
+ internal string Address { get; set; } = string.Empty;
+
+ public string Worksheet { get; internal set; }
+
+ public int FromCol { get; internal set; }
+
+ public int ToCol { get; internal set; }
+
+ public int FromRow { get; internal set; }
+
+ public int ToRow { get; internal set; }
+
+ public override string ToString() {
+ return Address;
+ }
+
+ private static readonly RangeAddress _empty = new();
+
+ public static RangeAddress Empty => _empty;
+
+ /// <summary>
+ /// Returns true if this range collides (full or partly) with the supplied range
+ /// </summary>
+ /// <param name="other">The range to check</param>
+ /// <returns></returns>
+ public bool CollidesWith(RangeAddress other) {
+ if (other.Worksheet != Worksheet) {
+ return false;
+ }
+ if (other.FromRow > ToRow
+ || other.FromCol > ToCol
+ || FromRow > other.ToRow
+ || FromCol > other.ToCol) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/RangeAddressFactory.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/RangeAddressFactory.cs
new file mode 100644
index 0000000..af9362e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/RangeAddressFactory.cs
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public class RangeAddressFactory {
+ private readonly ExcelDataProvider _excelDataProvider;
+ private readonly IndexToAddressTranslator _indexToAddressTranslator;
+
+ public RangeAddressFactory(ExcelDataProvider excelDataProvider)
+ : this(
+ excelDataProvider,
+ new(excelDataProvider),
+ new(excelDataProvider, ExcelReferenceType.RelativeRowAndColumn)) {}
+
+ public RangeAddressFactory(
+ ExcelDataProvider excelDataProvider,
+ AddressTranslator addressTranslator,
+ IndexToAddressTranslator indexToAddressTranslator) {
+ Require.That(excelDataProvider).Named("excelDataProvider").IsNotNull();
+ Require.That(addressTranslator).Named("addressTranslator").IsNotNull();
+ Require.That(indexToAddressTranslator).Named("indexToAddressTranslator").IsNotNull();
+ _excelDataProvider = excelDataProvider;
+ _indexToAddressTranslator = indexToAddressTranslator;
+ }
+
+ public RangeAddress Create(int col, int row) {
+ return Create(string.Empty, col, row);
+ }
+
+ public RangeAddress Create(string worksheetName, int col, int row) {
+ return new() {
+ Address = _indexToAddressTranslator.ToAddress(col, row),
+ Worksheet = worksheetName,
+ FromCol = col,
+ ToCol = col,
+ FromRow = row,
+ ToRow = row,
+ };
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="worksheetName">will be used if no worksheet name is specified in <paramref name="address"/></param>
+ /// <param name="address">address of a range</param>
+ /// <returns></returns>
+ public RangeAddress Create(string worksheetName, string address) {
+ Require.That(address).Named("range").IsNotNullOrEmpty();
+ //var addressInfo = ExcelAddressInfo.Parse(address);
+ var adr = new ExcelAddressBase(address);
+ var sheet = string.IsNullOrEmpty(adr.WorkSheet) ? worksheetName : adr.WorkSheet;
+ var dim = _excelDataProvider.GetDimensionEnd(adr.WorkSheet);
+ var rangeAddress = new RangeAddress {
+ Address = adr.Address,
+ Worksheet = sheet,
+ FromRow = adr._fromRow,
+ FromCol = adr._fromCol,
+ ToRow = (dim != null && adr._toRow > dim.Row) ? dim.Row : adr._toRow,
+ ToCol = adr._toCol,
+ };
+ return rangeAddress;
+ }
+
+ public RangeAddress Create(string range) {
+ Require.That(range).Named("range").IsNotNullOrEmpty();
+ //var addressInfo = ExcelAddressInfo.Parse(range);
+ var adr = new ExcelAddressBase(range);
+ var rangeAddress = new RangeAddress {
+ Address = adr.Address,
+ Worksheet = adr.WorkSheet ?? "",
+ FromRow = adr._fromRow,
+ FromCol = adr._fromCol,
+ ToRow = adr._toRow,
+ ToCol = adr._toCol,
+ };
+ return rangeAddress;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/ValueMatcher.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/ValueMatcher.cs
new file mode 100644
index 0000000..f9b6063
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/ValueMatcher.cs
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+public class ValueMatcher {
+ public const int IncompatibleOperands = -2;
+
+ public virtual int IsMatch(object o1, object o2) {
+ if (o1 != null && o2 == null) {
+ return 1;
+ }
+ if (o1 == null && o2 != null) {
+ return -1;
+ }
+ if (o1 == null && o2 == null) {
+ return 0;
+ }
+ //Handle ranges and defined names
+ o1 = CheckGetRange(o1);
+ o2 = CheckGetRange(o2);
+
+ if (o1 is string && o2 is string) {
+ return CompareStringToString(o1.ToString().ToLower(), o2.ToString().ToLower());
+ }
+ if (o1.GetType() == typeof(string)) {
+ return CompareStringToObject(o1.ToString(), o2);
+ }
+ if (o2.GetType() == typeof(string)) {
+ return CompareObjectToString(o1, o2.ToString());
+ }
+ return Convert.ToDouble(o1).CompareTo(Convert.ToDouble(o2));
+ }
+
+ private static object CheckGetRange(object v) {
+ if (v is ExcelDataProvider.IRangeInfo info) {
+ if (info.GetNCells() > 1) {
+ v = ExcelErrorValue.Create(eErrorType.Na);
+ }
+ v = info.GetOffset(0, 0);
+ } else if (v is ExcelDataProvider.INameInfo nameInfo) {
+ v = CheckGetRange(nameInfo);
+ }
+ return v;
+ }
+
+ protected virtual int CompareStringToString(string s1, string s2) {
+ return s1.CompareTo(s2);
+ }
+
+ protected virtual int CompareStringToObject(string o1, object o2) {
+ if (double.TryParse(o1, out var d1)) {
+ return d1.CompareTo(Convert.ToDouble(o2));
+ }
+ return IncompatibleOperands;
+ }
+
+ protected virtual int CompareObjectToString(object o1, string o2) {
+ if (double.TryParse(o2, out var d2)) {
+ return Convert.ToDouble(o1).CompareTo(d2);
+ }
+ return IncompatibleOperands;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelUtilities/WildCardValueMatcher.cs b/AppsheetEpplus/FormulaParsing/ExcelUtilities/WildCardValueMatcher.cs
new file mode 100644
index 0000000..fce2374
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelUtilities/WildCardValueMatcher.cs
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Text.RegularExpressions;
+
+namespace AppsheetEpplus;
+
+public class WildCardValueMatcher : ValueMatcher {
+ protected override int CompareStringToString(string s1, string s2) {
+ if (s1.Contains("*") || s1.Contains("?")) {
+ var regexPattern = Regex.Escape(s1);
+ regexPattern = string.Format("^{0}$", regexPattern);
+ regexPattern = regexPattern.Replace(@"\*", ".*");
+ regexPattern = regexPattern.Replace(@"\?", ".");
+ if (Regex.IsMatch(s2, regexPattern)) {
+ return 0;
+ }
+ }
+ return base.CompareStringToString(s1, s2);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExcelValues.cs b/AppsheetEpplus/FormulaParsing/ExcelValues.cs
new file mode 100644
index 0000000..248068e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExcelValues.cs
@@ -0,0 +1,206 @@
+using System;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Represents the errortypes in excel
+/// </summary>
+public enum eErrorType {
+ /// <summary>
+ /// Division by zero
+ /// </summary>
+ Div0,
+
+ /// <summary>
+ /// Not applicable
+ /// </summary>
+ Na,
+
+ /// <summary>
+ /// Name error
+ /// </summary>
+ Name,
+
+ /// <summary>
+ /// Null error
+ /// </summary>
+ Null,
+
+ /// <summary>
+ /// Num error
+ /// </summary>
+ Num,
+
+ /// <summary>
+ /// Reference error
+ /// </summary>
+ Ref,
+
+ /// <summary>
+ /// Value error
+ /// </summary>
+ Value,
+
+ // Bug G0004
+ /// <summary>
+ /// Error error // Google Bug G0004
+ /// </summary>
+ Error,
+
+ // Bug G0005
+ /// <summary>
+ /// ErrorValueIsNullOrEmpty error // Google Bug G0005
+ /// </summary>
+ ErrorValueIsNullOrEmpty,
+}
+
+/// <summary>
+/// Represents an Excel error.
+/// </summary>
+/// <seealso cref="eErrorType"/>
+public class ExcelErrorValue {
+ /// <summary>
+ /// Handles the convertion between <see cref="eErrorType"/> and the string values
+ /// used by Excel.
+ /// </summary>
+ public static class Values {
+ public const string Div0 = "#DIV/0!";
+ public const string Na = "#N/A";
+ public const string Name = "#NAME?";
+ public const string Null = "#NULL!";
+ public const string Num = "#NUM!";
+ public const string Ref = "#REF!";
+ public const string Value = "#VALUE!";
+ public const string Error = "#ERROR!"; // Bug G0004
+ public const string ErrorValueIsNullOrEmpty = "#ERRORVALUEISNULLOREMPTY!"; // Bug G0005
+
+ private static readonly Dictionary<string, eErrorType> _values = new() {
+ { Div0, eErrorType.Div0 },
+ { Na, eErrorType.Na },
+ { Name, eErrorType.Name },
+ { Null, eErrorType.Null },
+ { Num, eErrorType.Num },
+ { Ref, eErrorType.Ref },
+ { Value, eErrorType.Value },
+ { Error, eErrorType.Error }, // Bug G0004
+ {
+ ErrorValueIsNullOrEmpty,
+ eErrorType.ErrorValueIsNullOrEmpty
+ } // Bug G0005
+ ,
+ };
+
+ /// <summary>
+ /// Returns true if the supplied <paramref name="candidate"/> is an excel error.
+ /// </summary>
+ /// <param name="candidate"></param>
+ /// <returns></returns>
+ public static bool IsErrorValue(object candidate) {
+ if (candidate == null || !(candidate is ExcelErrorValue)) {
+ return false;
+ }
+ var candidateString = candidate.ToString();
+ return (!string.IsNullOrEmpty(candidateString) && _values.ContainsKey(candidateString));
+ }
+
+ /// <summary>
+ /// Returns true if the supplied <paramref name="candidate"/> is an excel error.
+ /// </summary>
+ /// <param name="candidate"></param>
+ /// <returns></returns>
+ public static bool StringIsErrorValue(string candidate) {
+ return (!string.IsNullOrEmpty(candidate) && _values.ContainsKey(candidate));
+ }
+
+ /// <summary>
+ /// Converts a string to an <see cref="eErrorType"/>
+ /// </summary>
+ /// <param name="val"></param>
+ /// <returns></returns>
+ /// <exception cref="ArgumentException">Thrown if the supplied value is not an Excel error</exception>
+ public static eErrorType ToErrorType(string val) {
+ if (string.IsNullOrEmpty(val) || !_values.ContainsKey(val)) {
+ throw new ArgumentException("Invalid error code " + (val ?? "<empty>"));
+ }
+ return _values[val];
+ }
+ }
+
+ internal static ExcelErrorValue Create(eErrorType errorType) {
+ return new(errorType);
+ }
+
+ internal static ExcelErrorValue Parse(string val) {
+ if (string.IsNullOrEmpty(
+ val)) // Google Bug G0005
+ {
+ val = Values.ErrorValueIsNullOrEmpty;
+ }
+
+ if (Values.StringIsErrorValue(val)) {
+ return new(Values.ToErrorType(val));
+ }
+ if (string.IsNullOrEmpty(val)) {
+ throw new ArgumentNullException("val");
+ }
+ throw new ArgumentException("Not a valid error value: " + val);
+ }
+
+ private ExcelErrorValue(eErrorType type) {
+ Type = type;
+ }
+
+ /// <summary>
+ /// The error type
+ /// </summary>
+ public eErrorType Type { get; private set; }
+
+ /// <summary>
+ /// Returns the string representation of the error type
+ /// </summary>
+ /// <returns></returns>
+ public override string ToString() {
+ switch (Type) {
+ case eErrorType.Div0:
+ return Values.Div0;
+ case eErrorType.Na:
+ return Values.Na;
+ case eErrorType.Name:
+ return Values.Name;
+ case eErrorType.Null:
+ return Values.Null;
+ case eErrorType.Num:
+ return Values.Num;
+ case eErrorType.Ref:
+ return Values.Ref;
+ case eErrorType.Value:
+ return Values.Value;
+ case eErrorType.Error: // Bug G0004
+ return Values.Error;
+ case eErrorType.ErrorValueIsNullOrEmpty: // Bug G0005
+ return Values.ErrorValueIsNullOrEmpty;
+ default:
+ throw (new ArgumentException("Invalid errortype"));
+ }
+ }
+
+ public static ExcelErrorValue operator +(object v1, ExcelErrorValue v2) {
+ return v2;
+ }
+
+ public static ExcelErrorValue operator +(ExcelErrorValue v1, ExcelErrorValue v2) {
+ return v1;
+ }
+
+ public override int GetHashCode() {
+ return base.GetHashCode();
+ }
+
+ public override bool Equals(object obj) {
+ if (!(obj is ExcelErrorValue value)) {
+ return false;
+ }
+ return value.ToString() == ToString();
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Exceptions/CircularReferenceException.cs b/AppsheetEpplus/FormulaParsing/Exceptions/CircularReferenceException.cs
new file mode 100644
index 0000000..47b68f0
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Exceptions/CircularReferenceException.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+public class CircularReferenceException : Exception {
+ public CircularReferenceException(string message)
+ : base(message) {}
+}
diff --git a/AppsheetEpplus/FormulaParsing/Exceptions/ExcelErrorCodes.cs b/AppsheetEpplus/FormulaParsing/Exceptions/ExcelErrorCodes.cs
new file mode 100644
index 0000000..d045649
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Exceptions/ExcelErrorCodes.cs
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class ExcelErrorCodes {
+ private ExcelErrorCodes(string code) {
+ Code = code;
+ }
+
+ public string Code { get; private set; }
+
+ public override int GetHashCode() {
+ return Code.GetHashCode();
+ }
+
+ public override bool Equals(object obj) {
+ if (obj is ExcelErrorCodes codes) {
+ return codes.Code.Equals(Code);
+ }
+ return false;
+ }
+
+ public static bool operator ==(ExcelErrorCodes c1, ExcelErrorCodes c2) {
+ return c1.Code.Equals(c2.Code);
+ }
+
+ public static bool operator !=(ExcelErrorCodes c1, ExcelErrorCodes c2) {
+ return !c1.Code.Equals(c2.Code);
+ }
+
+ private static readonly IEnumerable<string> Codes = new List<string> {
+ Value.Code,
+ Name.Code,
+ NoValueAvaliable.Code,
+ };
+
+ public static bool IsErrorCode(object valueToTest) {
+ if (valueToTest == null) {
+ return false;
+ }
+ var candidate = valueToTest.ToString();
+ if (Codes.FirstOrDefault(x => x == candidate) != null) {
+ return true;
+ }
+ return false;
+ }
+
+ public static ExcelErrorCodes Value => new("#VALUE!");
+
+ public static ExcelErrorCodes Name => new("#NAME?");
+
+ public static ExcelErrorCodes NoValueAvaliable => new("#N/A");
+}
diff --git a/AppsheetEpplus/FormulaParsing/Exceptions/ExcelErrorValueException.cs b/AppsheetEpplus/FormulaParsing/Exceptions/ExcelErrorValueException.cs
new file mode 100644
index 0000000..335680d
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Exceptions/ExcelErrorValueException.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// This Exception represents an Excel error. When this exception is thrown
+/// from an Excel function, the ErrorValue code will be set as the value of the
+/// parsed cell.
+/// </summary>
+/// <seealso cref="ExcelErrorValue"/>
+public class ExcelErrorValueException : Exception {
+ public ExcelErrorValueException(ExcelErrorValue error)
+ : this(error.ToString(), error) {}
+
+ public ExcelErrorValueException(string message, ExcelErrorValue error)
+ : base(message) {
+ ErrorValue = error;
+ }
+
+ public ExcelErrorValueException(eErrorType errorType)
+ : this(ExcelErrorValue.Create(errorType)) {}
+
+ /// <summary>
+ /// The error value
+ /// </summary>
+ public ExcelErrorValue ErrorValue { get; private set; }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Exceptions/UnrecognizedTokenException.cs b/AppsheetEpplus/FormulaParsing/Exceptions/UnrecognizedTokenException.cs
new file mode 100644
index 0000000..0bc07dd
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Exceptions/UnrecognizedTokenException.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+public class UnrecognizedTokenException : Exception {
+ public UnrecognizedTokenException(Token token)
+ : base("Unrecognized token: " + token.Value) {}
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/AtomicExpression.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/AtomicExpression.cs
new file mode 100644
index 0000000..d3c3cb6
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/AtomicExpression.cs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public abstract class AtomicExpression : Expression {
+ public AtomicExpression(string expression)
+ : base(expression) {}
+
+ public override bool IsGroupedExpression => false;
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/BooleanExpression.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/BooleanExpression.cs
new file mode 100644
index 0000000..0e85b26
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/BooleanExpression.cs
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class BooleanExpression : AtomicExpression {
+ private readonly bool? _precompiledValue;
+
+ public BooleanExpression(string expression)
+ : base(expression) {}
+
+ public BooleanExpression(bool value)
+ : base(value ? "true" : "false") {
+ _precompiledValue = value;
+ }
+
+ public override CompileResult Compile() {
+ var result = _precompiledValue ?? bool.Parse(ExpressionString);
+ return new(result, DataType.Boolean);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileResult.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileResult.cs
new file mode 100644
index 0000000..3546544
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileResult.cs
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+using System.Globalization;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class CompileResult {
+ private static readonly CompileResult _empty = new(null, DataType.Empty);
+
+ public static CompileResult Empty => _empty;
+
+ public CompileResult(object result, DataType dataType) {
+ Result = result;
+ DataType = dataType;
+ }
+
+ public CompileResult(eErrorType errorType) {
+ Result = ExcelErrorValue.Create(errorType);
+ DataType = DataType.ExcelError;
+ }
+
+ public CompileResult(ExcelErrorValue errorValue) {
+ ArgumentNullException.ThrowIfNull(errorValue);
+ Result = errorValue;
+ DataType = DataType.ExcelError;
+ }
+
+ public object Result { get; private set; }
+
+ public object ResultValue {
+ get {
+ var r = Result as ExcelDataProvider.IRangeInfo;
+ if (r == null) {
+ return Result;
+ }
+ return r.GetValue(r.Address._fromRow, r.Address._fromCol);
+ }
+ }
+
+ public double ResultNumeric {
+ get {
+ if (IsNumeric) {
+ return Result == null ? 0 : Convert.ToDouble(Result);
+ }
+ if (Result is DateTime time) {
+ return time.ToOADate();
+ }
+ if (Result is TimeSpan span) {
+ return new DateTime(span.Ticks).ToOADate();
+ }
+ if (IsNumericString) {
+ try {
+ return double.Parse(Result.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture);
+ } catch (Exception) {
+ return 0;
+ }
+ }
+ if (Result is ExcelDataProvider.IRangeInfo info) {
+ var c = info.FirstOrDefault();
+ if (c == null) {
+ return 0;
+ }
+ return c.ValueDoubleLogical;
+ }
+ return 0;
+ }
+ }
+
+ public DataType DataType { get; private set; }
+
+ public bool IsNumeric =>
+ DataType == DataType.Decimal
+ || DataType == DataType.Integer
+ || DataType == DataType.Empty
+ || DataType == DataType.Boolean
+ || DataType == DataType.Date;
+
+ public bool IsNumericString => DataType == DataType.String && ConvertUtil.IsNumericString(Result);
+
+ public bool IsResultOfSubtotal { get; set; }
+
+ public bool IsHiddenCell { get; set; }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileResultFactory.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileResultFactory.cs
new file mode 100644
index 0000000..724e72e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileResultFactory.cs
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+public class CompileResultFactory {
+ public virtual CompileResult Create(object obj) {
+ if ((obj is ExcelDataProvider.INameInfo info)) {
+ obj = info.Value;
+ }
+ if (obj is ExcelDataProvider.IRangeInfo rangeInfo) {
+ obj = rangeInfo.GetOffset(0, 0);
+ }
+ if (obj == null) {
+ return new(null, DataType.Empty);
+ }
+ if (obj.GetType().Equals(typeof(string))) {
+ return new(obj, DataType.String);
+ }
+ if (obj.GetType().Equals(typeof(double)) || obj is decimal) {
+ return new(obj, DataType.Decimal);
+ }
+ if (obj.GetType().Equals(typeof(int)) || obj is long || obj is short) {
+ return new(obj, DataType.Integer);
+ }
+ if (obj.GetType().Equals(typeof(bool))) {
+ return new(obj, DataType.Boolean);
+ }
+ if (obj.GetType().Equals(typeof(ExcelErrorValue))) {
+ return new(obj, DataType.ExcelError);
+ }
+ if (obj.GetType().Equals(typeof(DateTime))) {
+ return new(((DateTime)obj).ToOADate(), DataType.Date);
+ }
+ throw new ArgumentException("Non supported type " + obj.GetType().FullName);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategy.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategy.cs
new file mode 100644
index 0000000..8abf262
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategy.cs
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public abstract class CompileStrategy {
+ protected readonly Expression _expression;
+
+ public CompileStrategy(Expression expression) {
+ _expression = expression;
+ }
+
+ public abstract Expression Compile();
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategyFactory.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategyFactory.cs
new file mode 100644
index 0000000..cb7e10c
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategyFactory.cs
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public class CompileStrategyFactory : ICompileStrategyFactory {
+ public CompileStrategy Create(Expression expression) {
+ if (expression.Operator.Operator == Operators.Concat) {
+ return new StringConcatStrategy(expression);
+ }
+ return new DefaultCompileStrategy(expression);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileStrategy/DefaultCompileStrategy.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileStrategy/DefaultCompileStrategy.cs
new file mode 100644
index 0000000..52e2726
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileStrategy/DefaultCompileStrategy.cs
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class DefaultCompileStrategy : CompileStrategy {
+ public DefaultCompileStrategy(Expression expression)
+ : base(expression) {}
+
+ public override Expression Compile() {
+ return _expression.MergeWithNext();
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileStrategy/ICompileStrategyFactory.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileStrategy/ICompileStrategyFactory.cs
new file mode 100644
index 0000000..b89e794
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileStrategy/ICompileStrategyFactory.cs
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public interface ICompileStrategyFactory {
+ CompileStrategy Create(Expression expression);
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileStrategy/StringConcatStrategy.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileStrategy/StringConcatStrategy.cs
new file mode 100644
index 0000000..53422ce
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/CompileStrategy/StringConcatStrategy.cs
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class StringConcatStrategy : CompileStrategy {
+ public StringConcatStrategy(Expression expression)
+ : base(expression) {}
+
+ public override Expression Compile() {
+ var newExp =
+ _expression is ExcelAddressExpression
+ ? _expression
+ : ExpressionConverter.Instance.ToStringExpression(_expression);
+ newExp.Prev = _expression.Prev;
+ newExp.Next = _expression.Next;
+ if (_expression.Prev != null) {
+ _expression.Prev.Next = newExp;
+ }
+ if (_expression.Next != null) {
+ _expression.Next.Prev = newExp;
+ }
+ return newExp.MergeWithNext();
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/ConstantExpressions.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ConstantExpressions.cs
new file mode 100644
index 0000000..cb86b67
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ConstantExpressions.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace AppsheetEpplus;
+
+public static class ConstantExpressions {
+ public static Expression Percent {
+ get { return new ConstantExpression("Percent", () => new(0.01, DataType.Decimal)); }
+ }
+}
+
+public class ConstantExpression : AtomicExpression {
+ private readonly Func<CompileResult> _factoryMethod;
+
+ public ConstantExpression(string title, Func<CompileResult> factoryMethod)
+ : base(title) {
+ _factoryMethod = factoryMethod;
+ }
+
+ public override CompileResult Compile() {
+ return _factoryMethod();
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/DataType.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/DataType.cs
new file mode 100644
index 0000000..30302d2
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/DataType.cs
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public enum DataType {
+ Integer,
+ Decimal,
+ String,
+ Boolean,
+ Date,
+ Time,
+ Enumerable,
+ LookupArray,
+ ExcelAddress,
+ ExcelError,
+ Empty,
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/DateExpression.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/DateExpression.cs
new file mode 100644
index 0000000..c5a0bb8
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/DateExpression.cs
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+using System.Globalization;
+
+namespace AppsheetEpplus;
+
+public class DateExpression : AtomicExpression {
+ public DateExpression(string expression)
+ : base(expression) {}
+
+ public override CompileResult Compile() {
+ var date = double.Parse(ExpressionString, CultureInfo.InvariantCulture);
+ return new(DateTime.FromOADate(date), DataType.Date);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/DecimalExpression.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/DecimalExpression.cs
new file mode 100644
index 0000000..8bcd36c
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/DecimalExpression.cs
@@ -0,0 +1,60 @@
+using System.Globalization;
+
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class DecimalExpression : AtomicExpression {
+ private readonly double? _compiledValue;
+ private readonly bool _negate;
+
+ public DecimalExpression(string expression)
+ : this(expression, false) {}
+
+ public DecimalExpression(string expression, bool negate)
+ : base(expression) {
+ _negate = negate;
+ }
+
+ public DecimalExpression(double compiledValue)
+ : base(compiledValue.ToString(CultureInfo.InvariantCulture)) {
+ _compiledValue = compiledValue;
+ }
+
+ public override CompileResult Compile() {
+ double result = _compiledValue ?? double.Parse(ExpressionString, CultureInfo.InvariantCulture);
+ result = _negate ? result * -1 : result;
+ return new(result, DataType.Decimal);
+ }
+
+ public bool IsNegated => _negate;
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/EnumerableExpression.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/EnumerableExpression.cs
new file mode 100644
index 0000000..654e95b
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/EnumerableExpression.cs
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class EnumerableExpression : Expression {
+ public EnumerableExpression()
+ : this(new ExpressionCompiler()) {}
+
+ public EnumerableExpression(IExpressionCompiler expressionCompiler) {
+ _expressionCompiler = expressionCompiler;
+ }
+
+ private readonly IExpressionCompiler _expressionCompiler;
+
+ public override bool IsGroupedExpression => false;
+
+ public override Expression PrepareForNextChild() {
+ return this;
+ }
+
+ public override CompileResult Compile() {
+ var result = new List<object>();
+ foreach (var childExpression in Children) {
+ result.Add(_expressionCompiler.Compile(new List<Expression> { childExpression }).Result);
+ }
+ return new(result, DataType.Enumerable);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExcelAddressExpression.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExcelAddressExpression.cs
new file mode 100644
index 0000000..825040d
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExcelAddressExpression.cs
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class ExcelAddressExpression : AtomicExpression {
+ private readonly ExcelDataProvider _excelDataProvider;
+ private readonly ParsingContext _parsingContext;
+ private readonly RangeAddressFactory _rangeAddressFactory;
+ private readonly bool _negate;
+
+ public ExcelAddressExpression(
+ string expression,
+ ExcelDataProvider excelDataProvider,
+ ParsingContext parsingContext)
+ : this(expression, excelDataProvider, parsingContext, new(excelDataProvider), false) {}
+
+ public ExcelAddressExpression(
+ string expression,
+ ExcelDataProvider excelDataProvider,
+ ParsingContext parsingContext,
+ bool negate)
+ : this(expression, excelDataProvider, parsingContext, new(excelDataProvider), negate) {}
+
+ public ExcelAddressExpression(
+ string expression,
+ ExcelDataProvider excelDataProvider,
+ ParsingContext parsingContext,
+ RangeAddressFactory rangeAddressFactory,
+ bool negate)
+ : base(expression) {
+ Require.That(excelDataProvider).Named("excelDataProvider").IsNotNull();
+ Require.That(parsingContext).Named("parsingContext").IsNotNull();
+ Require.That(rangeAddressFactory).Named("rangeAddressFactory").IsNotNull();
+ _excelDataProvider = excelDataProvider;
+ _parsingContext = parsingContext;
+ _rangeAddressFactory = rangeAddressFactory;
+ _negate = negate;
+ }
+
+ public override bool IsGroupedExpression => false;
+
+ public override CompileResult Compile() {
+ if (ParentIsLookupFunction) {
+ return new(ExpressionString, DataType.ExcelAddress);
+ }
+ return CompileRangeValues();
+ }
+
+ private CompileResult CompileRangeValues() {
+ var c = _parsingContext.Scopes.Current;
+ var result = _excelDataProvider.GetRange(
+ c.Address.Worksheet,
+ c.Address.FromRow,
+ c.Address.FromCol,
+ ExpressionString);
+
+ if (result == null || result.IsEmpty) {
+ return CompileResult.Empty;
+ }
+ if (result.Address.Rows > 1 || result.Address.Columns > 1) {
+ return new(result, DataType.Enumerable);
+ }
+ return CompileSingleCell(result);
+ }
+
+ private CompileResult CompileSingleCell(ExcelDataProvider.IRangeInfo result) {
+ var cell = result.First();
+ var factory = new CompileResultFactory();
+ var compileResult = factory.Create(cell.Value);
+ if (_negate && compileResult.IsNumeric) {
+ compileResult = new(compileResult.ResultNumeric * -1, compileResult.DataType);
+ }
+ compileResult.IsHiddenCell = cell.IsHiddenRow;
+ return compileResult;
+ }
+
+ public bool IsNegated => _negate;
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExcelErrorExpression.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExcelErrorExpression.cs
new file mode 100644
index 0000000..ce530ee
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExcelErrorExpression.cs
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class ExcelErrorExpression : Expression {
+ private readonly ExcelErrorValue _error;
+
+ public ExcelErrorExpression(string expression, ExcelErrorValue error)
+ : base(expression) {
+ _error = error;
+ }
+
+ public ExcelErrorExpression(ExcelErrorValue error)
+ : this(error.ToString(), error) {}
+
+ public override bool IsGroupedExpression => false;
+
+ public override CompileResult Compile() {
+ return new(_error, DataType.ExcelError);
+ //if (ParentIsLookupFunction)
+ //{
+ // return new CompileResult(ExpressionString, DataType.ExcelError);
+ //}
+ //else
+ //{
+ // return CompileRangeValues();
+ //}
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/Expression.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/Expression.cs
new file mode 100644
index 0000000..791b074
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/Expression.cs
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public abstract class Expression {
+ public string ExpressionString { get; private set; }
+
+ private readonly List<Expression> _children = new();
+
+ public IEnumerable<Expression> Children => _children;
+
+ public Expression Next { get; set; }
+
+ public Expression Prev { get; set; }
+
+ public IOperator Operator { get; set; }
+
+ public abstract bool IsGroupedExpression { get; }
+
+ public Expression() {}
+
+ public Expression(string expression) {
+ ExpressionString = expression;
+ Operator = null;
+ }
+
+ public virtual bool ParentIsLookupFunction { get; set; }
+
+ public virtual bool HasChildren => _children.Any();
+
+ public virtual Expression PrepareForNextChild() {
+ return this;
+ }
+
+ public virtual Expression AddChild(Expression child) {
+ if (_children.Any()) {
+ var last = _children.Last();
+ child.Prev = last;
+ last.Next = child;
+ }
+ _children.Add(child);
+ return child;
+ }
+
+ public virtual Expression MergeWithNext() {
+ Expression expression;
+ if (Next != null && Operator != null) {
+ var result = Operator.Apply(Compile(), Next.Compile());
+ expression = ExpressionConverter.Instance.FromCompileResult(result);
+ if (expression is ExcelErrorExpression) {
+ expression.Next = null;
+ expression.Prev = null;
+ return expression;
+ }
+ if (Next != null) {
+ expression.Operator = Next.Operator;
+ } else {
+ expression.Operator = null;
+ }
+ expression.Next = Next.Next;
+ if (expression.Next != null) {
+ expression.Next.Prev = expression;
+ }
+ expression.Prev = Prev;
+ } else {
+ throw (new FormatException("Invalid formula syntax. Operator missing expression."));
+ }
+ if (Prev != null) {
+ Prev.Next = expression;
+ }
+ return expression;
+ }
+
+ public abstract CompileResult Compile();
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExpressionCompiler.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExpressionCompiler.cs
new file mode 100644
index 0000000..33e0d52
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExpressionCompiler.cs
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class ExpressionCompiler : IExpressionCompiler {
+ private IEnumerable<Expression> _expressions;
+ private readonly IExpressionConverter _expressionConverter;
+ private readonly ICompileStrategyFactory _compileStrategyFactory;
+
+ public ExpressionCompiler()
+ : this(new ExpressionConverter(), new CompileStrategyFactory()) {}
+
+ public ExpressionCompiler(
+ IExpressionConverter expressionConverter,
+ ICompileStrategyFactory compileStrategyFactory) {
+ _expressionConverter = expressionConverter;
+ _compileStrategyFactory = compileStrategyFactory;
+ }
+
+ public CompileResult Compile(IEnumerable<Expression> expressions) {
+ _expressions = expressions;
+ return PerformCompilation();
+ }
+
+ public CompileResult Compile(
+ string worksheet,
+ int row,
+ int column,
+ IEnumerable<Expression> expressions) {
+ _expressions = expressions;
+ return PerformCompilation(worksheet, row, column);
+ }
+
+ private CompileResult PerformCompilation(string worksheet = "", int row = -1, int column = -1) {
+ var compiledExpressions = HandleGroupedExpressions();
+ while (compiledExpressions.Any(x => x.Operator != null)) {
+ var prec = FindLowestPrecedence();
+ compiledExpressions = HandlePrecedenceLevel(prec);
+ }
+ if (_expressions.Any()) {
+ return compiledExpressions.First().Compile();
+ }
+ return CompileResult.Empty;
+ }
+
+ private IEnumerable<Expression> HandleGroupedExpressions() {
+ if (!_expressions.Any()) {
+ return [];
+ }
+ var first = _expressions.First();
+ var groupedExpressions = _expressions.Where(x => x.IsGroupedExpression);
+ foreach (var groupedExpression in groupedExpressions) {
+ var result = groupedExpression.Compile();
+ if (result == CompileResult.Empty) {
+ continue;
+ }
+ var newExp = _expressionConverter.FromCompileResult(result);
+ newExp.Operator = groupedExpression.Operator;
+ newExp.Prev = groupedExpression.Prev;
+ newExp.Next = groupedExpression.Next;
+ if (groupedExpression.Prev != null) {
+ groupedExpression.Prev.Next = newExp;
+ }
+ if (groupedExpression.Next != null) {
+ groupedExpression.Next.Prev = newExp;
+ }
+ if (groupedExpression == first) {
+ first = newExp;
+ }
+ }
+ return RefreshList(first);
+ }
+
+ private IEnumerable<Expression> HandlePrecedenceLevel(int precedence) {
+ var first = _expressions.First();
+ var expressionsToHandle = _expressions.Where(x =>
+ x.Operator != null && x.Operator.Precedence == precedence);
+ var last = expressionsToHandle.Last();
+ var expression = expressionsToHandle.First();
+ do {
+ var strategy = _compileStrategyFactory.Create(expression);
+ var compiledExpression = strategy.Compile();
+ if (compiledExpression is ExcelErrorExpression) {
+ return RefreshList(compiledExpression);
+ }
+ if (expression == first) {
+ first = compiledExpression;
+ }
+
+ expression = compiledExpression;
+ } while (expression != null
+ && expression.Operator != null
+ && expression.Operator.Precedence == precedence);
+ return RefreshList(first);
+ }
+
+ private int FindLowestPrecedence() {
+ return _expressions.Where(x => x.Operator != null).Min(x => x.Operator.Precedence);
+ }
+
+ private IEnumerable<Expression> RefreshList(Expression first) {
+ var resultList = new List<Expression>();
+ var exp = first;
+ resultList.Add(exp);
+ while (exp.Next != null) {
+ resultList.Add(exp.Next);
+ exp = exp.Next;
+ }
+ _expressions = resultList;
+ return resultList;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExpressionConverter.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExpressionConverter.cs
new file mode 100644
index 0000000..9e27c63
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExpressionConverter.cs
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+public class ExpressionConverter : IExpressionConverter {
+ public StringExpression ToStringExpression(Expression expression) {
+ var result = expression.Compile();
+ var newExp = new StringExpression(result.Result.ToString());
+ newExp.Operator = expression.Operator;
+ return newExp;
+ }
+
+ public Expression FromCompileResult(CompileResult compileResult) {
+ switch (compileResult.DataType) {
+ case DataType.Integer:
+ return compileResult.Result is string
+ ? new(compileResult.Result.ToString())
+ : new IntegerExpression(Convert.ToDouble(compileResult.Result));
+ case DataType.String:
+ return new StringExpression(compileResult.Result.ToString());
+ case DataType.Decimal:
+ return compileResult.Result is string
+ ? new(compileResult.Result.ToString())
+ : new DecimalExpression(((double)compileResult.Result));
+ case DataType.Boolean:
+ return compileResult.Result is string
+ ? new(compileResult.Result.ToString())
+ : new BooleanExpression((bool)compileResult.Result);
+ //case DataType.Enumerable:
+ // return
+ case DataType.ExcelError:
+ //throw (new OfficeOpenXml.FormulaParsing.Exceptions.ExcelErrorValueException((ExcelErrorValue)compileResult.Result)); //Added JK
+ return compileResult.Result is string
+ ? new(
+ compileResult.Result.ToString(),
+ ExcelErrorValue.Parse(compileResult.Result.ToString()))
+ : new ExcelErrorExpression((ExcelErrorValue)compileResult.Result);
+ case DataType.Empty:
+ return new IntegerExpression(0); //Added JK
+ }
+ return null;
+ }
+
+ private static IExpressionConverter _instance;
+
+ public static IExpressionConverter Instance {
+ get {
+ if (_instance == null) {
+ _instance = new ExpressionConverter();
+ }
+ return _instance;
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExpressionFactory.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExpressionFactory.cs
new file mode 100644
index 0000000..66b3426
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExpressionFactory.cs
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public class ExpressionFactory : IExpressionFactory {
+ private readonly ExcelDataProvider _excelDataProvider;
+ private readonly ParsingContext _parsingContext;
+
+ public ExpressionFactory(ExcelDataProvider excelDataProvider, ParsingContext context) {
+ _excelDataProvider = excelDataProvider;
+ _parsingContext = context;
+ }
+
+ public Expression Create(Token token) {
+ switch (token.TokenType) {
+ case TokenType.Integer:
+ return new IntegerExpression(token.Value, token.IsNegated);
+ case TokenType.String:
+ return new StringExpression(token.Value);
+ case TokenType.Decimal:
+ return new DecimalExpression(token.Value, token.IsNegated);
+ case TokenType.Boolean:
+ return new BooleanExpression(token.Value);
+ case TokenType.ExcelAddress:
+ return new ExcelAddressExpression(
+ token.Value,
+ _excelDataProvider,
+ _parsingContext,
+ token.IsNegated);
+ case TokenType.InvalidReference:
+ return new ExcelErrorExpression(token.Value, ExcelErrorValue.Create(eErrorType.Ref));
+ case TokenType.NumericError:
+ return new ExcelErrorExpression(token.Value, ExcelErrorValue.Create(eErrorType.Num));
+ case TokenType.ValueDataTypeError:
+ return new ExcelErrorExpression(token.Value, ExcelErrorValue.Create(eErrorType.Value));
+ case TokenType.Null:
+ return new ExcelErrorExpression(token.Value, ExcelErrorValue.Create(eErrorType.Null));
+ case TokenType.NameValue:
+ return new NamedValueExpression(token.Value, _parsingContext);
+ default:
+ return new StringExpression(token.Value);
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExpressionGraph.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExpressionGraph.cs
new file mode 100644
index 0000000..dbb1bd6
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExpressionGraph.cs
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class ExpressionGraph {
+ private readonly List<Expression> _expressions = new();
+
+ public IEnumerable<Expression> Expressions => _expressions;
+
+ public Expression Current { get; private set; }
+
+ public Expression Add(Expression expression) {
+ _expressions.Add(expression);
+ if (Current != null) {
+ Current.Next = expression;
+ expression.Prev = Current;
+ }
+ Current = expression;
+ return expression;
+ }
+
+ public void Reset() {
+ _expressions.Clear();
+ Current = null;
+ }
+
+ public void Remove(Expression item) {
+ if (item == Current) {
+ Current = item.Prev ?? item.Next;
+ }
+ _expressions.Remove(item);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExpressionGraphBuilder.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExpressionGraphBuilder.cs
new file mode 100644
index 0000000..f8c1677
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/ExpressionGraphBuilder.cs
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class ExpressionGraphBuilder : IExpressionGraphBuilder {
+ private readonly ExpressionGraph _graph = new();
+ private readonly IExpressionFactory _expressionFactory;
+ private readonly ParsingContext _parsingContext;
+ private int _tokenIndex;
+ private bool _negateNextExpression;
+
+ public ExpressionGraphBuilder(ExcelDataProvider excelDataProvider, ParsingContext parsingContext)
+ : this(new ExpressionFactory(excelDataProvider, parsingContext), parsingContext) {}
+
+ public ExpressionGraphBuilder(
+ IExpressionFactory expressionFactory,
+ ParsingContext parsingContext) {
+ _expressionFactory = expressionFactory;
+ _parsingContext = parsingContext;
+ }
+
+ public ExpressionGraph Build(IEnumerable<Token> tokens) {
+ _tokenIndex = 0;
+ _graph.Reset();
+ var tokensArr = tokens != null ? tokens.ToArray() : [];
+ BuildUp(tokensArr, null);
+ return _graph;
+ }
+
+ private void BuildUp(Token[] tokens, Expression parent) {
+ while (_tokenIndex < tokens.Length) {
+ var token = tokens[_tokenIndex];
+ if (token.TokenType == TokenType.Operator
+ && OperatorsDict.Instance.TryGetValue(token.Value, out var op)) {
+ SetOperatorOnExpression(parent, op);
+ } else if (token.TokenType == TokenType.Function) {
+ BuildFunctionExpression(tokens, parent, token.Value);
+ } else if (token.TokenType == TokenType.OpeningEnumerable) {
+ _tokenIndex++;
+ BuildEnumerableExpression(tokens, parent);
+ } else if (token.TokenType == TokenType.OpeningParenthesis) {
+ _tokenIndex++;
+ BuildGroupExpression(tokens, parent);
+ //if (parent is FunctionExpression)
+ //{
+ // return;
+ //}
+ } else if (token.TokenType == TokenType.ClosingParenthesis
+ || token.TokenType == TokenType.ClosingEnumerable) {
+ break;
+ } else if (token.TokenType == TokenType.Negator) {
+ _negateNextExpression = true;
+ } else if (token.TokenType == TokenType.Percent) {
+ SetOperatorOnExpression(parent, Operator.Percent);
+ if (parent == null) {
+ _graph.Add(ConstantExpressions.Percent);
+ } else {
+ parent.AddChild(ConstantExpressions.Percent);
+ }
+ } else {
+ CreateAndAppendExpression(ref parent, token);
+ }
+ _tokenIndex++;
+ }
+ }
+
+ private void BuildEnumerableExpression(Token[] tokens, Expression parent) {
+ if (parent == null) {
+ _graph.Add(new EnumerableExpression());
+ BuildUp(tokens, _graph.Current);
+ } else {
+ var enumerableExpression = new EnumerableExpression();
+ parent.AddChild(enumerableExpression);
+ BuildUp(tokens, enumerableExpression);
+ }
+ }
+
+ private void CreateAndAppendExpression(ref Expression parent, Token token) {
+ if (IsWaste(token)) {
+ return;
+ }
+ if (parent != null
+ && (token.TokenType == TokenType.Comma || token.TokenType == TokenType.SemiColon)) {
+ parent = parent.PrepareForNextChild();
+ return;
+ }
+ if (_negateNextExpression) {
+ token.Negate();
+ _negateNextExpression = false;
+ }
+ var expression = _expressionFactory.Create(token);
+ if (parent == null) {
+ _graph.Add(expression);
+ } else {
+ parent.AddChild(expression);
+ }
+ }
+
+ private bool IsWaste(Token token) {
+ if (token.TokenType == TokenType.String) {
+ return true;
+ }
+ return false;
+ }
+
+ private void BuildFunctionExpression(Token[] tokens, Expression parent, string funcName) {
+ if (parent == null) {
+ _graph.Add(new FunctionExpression(funcName, _parsingContext, _negateNextExpression));
+ _negateNextExpression = false;
+ HandleFunctionArguments(tokens, _graph.Current);
+ } else {
+ var func = new FunctionExpression(funcName, _parsingContext, _negateNextExpression);
+ _negateNextExpression = false;
+ parent.AddChild(func);
+ HandleFunctionArguments(tokens, func);
+ }
+ }
+
+ private void HandleFunctionArguments(Token[] tokens, Expression function) {
+ _tokenIndex++;
+ var token = tokens.ElementAt(_tokenIndex);
+ if (token.TokenType != TokenType.OpeningParenthesis) {
+ throw new ExcelErrorValueException(eErrorType.Value);
+ }
+ _tokenIndex++;
+ BuildUp(tokens, function.Children.First());
+ }
+
+ private void BuildGroupExpression(Token[] tokens, Expression parent) {
+ if (parent == null) {
+ _graph.Add(new GroupExpression(_negateNextExpression));
+ _negateNextExpression = false;
+ BuildUp(tokens, _graph.Current);
+ } else {
+ if (parent.IsGroupedExpression || parent is FunctionArgumentExpression) {
+ var newGroupExpression = new GroupExpression(_negateNextExpression);
+ _negateNextExpression = false;
+ parent.AddChild(newGroupExpression);
+ BuildUp(tokens, newGroupExpression);
+ }
+ BuildUp(tokens, parent);
+ }
+ }
+
+ private void SetOperatorOnExpression(Expression parent, IOperator op) {
+ if (parent == null) {
+ _graph.Current.Operator = op;
+ } else {
+ Expression candidate;
+ if (parent is FunctionArgumentExpression) {
+ candidate = parent.Children.Last();
+ } else {
+ candidate = parent.Children.Last();
+ if (candidate is FunctionArgumentExpression) {
+ candidate = candidate.Children.Last();
+ }
+ }
+ candidate.Operator = op;
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionArgumentExpression.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionArgumentExpression.cs
new file mode 100644
index 0000000..94e48c0
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionArgumentExpression.cs
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class FunctionArgumentExpression : GroupExpression {
+ private readonly Expression _function;
+
+ public FunctionArgumentExpression(Expression function)
+ : base(false) {
+ _function = function;
+ }
+
+ public override bool ParentIsLookupFunction {
+ get => base.ParentIsLookupFunction;
+ set {
+ base.ParentIsLookupFunction = value;
+ foreach (var child in Children) {
+ child.ParentIsLookupFunction = value;
+ }
+ }
+ }
+
+ public override bool IsGroupedExpression => false;
+
+ public override Expression PrepareForNextChild() {
+ return _function.PrepareForNextChild();
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/DefaultCompiler.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/DefaultCompiler.cs
new file mode 100644
index 0000000..4b885b4
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/DefaultCompiler.cs
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class DefaultCompiler : FunctionCompiler {
+ public DefaultCompiler(ExcelFunction function)
+ : base(function) {}
+
+ public override CompileResult Compile(IEnumerable<Expression> children, ParsingContext context) {
+ var args = new List<FunctionArgument>();
+ Function.BeforeInvoke(context);
+ foreach (var child in children) {
+ var compileResult = child.Compile();
+ if (compileResult.IsResultOfSubtotal) {
+ var arg = new FunctionArgument(compileResult.Result);
+ arg.SetExcelStateFlag(ExcelCellState.IsResultOfSubtotal);
+ args.Add(arg);
+ } else {
+ BuildFunctionArguments(compileResult.Result, args);
+ }
+ }
+ return Function.Execute(args, context);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/ErrorHandlingFunctionCompiler.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/ErrorHandlingFunctionCompiler.cs
new file mode 100644
index 0000000..c23bba4
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/ErrorHandlingFunctionCompiler.cs
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class ErrorHandlingFunctionCompiler : FunctionCompiler {
+ public ErrorHandlingFunctionCompiler(ExcelFunction function)
+ : base(function) {}
+
+ public override CompileResult Compile(IEnumerable<Expression> children, ParsingContext context) {
+ var args = new List<FunctionArgument>();
+ Function.BeforeInvoke(context);
+ foreach (var child in children) {
+ try {
+ var arg = child.Compile();
+ BuildFunctionArguments(arg?.Result, args);
+ } catch (ExcelErrorValueException efe) {
+ return ((ErrorHandlingFunction)Function).HandleError(efe.ErrorValue.ToString());
+ } catch // (Exception e)
+ {
+ return ((ErrorHandlingFunction)Function).HandleError(ExcelErrorValue.Values.Value);
+ }
+ }
+ return Function.Execute(args, context);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompiler.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompiler.cs
new file mode 100644
index 0000000..e6c0996
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompiler.cs
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public abstract class FunctionCompiler {
+ protected ExcelFunction Function { get; private set; }
+
+ public FunctionCompiler(ExcelFunction function) {
+ Require.That(function).Named("function").IsNotNull();
+ Function = function;
+ }
+
+ protected void BuildFunctionArguments(object result, List<FunctionArgument> args) {
+ if (result is IEnumerable<object> objects && !(objects is ExcelDataProvider.IRangeInfo)) {
+ var argList = new List<FunctionArgument>();
+ foreach (var arg in objects) {
+ BuildFunctionArguments(arg, argList);
+ }
+ args.Add(new(argList));
+ } else {
+ args.Add(new(result));
+ }
+ }
+
+ public abstract CompileResult Compile(IEnumerable<Expression> children, ParsingContext context);
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompilerFactory.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompilerFactory.cs
new file mode 100644
index 0000000..af9c099
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompilerFactory.cs
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class FunctionCompilerFactory {
+ private readonly Dictionary<Type, FunctionCompiler> _specialCompilers = new();
+
+ public FunctionCompilerFactory(FunctionRepository repository) {
+ _specialCompilers.Add(typeof(If), new IfFunctionCompiler(repository.GetFunction("if")));
+ _specialCompilers.Add(
+ typeof(IfError),
+ new IfErrorFunctionCompiler(repository.GetFunction("iferror")));
+ _specialCompilers.Add(typeof(IfNa), new IfNaFunctionCompiler(repository.GetFunction("ifna")));
+ }
+
+ private FunctionCompiler GetCompilerByType(ExcelFunction function) {
+ var funcType = function.GetType();
+ if (_specialCompilers.ContainsKey(funcType)) {
+ return _specialCompilers[funcType];
+ }
+ return new DefaultCompiler(function);
+ }
+
+ public virtual FunctionCompiler Create(ExcelFunction function) {
+ if (function.IsLookupFuction) {
+ return new LookupFunctionCompiler(function);
+ }
+ if (function.IsErrorHandlingFunction) {
+ return new ErrorHandlingFunctionCompiler(function);
+ }
+ return GetCompilerByType(function);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfErrorFunctionCompiler.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfErrorFunctionCompiler.cs
new file mode 100644
index 0000000..e5bb7ab
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfErrorFunctionCompiler.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class IfErrorFunctionCompiler : FunctionCompiler {
+ public IfErrorFunctionCompiler(ExcelFunction function)
+ : base(function) {
+ Require.That(function).Named("function").IsNotNull();
+ }
+
+ public override CompileResult Compile(IEnumerable<Expression> children, ParsingContext context) {
+ if (children.Count() != 2) {
+ throw new ExcelErrorValueException(eErrorType.Value);
+ }
+ var args = new List<FunctionArgument>();
+ Function.BeforeInvoke(context);
+ var firstChild = children.First();
+ var lastChild = children.ElementAt(1);
+ try {
+ var result = firstChild.Compile();
+ if (result.DataType == DataType.ExcelError) {
+ args.Add(new(lastChild.Compile().Result));
+ } else {
+ args.Add(new(result.Result));
+ }
+ } catch (ExcelErrorValueException) {
+ args.Add(new(lastChild.Compile().Result));
+ }
+ return Function.Execute(args, context);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfFunctionCompiler.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfFunctionCompiler.cs
new file mode 100644
index 0000000..e2b884b
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfFunctionCompiler.cs
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2014-01-27
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Why do the If function require a compiler of its own you might ask;)
+///
+/// It is because it only needs to evaluate one of the two last expressions. This
+/// compiler handles this - it ignores the irrelevant expression.
+/// </summary>
+public class IfFunctionCompiler : FunctionCompiler {
+ public IfFunctionCompiler(ExcelFunction function)
+ : base(function) {
+ Require.That(function).Named("function").IsNotNull();
+ if (!(function is If)) {
+ throw new ArgumentException("function must be of type If");
+ }
+ }
+
+ public override CompileResult Compile(IEnumerable<Expression> children, ParsingContext context) {
+ if (children.Count() < 3) {
+ throw new ExcelErrorValueException(eErrorType.Value);
+ }
+ var args = new List<FunctionArgument>();
+ Function.BeforeInvoke(context);
+ var firstChild = children.ElementAt(0);
+ var v = firstChild.Compile().Result;
+
+ /**** Handle names and ranges ****/
+ if (v is ExcelDataProvider.INameInfo info) {
+ v = info.Value;
+ }
+
+ if (v is ExcelDataProvider.IRangeInfo rangeInfo) {
+ if (rangeInfo.GetNCells() > 1) {
+ throw (new ArgumentException("Logical can't be more than one cell"));
+ }
+ v = rangeInfo.GetOffset(0, 0);
+ }
+ bool boolVal;
+ if (v is bool b) {
+ boolVal = b;
+ } else {
+ if (ConvertUtil.IsNumeric(v)) {
+ boolVal = ConvertUtil.GetValueDouble(v) != 0;
+ } else {
+ throw (new ArgumentException("Invalid logical test"));
+ }
+ }
+ /**** End Handle names and ranges ****/
+
+ args.Add(new(boolVal));
+ if (boolVal) {
+ var val = children.ElementAt(1).Compile().Result;
+ args.Add(new(val));
+ args.Add(new(null));
+ } else {
+ var val = children.ElementAt(2).Compile().Result;
+ args.Add(new(null));
+ args.Add(new(val));
+ }
+ return Function.Execute(args, context);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfNaFunctionCompiler.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfNaFunctionCompiler.cs
new file mode 100644
index 0000000..1e5075a
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfNaFunctionCompiler.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class IfNaFunctionCompiler : FunctionCompiler {
+ public IfNaFunctionCompiler(ExcelFunction function)
+ : base(function) {}
+
+ public override CompileResult Compile(IEnumerable<Expression> children, ParsingContext context) {
+ if (children.Count() != 2) {
+ throw new ExcelErrorValueException(eErrorType.Value);
+ }
+ var args = new List<FunctionArgument>();
+ Function.BeforeInvoke(context);
+ var firstChild = children.First();
+ var lastChild = children.ElementAt(1);
+ try {
+ var result = firstChild.Compile();
+ if (result.DataType == DataType.ExcelError
+ && (Equals(result.Result, ExcelErrorValue.Create(eErrorType.Na)))) {
+ args.Add(new(lastChild.Compile().Result));
+ } else {
+ args.Add(new(result.Result));
+ }
+ } catch (ExcelErrorValueException) {
+ args.Add(new(lastChild.Compile().Result));
+ }
+ return Function.Execute(args, context);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/LookupFunctionCompiler.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/LookupFunctionCompiler.cs
new file mode 100644
index 0000000..883fd75
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionCompilers/LookupFunctionCompiler.cs
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class LookupFunctionCompiler : FunctionCompiler {
+ public LookupFunctionCompiler(ExcelFunction function)
+ : base(function) {}
+
+ public override CompileResult Compile(IEnumerable<Expression> children, ParsingContext context) {
+ var args = new List<FunctionArgument>();
+ Function.BeforeInvoke(context);
+ var firstChild = true;
+ foreach (var child in children) {
+ if (!firstChild || Function.SkipArgumentEvaluation) {
+ child.ParentIsLookupFunction = Function.IsLookupFuction;
+ } else {
+ firstChild = false;
+ }
+ var arg = child.Compile();
+ BuildFunctionArguments(arg?.Result, args);
+ }
+ return Function.Execute(args, context);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionExpression.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionExpression.cs
new file mode 100644
index 0000000..88cc7cc
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/FunctionExpression.cs
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Expression that handles execution of a function.
+/// </summary>
+public class FunctionExpression : AtomicExpression {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="expression">should be the of the function</param>
+ /// <param name="parsingContext"></param>
+ /// <param name="isNegated">True if the numeric result of the function should be negated.</param>
+ public FunctionExpression(string expression, ParsingContext parsingContext, bool isNegated)
+ : base(expression) {
+ _parsingContext = parsingContext;
+ _functionCompilerFactory = new(parsingContext.Configuration.FunctionRepository);
+ _isNegated = isNegated;
+ base.AddChild(new FunctionArgumentExpression(this));
+ }
+
+ private readonly ParsingContext _parsingContext;
+ private readonly FunctionCompilerFactory _functionCompilerFactory;
+ private readonly bool _isNegated;
+
+ public override CompileResult Compile() {
+ try {
+ var function = _parsingContext.Configuration.FunctionRepository.GetFunction(ExpressionString);
+ if (function == null) {
+ if (_parsingContext.Debug) {
+ _parsingContext.Configuration.Logger.Log(
+ _parsingContext,
+ string.Format("'{0}' is not a supported function", ExpressionString));
+ }
+ return new(ExcelErrorValue.Create(eErrorType.Name), DataType.ExcelError);
+ }
+ if (_parsingContext.Debug) {
+ _parsingContext.Configuration.Logger.LogFunction(ExpressionString);
+ }
+ var compiler = _functionCompilerFactory.Create(function);
+ var result = compiler.Compile(HasChildren ? Children : [], _parsingContext);
+ if (_isNegated) {
+ if (!result.IsNumeric) {
+ if (_parsingContext.Debug) {
+ var msg = string.Format(
+ "Trying to negate a non-numeric value ({0}) in function '{1}'",
+ result.Result,
+ ExpressionString);
+ _parsingContext.Configuration.Logger.Log(_parsingContext, msg);
+ }
+ return new(ExcelErrorValue.Create(eErrorType.Value), DataType.ExcelError);
+ }
+ return new(result.ResultNumeric * -1, result.DataType);
+ }
+ return result;
+ } catch (ExcelErrorValueException e) {
+ if (_parsingContext.Debug) {
+ _parsingContext.Configuration.Logger.Log(_parsingContext, e);
+ }
+ return new(e.ErrorValue, DataType.ExcelError);
+ }
+ }
+
+ public override Expression PrepareForNextChild() {
+ return base.AddChild(new FunctionArgumentExpression(this));
+ }
+
+ public override bool HasChildren => (Children.Any() && Children.First().Children.Any());
+
+ public override Expression AddChild(Expression child) {
+ Children.Last().AddChild(child);
+ return child;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/GroupExpression.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/GroupExpression.cs
new file mode 100644
index 0000000..6fc8152
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/GroupExpression.cs
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class GroupExpression : Expression {
+ public GroupExpression(bool isNegated)
+ : this(isNegated, new ExpressionCompiler()) {}
+
+ public GroupExpression(bool isNegated, IExpressionCompiler expressionCompiler) {
+ _expressionCompiler = expressionCompiler;
+ _isNegated = isNegated;
+ }
+
+ private readonly IExpressionCompiler _expressionCompiler;
+ private readonly bool _isNegated;
+
+ public override CompileResult Compile() {
+ var result = _expressionCompiler.Compile(Children);
+ if (result.IsNumeric && _isNegated) {
+ return new(result.ResultNumeric * -1, result.DataType);
+ }
+ return result;
+ }
+
+ public override bool IsGroupedExpression => true;
+
+ public bool IsNegated => _isNegated;
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/IExpressionCompiler.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/IExpressionCompiler.cs
new file mode 100644
index 0000000..cdfbc64
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/IExpressionCompiler.cs
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public interface IExpressionCompiler {
+ CompileResult Compile(IEnumerable<Expression> expressions);
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/IExpressionConverter.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/IExpressionConverter.cs
new file mode 100644
index 0000000..737ca8e
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/IExpressionConverter.cs
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public interface IExpressionConverter {
+ StringExpression ToStringExpression(Expression expression);
+
+ Expression FromCompileResult(CompileResult compileResult);
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/IExpressionFactory.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/IExpressionFactory.cs
new file mode 100644
index 0000000..3b0015f
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/IExpressionFactory.cs
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+public interface IExpressionFactory {
+ Expression Create(Token token);
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/IExpressionGraphBuilder.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/IExpressionGraphBuilder.cs
new file mode 100644
index 0000000..d514970
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/IExpressionGraphBuilder.cs
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public interface IExpressionGraphBuilder {
+ ExpressionGraph Build(IEnumerable<Token> tokens);
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/IntegerExpression.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/IntegerExpression.cs
new file mode 100644
index 0000000..90afbc8
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/IntegerExpression.cs
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+using System.Globalization;
+
+namespace AppsheetEpplus;
+
+public class IntegerExpression : AtomicExpression {
+ private readonly double? _compiledValue;
+ private readonly bool _negate;
+
+ public IntegerExpression(string expression)
+ : this(expression, false) {}
+
+ public IntegerExpression(string expression, bool negate)
+ : base(expression) {
+ _negate = negate;
+ }
+
+ public IntegerExpression(double val)
+ : base(val.ToString(CultureInfo.InvariantCulture)) {
+ _compiledValue = Math.Floor(val);
+ }
+
+ public override CompileResult Compile() {
+ double result = _compiledValue ?? double.Parse(ExpressionString, CultureInfo.InvariantCulture);
+ result = _negate ? result * -1 : result;
+ return new(result, DataType.Integer);
+ }
+
+ public bool IsNegated => _negate;
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/NamedValueExpression.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/NamedValueExpression.cs
new file mode 100644
index 0000000..0416b0d
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/NamedValueExpression.cs
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class NamedValueExpression : AtomicExpression {
+ public NamedValueExpression(string expression, ParsingContext parsingContext)
+ : base(expression) {
+ _parsingContext = parsingContext;
+ }
+
+ private readonly ParsingContext _parsingContext;
+
+ public override CompileResult Compile() {
+ var c = _parsingContext.Scopes.Current;
+ var name = _parsingContext.ExcelDataProvider.GetName(c.Address.Worksheet, ExpressionString);
+ //var result = _parsingContext.Parser.Parse(value.ToString());
+
+ if (name == null) {
+ throw (new ExcelErrorValueException(ExcelErrorValue.Create(eErrorType.Name)));
+ }
+ if (name.Value == null) {
+ return null;
+ }
+ if (name.Value is ExcelDataProvider.IRangeInfo range) {
+ if (range.IsMulti) {
+ return new(range, DataType.Enumerable);
+ }
+ if (range.IsEmpty) {
+ return null;
+ }
+ var factory = new CompileResultFactory();
+ return factory.Create(range.First().Value);
+ }
+ {
+ var factory = new CompileResultFactory();
+ return factory.Create(name.Value);
+ }
+
+ //return new CompileResultFactory().Create(result);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ExpressionGraph/StringExpression.cs b/AppsheetEpplus/FormulaParsing/ExpressionGraph/StringExpression.cs
new file mode 100644
index 0000000..623dd53
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ExpressionGraph/StringExpression.cs
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class StringExpression : AtomicExpression {
+ public StringExpression(string expression)
+ : base(expression) {}
+
+ public override CompileResult Compile() {
+ return new(ExpressionString, DataType.String);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/FormulaParser.cs b/AppsheetEpplus/FormulaParsing/FormulaParser.cs
new file mode 100644
index 0000000..9988be8
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/FormulaParser.cs
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+public class FormulaParser {
+ private readonly ParsingContext _parsingContext;
+ private readonly ExcelDataProvider _excelDataProvider;
+
+ public FormulaParser(ExcelDataProvider excelDataProvider)
+ : this(excelDataProvider, ParsingContext.Create()) {}
+
+ public FormulaParser(ExcelDataProvider excelDataProvider, ParsingContext parsingContext) {
+ parsingContext.Parser = this;
+ parsingContext.ExcelDataProvider = excelDataProvider;
+ parsingContext.NameValueProvider = new EpplusNameValueProvider(excelDataProvider);
+ parsingContext.RangeAddressFactory = new(excelDataProvider);
+ _parsingContext = parsingContext;
+ _excelDataProvider = excelDataProvider;
+ Configure(configuration => {
+ configuration
+ .SetLexer(
+ new Lexer(
+ _parsingContext.Configuration.FunctionRepository,
+ _parsingContext.NameValueProvider))
+ .SetGraphBuilder(new ExpressionGraphBuilder(excelDataProvider, _parsingContext))
+ .SetExpresionCompiler(new ExpressionCompiler())
+ .FunctionRepository.LoadModule(new BuiltInFunctions());
+ });
+ }
+
+ public void Configure(Action<ParsingConfiguration> configMethod) {
+ configMethod.Invoke(_parsingContext.Configuration);
+ _lexer = _parsingContext.Configuration.Lexer ?? _lexer;
+ _graphBuilder = _parsingContext.Configuration.GraphBuilder ?? _graphBuilder;
+ _compiler = _parsingContext.Configuration.ExpressionCompiler ?? _compiler;
+ }
+
+ private ILexer _lexer;
+ private IExpressionGraphBuilder _graphBuilder;
+ private IExpressionCompiler _compiler;
+
+ public ILexer Lexer => _lexer;
+
+ public IEnumerable<string> FunctionNames =>
+ _parsingContext.Configuration.FunctionRepository.FunctionNames;
+
+ internal virtual object Parse(string formula, RangeAddress rangeAddress) {
+ using (var scope = _parsingContext.Scopes.NewScope(rangeAddress)) {
+ var tokens = _lexer.Tokenize(formula);
+ var graph = _graphBuilder.Build(tokens);
+ if (graph.Expressions.Count() == 0) {
+ return null;
+ }
+ return _compiler.Compile(graph.Expressions).Result;
+ }
+ }
+
+ internal virtual object Parse(IEnumerable<Token> tokens, string worksheet, string address) {
+ var rangeAddress = _parsingContext.RangeAddressFactory.Create(address);
+ using (var scope = _parsingContext.Scopes.NewScope(rangeAddress)) {
+ var graph = _graphBuilder.Build(tokens);
+ if (graph.Expressions.Count() == 0) {
+ return null;
+ }
+ return _compiler.Compile(graph.Expressions).Result;
+ }
+ }
+
+ internal virtual object ParseCell(
+ IEnumerable<Token> tokens,
+ string worksheet,
+ int row,
+ int column) {
+ var rangeAddress = _parsingContext.RangeAddressFactory.Create(worksheet, column, row);
+ using (var scope = _parsingContext.Scopes.NewScope(rangeAddress)) {
+ // _parsingContext.Dependencies.AddFormulaScope(scope);
+ var graph = _graphBuilder.Build(tokens);
+ if (graph.Expressions.Count() == 0) {
+ return 0d;
+ }
+ try {
+ var compileResult = _compiler.Compile(graph.Expressions);
+ // quick solution for the fact that an excelrange can be returned.
+ var rangeInfo = compileResult.Result as ExcelDataProvider.IRangeInfo;
+ if (rangeInfo == null) {
+ return compileResult.Result ?? 0d;
+ }
+ if (rangeInfo.IsEmpty) {
+ return 0d;
+ }
+ if (!rangeInfo.IsMulti) {
+ return rangeInfo.First().Value ?? 0d;
+ }
+ // ok to return multicell if it is a workbook scoped name.
+ if (string.IsNullOrEmpty(worksheet)) {
+ return rangeInfo;
+ }
+ if (_parsingContext.Debug) {
+ var msg = string.Format(
+ "A range with multiple cell was returned at row {0}, column {1}",
+ row,
+ column);
+ _parsingContext.Configuration.Logger.Log(_parsingContext, msg);
+ }
+ return ExcelErrorValue.Create(eErrorType.Value);
+ } catch (ExcelErrorValueException ex) {
+ if (_parsingContext.Debug) {
+ _parsingContext.Configuration.Logger.Log(_parsingContext, ex);
+ }
+ return ex.ErrorValue;
+ }
+ }
+ }
+
+ public virtual object Parse(string formula, string address) {
+ return Parse(formula, _parsingContext.RangeAddressFactory.Create(address));
+ }
+
+ public virtual object Parse(string formula) {
+ return Parse(formula, RangeAddress.Empty);
+ }
+
+ public virtual object ParseAt(string address) {
+ Require.That(address).Named("address").IsNotNullOrEmpty();
+ var rangeAddress = _parsingContext.RangeAddressFactory.Create(address);
+ return ParseAt(rangeAddress.Worksheet, rangeAddress.FromRow, rangeAddress.FromCol);
+ }
+
+ public virtual object ParseAt(string worksheetName, int row, int col) {
+ var f = _excelDataProvider.GetRangeFormula(worksheetName, row, col);
+ if (string.IsNullOrEmpty(f)) {
+ return _excelDataProvider.GetRangeValue(worksheetName, row, col);
+ }
+ return Parse(f, _parsingContext.RangeAddressFactory.Create(worksheetName, col, row));
+ //var dataItem = _excelDataProvider.GetRangeValues(address).FirstOrDefault();
+ //if (dataItem == null /*|| (dataItem.Value == null && dataItem.Formula == null)*/) return null;
+ //if (!string.IsNullOrEmpty(dataItem.Formula))
+ //{
+ // return Parse(dataItem.Formula, _parsingContext.RangeAddressFactory.Create(address));
+ //}
+ //return Parse(dataItem.Value.ToString(), _parsingContext.RangeAddressFactory.Create(address));
+ }
+
+ internal void InitNewCalc() {
+ if (_excelDataProvider != null) {
+ _excelDataProvider.Reset();
+ }
+ }
+
+ // Praveen's Formula Parser
+ public ExpressionGraph ParseToGraph(string formula) {
+ using (var scope = _parsingContext.Scopes.NewScope(RangeAddress.Empty)) {
+ var tokens = _lexer.Tokenize(formula);
+ var graph = _graphBuilder.Build(tokens);
+ return graph;
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/FormulaParserManager.cs b/AppsheetEpplus/FormulaParsing/FormulaParserManager.cs
new file mode 100644
index 0000000..9b5b6f5
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/FormulaParserManager.cs
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Provides access to various functionality regarding
+/// excel formula evaluation.
+/// </summary>
+public class FormulaParserManager {
+ private readonly FormulaParser _parser;
+
+ internal FormulaParserManager(FormulaParser parser) {
+ Require.That(parser).Named("parser").IsNotNull();
+ _parser = parser;
+ }
+
+ /// <summary>
+ /// Loads a module containing custom functions to the formula parser. By using
+ /// this method you can add your own implementations of Excel functions, by
+ /// implementing a <see cref="IFunctionModule"/>.
+ /// </summary>
+ /// <param name="module">A <see cref="IFunctionModule"/> containing <see cref="ExcelFunction"/>s.</param>
+ public void LoadFunctionModule(IFunctionModule module) {
+ _parser.Configure(x => x.FunctionRepository.LoadModule(module));
+ }
+
+ /// <summary>
+ /// If the supplied <paramref name="functionName"/> does not exist, the supplied
+ /// <paramref name="functionImpl"/> implementation will be added to the formula parser.
+ /// If it exists, the existing function will be replaced by the supplied <paramref name="functionImpl">function implementation</paramref>
+ /// </summary>
+ /// <param name="functionName"></param>
+ /// <param name="functionImpl"></param>
+ public void AddOrReplaceFunction(string functionName, ExcelFunction functionImpl) {
+ _parser.Configure(x => x.FunctionRepository.AddOrReplaceFunction(functionName, functionImpl));
+ }
+
+ /// <summary>
+ /// Returns an enumeration of all functions implemented, both the built in functions
+ /// and functions added using the LoadFunctionModule method of this class.
+ /// </summary>
+ /// <returns>Function names in lower case</returns>
+ public IEnumerable<string> GetImplementedFunctionNames() {
+ var fnList = _parser.FunctionNames.ToList();
+ fnList.Sort((x, y) => String.Compare(x, y, StringComparison.Ordinal));
+ return fnList;
+ }
+
+ /// <summary>
+ /// Parses the supplied <paramref name="formula"/> and returns the result.
+ /// </summary>
+ /// <param name="formula"></param>
+ /// <returns></returns>
+ public object Parse(string formula) {
+ return _parser.Parse(formula);
+ }
+
+ // Praveen's Parser Support
+ public ExpressionGraph ParseToGraph(string formula) {
+ return _parser.ParseToGraph(formula);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/INameValueProvider.cs b/AppsheetEpplus/FormulaParsing/INameValueProvider.cs
new file mode 100644
index 0000000..e4c59b5
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/INameValueProvider.cs
@@ -0,0 +1,9 @@
+namespace AppsheetEpplus;
+
+public interface INameValueProvider {
+ bool IsNamedValue(string key, string worksheet);
+
+ object GetNamedValue(string key);
+
+ void Reload();
+}
diff --git a/AppsheetEpplus/FormulaParsing/IParsingLifetimeEventHandler.cs b/AppsheetEpplus/FormulaParsing/IParsingLifetimeEventHandler.cs
new file mode 100644
index 0000000..f4eeed6
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/IParsingLifetimeEventHandler.cs
@@ -0,0 +1,5 @@
+namespace AppsheetEpplus;
+
+public interface IParsingLifetimeEventHandler {
+ void ParsingCompleted();
+}
diff --git a/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ILexer.cs b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ILexer.cs
new file mode 100644
index 0000000..b765128
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ILexer.cs
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public interface ILexer {
+ IEnumerable<Token> Tokenize(string input);
+
+ IEnumerable<Token> Tokenize(string input, string worksheet);
+}
diff --git a/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ISourceCodeTokenizer.cs b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ISourceCodeTokenizer.cs
new file mode 100644
index 0000000..1d16343
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ISourceCodeTokenizer.cs
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public interface ISourceCodeTokenizer {
+ IEnumerable<Token> Tokenize(string input, string worksheet);
+}
diff --git a/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ISyntacticAnalyzer.cs b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ISyntacticAnalyzer.cs
new file mode 100644
index 0000000..bf24a33
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ISyntacticAnalyzer.cs
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public interface ISyntacticAnalyzer {
+ void Analyze(IEnumerable<Token> tokens);
+}
diff --git a/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ITokenFactory.cs b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ITokenFactory.cs
new file mode 100644
index 0000000..e5c2e4d
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ITokenFactory.cs
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public interface ITokenFactory {
+ Token Create(IEnumerable<Token> tokens, string token);
+
+ Token Create(IEnumerable<Token> tokens, string token, string worksheet);
+
+ Token Create(string token, TokenType explicitTokenType);
+}
diff --git a/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ITokenIndexProvider.cs b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ITokenIndexProvider.cs
new file mode 100644
index 0000000..3c203d7
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ITokenIndexProvider.cs
@@ -0,0 +1,7 @@
+namespace AppsheetEpplus;
+
+public interface ITokenIndexProvider {
+ int Index { get; }
+
+ void MoveIndexPointerForward();
+}
diff --git a/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ITokenSeparatorProvider.cs b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ITokenSeparatorProvider.cs
new file mode 100644
index 0000000..48b7efa
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/ITokenSeparatorProvider.cs
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public interface ITokenSeparatorProvider {
+ IDictionary<string, Token> Tokens { get; }
+
+ bool IsOperator(string item);
+
+ bool IsPossibleLastPartOfMultipleCharOperator(string part);
+}
diff --git a/AppsheetEpplus/FormulaParsing/LexicalAnalysis/Lexer.cs b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/Lexer.cs
new file mode 100644
index 0000000..0dc1cef
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/Lexer.cs
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+//
+namespace AppsheetEpplus;
+
+public class Lexer : ILexer {
+ public Lexer(FunctionRepository functionRepository, INameValueProvider nameValueProvider)
+ : this(
+ new SourceCodeTokenizer(functionRepository, nameValueProvider),
+ new SyntacticAnalyzer()) {}
+
+ public Lexer(ISourceCodeTokenizer tokenizer, ISyntacticAnalyzer analyzer) {
+ _tokenizer = tokenizer;
+ _analyzer = analyzer;
+ }
+
+ private readonly ISourceCodeTokenizer _tokenizer;
+ private readonly ISyntacticAnalyzer _analyzer;
+
+ public IEnumerable<Token> Tokenize(string input) {
+ return Tokenize(input, null);
+ }
+
+ public IEnumerable<Token> Tokenize(string input, string worksheet) {
+ var tokens = _tokenizer.Tokenize(input, worksheet);
+ _analyzer.Analyze(tokens);
+ return tokens;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/LexicalAnalysis/SourceCodeTokenizer.cs b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/SourceCodeTokenizer.cs
new file mode 100644
index 0000000..3a6a006
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/SourceCodeTokenizer.cs
@@ -0,0 +1,296 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AppsheetEpplus;
+
+public class SourceCodeTokenizer : ISourceCodeTokenizer {
+ public static ISourceCodeTokenizer Default =>
+ new SourceCodeTokenizer(FunctionNameProvider.Empty, NameValueProvider.Empty);
+
+ public SourceCodeTokenizer(
+ IFunctionNameProvider functionRepository,
+ INameValueProvider nameValueProvider)
+ : this(
+ new TokenFactory(functionRepository, nameValueProvider),
+ new TokenSeparatorProvider()) {}
+
+ public SourceCodeTokenizer(ITokenFactory tokenFactory, ITokenSeparatorProvider tokenProvider) {
+ _tokenFactory = tokenFactory;
+ _tokenProvider = tokenProvider;
+ }
+
+ private readonly ITokenSeparatorProvider _tokenProvider;
+ private readonly ITokenFactory _tokenFactory;
+
+ public IEnumerable<Token> Tokenize(string input) {
+ return Tokenize(input, null);
+ }
+
+ public IEnumerable<Token> Tokenize(string input, string worksheet) {
+ if (string.IsNullOrEmpty(input)) {
+ return [];
+ }
+ // MA 1401: Ignore leading plus in formula.
+ input = input.TrimStart('+');
+ var context = new TokenizerContext(input);
+
+ bool isSingleQuoteString = false;
+ for (int i = 0; i < context.FormulaChars.Length; i++) {
+ var c = context.FormulaChars[i];
+ if (CharIsTokenSeparator(c, out var tokenSeparator)) {
+ if (context.IsInString) {
+ if (IsDoubleQuote(tokenSeparator, i, context)) {
+ i++;
+ context.AppendToCurrentToken(c);
+ continue;
+ }
+ if (tokenSeparator.TokenType != TokenType.String) {
+ context.AppendToCurrentToken(c);
+ continue;
+ }
+ // CHANGE 2
+ if ((isSingleQuoteString && c != '\'') || (!isSingleQuoteString && c != '"')) {
+ context.AppendToCurrentToken(c);
+ continue;
+ }
+ }
+ if (tokenSeparator.TokenType == TokenType.OpeningBracket) {
+ context.AppendToCurrentToken(c);
+ context.BracketCount++;
+ continue;
+ }
+ if (tokenSeparator.TokenType == TokenType.ClosingBracket) {
+ context.AppendToCurrentToken(c);
+ context.BracketCount--;
+ continue;
+ }
+ if (context.BracketCount > 0) {
+ context.AppendToCurrentToken(c);
+ continue;
+ }
+ // two operators in sequence could be "<=" or ">="
+ if (IsPartOfMultipleCharSeparator(context, c)) {
+ var sOp = context.LastToken.Value + c.ToString(CultureInfo.InvariantCulture);
+ var op = _tokenProvider.Tokens[sOp];
+ context.ReplaceLastToken(op);
+ context.NewToken();
+ continue;
+ }
+ if (tokenSeparator.TokenType == TokenType.String) {
+ // CHANGE3 :
+ isSingleQuoteString = (c == '\'');
+ if (context.LastToken != null
+ && context.LastToken.TokenType == TokenType.OpeningEnumerable) {
+ // context.AppendToCurrentToken(c); // Praveen's change of 10/28/2015
+ context.ToggleIsInString();
+ continue;
+ }
+ if (context.LastToken != null && context.LastToken.TokenType == TokenType.String) {
+ context.AddToken(
+ !context.CurrentTokenHasValue
+ ? new(string.Empty, TokenType.StringContent)
+ : new Token(context.CurrentToken, TokenType.StringContent));
+ }
+ context.AddToken(new("\"", TokenType.String));
+ context.ToggleIsInString();
+ context.NewToken();
+ continue;
+ }
+ if (context.CurrentTokenHasValue) {
+ if (Regex.IsMatch(context.CurrentToken, "^\"*$")) {
+ context.AddToken(_tokenFactory.Create(context.CurrentToken, TokenType.StringContent));
+ } else {
+ context.AddToken(CreateToken(context, worksheet));
+ }
+
+ //If the a next token is an opening parantheses and the previous token is interpeted as an address or name, then the currenct token is a function
+ if (tokenSeparator.TokenType == TokenType.OpeningParenthesis
+ && (context.LastToken.TokenType == TokenType.ExcelAddress
+ || context.LastToken.TokenType == TokenType.NameValue)) {
+ context.LastToken.TokenType = TokenType.Function;
+ }
+ }
+ if (tokenSeparator.Value == "-") {
+ if (TokenIsNegator(context)) {
+ context.AddToken(new("-", TokenType.Negator));
+ continue;
+ }
+ }
+ context.AddToken(tokenSeparator);
+ context.NewToken();
+ continue;
+ }
+ context.AppendToCurrentToken(c);
+ }
+ if (context.CurrentTokenHasValue) {
+ context.AddToken(CreateToken(context, worksheet));
+ }
+
+ CleanupTokens(context, _tokenProvider.Tokens);
+
+ return context.Result;
+ }
+
+ private static bool IsDoubleQuote(
+ Token tokenSeparator,
+ int formulaCharIndex,
+ TokenizerContext context) {
+ return tokenSeparator.TokenType == TokenType.String
+ && formulaCharIndex + 1 < context.FormulaChars.Length
+ && context.FormulaChars[formulaCharIndex + 1] == '\"';
+ }
+
+ private static void CleanupTokens(TokenizerContext context, IDictionary<string, Token> tokens) {
+ for (int i = 0; i < context.Result.Count; i++) {
+ var token = context.Result[i];
+ if (token.TokenType == TokenType.Unrecognized) {
+ if (i < context.Result.Count - 1) {
+ if (context.Result[i + 1].TokenType == TokenType.OpeningParenthesis) {
+ token.TokenType = TokenType.Function;
+ } else {
+ token.TokenType = TokenType.NameValue;
+ }
+ } else {
+ token.TokenType = TokenType.NameValue;
+ }
+ } else if (token.TokenType == TokenType.Function) {
+ if (i < context.Result.Count - 1) {
+ if (context.Result[i + 1].TokenType == TokenType.OpeningParenthesis) {
+ token.TokenType = TokenType.Function;
+ } else {
+ token.TokenType = TokenType.Unrecognized;
+ }
+ } else {
+ token.TokenType = TokenType.Unrecognized;
+ }
+ } else if ((token.TokenType == TokenType.Operator || token.TokenType == TokenType.Negator)
+ && i < context.Result.Count - 1
+ && (token.Value == "+" || token.Value == "-")) {
+ if (i > 0
+ && token.Value
+ == "+") //Remove any + with an opening parenthesis before.
+ {
+ if (context.Result[i - 1].TokenType == TokenType.OpeningParenthesis) {
+ context.Result.RemoveAt(i);
+ SetNegatorOperator(context, i, tokens);
+ i--;
+ continue;
+ }
+ }
+
+ var nextToken = context.Result[i + 1];
+ if (nextToken.TokenType == TokenType.Operator || nextToken.TokenType == TokenType.Negator) {
+ if (token.Value == "+" && (nextToken.Value == "+" || nextToken.Value == "-")) {
+ //Remove first
+ context.Result.RemoveAt(i);
+ SetNegatorOperator(context, i, tokens);
+ i--;
+ } else if (token.Value == "-" && nextToken.Value == "+") {
+ //Remove second
+ context.Result.RemoveAt(i + 1);
+ SetNegatorOperator(context, i, tokens);
+ i--;
+ } else if (token.Value == "-" && nextToken.Value == "-") {
+ //Remove first and set operator to +
+ context.Result.RemoveAt(i);
+ if (i == 0) {
+ context.Result.RemoveAt(i + 1);
+ i += 2;
+ } else {
+ //context.Result[i].TokenType = TokenType.Operator;
+ //context.Result[i].Value = "+";
+ context.Result[i] = tokens["+"];
+ SetNegatorOperator(context, i, tokens);
+ i--;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static void SetNegatorOperator(
+ TokenizerContext context,
+ int i,
+ IDictionary<string, Token> tokens) {
+ if (context.Result[i].Value == "-"
+ && i > 0
+ && (context.Result[i].TokenType == TokenType.Operator
+ || context.Result[i].TokenType == TokenType.Negator)) {
+ if (TokenIsNegator(context.Result[i - 1])) {
+ context.Result[i] = new("-", TokenType.Negator);
+ } else {
+ context.Result[i] = tokens["-"];
+ }
+ }
+ }
+
+ private static bool TokenIsNegator(TokenizerContext context) {
+ return TokenIsNegator(context.LastToken);
+ }
+
+ private static bool TokenIsNegator(Token t) {
+ return t == null
+ || t.TokenType == TokenType.Operator
+ || t.TokenType == TokenType.OpeningParenthesis
+ || t.TokenType == TokenType.Comma
+ || t.TokenType == TokenType.SemiColon
+ || t.TokenType == TokenType.OpeningEnumerable;
+ }
+
+ private bool IsPartOfMultipleCharSeparator(TokenizerContext context, char c) {
+ var lastToken = context.LastToken != null ? context.LastToken.Value : string.Empty;
+ return _tokenProvider.IsOperator(lastToken)
+ && _tokenProvider.IsPossibleLastPartOfMultipleCharOperator(
+ c.ToString(CultureInfo.InvariantCulture))
+ && !context.CurrentTokenHasValue;
+ }
+
+ private Token CreateToken(TokenizerContext context, string worksheet) {
+ if (context.CurrentToken == "-") {
+ if (context.LastToken == null && context.LastToken.TokenType == TokenType.Operator) {
+ return new("-", TokenType.Negator);
+ }
+ }
+ return _tokenFactory.Create(context.Result, context.CurrentToken, worksheet);
+ }
+
+ private bool CharIsTokenSeparator(char c, out Token token) {
+ var result = _tokenProvider.Tokens.ContainsKey(c.ToString());
+ token = result ? token = _tokenProvider.Tokens[c.ToString()] : null;
+ return result;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/LexicalAnalysis/SyntacticAnalyzer.cs b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/SyntacticAnalyzer.cs
new file mode 100644
index 0000000..fe25778
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/SyntacticAnalyzer.cs
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class SyntacticAnalyzer : ISyntacticAnalyzer {
+ private class AnalyzingContext {
+ public int NumberOfOpenedParentheses { get; set; }
+
+ public int NumberOfClosedParentheses { get; set; }
+
+ public int OpenedStrings { get; set; }
+
+ public int ClosedStrings { get; set; }
+
+ public bool IsInString { get; set; }
+ }
+
+ public void Analyze(IEnumerable<Token> tokens) {
+ var context = new AnalyzingContext();
+ foreach (var token in tokens) {
+ if (token.TokenType == TokenType.Unrecognized) {
+ throw new UnrecognizedTokenException(token);
+ }
+ EnsureParenthesesAreWellFormed(token, context);
+ EnsureStringsAreWellFormed(token, context);
+ }
+ Validate(context);
+ }
+
+ private static void Validate(AnalyzingContext context) {
+ if (context.NumberOfOpenedParentheses != context.NumberOfClosedParentheses) {
+ throw new FormatException("Number of opened and closed parentheses does not match");
+ }
+ if (context.OpenedStrings != context.ClosedStrings) {
+ throw new FormatException("Unterminated string");
+ }
+ }
+
+ private void EnsureParenthesesAreWellFormed(Token token, AnalyzingContext context) {
+ if (token.TokenType == TokenType.OpeningParenthesis) {
+ context.NumberOfOpenedParentheses++;
+ } else if (token.TokenType == TokenType.ClosingParenthesis) {
+ context.NumberOfClosedParentheses++;
+ }
+ }
+
+ private void EnsureStringsAreWellFormed(Token token, AnalyzingContext context) {
+ if (!context.IsInString && token.TokenType == TokenType.String) {
+ context.IsInString = true;
+ context.OpenedStrings++;
+ } else if (context.IsInString && token.TokenType == TokenType.String) {
+ context.IsInString = false;
+ context.ClosedStrings++;
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/LexicalAnalysis/Token.cs b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/Token.cs
new file mode 100644
index 0000000..c4d1977
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/Token.cs
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public class Token {
+ public Token(string token, TokenType tokenType) {
+ Value = token;
+ TokenType = tokenType;
+ }
+
+ public string Value { get; internal set; }
+
+ public TokenType TokenType { get; internal set; }
+
+ public void Append(string stringToAppend) {
+ Value += stringToAppend;
+ }
+
+ public bool IsNegated { get; private set; }
+
+ public void Negate() {
+ if (TokenType == TokenType.Decimal
+ || TokenType == TokenType.Integer
+ || TokenType == TokenType.ExcelAddress) {
+ IsNegated = true;
+ }
+ }
+
+ public override string ToString() {
+ return TokenType + ", " + Value;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/LexicalAnalysis/TokenFactory.cs b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/TokenFactory.cs
new file mode 100644
index 0000000..1dd3084
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/TokenFactory.cs
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ * Jan Källman Replaced Adress validate 2013-03-01
+ * *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AppsheetEpplus;
+
+public class TokenFactory : ITokenFactory {
+ public TokenFactory(
+ IFunctionNameProvider functionRepository,
+ INameValueProvider nameValueProvider)
+ : this(new TokenSeparatorProvider(), nameValueProvider, functionRepository) {}
+
+ public TokenFactory(
+ ITokenSeparatorProvider tokenSeparatorProvider,
+ INameValueProvider nameValueProvider,
+ IFunctionNameProvider functionNameProvider) {
+ _tokenSeparatorProvider = tokenSeparatorProvider;
+ _functionNameProvider = functionNameProvider;
+ _nameValueProvider = nameValueProvider;
+ }
+
+ private readonly ITokenSeparatorProvider _tokenSeparatorProvider;
+ private readonly IFunctionNameProvider _functionNameProvider;
+ private readonly INameValueProvider _nameValueProvider;
+
+ public Token Create(IEnumerable<Token> tokens, string token) {
+ return Create(tokens, token, null);
+ }
+
+ public Token Create(IEnumerable<Token> tokens, string token, string worksheet) {
+ if (_tokenSeparatorProvider.Tokens.TryGetValue(token, out var tokenSeparator)) {
+ return tokenSeparator;
+ }
+ var tokenList = (IList<Token>)tokens;
+ //Address with worksheet-string before /JK
+ if (token.StartsWith("!") && tokenList[tokenList.Count - 1].TokenType == TokenType.String) {
+ var i = tokenList.Count - 2;
+ if (i > 0) {
+ string addr;
+ if (tokenList[i].TokenType == TokenType.StringContent) {
+ addr = "'" + tokenList[i].Value.Replace("'", "''") + "'";
+ } else {
+ throw (new ArgumentException(
+ string.Format("Invalid formula token sequence near {0}", token)));
+ }
+ //Remove the string tokens and content
+ tokenList.RemoveAt(tokenList.Count - 1);
+ tokenList.RemoveAt(tokenList.Count - 1);
+ tokenList.RemoveAt(tokenList.Count - 1);
+
+ return new(addr + token, TokenType.ExcelAddress);
+ }
+ throw (new ArgumentException(
+ string.Format("Invalid formula token sequence near {0}", token)));
+ }
+
+ if (tokens.Any() && tokens.Last().TokenType == TokenType.String) {
+ return new(token, TokenType.StringContent);
+ }
+ if (!string.IsNullOrEmpty(token)) {
+ token = token.Trim();
+ }
+ if (Regex.IsMatch(token, RegexConstants.Decimal)) {
+ return new(token, TokenType.Decimal);
+ }
+ if (Regex.IsMatch(token, RegexConstants.Integer)) {
+ return new(token, TokenType.Integer);
+ }
+ if (Regex.IsMatch(token, RegexConstants.Boolean, RegexOptions.IgnoreCase)) {
+ return new(token, TokenType.Boolean);
+ }
+ if (token.ToUpper(CultureInfo.InvariantCulture).Contains("#REF!")) {
+ return new(token, TokenType.InvalidReference);
+ }
+ if (token.ToUpper(CultureInfo.InvariantCulture) == "#NUM!") {
+ return new(token, TokenType.NumericError);
+ }
+ if (token.ToUpper(CultureInfo.InvariantCulture) == "#VALUE!") {
+ return new(token, TokenType.ValueDataTypeError);
+ }
+ if (token.ToUpper(CultureInfo.InvariantCulture) == "#NULL!") {
+ return new(token, TokenType.Null);
+ }
+ if (_nameValueProvider != null && _nameValueProvider.IsNamedValue(token, worksheet)) {
+ return new(token, TokenType.NameValue);
+ }
+ if (_functionNameProvider.IsFunctionName(token)) {
+ return new(token, TokenType.Function);
+ }
+ if (tokenList.Count > 0
+ && tokenList[tokenList.Count - 1].TokenType == TokenType.OpeningEnumerable) {
+ return new(token, TokenType.Enumerable);
+ }
+ var at = ExcelAddressBase.IsValid(token);
+ if (at == ExcelAddressBase.AddressType.InternalAddress) {
+ return new(token.ToUpper(CultureInfo.InvariantCulture), TokenType.ExcelAddress);
+ }
+ return new(token, TokenType.Unrecognized);
+ }
+
+ public Token Create(string token, TokenType explicitTokenType) {
+ return new(token, explicitTokenType);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/LexicalAnalysis/TokenSeparatorProvider.cs b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/TokenSeparatorProvider.cs
new file mode 100644
index 0000000..ceeb6a8
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/TokenSeparatorProvider.cs
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+public class TokenSeparatorProvider : ITokenSeparatorProvider {
+ private static readonly Dictionary<string, Token> _tokens = new();
+
+ static TokenSeparatorProvider() {
+ _tokens.Add("+", new("+", TokenType.Operator));
+ _tokens.Add("-", new("-", TokenType.Operator));
+ _tokens.Add("*", new("*", TokenType.Operator));
+ _tokens.Add("/", new("/", TokenType.Operator));
+ _tokens.Add("^", new("^", TokenType.Operator));
+ _tokens.Add("&", new("&", TokenType.Operator));
+ _tokens.Add(">", new(">", TokenType.Operator));
+ _tokens.Add("<", new("<", TokenType.Operator));
+ _tokens.Add("=", new("=", TokenType.Operator));
+ _tokens.Add("<=", new("<=", TokenType.Operator));
+ _tokens.Add(">=", new(">=", TokenType.Operator));
+ _tokens.Add("<>", new("<>", TokenType.Operator));
+ _tokens.Add("(", new("(", TokenType.OpeningParenthesis));
+ _tokens.Add(")", new(")", TokenType.ClosingParenthesis));
+ _tokens.Add("{", new("{", TokenType.OpeningEnumerable));
+ _tokens.Add("}", new("}", TokenType.ClosingEnumerable));
+ _tokens.Add("'", new("'", TokenType.String));
+ _tokens.Add("\"", new("\"", TokenType.String));
+ _tokens.Add(",", new(",", TokenType.Comma));
+ _tokens.Add(";", new(";", TokenType.SemiColon));
+ _tokens.Add("[", new("[", TokenType.OpeningBracket));
+ _tokens.Add("]", new("]", TokenType.ClosingBracket));
+ _tokens.Add("%", new("%", TokenType.Percent));
+ }
+
+ IDictionary<string, Token> ITokenSeparatorProvider.Tokens => _tokens;
+
+ public bool IsOperator(string item) {
+ if (_tokens.TryGetValue(item, out var token)) {
+ if (token.TokenType == TokenType.Operator) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool IsPossibleLastPartOfMultipleCharOperator(string part) {
+ return part == "=" || part == ">";
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/LexicalAnalysis/TokenType.cs b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/TokenType.cs
new file mode 100644
index 0000000..0d0e1ff
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/TokenType.cs
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public enum TokenType {
+ Operator,
+ Negator,
+ OpeningParenthesis,
+ ClosingParenthesis,
+ OpeningEnumerable,
+ ClosingEnumerable,
+ OpeningBracket,
+ ClosingBracket,
+ Enumerable,
+ Comma,
+ SemiColon,
+ String,
+ StringContent,
+ Integer,
+ Boolean,
+ Decimal,
+ Percent,
+ Function,
+ ExcelAddress,
+ NameValue,
+ InvalidReference,
+ NumericError,
+ ValueDataTypeError,
+ Null,
+ Unrecognized,
+}
diff --git a/AppsheetEpplus/FormulaParsing/LexicalAnalysis/TokenizerContext.cs b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/TokenizerContext.cs
new file mode 100644
index 0000000..04ee516
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/LexicalAnalysis/TokenizerContext.cs
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace AppsheetEpplus;
+
+public class TokenizerContext {
+ public TokenizerContext(string formula) {
+ if (!string.IsNullOrEmpty(formula)) {
+ _chars = formula.ToArray();
+ }
+ }
+
+ private readonly char[] _chars;
+ private readonly List<Token> _result = new();
+ private StringBuilder _currentToken = new();
+
+ public char[] FormulaChars => _chars;
+
+ public IList<Token> Result => _result;
+
+ public bool IsInString { get; private set; }
+
+ public void ToggleIsInString() {
+ IsInString = !IsInString;
+ }
+
+ internal int BracketCount { get; set; }
+
+ public string CurrentToken => _currentToken.ToString();
+
+ public bool CurrentTokenHasValue =>
+ !string.IsNullOrEmpty(IsInString ? CurrentToken : CurrentToken.Trim());
+
+ public void NewToken() {
+ _currentToken = new();
+ }
+
+ public void AddToken(Token token) {
+ _result.Add(token);
+ }
+
+ public void AppendToCurrentToken(char c) {
+ _currentToken.Append(c.ToString());
+ }
+
+ public void AppendToLastToken(string stringToAppend) {
+ _result.Last().Append(stringToAppend);
+ }
+
+ public void SetLastTokenType(TokenType type) {
+ _result.Last().TokenType = type;
+ }
+
+ public void ReplaceLastToken(Token newToken) {
+ var count = _result.Count;
+ if (count > 0) {
+ _result.RemoveAt(count - 1);
+ }
+ _result.Add(newToken);
+ }
+
+ public Token LastToken => _result.Count > 0 ? _result.Last() : null;
+}
diff --git a/AppsheetEpplus/FormulaParsing/Logging/IFormulaParserLogger.cs b/AppsheetEpplus/FormulaParsing/Logging/IFormulaParserLogger.cs
new file mode 100644
index 0000000..26d5eb2
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Logging/IFormulaParserLogger.cs
@@ -0,0 +1,46 @@
+using System;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Used for logging during FormulaParsing
+/// </summary>
+public interface IFormulaParserLogger : IDisposable {
+ /// <summary>
+ /// Called each time an exception occurs during formula parsing.
+ /// </summary>
+ /// <param name="context"></param>
+ /// <param name="ex"></param>
+ void Log(ParsingContext context, Exception ex);
+
+ /// <summary>
+ /// Called each time information should be logged during formula parsing.
+ /// </summary>
+ /// <param name="context"></param>
+ /// <param name="message"></param>
+ void Log(ParsingContext context, string message);
+
+ /// <summary>
+ /// Called to log a message outside the parsing context.
+ /// </summary>
+ /// <param name="message"></param>
+ void Log(string message);
+
+ /// <summary>
+ /// Called each time a cell within the calc chain is accessed during formula parsing.
+ /// </summary>
+ void LogCellCounted();
+
+ /// <summary>
+ /// Called each time a function is called during formula parsing.
+ /// </summary>
+ /// <param name="func"></param>
+ void LogFunction(string func);
+
+ /// <summary>
+ /// Some functions measure performance, if so this function will be called.
+ /// </summary>
+ /// <param name="func"></param>
+ /// <param name="milliseconds"></param>
+ void LogFunction(string func, long milliseconds);
+}
diff --git a/AppsheetEpplus/FormulaParsing/NameValueProvider.cs b/AppsheetEpplus/FormulaParsing/NameValueProvider.cs
new file mode 100644
index 0000000..6716063
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/NameValueProvider.cs
@@ -0,0 +1,17 @@
+namespace AppsheetEpplus;
+
+public class NameValueProvider : INameValueProvider {
+ private NameValueProvider() {}
+
+ public static INameValueProvider Empty => new NameValueProvider();
+
+ public bool IsNamedValue(string key, string worksheet) {
+ return false;
+ }
+
+ public object GetNamedValue(string key) {
+ return null;
+ }
+
+ public void Reload() {}
+}
diff --git a/AppsheetEpplus/FormulaParsing/ParsedValue.cs b/AppsheetEpplus/FormulaParsing/ParsedValue.cs
new file mode 100644
index 0000000..9671d80
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ParsedValue.cs
@@ -0,0 +1,15 @@
+namespace AppsheetEpplus;
+
+public class ParsedValue {
+ public ParsedValue(object val, int rowIndex, int colIndex) {
+ Value = val;
+ RowIndex = rowIndex;
+ ColIndex = colIndex;
+ }
+
+ public object Value { get; private set; }
+
+ public int RowIndex { get; private set; }
+
+ public int ColIndex { get; private set; }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ParsingConfiguration.cs b/AppsheetEpplus/FormulaParsing/ParsingConfiguration.cs
new file mode 100644
index 0000000..e28f9df
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ParsingConfiguration.cs
@@ -0,0 +1,54 @@
+namespace AppsheetEpplus;
+
+public class ParsingConfiguration {
+ public virtual ILexer Lexer { get; private set; }
+
+ public IFormulaParserLogger Logger { get; private set; }
+
+ public IExpressionGraphBuilder GraphBuilder { get; private set; }
+
+ public IExpressionCompiler ExpressionCompiler { get; private set; }
+
+ public FunctionRepository FunctionRepository { get; private set; } = FunctionRepository.Create();
+
+ private ParsingConfiguration() {}
+
+ internal static ParsingConfiguration Create() {
+ return new();
+ }
+
+ public ParsingConfiguration SetLexer(ILexer lexer) {
+ Lexer = lexer;
+ return this;
+ }
+
+ public ParsingConfiguration SetGraphBuilder(IExpressionGraphBuilder graphBuilder) {
+ GraphBuilder = graphBuilder;
+ return this;
+ }
+
+ public ParsingConfiguration SetExpresionCompiler(IExpressionCompiler expressionCompiler) {
+ ExpressionCompiler = expressionCompiler;
+ return this;
+ }
+
+ /// <summary>
+ /// Attaches a logger, errors and log entries will be written to the logger during the parsing process.
+ /// </summary>
+ /// <param name="logger"></param>
+ /// <returns></returns>
+ public ParsingConfiguration AttachLogger(IFormulaParserLogger logger) {
+ Require.That(logger).Named("logger").IsNotNull();
+ Logger = logger;
+ return this;
+ }
+
+ /// <summary>
+ /// if a logger is attached it will be removed.
+ /// </summary>
+ /// <returns></returns>
+ public ParsingConfiguration DetachLogger() {
+ Logger = null;
+ return this;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ParsingContext.cs b/AppsheetEpplus/FormulaParsing/ParsingContext.cs
new file mode 100644
index 0000000..629ea91
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ParsingContext.cs
@@ -0,0 +1,57 @@
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Parsing context
+/// </summary>
+public class ParsingContext : IParsingLifetimeEventHandler {
+ private ParsingContext() {}
+
+ /// <summary>
+ /// The <see cref="FormulaParser"/> of the current context.
+ /// </summary>
+ public FormulaParser Parser { get; set; }
+
+ /// <summary>
+ /// The <see cref="ExcelDataProvider"/> is an abstraction on top of
+ /// Excel, in this case EPPlus.
+ /// </summary>
+ public ExcelDataProvider ExcelDataProvider { get; set; }
+
+ /// <summary>
+ /// Utility for handling addresses
+ /// </summary>
+ public RangeAddressFactory RangeAddressFactory { get; set; }
+
+ /// <summary>
+ /// <see cref="INameValueProvider"/> of the current context
+ /// </summary>
+ public INameValueProvider NameValueProvider { get; set; }
+
+ /// <summary>
+ /// Configuration
+ /// </summary>
+ public ParsingConfiguration Configuration { get; set; }
+
+ /// <summary>
+ /// Scopes, a scope represents the parsing of a cell or a value.
+ /// </summary>
+ public ParsingScopes Scopes { get; private set; }
+
+ /// <summary>
+ /// Returns true if a <see cref="IFormulaParserLogger"/> is attached to the parser.
+ /// </summary>
+ public bool Debug => Configuration.Logger != null;
+
+ /// <summary>
+ /// Factory method.
+ /// </summary>
+ /// <returns></returns>
+ public static ParsingContext Create() {
+ var context = new ParsingContext();
+ context.Configuration = ParsingConfiguration.Create();
+ context.Scopes = new(context);
+ return context;
+ }
+
+ void IParsingLifetimeEventHandler.ParsingCompleted() {}
+}
diff --git a/AppsheetEpplus/FormulaParsing/ParsingScope.cs b/AppsheetEpplus/FormulaParsing/ParsingScope.cs
new file mode 100644
index 0000000..9b4783f
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ParsingScope.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Represents a parsing of a single input or workbook addrses.
+/// </summary>
+public class ParsingScope : IDisposable {
+ private readonly ParsingScopes _parsingScopes;
+
+ public ParsingScope(ParsingScopes parsingScopes, RangeAddress address)
+ : this(parsingScopes, null, address) {}
+
+ public ParsingScope(ParsingScopes parsingScopes, ParsingScope parent, RangeAddress address) {
+ _parsingScopes = parsingScopes;
+ Parent = parent;
+ Address = address;
+ }
+
+ /// <summary>
+ /// Id of the scope.
+ /// </summary>
+ public Guid ScopeId { get; private set; } = Guid.NewGuid();
+
+ /// <summary>
+ /// The calling scope.
+ /// </summary>
+ public ParsingScope Parent { get; private set; }
+
+ /// <summary>
+ /// The address of the cell currently beeing parsed.
+ /// </summary>
+ public RangeAddress Address { get; private set; }
+
+ /// <summary>
+ /// True if the current scope is a Subtotal function beeing executed.
+ /// </summary>
+ public bool IsSubtotal { get; set; }
+
+ public void Dispose() {
+ _parsingScopes.KillScope(this);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/ParsingScopes.cs b/AppsheetEpplus/FormulaParsing/ParsingScopes.cs
new file mode 100644
index 0000000..b500902
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/ParsingScopes.cs
@@ -0,0 +1,50 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// This class implements a stack on which instances of <see cref="ParsingScope"/>
+/// are put. Each ParsingScope represents the parsing of an address in the workbook.
+/// </summary>
+public class ParsingScopes {
+ private readonly IParsingLifetimeEventHandler _lifetimeEventHandler;
+
+ public ParsingScopes(IParsingLifetimeEventHandler lifetimeEventHandler) {
+ _lifetimeEventHandler = lifetimeEventHandler;
+ }
+
+ private readonly Stack<ParsingScope> _scopes = new();
+
+ /// <summary>
+ /// Creates a new <see cref="ParsingScope"/> and puts it on top of the stack.
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public virtual ParsingScope NewScope(RangeAddress address) {
+ ParsingScope scope;
+ if (_scopes.Count() > 0) {
+ scope = new(this, _scopes.Peek(), address);
+ } else {
+ scope = new(this, address);
+ }
+ _scopes.Push(scope);
+ return scope;
+ }
+
+ /// <summary>
+ /// The current parsing scope.
+ /// </summary>
+ public virtual ParsingScope Current => _scopes.Count() > 0 ? _scopes.Peek() : null;
+
+ /// <summary>
+ /// Removes the current scope, setting the calling scope to current.
+ /// </summary>
+ /// <param name="parsingScope"></param>
+ public virtual void KillScope(ParsingScope parsingScope) {
+ _scopes.Pop();
+ if (_scopes.Count() == 0) {
+ _lifetimeEventHandler.ParsingCompleted();
+ }
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Utilities/ArgumentInfo.cs b/AppsheetEpplus/FormulaParsing/Utilities/ArgumentInfo.cs
new file mode 100644
index 0000000..a06f5c9
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Utilities/ArgumentInfo.cs
@@ -0,0 +1,16 @@
+namespace AppsheetEpplus;
+
+public class ArgumentInfo<T> {
+ public ArgumentInfo(T val) {
+ Value = val;
+ }
+
+ public T Value { get; private set; }
+
+ public string Name { get; private set; }
+
+ public ArgumentInfo<T> Named(string argName) {
+ Name = argName;
+ return this;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Utilities/ExtensionMethods.cs b/AppsheetEpplus/FormulaParsing/Utilities/ExtensionMethods.cs
new file mode 100644
index 0000000..5afb886
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Utilities/ExtensionMethods.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace AppsheetEpplus;
+
+public static class ExtensionMethods {
+ public static void IsNotNullOrEmpty(this ArgumentInfo<string> val) {
+ if (string.IsNullOrEmpty(val.Value)) {
+ throw new ArgumentException(val.Name + " cannot be null or empty");
+ }
+ }
+
+ public static void IsNotNull<T>(this ArgumentInfo<T> val)
+ where T : class {
+ if (val.Value == null) {
+ throw new ArgumentNullException(val.Name);
+ }
+ }
+
+ public static bool IsNumeric(this object obj) {
+ if (obj == null) {
+ return false;
+ }
+ return (obj.GetType().IsPrimitive
+ || obj is double
+ || obj is decimal
+ || obj is DateTime
+ || obj is TimeSpan);
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Utilities/IdProvider.cs b/AppsheetEpplus/FormulaParsing/Utilities/IdProvider.cs
new file mode 100644
index 0000000..53bcbdf
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Utilities/IdProvider.cs
@@ -0,0 +1,5 @@
+namespace AppsheetEpplus;
+
+public abstract class IdProvider {
+ public abstract object NewId();
+}
diff --git a/AppsheetEpplus/FormulaParsing/Utilities/IntegerIdProvider.cs b/AppsheetEpplus/FormulaParsing/Utilities/IntegerIdProvider.cs
new file mode 100644
index 0000000..76eab29
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Utilities/IntegerIdProvider.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace AppsheetEpplus;
+
+public class IntegerIdProvider : IdProvider {
+ private int _lastId = int.MinValue;
+
+ public override object NewId() {
+ if (_lastId >= int.MaxValue) {
+ throw new InvalidOperationException("IdProvider run out of id:s");
+ }
+ return _lastId++;
+ }
+}
diff --git a/AppsheetEpplus/FormulaParsing/Utilities/RegexConstants.cs b/AppsheetEpplus/FormulaParsing/Utilities/RegexConstants.cs
new file mode 100644
index 0000000..ca515a7
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Utilities/RegexConstants.cs
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+public static class RegexConstants {
+ public const string SingleCellAddress =
+ @"^(('[^/\\?*\[\]]{1,31}'|[A-Za-z_]{1,31})!)?[A-Z]{1,3}[1-9]{1}[0-9]{0,7}$";
+
+ //Changed JK 26/2-2013
+ public const string ExcelAddress =
+ @"^(('[^/\\?*\[\]]{1,31}'|[A-Za-z_]{1,31})!)?[\$]{0,1}([A-Z]|[A-Z]{1,3}[\$]{0,1}[1-9]{1}[0-9]{0,7})(\:({0,1}[A-Z]|[A-Z]{1,3}[\$]{0,1}[1-9]{1}[0-9]{0,7})){0,1}$";
+
+ //public const string ExcelAddress = @"^([\$]{0,1}([A-Z]{1,3}[\$]{0,1}[0-9]{1,7})(\:([\$]{0,1}[A-Z]{1,3}[\$]{0,1}[0-9]{1,7}){0,1})|([\$]{0,1}[A-Z]{1,3}\:[\$]{0,1}[A-Z]{1,3})|([\$]{0,1}[0-9]{1,7}\:[\$]{0,1}[0-9]{1,7}))$";
+ public const string Boolean = "^(true|false)$";
+ public const string Decimal = @"^[0-9]+\.[0-9]+$";
+ public const string Integer = "^[0-9]+$";
+}
diff --git a/AppsheetEpplus/FormulaParsing/Utilities/Require.cs b/AppsheetEpplus/FormulaParsing/Utilities/Require.cs
new file mode 100644
index 0000000..732bd27
--- /dev/null
+++ b/AppsheetEpplus/FormulaParsing/Utilities/Require.cs
@@ -0,0 +1,7 @@
+namespace AppsheetEpplus;
+
+public static class Require {
+ public static ArgumentInfo<T> That<T>(T arg) {
+ return new(arg);
+ }
+}
diff --git a/AppsheetEpplus/IRangeID.cs b/AppsheetEpplus/IRangeID.cs
new file mode 100644
index 0000000..f100426
--- /dev/null
+++ b/AppsheetEpplus/IRangeID.cs
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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 2010-02-04
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Id from a cell, column or row.
+/// </summary>
+internal interface IRangeId {
+ /// <summary>
+ /// This is the id for a cell, row or column.
+ /// The id is a composit of the SheetID, the row number and the column number.
+ /// Bit 1-14 SheetID, Bit 15-28 Column number (0 if entire column), Bit 29- Row number (0 if entire row).
+ /// </summary>
+ ulong RangeID { get; set; }
+}
diff --git a/AppsheetEpplus/OfficeProperties.cs b/AppsheetEpplus/OfficeProperties.cs
new file mode 100644
index 0000000..95e30c1
--- /dev/null
+++ b/AppsheetEpplus/OfficeProperties.cs
@@ -0,0 +1,265 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan K�llman Total rewrite 2010-03-01
+ * Jan K�llman License changed GPL-->LGPL 2011-12-27
+ * Raziq York Added Created & Modified 2014-08-20
+ *******************************************************************************/
+
+using System;
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Provides access to the properties bag of the package
+/// </summary>
+public sealed class OfficeProperties : XmlHelper {
+ private readonly XmlDocument _xmlPropertiesCore;
+ private readonly XmlDocument _xmlPropertiesExtended;
+
+ private readonly Uri _uriPropertiesCore = new("/docProps/core.xml", UriKind.Relative);
+ private readonly Uri _uriPropertiesExtended = new("/docProps/app.xml", UriKind.Relative);
+
+ private readonly XmlHelper _coreHelper;
+ private readonly XmlHelper _extendedHelper;
+
+ /// <summary>
+ /// Provides access to all the office document properties.
+ /// </summary>
+ /// <param name="package"></param>
+ /// <param name="ns"></param>
+ internal OfficeProperties(ExcelPackage package, XmlNamespaceManager ns)
+ : base(ns) {
+ const string coreBaseXml =
+ $"""<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><cp:coreProperties xmlns:cp="{ExcelPackage._schemaCore}" xmlns:dc="{ExcelPackage._schemaDc}" xmlns:dcterms="{ExcelPackage._schemaDcTerms}" xmlns:dcmitype="{ExcelPackage._schemaDcmiType}" xmlns:xsi="{ExcelPackage._schemaXsi}"></cp:coreProperties>""";
+ _xmlPropertiesCore = package.GetOrCreateXmlDocument(
+ _uriPropertiesCore,
+ "application/vnd.openxmlformats-package.core-properties+xml",
+ "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
+ coreBaseXml);
+ _coreHelper = XmlHelperFactory.Create(
+ ns,
+ _xmlPropertiesCore.SelectSingleNode("cp:coreProperties", NameSpaceManager));
+
+ const string extendedBaseXml =
+ $"""<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><Properties xmlns:vt="{ExcelPackage._schemaVt}" xmlns="{ExcelPackage._schemaExtended}"></Properties>""";
+ _xmlPropertiesExtended = package.GetOrCreateXmlDocument(
+ _uriPropertiesExtended,
+ "application/vnd.openxmlformats-officedocument.extended-properties+xml",
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
+ extendedBaseXml);
+ _extendedHelper = XmlHelperFactory.Create(ns, _xmlPropertiesExtended);
+ }
+
+ private const string _titlePath = "dc:title";
+
+ /// <summary>
+ /// Gets/sets the title property of the document (core property)
+ /// </summary>
+ public string Title {
+ get => _coreHelper.GetXmlNodeString(_titlePath);
+ set => _coreHelper.SetXmlNodeString(_titlePath, value);
+ }
+
+ private const string _subjectPath = "dc:subject";
+
+ /// <summary>
+ /// Gets/sets the subject property of the document (core property)
+ /// </summary>
+ public string Subject {
+ get => _coreHelper.GetXmlNodeString(_subjectPath);
+ set => _coreHelper.SetXmlNodeString(_subjectPath, value);
+ }
+
+ private const string _authorPath = "dc:creator";
+
+ /// <summary>
+ /// Gets/sets the author property of the document (core property)
+ /// </summary>
+ public string Author {
+ get => _coreHelper.GetXmlNodeString(_authorPath);
+ set => _coreHelper.SetXmlNodeString(_authorPath, value);
+ }
+
+ private const string _commentsPath = "dc:description";
+
+ /// <summary>
+ /// Gets/sets the comments property of the document (core property)
+ /// </summary>
+ public string Comments {
+ get => _coreHelper.GetXmlNodeString(_commentsPath);
+ set => _coreHelper.SetXmlNodeString(_commentsPath, value);
+ }
+
+ private const string _keywordsPath = "cp:keywords";
+
+ /// <summary>
+ /// Gets/sets the keywords property of the document (core property)
+ /// </summary>
+ public string Keywords {
+ get => _coreHelper.GetXmlNodeString(_keywordsPath);
+ set => _coreHelper.SetXmlNodeString(_keywordsPath, value);
+ }
+
+ private const string _lastModifiedByPath = "cp:lastModifiedBy";
+
+ /// <summary>
+ /// Gets/sets the lastModifiedBy property of the document (core property)
+ /// </summary>
+ public string LastModifiedBy {
+ get => _coreHelper.GetXmlNodeString(_lastModifiedByPath);
+ set => _coreHelper.SetXmlNodeString(_lastModifiedByPath, value);
+ }
+
+ private const string _lastPrintedPath = "cp:lastPrinted";
+
+ /// <summary>
+ /// Gets/sets the lastPrinted property of the document (core property)
+ /// </summary>
+ public string LastPrinted {
+ get => _coreHelper.GetXmlNodeString(_lastPrintedPath);
+ set => _coreHelper.SetXmlNodeString(_lastPrintedPath, value);
+ }
+
+ private const string _createdPath = "dcterms:created";
+
+ /// <summary>
+ /// Gets/sets the created property of the document (core property)
+ /// </summary>
+ public DateTime Created {
+ get =>
+ DateTime.TryParse(_coreHelper.GetXmlNodeString(_createdPath), out var date)
+ ? date
+ : DateTime.MinValue;
+ set {
+ var dateString = value.ToUniversalTime().ToString("s", CultureInfo.InvariantCulture) + "Z";
+ _coreHelper.SetXmlNodeString(_createdPath, dateString);
+ _coreHelper.SetXmlNodeString(_createdPath + "/@xsi:type", "dcterms:W3CDTF");
+ }
+ }
+
+ private const string _categoryPath = "cp:category";
+
+ /// <summary>
+ /// Gets/sets the category property of the document (core property)
+ /// </summary>
+ public string Category {
+ get => _coreHelper.GetXmlNodeString(_categoryPath);
+ set => _coreHelper.SetXmlNodeString(_categoryPath, value);
+ }
+
+ private const string _contentStatusPath = "cp:contentStatus";
+
+ /// <summary>
+ /// Gets/sets the status property of the document (core property)
+ /// </summary>
+ public string Status {
+ get => _coreHelper.GetXmlNodeString(_contentStatusPath);
+ set => _coreHelper.SetXmlNodeString(_contentStatusPath, value);
+ }
+
+ /// <summary>
+ /// Provides access to the XML document that holds the extended properties of the document (app.xml)
+ /// </summary>
+ public XmlDocument ExtendedPropertiesXml {
+ get {
+ if (_xmlPropertiesExtended == null) {}
+ return (_xmlPropertiesExtended);
+ }
+ }
+
+ private const string _applicationPath = "xp:Properties/xp:Application";
+
+ /// <summary>
+ /// Gets/Set the Application property of the document (extended property)
+ /// </summary>
+ public string Application {
+ get => _extendedHelper.GetXmlNodeString(_applicationPath);
+ set => _extendedHelper.SetXmlNodeString(_applicationPath, value);
+ }
+
+ private const string _hyperlinkBasePath = "xp:Properties/xp:HyperlinkBase";
+
+ /// <summary>
+ /// Gets/sets the HyperlinkBase property of the document (extended property)
+ /// </summary>
+ public Uri HyperlinkBase {
+ get => new(_extendedHelper.GetXmlNodeString(_hyperlinkBasePath), UriKind.Absolute);
+ set => _extendedHelper.SetXmlNodeString(_hyperlinkBasePath, value.AbsoluteUri);
+ }
+
+ private const string _appVersionPath = "xp:Properties/xp:AppVersion";
+
+ /// <summary>
+ /// Gets/Set the AppVersion property of the document (extended property)
+ /// </summary>
+ public string AppVersion {
+ get => _extendedHelper.GetXmlNodeString(_appVersionPath);
+ set => _extendedHelper.SetXmlNodeString(_appVersionPath, value);
+ }
+
+ private const string _companyPath = "xp:Properties/xp:Company";
+
+ /// <summary>
+ /// Gets/sets the Company property of the document (extended property)
+ /// </summary>
+ public string Company {
+ get => _extendedHelper.GetXmlNodeString(_companyPath);
+ set => _extendedHelper.SetXmlNodeString(_companyPath, value);
+ }
+
+ private const string _managerPath = "xp:Properties/xp:Manager";
+
+ /// <summary>
+ /// Gets/sets the Manager property of the document (extended property)
+ /// </summary>
+ public string Manager {
+ get => _extendedHelper.GetXmlNodeString(_managerPath);
+ set => _extendedHelper.SetXmlNodeString(_managerPath, value);
+ }
+
+ private const string _modifiedPath = "dcterms:modified";
+
+ /// <summary>
+ /// Gets/sets the modified property of the document (core property)
+ /// </summary>
+ public DateTime Modified {
+ get =>
+ DateTime.TryParse(_coreHelper.GetXmlNodeString(_modifiedPath), out var date)
+ ? date
+ : DateTime.MinValue;
+ set {
+ var dateString = value.ToUniversalTime().ToString("s", CultureInfo.InvariantCulture) + "Z";
+ _coreHelper.SetXmlNodeString(_modifiedPath, dateString);
+ _coreHelper.SetXmlNodeString(_modifiedPath + "/@xsi:type", "dcterms:W3CDTF");
+ }
+ }
+}
diff --git a/AppsheetEpplus/Packaging/ZipPackage.cs b/AppsheetEpplus/Packaging/ZipPackage.cs
new file mode 100644
index 0000000..444b4d0
--- /dev/null
+++ b/AppsheetEpplus/Packaging/ZipPackage.cs
@@ -0,0 +1,262 @@
+/*******************************************************************************
+ * 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 25-Oct-2012
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Specifies whether the target is inside or outside the System.IO.Packaging.Package.
+/// </summary>
+public enum TargetMode {
+ /// <summary>
+ /// The relationship references a part that is inside the package.
+ /// </summary>
+ Internal = 0,
+
+ /// <summary>
+ /// The relationship references a resource that is external to the package.
+ /// </summary>
+ External = 1,
+}
+
+/// <summary>
+/// Represent an OOXML Zip package.
+/// </summary>
+internal class ZipPackage : ZipPackageRelationshipBase {
+ internal class ContentType {
+ internal string Name;
+ internal bool IsExtension;
+ internal string Match;
+
+ public ContentType(string name, bool isExtension, string match) {
+ Name = name;
+ IsExtension = isExtension;
+ Match = match;
+ }
+ }
+
+ private readonly Dictionary<string, ZipPackagePart> Parts = new(
+ StringComparer.InvariantCultureIgnoreCase);
+ internal Dictionary<string, ContentType> _contentTypes = new(
+ StringComparer.InvariantCultureIgnoreCase);
+
+ internal ZipPackage() {
+ AddNew();
+ }
+
+ private void AddNew() {
+ _contentTypes.Add("xml", new(ExcelPackage._schemaXmlExtension, true, "xml"));
+ _contentTypes.Add("rels", new(ExcelPackage._schemaRelsExtension, true, "rels"));
+ }
+
+ internal ZipPackage(Stream stream) {
+ bool hasContentTypeXml = false;
+ if (stream == null || stream.Length == 0) {
+ AddNew();
+ } else {
+ var rels = new Dictionary<string, ZipArchiveEntry>();
+ stream.Seek(0, SeekOrigin.Begin);
+ using var zip = new ZipArchive(stream, ZipArchiveMode.Read, leaveOpen: true);
+ foreach (var e in zip.Entries) {
+ if (e.Length > 0) {
+ if (e.FullName.Equals(
+ "[content_types].xml",
+ StringComparison.InvariantCultureIgnoreCase)) {
+ using var inputStream = e.Open();
+ AddContentTypes(inputStream);
+ hasContentTypeXml = true;
+ } else if (e.FullName.Equals(
+ "_rels/.rels",
+ StringComparison.InvariantCultureIgnoreCase)) {
+ using var inputStream = e.Open();
+ ReadRelation(inputStream, "");
+ } else {
+ if (e.FullName.EndsWith(".rels", StringComparison.InvariantCultureIgnoreCase)) {
+ rels.Add(GetUriKey(e.FullName), e);
+ } else {
+ var data = new byte[e.Length];
+ using var inputStream = e.Open();
+ inputStream.ReadExactly(data);
+ var part = new ZipPackagePart(
+ this,
+ e,
+ ImmutableCollectionsMarshal.AsImmutableArray(data));
+ Parts.Add(GetUriKey(e.FullName), part);
+ }
+ }
+ }
+ }
+ foreach (var p in Parts) {
+ string name = Path.GetFileName(p.Key);
+ string extension = Path.GetExtension(p.Key);
+ string relFile = string.Format(
+ "{0}_rels/{1}.rels",
+ p.Key.Substring(0, p.Key.Length - name.Length),
+ name);
+ if (rels.TryGetValue(relFile, out var zipArchiveEntry)) {
+ using var inputStream = zipArchiveEntry.Open();
+ p.Value.ReadRelation(inputStream, p.Value.Uri.OriginalString);
+ }
+ if (_contentTypes.TryGetValue(p.Key, out var type)) {
+ p.Value.ContentType = type.Name;
+ } else if (extension.Length > 1 && _contentTypes.ContainsKey(extension.Substring(1))) {
+ p.Value.ContentType = _contentTypes[extension.Substring(1)].Name;
+ }
+ }
+ if (!hasContentTypeXml) {
+ throw new InvalidDataException("The file is not an valid Package file.");
+ }
+ }
+ }
+
+ private void AddContentTypes(Stream inputStream) {
+ var doc = new XmlDocument();
+ XmlHelper.LoadXmlSafe(doc, inputStream);
+
+ foreach (XmlElement c in doc.DocumentElement.ChildNodes) {
+ ContentType ct;
+ if (string.IsNullOrEmpty(c.GetAttribute("Extension"))) {
+ ct = new(c.GetAttribute("ContentType"), false, c.GetAttribute("PartName"));
+ } else {
+ ct = new(c.GetAttribute("ContentType"), true, c.GetAttribute("Extension"));
+ }
+ _contentTypes.Add(GetUriKey(ct.Match), ct);
+ }
+ }
+
+ internal void CreatePart(Uri partUri, string contentType, Action<StreamWriter> saveHandler) {
+ if (PartExists(partUri)) {
+ throw (new InvalidOperationException("Part already exist"));
+ }
+
+ var part = new ZipPackagePart(this, partUri, contentType, saveHandler);
+ _contentTypes.Add(
+ GetUriKey(part.Uri.OriginalString),
+ new(contentType, false, part.Uri.OriginalString));
+ Parts.Add(GetUriKey(part.Uri.OriginalString), part);
+ }
+
+ internal ZipPackagePart GetPart(Uri partUri) {
+ if (PartExists(partUri)) {
+ return Parts
+ .Single(x =>
+ x.Key.Equals(
+ GetUriKey(partUri.OriginalString),
+ StringComparison.InvariantCultureIgnoreCase))
+ .Value;
+ }
+ throw (new InvalidOperationException("Part does not exist."));
+ }
+
+ internal string GetUriKey(string uri) {
+ string ret = uri;
+ if (ret[0] != '/') {
+ ret = "/" + ret;
+ }
+ return ret;
+ }
+
+ internal bool PartExists(Uri partUri) {
+ var uriKey = GetUriKey(partUri.OriginalString.ToLower(CultureInfo.InvariantCulture));
+ return Parts.Keys.Any(x => x.Equals(uriKey, StringComparison.InvariantCultureIgnoreCase));
+ }
+
+ internal void DeletePart(Uri uri) {
+ var delList = new List<object[]>();
+ foreach (var p in Parts.Values) {
+ foreach (var r in p.GetRelationships()) {
+ if (UriHelper
+ .ResolvePartUri(p.Uri, r.TargetUri)
+ .OriginalString.Equals(
+ uri.OriginalString,
+ StringComparison.InvariantCultureIgnoreCase)) {
+ delList.Add([r.Id, p]);
+ }
+ }
+ }
+ foreach (var o in delList) {
+ ((ZipPackagePart)o[1]).DeleteRelationship(o[0].ToString());
+ }
+ var rels = GetPart(uri).GetRelationships();
+ while (rels.Count > 0) {
+ rels.Remove(rels.First().Id);
+ }
+ _contentTypes.Remove(GetUriKey(uri.OriginalString));
+ //remove all relations
+ Parts.Remove(GetUriKey(uri.OriginalString));
+ }
+
+ internal void Save(Stream stream) {
+ using var zipArchive = new ZipArchive(stream, ZipArchiveMode.Create, leaveOpen: true);
+ // Content types
+ var contentTypesEntry = zipArchive.CreateEntry("[Content_Types].xml");
+ using (var contentTypesWriter = new StreamWriter(contentTypesEntry.Open())) {
+ contentTypesWriter.Write(GetContentTypeXml());
+ }
+ // Top Rels
+ _rels.WriteZip(zipArchive, "_rels/.rels");
+ ZipPackagePart ssPart = null;
+ foreach (var part in Parts.Values) {
+ if (part.ContentType != ExcelPackage._contentTypeSharedString) {
+ part.WriteZip(zipArchive);
+ } else {
+ ssPart = part;
+ }
+ }
+ //Shared strings must be saved after all worksheets. The ss dictionary is populated when that workheets are saved (to get the best performance).
+ if (ssPart != null) {
+ ssPart.WriteZip(zipArchive);
+ }
+ }
+
+ private string GetContentTypeXml() {
+ StringBuilder xml = new StringBuilder(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">");
+ foreach (ContentType ct in _contentTypes.Values) {
+ if (ct.IsExtension) {
+ xml.Append($"<Default ContentType=\"{ct.Name}\" Extension=\"{ct.Match}\"/>");
+ } else {
+ xml.Append($"<Override ContentType=\"{ct.Name}\" PartName=\"{GetUriKey(ct.Match)}\" />");
+ }
+ }
+ xml.Append("</Types>");
+ return xml.ToString();
+ }
+}
diff --git a/AppsheetEpplus/Packaging/ZipPackagePart.cs b/AppsheetEpplus/Packaging/ZipPackagePart.cs
new file mode 100644
index 0000000..e1ca691
--- /dev/null
+++ b/AppsheetEpplus/Packaging/ZipPackagePart.cs
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * 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 25-Oct-2012
+ *******************************************************************************/
+
+using System;
+using System.Collections.Immutable;
+using System.IO;
+using System.IO.Compression;
+using System.Runtime.InteropServices;
+
+namespace AppsheetEpplus;
+
+internal class ZipPackagePart : ZipPackageRelationshipBase, IDisposable {
+ internal ZipPackagePart(ZipPackage package, ZipArchiveEntry entry, ImmutableArray<byte> data) {
+ Package = package;
+ SaveHandler = null;
+ Uri = new(package.GetUriKey(entry.FullName), UriKind.Relative);
+ _data = data;
+ }
+
+ private readonly ImmutableArray<byte> _data;
+
+ internal ZipPackagePart(
+ ZipPackage package,
+ Uri partUri,
+ string contentType,
+ Action<StreamWriter> saveHandler) {
+ Package = package;
+ Uri = partUri;
+ ContentType = contentType;
+ SaveHandler = saveHandler;
+ }
+
+ private ZipPackage Package { get; }
+
+ internal override ZipPackageRelationship CreateRelationship(
+ Uri targetUri,
+ TargetMode targetMode,
+ string relationshipType) {
+ var rel = base.CreateRelationship(targetUri, targetMode, relationshipType);
+ rel.SourceUri = Uri;
+ return rel;
+ }
+
+ internal MemoryStream GetStream() {
+ return new(ImmutableCollectionsMarshal.AsArray(_data) ?? [], false);
+ }
+
+ private string _contentType = "";
+
+ public string ContentType {
+ get => _contentType;
+ internal set {
+ if (!string.IsNullOrEmpty(_contentType)) {
+ if (Package._contentTypes.ContainsKey(Package.GetUriKey(Uri.OriginalString))) {
+ Package._contentTypes.Remove(Package.GetUriKey(Uri.OriginalString));
+ Package._contentTypes.Add(
+ Package.GetUriKey(Uri.OriginalString),
+ new(value, false, Uri.OriginalString));
+ }
+ }
+ _contentType = value;
+ }
+ }
+
+ public Uri Uri { get; }
+
+ internal Action<StreamWriter> SaveHandler { get; set; }
+
+ internal void WriteZip(ZipArchive zipArchive) {
+ if (SaveHandler == null) {
+ if (_data.Length == 0) {
+ return;
+ }
+ var zipEntry = zipArchive.CreateEntry(Uri.OriginalString);
+ using var os = zipEntry.Open();
+ os.Write(_data.AsSpan());
+ } else {
+ var zipEntry = zipArchive.CreateEntry(Uri.OriginalString);
+ using var streamWriter = new StreamWriter(zipEntry.Open());
+ SaveHandler(streamWriter);
+ }
+
+ if (_rels.Count > 0) {
+ string f = Uri.OriginalString;
+ var name = Path.GetFileName(f);
+ _rels.WriteZip(zipArchive, $"{f.Substring(0, f.Length - name.Length)}_rels/{name}.rels");
+ }
+ }
+
+ public void Dispose() {}
+}
diff --git a/AppsheetEpplus/Packaging/ZipPackageRelationship.cs b/AppsheetEpplus/Packaging/ZipPackageRelationship.cs
new file mode 100644
index 0000000..915cddf
--- /dev/null
+++ b/AppsheetEpplus/Packaging/ZipPackageRelationship.cs
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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 25-Oct-2012
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+internal class ZipPackageRelationship {
+ public Uri TargetUri { get; internal set; }
+
+ public Uri SourceUri { get; internal set; }
+
+ public string RelationshipType { get; internal set; }
+
+ public TargetMode TargetMode { get; internal set; }
+
+ public string Id { get; internal set; }
+}
diff --git a/AppsheetEpplus/Packaging/ZipPackageRelationshipBase.cs b/AppsheetEpplus/Packaging/ZipPackageRelationshipBase.cs
new file mode 100644
index 0000000..240ed85
--- /dev/null
+++ b/AppsheetEpplus/Packaging/ZipPackageRelationshipBase.cs
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * 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 25-Oct-2012
+ *******************************************************************************/
+
+using System;
+using System.IO;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+internal abstract class ZipPackageRelationshipBase {
+ protected ZipPackageRelationshipCollection _rels = new();
+ protected internal int maxRId = 1;
+
+ internal void DeleteRelationship(string id) {
+ _rels.Remove(id);
+ UpdateMaxRId(id, ref maxRId);
+ }
+
+ protected void UpdateMaxRId(string id, ref int maxRId) {
+ if (id.StartsWith("rId")) {
+ if (int.TryParse(id.Substring(3), out var num)) {
+ if (num == maxRId - 1) {
+ maxRId--;
+ }
+ }
+ }
+ }
+
+ internal virtual ZipPackageRelationship CreateRelationship(
+ Uri targetUri,
+ TargetMode targetMode,
+ string relationshipType) {
+ var rel = new ZipPackageRelationship();
+ rel.TargetUri = targetUri;
+ rel.TargetMode = targetMode;
+ rel.RelationshipType = relationshipType;
+ rel.Id = "rId" + (maxRId++);
+ _rels.Add(rel);
+ return rel;
+ }
+
+ internal bool RelationshipExists(string id) {
+ return _rels.ContainsKey(id);
+ }
+
+ internal ZipPackageRelationshipCollection GetRelationshipsByType(string schema) {
+ return _rels.GetRelationshipsByType(schema);
+ }
+
+ internal ZipPackageRelationshipCollection GetRelationships() {
+ return _rels;
+ }
+
+ internal ZipPackageRelationship GetRelationship(string id) {
+ return _rels[id];
+ }
+
+ internal void ReadRelation(Stream inputStream, string source) {
+ var doc = new XmlDocument();
+ XmlHelper.LoadXmlSafe(doc, inputStream);
+
+ foreach (XmlElement c in doc.DocumentElement.ChildNodes) {
+ var rel = new ZipPackageRelationship();
+ rel.Id = c.GetAttribute("Id");
+ rel.RelationshipType = c.GetAttribute("Type");
+ rel.TargetMode = c.GetAttribute("TargetMode")
+ .Equals("external", StringComparison.InvariantCultureIgnoreCase)
+ ? TargetMode.External
+ : TargetMode.Internal;
+ try {
+ rel.TargetUri = new(c.GetAttribute("Target"), UriKind.RelativeOrAbsolute);
+ } catch {
+ //The URI is not a valid URI. Encode it to make i valid.
+ rel.TargetUri = new(
+ Uri.EscapeUriString("Invalid:URI " + c.GetAttribute("Target")),
+ UriKind.RelativeOrAbsolute);
+ }
+ if (!string.IsNullOrEmpty(source)) {
+ rel.SourceUri = new(source, UriKind.Relative);
+ }
+ if (rel.Id.StartsWith("rid", StringComparison.InvariantCultureIgnoreCase)) {
+ if (int.TryParse(rel.Id.Substring(3), out var id)) {
+ if (id >= maxRId
+ && id
+ < int.MaxValue
+ - 10000) //Not likly to have this high id's but make sure we have space to avoid overflow.
+ {
+ maxRId = id + 1;
+ }
+ }
+ }
+ _rels.Add(rel);
+ }
+ }
+}
diff --git a/AppsheetEpplus/Packaging/ZipPackageRelationshipCollection.cs b/AppsheetEpplus/Packaging/ZipPackageRelationshipCollection.cs
new file mode 100644
index 0000000..ef9c5c1
--- /dev/null
+++ b/AppsheetEpplus/Packaging/ZipPackageRelationshipCollection.cs
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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 25-Oct-2012
+ *******************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Security;
+
+namespace AppsheetEpplus;
+
+internal class ZipPackageRelationshipCollection : IEnumerable<ZipPackageRelationship> {
+ protected internal Dictionary<string, ZipPackageRelationship> _rels = new(
+ StringComparer.InvariantCultureIgnoreCase);
+
+ internal void Add(ZipPackageRelationship item) {
+ _rels.Add(item.Id, item);
+ }
+
+ public IEnumerator<ZipPackageRelationship> GetEnumerator() {
+ return _rels.Values.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _rels.Values.GetEnumerator();
+ }
+
+ internal void Remove(string id) {
+ _rels.Remove(id);
+ }
+
+ internal bool ContainsKey(string id) {
+ return _rels.ContainsKey(id);
+ }
+
+ internal ZipPackageRelationship this[string id] => _rels[id];
+
+ internal ZipPackageRelationshipCollection GetRelationshipsByType(string relationshipType) {
+ var ret = new ZipPackageRelationshipCollection();
+ foreach (var rel in _rels.Values) {
+ if (rel.RelationshipType == relationshipType) {
+ ret.Add(rel);
+ }
+ }
+ return ret;
+ }
+
+ internal void WriteZip(ZipArchive zipArchive, string filename) {
+ var entry = zipArchive.CreateEntry(filename);
+ using var writer = new StreamWriter(entry.Open());
+
+ writer.Write(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">");
+ foreach (var rel in _rels.Values) {
+ writer.Write(
+ "<Relationship Id=\"{0}\" Type=\"{1}\" Target=\"{2}\"{3}/>",
+ SecurityElement.Escape(rel.Id),
+ rel.RelationshipType,
+ SecurityElement.Escape(rel.TargetUri.OriginalString),
+ rel.TargetMode == TargetMode.External ? " TargetMode=\"External\"" : "");
+ }
+ writer.Write("</Relationships>");
+ }
+
+ public int Count => _rels.Count;
+}
diff --git a/AppsheetEpplus/RangeCollection.cs b/AppsheetEpplus/RangeCollection.cs
new file mode 100644
index 0000000..87fa5be
--- /dev/null
+++ b/AppsheetEpplus/RangeCollection.cs
@@ -0,0 +1,277 @@
+/*******************************************************************************
+ * 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 2010-02-04
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// This is the store for all Rows, Columns and Cells.
+/// It is a Dictionary implementation that allows you to change the Key (the RowID, ColumnID or CellID )
+/// </summary>
+internal class RangeCollection : IEnumerator<IRangeId>, IEnumerable {
+ private class IndexItem {
+ internal IndexItem(ulong cellId) {
+ RangeID = cellId;
+ }
+
+ internal IndexItem(ulong cellId, int listPointer) {
+ RangeID = cellId;
+ ListPointer = listPointer;
+ }
+
+ internal ulong RangeID;
+ internal int ListPointer;
+ }
+
+ /// <summary>
+ /// Compares an IndexItem
+ /// </summary>
+ internal class Compare : IComparer<IndexItem> {
+ int IComparer<IndexItem>.Compare(IndexItem x, IndexItem y) {
+ return x.RangeID < y.RangeID
+ ? -1
+ : x.RangeID > y.RangeID
+ ? 1
+ : 0;
+ }
+ }
+
+ private IndexItem[] _cellIndex;
+ private List<IRangeId> _cells;
+ private static readonly Compare _comparer = new();
+
+ /// <summary>
+ /// Creates a new collection
+ /// </summary>
+ /// <param name="cells">The Cells. This list must be sorted</param>
+ internal RangeCollection(List<IRangeId> cells) {
+ _cells = cells;
+ InitSize(_cells);
+ for (int i = 0; i < _cells.Count; i++) {
+ _cellIndex[i] = new(cells[i].RangeID, i);
+ }
+ }
+
+ ~RangeCollection() {
+ _cells = null;
+ _cellIndex = null;
+ }
+
+ /// <summary>
+ /// Return the item with the RangeID
+ /// </summary>
+ /// <param name="rangeId"></param>
+ /// <returns></returns>
+ internal IRangeId this[ulong rangeId] => _cells[_cellIndex[IndexOf(rangeId)].ListPointer];
+
+ /// <summary>
+ /// Return specified index from the sorted list
+ /// </summary>
+ /// <param name="index"></param>
+ /// <returns></returns>
+ internal IRangeId this[int index] => _cells[_cellIndex[index].ListPointer];
+
+ internal int Count => _cells.Count;
+
+ internal void Add(IRangeId cell) {
+ var ix = IndexOf(cell.RangeID);
+ if (ix >= 0) {
+ throw (new("Item already exists"));
+ }
+ Insert(~ix, cell);
+ }
+
+ internal void Delete(ulong key) {
+ var ix = IndexOf(key);
+ if (ix < 0) {
+ throw (new("Key does not exists"));
+ }
+ int listPointer = _cellIndex[ix].ListPointer;
+ Array.Copy(_cellIndex, ix + 1, _cellIndex, ix, _cells.Count - ix - 1);
+ _cells.RemoveAt(listPointer);
+
+ //Item is removed subtract one from all items with greater ListPointer
+ for (int i = 0; i < _cells.Count; i++) {
+ if (_cellIndex[i].ListPointer >= listPointer) {
+ _cellIndex[i].ListPointer--;
+ }
+ }
+ }
+
+ internal int IndexOf(ulong key) {
+ return Array.BinarySearch(_cellIndex, 0, _cells.Count, new(key), _comparer);
+ }
+
+ internal bool ContainsKey(ulong key) {
+ return IndexOf(key) < 0 ? false : true;
+ }
+
+ private int _size { get; set; }
+
+ /// <summary>
+ /// Insert a number of rows in the collecion but dont update the cell only the index
+ /// </summary>
+ /// <param name="rowId"></param>
+ /// <param name="rows"></param>
+ /// <returns>Index of first rangeItem</returns>
+ internal int InsertRowsUpdateIndex(ulong rowId, int rows) {
+ int index = IndexOf(rowId);
+ if (index < 0) {
+ index = ~index; //No match found invert to get start cell
+ }
+ ulong rowAdd = (((ulong)rows) << 29);
+ for (int i = index; i < _cells.Count; i++) {
+ _cellIndex[i].RangeID += rowAdd;
+ }
+ return index;
+ }
+
+ /// <summary>
+ /// Insert a number of rows in the collecion
+ /// </summary>
+ /// <param name="rowId"></param>
+ /// <param name="rows"></param>
+ /// <returns>Index of first rangeItem</returns>
+ internal int InsertRows(ulong rowId, int rows) {
+ int index = IndexOf(rowId);
+ if (index < 0) {
+ index = ~index; //No match found invert to get start cell
+ }
+ ulong rowAdd = (((ulong)rows) << 29);
+ for (int i = index; i < _cells.Count; i++) {
+ _cellIndex[i].RangeID += rowAdd;
+ _cells[_cellIndex[i].ListPointer].RangeID += rowAdd;
+ }
+ return index;
+ }
+
+ /// <summary>
+ /// Delete rows from the collecion
+ /// </summary>
+ /// <param name="rowId"></param>
+ /// <param name="rows"></param>
+ /// <param name="updateCells">Update range id's on cells</param>
+ internal int DeleteRows(ulong rowId, int rows, bool updateCells) {
+ ulong rowAdd = (((ulong)rows) << 29);
+ var index = IndexOf(rowId);
+ if (index < 0) {
+ index = ~index; //No match found invert to get start cell
+ }
+
+ if (index >= _cells.Count || _cellIndex[index] == null) {
+ return -1; //No row above this row
+ }
+ while (index < _cells.Count && _cellIndex[index].RangeID < rowId + rowAdd) {
+ Delete(_cellIndex[index].RangeID);
+ }
+
+ int updIndex = IndexOf(rowId + rowAdd);
+ if (updIndex < 0) {
+ updIndex = ~updIndex; //No match found invert to get start cell
+ }
+
+ for (int i = updIndex; i < _cells.Count; i++) {
+ _cellIndex[i].RangeID -= rowAdd; //Change the index
+ if (updateCells) {
+ _cells[_cellIndex[i].ListPointer].RangeID -= rowAdd; //Change the cell/row or column object
+ }
+ }
+ return index;
+ }
+
+ internal void InsertColumn(ulong columnId, int columns) {
+ throw (new("Working on it..."));
+ }
+
+ internal void DeleteColumn(ulong columnId, int columns) {
+ throw (new("Working on it..."));
+ }
+
+ /// <summary>
+ /// Init the size starting from 128 items. Double the size until the list fits.
+ /// </summary>
+ /// <param name="_cells"></param>
+ private void InitSize(List<IRangeId> cells) {
+ _size = 128;
+ while (cells.Count > _size) {
+ _size <<= 1;
+ }
+ _cellIndex = new IndexItem[_size];
+ }
+
+ /// <summary>
+ /// Check the size and double the size if out of bound
+ /// </summary>
+ private void CheckSize() {
+ if (_cells.Count >= _size) {
+ _size <<= 1;
+ Array.Resize(ref _cellIndex, _size);
+ }
+ }
+
+ private void Insert(int ix, IRangeId cell) {
+ CheckSize();
+ Array.Copy(_cellIndex, ix, _cellIndex, ix + 1, _cells.Count - ix);
+ _cellIndex[ix] = new(cell.RangeID, _cells.Count);
+ _cells.Add(cell);
+ }
+
+ IRangeId IEnumerator<IRangeId>.Current {
+ get { throw new NotImplementedException(); }
+ }
+
+ void IDisposable.Dispose() {
+ _ix = -1;
+ }
+
+ private int _ix = -1;
+
+ object IEnumerator.Current {
+ get { return _cells[_cellIndex[_ix].ListPointer]; }
+ }
+
+ bool IEnumerator.MoveNext() {
+ _ix++;
+ return _ix < _cells.Count;
+ }
+
+ void IEnumerator.Reset() {
+ _ix = -1;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return MemberwiseClone() as IEnumerator;
+ }
+}
diff --git a/AppsheetEpplus/Style/Dxf/DxfStyleBase.cs b/AppsheetEpplus/Style/Dxf/DxfStyleBase.cs
new file mode 100644
index 0000000..569badf
--- /dev/null
+++ b/AppsheetEpplus/Style/Dxf/DxfStyleBase.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Globalization;
+
+namespace AppsheetEpplus;
+
+public abstract class DxfStyleBase<T> {
+ protected ExcelStyles _styles;
+
+ internal DxfStyleBase(ExcelStyles styles) {
+ _styles = styles;
+ }
+
+ protected internal abstract string Id { get; }
+
+ protected internal abstract bool HasValue { get; }
+
+ protected internal abstract void CreateNodes(XmlHelper helper, string path);
+
+ protected internal abstract T Clone();
+
+ protected void SetValueColor(XmlHelper helper, string path, ExcelDxfColor color) {
+ if (color != null && color.HasValue) {
+ if (color.Rgb != null) {
+ SetValue(helper, path + "/@rgb", color.Rgb);
+ } else if (color.Auto != null) {
+ SetValueBool(helper, path + "/@auto", color.Auto);
+ } else if (color.Theme != null) {
+ SetValue(helper, path + "/@theme", color.Theme);
+ } else if (color.Index != null) {
+ SetValue(helper, path + "/@indexed", color.Index);
+ }
+ if (color.Tint != null) {
+ SetValue(helper, path + "/@tint", color.Tint);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Same as SetValue but will set first char to lower case.
+ /// </summary>
+ /// <param name="helper"></param>
+ /// <param name="path"></param>
+ /// <param name="v"></param>
+ protected void SetValueEnum(XmlHelper helper, string path, Enum v) {
+ if (v == null) {
+ helper.DeleteNode(path);
+ } else {
+ var s = v.ToString();
+ s = s.Substring(0, 1).ToLower(CultureInfo.InvariantCulture) + s.Substring(1);
+ helper.SetXmlNodeString(path, s);
+ }
+ }
+
+ protected void SetValue(XmlHelper helper, string path, object v) {
+ if (v == null) {
+ helper.DeleteNode(path);
+ } else {
+ helper.SetXmlNodeString(path, v.ToString());
+ }
+ }
+
+ protected void SetValueBool(XmlHelper helper, string path, bool? v) {
+ if (v == null) {
+ helper.DeleteNode(path);
+ } else {
+ helper.SetXmlNodeBool(path, (bool)v);
+ }
+ }
+
+ protected string GetAsString(object v) {
+ return (v ?? "").ToString();
+ }
+
+ /// <summary>
+ /// Is this value allowed to be changed?
+ /// </summary>
+ protected internal bool AllowChange { get; set; } = false;
+}
diff --git a/AppsheetEpplus/Style/Dxf/ExcelDxfBorder.cs b/AppsheetEpplus/Style/Dxf/ExcelDxfBorder.cs
new file mode 100644
index 0000000..10a219d
--- /dev/null
+++ b/AppsheetEpplus/Style/Dxf/ExcelDxfBorder.cs
@@ -0,0 +1,81 @@
+namespace AppsheetEpplus;
+
+public class ExcelDxfBorderBase : DxfStyleBase<ExcelDxfBorderBase> {
+ internal ExcelDxfBorderBase(ExcelStyles styles)
+ : base(styles) {
+ Left = new(_styles);
+ Right = new(_styles);
+ Top = new(_styles);
+ Bottom = new(_styles);
+ }
+
+ /// <summary>
+ /// Left border style
+ /// </summary>
+ public ExcelDxfBorderItem Left { get; internal set; }
+
+ /// <summary>
+ /// Right border style
+ /// </summary>
+ public ExcelDxfBorderItem Right { get; internal set; }
+
+ /// <summary>
+ /// Top border style
+ /// </summary>
+ public ExcelDxfBorderItem Top { get; internal set; }
+
+ /// <summary>
+ /// Bottom border style
+ /// </summary>
+ public ExcelDxfBorderItem Bottom { get; internal set; }
+
+ ///// <summary>
+ ///// Diagonal border style
+ ///// </summary>
+ //public ExcelDxfBorderItem Diagonal
+ //{
+ // get;
+ // private set;
+ //}
+ ///// <summary>
+ ///// A diagonal from the bottom left to top right of the cell
+ ///// </summary>
+ //public bool DiagonalUp
+ //{
+ // get;
+ // set;
+ //}
+ ///// <summary>
+ ///// A diagonal from the top left to bottom right of the cell
+ ///// </summary>
+ //public bool DiagonalDown
+ //{
+ // get;
+ // set;
+ //}
+
+ protected internal override string Id =>
+ Top.Id
+ + Bottom.Id
+ + Left.Id
+ + Right.Id /* + Diagonal.Id + GetAsString(DiagonalUp) + GetAsString(DiagonalDown)*/;
+
+ protected internal override void CreateNodes(XmlHelper helper, string path) {
+ Left.CreateNodes(helper, path + "/d:left");
+ Right.CreateNodes(helper, path + "/d:right");
+ Top.CreateNodes(helper, path + "/d:top");
+ Bottom.CreateNodes(helper, path + "/d:bottom");
+ }
+
+ protected internal override bool HasValue =>
+ Left.HasValue || Right.HasValue || Top.HasValue || Bottom.HasValue;
+
+ protected internal override ExcelDxfBorderBase Clone() {
+ return new(_styles) {
+ Bottom = Bottom.Clone(),
+ Top = Top.Clone(),
+ Left = Left.Clone(),
+ Right = Right.Clone(),
+ };
+ }
+}
diff --git a/AppsheetEpplus/Style/Dxf/ExcelDxfBorderItem.cs b/AppsheetEpplus/Style/Dxf/ExcelDxfBorderItem.cs
new file mode 100644
index 0000000..029eac0
--- /dev/null
+++ b/AppsheetEpplus/Style/Dxf/ExcelDxfBorderItem.cs
@@ -0,0 +1,29 @@
+namespace AppsheetEpplus;
+
+public class ExcelDxfBorderItem : DxfStyleBase<ExcelDxfBorderItem> {
+ internal ExcelDxfBorderItem(ExcelStyles styles)
+ : base(styles) {
+ Color = new(styles);
+ }
+
+ public ExcelBorderStyle? Style { get; set; }
+
+ public ExcelDxfColor Color { get; internal set; }
+
+ protected internal override string Id =>
+ GetAsString(Style) + "|" + (Color == null ? "" : Color.Id);
+
+ protected internal override void CreateNodes(XmlHelper helper, string path) {
+ SetValueEnum(helper, path + "/@style", Style);
+ SetValueColor(helper, path + "/d:color", Color);
+ }
+
+ protected internal override bool HasValue => Style != null || Color.HasValue;
+
+ protected internal override ExcelDxfBorderItem Clone() {
+ return new(_styles) {
+ Style = Style,
+ Color = Color,
+ };
+ }
+}
diff --git a/AppsheetEpplus/Style/Dxf/ExcelDxfColor.cs b/AppsheetEpplus/Style/Dxf/ExcelDxfColor.cs
new file mode 100644
index 0000000..0cb4b36
--- /dev/null
+++ b/AppsheetEpplus/Style/Dxf/ExcelDxfColor.cs
@@ -0,0 +1,46 @@
+using System;
+
+namespace AppsheetEpplus;
+
+public class ExcelDxfColor : DxfStyleBase<ExcelDxfColor> {
+ public ExcelDxfColor(ExcelStyles styles)
+ : base(styles) {}
+
+ public int? Theme { get; set; }
+
+ public int? Index { get; set; }
+
+ public bool? Auto { get; set; }
+
+ public double? Tint { get; set; }
+
+ public string Rgb { get; set; }
+
+ protected internal override string Id =>
+ GetAsString(Theme)
+ + "|"
+ + GetAsString(Index)
+ + "|"
+ + GetAsString(Auto)
+ + "|"
+ + GetAsString(Tint)
+ + "|"
+ + GetAsString(Rgb);
+
+ protected internal override ExcelDxfColor Clone() {
+ return new(_styles) {
+ Theme = Theme,
+ Index = Index,
+ Rgb = Rgb,
+ Auto = Auto,
+ Tint = Tint,
+ };
+ }
+
+ protected internal override bool HasValue =>
+ Theme != null || Index != null || Auto != null || Tint != null || Rgb != null;
+
+ protected internal override void CreateNodes(XmlHelper helper, string path) {
+ throw new NotImplementedException();
+ }
+}
diff --git a/AppsheetEpplus/Style/Dxf/ExcelDxfFill.cs b/AppsheetEpplus/Style/Dxf/ExcelDxfFill.cs
new file mode 100644
index 0000000..887807d
--- /dev/null
+++ b/AppsheetEpplus/Style/Dxf/ExcelDxfFill.cs
@@ -0,0 +1,46 @@
+namespace AppsheetEpplus;
+
+public class ExcelDxfFill : DxfStyleBase<ExcelDxfFill> {
+ public ExcelDxfFill(ExcelStyles styles)
+ : base(styles) {
+ PatternColor = new(styles);
+ BackgroundColor = new(styles);
+ }
+
+ public ExcelFillStyle? PatternType { get; set; }
+
+ /// <summary>
+ /// The color of the pattern
+ /// </summary>
+ public ExcelDxfColor PatternColor { get; internal set; }
+
+ /// <summary>
+ /// The background color
+ /// </summary>
+ public ExcelDxfColor BackgroundColor { get; internal set; }
+
+ protected internal override string Id =>
+ GetAsString(PatternType)
+ + "|"
+ + (PatternColor == null ? "" : PatternColor.Id)
+ + "|"
+ + (BackgroundColor == null ? "" : BackgroundColor.Id);
+
+ protected internal override void CreateNodes(XmlHelper helper, string path) {
+ helper.CreateNode(path);
+ SetValueEnum(helper, path + "/d:patternFill/@patternType", PatternType);
+ SetValueColor(helper, path + "/d:patternFill/d:fgColor", PatternColor);
+ SetValueColor(helper, path + "/d:patternFill/d:bgColor", BackgroundColor);
+ }
+
+ protected internal override bool HasValue =>
+ PatternType != null || PatternColor.HasValue || BackgroundColor.HasValue;
+
+ protected internal override ExcelDxfFill Clone() {
+ return new(_styles) {
+ PatternType = PatternType,
+ PatternColor = PatternColor.Clone(),
+ BackgroundColor = BackgroundColor.Clone(),
+ };
+ }
+}
diff --git a/AppsheetEpplus/Style/Dxf/ExcelDxfFontBase.cs b/AppsheetEpplus/Style/Dxf/ExcelDxfFontBase.cs
new file mode 100644
index 0000000..cb81921
--- /dev/null
+++ b/AppsheetEpplus/Style/Dxf/ExcelDxfFontBase.cs
@@ -0,0 +1,72 @@
+namespace AppsheetEpplus;
+
+public class ExcelDxfFontBase : DxfStyleBase<ExcelDxfFontBase> {
+ public ExcelDxfFontBase(ExcelStyles styles)
+ : base(styles) {
+ Color = new(styles);
+ }
+
+ /// <summary>
+ /// Font bold
+ /// </summary>
+ public bool? Bold { get; set; }
+
+ /// <summary>
+ /// Font Italic
+ /// </summary>
+ public bool? Italic { get; set; }
+
+ /// <summary>
+ /// Font-Strikeout
+ /// </summary>
+ public bool? Strike { get; set; }
+
+ //public float? Size { get; set; }
+ public ExcelDxfColor Color { get; set; }
+
+ //public string Name { get; set; }
+ //public int? Family { get; set; }
+ ///// <summary>
+ ///// Font-Vertical Align
+ ///// </summary>
+ //public ExcelVerticalAlignmentFont? VerticalAlign
+ //{
+ // get;
+ // set;
+ //}
+
+ public ExcelUnderLineType? Underline { get; set; }
+
+ protected internal override string Id =>
+ GetAsString(Bold)
+ + "|"
+ + GetAsString(Italic)
+ + "|"
+ + GetAsString(Strike)
+ + "|"
+ + (Color == null ? "" : Color.Id)
+ + "|" /*+ GetAsString(VerticalAlign) + "|"*/
+ + GetAsString(Underline);
+
+ protected internal override void CreateNodes(XmlHelper helper, string path) {
+ helper.CreateNode(path);
+ SetValueBool(helper, path + "/d:b/@val", Bold);
+ SetValueBool(helper, path + "/d:i/@val", Italic);
+ SetValueBool(helper, path + "/d:strike", Strike);
+ SetValue(helper, path + "/d:u/@val", Underline);
+ SetValueColor(helper, path + "/d:color", Color);
+ }
+
+ protected internal override bool HasValue =>
+ Bold != null || Italic != null || Strike != null || Underline != null || Color.HasValue;
+
+ protected internal override ExcelDxfFontBase Clone() {
+ return new(_styles) {
+ Bold = Bold,
+ Color = Color.Clone(),
+ Italic = Italic,
+ Strike = Strike,
+ Underline = Underline,
+ };
+ }
+}
diff --git a/AppsheetEpplus/Style/Dxf/ExcelDxfNumberFormat.cs b/AppsheetEpplus/Style/Dxf/ExcelDxfNumberFormat.cs
new file mode 100644
index 0000000..7c00ffd
--- /dev/null
+++ b/AppsheetEpplus/Style/Dxf/ExcelDxfNumberFormat.cs
@@ -0,0 +1,77 @@
+namespace AppsheetEpplus;
+
+public class ExcelDxfNumberFormat : DxfStyleBase<ExcelDxfNumberFormat> {
+ public ExcelDxfNumberFormat(ExcelStyles styles)
+ : base(styles) {}
+
+ private int _numFmtID = int.MinValue;
+
+ /// <summary>
+ /// Id for number format
+ ///
+ /// Build in ID's
+ ///
+ /// 0 General
+ /// 1 0
+ /// 2 0.00
+ /// 3 #,##0
+ /// 4 #,##0.00
+ /// 9 0%
+ /// 10 0.00%
+ /// 11 0.00E+00
+ /// 12 # ?/?
+ /// 13 # ??/??
+ /// 14 mm-dd-yy
+ /// 15 d-mmm-yy
+ /// 16 d-mmm
+ /// 17 mmm-yy
+ /// 18 h:mm AM/PM
+ /// 19 h:mm:ss AM/PM
+ /// 20 h:mm
+ /// 21 h:mm:ss
+ /// 22 m/d/yy h:mm
+ /// 37 #,##0 ;(#,##0)
+ /// 38 #,##0 ;[Red](#,##0)
+ /// 39 #,##0.00;(#,##0.00)
+ /// 40 #,##0.00;[Red](#,##0.00)
+ /// 45 mm:ss
+ /// 46 [h]:mm:ss
+ /// 47 mmss.0
+ /// 48 ##0.0E+0
+ /// 49 @
+ /// </summary>
+ public int NumFmtID {
+ get => _numFmtID;
+ internal set => _numFmtID = value;
+ }
+
+ private string _format = "";
+
+ public string Format {
+ get => _format;
+ set {
+ _format = value;
+ NumFmtID = ExcelNumberFormat.GetFromBuildIdFromFormat(value);
+ }
+ }
+
+ protected internal override string Id => Format;
+
+ protected internal override void CreateNodes(XmlHelper helper, string path) {
+ if (NumFmtID < 0 && !string.IsNullOrEmpty(Format)) {
+ NumFmtID = _styles._nextDfxNumFmtID++;
+ }
+ helper.CreateNode(path);
+ SetValue(helper, path + "/@numFmtId", NumFmtID);
+ SetValue(helper, path + "/@formatCode", Format);
+ }
+
+ protected internal override bool HasValue => !string.IsNullOrEmpty(Format);
+
+ protected internal override ExcelDxfNumberFormat Clone() {
+ return new(_styles) {
+ NumFmtID = NumFmtID,
+ Format = Format,
+ };
+ }
+}
diff --git a/AppsheetEpplus/Style/Dxf/ExcelDxfStyle.cs b/AppsheetEpplus/Style/Dxf/ExcelDxfStyle.cs
new file mode 100644
index 0000000..7d3bde6
--- /dev/null
+++ b/AppsheetEpplus/Style/Dxf/ExcelDxfStyle.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections.Immutable;
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+public class ExcelDxfStyleConditionalFormatting : DxfStyleBase<ExcelDxfStyleConditionalFormatting> {
+ private readonly DxfStyleXmlHelper _helper;
+
+ private class DxfStyleXmlHelper(XmlNamespaceManager nameSpaceManager, XmlNode topNode)
+ : XmlHelper(nameSpaceManager, topNode) {
+ protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
+ "font",
+ "numFmt",
+ "fill",
+ "border",
+ ];
+ }
+
+ internal ExcelDxfStyleConditionalFormatting(
+ XmlNamespaceManager nameSpaceManager,
+ XmlNode topNode,
+ ExcelStyles styles)
+ : base(styles) {
+ NumberFormat = new(_styles);
+ Font = new(_styles);
+ Border = new(_styles);
+ Fill = new(_styles);
+ if (topNode != null) {
+ _helper = new(nameSpaceManager, topNode);
+ NumberFormat.NumFmtID = _helper.GetXmlNodeInt("d:numFmt/@numFmtId");
+ NumberFormat.Format = _helper.GetXmlNodeString("d:numFmt/@formatCode");
+ if (NumberFormat.NumFmtID < 164 && string.IsNullOrEmpty(NumberFormat.Format)) {
+ NumberFormat.Format = ExcelNumberFormat.GetFromBuildInFromId(NumberFormat.NumFmtID);
+ }
+
+ Font.Bold = _helper.GetXmlNodeBoolNullable("d:font/d:b/@val");
+ Font.Italic = _helper.GetXmlNodeBoolNullable("d:font/d:i/@val");
+ Font.Strike = _helper.GetXmlNodeBoolNullable("d:font/d:strike");
+ Font.Underline = GetUnderLineEnum(_helper.GetXmlNodeString("d:font/d:u/@val"));
+ Font.Color = GetColor(_helper, "d:font/d:color");
+
+ Border.Left = GetBorderItem(_helper, "d:border/d:left");
+ Border.Right = GetBorderItem(_helper, "d:border/d:right");
+ Border.Bottom = GetBorderItem(_helper, "d:border/d:bottom");
+ Border.Top = GetBorderItem(_helper, "d:border/d:top");
+
+ Fill.PatternType = GetPatternTypeEnum(
+ _helper.GetXmlNodeString("d:fill/d:patternFill/@patternType"));
+ Fill.BackgroundColor = GetColor(_helper, "d:fill/d:patternFill/d:bgColor/");
+ Fill.PatternColor = GetColor(_helper, "d:fill/d:patternFill/d:fgColor/");
+ } else {
+ _helper = new(nameSpaceManager, null);
+ }
+ }
+
+ private ExcelDxfBorderItem GetBorderItem(XmlHelper helper, string path) {
+ ExcelDxfBorderItem bi = new ExcelDxfBorderItem(_styles);
+ bi.Style = GetBorderStyleEnum(helper.GetXmlNodeString(path + "/@style"));
+ bi.Color = GetColor(helper, path + "/d:color");
+ return bi;
+ }
+
+ private ExcelBorderStyle GetBorderStyleEnum(string style) =>
+ Enum.TryParse<ExcelBorderStyle>(style, true, out var result) ? result : ExcelBorderStyle.None;
+
+ private ExcelFillStyle GetPatternTypeEnum(string patternType) =>
+ Enum.TryParse<ExcelFillStyle>(patternType, true, out var result) ? result : ExcelFillStyle.None;
+
+ private ExcelDxfColor GetColor(XmlHelper helper, string path) {
+ ExcelDxfColor ret = new ExcelDxfColor(_styles);
+ ret.Theme = helper.GetXmlNodeIntNull(path + "/@theme");
+ ret.Index = helper.GetXmlNodeIntNull(path + "/@indexed");
+ ret.Rgb = helper.GetXmlNodeString(path + "/@rgb");
+ ret.Auto = helper.GetXmlNodeBoolNullable(path + "/@auto");
+ ret.Tint = helper.GetXmlNodeDoubleNull(path + "/@tint");
+ return ret;
+ }
+
+ private ExcelUnderLineType? GetUnderLineEnum(string value) {
+ switch (value.ToLower(CultureInfo.InvariantCulture)) {
+ case "single":
+ return ExcelUnderLineType.Single;
+ case "double":
+ return ExcelUnderLineType.Double;
+ case "singleaccounting":
+ return ExcelUnderLineType.SingleAccounting;
+ case "doubleaccounting":
+ return ExcelUnderLineType.DoubleAccounting;
+ default:
+ return null;
+ }
+ }
+
+ internal int DxfId { get; set; }
+
+ public ExcelDxfFontBase Font { get; set; }
+
+ public ExcelDxfNumberFormat NumberFormat { get; set; }
+
+ public ExcelDxfFill Fill { get; set; }
+
+ public ExcelDxfBorderBase Border { get; set; }
+
+ protected internal override string Id =>
+ NumberFormat.Id + Font.Id + Border.Id + Fill.Id + (AllowChange ? "" : DxfId.ToString()); //If allowchange is false we add the dxfID to ensure it's not used when conditional formatting is updated);
+
+ protected internal override ExcelDxfStyleConditionalFormatting Clone() {
+ var s = new ExcelDxfStyleConditionalFormatting(_helper.NameSpaceManager, null, _styles);
+ s.Font = Font.Clone();
+ s.NumberFormat = NumberFormat.Clone();
+ s.Fill = Fill.Clone();
+ s.Border = Border.Clone();
+ return s;
+ }
+
+ protected internal override void CreateNodes(XmlHelper helper, string path) {
+ if (Font.HasValue) {
+ Font.CreateNodes(helper, "d:font");
+ }
+ if (NumberFormat.HasValue) {
+ NumberFormat.CreateNodes(helper, "d:numFmt");
+ }
+ if (Fill.HasValue) {
+ Fill.CreateNodes(helper, "d:fill");
+ }
+ if (Border.HasValue) {
+ Border.CreateNodes(helper, "d:border");
+ }
+ }
+
+ protected internal override bool HasValue =>
+ Font.HasValue || NumberFormat.HasValue || Fill.HasValue || Border.HasValue;
+}
diff --git a/AppsheetEpplus/Style/ExcelBorder.cs b/AppsheetEpplus/Style/ExcelBorder.cs
new file mode 100644
index 0000000..f5ba1ca
--- /dev/null
+++ b/AppsheetEpplus/Style/ExcelBorder.cs
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Cell Border style
+/// </summary>
+public sealed class Border : StyleBase {
+ internal Border(
+ ExcelStyles styles,
+ XmlHelper.ChangedEventHandler changedEvent,
+ int positionId,
+ string address,
+ int index)
+ : base(styles, changedEvent, positionId, address) {
+ Index = index;
+ }
+
+ /// <summary>
+ /// Left border style
+ /// </summary>
+ public ExcelBorderItem Left =>
+ new(_styles, _ChangedEvent, _positionID, _address, eStyleClass.BorderLeft, this);
+
+ /// <summary>
+ /// Right border style
+ /// </summary>
+ public ExcelBorderItem Right =>
+ new(_styles, _ChangedEvent, _positionID, _address, eStyleClass.BorderRight, this);
+
+ /// <summary>
+ /// Top border style
+ /// </summary>
+ public ExcelBorderItem Top =>
+ new(_styles, _ChangedEvent, _positionID, _address, eStyleClass.BorderTop, this);
+
+ /// <summary>
+ /// Bottom border style
+ /// </summary>
+ public ExcelBorderItem Bottom =>
+ new(_styles, _ChangedEvent, _positionID, _address, eStyleClass.BorderBottom, this);
+
+ /// <summary>
+ /// 0Diagonal border style
+ /// </summary>
+ public ExcelBorderItem Diagonal =>
+ new(_styles, _ChangedEvent, _positionID, _address, eStyleClass.BorderDiagonal, this);
+
+ /// <summary>
+ /// A diagonal from the bottom left to top right of the cell
+ /// </summary>
+ public bool DiagonalUp {
+ get {
+ if (Index >= 0) {
+ return _styles.Borders[Index].DiagonalUp;
+ }
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// A diagonal from the top left to bottom right of the cell
+ /// </summary>
+ public bool DiagonalDown {
+ get {
+ if (Index >= 0) {
+ return _styles.Borders[Index].DiagonalDown;
+ }
+ return false;
+ }
+ }
+
+ internal override string Id =>
+ Top.Id + Bottom.Id + Left.Id + Right.Id + Diagonal.Id + DiagonalUp + DiagonalDown;
+}
diff --git a/AppsheetEpplus/Style/ExcelBorderItem.cs b/AppsheetEpplus/Style/ExcelBorderItem.cs
new file mode 100644
index 0000000..e1fc6d9
--- /dev/null
+++ b/AppsheetEpplus/Style/ExcelBorderItem.cs
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Cell border style
+/// </summary>
+public sealed class ExcelBorderItem : StyleBase {
+ private readonly eStyleClass _cls;
+ private readonly StyleBase _parent;
+
+ internal ExcelBorderItem(
+ ExcelStyles styles,
+ XmlHelper.ChangedEventHandler changedEvent,
+ int worksheetId,
+ string address,
+ eStyleClass cls,
+ StyleBase parent)
+ : base(styles, changedEvent, worksheetId, address) {
+ _cls = cls;
+ _parent = parent;
+ }
+
+ /// <summary>
+ /// The line style of the border
+ /// </summary>
+ public ExcelBorderStyle Style => GetSource().Style;
+
+ private ExcelColor _color;
+
+ /// <summary>
+ /// The color of the border
+ /// </summary>
+ public ExcelColor Color {
+ get {
+ if (_color == null) {
+ _color = new(_styles, _ChangedEvent, _positionID, _address, _cls, _parent);
+ }
+ return _color;
+ }
+ }
+
+ internal override string Id => Style + Color.Id;
+
+ internal override void SetIndex(int index) {
+ _parent.Index = index;
+ }
+
+ private ExcelBorderItemXml GetSource() {
+ int ix = _parent.Index < 0 ? 0 : _parent.Index;
+
+ switch (_cls) {
+ case eStyleClass.BorderTop:
+ return _styles.Borders[ix].Top;
+ case eStyleClass.BorderBottom:
+ return _styles.Borders[ix].Bottom;
+ case eStyleClass.BorderLeft:
+ return _styles.Borders[ix].Left;
+ case eStyleClass.BorderRight:
+ return _styles.Borders[ix].Right;
+ case eStyleClass.BorderDiagonal:
+ return _styles.Borders[ix].Diagonal;
+ default:
+ throw new("Invalid class for Borderitem");
+ }
+ }
+}
diff --git a/AppsheetEpplus/Style/ExcelColor.cs b/AppsheetEpplus/Style/ExcelColor.cs
new file mode 100644
index 0000000..61ccc6d
--- /dev/null
+++ b/AppsheetEpplus/Style/ExcelColor.cs
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Color for cellstyling
+/// </summary>
+public sealed class ExcelColor : StyleBase {
+ private readonly eStyleClass _cls;
+ private readonly StyleBase _parent;
+
+ internal ExcelColor(
+ ExcelStyles styles,
+ XmlHelper.ChangedEventHandler changedEvent,
+ int worksheetId,
+ string address,
+ eStyleClass cls,
+ StyleBase parent)
+ : base(styles, changedEvent, worksheetId, address) {
+ _parent = parent;
+ _cls = cls;
+ }
+
+ /// <summary>
+ /// The theme color
+ /// </summary>
+ public string Theme => GetSource().Theme;
+
+ /// <summary>
+ /// The tint value
+ /// </summary>
+ public decimal Tint => GetSource().Tint;
+
+ /// <summary>
+ /// The RGB value
+ /// </summary>
+ public string Rgb => GetSource().Rgb;
+
+ /// <summary>
+ /// The indexed color number.
+ /// </summary>
+ public int Indexed => GetSource().Indexed;
+
+ internal override string Id => Theme + Tint + Rgb + Indexed;
+
+ private ExcelColorXml GetSource() {
+ Index = _parent.Index < 0 ? 0 : _parent.Index;
+ switch (_cls) {
+ case eStyleClass.FillBackgroundColor:
+ return _styles.Fills[Index].BackgroundColor;
+ case eStyleClass.FillPatternColor:
+ return _styles.Fills[Index].PatternColor;
+ case eStyleClass.Font:
+ return _styles.Fonts[Index].Color;
+ case eStyleClass.BorderLeft:
+ return _styles.Borders[Index].Left.Color;
+ case eStyleClass.BorderTop:
+ return _styles.Borders[Index].Top.Color;
+ case eStyleClass.BorderRight:
+ return _styles.Borders[Index].Right.Color;
+ case eStyleClass.BorderBottom:
+ return _styles.Borders[Index].Bottom.Color;
+ case eStyleClass.BorderDiagonal:
+ return _styles.Borders[Index].Diagonal.Color;
+ default:
+ throw (new("Invalid style-class for Color"));
+ }
+ }
+
+ internal override void SetIndex(int index) {
+ _parent.Index = index;
+ }
+}
diff --git a/AppsheetEpplus/Style/ExcelFill.cs b/AppsheetEpplus/Style/ExcelFill.cs
new file mode 100644
index 0000000..620e9af
--- /dev/null
+++ b/AppsheetEpplus/Style/ExcelFill.cs
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// The background fill of a cell
+/// </summary>
+public class ExcelFill : StyleBase {
+ internal ExcelFill(
+ ExcelStyles styles,
+ XmlHelper.ChangedEventHandler changedEvent,
+ int positionId,
+ string address,
+ int index)
+ : base(styles, changedEvent, positionId, address) {
+ Index = index;
+ }
+
+ /// <summary>
+ /// The pattern for solid fills.
+ /// </summary>
+ public ExcelFillStyle PatternType {
+ get {
+ if (Index == int.MinValue) {
+ return ExcelFillStyle.None;
+ }
+ return _styles.Fills[Index].PatternType;
+ }
+ }
+
+ private ExcelColor _patternColor;
+
+ /// <summary>
+ /// The color of the pattern
+ /// </summary>
+ public ExcelColor PatternColor {
+ get {
+ if (_patternColor == null) {
+ _patternColor = new(
+ _styles,
+ _ChangedEvent,
+ _positionID,
+ _address,
+ eStyleClass.FillPatternColor,
+ this);
+ if (_gradient != null) {
+ _gradient = null;
+ }
+ }
+ return _patternColor;
+ }
+ }
+
+ private ExcelColor _backgroundColor;
+
+ /// <summary>
+ /// The background color
+ /// </summary>
+ public ExcelColor BackgroundColor {
+ get {
+ if (_backgroundColor == null) {
+ _backgroundColor = new(
+ _styles,
+ _ChangedEvent,
+ _positionID,
+ _address,
+ eStyleClass.FillBackgroundColor,
+ this);
+ if (_gradient != null) {
+ _gradient = null;
+ }
+ }
+ return _backgroundColor;
+ }
+ }
+
+ private ExcelGradientFill _gradient;
+
+ /// <summary>
+ /// Access to properties for gradient fill.
+ /// </summary>
+ public ExcelGradientFill Gradient {
+ get {
+ if (_gradient == null) {
+ _gradient = new(_styles, _ChangedEvent, _positionID, _address, Index);
+ _backgroundColor = null;
+ _patternColor = null;
+ }
+ return _gradient;
+ }
+ }
+
+ internal override string Id {
+ get {
+ if (_gradient == null) {
+ return PatternType + PatternColor.Id + BackgroundColor.Id;
+ }
+ return _gradient.Id;
+ }
+ }
+}
diff --git a/AppsheetEpplus/Style/ExcelFont.cs b/AppsheetEpplus/Style/ExcelFont.cs
new file mode 100644
index 0000000..bbb1ca4
--- /dev/null
+++ b/AppsheetEpplus/Style/ExcelFont.cs
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Cell style Font
+/// </summary>
+public sealed class ExcelFont : StyleBase {
+ internal ExcelFont(
+ ExcelStyles styles,
+ XmlHelper.ChangedEventHandler changedEvent,
+ int positionId,
+ string address,
+ int index)
+ : base(styles, changedEvent, positionId, address) {
+ Index = index;
+ }
+
+ /// <summary>
+ /// The name of the font
+ /// </summary>
+ public string Name => _styles.Fonts[Index].Name;
+
+ /// <summary>
+ /// The Size of the font
+ /// </summary>
+ public float Size => _styles.Fonts[Index].Size;
+
+ /// <summary>
+ /// Font family
+ /// </summary>
+ public int Family => _styles.Fonts[Index].Family;
+
+ /// <summary>
+ /// Cell color
+ /// </summary>
+ public ExcelColor Color =>
+ new(_styles, _ChangedEvent, _positionID, _address, eStyleClass.Font, this);
+
+ /// <summary>
+ /// Scheme
+ /// </summary>
+ public string Scheme => _styles.Fonts[Index].Scheme;
+
+ /// <summary>
+ /// Font-bold
+ /// </summary>
+ public bool Bold {
+ get => _styles.Fonts[Index].Bold;
+ set =>
+ _ChangedEvent(this, new(eStyleClass.Font, eStyleProperty.Bold, value, _positionID, _address));
+ }
+
+ /// <summary>
+ /// Font-italic
+ /// </summary>
+ public bool Italic => _styles.Fonts[Index].Italic;
+
+ /// <summary>
+ /// Font-Strikeout
+ /// </summary>
+ public bool Strike => _styles.Fonts[Index].Strike;
+
+ /// <summary>
+ /// Font-Underline
+ /// </summary>
+ public bool UnderLine => _styles.Fonts[Index].UnderLine;
+
+ public ExcelUnderLineType UnderLineType => _styles.Fonts[Index].UnderLineType;
+
+ /// <summary>
+ /// Font-Vertical Align
+ /// </summary>
+ public ExcelVerticalAlignmentFont VerticalAlign =>
+ Enum.TryParse<ExcelVerticalAlignmentFont>(
+ _styles.Fonts[Index].VerticalAlign,
+ true,
+ out var result)
+ ? result
+ : ExcelVerticalAlignmentFont.None;
+
+ internal override string Id =>
+ Name
+ + Size
+ + Family
+ + Scheme
+ + Bold.ToString()[0]
+ + Italic.ToString()[0]
+ + Strike.ToString()[0]
+ + UnderLine.ToString()[0]
+ + VerticalAlign;
+}
diff --git a/AppsheetEpplus/Style/ExcelGradientFill.cs b/AppsheetEpplus/Style/ExcelGradientFill.cs
new file mode 100644
index 0000000..ab645e3
--- /dev/null
+++ b/AppsheetEpplus/Style/ExcelGradientFill.cs
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// The background fill of a cell
+/// </summary>
+public class ExcelGradientFill : StyleBase {
+ internal ExcelGradientFill(
+ ExcelStyles styles,
+ XmlHelper.ChangedEventHandler changedEvent,
+ int positionId,
+ string address,
+ int index)
+ : base(styles, changedEvent, positionId, address) {
+ Index = index;
+ }
+
+ /// <summary>
+ /// Angle of the linear gradient
+ /// </summary>
+ public double Degree => ((ExcelGradientFillXml)_styles.Fills[Index]).Degree;
+
+ /// <summary>
+ /// Linear or Path gradient
+ /// </summary>
+ public ExcelFillGradientType Type => ((ExcelGradientFillXml)_styles.Fills[Index]).Type;
+
+ /// <summary>
+ /// Specifies in percentage format(from the top to the bottom) the position of the top edge of the inner rectangle (color 1). For top, 0 means the top edge of the inner rectangle is on the top edge of the cell, and 1 means it is on the bottom edge of the cell. (applies to From Corner and From Center gradients).
+ /// </summary>
+ public double Top => ((ExcelGradientFillXml)_styles.Fills[Index]).Top;
+
+ /// <summary>
+ /// Specifies in percentage format (from the top to the bottom) the position of the bottom edge of the inner rectangle (color 1). For bottom, 0 means the bottom edge of the inner rectangle is on the top edge of the cell, and 1 means it is on the bottom edge of the cell.
+ /// </summary>
+ public double Bottom => ((ExcelGradientFillXml)_styles.Fills[Index]).Bottom;
+
+ /// <summary>
+ /// Specifies in percentage format (from the left to the right) the position of the left edge of the inner rectangle (color 1). For left, 0 means the left edge of the inner rectangle is on the left edge of the cell, and 1 means it is on the right edge of the cell. (applies to From Corner and From Center gradients).
+ /// </summary>
+ public double Left => ((ExcelGradientFillXml)_styles.Fills[Index]).Left;
+
+ /// <summary>
+ /// Specifies in percentage format (from the left to the right) the position of the right edge of the inner rectangle (color 1). For right, 0 means the right edge of the inner rectangle is on the left edge of the cell, and 1 means it is on the right edge of the cell. (applies to From Corner and From Center gradients).
+ /// </summary>
+ public double Right => ((ExcelGradientFillXml)_styles.Fills[Index]).Right;
+
+ private ExcelColor _gradientColor1;
+
+ /// <summary>
+ /// Gradient Color 1
+ /// </summary>
+ public ExcelColor Color1 {
+ get {
+ if (_gradientColor1 == null) {
+ _gradientColor1 = new(
+ _styles,
+ _ChangedEvent,
+ _positionID,
+ _address,
+ eStyleClass.FillGradientColor1,
+ this);
+ }
+ return _gradientColor1;
+ }
+ }
+
+ private ExcelColor _gradientColor2;
+
+ /// <summary>
+ /// Gradient Color 2
+ /// </summary>
+ public ExcelColor Color2 {
+ get {
+ if (_gradientColor2 == null) {
+ _gradientColor2 = new(
+ _styles,
+ _ChangedEvent,
+ _positionID,
+ _address,
+ eStyleClass.FillGradientColor2,
+ this);
+ }
+ return _gradientColor2;
+ }
+ }
+
+ internal override string Id =>
+ Degree.ToString() + Type + Color1.Id + Color2.Id + Top + Bottom + Left + Right;
+}
diff --git a/AppsheetEpplus/Style/ExcelNumberFormat.cs b/AppsheetEpplus/Style/ExcelNumberFormat.cs
new file mode 100644
index 0000000..e728eca
--- /dev/null
+++ b/AppsheetEpplus/Style/ExcelNumberFormat.cs
@@ -0,0 +1,210 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// The numberformat of the cell
+/// </summary>
+public sealed class ExcelNumberFormat : StyleBase {
+ internal ExcelNumberFormat(
+ ExcelStyles styles,
+ XmlHelper.ChangedEventHandler changedEvent,
+ int positionId,
+ string address,
+ int index)
+ : base(styles, changedEvent, positionId, address) {
+ Index = index;
+ }
+
+ /// <summary>
+ /// The numeric index fror the format
+ /// </summary>
+ public int NumFmtID => Index;
+
+ /// <summary>
+ /// The numberformat
+ /// </summary>
+ public string Format {
+ get {
+ for (int i = 0; i < _styles.NumberFormats.Count; i++) {
+ if (Index == _styles.NumberFormats[i].NumFmtId) {
+ return _styles.NumberFormats[i].Format;
+ }
+ }
+ return "general";
+ }
+ set =>
+ _ChangedEvent(
+ this,
+ new(
+ eStyleClass.Numberformat,
+ eStyleProperty.Format,
+ (string.IsNullOrEmpty(value) ? "General" : value),
+ _positionID,
+ _address));
+ }
+
+ internal override string Id => Format;
+
+ /// <summary>
+ /// If the numeric format is a build-in from.
+ /// </summary>
+ public bool BuildIn { get; private set; }
+
+ internal static string GetFromBuildInFromId(int numFmtId) {
+ switch (numFmtId) {
+ case 0:
+ return "General";
+ case 1:
+ return "0";
+ case 2:
+ return "0.00";
+ case 3:
+ return "#,##0";
+ case 4:
+ return "#,##0.00";
+ case 9:
+ return "0%";
+ case 10:
+ return "0.00%";
+ case 11:
+ return "0.00E+00";
+ case 12:
+ return "# ?/?";
+ case 13:
+ return "# ??/??";
+ case 14:
+ return "mm-dd-yy";
+ case 15:
+ return "d-mmm-yy";
+ case 16:
+ return "d-mmm";
+ case 17:
+ return "mmm-yy";
+ case 18:
+ return "h:mm AM/PM";
+ case 19:
+ return "h:mm:ss AM/PM";
+ case 20:
+ return "h:mm";
+ case 21:
+ return "h:mm:ss";
+ case 22:
+ return "m/d/yy h:mm";
+ case 37:
+ return "#,##0 ;(#,##0)";
+ case 38:
+ return "#,##0 ;[Red](#,##0)";
+ case 39:
+ return "#,##0.00;(#,##0.00)";
+ case 40:
+ return "#,##0.00;[Red](#,##0.00)";
+ case 45:
+ return "mm:ss";
+ case 46:
+ return "[h]:mm:ss";
+ case 47:
+ return "mmss.0";
+ case 48:
+ return "##0.0";
+ case 49:
+ return "@";
+ default:
+ return string.Empty;
+ }
+ }
+
+ internal static int GetFromBuildIdFromFormat(string format) {
+ switch (format) {
+ case "General":
+ case "":
+ return 0;
+ case "0":
+ return 1;
+ case "0.00":
+ return 2;
+ case "#,##0":
+ return 3;
+ case "#,##0.00":
+ return 4;
+ case "0%":
+ return 9;
+ case "0.00%":
+ return 10;
+ case "0.00E+00":
+ return 11;
+ case "# ?/?":
+ return 12;
+ case "# ??/??":
+ return 13;
+ case "mm-dd-yy":
+ return 14;
+ case "d-mmm-yy":
+ return 15;
+ case "d-mmm":
+ return 16;
+ case "mmm-yy":
+ return 17;
+ case "h:mm AM/PM":
+ return 18;
+ case "h:mm:ss AM/PM":
+ return 19;
+ case "h:mm":
+ return 20;
+ case "h:mm:ss":
+ return 21;
+ case "m/d/yy h:mm":
+ return 22;
+ case "#,##0 ;(#,##0)":
+ return 37;
+ case "#,##0 ;[Red](#,##0)":
+ return 38;
+ case "#,##0.00;(#,##0.00)":
+ return 39;
+ case "#,##0.00;[Red](#,##0.00)":
+ return 40;
+ case "mm:ss":
+ return 45;
+ case "[h]:mm:ss":
+ return 46;
+ case "mmss.0":
+ return 47;
+ case "##0.0":
+ return 48;
+ case "@":
+ return 49;
+ default:
+ return int.MinValue;
+ }
+ }
+}
diff --git a/AppsheetEpplus/Style/ExcelRichText.cs b/AppsheetEpplus/Style/ExcelRichText.cs
new file mode 100644
index 0000000..e585a77
--- /dev/null
+++ b/AppsheetEpplus/Style/ExcelRichText.cs
@@ -0,0 +1,277 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ * Richard Tallent Fix inadvertent removal of XML node 2012-10-31
+ * Richard Tallent Remove VertAlign node if no alignment specified 2012-10-31
+ *******************************************************************************/
+
+using System;
+using System.Collections.Immutable;
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// A richtext part
+/// </summary>
+public class ExcelRichText : XmlHelper {
+ protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
+ "rPr",
+ "t",
+ "b",
+ "i",
+ "strike",
+ "u",
+ "vertAlign",
+ "sz",
+ "color",
+ "rFont",
+ "family",
+ "scheme",
+ "charset",
+ ];
+
+ internal ExcelRichText(
+ XmlNamespaceManager ns,
+ XmlNode topNode,
+ ExcelRichTextCollection collection)
+ : base(ns, topNode) {
+ _collection = collection;
+ }
+
+ internal delegate void CallbackDelegate();
+
+ private CallbackDelegate _callback;
+
+ internal void SetCallback(CallbackDelegate callback) {
+ _callback = callback;
+ }
+
+ private const string _textPath = "d:t";
+
+ /// <summary>
+ /// The text
+ /// </summary>
+ public string Text {
+ get {
+ // Bug 15151
+ if (TopNode.Name == "t") {
+ return TopNode.InnerText;
+ }
+ return GetXmlNodeString(_textPath);
+ }
+ set {
+ _collection.ConvertRichtext();
+ // Don't remove if blank -- setting a blank rich text value on a node is common,
+ // for example when applying both bold and italic to text.
+ SetXmlNodeString(_textPath, value, false);
+ if (PreserveSpace) {
+ XmlElement elem = TopNode.SelectSingleNode(_textPath, NameSpaceManager) as XmlElement;
+ elem.SetAttribute("xml:space", "preserve");
+ }
+ if (_callback != null) {
+ _callback();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Preserves whitespace. Default true
+ /// </summary>
+ public bool PreserveSpace {
+ get {
+ XmlElement elem = TopNode.SelectSingleNode(_textPath, NameSpaceManager) as XmlElement;
+ if (elem != null) {
+ return elem.GetAttribute("xml:space") == "preserve";
+ }
+ return false;
+ }
+ set {
+ _collection.ConvertRichtext();
+ XmlElement elem = TopNode.SelectSingleNode(_textPath, NameSpaceManager) as XmlElement;
+ if (elem != null) {
+ if (value) {
+ elem.SetAttribute("xml:space", "preserve");
+ } else {
+ elem.RemoveAttribute("xml:space");
+ }
+ }
+ if (_callback != null) {
+ _callback();
+ }
+ }
+ }
+
+ private const string _boldPath = "d:rPr/d:b";
+
+ /// <summary>
+ /// Bold text
+ /// </summary>
+ public bool Bold {
+ get => ExistNode(_boldPath);
+ set {
+ _collection.ConvertRichtext();
+ if (value) {
+ CreateNode(_boldPath);
+ } else {
+ DeleteNode(_boldPath);
+ }
+ if (_callback != null) {
+ _callback();
+ }
+ }
+ }
+
+ private const string _italicPath = "d:rPr/d:i";
+
+ /// <summary>
+ /// Italic text
+ /// </summary>
+ public bool Italic {
+ get =>
+ //return GetXmlNodeBool(ITALIC_PATH, false);
+ ExistNode(_italicPath);
+ set {
+ _collection.ConvertRichtext();
+ if (value) {
+ CreateNode(_italicPath);
+ } else {
+ DeleteNode(_italicPath);
+ }
+ if (_callback != null) {
+ _callback();
+ }
+ }
+ }
+
+ private const string _strikePath = "d:rPr/d:strike";
+
+ /// <summary>
+ /// Strike-out text
+ /// </summary>
+ public bool Strike {
+ get => ExistNode(_strikePath);
+ set {
+ _collection.ConvertRichtext();
+ if (value) {
+ CreateNode(_strikePath);
+ } else {
+ DeleteNode(_strikePath);
+ }
+ if (_callback != null) {
+ _callback();
+ }
+ }
+ }
+
+ private const string _underlinePath = "d:rPr/d:u";
+
+ /// <summary>
+ /// Underlined text
+ /// </summary>
+ public bool UnderLine {
+ get => ExistNode(_underlinePath);
+ set {
+ _collection.ConvertRichtext();
+ if (value) {
+ CreateNode(_underlinePath);
+ } else {
+ DeleteNode(_underlinePath);
+ }
+ if (_callback != null) {
+ _callback();
+ }
+ }
+ }
+
+ private const string _vertAlignPath = "d:rPr/d:vertAlign/@val";
+
+ /// <summary>
+ /// Vertical Alignment
+ /// </summary>
+ public ExcelVerticalAlignmentFont VerticalAlign =>
+ Enum.TryParse<ExcelVerticalAlignmentFont>(
+ GetXmlNodeString(TopNode, _vertAlignPath),
+ true,
+ out var result)
+ ? result
+ : ExcelVerticalAlignmentFont.None;
+
+ private const string _sizePath = "d:rPr/d:sz/@val";
+
+ /// <summary>
+ /// Font size
+ /// </summary>
+ public float Size {
+ get => Convert.ToSingle(GetXmlNodeDecimal(_sizePath));
+ set {
+ _collection.ConvertRichtext();
+ SetXmlNodeString(_sizePath, value.ToString(CultureInfo.InvariantCulture));
+ if (_callback != null) {
+ _callback();
+ }
+ }
+ }
+
+ private const string _fontPath = "d:rPr/d:rFont/@val";
+
+ /// <summary>
+ /// Name of the font
+ /// </summary>
+ public string FontName {
+ get => GetXmlNodeString(_fontPath);
+ set {
+ _collection.ConvertRichtext();
+ SetXmlNodeString(_fontPath, value);
+ if (_callback != null) {
+ _callback();
+ }
+ }
+ }
+
+ private const string _colorPath = "d:rPr/d:color/@rgb";
+
+ /// <summary>
+ /// Text color
+ /// </summary>
+ public string Color {
+ get => GetXmlNodeString(_colorPath);
+ set {
+ _collection.ConvertRichtext();
+ SetXmlNodeString(_colorPath, value);
+ if (_callback != null) {
+ _callback();
+ }
+ }
+ }
+
+ public ExcelRichTextCollection _collection { get; set; }
+}
diff --git a/AppsheetEpplus/Style/ExcelRichTextCollection.cs b/AppsheetEpplus/Style/ExcelRichTextCollection.cs
new file mode 100644
index 0000000..2641b2e
--- /dev/null
+++ b/AppsheetEpplus/Style/ExcelRichTextCollection.cs
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Collection of Richtext objects
+/// </summary>
+public class ExcelRichTextCollection : XmlHelper, IEnumerable<ExcelRichText> {
+ private readonly List<ExcelRichText> _list = new();
+ private readonly ExcelRangeBase _cells;
+
+ internal ExcelRichTextCollection(XmlNamespaceManager ns, XmlNode topNode)
+ : base(ns, topNode) {
+ var nl = topNode.SelectNodes("d:r|d:t", NameSpaceManager); // Bug 15151
+ if (nl != null) {
+ foreach (XmlNode n in nl) {
+ _list.Add(new(ns, n, this));
+ }
+ }
+ }
+
+ internal ExcelRichTextCollection(XmlNamespaceManager ns, XmlNode topNode, ExcelRangeBase cells)
+ : this(ns, topNode) {
+ _cells = cells;
+ }
+
+ /// <summary>
+ /// Collection containing the richtext objects
+ /// </summary>
+ /// <param name="index"></param>
+ /// <returns></returns>
+ public ExcelRichText this[int index] {
+ get {
+ var item = _list[index];
+ if (_cells != null) {
+ item.SetCallback(UpdateCells);
+ }
+ return item;
+ }
+ }
+
+ /// <summary>
+ /// Items in the list
+ /// </summary>
+ public int Count => _list.Count;
+
+ /// <summary>
+ /// Add a rich text string
+ /// </summary>
+ /// <param name="text">The text to add</param>
+ /// <returns></returns>
+ public ExcelRichText Add(string text) {
+ ConvertRichtext();
+ XmlDocument doc;
+ if (TopNode is XmlDocument document) {
+ doc = document;
+ } else {
+ doc = TopNode.OwnerDocument;
+ }
+ var node = doc.CreateElement("d", "r", ExcelPackage._schemaMain);
+ TopNode.AppendChild(node);
+ var rt = new ExcelRichText(NameSpaceManager, node, this);
+ if (_list.Count > 0) {
+ ExcelRichText prevItem = _list[_list.Count - 1];
+ rt.FontName = prevItem.FontName;
+ rt.Size = prevItem.Size;
+ rt.Color = prevItem.Color == "" ? "FF00000" : prevItem.Color;
+ rt.PreserveSpace = rt.PreserveSpace;
+ rt.Bold = prevItem.Bold;
+ rt.Italic = prevItem.Italic;
+ rt.UnderLine = prevItem.UnderLine;
+ } else if (_cells == null) {
+ rt.FontName = "Calibri";
+ rt.Size = 11;
+ } else {
+ var style = _cells.Offset(0, 0).Style;
+ rt.FontName = style.Font.Name;
+ rt.Size = style.Font.Size;
+ rt.Bold = style.Font.Bold;
+ rt.Italic = style.Font.Italic;
+ _cells.IsRichText = true;
+ }
+ rt.Text = text;
+ rt.PreserveSpace = true;
+ if (_cells != null) {
+ rt.SetCallback(UpdateCells);
+ UpdateCells();
+ }
+ _list.Add(rt);
+ return rt;
+ }
+
+ internal void ConvertRichtext() {
+ if (_cells == null) {
+ return;
+ }
+ var isRt = _cells.Worksheet._flags.GetFlagValue(
+ _cells._fromRow,
+ _cells._fromCol,
+ CellFlags.RichText);
+ if (Count == 1 && isRt == false) {
+ _cells.Worksheet._flags.SetFlagValue(
+ _cells._fromRow,
+ _cells._fromCol,
+ true,
+ CellFlags.RichText);
+ var s = _cells.Worksheet._styles.GetValue(_cells._fromRow, _cells._fromCol);
+ //var fnt = cell.Style.Font;
+ var fnt = _cells.Worksheet.Workbook.Styles
+ .GetStyleObject(
+ s,
+ _cells.Worksheet.PositionID,
+ ExcelCellBase.GetAddress(_cells._fromRow, _cells._fromCol))
+ .Font;
+ this[0].PreserveSpace = true;
+ this[0].Bold = fnt.Bold;
+ this[0].FontName = fnt.Name;
+ this[0].Italic = fnt.Italic;
+ this[0].Size = fnt.Size;
+ this[0].UnderLine = fnt.UnderLine;
+ }
+ }
+
+ internal void UpdateCells() {
+ _cells.SetValueRichText(TopNode.InnerXml);
+ }
+
+ /// <summary>
+ /// Removes an item at the specific index
+ /// </summary>
+ /// <param name="index"></param>
+ public void RemoveAt(int index) {
+ TopNode.RemoveChild(_list[index].TopNode);
+ _list.RemoveAt(index);
+ if (_cells != null && _list.Count == 0) {
+ _cells.IsRichText = false;
+ }
+ }
+
+ /// <summary>
+ /// Removes an item
+ /// </summary>
+ /// <param name="item"></param>
+ public void Remove(ExcelRichText item) {
+ TopNode.RemoveChild(item.TopNode);
+ _list.Remove(item);
+ if (_cells != null && _list.Count == 0) {
+ _cells.IsRichText = false;
+ }
+ }
+
+ //public void Insert(int index, string Text)
+ //{
+ // _list.Insert(index, item);
+ //}
+
+ /// <summary>
+ /// The text
+ /// </summary>
+ public string Text {
+ get {
+ StringBuilder sb = new StringBuilder();
+ foreach (var item in _list) {
+ sb.Append(item.Text);
+ }
+ return sb.ToString();
+ }
+ set {
+ if (Count == 0) {
+ Add(value);
+ } else {
+ this[0].Text = value;
+ for (int ix = 1; ix < Count; ix++) {
+ RemoveAt(ix);
+ }
+ }
+ }
+ }
+
+ IEnumerator<ExcelRichText> IEnumerable<ExcelRichText>.GetEnumerator() {
+ return _list
+ .Select(x => {
+ x.SetCallback(UpdateCells);
+ return x;
+ })
+ .GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _list
+ .Select(x => {
+ x.SetCallback(UpdateCells);
+ return x;
+ })
+ .GetEnumerator();
+ }
+}
diff --git a/AppsheetEpplus/Style/ExcelStyle.cs b/AppsheetEpplus/Style/ExcelStyle.cs
new file mode 100644
index 0000000..65d5a28
--- /dev/null
+++ b/AppsheetEpplus/Style/ExcelStyle.cs
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Toplevel class for cell styling
+/// </summary>
+public sealed class ExcelStyle : StyleBase {
+ internal ExcelStyle(
+ ExcelStyles styles,
+ XmlHelper.ChangedEventHandler changedEvent,
+ int positionId,
+ string address,
+ int xfsId)
+ : base(styles, changedEvent, positionId, address) {
+ Index = xfsId;
+ ExcelXfs xfs;
+ if (positionId > -1) {
+ xfs = _styles.CellXfs[xfsId];
+ } else {
+ xfs = _styles.CellStyleXfs[xfsId];
+ }
+ Styles = styles;
+ PositionID = positionId;
+ Numberformat = new(styles, changedEvent, PositionID, address, xfs.NumberFormatId);
+ Font = new(styles, changedEvent, PositionID, address, xfs.FontId);
+ Fill = new(styles, changedEvent, PositionID, address, xfs.FillId);
+ Border = new(styles, changedEvent, PositionID, address, xfs.BorderId);
+ }
+
+ /// <summary>
+ /// Numberformat
+ /// </summary>
+ public ExcelNumberFormat Numberformat { get; set; }
+
+ /// <summary>
+ /// Font styling
+ /// </summary>
+ public ExcelFont Font { get; set; }
+
+ /// <summary>
+ /// Fill Styling
+ /// </summary>
+ public ExcelFill Fill { get; set; }
+
+ /// <summary>
+ /// Border
+ /// </summary>
+ public Border Border { get; set; }
+
+ /// <summary>
+ /// The horizontal alignment in the cell
+ /// </summary>
+ public ExcelHorizontalAlignment HorizontalAlignment => _styles.CellXfs[Index].HorizontalAlignment;
+
+ /// <summary>
+ /// The vertical alignment in the cell
+ /// </summary>
+ public ExcelVerticalAlignment VerticalAlignment => _styles.CellXfs[Index].VerticalAlignment;
+
+ /// <summary>
+ /// Wrap the text
+ /// </summary>
+ public bool WrapText {
+ get => _styles.CellXfs[Index].WrapText;
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Style, eStyleProperty.WrapText, value, _positionID, _address));
+ }
+
+ /// <summary>
+ /// Readingorder
+ /// </summary>
+ public ExcelReadingOrder ReadingOrder => _styles.CellXfs[Index].ReadingOrder;
+
+ /// <summary>
+ /// Shrink the text to fit
+ /// </summary>
+ public bool ShrinkToFit => _styles.CellXfs[Index].ShrinkToFit;
+
+ /// <summary>
+ /// The margin between the border and the text
+ /// </summary>
+ public int Indent => _styles.CellXfs[Index].Indent;
+
+ /// <summary>
+ /// Text orientation in degrees. Values range from 0 to 180.
+ /// </summary>
+ public int TextRotation => _styles.CellXfs[Index].TextRotation;
+
+ /// <summary>
+ /// If true the cell is locked for editing when the sheet is protected
+ /// <seealso cref="ExcelWorksheet.Protection"/>
+ /// </summary>
+ public bool Locked => _styles.CellXfs[Index].Locked;
+
+ /// <summary>
+ /// If true the formula is hidden when the sheet is protected.
+ /// <seealso cref="ExcelWorksheet.Protection"/>
+ /// </summary>
+ public bool Hidden => _styles.CellXfs[Index].Hidden;
+
+ /// <summary>
+ /// The index in the style collection
+ /// </summary>
+ public int XfId => _styles.CellXfs[Index].XfId;
+
+ internal int PositionID { get; set; }
+
+ internal ExcelStyles Styles { get; set; }
+
+ internal override string Id =>
+ Numberformat.Id
+ + "|"
+ + Font.Id
+ + "|"
+ + Fill.Id
+ + "|"
+ + Border.Id
+ + "|"
+ + VerticalAlignment
+ + "|"
+ + HorizontalAlignment
+ + "|"
+ + WrapText
+ + "|"
+ + ReadingOrder
+ + "|"
+ + XfId;
+}
diff --git a/AppsheetEpplus/Style/IStyle.cs b/AppsheetEpplus/Style/IStyle.cs
new file mode 100644
index 0000000..7aafb76
--- /dev/null
+++ b/AppsheetEpplus/Style/IStyle.cs
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+internal interface IStyle {
+ void SetNewStyleId(string value);
+
+ ulong Id { get; }
+
+ ExcelStyle ExcelStyle { get; }
+}
diff --git a/AppsheetEpplus/Style/StyleBase.cs b/AppsheetEpplus/Style/StyleBase.cs
new file mode 100644
index 0000000..a9904ae
--- /dev/null
+++ b/AppsheetEpplus/Style/StyleBase.cs
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Border line style
+/// </summary>
+public enum ExcelBorderStyle {
+ None,
+ Hair,
+ Dotted,
+ DashDot,
+ Thin,
+ DashDotDot,
+ Dashed,
+ MediumDashDotDot,
+ MediumDashed,
+ MediumDashDot,
+ Thick,
+ Medium,
+ Double,
+}
+
+/// <summary>
+/// Horizontal text alignment
+/// </summary>
+public enum ExcelHorizontalAlignment {
+ General,
+ Left,
+ Center,
+ CenterContinuous,
+ Right,
+ Fill,
+ Distributed,
+ Justify,
+}
+
+/// <summary>
+/// Vertical text alignment
+/// </summary>
+public enum ExcelVerticalAlignment {
+ Top,
+ Center,
+ Bottom,
+ Distributed,
+ Justify,
+}
+
+/// <summary>
+/// Font-Vertical Align
+/// </summary>
+public enum ExcelVerticalAlignmentFont {
+ None,
+ Subscript,
+ Superscript,
+}
+
+/// <summary>
+/// Font-Underlinestyle for
+/// </summary>
+public enum ExcelUnderLineType {
+ None,
+ Single,
+ Double,
+ SingleAccounting,
+ DoubleAccounting,
+}
+
+/// <summary>
+/// Fill pattern
+/// </summary>
+public enum ExcelFillStyle {
+ None,
+ Solid,
+ DarkGray,
+ MediumGray,
+ LightGray,
+ Gray125,
+ Gray0625,
+ DarkVertical,
+ DarkHorizontal,
+ DarkDown,
+ DarkUp,
+ DarkGrid,
+ DarkTrellis,
+ LightVertical,
+ LightHorizontal,
+ LightDown,
+ LightUp,
+ LightGrid,
+ LightTrellis,
+}
+
+/// <summary>
+/// Type of gradient fill
+/// </summary>
+public enum ExcelFillGradientType {
+ /// <summary>
+ /// No gradient fill.
+ /// </summary>
+ None,
+
+ /// <summary>
+ /// This gradient fill is of linear gradient type. Linear gradient type means that the transition from one color to the next is along a line (e.g., horizontal, vertical,diagonal, etc.)
+ /// </summary>
+ Linear,
+
+ /// <summary>
+ /// This gradient fill is of path gradient type. Path gradient type means the that the boundary of transition from one color to the next is a rectangle, defined by top,bottom, left, and right attributes on the gradientFill element.
+ /// </summary>
+ Path,
+}
+
+/// <summary>
+/// The reading order
+/// </summary>
+public enum ExcelReadingOrder {
+ /// <summary>
+ /// Reading order is determined by scanning the text for the first non-whitespace character: if it is a strong right-to-left character, the reading order is right-to-left; otherwise, the reading order left-to-right.
+ /// </summary>
+ ContextDependent = 0,
+
+ /// <summary>
+ /// Left to Right
+ /// </summary>
+ LeftToRight = 1,
+
+ /// <summary>
+ /// Right to Left
+ /// </summary>
+ RightToLeft = 2,
+}
+
+public abstract class StyleBase {
+ protected ExcelStyles _styles;
+ internal XmlHelper.ChangedEventHandler _ChangedEvent;
+ protected int _positionID;
+ protected string _address;
+
+ internal StyleBase(
+ ExcelStyles styles,
+ XmlHelper.ChangedEventHandler changedEvent,
+ int positionId,
+ string address) {
+ _styles = styles;
+ _ChangedEvent = changedEvent;
+ _address = address;
+ _positionID = positionId;
+ }
+
+ internal int Index { get; set; }
+
+ internal abstract string Id { get; }
+
+ internal virtual void SetIndex(int index) {
+ Index = index;
+ }
+}
diff --git a/AppsheetEpplus/Style/StyleChangeEventArgs.cs b/AppsheetEpplus/Style/StyleChangeEventArgs.cs
new file mode 100644
index 0000000..340ef1f
--- /dev/null
+++ b/AppsheetEpplus/Style/StyleChangeEventArgs.cs
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+internal enum eStyleClass {
+ Numberformat,
+ Font,
+ Border,
+ BorderTop,
+ BorderLeft,
+ BorderBottom,
+ BorderRight,
+ BorderDiagonal,
+ Fill,
+ GradientFill,
+ FillBackgroundColor,
+ FillPatternColor,
+ FillGradientColor1,
+ FillGradientColor2,
+ NamedStyle,
+ Style,
+}
+
+internal enum eStyleProperty {
+ Format,
+ Name,
+ Size,
+ Bold,
+ Italic,
+ Strike,
+ Color,
+ Tint,
+ IndexedColor,
+ AutoColor,
+ GradientColor,
+ Family,
+ Scheme,
+ UnderlineType,
+ HorizontalAlign,
+ VerticalAlign,
+ Border,
+ NamedStyle,
+ Style,
+ PatternType,
+ ReadingOrder,
+ WrapText,
+ TextRotation,
+ Locked,
+ Hidden,
+ ShrinkToFit,
+ BorderDiagonalUp,
+ BorderDiagonalDown,
+ GradientDegree,
+ GradientType,
+ GradientTop,
+ GradientBottom,
+ GradientLeft,
+ GradientRight,
+ XfId,
+ Indent,
+}
+
+internal class StyleChangeEventArgs : EventArgs {
+ internal StyleChangeEventArgs(
+ eStyleClass styleclass,
+ eStyleProperty styleProperty,
+ object value,
+ int positionId,
+ string address) {
+ StyleClass = styleclass;
+ StyleProperty = styleProperty;
+ Value = value;
+ Address = address;
+ PositionID = positionId;
+ }
+
+ internal eStyleClass StyleClass;
+ internal eStyleProperty StyleProperty;
+
+ //internal string PropertyName;
+ internal object Value;
+
+ internal int PositionID { get; set; }
+
+ //internal string Address;
+ internal string Address;
+}
diff --git a/AppsheetEpplus/Style/XmlAccess/ExcelBorderItemXml.cs b/AppsheetEpplus/Style/XmlAccess/ExcelBorderItemXml.cs
new file mode 100644
index 0000000..a68da66
--- /dev/null
+++ b/AppsheetEpplus/Style/XmlAccess/ExcelBorderItemXml.cs
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System;
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Xml access class for border items
+/// </summary>
+public sealed class ExcelBorderItemXml : StyleXmlHelper {
+ internal ExcelBorderItemXml(XmlNamespaceManager nameSpaceManager)
+ : base(nameSpaceManager) {
+ _borderStyle = ExcelBorderStyle.None;
+ _color = new(NameSpaceManager);
+ }
+
+ internal ExcelBorderItemXml(XmlNamespaceManager nsm, XmlNode topNode)
+ : base(nsm, topNode) {
+ if (topNode != null) {
+ _borderStyle = GetBorderStyle(GetXmlNodeString("@style"));
+ _color = new(nsm, topNode.SelectSingleNode(_colorPath, nsm));
+ Exists = true;
+ } else {
+ Exists = false;
+ }
+ }
+
+ private ExcelBorderStyle GetBorderStyle(string style) {
+ if (style == "") {
+ return ExcelBorderStyle.None;
+ }
+ return Enum.TryParse<ExcelBorderStyle>(style, true, out var result)
+ ? result
+ : ExcelBorderStyle.None;
+ }
+
+ private ExcelBorderStyle _borderStyle = ExcelBorderStyle.None;
+
+ /// <summary>
+ /// Cell Border style
+ /// </summary>
+ public ExcelBorderStyle Style {
+ get => _borderStyle;
+ set {
+ _borderStyle = value;
+ Exists = true;
+ }
+ }
+
+ private ExcelColorXml _color;
+ private const string _colorPath = "d:color";
+
+ /// <summary>
+ /// Border style
+ /// </summary>
+ public ExcelColorXml Color {
+ get => _color;
+ internal set => _color = value;
+ }
+
+ internal override string Id {
+ get {
+ if (Exists) {
+ return Style + Color.Id;
+ }
+ return "None";
+ }
+ }
+
+ internal ExcelBorderItemXml Copy() {
+ ExcelBorderItemXml borderItem = new ExcelBorderItemXml(NameSpaceManager);
+ borderItem.Style = _borderStyle;
+ borderItem.Color = _color.Copy();
+ return borderItem;
+ }
+
+ internal override XmlNode CreateXmlNode(XmlNode topNode) {
+ TopNode = topNode;
+
+ if (Style != ExcelBorderStyle.None) {
+ SetXmlNodeString("@style", SetBorderString(Style));
+ if (Color.Exists) {
+ CreateNode(_colorPath);
+ topNode.AppendChild(
+ Color.CreateXmlNode(TopNode.SelectSingleNode(_colorPath, NameSpaceManager)));
+ }
+ }
+ return TopNode;
+ }
+
+ private string SetBorderString(ExcelBorderStyle style) {
+ string newName = Enum.GetName(typeof(ExcelBorderStyle), style);
+ return newName.Substring(0, 1).ToLower(CultureInfo.InvariantCulture)
+ + newName.Substring(1, newName.Length - 1);
+ }
+
+ public bool Exists { get; private set; }
+}
diff --git a/AppsheetEpplus/Style/XmlAccess/ExcelBorderXml.cs b/AppsheetEpplus/Style/XmlAccess/ExcelBorderXml.cs
new file mode 100644
index 0000000..f905799
--- /dev/null
+++ b/AppsheetEpplus/Style/XmlAccess/ExcelBorderXml.cs
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Xml access class for border top level
+/// </summary>
+public sealed class ExcelBorderXml : StyleXmlHelper {
+ internal ExcelBorderXml(XmlNamespaceManager nameSpaceManager)
+ : base(nameSpaceManager) {}
+
+ internal ExcelBorderXml(XmlNamespaceManager nsm, XmlNode topNode)
+ : base(nsm, topNode) {
+ _left = new(nsm, topNode.SelectSingleNode(_leftPath, nsm));
+ _right = new(nsm, topNode.SelectSingleNode(_rightPath, nsm));
+ _top = new(nsm, topNode.SelectSingleNode(_topPath, nsm));
+ _bottom = new(nsm, topNode.SelectSingleNode(_bottomPath, nsm));
+ _diagonal = new(nsm, topNode.SelectSingleNode(_diagonalPath, nsm));
+ _diagonalUp = GetBoolValue(topNode, _diagonalUpPath);
+ _diagonalDown = GetBoolValue(topNode, _diagonalDownPath);
+ }
+
+ internal override string Id =>
+ Left.Id + Right.Id + Top.Id + Bottom.Id + Diagonal.Id + DiagonalUp + DiagonalDown;
+
+ private const string _leftPath = "d:left";
+ private ExcelBorderItemXml _left;
+
+ /// <summary>
+ /// Left border style properties
+ /// </summary>
+ public ExcelBorderItemXml Left {
+ get => _left;
+ internal set => _left = value;
+ }
+
+ private const string _rightPath = "d:right";
+ private ExcelBorderItemXml _right;
+
+ /// <summary>
+ /// Right border style properties
+ /// </summary>
+ public ExcelBorderItemXml Right {
+ get => _right;
+ internal set => _right = value;
+ }
+
+ private const string _topPath = "d:top";
+ private ExcelBorderItemXml _top;
+
+ /// <summary>
+ /// Top border style properties
+ /// </summary>
+ public ExcelBorderItemXml Top {
+ get => _top;
+ internal set => _top = value;
+ }
+
+ private const string _bottomPath = "d:bottom";
+ private ExcelBorderItemXml _bottom;
+
+ /// <summary>
+ /// Bottom border style properties
+ /// </summary>
+ public ExcelBorderItemXml Bottom {
+ get => _bottom;
+ internal set => _bottom = value;
+ }
+
+ private const string _diagonalPath = "d:diagonal";
+ private ExcelBorderItemXml _diagonal;
+
+ /// <summary>
+ /// Diagonal border style properties
+ /// </summary>
+ public ExcelBorderItemXml Diagonal {
+ get => _diagonal;
+ internal set => _diagonal = value;
+ }
+
+ private const string _diagonalUpPath = "@diagonalUp";
+ private bool _diagonalUp;
+
+ /// <summary>
+ /// Diagonal up border
+ /// </summary>
+ public bool DiagonalUp {
+ get => _diagonalUp;
+ internal set => _diagonalUp = value;
+ }
+
+ private const string _diagonalDownPath = "@diagonalDown";
+ private bool _diagonalDown;
+
+ /// <summary>
+ /// Diagonal down border
+ /// </summary>
+ public bool DiagonalDown {
+ get => _diagonalDown;
+ internal set => _diagonalDown = value;
+ }
+
+ internal ExcelBorderXml Copy() {
+ ExcelBorderXml newBorder = new ExcelBorderXml(NameSpaceManager);
+ newBorder.Bottom = _bottom.Copy();
+ newBorder.Diagonal = _diagonal.Copy();
+ newBorder.Left = _left.Copy();
+ newBorder.Right = _right.Copy();
+ newBorder.Top = _top.Copy();
+ newBorder.DiagonalUp = _diagonalUp;
+ newBorder.DiagonalDown = _diagonalDown;
+
+ return newBorder;
+ }
+
+ internal override XmlNode CreateXmlNode(XmlNode topNode) {
+ TopNode = topNode;
+ CreateNode(_leftPath);
+ topNode.AppendChild(_left.CreateXmlNode(TopNode.SelectSingleNode(_leftPath, NameSpaceManager)));
+ CreateNode(_rightPath);
+ topNode.AppendChild(
+ _right.CreateXmlNode(TopNode.SelectSingleNode(_rightPath, NameSpaceManager)));
+ CreateNode(_topPath);
+ topNode.AppendChild(_top.CreateXmlNode(TopNode.SelectSingleNode(_topPath, NameSpaceManager)));
+ CreateNode(_bottomPath);
+ topNode.AppendChild(
+ _bottom.CreateXmlNode(TopNode.SelectSingleNode(_bottomPath, NameSpaceManager)));
+ CreateNode(_diagonalPath);
+ topNode.AppendChild(
+ _diagonal.CreateXmlNode(TopNode.SelectSingleNode(_diagonalPath, NameSpaceManager)));
+ if (_diagonalUp) {
+ SetXmlNodeString(_diagonalUpPath, "1");
+ }
+ if (_diagonalDown) {
+ SetXmlNodeString(_diagonalDownPath, "1");
+ }
+ return topNode;
+ }
+}
diff --git a/AppsheetEpplus/Style/XmlAccess/ExcelColorXml.cs b/AppsheetEpplus/Style/XmlAccess/ExcelColorXml.cs
new file mode 100644
index 0000000..d1a3792
--- /dev/null
+++ b/AppsheetEpplus/Style/XmlAccess/ExcelColorXml.cs
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System;
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Xml access class for color
+/// </summary>
+public sealed class ExcelColorXml : StyleXmlHelper {
+ internal ExcelColorXml(XmlNamespaceManager nameSpaceManager)
+ : base(nameSpaceManager) {
+ _auto = false;
+ _theme = "";
+ _tint = 0;
+ _rgb = "";
+ _indexed = int.MinValue;
+ }
+
+ internal ExcelColorXml(XmlNamespaceManager nsm, XmlNode topNode)
+ : base(nsm, topNode) {
+ if (topNode == null) {
+ _exists = false;
+ } else {
+ _exists = true;
+ _auto = GetXmlNodeBool("@auto");
+ _theme = GetXmlNodeString("@theme");
+ _tint = GetXmlNodeDecimalNull("@tint") ?? decimal.MinValue;
+ _rgb = GetXmlNodeString("@rgb");
+ _indexed = GetXmlNodeIntNull("@indexed") ?? int.MinValue;
+ }
+ }
+
+ internal override string Id => _auto + "|" + _theme + "|" + _tint + "|" + _rgb + "|" + _indexed;
+
+ private bool _auto;
+
+ public bool Auto {
+ get => _auto;
+ set {
+ _auto = value;
+ _exists = true;
+ Clear();
+ }
+ }
+
+ private string _theme;
+
+ /// <summary>
+ /// Theme color value
+ /// </summary>
+ public string Theme => _theme;
+
+ private decimal _tint;
+
+ /// <summary>
+ /// Tint
+ /// </summary>
+ public decimal Tint {
+ get {
+ if (_tint == decimal.MinValue) {
+ return 0;
+ }
+ return _tint;
+ }
+ set {
+ _tint = value;
+ _exists = true;
+ }
+ }
+
+ private string _rgb;
+
+ /// <summary>
+ /// RGB value
+ /// </summary>
+ public string Rgb {
+ get => _rgb;
+ set {
+ _rgb = value;
+ _exists = true;
+ _indexed = int.MinValue;
+ _auto = false;
+ }
+ }
+
+ private int _indexed;
+
+ /// <summary>
+ /// Indexed color value
+ /// </summary>
+ public int Indexed {
+ get => (_indexed == int.MinValue ? 0 : _indexed);
+ set {
+ if (value < 0 || value > 65) {
+ throw (new ArgumentOutOfRangeException("Index out of range"));
+ }
+ Clear();
+ _indexed = value;
+ _exists = true;
+ }
+ }
+
+ internal void Clear() {
+ _theme = "";
+ _tint = decimal.MinValue;
+ _indexed = int.MinValue;
+ _rgb = "";
+ _auto = false;
+ }
+
+ internal ExcelColorXml Copy() {
+ return new(NameSpaceManager) {
+ _indexed = _indexed,
+ _tint = _tint,
+ _rgb = _rgb,
+ _theme = _theme,
+ _auto = _auto,
+ _exists = _exists,
+ };
+ }
+
+ internal override XmlNode CreateXmlNode(XmlNode topNode) {
+ TopNode = topNode;
+ if (_rgb != "") {
+ SetXmlNodeString("@rgb", _rgb);
+ } else if (_indexed >= 0) {
+ SetXmlNodeString("@indexed", _indexed.ToString());
+ } else if (_auto) {
+ SetXmlNodeBool("@auto", _auto);
+ } else {
+ SetXmlNodeString("@theme", _theme);
+ }
+ if (_tint != decimal.MinValue) {
+ SetXmlNodeString("@tint", _tint.ToString(CultureInfo.InvariantCulture));
+ }
+ return TopNode;
+ }
+
+ private bool _exists;
+
+ internal bool Exists => _exists;
+}
diff --git a/AppsheetEpplus/Style/XmlAccess/ExcelFillXml.cs b/AppsheetEpplus/Style/XmlAccess/ExcelFillXml.cs
new file mode 100644
index 0000000..5a00bcd
--- /dev/null
+++ b/AppsheetEpplus/Style/XmlAccess/ExcelFillXml.cs
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System;
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Xml access class for fills
+/// </summary>
+public class ExcelFillXml : StyleXmlHelper {
+ internal ExcelFillXml(XmlNamespaceManager nameSpaceManager)
+ : base(nameSpaceManager) {
+ _fillPatternType = ExcelFillStyle.None;
+ _backgroundColor = new(NameSpaceManager);
+ _patternColor = new(NameSpaceManager);
+ }
+
+ internal ExcelFillXml(XmlNamespaceManager nsm, XmlNode topNode)
+ : base(nsm, topNode) {
+ PatternType = GetPatternType(GetXmlNodeString(_fillPatternTypePath));
+ _backgroundColor = new(nsm, topNode.SelectSingleNode(_backgroundColorPath, nsm));
+ _patternColor = new(nsm, topNode.SelectSingleNode(_patternColorPath, nsm));
+ }
+
+ private ExcelFillStyle GetPatternType(string patternType) {
+ return Enum.TryParse<ExcelFillStyle>(patternType, true, out var result)
+ ? result
+ : ExcelFillStyle.None;
+ }
+
+ internal override string Id => PatternType + PatternColor.Id + BackgroundColor.Id;
+
+ private const string _fillPatternTypePath = "d:patternFill/@patternType";
+ protected ExcelFillStyle _fillPatternType;
+
+ /// <summary>
+ /// Cell fill pattern style
+ /// </summary>
+ public ExcelFillStyle PatternType {
+ get => _fillPatternType;
+ set => _fillPatternType = value;
+ }
+
+ protected ExcelColorXml _patternColor;
+ private const string _patternColorPath = "d:patternFill/d:bgColor";
+
+ /// <summary>
+ /// Pattern color
+ /// </summary>
+ public ExcelColorXml PatternColor {
+ get => _patternColor;
+ internal set => _patternColor = value;
+ }
+
+ protected ExcelColorXml _backgroundColor;
+ private const string _backgroundColorPath = "d:patternFill/d:fgColor";
+
+ /// <summary>
+ /// Cell background color
+ /// </summary>
+ public ExcelColorXml BackgroundColor {
+ get => _backgroundColor;
+ internal set => _backgroundColor = value;
+ }
+
+ internal virtual ExcelFillXml Copy() {
+ ExcelFillXml newFill = new ExcelFillXml(NameSpaceManager);
+ newFill.PatternType = _fillPatternType;
+ newFill.BackgroundColor = _backgroundColor.Copy();
+ newFill.PatternColor = _patternColor.Copy();
+ return newFill;
+ }
+
+ internal override XmlNode CreateXmlNode(XmlNode topNode) {
+ TopNode = topNode;
+ SetXmlNodeString(_fillPatternTypePath, SetPatternString(_fillPatternType));
+ if (PatternType != ExcelFillStyle.None) {
+ XmlNode pattern = topNode.SelectSingleNode(_fillPatternTypePath, NameSpaceManager);
+ if (BackgroundColor.Exists) {
+ CreateNode(_backgroundColorPath);
+ BackgroundColor.CreateXmlNode(
+ topNode.SelectSingleNode(_backgroundColorPath, NameSpaceManager));
+ if (PatternColor.Exists) {
+ CreateNode(_patternColorPath);
+ //topNode.AppendChild(PatternColor.CreateXmlNode(topNode.SelectSingleNode(_patternColorPath, NameSpaceManager)));
+ PatternColor.CreateXmlNode(topNode.SelectSingleNode(_patternColorPath, NameSpaceManager));
+ }
+ }
+ }
+ return topNode;
+ }
+
+ private string SetPatternString(ExcelFillStyle pattern) {
+ string newName = Enum.GetName(typeof(ExcelFillStyle), pattern);
+ return newName.Substring(0, 1).ToLower(CultureInfo.InvariantCulture)
+ + newName.Substring(1, newName.Length - 1);
+ }
+}
diff --git a/AppsheetEpplus/Style/XmlAccess/ExcelFontXml.cs b/AppsheetEpplus/Style/XmlAccess/ExcelFontXml.cs
new file mode 100644
index 0000000..ef66ee9
--- /dev/null
+++ b/AppsheetEpplus/Style/XmlAccess/ExcelFontXml.cs
@@ -0,0 +1,294 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System;
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Xml access class for fonts
+/// </summary>
+public sealed class ExcelFontXml : StyleXmlHelper {
+ internal ExcelFontXml(XmlNamespaceManager nameSpaceManager)
+ : base(nameSpaceManager) {
+ _name = "";
+ _size = 0;
+ _family = int.MinValue;
+ _scheme = "";
+ _color = _color = new(NameSpaceManager);
+ _bold = false;
+ _italic = false;
+ _strike = false;
+ _underlineType = ExcelUnderLineType.None;
+ _verticalAlign = "";
+ }
+
+ internal ExcelFontXml(XmlNamespaceManager nsm, XmlNode topNode)
+ : base(nsm, topNode) {
+ _name = GetXmlNodeString(_namePath);
+ _size = (float)GetXmlNodeDecimal(_sizePath);
+ _family = GetXmlNodeIntNull(_familyPath) ?? int.MinValue;
+ _scheme = GetXmlNodeString(_schemePath);
+ _color = new(nsm, topNode.SelectSingleNode(_colorPath, nsm));
+ _bold = GetBoolValue(topNode, _boldPath);
+ _italic = GetBoolValue(topNode, _italicPath);
+ _strike = GetBoolValue(topNode, _strikePath);
+ _verticalAlign = GetXmlNodeString(_verticalAlignPath);
+ if (topNode.SelectSingleNode(_underLinedPath, NameSpaceManager) != null) {
+ string ut = GetXmlNodeString(_underLinedPath + "/@val");
+ if (ut == "") {
+ _underlineType = ExcelUnderLineType.Single;
+ } else {
+ if (!Enum.TryParse(ut, true, out _underlineType)) {
+ _underlineType = ExcelUnderLineType.Single;
+ }
+ }
+ } else {
+ _underlineType = ExcelUnderLineType.None;
+ }
+ }
+
+ internal override string Id =>
+ Name
+ + "|"
+ + Size
+ + "|"
+ + Family
+ + "|"
+ + Color.Id
+ + "|"
+ + Scheme
+ + "|"
+ + Bold
+ + "|"
+ + Italic
+ + "|"
+ + Strike
+ + "|"
+ + VerticalAlign
+ + "|"
+ + UnderLineType;
+
+ private const string _namePath = "d:name/@val";
+ private string _name;
+
+ /// <summary>
+ /// The name of the font
+ /// </summary>
+ public string Name {
+ get => _name;
+ set {
+ Scheme = ""; //Reset schema to avoid corrupt file if unsupported font is selected.
+ _name = value;
+ }
+ }
+
+ private const string _sizePath = "d:sz/@val";
+ private float _size;
+
+ /// <summary>
+ /// Font size
+ /// </summary>
+ public float Size {
+ get => _size;
+ set => _size = value;
+ }
+
+ private const string _familyPath = "d:family/@val";
+ private int _family;
+
+ /// <summary>
+ /// Font family
+ /// </summary>
+ public int Family {
+ get => (_family == int.MinValue ? 0 : _family);
+ set => _family = value;
+ }
+
+ private ExcelColorXml _color;
+ private const string _colorPath = "d:color";
+
+ /// <summary>
+ /// Text color
+ /// </summary>
+ public ExcelColorXml Color {
+ get => _color;
+ internal set => _color = value;
+ }
+
+ private const string _schemePath = "d:scheme/@val";
+ private string _scheme = "";
+
+ /// <summary>
+ /// Font Scheme
+ /// </summary>
+ public string Scheme {
+ get => _scheme;
+ private set => _scheme = value;
+ }
+
+ private const string _boldPath = "d:b";
+ private bool _bold;
+
+ /// <summary>
+ /// If the font is bold
+ /// </summary>
+ public bool Bold {
+ get => _bold;
+ set => _bold = value;
+ }
+
+ private const string _italicPath = "d:i";
+ private bool _italic;
+
+ /// <summary>
+ /// If the font is italic
+ /// </summary>
+ public bool Italic {
+ get => _italic;
+ set => _italic = value;
+ }
+
+ private const string _strikePath = "d:strike";
+ private bool _strike;
+
+ /// <summary>
+ /// If the font is striked out
+ /// </summary>
+ public bool Strike {
+ get => _strike;
+ set => _strike = value;
+ }
+
+ private const string _underLinedPath = "d:u";
+
+ /// <summary>
+ /// If the font is underlined.
+ /// When set to true a the text is underlined with a single line
+ /// </summary>
+ public bool UnderLine {
+ get => UnderLineType != ExcelUnderLineType.None;
+ set => _underlineType = value ? ExcelUnderLineType.Single : ExcelUnderLineType.None;
+ }
+
+ private ExcelUnderLineType _underlineType;
+
+ /// <summary>
+ /// If the font is underlined
+ /// </summary>
+ public ExcelUnderLineType UnderLineType {
+ get => _underlineType;
+ set => _underlineType = value;
+ }
+
+ private const string _verticalAlignPath = "d:vertAlign/@val";
+ private string _verticalAlign;
+
+ /// <summary>
+ /// Vertical aligned
+ /// </summary>
+ public string VerticalAlign {
+ get => _verticalAlign;
+ set => _verticalAlign = value;
+ }
+
+ internal ExcelFontXml Copy() {
+ ExcelFontXml newFont = new ExcelFontXml(NameSpaceManager);
+ newFont.Name = _name;
+ newFont.Size = _size;
+ newFont.Family = _family;
+ newFont.Scheme = _scheme;
+ newFont.Bold = _bold;
+ newFont.Italic = _italic;
+ newFont.UnderLineType = _underlineType;
+ newFont.Strike = _strike;
+ newFont.VerticalAlign = _verticalAlign;
+ newFont.Color = Color.Copy();
+ return newFont;
+ }
+
+ internal override XmlNode CreateXmlNode(XmlNode topElement) {
+ TopNode = topElement;
+
+ if (_bold) {
+ CreateNode(_boldPath);
+ } else {
+ DeleteAllNode(_boldPath);
+ }
+ if (_italic) {
+ CreateNode(_italicPath);
+ } else {
+ DeleteAllNode(_italicPath);
+ }
+ if (_strike) {
+ CreateNode(_strikePath);
+ } else {
+ DeleteAllNode(_strikePath);
+ }
+
+ if (_underlineType == ExcelUnderLineType.None) {
+ DeleteAllNode(_underLinedPath);
+ } else if (_underlineType == ExcelUnderLineType.Single) {
+ CreateNode(_underLinedPath);
+ } else {
+ var v = _underlineType.ToString();
+ SetXmlNodeString(
+ _underLinedPath + "/@val",
+ v.Substring(0, 1).ToLower(CultureInfo.InvariantCulture) + v.Substring(1));
+ }
+
+ if (_verticalAlign != "") {
+ SetXmlNodeString(_verticalAlignPath, _verticalAlign);
+ }
+ if (_size > 0) {
+ SetXmlNodeString(_sizePath, _size.ToString(CultureInfo.InvariantCulture));
+ }
+ if (_color.Exists) {
+ CreateNode(_colorPath);
+ TopNode.AppendChild(
+ _color.CreateXmlNode(TopNode.SelectSingleNode(_colorPath, NameSpaceManager)));
+ }
+ if (!string.IsNullOrEmpty(_name)) {
+ SetXmlNodeString(_namePath, _name);
+ }
+ if (_family > int.MinValue) {
+ SetXmlNodeString(_familyPath, _family.ToString());
+ }
+ if (_scheme != "") {
+ SetXmlNodeString(_schemePath, _scheme);
+ }
+
+ return TopNode;
+ }
+}
diff --git a/AppsheetEpplus/Style/XmlAccess/ExcelGradientFillXml.cs b/AppsheetEpplus/Style/XmlAccess/ExcelGradientFillXml.cs
new file mode 100644
index 0000000..fb4a173
--- /dev/null
+++ b/AppsheetEpplus/Style/XmlAccess/ExcelGradientFillXml.cs
@@ -0,0 +1,184 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Xml access class for gradient fillsde
+/// </summary>
+public sealed class ExcelGradientFillXml : ExcelFillXml {
+ internal ExcelGradientFillXml(XmlNamespaceManager nameSpaceManager)
+ : base(nameSpaceManager) {
+ GradientColor1 = new(nameSpaceManager);
+ GradientColor2 = new(nameSpaceManager);
+ }
+
+ internal ExcelGradientFillXml(XmlNamespaceManager nsm, XmlNode topNode)
+ : base(nsm, topNode) {
+ Degree = GetXmlNodeDouble(_degreePath);
+ Type =
+ GetXmlNodeString(_typePath) == "path"
+ ? ExcelFillGradientType.Path
+ : ExcelFillGradientType.Linear;
+ GradientColor1 = new(nsm, topNode.SelectSingleNode(_gradientColor1Path, nsm));
+ GradientColor2 = new(nsm, topNode.SelectSingleNode(_gradientColor2Path, nsm));
+
+ Top = GetXmlNodeDouble(_topPath);
+ Bottom = GetXmlNodeDouble(_bottomPath);
+ Left = GetXmlNodeDouble(_leftPath);
+ Right = GetXmlNodeDouble(_rightPath);
+ }
+
+ private const string _typePath = "d:gradientFill/@type";
+
+ /// <summary>
+ /// Type of gradient fill.
+ /// </summary>
+ public ExcelFillGradientType Type { get; internal set; }
+
+ private const string _degreePath = "d:gradientFill/@degree";
+
+ /// <summary>
+ /// Angle of the linear gradient
+ /// </summary>
+ public double Degree { get; internal set; }
+
+ private const string _gradientColor1Path = "d:gradientFill/d:stop[@position=\"0\"]/d:color";
+
+ /// <summary>
+ /// Gradient color 1
+ /// </summary>
+ public ExcelColorXml GradientColor1 { get; private set; }
+
+ private const string _gradientColor2Path = "d:gradientFill/d:stop[@position=\"1\"]/d:color";
+
+ /// <summary>
+ /// Gradient color 2
+ /// </summary>
+ public ExcelColorXml GradientColor2 { get; private set; }
+
+ private const string _bottomPath = "d:gradientFill/@bottom";
+
+ /// <summary>
+ /// Percentage format bottom
+ /// </summary>
+ public double Bottom { get; internal set; }
+
+ private const string _topPath = "d:gradientFill/@top";
+
+ /// <summary>
+ /// Percentage format top
+ /// </summary>
+ public double Top { get; internal set; }
+
+ private const string _leftPath = "d:gradientFill/@left";
+
+ /// <summary>
+ /// Percentage format left
+ /// </summary>
+ public double Left { get; internal set; }
+
+ private const string _rightPath = "d:gradientFill/@right";
+
+ /// <summary>
+ /// Percentage format right
+ /// </summary>
+ public double Right { get; internal set; }
+
+ internal override string Id =>
+ base.Id + Degree + GradientColor1.Id + GradientColor2.Id + Type + Left + Right + Bottom + Top;
+
+ internal override ExcelFillXml Copy() {
+ ExcelGradientFillXml newFill = new ExcelGradientFillXml(NameSpaceManager);
+ newFill.PatternType = _fillPatternType;
+ newFill.BackgroundColor = _backgroundColor.Copy();
+ newFill.PatternColor = _patternColor.Copy();
+
+ newFill.GradientColor1 = GradientColor1.Copy();
+ newFill.GradientColor2 = GradientColor2.Copy();
+ newFill.Type = Type;
+ newFill.Degree = Degree;
+ newFill.Top = Top;
+ newFill.Bottom = Bottom;
+ newFill.Left = Left;
+ newFill.Right = Right;
+
+ return newFill;
+ }
+
+ internal override XmlNode CreateXmlNode(XmlNode topNode) {
+ TopNode = topNode;
+ CreateNode("d:gradientFill");
+ if (Type == ExcelFillGradientType.Path) {
+ SetXmlNodeString(_typePath, "path");
+ }
+ if (!double.IsNaN(Degree)) {
+ SetXmlNodeString(_degreePath, Degree.ToString(CultureInfo.InvariantCulture));
+ }
+ if (GradientColor1 != null) {
+ /*** Gradient color node 1***/
+ var node = TopNode.SelectSingleNode("d:gradientFill", NameSpaceManager);
+ var stopNode = node.OwnerDocument.CreateElement("stop", ExcelPackage._schemaMain);
+ stopNode.SetAttribute("position", "0");
+ node.AppendChild(stopNode);
+ var colorNode = node.OwnerDocument.CreateElement("color", ExcelPackage._schemaMain);
+ stopNode.AppendChild(colorNode);
+ GradientColor1.CreateXmlNode(colorNode);
+
+ /*** Gradient color node 2***/
+ stopNode = node.OwnerDocument.CreateElement("stop", ExcelPackage._schemaMain);
+ stopNode.SetAttribute("position", "1");
+ node.AppendChild(stopNode);
+ colorNode = node.OwnerDocument.CreateElement("color", ExcelPackage._schemaMain);
+ stopNode.AppendChild(colorNode);
+
+ GradientColor2.CreateXmlNode(colorNode);
+ }
+ if (!double.IsNaN(Top)) {
+ SetXmlNodeString(_topPath, Top.ToString("F5", CultureInfo.InvariantCulture));
+ }
+ if (!double.IsNaN(Bottom)) {
+ SetXmlNodeString(_bottomPath, Bottom.ToString("F5", CultureInfo.InvariantCulture));
+ }
+ if (!double.IsNaN(Left)) {
+ SetXmlNodeString(_leftPath, Left.ToString("F5", CultureInfo.InvariantCulture));
+ }
+ if (!double.IsNaN(Right)) {
+ SetXmlNodeString(_rightPath, Right.ToString("F5", CultureInfo.InvariantCulture));
+ }
+
+ return topNode;
+ }
+}
diff --git a/AppsheetEpplus/Style/XmlAccess/ExcelNamedStyleXml.cs b/AppsheetEpplus/Style/XmlAccess/ExcelNamedStyleXml.cs
new file mode 100644
index 0000000..8039ebd
--- /dev/null
+++ b/AppsheetEpplus/Style/XmlAccess/ExcelNamedStyleXml.cs
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Xml access class for named styles
+/// </summary>
+public sealed class ExcelNamedStyleXml : StyleXmlHelper {
+ private readonly ExcelStyles _styles;
+
+ internal ExcelNamedStyleXml(XmlNamespaceManager nameSpaceManager, ExcelStyles styles)
+ : base(nameSpaceManager) {
+ _styles = styles;
+ BuildInId = int.MinValue;
+ }
+
+ internal ExcelNamedStyleXml(
+ XmlNamespaceManager nameSpaceManager,
+ XmlNode topNode,
+ ExcelStyles styles)
+ : base(nameSpaceManager, topNode) {
+ StyleXfId = GetXmlNodeInt(_idPath);
+ Name = GetXmlNodeString(_namePath);
+ BuildInId = GetXmlNodeInt(_buildInIdPath);
+ CustomBuildin = GetXmlNodeBool(_customBuiltinPath);
+
+ _styles = styles;
+ _style = new(styles, styles.NamedStylePropertyChange, -1, Name, _styleXfId);
+ }
+
+ internal override string Id => Name;
+
+ private int _styleXfId;
+ private const string _idPath = "@xfId";
+
+ /// <summary>
+ /// Named style index
+ /// </summary>
+ public int StyleXfId {
+ get => _styleXfId;
+ set => _styleXfId = value;
+ }
+
+ private int _xfId = int.MinValue;
+
+ /// <summary>
+ /// Style index
+ /// </summary>
+ internal int XfId {
+ get => _xfId;
+ set => _xfId = value;
+ }
+
+ private const string _buildInIdPath = "@builtinId";
+
+ public int BuildInId { get; set; }
+
+ private const string _customBuiltinPath = "@customBuiltin";
+
+ public bool CustomBuildin { get; set; }
+
+ private const string _namePath = "@name";
+ private string _name;
+
+ /// <summary>
+ /// Name of the style
+ /// </summary>
+ public string Name {
+ get => _name;
+ internal set => _name = value;
+ }
+
+ private ExcelStyle _style;
+
+ /// <summary>
+ /// The style object
+ /// </summary>
+ public ExcelStyle Style {
+ get => _style;
+ internal set => _style = value;
+ }
+
+ internal override XmlNode CreateXmlNode(XmlNode topNode) {
+ TopNode = topNode;
+ SetXmlNodeString(_namePath, _name);
+ SetXmlNodeString("@xfId", _styles.CellStyleXfs[StyleXfId].newID.ToString());
+ if (BuildInId >= 0) {
+ SetXmlNodeString("@builtinId", BuildInId.ToString());
+ }
+ if (CustomBuildin) {
+ SetXmlNodeBool(_customBuiltinPath, true);
+ }
+ return TopNode;
+ }
+}
diff --git a/AppsheetEpplus/Style/XmlAccess/ExcelNumberFormatXml.cs b/AppsheetEpplus/Style/XmlAccess/ExcelNumberFormatXml.cs
new file mode 100644
index 0000000..7bcbf32
--- /dev/null
+++ b/AppsheetEpplus/Style/XmlAccess/ExcelNumberFormatXml.cs
@@ -0,0 +1,696 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Xml access class for number formats
+/// </summary>
+public sealed class ExcelNumberFormatXml : StyleXmlHelper {
+ internal ExcelNumberFormatXml(XmlNamespaceManager nameSpaceManager)
+ : base(nameSpaceManager) {}
+
+ internal ExcelNumberFormatXml(XmlNamespaceManager nameSpaceManager, bool buildIn)
+ : base(nameSpaceManager) {
+ BuildIn = buildIn;
+ }
+
+ internal ExcelNumberFormatXml(XmlNamespaceManager nsm, XmlNode topNode)
+ : base(nsm, topNode) {
+ _numFmtId = GetXmlNodeInt("@numFmtId");
+ _format = GetXmlNodeString("@formatCode");
+ }
+
+ public bool BuildIn { get; private set; }
+
+ private int _numFmtId;
+
+ // const string idPath = "@numFmtId";
+ /// <summary>
+ /// Id for number format
+ ///
+ /// Build in ID's
+ ///
+ /// 0 General
+ /// 1 0
+ /// 2 0.00
+ /// 3 #,##0
+ /// 4 #,##0.00
+ /// 9 0%
+ /// 10 0.00%
+ /// 11 0.00E+00
+ /// 12 # ?/?
+ /// 13 # ??/??
+ /// 14 mm-dd-yy
+ /// 15 d-mmm-yy
+ /// 16 d-mmm
+ /// 17 mmm-yy
+ /// 18 h:mm AM/PM
+ /// 19 h:mm:ss AM/PM
+ /// 20 h:mm
+ /// 21 h:mm:ss
+ /// 22 m/d/yy h:mm
+ /// 37 #,##0 ;(#,##0)
+ /// 38 #,##0 ;[Red](#,##0)
+ /// 39 #,##0.00;(#,##0.00)
+ /// 40 #,##0.00;[Red](#,##0.00)
+ /// 45 mm:ss
+ /// 46 [h]:mm:ss
+ /// 47 mmss.0
+ /// 48 ##0.0E+0
+ /// 49 @
+ /// </summary>
+ public int NumFmtId {
+ get => _numFmtId;
+ set => _numFmtId = value;
+ }
+
+ internal override string Id => _format;
+
+ private string _format = string.Empty;
+
+ public string Format {
+ get => _format;
+ set {
+ _numFmtId = ExcelNumberFormat.GetFromBuildIdFromFormat(value);
+ _format = value;
+ }
+ }
+
+ internal string GetNewId(int numFmtId, string format) {
+ if (numFmtId < 0) {
+ numFmtId = ExcelNumberFormat.GetFromBuildIdFromFormat(format);
+ }
+ return numFmtId.ToString();
+ }
+
+ internal static void AddBuildIn(
+ XmlNamespaceManager nameSpaceManager,
+ ExcelStyleCollection<ExcelNumberFormatXml> numberFormats) {
+ numberFormats.Add(
+ "General",
+ new(nameSpaceManager, true) {
+ NumFmtId = 0,
+ Format = "General",
+ });
+ numberFormats.Add(
+ "0",
+ new(nameSpaceManager, true) {
+ NumFmtId = 1,
+ Format = "0",
+ });
+ numberFormats.Add(
+ "0.00",
+ new(nameSpaceManager, true) {
+ NumFmtId = 2,
+ Format = "0.00",
+ });
+ numberFormats.Add(
+ "#,##0",
+ new(nameSpaceManager, true) {
+ NumFmtId = 3,
+ Format = "#,##0",
+ });
+ numberFormats.Add(
+ "#,##0.00",
+ new(nameSpaceManager, true) {
+ NumFmtId = 4,
+ Format = "#,##0.00",
+ });
+ numberFormats.Add(
+ "0%",
+ new(nameSpaceManager, true) {
+ NumFmtId = 9,
+ Format = "0%",
+ });
+ numberFormats.Add(
+ "0.00%",
+ new(nameSpaceManager, true) {
+ NumFmtId = 10,
+ Format = "0.00%",
+ });
+ numberFormats.Add(
+ "0.00E+00",
+ new(nameSpaceManager, true) {
+ NumFmtId = 11,
+ Format = "0.00E+00",
+ });
+ numberFormats.Add(
+ "# ?/?",
+ new(nameSpaceManager, true) {
+ NumFmtId = 12,
+ Format = "# ?/?",
+ });
+ numberFormats.Add(
+ "# ??/??",
+ new(nameSpaceManager, true) {
+ NumFmtId = 13,
+ Format = "# ??/??",
+ });
+ numberFormats.Add(
+ "mm-dd-yy",
+ new(nameSpaceManager, true) {
+ NumFmtId = 14,
+ Format = "mm-dd-yy",
+ });
+ numberFormats.Add(
+ "d-mmm-yy",
+ new(nameSpaceManager, true) {
+ NumFmtId = 15,
+ Format = "d-mmm-yy",
+ });
+ numberFormats.Add(
+ "d-mmm",
+ new(nameSpaceManager, true) {
+ NumFmtId = 16,
+ Format = "d-mmm",
+ });
+ numberFormats.Add(
+ "mmm-yy",
+ new(nameSpaceManager, true) {
+ NumFmtId = 17,
+ Format = "mmm-yy",
+ });
+ numberFormats.Add(
+ "h:mm AM/PM",
+ new(nameSpaceManager, true) {
+ NumFmtId = 18,
+ Format = "h:mm AM/PM",
+ });
+ numberFormats.Add(
+ "h:mm:ss AM/PM",
+ new(nameSpaceManager, true) {
+ NumFmtId = 19,
+ Format = "h:mm:ss AM/PM",
+ });
+ numberFormats.Add(
+ "h:mm",
+ new(nameSpaceManager, true) {
+ NumFmtId = 20,
+ Format = "h:mm",
+ });
+ numberFormats.Add(
+ "h:mm:ss",
+ new(nameSpaceManager, true) {
+ NumFmtId = 21,
+ Format = "h:mm:ss",
+ });
+ numberFormats.Add(
+ "m/d/yy h:mm",
+ new(nameSpaceManager, true) {
+ NumFmtId = 22,
+ Format = "m/d/yy h:mm",
+ });
+ numberFormats.Add(
+ "#,##0 ;(#,##0)",
+ new(nameSpaceManager, true) {
+ NumFmtId = 37,
+ Format = "#,##0 ;(#,##0)",
+ });
+ numberFormats.Add(
+ "#,##0 ;[Red](#,##0)",
+ new(nameSpaceManager, true) {
+ NumFmtId = 38,
+ Format = "#,##0 ;[Red](#,##0)",
+ });
+ numberFormats.Add(
+ "#,##0.00;(#,##0.00)",
+ new(nameSpaceManager, true) {
+ NumFmtId = 39,
+ Format = "#,##0.00;(#,##0.00)",
+ });
+ numberFormats.Add(
+ "#,##0.00;[Red](#,##0.00)",
+ new(nameSpaceManager, true) {
+ NumFmtId = 40,
+ Format = "#,##0.00;[Red](#,#)",
+ });
+ numberFormats.Add(
+ "mm:ss",
+ new(nameSpaceManager, true) {
+ NumFmtId = 45,
+ Format = "mm:ss",
+ });
+ numberFormats.Add(
+ "[h]:mm:ss",
+ new(nameSpaceManager, true) {
+ NumFmtId = 46,
+ Format = "[h]:mm:ss",
+ });
+ numberFormats.Add(
+ "mmss.0",
+ new(nameSpaceManager, true) {
+ NumFmtId = 47,
+ Format = "mmss.0",
+ });
+ numberFormats.Add(
+ "##0.0",
+ new(nameSpaceManager, true) {
+ NumFmtId = 48,
+ Format = "##0.0",
+ });
+ numberFormats.Add(
+ "@",
+ new(nameSpaceManager, true) {
+ NumFmtId = 49,
+ Format = "@",
+ });
+
+ numberFormats.NextId = 164; //Start for custom formats.
+ }
+
+ internal override XmlNode CreateXmlNode(XmlNode topNode) {
+ TopNode = topNode;
+ SetXmlNodeString("@numFmtId", NumFmtId.ToString());
+ SetXmlNodeString("@formatCode", Format);
+ return TopNode;
+ }
+
+ internal enum eFormatType {
+ Unknown = 0,
+ Number = 1,
+ DateTime = 2,
+ }
+
+ private ExcelFormatTranslator _translator;
+
+ internal ExcelFormatTranslator FormatTranslator {
+ get {
+ if (_translator == null) {
+ _translator = new(Format, NumFmtId);
+ }
+ return _translator;
+ }
+ }
+
+ internal class ExcelFormatTranslator {
+ internal ExcelFormatTranslator(string format, int numFmtId) {
+ if (numFmtId == 14) {
+ NetFormat = NetFormatForWidth = "d";
+ NetTextFormat = NetTextFormatForWidth = "";
+ DataType = eFormatType.DateTime;
+ } else if (format.Equals("general", StringComparison.InvariantCultureIgnoreCase)) {
+ NetFormat = NetFormatForWidth = "0.#####";
+ NetTextFormat = NetTextFormatForWidth = "";
+ DataType = eFormatType.Number;
+ } else {
+ ToNetFormat(format, false);
+ ToNetFormat(format, true);
+ }
+ }
+
+ internal string NetTextFormat { get; private set; }
+
+ internal string NetFormat { get; private set; }
+
+ private CultureInfo _ci;
+
+ internal CultureInfo Culture {
+ get {
+ if (_ci == null) {
+ return CultureInfo.CurrentCulture;
+ }
+ return _ci;
+ }
+ private set => _ci = value;
+ }
+
+ internal eFormatType DataType { get; private set; }
+
+ internal string NetTextFormatForWidth { get; private set; }
+
+ internal string NetFormatForWidth { get; private set; }
+
+ internal string FractionFormat { get; private set; }
+
+ private void ToNetFormat(string excelFormat, bool forColWidth) {
+ DataType = eFormatType.Unknown;
+ int secCount = 0;
+ bool isText = false;
+ bool isBracket = false;
+ string bracketText = "";
+ bool prevBslsh = false;
+ bool useMinute = false;
+ bool prevUnderScore = false;
+ bool ignoreNext = false;
+ string specialDateFormat = "";
+ bool containsAmPm = excelFormat.Contains("AM/PM");
+ List<int> lstDec = [];
+ StringBuilder sb = new StringBuilder();
+ Culture = null;
+ var format = "";
+ var text = "";
+ char clc;
+
+ if (containsAmPm) {
+ excelFormat = Regex.Replace(excelFormat, "AM/PM", "");
+ DataType = eFormatType.DateTime;
+ }
+
+ for (int pos = 0; pos < excelFormat.Length; pos++) {
+ char c = excelFormat[pos];
+ if (c == '"') {
+ isText = !isText;
+ } else {
+ if (ignoreNext) {
+ ignoreNext = false;
+ continue;
+ }
+ if (isText && !isBracket) {
+ sb.Append(c);
+ } else if (isBracket) {
+ if (c == ']') {
+ isBracket = false;
+ if (bracketText[0]
+ == '$') //Local Info
+ {
+ string[] li = Regex.Split(bracketText, "-");
+ if (li[0].Length > 1) {
+ sb.Append("\"" + li[0].Substring(1, li[0].Length - 1) + "\""); //Currency symbol
+ }
+ if (li.Length > 1) {
+ if (li[1].Equals("f800", StringComparison.InvariantCultureIgnoreCase)) {
+ specialDateFormat = "D";
+ } else if (li[1].Equals("f400", StringComparison.InvariantCultureIgnoreCase)) {
+ specialDateFormat = "T";
+ } else {
+ var num = int.Parse(li[1], NumberStyles.HexNumber);
+ try {
+ Culture = CultureInfo.GetCultureInfo(num & 0xFFFF);
+ } catch {
+ Culture = null;
+ }
+ }
+ }
+ } else if (bracketText[0] == 't') {
+ sb.Append("hh"); //TODO:This will not be correct for dates over 24H.
+ } else if (bracketText[0] == 'h') {
+ specialDateFormat = "hh"; //TODO:This will not be correct for dates over 24H.
+ }
+ } else {
+ bracketText += c;
+ }
+ } else if (prevUnderScore) {
+ if (forColWidth) {
+ sb.AppendFormat("\"{0}\"", c);
+ }
+ prevUnderScore = false;
+ } else {
+ if (c
+ == ';') //We use first part (for positive only at this stage)
+ {
+ secCount++;
+ if (DataType == eFormatType.DateTime || secCount == 3) {
+ //Add qoutes
+ if (DataType == eFormatType.DateTime) {
+ SetDecimal(lstDec, sb); //Remove?
+ }
+ lstDec = [];
+ format = sb.ToString();
+ sb = new();
+ } else {
+ sb.Append(c);
+ }
+ } else {
+ clc = c.ToString().ToLower(CultureInfo.InvariantCulture)[0]; //Lowercase character
+ //Set the datetype
+ if (DataType == eFormatType.Unknown) {
+ if (c == '0' || c == '#' || c == '.') {
+ DataType = eFormatType.Number;
+ } else if (clc == 'y'
+ || clc == 'm'
+ || clc == 'd'
+ || clc == 'h'
+ || clc == 'm'
+ || clc == 's') {
+ DataType = eFormatType.DateTime;
+ }
+ }
+
+ if (prevBslsh) {
+ if (c == '.' || c == ',') {
+ sb.Append('\\');
+ }
+ sb.Append(c);
+ prevBslsh = false;
+ } else if (c == '[') {
+ bracketText = "";
+ isBracket = true;
+ } else if (c == '\\') {
+ prevBslsh = true;
+ } else if (c == '0'
+ || c == '#'
+ || c == '.'
+ || c == ','
+ || c == '%'
+ || clc == 'd'
+ || clc == 's') {
+ sb.Append(c);
+ if (c == '.') {
+ lstDec.Add(sb.Length - 1);
+ }
+ } else if (clc == 'h') {
+ if (containsAmPm) {
+ sb.Append('h');
+ ;
+ } else {
+ sb.Append('H');
+ }
+ useMinute = true;
+ } else if (clc == 'm') {
+ if (useMinute) {
+ sb.Append('m');
+ } else {
+ sb.Append('M');
+ }
+ } else if (c
+ == '_') //Skip next but use for alignment
+ {
+ prevUnderScore = true;
+ } else if (c == '?') {
+ sb.Append(' ');
+ } else if (c == '/') {
+ if (DataType == eFormatType.Number) {
+ int startPos = pos - 1;
+ while (startPos >= 0
+ && (excelFormat[startPos] == '?'
+ || excelFormat[startPos] == '#'
+ || excelFormat[startPos] == '0')) {
+ startPos--;
+ }
+
+ if (startPos
+ > 0) //RemovePart
+ {
+ sb.Remove(sb.Length - (pos - startPos - 1), (pos - startPos - 1));
+ }
+
+ int endPos = pos + 1;
+ while (endPos < excelFormat.Length
+ && (excelFormat[endPos] == '?'
+ || excelFormat[endPos] == '#'
+ || (excelFormat[endPos] >= '0' && excelFormat[endPos] <= '9'))) {
+ endPos++;
+ }
+ pos = endPos;
+ if (FractionFormat != "") {
+ FractionFormat = excelFormat.Substring(startPos + 1, endPos - startPos - 1);
+ }
+ sb.Append('?'); //Will be replaced later on by the fraction
+ } else {
+ sb.Append('/');
+ }
+ } else if (c == '*') {
+ //repeat char--> ignore
+ ignoreNext = true;
+ } else if (c == '@') {
+ sb.Append("{0}");
+ } else {
+ sb.Append(c);
+ }
+ }
+ }
+ }
+ }
+
+ //Add qoutes
+ if (DataType == eFormatType.DateTime) {
+ SetDecimal(lstDec, sb); //Remove?
+ }
+
+ // AM/PM format
+ if (containsAmPm) {
+ format += "tt";
+ }
+
+ if (format == "") {
+ format = sb.ToString();
+ } else {
+ text = sb.ToString();
+ }
+ if (specialDateFormat != "") {
+ format = specialDateFormat;
+ }
+
+ if (forColWidth) {
+ NetFormatForWidth = format;
+ NetTextFormatForWidth = text;
+ } else {
+ NetFormat = format;
+ NetTextFormat = text;
+ }
+ if (Culture == null) {
+ Culture = CultureInfo.CurrentCulture;
+ }
+ }
+
+ private static void SetDecimal(List<int> lstDec, StringBuilder sb) {
+ if (lstDec.Count > 1) {
+ for (int i = lstDec.Count - 1; i >= 0; i--) {
+ sb.Insert(lstDec[i] + 1, '\'');
+ sb.Insert(lstDec[i], '\'');
+ }
+ }
+ }
+
+ internal string FormatFraction(double d) {
+ int numerator,
+ denomerator;
+
+ int intPart = (int)d;
+
+ string[] fmt = FractionFormat.Split('/');
+
+ if (!int.TryParse(fmt[1], out var fixedDenominator)) {
+ fixedDenominator = 0;
+ }
+
+ if (d == 0 || double.IsNaN(d)) {
+ if (fmt[0].Trim() == "" && fmt[1].Trim() == "") {
+ return new(' ', FractionFormat.Length);
+ }
+ return 0.ToString(fmt[0]) + "/" + 1.ToString(fmt[0]);
+ }
+
+ int maxDigits = fmt[1].Length;
+ string sign = d < 0 ? "-" : "";
+ if (fixedDenominator == 0) {
+ List<double> numerators = [1, 0];
+ List<double> denominators = [0, 1];
+
+ if (maxDigits < 1 && maxDigits > 12) {
+ throw (new ArgumentException("Number of digits out of range (1-12)"));
+ }
+
+ int maxNum = 0;
+ for (int i = 0; i < maxDigits; i++) {
+ maxNum += 9 * (int)(Math.Pow(10, i));
+ }
+
+ double divRes = 1 / (Math.Abs(d) - intPart);
+ double result,
+ prevResult = double.NaN;
+ int listPos = 2,
+ index = 1;
+ while (true) {
+ index++;
+ double intDivRes = Math.Floor(divRes);
+ numerators.Add((intDivRes * numerators[index - 1] + numerators[index - 2]));
+ if (numerators[index] > maxNum) {
+ break;
+ }
+
+ denominators.Add((intDivRes * denominators[index - 1] + denominators[index - 2]));
+
+ result = numerators[index] / denominators[index];
+ if (denominators[index] > maxNum) {
+ break;
+ }
+ listPos = index;
+
+ if (result == prevResult) {
+ break;
+ }
+
+ if (result == d) {
+ break;
+ }
+
+ prevResult = result;
+
+ divRes = 1 / (divRes - intDivRes); //Rest
+ }
+
+ numerator = (int)numerators[listPos];
+ denomerator = (int)denominators[listPos];
+ } else {
+ numerator = (int)Math.Round((d - intPart) / (1D / fixedDenominator), 0);
+ denomerator = fixedDenominator;
+ }
+ if (numerator == denomerator || numerator == 0) {
+ if (numerator == denomerator) {
+ intPart++;
+ }
+ return sign + intPart.ToString(NetFormat).Replace("?", new(' ', FractionFormat.Length));
+ }
+ if (intPart == 0) {
+ return sign + FmtInt(numerator, fmt[0]) + "/" + FmtInt(denomerator, fmt[1]);
+ }
+ return sign
+ + intPart
+ .ToString(NetFormat)
+ .Replace("?", FmtInt(numerator, fmt[0]) + "/" + FmtInt(denomerator, fmt[1]));
+ }
+
+ private string FmtInt(double value, string format) {
+ string v = value.ToString("#");
+ string pad = "";
+ if (v.Length < format.Length) {
+ for (int i = format.Length - v.Length - 1; i >= 0; i--) {
+ if (format[i] == '?') {
+ pad += " ";
+ } else if (format[i] == ' ') {
+ pad += "0";
+ }
+ }
+ }
+ return pad + v;
+ }
+ }
+}
diff --git a/AppsheetEpplus/Style/XmlAccess/ExcelXfsXml.cs b/AppsheetEpplus/Style/XmlAccess/ExcelXfsXml.cs
new file mode 100644
index 0000000..4032042
--- /dev/null
+++ b/AppsheetEpplus/Style/XmlAccess/ExcelXfsXml.cs
@@ -0,0 +1,717 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System;
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Xml access class xfs records. This is the top level style object.
+/// </summary>
+public sealed class ExcelXfs : StyleXmlHelper {
+ private readonly ExcelStyles _styles;
+
+ internal ExcelXfs(XmlNamespaceManager nameSpaceManager, ExcelStyles styles)
+ : base(nameSpaceManager) {
+ _styles = styles;
+ isBuildIn = false;
+ }
+
+ internal ExcelXfs(XmlNamespaceManager nsm, XmlNode topNode, ExcelStyles styles)
+ : base(nsm, topNode) {
+ _styles = styles;
+ _xfID = GetXmlNodeInt("@xfId");
+ if (_xfID == 0) {
+ isBuildIn = true; //Normal taggen
+ }
+ _numFmtId = GetXmlNodeInt("@numFmtId");
+ _fontId = GetXmlNodeInt("@fontId");
+ _fillId = GetXmlNodeInt("@fillId");
+ _borderId = GetXmlNodeInt("@borderId");
+ _readingOrder = GetReadingOrder(GetXmlNodeString(_readingOrderPath));
+ _indent = GetXmlNodeInt(_indentPath);
+ _shrinkToFit = GetXmlNodeString(_shrinkToFitPath) == "1" ? true : false;
+ _verticalAlignment = GetVerticalAlign(GetXmlNodeString(_verticalAlignPath));
+ _horizontalAlignment = GetHorizontalAlign(GetXmlNodeString(_horizontalAlignPath));
+ _wrapText = GetXmlNodeBool(_wrapTextPath);
+ _textRotation = GetXmlNodeInt(textRotationPath);
+ _hidden = GetXmlNodeBool(_hiddenPath);
+ _locked = GetXmlNodeBool(_lockedPath, true);
+ }
+
+ private ExcelReadingOrder GetReadingOrder(string value) {
+ switch (value) {
+ case "1":
+ return ExcelReadingOrder.LeftToRight;
+ case "2":
+ return ExcelReadingOrder.RightToLeft;
+ default:
+ return ExcelReadingOrder.ContextDependent;
+ }
+ }
+
+ private ExcelHorizontalAlignment GetHorizontalAlign(string align) =>
+ Enum.TryParse<ExcelHorizontalAlignment>(align, true, out var result)
+ ? result
+ : ExcelHorizontalAlignment.General;
+
+ private ExcelVerticalAlignment GetVerticalAlign(string align) =>
+ Enum.TryParse<ExcelVerticalAlignment>(align, true, out var result)
+ ? result
+ : ExcelVerticalAlignment.Bottom;
+
+ private int _xfID;
+
+ /// <summary>
+ /// Style index
+ /// </summary>
+ public int XfId {
+ get => _xfID;
+ set => _xfID = value;
+ }
+
+ private int _numFmtId;
+
+ internal int NumberFormatId {
+ get => _numFmtId;
+ set {
+ _numFmtId = value;
+ ApplyNumberFormat = (value > 0);
+ }
+ }
+
+ private int _fontId;
+
+ internal int FontId {
+ get => _fontId;
+ set => _fontId = value;
+ }
+
+ private int _fillId;
+
+ internal int FillId {
+ get => _fillId;
+ set => _fillId = value;
+ }
+
+ private int _borderId;
+
+ internal int BorderId {
+ get => _borderId;
+ set => _borderId = value;
+ }
+
+ private bool isBuildIn { get; set; }
+
+ internal bool ApplyNumberFormat { get; set; }
+
+ internal bool ApplyFont { get; set; }
+
+ internal bool ApplyFill { get; set; }
+
+ internal bool ApplyBorder { get; set; }
+
+ internal bool ApplyAlignment { get; set; }
+
+ internal bool ApplyProtection { get; set; }
+
+ public ExcelStyles Styles { get; private set; }
+
+ /// <summary>
+ /// Numberformat properties
+ /// </summary>
+ public ExcelNumberFormatXml Numberformat => _styles.NumberFormats[_numFmtId < 0 ? 0 : _numFmtId];
+
+ /// <summary>
+ /// Font properties
+ /// </summary>
+ public ExcelFontXml Font => _styles.Fonts[_fontId < 0 ? 0 : _fontId];
+
+ /// <summary>
+ /// Fill properties
+ /// </summary>
+ public ExcelFillXml Fill => _styles.Fills[_fillId < 0 ? 0 : _fillId];
+
+ /// <summary>
+ /// Border style properties
+ /// </summary>
+ public ExcelBorderXml Border => _styles.Borders[_borderId < 0 ? 0 : _borderId];
+
+ private const string _horizontalAlignPath = "d:alignment/@horizontal";
+ private ExcelHorizontalAlignment _horizontalAlignment = ExcelHorizontalAlignment.General;
+
+ /// <summary>
+ /// Horizontal alignment
+ /// </summary>
+ public ExcelHorizontalAlignment HorizontalAlignment {
+ get => _horizontalAlignment;
+ set => _horizontalAlignment = value;
+ }
+
+ private const string _verticalAlignPath = "d:alignment/@vertical";
+ private ExcelVerticalAlignment _verticalAlignment = ExcelVerticalAlignment.Bottom;
+
+ /// <summary>
+ /// Vertical alignment
+ /// </summary>
+ public ExcelVerticalAlignment VerticalAlignment {
+ get => _verticalAlignment;
+ set => _verticalAlignment = value;
+ }
+
+ private const string _wrapTextPath = "d:alignment/@wrapText";
+ private bool _wrapText;
+
+ /// <summary>
+ /// Wraped text
+ /// </summary>
+ public bool WrapText {
+ get => _wrapText;
+ set => _wrapText = value;
+ }
+
+ private readonly string textRotationPath = "d:alignment/@textRotation";
+ private int _textRotation;
+
+ /// <summary>
+ /// Text rotation angle
+ /// </summary>
+ public int TextRotation {
+ get => (_textRotation == int.MinValue ? 0 : _textRotation);
+ set => _textRotation = value;
+ }
+
+ private const string _lockedPath = "d:protection/@locked";
+ private bool _locked = true;
+
+ /// <summary>
+ /// Locked when sheet is protected
+ /// </summary>
+ public bool Locked {
+ get => _locked;
+ set => _locked = value;
+ }
+
+ private const string _hiddenPath = "d:protection/@hidden";
+ private bool _hidden;
+
+ /// <summary>
+ /// Hide formulas when sheet is protected
+ /// </summary>
+ public bool Hidden {
+ get => _hidden;
+ set => _hidden = value;
+ }
+
+ private const string _readingOrderPath = "d:alignment/@readingOrder";
+ private ExcelReadingOrder _readingOrder = ExcelReadingOrder.ContextDependent;
+
+ /// <summary>
+ /// Readingorder
+ /// </summary>
+ public ExcelReadingOrder ReadingOrder {
+ get => _readingOrder;
+ set => _readingOrder = value;
+ }
+
+ private const string _shrinkToFitPath = "d:alignment/@shrinkToFit";
+ private bool _shrinkToFit;
+
+ /// <summary>
+ /// Shrink to fit
+ /// </summary>
+ public bool ShrinkToFit {
+ get => _shrinkToFit;
+ set => _shrinkToFit = value;
+ }
+
+ private const string _indentPath = "d:alignment/@indent";
+ private int _indent;
+
+ /// <summary>
+ /// Indentation
+ /// </summary>
+ public int Indent {
+ get => (_indent == int.MinValue ? 0 : _indent);
+ set => _indent = value;
+ }
+
+ internal void RegisterEvent(ExcelXfs xf) {
+ // RegisterEvent(xf, xf.Xf_ChangedEvent);
+ }
+
+ internal override string Id =>
+ XfId
+ + "|"
+ + NumberFormatId
+ + "|"
+ + FontId
+ + "|"
+ + FillId
+ + "|"
+ + BorderId
+ + VerticalAlignment
+ + "|"
+ + HorizontalAlignment
+ + "|"
+ + WrapText
+ + "|"
+ + ReadingOrder
+ + "|"
+ + isBuildIn
+ + TextRotation
+ + Locked
+ + Hidden
+ + ShrinkToFit
+ + Indent;
+
+ //return Numberformat.Id + "|" + Font.Id + "|" + Fill.Id + "|" + Border.Id + VerticalAlignment.ToString() + "|" + HorizontalAlignment.ToString() + "|" + WrapText.ToString() + "|" + ReadingOrder.ToString();
+ internal ExcelXfs Copy() {
+ return Copy(_styles);
+ }
+
+ internal ExcelXfs Copy(ExcelStyles styles) {
+ ExcelXfs newXf = new ExcelXfs(NameSpaceManager, styles);
+ newXf.NumberFormatId = _numFmtId;
+ newXf.FontId = _fontId;
+ newXf.FillId = _fillId;
+ newXf.BorderId = _borderId;
+ newXf.XfId = _xfID;
+ newXf.ReadingOrder = _readingOrder;
+ newXf.HorizontalAlignment = _horizontalAlignment;
+ newXf.VerticalAlignment = _verticalAlignment;
+ newXf.WrapText = _wrapText;
+ newXf.ShrinkToFit = _shrinkToFit;
+ newXf.Indent = _indent;
+ newXf.TextRotation = _textRotation;
+ newXf.Locked = _locked;
+ newXf.Hidden = _hidden;
+ return newXf;
+ }
+
+ internal int GetNewId(
+ ExcelStyleCollection<ExcelXfs> xfsCol,
+ StyleBase styleObject,
+ eStyleClass styleClass,
+ eStyleProperty styleProperty,
+ object value) {
+ ExcelXfs newXfs = Copy();
+ switch (styleClass) {
+ case eStyleClass.Numberformat:
+ newXfs.NumberFormatId = GetIdNumberFormat(styleProperty, value);
+ styleObject.SetIndex(newXfs.NumberFormatId);
+ break;
+ case eStyleClass.Font: {
+ newXfs.FontId = GetIdFont(styleProperty, value);
+ styleObject.SetIndex(newXfs.FontId);
+ break;
+ }
+ case eStyleClass.Fill:
+ case eStyleClass.FillBackgroundColor:
+ case eStyleClass.FillPatternColor:
+ newXfs.FillId = GetIdFill(styleClass, styleProperty, value);
+ styleObject.SetIndex(newXfs.FillId);
+ break;
+ case eStyleClass.GradientFill:
+ case eStyleClass.FillGradientColor1:
+ case eStyleClass.FillGradientColor2:
+ newXfs.FillId = GetIdGradientFill(styleClass, styleProperty, value);
+ styleObject.SetIndex(newXfs.FillId);
+ break;
+ case eStyleClass.Border:
+ case eStyleClass.BorderBottom:
+ case eStyleClass.BorderDiagonal:
+ case eStyleClass.BorderLeft:
+ case eStyleClass.BorderRight:
+ case eStyleClass.BorderTop:
+ newXfs.BorderId = GetIdBorder(styleClass, styleProperty, value);
+ styleObject.SetIndex(newXfs.BorderId);
+ break;
+ case eStyleClass.Style:
+ switch (styleProperty) {
+ case eStyleProperty.XfId:
+ newXfs.XfId = (int)value;
+ break;
+ case eStyleProperty.HorizontalAlign:
+ newXfs.HorizontalAlignment = (ExcelHorizontalAlignment)value;
+ break;
+ case eStyleProperty.VerticalAlign:
+ newXfs.VerticalAlignment = (ExcelVerticalAlignment)value;
+ break;
+ case eStyleProperty.WrapText:
+ newXfs.WrapText = (bool)value;
+ break;
+ case eStyleProperty.ReadingOrder:
+ newXfs.ReadingOrder = (ExcelReadingOrder)value;
+ break;
+ case eStyleProperty.ShrinkToFit:
+ newXfs.ShrinkToFit = (bool)value;
+ break;
+ case eStyleProperty.Indent:
+ newXfs.Indent = (int)value;
+ break;
+ case eStyleProperty.TextRotation:
+ newXfs.TextRotation = (int)value;
+ break;
+ case eStyleProperty.Locked:
+ newXfs.Locked = (bool)value;
+ break;
+ case eStyleProperty.Hidden:
+ newXfs.Hidden = (bool)value;
+ break;
+ default:
+ throw (new("Invalid property for class style."));
+ }
+ break;
+ }
+ int id = xfsCol.FindIndexById(newXfs.Id);
+ if (id < 0) {
+ return xfsCol.Add(newXfs.Id, newXfs);
+ }
+ return id;
+ }
+
+ private int GetIdBorder(eStyleClass styleClass, eStyleProperty styleProperty, object value) {
+ ExcelBorderXml border = Border.Copy();
+
+ switch (styleClass) {
+ case eStyleClass.BorderBottom:
+ SetBorderItem(border.Bottom, styleProperty, value);
+ break;
+ case eStyleClass.BorderDiagonal:
+ SetBorderItem(border.Diagonal, styleProperty, value);
+ break;
+ case eStyleClass.BorderLeft:
+ SetBorderItem(border.Left, styleProperty, value);
+ break;
+ case eStyleClass.BorderRight:
+ SetBorderItem(border.Right, styleProperty, value);
+ break;
+ case eStyleClass.BorderTop:
+ SetBorderItem(border.Top, styleProperty, value);
+ break;
+ case eStyleClass.Border:
+ if (styleProperty == eStyleProperty.BorderDiagonalUp) {
+ border.DiagonalUp = (bool)value;
+ } else if (styleProperty == eStyleProperty.BorderDiagonalDown) {
+ border.DiagonalDown = (bool)value;
+ } else {
+ throw (new("Invalid property for class Border."));
+ }
+ break;
+ default:
+ throw (new("Invalid class/property for class Border."));
+ }
+ int subId;
+ string id = border.Id;
+ subId = _styles.Borders.FindIndexById(id);
+ if (subId == int.MinValue) {
+ return _styles.Borders.Add(id, border);
+ }
+ return subId;
+ }
+
+ private void SetBorderItem(
+ ExcelBorderItemXml excelBorderItem,
+ eStyleProperty styleProperty,
+ object value) {
+ if (styleProperty == eStyleProperty.Style) {
+ excelBorderItem.Style = (ExcelBorderStyle)value;
+ } else if (styleProperty == eStyleProperty.Color
+ || styleProperty == eStyleProperty.Tint
+ || styleProperty == eStyleProperty.IndexedColor) {
+ if (excelBorderItem.Style == ExcelBorderStyle.None) {
+ throw (new("Can't set bordercolor when style is not set."));
+ }
+ excelBorderItem.Color.Rgb = value.ToString();
+ }
+ }
+
+ private int GetIdFill(eStyleClass styleClass, eStyleProperty styleProperty, object value) {
+ ExcelFillXml fill = Fill.Copy();
+
+ switch (styleProperty) {
+ case eStyleProperty.PatternType:
+ if (fill is ExcelGradientFillXml) {
+ fill = new(NameSpaceManager);
+ }
+ fill.PatternType = (ExcelFillStyle)value;
+ break;
+ case eStyleProperty.Color:
+ case eStyleProperty.Tint:
+ case eStyleProperty.IndexedColor:
+ case eStyleProperty.AutoColor:
+ if (fill is ExcelGradientFillXml) {
+ fill = new(NameSpaceManager);
+ }
+ if (fill.PatternType == ExcelFillStyle.None) {
+ throw (new ArgumentException("Can't set color when patterntype is not set."));
+ }
+ ExcelColorXml destColor;
+ if (styleClass == eStyleClass.FillPatternColor) {
+ destColor = fill.PatternColor;
+ } else {
+ destColor = fill.BackgroundColor;
+ }
+
+ if (styleProperty == eStyleProperty.Color) {
+ destColor.Rgb = value.ToString();
+ } else if (styleProperty == eStyleProperty.Tint) {
+ destColor.Tint = (decimal)value;
+ } else if (styleProperty == eStyleProperty.IndexedColor) {
+ destColor.Indexed = (int)value;
+ } else {
+ destColor.Auto = (bool)value;
+ }
+
+ break;
+ default:
+ throw (new ArgumentException("Invalid class/property for class Fill."));
+ }
+ int subId;
+ string id = fill.Id;
+ subId = _styles.Fills.FindIndexById(id);
+ if (subId == int.MinValue) {
+ return _styles.Fills.Add(id, fill);
+ }
+ return subId;
+ }
+
+ private int GetIdGradientFill(
+ eStyleClass styleClass,
+ eStyleProperty styleProperty,
+ object value) {
+ ExcelGradientFillXml fill;
+ if (Fill is ExcelGradientFillXml) {
+ fill = (ExcelGradientFillXml)Fill.Copy();
+ } else {
+ fill = new(Fill.NameSpaceManager);
+ fill.GradientColor1.Rgb = "FFFFFFFF";
+ fill.GradientColor2.Rgb = "FF4F81BD";
+ fill.Type = ExcelFillGradientType.Linear;
+ fill.Degree = 90;
+ fill.Top = double.NaN;
+ fill.Bottom = double.NaN;
+ fill.Left = double.NaN;
+ fill.Right = double.NaN;
+ }
+
+ switch (styleProperty) {
+ case eStyleProperty.GradientType:
+ fill.Type = (ExcelFillGradientType)value;
+ break;
+ case eStyleProperty.GradientDegree:
+ fill.Degree = (double)value;
+ break;
+ case eStyleProperty.GradientTop:
+ fill.Top = (double)value;
+ break;
+ case eStyleProperty.GradientBottom:
+ fill.Bottom = (double)value;
+ break;
+ case eStyleProperty.GradientLeft:
+ fill.Left = (double)value;
+ break;
+ case eStyleProperty.GradientRight:
+ fill.Right = (double)value;
+ break;
+ case eStyleProperty.Color:
+ case eStyleProperty.Tint:
+ case eStyleProperty.IndexedColor:
+ case eStyleProperty.AutoColor:
+ ExcelColorXml destColor;
+
+ if (styleClass == eStyleClass.FillGradientColor1) {
+ destColor = fill.GradientColor1;
+ } else {
+ destColor = fill.GradientColor2;
+ }
+
+ if (styleProperty == eStyleProperty.Color) {
+ destColor.Rgb = value.ToString();
+ } else if (styleProperty == eStyleProperty.Tint) {
+ destColor.Tint = (decimal)value;
+ } else if (styleProperty == eStyleProperty.IndexedColor) {
+ destColor.Indexed = (int)value;
+ } else {
+ destColor.Auto = (bool)value;
+ }
+ break;
+ default:
+ throw (new ArgumentException("Invalid class/property for class Fill."));
+ }
+ int subId;
+ string id = fill.Id;
+ subId = _styles.Fills.FindIndexById(id);
+ if (subId == int.MinValue) {
+ return _styles.Fills.Add(id, fill);
+ }
+ return subId;
+ }
+
+ private int GetIdNumberFormat(eStyleProperty styleProperty, object value) {
+ if (styleProperty == eStyleProperty.Format) {
+ ExcelNumberFormatXml item = null;
+ if (!_styles.NumberFormats.FindById(value.ToString(), ref item)) {
+ item = new(NameSpaceManager) {
+ Format = value.ToString(),
+ NumFmtId = _styles.NumberFormats.NextId++,
+ };
+ _styles.NumberFormats.Add(value.ToString(), item);
+ }
+ return item.NumFmtId;
+ }
+ throw (new("Invalid property for class Numberformat"));
+ }
+
+ private int GetIdFont(eStyleProperty styleProperty, object value) {
+ ExcelFontXml fnt = Font.Copy();
+
+ switch (styleProperty) {
+ case eStyleProperty.Name:
+ fnt.Name = value.ToString();
+ break;
+ case eStyleProperty.Size:
+ fnt.Size = (float)value;
+ break;
+ case eStyleProperty.Family:
+ fnt.Family = (int)value;
+ break;
+ case eStyleProperty.Bold:
+ fnt.Bold = (bool)value;
+ break;
+ case eStyleProperty.Italic:
+ fnt.Italic = (bool)value;
+ break;
+ case eStyleProperty.Strike:
+ fnt.Strike = (bool)value;
+ break;
+ case eStyleProperty.UnderlineType:
+ fnt.UnderLineType = (ExcelUnderLineType)value;
+ break;
+ case eStyleProperty.Color:
+ fnt.Color.Rgb = value.ToString();
+ break;
+ case eStyleProperty.VerticalAlign:
+ fnt.VerticalAlign =
+ ((ExcelVerticalAlignmentFont)value) == ExcelVerticalAlignmentFont.None
+ ? ""
+ : value.ToString().ToLower(CultureInfo.InvariantCulture);
+ break;
+ default:
+ throw (new("Invalid property for class Font"));
+ }
+ int subId;
+ string id = fnt.Id;
+ subId = _styles.Fonts.FindIndexById(id);
+ if (subId == int.MinValue) {
+ return _styles.Fonts.Add(id, fnt);
+ }
+ return subId;
+ }
+
+ internal override XmlNode CreateXmlNode(XmlNode topNode) {
+ return CreateXmlNode(topNode, false);
+ }
+
+ internal XmlNode CreateXmlNode(XmlNode topNode, bool isCellStyleXsf) {
+ TopNode = topNode;
+ var doSetXfId =
+ (!isCellStyleXsf
+ && _xfID > int.MinValue
+ && _styles.CellStyleXfs.Count > 0
+ && _styles.CellStyleXfs[_xfID].newID > int.MinValue);
+ if (_numFmtId > 0) {
+ SetXmlNodeString("@numFmtId", _numFmtId.ToString());
+ if (doSetXfId) {
+ SetXmlNodeString("@applyNumberFormat", "1");
+ }
+ }
+ if (_fontId >= 0) {
+ SetXmlNodeString("@fontId", _styles.Fonts[_fontId].newID.ToString());
+ if (doSetXfId) {
+ SetXmlNodeString("@applyFont", "1");
+ }
+ }
+ if (_fillId >= 0) {
+ SetXmlNodeString("@fillId", _styles.Fills[_fillId].newID.ToString());
+ if (doSetXfId) {
+ SetXmlNodeString("@applyFill", "1");
+ }
+ }
+ if (_borderId >= 0) {
+ SetXmlNodeString("@borderId", _styles.Borders[_borderId].newID.ToString());
+ if (doSetXfId) {
+ SetXmlNodeString("@applyBorder", "1");
+ }
+ }
+ if (_horizontalAlignment != ExcelHorizontalAlignment.General) {
+ SetXmlNodeString(_horizontalAlignPath, SetAlignString(_horizontalAlignment));
+ }
+ if (doSetXfId) {
+ SetXmlNodeString("@xfId", _styles.CellStyleXfs[_xfID].newID.ToString());
+ }
+ if (_verticalAlignment != ExcelVerticalAlignment.Bottom) {
+ SetXmlNodeString(_verticalAlignPath, SetAlignString(_verticalAlignment));
+ }
+ if (_wrapText) {
+ SetXmlNodeString(_wrapTextPath, "1");
+ }
+ if (_readingOrder != ExcelReadingOrder.ContextDependent) {
+ SetXmlNodeString(_readingOrderPath, ((int)_readingOrder).ToString());
+ }
+ if (_shrinkToFit) {
+ SetXmlNodeString(_shrinkToFitPath, "1");
+ }
+ if (_indent > 0) {
+ SetXmlNodeString(_indentPath, _indent.ToString());
+ }
+ if (_textRotation > 0) {
+ SetXmlNodeString(textRotationPath, _textRotation.ToString());
+ }
+ if (!_locked) {
+ SetXmlNodeString(_lockedPath, "0");
+ }
+ if (_hidden) {
+ SetXmlNodeString(_hiddenPath, "1");
+ }
+ return TopNode;
+ }
+
+ private string SetAlignString(Enum align) {
+ string newName = Enum.GetName(align.GetType(), align);
+ return newName.Substring(0, 1).ToLower(CultureInfo.InvariantCulture)
+ + newName.Substring(1, newName.Length - 1);
+ }
+}
diff --git a/AppsheetEpplus/Style/XmlAccess/StyleXmlHelper.cs b/AppsheetEpplus/Style/XmlAccess/StyleXmlHelper.cs
new file mode 100644
index 0000000..f17ffa6
--- /dev/null
+++ b/AppsheetEpplus/Style/XmlAccess/StyleXmlHelper.cs
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Xml helper class for cell style classes
+/// </summary>
+public abstract class StyleXmlHelper : XmlHelper {
+ internal StyleXmlHelper(XmlNamespaceManager nameSpaceManager)
+ : base(nameSpaceManager) {}
+
+ internal StyleXmlHelper(XmlNamespaceManager nameSpaceManager, XmlNode topNode)
+ : base(nameSpaceManager, topNode) {}
+
+ internal abstract XmlNode CreateXmlNode(XmlNode top);
+
+ internal abstract string Id { get; }
+
+ internal long useCnt = 0;
+ internal int newID = int.MinValue;
+
+ protected bool GetBoolValue(XmlNode topNode, string path) {
+ var node = topNode.SelectSingleNode(path, NameSpaceManager);
+ if (node is XmlAttribute) {
+ return node.Value != "0";
+ }
+ if (node != null
+ && ((node.Attributes["val"] != null && node.Attributes["val"].Value != "0")
+ || node.Attributes["val"] == null)) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/AppsheetEpplus/Table/ExcelTable.cs b/AppsheetEpplus/Table/ExcelTable.cs
new file mode 100644
index 0000000..d7115fd
--- /dev/null
+++ b/AppsheetEpplus/Table/ExcelTable.cs
@@ -0,0 +1,348 @@
+/*******************************************************************************
+ * 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;
+
+namespace AppsheetEpplus;
+
+/// <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();
+ }
+}
diff --git a/AppsheetEpplus/Table/ExcelTableCollection.cs b/AppsheetEpplus/Table/ExcelTableCollection.cs
new file mode 100644
index 0000000..60a4878
--- /dev/null
+++ b/AppsheetEpplus/Table/ExcelTableCollection.cs
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * 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;
+using System.Collections.Generic;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// A collection of table objects
+/// </summary>
+public class ExcelTableCollection : IEnumerable<ExcelTable> {
+ private readonly List<ExcelTable> _tables = new();
+ internal Dictionary<string, int> _tableNames = new(StringComparer.InvariantCultureIgnoreCase);
+ private readonly ExcelWorksheet _ws;
+
+ internal ExcelTableCollection(ExcelWorksheet ws) {
+ var pck = ws._package.Package;
+ _ws = ws;
+ foreach (XmlElement node in ws.WorksheetXml.SelectNodes(
+ "//d:tableParts/d:tablePart",
+ ws.NameSpaceManager)) {
+ var rel = ws.Part.GetRelationship(node.GetAttribute("id", ExcelPackage._schemaRelationships));
+ var tbl = new ExcelTable(rel, ws);
+ _tableNames.Add(tbl.Name, _tables.Count);
+ _tables.Add(tbl);
+ }
+ }
+
+ internal string GetNewTableName() {
+ string name = "Table1";
+ int i = 2;
+ while (_ws.Workbook.ExistsTableName(name)) {
+ name = string.Format("Table{0}", i++);
+ }
+ return name;
+ }
+
+ /// <summary>
+ /// Number of items in the collection
+ /// </summary>
+ public int Count => _tables.Count;
+
+ /// <summary>
+ /// Get the table object from a range.
+ /// </summary>
+ /// <param name="range">The range</param>
+ /// <returns>The table. Null if no range matches</returns>
+ public ExcelTable GetFromRange(ExcelRangeBase range) {
+ foreach (var tbl in range.Worksheet.Tables) {
+ if (tbl.Address._address == range._address) {
+ return tbl;
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// The table Index. Base 0.
+ /// </summary>
+ /// <param name="index"></param>
+ /// <returns></returns>
+ public ExcelTable this[int index] {
+ get {
+ if (index < 0 || index >= _tables.Count) {
+ throw (new ArgumentOutOfRangeException("Table index out of range"));
+ }
+ return _tables[index];
+ }
+ }
+
+ /// <summary>
+ /// Indexer
+ /// </summary>
+ /// <param name="name">The name of the table</param>
+ /// <returns>The table. Null if the table name is not found in the collection</returns>
+ public ExcelTable this[string name] {
+ get {
+ if (_tableNames.ContainsKey(name)) {
+ return _tables[_tableNames[name]];
+ }
+ return null;
+ }
+ }
+
+ public IEnumerator<ExcelTable> GetEnumerator() {
+ return _tables.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _tables.GetEnumerator();
+ }
+}
diff --git a/AppsheetEpplus/Table/ExcelTableColumn.cs b/AppsheetEpplus/Table/ExcelTableColumn.cs
new file mode 100644
index 0000000..b174914
--- /dev/null
+++ b/AppsheetEpplus/Table/ExcelTableColumn.cs
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * 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.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Build-in table row functions
+/// </summary>
+public enum RowFunctions {
+ Average,
+ Count,
+ CountNums,
+ Custom,
+ Max,
+ Min,
+ None,
+ StdDev,
+ Sum,
+ Var,
+}
+
+/// <summary>
+/// A table column
+/// </summary>
+public class ExcelTableColumn : XmlHelper {
+ internal ExcelTable _tbl;
+
+ internal ExcelTableColumn(XmlNamespaceManager ns, XmlNode topNode, ExcelTable tbl, int pos)
+ : base(ns, topNode) {
+ _tbl = tbl;
+ Position = pos;
+ }
+
+ /// <summary>
+ /// The column id
+ /// </summary>
+ public int Id {
+ get => GetXmlNodeInt("@id");
+ set => SetXmlNodeString("@id", value.ToString());
+ }
+
+ /// <summary>
+ /// The position of the column
+ /// </summary>
+ public int Position { get; private set; }
+
+ /// <summary>
+ /// The name of the column
+ /// </summary>
+ public string Name {
+ get {
+ var n = GetXmlNodeString("@name");
+ if (string.IsNullOrEmpty(n)) {
+ if (_tbl.ShowHeader) {
+ n = ConvertUtil.ExcelDecodeString(
+ _tbl.WorkSheet.GetValue<string>(
+ _tbl.Address._fromRow,
+ _tbl.Address._fromCol + Position));
+ } else {
+ n = "Column" + (Position + 1);
+ }
+ }
+ return n;
+ }
+ set {
+ var v = ConvertUtil.ExcelEncodeString(value);
+ SetXmlNodeString("@name", v);
+ if (_tbl.ShowHeader) {
+ _tbl.WorkSheet.SetValue(_tbl.Address._fromRow, _tbl.Address._fromCol + Position, value);
+ }
+ _tbl.WorkSheet.SetTableTotalFunction(_tbl, this);
+ }
+ }
+
+ /// <summary>
+ /// A string text in the total row
+ /// </summary>
+ public string TotalsRowLabel {
+ get => GetXmlNodeString("@totalsRowLabel");
+ set => SetXmlNodeString("@totalsRowLabel", value);
+ }
+
+ /// <summary>
+ /// Build-in total row functions.
+ /// To set a custom Total row formula use the TotalsRowFormula property
+ /// <seealso cref="TotalsRowFormula"/>
+ /// </summary>
+ public RowFunctions TotalsRowFunction {
+ get {
+ if (GetXmlNodeString("@totalsRowFunction") == "") {
+ return RowFunctions.None;
+ }
+ return (RowFunctions)
+ Enum.Parse(typeof(RowFunctions), GetXmlNodeString("@totalsRowFunction"), true);
+ }
+ set {
+ if (value == RowFunctions.Custom) {
+ throw (new("Use the TotalsRowFormula-property to set a custom table formula"));
+ }
+ string s = value.ToString();
+ s = s.Substring(0, 1).ToLower(CultureInfo.InvariantCulture) + s.Substring(1, s.Length - 1);
+ SetXmlNodeString("@totalsRowFunction", s);
+ _tbl.WorkSheet.SetTableTotalFunction(_tbl, this);
+ }
+ }
+
+ private const string _totalsrowformulaPath = "d:totalsRowFormula";
+
+ /// <summary>
+ /// Sets a custom Totals row Formula.
+ /// Be carefull with this property since it is not validated.
+ /// <example>
+ /// tbl.Columns[9].TotalsRowFormula = string.Format("SUM([{0}])",tbl.Columns[9].Name);
+ /// </example>
+ /// </summary>
+ public string TotalsRowFormula {
+ get => GetXmlNodeString(_totalsrowformulaPath);
+ set {
+ if (value.StartsWith("=")) {
+ value = value.Substring(1, value.Length - 1);
+ }
+ SetXmlNodeString("@totalsRowFunction", "custom");
+ SetXmlNodeString(_totalsrowformulaPath, value);
+ _tbl.WorkSheet.SetTableTotalFunction(_tbl, this);
+ }
+ }
+
+ private const string _datacellstylePath = "@dataCellStyle";
+
+ /// <summary>
+ /// The named style for datacells in the column
+ /// </summary>
+ public string DataCellStyleName {
+ get => GetXmlNodeString(_datacellstylePath);
+ set {
+ if (_tbl.WorkSheet.Workbook.Styles.NamedStyles.FindIndexById(value) < 0) {
+ throw (new(string.Format("Named style {0} does not exist.", value)));
+ }
+ SetXmlNodeString(TopNode, _datacellstylePath, value, true);
+
+ int fromRow = _tbl.Address._fromRow + (_tbl.ShowHeader ? 1 : 0),
+ toRow = _tbl.Address._toRow - (_tbl.ShowTotal ? 1 : 0),
+ col = _tbl.Address._fromCol + Position;
+
+ if (fromRow <= toRow) {
+ _tbl.WorkSheet.Cells[fromRow, col, toRow, col].StyleName = value;
+ }
+ }
+ }
+
+ private const string _calculatedcolumnformulaPath = "d:calculatedColumnFormula";
+
+ /// <summary>
+ /// Sets a calculated column Formula.
+ /// Be carefull with this property since it is not validated.
+ /// <example>
+ /// tbl.Columns[9].CalculatedColumnFormula = string.Format("SUM(MyDataTable[[#This Row],[{0}]])",tbl.Columns[9].Name);
+ /// </example>
+ /// </summary>
+ public string CalculatedColumnFormula {
+ get => GetXmlNodeString(_calculatedcolumnformulaPath);
+ set {
+ if (value.StartsWith("=")) {
+ value = value.Substring(1, value.Length - 1);
+ }
+ SetXmlNodeString(_calculatedcolumnformulaPath, value);
+ }
+ }
+}
diff --git a/AppsheetEpplus/Table/ExcelTableColumnCollection.cs b/AppsheetEpplus/Table/ExcelTableColumnCollection.cs
new file mode 100644
index 0000000..a465765
--- /dev/null
+++ b/AppsheetEpplus/Table/ExcelTableColumnCollection.cs
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * 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;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// A collection of table columns
+/// </summary>
+public class ExcelTableColumnCollection : IEnumerable<ExcelTableColumn> {
+ private readonly List<ExcelTableColumn> _cols = new();
+ private readonly Dictionary<string, int> _colNames = new(
+ StringComparer.InvariantCultureIgnoreCase);
+
+ public ExcelTableColumnCollection(ExcelTable table) {
+ Table = table;
+ foreach (XmlNode node in table.TableXml.SelectNodes(
+ "//d:table/d:tableColumns/d:tableColumn",
+ table.NameSpaceManager)) {
+ _cols.Add(new(table.NameSpaceManager, node, table, _cols.Count));
+ _colNames.Add(_cols[_cols.Count - 1].Name, _cols.Count - 1);
+ }
+ }
+
+ /// <summary>
+ /// A reference to the table object
+ /// </summary>
+ public ExcelTable Table { get; private set; }
+
+ /// <summary>
+ /// Number of items in the collection
+ /// </summary>
+ public int Count => _cols.Count;
+
+ /// <summary>
+ /// The column Index. Base 0.
+ /// </summary>
+ /// <param name="index"></param>
+ /// <returns></returns>
+ public ExcelTableColumn this[int index] {
+ get {
+ if (index < 0 || index >= _cols.Count) {
+ throw (new ArgumentOutOfRangeException("Column index out of range"));
+ }
+ return _cols[index];
+ }
+ }
+
+ /// <summary>
+ /// Indexer
+ /// </summary>
+ /// <param name="name">The name of the table</param>
+ /// <returns>The table column. Null if the table name is not found in the collection</returns>
+ public ExcelTableColumn this[string name] {
+ get {
+ if (_colNames.ContainsKey(name)) {
+ return _cols[_colNames[name]];
+ }
+ return null;
+ }
+ }
+
+ IEnumerator<ExcelTableColumn> IEnumerable<ExcelTableColumn>.GetEnumerator() {
+ return _cols.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _cols.GetEnumerator();
+ }
+
+ internal string GetUniqueName(string name) {
+ if (_colNames.ContainsKey(name)) {
+ string newName;
+ var i = 2;
+ do {
+ newName = name + (i++).ToString(CultureInfo.InvariantCulture);
+ } while (_colNames.ContainsKey(newName));
+ return newName;
+ }
+ return name;
+ }
+}
diff --git a/AppsheetEpplus/Table/PivotTable/ExcelPivotCacheDefinition.cs b/AppsheetEpplus/Table/PivotTable/ExcelPivotCacheDefinition.cs
new file mode 100644
index 0000000..5a41248
--- /dev/null
+++ b/AppsheetEpplus/Table/PivotTable/ExcelPivotCacheDefinition.cs
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * 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.Linq;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+public enum eSourceType {
+ /// <summary>
+ /// Indicates that the cache contains data that consolidates ranges.
+ /// </summary>
+ Consolidation,
+
+ /// <summary>
+ /// Indicates that the cache contains data from an external data source.
+ /// </summary>
+ External,
+
+ /// <summary>
+ /// Indicates that the cache contains a scenario summary report
+ /// </summary>
+ Scenario,
+
+ /// <summary>
+ /// Indicates that the cache contains worksheet data
+ /// </summary>
+ Worksheet,
+}
+
+/// <summary>
+/// Cache definition. This class defines the source data. Note that one cache definition can be shared between many pivot tables.
+/// </summary>
+public class ExcelPivotCacheDefinition : XmlHelper {
+ internal ExcelPivotCacheDefinition(XmlNamespaceManager ns, ExcelPivotTable pivotTable)
+ : base(ns, null) {
+ foreach (var r in pivotTable.Part.GetRelationshipsByType(
+ ExcelPackage._schemaRelationships + "/pivotCacheDefinition")) {
+ Relationship = r;
+ }
+ CacheDefinitionUri = UriHelper.ResolvePartUri(Relationship.SourceUri, Relationship.TargetUri);
+
+ var pck = pivotTable.WorkSheet._package.Package;
+ Part = pck.GetPart(CacheDefinitionUri);
+ LoadXmlSafe(CacheDefinitionXml, Part.GetStream());
+
+ TopNode = CacheDefinitionXml.DocumentElement;
+ PivotTable = pivotTable;
+ if (CacheSource == eSourceType.Worksheet) {
+ var worksheetName = GetXmlNodeString(_sourceWorksheetPath);
+ if (pivotTable.WorkSheet.Workbook.Worksheets.Any(t => t.Name == worksheetName)) {
+ _sourceRange = pivotTable
+ .WorkSheet
+ .Workbook
+ .Worksheets[worksheetName].Cells[GetXmlNodeString(_sourceAddressPath)];
+ }
+ }
+ }
+
+ /// <summary>
+ /// Reference to the internal package part
+ /// </summary>
+ internal ZipPackagePart Part { get; set; }
+
+ /// <summary>
+ /// Provides access to the XML data representing the cache definition in the package.
+ /// </summary>
+ public XmlDocument CacheDefinitionXml { get; private set; } = new();
+
+ /// <summary>
+ /// The package internal URI to the pivottable cache definition Xml Document.
+ /// </summary>
+ public Uri CacheDefinitionUri { get; internal set; }
+
+ internal Uri CacheRecordUri { get; set; }
+
+ internal ZipPackageRelationship Relationship { get; set; }
+
+ internal ZipPackageRelationship RecordRelationship { get; set; }
+
+ internal string RecordRelationshipID {
+ get => GetXmlNodeString("@r:id");
+ set => SetXmlNodeString("@r:id", value);
+ }
+
+ /// <summary>
+ /// Referece to the PivoTable object
+ /// </summary>
+ public ExcelPivotTable PivotTable { get; private set; }
+
+ private const string _sourceWorksheetPath = "d:cacheSource/d:worksheetSource/@sheet";
+ private const string _sourceNamePath = "d:cacheSource/d:worksheetSource/@name";
+ private const string _sourceAddressPath = "d:cacheSource/d:worksheetSource/@ref";
+ internal ExcelRangeBase _sourceRange;
+
+ /// <summary>
+ /// The source data range when the pivottable has a worksheet datasource.
+ /// The number of columns in the range must be intact if this property is changed.
+ /// The range must be in the same workbook as the pivottable.
+ /// </summary>
+ public ExcelRangeBase SourceRange {
+ get {
+ if (_sourceRange == null) {
+ if (CacheSource == eSourceType.Worksheet) {
+ var ws = PivotTable.WorkSheet.Workbook.Worksheets[GetXmlNodeString(_sourceWorksheetPath)];
+ if (ws
+ == null) //Not worksheet, check name or table name
+ {
+ var name = GetXmlNodeString(_sourceNamePath);
+ foreach (var n in PivotTable.WorkSheet.Workbook.Names) {
+ if (name.Equals(n.Name, StringComparison.InvariantCultureIgnoreCase)) {
+ _sourceRange = n;
+ return _sourceRange;
+ }
+ }
+ foreach (var w in PivotTable.WorkSheet.Workbook.Worksheets) {
+ if (w.Tables._tableNames.ContainsKey(name)) {
+ _sourceRange = w.Cells[w.Tables[name].Address.Address];
+ break;
+ }
+ foreach (var n in w.Names) {
+ if (name.Equals(n.Name, StringComparison.InvariantCultureIgnoreCase)) {
+ _sourceRange = n;
+ break;
+ }
+ }
+ }
+ } else {
+ _sourceRange = ws.Cells[GetXmlNodeString(_sourceAddressPath)];
+ }
+ } else {
+ throw (new ArgumentException("The cachesource is not a worksheet"));
+ }
+ }
+ return _sourceRange;
+ }
+ set {
+ if (PivotTable.WorkSheet.Workbook != value.Worksheet.Workbook) {
+ throw (new ArgumentException("Range must be in the same package as the pivottable"));
+ }
+
+ var sr = SourceRange;
+ if (value.End.Column - value.Start.Column != sr.End.Column - sr.Start.Column) {
+ throw (new ArgumentException(
+ "Can not change the number of columns(fields) in the SourceRange"));
+ }
+
+ SetXmlNodeString(_sourceWorksheetPath, value.Worksheet.Name);
+ SetXmlNodeString(_sourceAddressPath, value.FirstAddress);
+ _sourceRange = value;
+ }
+ }
+
+ /// <summary>
+ /// Type of source data
+ /// </summary>
+ public eSourceType CacheSource {
+ get {
+ var s = GetXmlNodeString("d:cacheSource/@type");
+ if (s == "") {
+ return eSourceType.Worksheet;
+ }
+ return (eSourceType)Enum.Parse(typeof(eSourceType), s, true);
+ }
+ }
+
+ private string GetStartXml(ExcelRangeBase sourceAddress) {
+ string xml =
+ "<pivotCacheDefinition xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" r:id=\"\" refreshOnLoad=\"1\" refreshedBy=\"SomeUser\" refreshedDate=\"40504.582403125001\" createdVersion=\"1\" refreshedVersion=\"3\" recordCount=\"5\" upgradeOnRefresh=\"1\">";
+
+ xml += "<cacheSource type=\"worksheet\">";
+ xml += string.Format(
+ "<worksheetSource ref=\"{0}\" sheet=\"{1}\" /> ",
+ sourceAddress.Address,
+ sourceAddress.WorkSheet);
+ xml += "</cacheSource>";
+ xml += string.Format(
+ "<cacheFields count=\"{0}\">",
+ sourceAddress._toCol - sourceAddress._fromCol + 1);
+ var sourceWorksheet = PivotTable.WorkSheet.Workbook.Worksheets[sourceAddress.WorkSheet];
+ for (int col = sourceAddress._fromCol; col <= sourceAddress._toCol; col++) {
+ if (sourceWorksheet == null
+ || sourceWorksheet._values.GetValue(sourceAddress._fromRow, col) == null
+ || sourceWorksheet._values.GetValue(sourceAddress._fromRow, col).ToString().Trim()
+ == "") {
+ xml += string.Format(
+ "<cacheField name=\"Column{0}\" numFmtId=\"0\">",
+ col - sourceAddress._fromCol + 1);
+ } else {
+ xml += string.Format(
+ "<cacheField name=\"{0}\" numFmtId=\"0\">",
+ sourceWorksheet._values.GetValue(sourceAddress._fromRow, col));
+ }
+ //xml += "<sharedItems containsNonDate=\"0\" containsString=\"0\" containsBlank=\"1\" /> ";
+ xml += "<sharedItems containsBlank=\"1\" /> ";
+ xml += "</cacheField>";
+ }
+ xml += "</cacheFields>";
+ xml += "</pivotCacheDefinition>";
+
+ return xml;
+ }
+}
diff --git a/AppsheetEpplus/Table/PivotTable/ExcelPivotTable.cs b/AppsheetEpplus/Table/PivotTable/ExcelPivotTable.cs
new file mode 100644
index 0000000..b3590d7
--- /dev/null
+++ b/AppsheetEpplus/Table/PivotTable/ExcelPivotTable.cs
@@ -0,0 +1,643 @@
+/*******************************************************************************
+ * 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.Immutable;
+using System.Text.RegularExpressions;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// An Excel Pivottable
+/// </summary>
+public class ExcelPivotTable : XmlHelper {
+ protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
+ "location",
+ "pivotFields",
+ "rowFields",
+ "rowItems",
+ "colFields",
+ "colItems",
+ "pageFields",
+ "pageItems",
+ "dataFields",
+ "dataItems",
+ "formats",
+ "pivotTableStyleInfo",
+ ];
+
+ internal ExcelPivotTable(ZipPackageRelationship rel, ExcelWorksheet sheet)
+ : base(sheet.NameSpaceManager) {
+ WorkSheet = sheet;
+ PivotTableUri = UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri);
+ Relationship = rel;
+ var package = sheet._package;
+ PivotTableXml = package.GetXmlDocument(PivotTableUri);
+ TopNode = PivotTableXml.DocumentElement;
+ Address = new(GetXmlNodeString("d:location/@ref"));
+
+ CacheDefinition = new(sheet.NameSpaceManager, this);
+ LoadFields();
+
+ //Add row fields.
+ foreach (XmlElement rowElem in TopNode.SelectNodes("d:rowFields/d:field", NameSpaceManager)) {
+ if (int.TryParse(rowElem.GetAttribute("x"), out var x) && x >= 0) {
+ RowFields.AddInternal(Fields[x]);
+ } else {
+ rowElem.ParentNode.RemoveChild(rowElem);
+ }
+ }
+
+ ////Add column fields.
+ foreach (XmlElement colElem in TopNode.SelectNodes("d:colFields/d:field", NameSpaceManager)) {
+ if (int.TryParse(colElem.GetAttribute("x"), out var x) && x >= 0) {
+ ColumnFields.AddInternal(Fields[x]);
+ } else {
+ colElem.ParentNode.RemoveChild(colElem);
+ }
+ }
+
+ //Add Page elements
+ //int index = 0;
+ foreach (XmlElement pageElem in TopNode.SelectNodes(
+ "d:pageFields/d:pageField",
+ NameSpaceManager)) {
+ if (int.TryParse(pageElem.GetAttribute("fld"), out var fld) && fld >= 0) {
+ var field = Fields[fld];
+ field._pageFieldSettings = new(NameSpaceManager, pageElem, field, fld);
+ PageFields.AddInternal(field);
+ }
+ }
+
+ //Add data elements
+ //index = 0;
+ foreach (XmlElement dataElem in TopNode.SelectNodes(
+ "d:dataFields/d:dataField",
+ NameSpaceManager)) {
+ if (int.TryParse(dataElem.GetAttribute("fld"), out var fld) && fld >= 0) {
+ var field = Fields[fld];
+ var dataField = new ExcelPivotTableDataField(NameSpaceManager, dataElem, field);
+ DataFields.AddInternal(dataField);
+ }
+ }
+ }
+
+ private void LoadFields() {
+ //Fields.Clear();
+ //int ix=0;
+ //foreach(XmlElement fieldNode in PivotXml.SelectNodes("//d:pivotFields/d:pivotField",NameSpaceManager))
+ //{
+ // Fields.AddInternal(new ExcelPivotTableField(NameSpaceManager, fieldNode, this, ix++));
+ //}
+
+ int index = 0;
+ //Add fields.
+ foreach (XmlElement fieldElem in TopNode.SelectNodes(
+ "d:pivotFields/d:pivotField",
+ NameSpaceManager)) {
+ var fld = new ExcelPivotTableField(NameSpaceManager, fieldElem, this, index, index++);
+ Fields.AddInternal(fld);
+ }
+
+ //Add fields.
+ index = 0;
+ foreach (XmlElement fieldElem in CacheDefinition.TopNode.SelectNodes(
+ "d:cacheFields/d:cacheField",
+ NameSpaceManager)) {
+ var fld = Fields[index++];
+ fld.SetCacheFieldNode(fieldElem);
+ }
+ }
+
+ private XmlDocument GetStartXml(
+ string name,
+ int id,
+ ExcelAddressBase address,
+ ExcelAddressBase sourceAddress) {
+ string xml = $"""
+ <pivotTableDefinition xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" name="
+ {name}" cacheId="{id
+ }" dataOnRows="1" applyNumberFormats="0" applyBorderFormats="0" applyFontFormats="0" applyPatternFormats="0" applyAlignmentFormats="0" applyWidthHeightFormats="1" dataCaption="Data" createdVersion="4" showMemberPropertyTips="0" useAutoFormatting="1" itemPrintTitles="1" indent="0" compact="0" compactData="0" gridDropZones="1">
+
+ """;
+ xml +=
+ $"""<location ref="{address.FirstAddress
+ }" firstHeaderRow="1" firstDataRow="1" firstDataCol="1" />""";
+ xml += $"""<pivotFields count="{sourceAddress._toCol - sourceAddress._fromCol + 1}">""";
+ for (int col = sourceAddress._fromCol; col <= sourceAddress._toCol; col++) {
+ xml += """<pivotField showAll="0" />""";
+ }
+ xml += "</pivotFields>";
+ xml +=
+ """<pivotTableStyleInfo name="PivotStyleMedium9" showRowHeaders="1" showColHeaders="1" showRowStripes="0" showColStripes="0" showLastColumn="1" />""";
+ xml += "</pivotTableDefinition>";
+ var result = new XmlDocument();
+ result.LoadXml(xml);
+ return result;
+ }
+
+ internal ZipPackagePart Part { get; }
+
+ /// <summary>
+ /// Provides access to the XML data representing the pivottable in the package.
+ /// </summary>
+ public XmlDocument PivotTableXml { get; private set; }
+
+ /// <summary>
+ /// The package internal URI to the pivottable Xml Document.
+ /// </summary>
+ public Uri PivotTableUri { get; internal set; }
+
+ internal ZipPackageRelationship Relationship { get; set; }
+
+ //const string ID_PATH = "@id";
+ //internal int Id
+ //{
+ // get
+ // {
+ // return GetXmlNodeInt(ID_PATH);
+ // }
+ // set
+ // {
+ // SetXmlNodeString(ID_PATH, value.ToString());
+ // }
+ //}
+ private const string _namePath = "@name";
+ private const string _displayNamePath = "@displayName";
+
+ /// <summary>
+ /// Name of the pivottable object in Excel
+ /// </summary>
+ public string Name {
+ get => GetXmlNodeString(_namePath);
+ set {
+ if (WorkSheet.Workbook.ExistsTableName(value)) {
+ throw (new ArgumentException("PivotTable name is not unique"));
+ }
+ string prevName = Name;
+ if (WorkSheet.Tables._tableNames.ContainsKey(prevName)) {
+ int ix = WorkSheet.Tables._tableNames[prevName];
+ WorkSheet.Tables._tableNames.Remove(prevName);
+ WorkSheet.Tables._tableNames.Add(value, ix);
+ }
+ SetXmlNodeString(_namePath, value);
+ SetXmlNodeString(_displayNamePath, CleanDisplayName(value));
+ }
+ }
+
+ /// <summary>
+ /// Reference to the pivot table cache definition object
+ /// </summary>
+ public ExcelPivotCacheDefinition CacheDefinition { get; }
+
+ private string CleanDisplayName(string name) {
+ return Regex.Replace(name, @"[^\w\.-_]", "_");
+ }
+
+ /// <summary>
+ /// The worksheet where the pivottable is located
+ /// </summary>
+ public ExcelWorksheet WorkSheet { get; set; }
+
+ /// <summary>
+ /// The location of the pivot table
+ /// </summary>
+ public ExcelAddressBase Address { get; internal set; }
+
+ /// <summary>
+ /// If multiple datafields are displayed in the row area or the column area
+ /// </summary>
+ public bool DataOnRows {
+ get => GetXmlNodeBool("@dataOnRows");
+ set => SetXmlNodeBool("@dataOnRows", value);
+ }
+
+ /// <summary>
+ /// if true apply legacy table autoformat number format properties.
+ /// </summary>
+ public bool ApplyNumberFormats {
+ get => GetXmlNodeBool("@applyNumberFormats");
+ set => SetXmlNodeBool("@applyNumberFormats", value);
+ }
+
+ /// <summary>
+ /// If true apply legacy table autoformat border properties
+ /// </summary>
+ public bool ApplyBorderFormats {
+ get => GetXmlNodeBool("@applyBorderFormats");
+ set => SetXmlNodeBool("@applyBorderFormats", value);
+ }
+
+ /// <summary>
+ /// If true apply legacy table autoformat font properties
+ /// </summary>
+ public bool ApplyFontFormats {
+ get => GetXmlNodeBool("@applyFontFormats");
+ set => SetXmlNodeBool("@applyFontFormats", value);
+ }
+
+ /// <summary>
+ /// If true apply legacy table autoformat pattern properties
+ /// </summary>
+ public bool ApplyPatternFormats {
+ get => GetXmlNodeBool("@applyPatternFormats");
+ set => SetXmlNodeBool("@applyPatternFormats", value);
+ }
+
+ /// <summary>
+ /// If true apply legacy table autoformat width/height properties.
+ /// </summary>
+ public bool ApplyWidthHeightFormats {
+ get => GetXmlNodeBool("@applyWidthHeightFormats");
+ set => SetXmlNodeBool("@applyWidthHeightFormats", value);
+ }
+
+ /// <summary>
+ /// Show member property information
+ /// </summary>
+ public bool ShowMemberPropertyTips {
+ get => GetXmlNodeBool("@showMemberPropertyTips");
+ set => SetXmlNodeBool("@showMemberPropertyTips", value);
+ }
+
+ /// <summary>
+ /// Show the drill indicators
+ /// </summary>
+ public bool ShowCalcMember {
+ get => GetXmlNodeBool("@showCalcMbrs");
+ set => SetXmlNodeBool("@showCalcMbrs", value);
+ }
+
+ /// <summary>
+ /// If the user is prevented from drilling down on a PivotItem or aggregate value
+ /// </summary>
+ public bool EnableDrill {
+ get => GetXmlNodeBool("@enableDrill", true);
+ set => SetXmlNodeBool("@enableDrill", value);
+ }
+
+ /// <summary>
+ /// Show the drill down buttons
+ /// </summary>
+ public bool ShowDrill {
+ get => GetXmlNodeBool("@showDrill", true);
+ set => SetXmlNodeBool("@showDrill", value);
+ }
+
+ /// <summary>
+ /// If the tooltips should be displayed for PivotTable data cells.
+ /// </summary>
+ public bool ShowDataTips {
+ get => GetXmlNodeBool("@showDataTips", true);
+ set => SetXmlNodeBool("@showDataTips", value, true);
+ }
+
+ /// <summary>
+ /// If the row and column titles from the PivotTable should be printed.
+ /// </summary>
+ public bool FieldPrintTitles {
+ get => GetXmlNodeBool("@fieldPrintTitles");
+ set => SetXmlNodeBool("@fieldPrintTitles", value);
+ }
+
+ /// <summary>
+ /// If the row and column titles from the PivotTable should be printed.
+ /// </summary>
+ public bool ItemPrintTitles {
+ get => GetXmlNodeBool("@itemPrintTitles");
+ set => SetXmlNodeBool("@itemPrintTitles", value);
+ }
+
+ /// <summary>
+ /// If the grand totals should be displayed for the PivotTable columns
+ /// </summary>
+ public bool ColumGrandTotals {
+ get => GetXmlNodeBool("@colGrandTotals");
+ set => SetXmlNodeBool("@colGrandTotals", value);
+ }
+
+ /// <summary>
+ /// If the grand totals should be displayed for the PivotTable rows
+ /// </summary>
+ public bool RowGrandTotals {
+ get => GetXmlNodeBool("@rowGrandTotals");
+ set => SetXmlNodeBool("@rowGrandTotals", value);
+ }
+
+ /// <summary>
+ /// If the drill indicators expand collapse buttons should be printed.
+ /// </summary>
+ public bool PrintDrill {
+ get => GetXmlNodeBool("@printDrill");
+ set => SetXmlNodeBool("@printDrill", value);
+ }
+
+ /// <summary>
+ /// Indicates whether to show error messages in cells.
+ /// </summary>
+ public bool ShowError {
+ get => GetXmlNodeBool("@showError");
+ set => SetXmlNodeBool("@showError", value);
+ }
+
+ /// <summary>
+ /// The string to be displayed in cells that contain errors.
+ /// </summary>
+ public string ErrorCaption {
+ get => GetXmlNodeString("@errorCaption");
+ set => SetXmlNodeString("@errorCaption", value);
+ }
+
+ /// <summary>
+ /// Specifies the name of the value area field header in the PivotTable.
+ /// This caption is shown when the PivotTable when two or more fields are in the values area.
+ /// </summary>
+ public string DataCaption {
+ get => GetXmlNodeString("@dataCaption");
+ set => SetXmlNodeString("@dataCaption", value);
+ }
+
+ /// <summary>
+ /// Show field headers
+ /// </summary>
+ public bool ShowHeaders {
+ get => GetXmlNodeBool("@showHeaders");
+ set => SetXmlNodeBool("@showHeaders", value);
+ }
+
+ /// <summary>
+ /// The number of page fields to display before starting another row or column
+ /// </summary>
+ public int PageWrap {
+ get => GetXmlNodeInt("@pageWrap");
+ set {
+ if (value < 0) {
+ throw new("Value can't be negative");
+ }
+ SetXmlNodeString("@pageWrap", value.ToString());
+ }
+ }
+
+ /// <summary>
+ /// A boolean that indicates whether legacy auto formatting has been applied to the PivotTable view
+ /// </summary>
+ public bool UseAutoFormatting {
+ get => GetXmlNodeBool("@useAutoFormatting");
+ set => SetXmlNodeBool("@useAutoFormatting", value);
+ }
+
+ /// <summary>
+ /// A boolean that indicates whether the in-grid drop zones should be displayed at runtime, and whether classic layout is applied
+ /// </summary>
+ public bool GridDropZones {
+ get => GetXmlNodeBool("@gridDropZones");
+ set => SetXmlNodeBool("@gridDropZones", value);
+ }
+
+ /// <summary>
+ /// Specifies the indentation increment for compact axis and can be used to set the Report Layout to Compact Form
+ /// </summary>
+ public int Indent {
+ get => GetXmlNodeInt("@indent");
+ set => SetXmlNodeString("@indent", value.ToString());
+ }
+
+ /// <summary>
+ /// A boolean that indicates whether data fields in the PivotTable should be displayed in outline form
+ /// </summary>
+ public bool OutlineData {
+ get => GetXmlNodeBool("@outlineData");
+ set => SetXmlNodeBool("@outlineData", value);
+ }
+
+ /// <summary>
+ /// a boolean that indicates whether new fields should have their outline flag set to true
+ /// </summary>
+ public bool Outline {
+ get => GetXmlNodeBool("@outline");
+ set => SetXmlNodeBool("@outline", value);
+ }
+
+ /// <summary>
+ /// A boolean that indicates whether the fields of a PivotTable can have multiple filters set on them
+ /// </summary>
+ public bool MultipleFieldFilters {
+ get => GetXmlNodeBool("@multipleFieldFilters");
+ set => SetXmlNodeBool("@multipleFieldFilters", value);
+ }
+
+ /// <summary>
+ /// A boolean that indicates whether new fields should have their compact flag set to true
+ /// </summary>
+ public bool Compact {
+ get => GetXmlNodeBool("@compact");
+ set => SetXmlNodeBool("@compact", value);
+ }
+
+ /// <summary>
+ /// A boolean that indicates whether the field next to the data field in the PivotTable should be displayed in the same column of the spreadsheet
+ /// </summary>
+ public bool CompactData {
+ get => GetXmlNodeBool("@compactData");
+ set => SetXmlNodeBool("@compactData", value);
+ }
+
+ /// <summary>
+ /// Specifies the string to be displayed for grand totals.
+ /// </summary>
+ public string GrandTotalCaption {
+ get => GetXmlNodeString("@grandTotalCaption");
+ set => SetXmlNodeString("@grandTotalCaption", value);
+ }
+
+ /// <summary>
+ /// Specifies the string to be displayed in row header in compact mode.
+ /// </summary>
+ public string RowHeaderCaption {
+ get => GetXmlNodeString("@rowHeaderCaption");
+ set => SetXmlNodeString("@rowHeaderCaption", value);
+ }
+
+ /// <summary>
+ /// Specifies the string to be displayed in cells with no value
+ /// </summary>
+ public string MissingCaption {
+ get => GetXmlNodeString("@missingCaption");
+ set => SetXmlNodeString("@missingCaption", value);
+ }
+
+ private const string _firstheaderrowPath = "d:location/@firstHeaderRow";
+
+ /// <summary>
+ /// Specifies the first row of the PivotTable header, relative to the top left cell in the ref value
+ /// </summary>
+ public int FirstHeaderRow {
+ get => GetXmlNodeInt(_firstheaderrowPath);
+ set => SetXmlNodeString(_firstheaderrowPath, value.ToString());
+ }
+
+ private const string _firstdatarowPath = "d:location/@firstDataRow";
+
+ /// <summary>
+ /// Specifies the first column of the PivotTable data, relative to the top left cell in the ref value
+ /// </summary>
+ public int FirstDataRow {
+ get => GetXmlNodeInt(_firstdatarowPath);
+ set => SetXmlNodeString(_firstdatarowPath, value.ToString());
+ }
+
+ private const string _firstdatacolPath = "d:location/@firstDataCol";
+
+ /// <summary>
+ /// Specifies the first column of the PivotTable data, relative to the top left cell in the ref value
+ /// </summary>
+ public int FirstDataCol {
+ get => GetXmlNodeInt(_firstdatacolPath);
+ set => SetXmlNodeString(_firstdatacolPath, value.ToString());
+ }
+
+ private ExcelPivotTableFieldCollection _fields;
+
+ /// <summary>
+ /// The fields in the table
+ /// </summary>
+ public ExcelPivotTableFieldCollection Fields {
+ get {
+ if (_fields == null) {
+ _fields = new(this, "");
+ }
+ return _fields;
+ }
+ }
+
+ private ExcelPivotTableRowColumnFieldCollection _rowFields;
+
+ /// <summary>
+ /// Row label fields
+ /// </summary>
+ public ExcelPivotTableRowColumnFieldCollection RowFields {
+ get {
+ if (_rowFields == null) {
+ _rowFields = new(this, "rowFields");
+ }
+ return _rowFields;
+ }
+ }
+
+ private ExcelPivotTableRowColumnFieldCollection _columnFields;
+
+ /// <summary>
+ /// Column label fields
+ /// </summary>
+ public ExcelPivotTableRowColumnFieldCollection ColumnFields {
+ get {
+ if (_columnFields == null) {
+ _columnFields = new(this, "colFields");
+ }
+ return _columnFields;
+ }
+ }
+
+ private ExcelPivotTableDataFieldCollection _dataFields;
+
+ /// <summary>
+ /// Value fields
+ /// </summary>
+ public ExcelPivotTableDataFieldCollection DataFields {
+ get {
+ if (_dataFields == null) {
+ _dataFields = new(this);
+ }
+ return _dataFields;
+ }
+ }
+
+ private ExcelPivotTableRowColumnFieldCollection _pageFields;
+
+ /// <summary>
+ /// Report filter fields
+ /// </summary>
+ public ExcelPivotTableRowColumnFieldCollection PageFields {
+ get {
+ if (_pageFields == null) {
+ _pageFields = new(this, "pageFields");
+ }
+ return _pageFields;
+ }
+ }
+
+ private const string _stylenamePath = "d:pivotTableStyleInfo/@name";
+
+ /// <summary>
+ /// Pivot style name. Used for custom styles
+ /// </summary>
+ public string StyleName {
+ get => GetXmlNodeString(_stylenamePath);
+ set {
+ if (value.StartsWith("PivotStyle")) {
+ try {
+ _tableStyle = (TableStyles)
+ Enum.Parse(typeof(TableStyles), value.Substring(10, value.Length - 10), true);
+ } catch {
+ _tableStyle = TableStyles.Custom;
+ }
+ } else if (value == "None") {
+ _tableStyle = TableStyles.None;
+ value = "";
+ } else {
+ _tableStyle = TableStyles.Custom;
+ }
+ SetXmlNodeString(_stylenamePath, value, true);
+ }
+ }
+
+ private TableStyles _tableStyle = TableStyles.Medium6;
+
+ /// <summary>
+ /// The table style. If this property is cusom the style from the StyleName propery is used.
+ /// </summary>
+ public TableStyles TableStyle {
+ get => _tableStyle;
+ set {
+ _tableStyle = value;
+ if (value != TableStyles.Custom) {
+ SetXmlNodeString(_stylenamePath, "PivotStyle" + value);
+ }
+ }
+ }
+
+ internal int CacheID {
+ get => GetXmlNodeInt("@cacheId");
+ set => SetXmlNodeString("@cacheId", value.ToString());
+ }
+}
diff --git a/AppsheetEpplus/Table/PivotTable/ExcelPivotTableCollection.cs b/AppsheetEpplus/Table/PivotTable/ExcelPivotTableCollection.cs
new file mode 100644
index 0000000..702107c
--- /dev/null
+++ b/AppsheetEpplus/Table/PivotTable/ExcelPivotTableCollection.cs
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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;
+using System.Collections.Generic;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// A collection of pivottable objects
+/// </summary>
+public class ExcelPivotTableCollection : IEnumerable<ExcelPivotTable> {
+ private readonly List<ExcelPivotTable> _pivotTables = new();
+ internal readonly Dictionary<string, int> _pivotTableNames = new();
+
+ internal ExcelPivotTableCollection(ExcelWorksheet ws) {
+ foreach (var rel in ws.Part.GetRelationships()) {
+ if (rel.RelationshipType == ExcelPackage._schemaRelationships + "/pivotTable") {
+ var tbl = new ExcelPivotTable(rel, ws);
+ _pivotTableNames.Add(tbl.Name, _pivotTables.Count);
+ _pivotTables.Add(tbl);
+ }
+ }
+ }
+
+ public int Count => _pivotTables.Count;
+
+ /// <summary>
+ /// The pivottable Index. Base 0.
+ /// </summary>
+ /// <param name="index"></param>
+ /// <returns></returns>
+ public ExcelPivotTable this[int index] {
+ get {
+ if (index < 0 || index >= _pivotTables.Count) {
+ throw (new ArgumentOutOfRangeException("PivotTable index out of range"));
+ }
+ return _pivotTables[index];
+ }
+ }
+
+ /// <summary>
+ /// Pivottabes accesed by name
+ /// </summary>
+ /// <param name="name">The name of the pivottable</param>
+ /// <returns>The Pivotable. Null if the no match is found</returns>
+ public ExcelPivotTable this[string name] {
+ get {
+ if (_pivotTableNames.ContainsKey(name)) {
+ return _pivotTables[_pivotTableNames[name]];
+ }
+ return null;
+ }
+ }
+
+ public IEnumerator<ExcelPivotTable> GetEnumerator() {
+ return _pivotTables.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _pivotTables.GetEnumerator();
+ }
+}
diff --git a/AppsheetEpplus/Table/PivotTable/ExcelPivotTableDataField.cs b/AppsheetEpplus/Table/PivotTable/ExcelPivotTableDataField.cs
new file mode 100644
index 0000000..1e1b955
--- /dev/null
+++ b/AppsheetEpplus/Table/PivotTable/ExcelPivotTableDataField.cs
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * 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.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// A pivo table data field
+/// </summary>
+public class ExcelPivotTableDataField : XmlHelper {
+ internal ExcelPivotTableDataField(
+ XmlNamespaceManager ns,
+ XmlNode topNode,
+ ExcelPivotTableField field)
+ : base(ns, topNode) {
+ if (topNode.Attributes.Count == 0) {
+ Index = field.Index;
+ BaseField = 0;
+ BaseItem = 0;
+ }
+
+ Field = field;
+ }
+
+ /// <summary>
+ /// The field
+ /// </summary>
+ public ExcelPivotTableField Field { get; private set; }
+
+ /// <summary>
+ /// The index of the datafield
+ /// </summary>
+ public int Index {
+ get => GetXmlNodeInt("@fld");
+ internal set => SetXmlNodeString("@fld", value.ToString());
+ }
+
+ /// <summary>
+ /// The name of the datafield
+ /// </summary>
+ public string Name {
+ get => GetXmlNodeString("@name");
+ set {
+ if (Field._table.DataFields.ExistsDfName(value, this)) {
+ throw (new InvalidOperationException("Duplicate datafield name"));
+ }
+ SetXmlNodeString("@name", value);
+ }
+ }
+
+ /// <summary>
+ /// Field index. Reference to the field collection
+ /// </summary>
+ public int BaseField {
+ get => GetXmlNodeInt("@baseField");
+ set => SetXmlNodeString("@baseField", value.ToString());
+ }
+
+ /// <summary>
+ /// Specifies the index to the base item when the ShowDataAs calculation is in use
+ /// </summary>
+ public int BaseItem {
+ get => GetXmlNodeInt("@baseItem");
+ set => SetXmlNodeString("@baseItem", value.ToString());
+ }
+
+ /// <summary>
+ /// Number format id.
+ /// </summary>
+ internal int NumFmtId {
+ get => GetXmlNodeInt("@numFmtId");
+ set => SetXmlNodeString("@numFmtId", value.ToString());
+ }
+
+ /// <summary>
+ /// Number format for the data column
+ /// </summary>
+ public string Format {
+ get {
+ foreach (var nf in Field._table.WorkSheet.Workbook.Styles.NumberFormats) {
+ if (nf.NumFmtId == NumFmtId) {
+ return nf.Format;
+ }
+ }
+ return Field._table.WorkSheet.Workbook.Styles.NumberFormats[0].Format;
+ }
+ set {
+ var styles = Field._table.WorkSheet.Workbook.Styles;
+
+ ExcelNumberFormatXml nf = null;
+ if (!styles.NumberFormats.FindById(value, ref nf)) {
+ nf = new(NameSpaceManager) {
+ Format = value,
+ NumFmtId = styles.NumberFormats.NextId++,
+ };
+ styles.NumberFormats.Add(value, nf);
+ }
+ NumFmtId = nf.NumFmtId;
+ }
+ }
+
+ /// <summary>
+ /// Type of aggregate function
+ /// </summary>
+ public DataFieldFunctions Function {
+ get {
+ string s = GetXmlNodeString("@subtotal");
+ if (s == "") {
+ return DataFieldFunctions.None;
+ }
+ return (DataFieldFunctions)Enum.Parse(typeof(DataFieldFunctions), s, true);
+ }
+ set {
+ string v;
+ switch (value) {
+ case DataFieldFunctions.None:
+ DeleteNode("@subtotal");
+ return;
+ case DataFieldFunctions.CountNums:
+ v = "CountNums";
+ break;
+ case DataFieldFunctions.StdDev:
+ v = "stdDev";
+ break;
+ case DataFieldFunctions.StdDevP:
+ v = "stdDevP";
+ break;
+ default:
+ v = value.ToString().ToLower(CultureInfo.InvariantCulture);
+ break;
+ }
+ SetXmlNodeString("@subtotal", v);
+ }
+ }
+ /////Since we have no items, Excel will crash when we use showDataAs options that require baseItem's
+ //public eShowDataAs ShowDataAs
+ //{
+ // get
+ // {
+ // string s = GetXmlNodeString("@showDataAs");
+ // if (s == "")
+ // {
+ // return eShowDataAs.Normal;
+ // }
+ // else
+ // {
+ // return (eShowDataAs)Enum.Parse(typeof(eShowDataAs), s, true);
+ // }
+ // }
+ // set
+ // {
+ // string v = value.ToString();
+ // v = v.Substring(0, 1).ToLower() + v.Substring(1);
+ // SetXmlNodeString("@showDataAs", v);
+ // }
+ //}
+}
diff --git a/AppsheetEpplus/Table/PivotTable/ExcelPivotTableField.cs b/AppsheetEpplus/Table/PivotTable/ExcelPivotTableField.cs
new file mode 100644
index 0000000..993277e
--- /dev/null
+++ b/AppsheetEpplus/Table/PivotTable/ExcelPivotTableField.cs
@@ -0,0 +1,566 @@
+/*******************************************************************************
+ * 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.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Defines the axis for a PivotTable
+/// </summary>
+public enum ePivotFieldAxis {
+ /// <summary>
+ /// None
+ /// </summary>
+ None = -1,
+
+ /// <summary>
+ /// Column axis
+ /// </summary>
+ Column,
+
+ /// <summary>
+ /// Page axis (Include Count Filter)
+ ///
+ /// </summary>
+ Page,
+
+ /// <summary>
+ /// Row axis
+ /// </summary>
+ Row,
+
+ /// <summary>
+ /// Values axis
+ /// </summary>
+ Values,
+}
+
+/// <summary>
+/// Build-in table row functions
+/// </summary>
+public enum DataFieldFunctions {
+ Average,
+ Count,
+ CountNums,
+ Max,
+ Min,
+ Product,
+ None,
+ StdDev,
+ StdDevP,
+ Sum,
+ Var,
+ VarP,
+}
+
+/// <summary>
+/// Defines the data formats for a field in the PivotTable
+/// </summary>
+public enum eShowDataAs {
+ /// <summary>
+ /// Indicates the field is shown as the "difference from" a value.
+ /// </summary>
+ Difference,
+
+ /// <summary>
+ /// Indicates the field is shown as the "index.
+ /// </summary>
+ Index,
+
+ /// <summary>
+ /// Indicates that the field is shown as its normal datatype.
+ /// </summary>
+ Normal,
+
+ /// <summary>
+ /// /Indicates the field is show as the "percentage of" a value
+ /// </summary>
+ Percent,
+
+ /// <summary>
+ /// Indicates the field is shown as the "percentage difference from" a value.
+ /// </summary>
+ PercentDiff,
+
+ /// <summary>
+ /// Indicates the field is shown as the percentage of column.
+ /// </summary>
+ PercentOfCol,
+
+ /// <summary>
+ /// Indicates the field is shown as the percentage of row
+ /// </summary>
+ PercentOfRow,
+
+ /// <summary>
+ /// Indicates the field is shown as percentage of total.
+ /// </summary>
+ PercentOfTotal,
+
+ /// <summary>
+ /// Indicates the field is shown as running total in the table.
+ /// </summary>
+ RunTotal,
+}
+
+/// <summary>
+/// Built-in subtotal functions
+/// </summary>
+[Flags]
+public enum eSubTotalFunctions {
+ None = 1,
+ Count = 2,
+ CountA = 4,
+ Avg = 8,
+ Default = 16,
+ Min = 32,
+ Max = 64,
+ Product = 128,
+ StdDev = 256,
+ StdDevP = 512,
+ Sum = 1024,
+ Var = 2048,
+ VarP = 4096,
+}
+
+/// <summary>
+/// Data grouping
+/// </summary>
+[Flags]
+public enum eDateGroupBy {
+ Years = 1,
+ Quarters = 2,
+ Months = 4,
+ Days = 8,
+ Hours = 16,
+ Minutes = 32,
+ Seconds = 64,
+}
+
+/// <summary>
+/// Sorting
+/// </summary>
+public enum eSortType {
+ None,
+ Ascending,
+ Descending,
+}
+
+/// <summary>
+/// A pivot table field.
+/// </summary>
+public class ExcelPivotTableField : XmlHelper {
+ internal ExcelPivotTable _table;
+
+ internal ExcelPivotTableField(
+ XmlNamespaceManager ns,
+ XmlNode topNode,
+ ExcelPivotTable table,
+ int index,
+ int baseIndex)
+ : base(ns, topNode) {
+ Index = index;
+ BaseIndex = baseIndex;
+ _table = table;
+ }
+
+ public int Index { get; set; }
+
+ internal int BaseIndex { get; set; }
+
+ /// <summary>
+ /// Name of the field
+ /// </summary>
+ public string Name {
+ get {
+ string v = GetXmlNodeString("@name");
+ if (v == "") {
+ return _cacheFieldHelper.GetXmlNodeString("@name");
+ }
+ return v;
+ }
+ set => SetXmlNodeString("@name", value);
+ }
+
+ /// <summary>
+ /// Compact mode
+ /// </summary>
+ public bool Compact {
+ get => GetXmlNodeBool("@compact");
+ set => SetXmlNodeBool("@compact", value);
+ }
+
+ /// <summary>
+ /// A boolean that indicates whether the items in this field should be shown in Outline form
+ /// </summary>
+ public bool Outline {
+ get => GetXmlNodeBool("@outline");
+ set => SetXmlNodeBool("@outline", value);
+ }
+
+ /// <summary>
+ /// The custom text that is displayed for the subtotals label
+ /// </summary>
+ public bool SubtotalTop {
+ get => GetXmlNodeBool("@subtotalTop");
+ set => SetXmlNodeBool("@subtotalTop", value);
+ }
+
+ /// <summary>
+ /// A boolean that indicates whether to show all items for this field
+ /// </summary>
+ public bool ShowAll {
+ get => GetXmlNodeBool("@showAll");
+ set => SetXmlNodeBool("@showAll", value);
+ }
+
+ /// <summary>
+ /// The type of sort that is applied to this field
+ /// </summary>
+ public eSortType Sort {
+ get {
+ string v = GetXmlNodeString("@sortType");
+ return v == "" ? eSortType.None : (eSortType)Enum.Parse(typeof(eSortType), v, true);
+ }
+ set {
+ if (value == eSortType.None) {
+ DeleteNode("@sortType");
+ } else {
+ SetXmlNodeString("@sortType", value.ToString().ToLower(CultureInfo.InvariantCulture));
+ }
+ }
+ }
+
+ /// <summary>
+ /// A boolean that indicates whether manual filter is in inclusive mode
+ /// </summary>
+ public bool IncludeNewItemsInFilter {
+ get => GetXmlNodeBool("@includeNewItemsInFilter");
+ set => SetXmlNodeBool("@includeNewItemsInFilter", value);
+ }
+
+ /// <summary>
+ /// Enumeration of the different subtotal operations that can be applied to page, row or column fields
+ /// </summary>
+ public eSubTotalFunctions SubTotalFunctions {
+ get {
+ eSubTotalFunctions ret = 0;
+ XmlNodeList nl = TopNode.SelectNodes("d:items/d:item/@t", NameSpaceManager);
+ if (nl.Count == 0) {
+ return eSubTotalFunctions.None;
+ }
+ foreach (XmlAttribute item in nl) {
+ try {
+ ret |= (eSubTotalFunctions)Enum.Parse(typeof(eSubTotalFunctions), item.Value, true);
+ } catch (ArgumentException ex) {
+ throw new ArgumentException(
+ "Unable to parse value of "
+ + item.Value
+ + " to a valid pivot table subtotal function",
+ ex);
+ }
+ }
+ return ret;
+ }
+ set {
+ if ((value & eSubTotalFunctions.None) == eSubTotalFunctions.None
+ && (value != eSubTotalFunctions.None)) {
+ throw (new ArgumentException("Value None can not be combined with other values."));
+ }
+ if ((value & eSubTotalFunctions.Default) == eSubTotalFunctions.Default
+ && (value != eSubTotalFunctions.Default)) {
+ throw (new ArgumentException("Value Default can not be combined with other values."));
+ }
+
+ // remove old attribute
+ XmlNodeList nl = TopNode.SelectNodes("d:items/d:item/@t", NameSpaceManager);
+ if (nl.Count > 0) {
+ foreach (XmlAttribute item in nl) {
+ DeleteNode("@" + item.Value + "Subtotal");
+ item.OwnerElement.ParentNode.RemoveChild(item.OwnerElement);
+ }
+ }
+
+ if (value == eSubTotalFunctions.None) {
+ // for no subtotals, set defaultSubtotal to off
+ SetXmlNodeBool("@defaultSubtotal", false);
+ TopNode.InnerXml = "";
+ } else {
+ string innerXml = "";
+ int count = 0;
+ foreach (eSubTotalFunctions e in Enum.GetValues(typeof(eSubTotalFunctions))) {
+ if ((value & e) == e) {
+ var newTotalType = e.ToString();
+ var totalType =
+ char.ToLower(newTotalType[0], CultureInfo.InvariantCulture)
+ + newTotalType.Substring(1);
+ // add new attribute
+ SetXmlNodeBool("@" + totalType + "Subtotal", true);
+ innerXml += "<item t=\"" + totalType + "\" />";
+ count++;
+ }
+ }
+ TopNode.InnerXml = string.Format("<items count=\"{0}\">{1}</items>", count, innerXml);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Type of axis
+ /// </summary>
+ public ePivotFieldAxis Axis {
+ get {
+ switch (GetXmlNodeString("@axis")) {
+ case "axisRow":
+ return ePivotFieldAxis.Row;
+ case "axisCol":
+ return ePivotFieldAxis.Column;
+ case "axisPage":
+ return ePivotFieldAxis.Page;
+ case "axisValues":
+ return ePivotFieldAxis.Values;
+ default:
+ return ePivotFieldAxis.None;
+ }
+ }
+ internal set {
+ switch (value) {
+ case ePivotFieldAxis.Row:
+ SetXmlNodeString("@axis", "axisRow");
+ break;
+ case ePivotFieldAxis.Column:
+ SetXmlNodeString("@axis", "axisCol");
+ break;
+ case ePivotFieldAxis.Values:
+ SetXmlNodeString("@axis", "axisValues");
+ break;
+ case ePivotFieldAxis.Page:
+ SetXmlNodeString("@axis", "axisPage");
+ break;
+ default:
+ DeleteNode("@axis");
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// If the field is a row field
+ /// </summary>
+ public bool IsRowField {
+ get =>
+ (TopNode.SelectSingleNode(
+ string.Format("../../d:rowFields/d:field[@x={0}]", Index),
+ NameSpaceManager) != null);
+ internal set {
+ if (value) {
+ var rowsNode = TopNode.SelectSingleNode("../../d:rowFields", NameSpaceManager);
+ if (rowsNode == null) {
+ _table.CreateNode("d:rowFields");
+ }
+ rowsNode = TopNode.SelectSingleNode("../../d:rowFields", NameSpaceManager);
+
+ AppendField(rowsNode, Index, "field", "x");
+ if (BaseIndex == Index) {
+ TopNode.InnerXml = "<items count=\"1\"><item t=\"default\" /></items>";
+ } else {
+ TopNode.InnerXml = "<items count=\"0\"></items>";
+ }
+ } else {
+ XmlElement node =
+ TopNode.SelectSingleNode(
+ string.Format("../../d:rowFields/d:field[@x={0}]", Index),
+ NameSpaceManager) as XmlElement;
+ if (node != null) {
+ node.ParentNode.RemoveChild(node);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// If the field is a column field
+ /// </summary>
+ public bool IsColumnField {
+ get =>
+ (TopNode.SelectSingleNode(
+ string.Format("../../d:colFields/d:field[@x={0}]", Index),
+ NameSpaceManager) != null);
+ internal set {
+ if (value) {
+ var columnsNode = TopNode.SelectSingleNode("../../d:colFields", NameSpaceManager);
+ if (columnsNode == null) {
+ _table.CreateNode("d:colFields");
+ }
+ columnsNode = TopNode.SelectSingleNode("../../d:colFields", NameSpaceManager);
+
+ AppendField(columnsNode, Index, "field", "x");
+ if (BaseIndex == Index) {
+ TopNode.InnerXml = "<items count=\"1\"><item t=\"default\" /></items>";
+ } else {
+ TopNode.InnerXml = "<items count=\"0\"></items>";
+ }
+ } else {
+ XmlElement node =
+ TopNode.SelectSingleNode(
+ string.Format("../../d:colFields/d:field[@x={0}]", Index),
+ NameSpaceManager) as XmlElement;
+ if (node != null) {
+ node.ParentNode.RemoveChild(node);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// If the field is a datafield
+ /// </summary>
+ public bool IsDataField => GetXmlNodeBool("@dataField", false);
+
+ /// <summary>
+ /// If the field is a page field.
+ /// </summary>
+ public bool IsPageField {
+ get => (Axis == ePivotFieldAxis.Page);
+ internal set {
+ if (value) {
+ var dataFieldsNode = TopNode.SelectSingleNode("../../d:pageFields", NameSpaceManager);
+ if (dataFieldsNode == null) {
+ _table.CreateNode("d:pageFields");
+ dataFieldsNode = TopNode.SelectSingleNode("../../d:pageFields", NameSpaceManager);
+ }
+
+ TopNode.InnerXml = "<items count=\"1\"><item t=\"default\" /></items>";
+
+ XmlElement node = AppendField(dataFieldsNode, Index, "pageField", "fld");
+ _pageFieldSettings = new(NameSpaceManager, node, this, Index);
+ } else {
+ _pageFieldSettings = null;
+ XmlElement node =
+ TopNode.SelectSingleNode(
+ string.Format("../../d:pageFields/d:pageField[@fld={0}]", Index),
+ NameSpaceManager) as XmlElement;
+ if (node != null) {
+ node.ParentNode.RemoveChild(node);
+ }
+ }
+ }
+ }
+
+ //public ExcelPivotGrouping DateGrouping
+ //{
+
+ //}
+ internal ExcelPivotTablePageFieldSettings _pageFieldSettings;
+
+ public ExcelPivotTablePageFieldSettings PageFieldSettings => _pageFieldSettings;
+
+ internal eDateGroupBy DateGrouping { get; set; }
+
+ private ExcelPivotTableFieldGroup _grouping;
+
+ /// <summary>
+ /// Grouping settings.
+ /// Null if the field has no grouping otherwise ExcelPivotTableFieldNumericGroup or ExcelPivotTableFieldNumericGroup.
+ /// </summary>
+ public ExcelPivotTableFieldGroup Grouping => _grouping;
+
+ internal XmlElement AppendField(
+ XmlNode rowsNode,
+ int index,
+ string fieldNodeText,
+ string indexAttrText) {
+ XmlElement prevField = null,
+ newElement;
+ foreach (XmlElement field in rowsNode.ChildNodes) {
+ string x = field.GetAttribute(indexAttrText);
+ if (int.TryParse(x, out var fieldIndex)) {
+ if (fieldIndex
+ == index) //Row already exists
+ {
+ return field;
+ }
+ //else if (fieldIndex > index)
+ //{
+ // newElement = rowsNode.OwnerDocument.CreateElement(fieldNodeText, ExcelPackage.schemaMain);
+ // newElement.SetAttribute(indexAttrText, index.ToString());
+ // rowsNode.InsertAfter(newElement, field);
+ //}
+ }
+ prevField = field;
+ }
+ newElement = rowsNode.OwnerDocument.CreateElement(fieldNodeText, ExcelPackage._schemaMain);
+ newElement.SetAttribute(indexAttrText, index.ToString());
+ rowsNode.InsertAfter(newElement, prevField);
+
+ return newElement;
+ }
+
+ internal XmlHelperInstance _cacheFieldHelper;
+
+ internal void SetCacheFieldNode(XmlNode cacheField) {
+ _cacheFieldHelper = new(NameSpaceManager, cacheField);
+ var groupNode = cacheField.SelectSingleNode("d:fieldGroup", NameSpaceManager);
+ if (groupNode != null) {
+ var groupBy = groupNode.SelectSingleNode("d:rangePr/@groupBy", NameSpaceManager);
+ if (groupBy == null) {
+ _grouping = new ExcelPivotTableFieldNumericGroup(NameSpaceManager, cacheField);
+ } else {
+ DateGrouping = (eDateGroupBy)Enum.Parse(typeof(eDateGroupBy), groupBy.Value, true);
+ _grouping = new ExcelPivotTableFieldDateGroup(NameSpaceManager, groupNode);
+ }
+ }
+ }
+
+ internal ExcelPivotTableFieldCollectionBase<ExcelPivotTableFieldItem> _items;
+
+ /// <summary>
+ /// Pivottable field Items. Used for grouping.
+ /// </summary>
+ public ExcelPivotTableFieldCollectionBase<ExcelPivotTableFieldItem> Items {
+ get {
+ if (_items == null) {
+ _items = new(_table);
+ foreach (XmlNode node in TopNode.SelectNodes("d:items//d:item", NameSpaceManager)) {
+ var item = new ExcelPivotTableFieldItem(NameSpaceManager, node, this);
+ if (item.T == "") {
+ _items.AddInternal(item);
+ }
+ }
+ }
+ return _items;
+ }
+ }
+}
diff --git a/AppsheetEpplus/Table/PivotTable/ExcelPivotTableFieldCollection.cs b/AppsheetEpplus/Table/PivotTable/ExcelPivotTableFieldCollection.cs
new file mode 100644
index 0000000..f69bef6
--- /dev/null
+++ b/AppsheetEpplus/Table/PivotTable/ExcelPivotTableFieldCollection.cs
@@ -0,0 +1,302 @@
+/*******************************************************************************
+ * 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;
+using System.Collections.Generic;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Base collection class for pivottable fields
+/// </summary>
+/// <typeparam name="T"></typeparam>
+public class ExcelPivotTableFieldCollectionBase<T> : IEnumerable<T> {
+ protected ExcelPivotTable _table;
+ internal List<T> _list = new();
+
+ internal ExcelPivotTableFieldCollectionBase(ExcelPivotTable table) {
+ _table = table;
+ }
+
+ public IEnumerator<T> GetEnumerator() {
+ return _list.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _list.GetEnumerator();
+ }
+
+ public int Count => _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<ExcelPivotTableField> {
+ internal ExcelPivotTableFieldCollection(ExcelPivotTable table, string topNode)
+ : base(table) {}
+
+ /// <summary>
+ /// Indexer by name
+ /// </summary>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ public ExcelPivotTableField this[string name] {
+ get {
+ foreach (var field in _list) {
+ if (field.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)) {
+ return field;
+ }
+ }
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Returns the date group field.
+ /// </summary>
+ /// <param name="groupBy">The type of grouping</param>
+ /// <returns>The matching field. If none is found null is returned</returns>
+ public ExcelPivotTableField GetDateGroupField(eDateGroupBy groupBy) {
+ foreach (var fld in _list) {
+ if (fld.Grouping is ExcelPivotTableFieldDateGroup group && (group.GroupBy) == groupBy) {
+ return fld;
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Returns the numeric group field.
+ /// </summary>
+ /// <returns>The matching field. If none is found null is returned</returns>
+ public ExcelPivotTableField GetNumericGroupField() {
+ foreach (var fld in _list) {
+ if (fld.Grouping is ExcelPivotTableFieldNumericGroup) {
+ return fld;
+ }
+ }
+ return null;
+ }
+}
+
+/// <summary>
+/// Collection class for Row and column fields in a Pivottable
+/// </summary>
+public class ExcelPivotTableRowColumnFieldCollection
+ : ExcelPivotTableFieldCollectionBase<ExcelPivotTableField> {
+ internal string _topNode;
+
+ internal ExcelPivotTableRowColumnFieldCollection(ExcelPivotTable table, string topNode)
+ : base(table) {
+ _topNode = topNode;
+ }
+
+ /// <summary>
+ /// Add a new row/column field
+ /// </summary>
+ /// <param name="field">The field</param>
+ /// <returns>The new field</returns>
+ public ExcelPivotTableField Add(ExcelPivotTableField field) {
+ SetFlag(field, true);
+ _list.Add(field);
+ return field;
+ }
+
+ /// <summary>
+ /// Insert a new row/column field
+ /// </summary>
+ /// <param name="field">The field</param>
+ /// <param name="index">The position to insert the field</param>
+ /// <returns>The new field</returns>
+ 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(
+ "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(
+ "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("Field is a column or row field. Can't add it to the PageFields collection"));
+ }
+ if (_table.Address._fromRow < 3) {
+ throw (new(
+ 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;
+ }
+ }
+
+ /// <summary>
+ /// Remove a field
+ /// </summary>
+ /// <param name="field"></param>
+ public void Remove(ExcelPivotTableField field) {
+ if (!_list.Contains(field)) {
+ throw new ArgumentException("Field not in collection");
+ }
+ SetFlag(field, false);
+ _list.Remove(field);
+ }
+
+ /// <summary>
+ /// Remove a field at a specific position
+ /// </summary>
+ /// <param name="index"></param>
+ public void RemoveAt(int index) {
+ if (index > -1 && index < _list.Count) {
+ throw (new IndexOutOfRangeException());
+ }
+ SetFlag(_list[index], false);
+ _list.RemoveAt(index);
+ }
+}
+
+/// <summary>
+/// Collection class for data fields in a Pivottable
+/// </summary>
+public class ExcelPivotTableDataFieldCollection
+ : ExcelPivotTableFieldCollectionBase<ExcelPivotTableDataField> {
+ internal ExcelPivotTableDataFieldCollection(ExcelPivotTable table)
+ : base(table) {}
+
+ /// <summary>
+ /// Add a new datafield
+ /// </summary>
+ /// <param name="field">The field</param>
+ /// <returns>The new datafield</returns>
+ 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++;
+ } 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;
+ }
+
+ /// <summary>
+ /// Remove a datafield
+ /// </summary>
+ /// <param name="dataField"></param>
+ 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);
+ }
+}
diff --git a/AppsheetEpplus/Table/PivotTable/ExcelPivotTableFieldGroup.cs b/AppsheetEpplus/Table/PivotTable/ExcelPivotTableFieldGroup.cs
new file mode 100644
index 0000000..6cfa457
--- /dev/null
+++ b/AppsheetEpplus/Table/PivotTable/ExcelPivotTableFieldGroup.cs
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * 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.Globalization;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Base class for pivot table field groups
+/// </summary>
+public class ExcelPivotTableFieldGroup : XmlHelper {
+ internal ExcelPivotTableFieldGroup(XmlNamespaceManager ns, XmlNode topNode)
+ : base(ns, topNode) {}
+}
+
+/// <summary>
+/// A date group
+/// </summary>
+public class ExcelPivotTableFieldDateGroup : ExcelPivotTableFieldGroup {
+ internal ExcelPivotTableFieldDateGroup(XmlNamespaceManager ns, XmlNode topNode)
+ : base(ns, topNode) {}
+
+ private const string _groupByPath = "d:fieldGroup/d:rangePr/@groupBy";
+
+ /// <summary>
+ /// How to group the date field
+ /// </summary>
+ public eDateGroupBy GroupBy {
+ get {
+ string v = GetXmlNodeString(_groupByPath);
+ if (v != "") {
+ return (eDateGroupBy)Enum.Parse(typeof(eDateGroupBy), v, true);
+ }
+ throw (new("Invalid date Groupby"));
+ }
+ private set =>
+ SetXmlNodeString(_groupByPath, value.ToString().ToLower(CultureInfo.InvariantCulture));
+ }
+
+ /// <summary>
+ /// Auto detect start date
+ /// </summary>
+ public bool AutoStart => GetXmlNodeBool("@autoStart", false);
+
+ /// <summary>
+ /// Auto detect end date
+ /// </summary>
+ public bool AutoEnd => GetXmlNodeBool("@autoStart", false);
+}
+
+/// <summary>
+/// A pivot table field numeric grouping
+/// </summary>
+public class ExcelPivotTableFieldNumericGroup : ExcelPivotTableFieldGroup {
+ internal ExcelPivotTableFieldNumericGroup(XmlNamespaceManager ns, XmlNode topNode)
+ : base(ns, topNode) {}
+
+ private const string _startPath = "d:fieldGroup/d:rangePr/@startNum";
+
+ /// <summary>
+ /// Start value
+ /// </summary>
+ public double Start => (double)GetXmlNodeDoubleNull(_startPath);
+
+ private const string _endPath = "d:fieldGroup/d:rangePr/@endNum";
+
+ /// <summary>
+ /// End value
+ /// </summary>
+ public double End => (double)GetXmlNodeDoubleNull(_endPath);
+
+ private const string _groupIntervalPath = "d:fieldGroup/d:rangePr/@groupInterval";
+
+ /// <summary>
+ /// Interval
+ /// </summary>
+ public double Interval => (double)GetXmlNodeDoubleNull(_groupIntervalPath);
+}
diff --git a/AppsheetEpplus/Table/PivotTable/ExcelPivotTableFieldItem.cs b/AppsheetEpplus/Table/PivotTable/ExcelPivotTableFieldItem.cs
new file mode 100644
index 0000000..f1343f6
--- /dev/null
+++ b/AppsheetEpplus/Table/PivotTable/ExcelPivotTableFieldItem.cs
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// A field Item. Used for grouping
+/// </summary>
+public class ExcelPivotTableFieldItem : XmlHelper {
+ private readonly ExcelPivotTableField _field;
+
+ internal ExcelPivotTableFieldItem(
+ XmlNamespaceManager ns,
+ XmlNode topNode,
+ ExcelPivotTableField field)
+ : base(ns, topNode) {
+ _field = field;
+ }
+
+ /// <summary>
+ /// The text. Unique values only
+ /// </summary>
+ public string Text {
+ get => GetXmlNodeString("@n");
+ set {
+ if (string.IsNullOrEmpty(value)) {
+ DeleteNode("@n");
+ return;
+ }
+ foreach (var item in _field.Items) {
+ if (item.Text == value) {
+ throw (new ArgumentException("Duplicate Text"));
+ }
+ }
+ SetXmlNodeString("@n", value);
+ }
+ }
+
+ internal int X => GetXmlNodeInt("@x");
+
+ internal string T => GetXmlNodeString("@t");
+}
diff --git a/AppsheetEpplus/Table/PivotTable/ExcelPivotTablePageFieldSettings.cs b/AppsheetEpplus/Table/PivotTable/ExcelPivotTablePageFieldSettings.cs
new file mode 100644
index 0000000..a90de61
--- /dev/null
+++ b/AppsheetEpplus/Table/PivotTable/ExcelPivotTablePageFieldSettings.cs
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// A page / report filter field
+/// </summary>
+public class ExcelPivotTablePageFieldSettings : XmlHelper {
+ private ExcelPivotTableField _field;
+
+ internal ExcelPivotTablePageFieldSettings(
+ XmlNamespaceManager ns,
+ XmlNode topNode,
+ ExcelPivotTableField field,
+ int index)
+ : base(ns, topNode) {
+ if (GetXmlNodeString("@hier") == "") {
+ Hier = -1;
+ }
+ _field = field;
+ }
+
+ internal int Index {
+ get => GetXmlNodeInt("@fld");
+ set => SetXmlNodeString("@fld", value.ToString());
+ }
+
+ /// <summary>
+ /// The Name of the field
+ /// </summary>
+ public string Name {
+ get => GetXmlNodeString("@name");
+ set => SetXmlNodeString("@name", value);
+ }
+
+ /***** Dont work. Need items to be populated. ****/
+ ///// <summary>
+ ///// The selected item
+ ///// </summary>
+ //public int SelectedItem
+ //{
+ // get
+ // {
+ // return GetXmlNodeInt("@item");
+ // }
+ // set
+ // {
+ // if (value < 0) throw new InvalidOperationException("Can't be negative");
+ // SetXmlNodeString("@item", value.ToString());
+ // }
+ //}
+ internal int NumFmtId {
+ get => GetXmlNodeInt("@numFmtId");
+ set => SetXmlNodeString("@numFmtId", value.ToString());
+ }
+
+ internal int Hier {
+ get => GetXmlNodeInt("@hier");
+ set => SetXmlNodeString("@hier", value.ToString());
+ }
+}
diff --git a/AppsheetEpplus/Utils/AddressUtility.cs b/AppsheetEpplus/Utils/AddressUtility.cs
new file mode 100644
index 0000000..5f1a5d8
--- /dev/null
+++ b/AppsheetEpplus/Utils/AddressUtility.cs
@@ -0,0 +1,20 @@
+using System.Text.RegularExpressions;
+
+namespace AppsheetEpplus;
+
+public static class AddressUtility {
+ public static string ParseEntireColumnSelections(string address) {
+ string parsedAddress = address;
+ var matches = Regex.Matches(address, "[A-Z]+:[A-Z]+");
+ foreach (Match match in matches) {
+ AddRowNumbersToEntireColumnRange(ref parsedAddress, match.Value);
+ }
+ return parsedAddress;
+ }
+
+ private static void AddRowNumbersToEntireColumnRange(ref string address, string range) {
+ var parsedRange = string.Format("{0}{1}", range, ExcelPackage.MaxRows);
+ var splitArr = parsedRange.Split([':']);
+ address = address.Replace(range, string.Format("{0}1:{1}", splitArr[0], splitArr[1]));
+ }
+}
diff --git a/AppsheetEpplus/Utils/Argument.cs b/AppsheetEpplus/Utils/Argument.cs
new file mode 100644
index 0000000..72afd32
--- /dev/null
+++ b/AppsheetEpplus/Utils/Argument.cs
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+internal class Argument<T> : IArgument<T> {
+ public Argument(T value) {
+ _value = value;
+ }
+
+ private readonly T _value;
+
+ T IArgument<T>.Value => _value;
+}
diff --git a/AppsheetEpplus/Utils/ArgumentExtensions.cs b/AppsheetEpplus/Utils/ArgumentExtensions.cs
new file mode 100644
index 0000000..d2cf41e
--- /dev/null
+++ b/AppsheetEpplus/Utils/ArgumentExtensions.cs
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Extension methods for guarding
+/// </summary>
+public static class ArgumentExtensions {
+ /// <summary>
+ /// Throws an ArgumentNullException if argument is null
+ /// </summary>
+ /// <typeparam name="T">Argument type</typeparam>
+ /// <param name="argument">Argument to check</param>
+ /// <param name="argumentName">parameter/argument name</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ public static void IsNotNull<T>(this IArgument<T> argument, string argumentName)
+ where T : class {
+ argumentName = string.IsNullOrEmpty(argumentName) ? "value" : argumentName;
+ if (argument.Value == null) {
+ throw new ArgumentNullException(argumentName);
+ }
+ }
+
+ /// <summary>
+ /// Throws an <see cref="ArgumentNullException"/> if the string argument is null or empty
+ /// </summary>
+ /// <param name="argument">Argument to check</param>
+ /// <param name="argumentName">parameter/argument name</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ public static void IsNotNullOrEmpty(this IArgument<string> argument, string argumentName) {
+ if (string.IsNullOrEmpty(argument.Value)) {
+ throw new ArgumentNullException(argumentName);
+ }
+ }
+
+ /// <summary>
+ /// Throws an ArgumentOutOfRangeException if the value of the argument is out of the supplied range
+ /// </summary>
+ /// <typeparam name="T">Type implementing <see cref="IComparable"/></typeparam>
+ /// <param name="argument">The argument to check</param>
+ /// <param name="min">Min value of the supplied range</param>
+ /// <param name="max">Max value of the supplied range</param>
+ /// <param name="argumentName">parameter/argument name</param>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public static void IsInRange<T>(this IArgument<T> argument, T min, T max, string argumentName)
+ where T : IComparable {
+ if (!(argument.Value.CompareTo(min) >= 0 && argument.Value.CompareTo(max) <= 0)) {
+ throw new ArgumentOutOfRangeException(argumentName);
+ }
+ }
+}
diff --git a/AppsheetEpplus/Utils/ConvertUtil.cs b/AppsheetEpplus/Utils/ConvertUtil.cs
new file mode 100644
index 0000000..ecdf789
--- /dev/null
+++ b/AppsheetEpplus/Utils/ConvertUtil.cs
@@ -0,0 +1,171 @@
+using System;
+using System.Globalization;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace AppsheetEpplus;
+
+internal static class ConvertUtil {
+ internal static bool IsNumeric(object candidate) {
+ if (candidate == null) {
+ return false;
+ }
+ return (candidate.GetType().IsPrimitive
+ || candidate is double
+ || candidate is decimal
+ || candidate is DateTime
+ || candidate is TimeSpan
+ || candidate is long);
+ }
+
+ internal static bool IsNumericString(object candidate) {
+ if (candidate != null) {
+ return Regex.IsMatch(candidate.ToString(), @"^[\d]+(\,[\d])?");
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Convert an object value to a double
+ /// </summary>
+ /// <param name="v"></param>
+ /// <param name="ignoreBool"></param>
+ /// <returns></returns>
+ internal static double GetValueDouble(object v, bool ignoreBool = false) {
+ double d;
+ try {
+ if (ignoreBool && v is bool) {
+ return 0;
+ }
+ if (IsNumeric(v)) {
+ if (v is DateTime time) {
+ d = time.ToOADate();
+ } else if (v is TimeSpan span) {
+ d = DateTime.FromOADate(0).Add(span).ToOADate();
+ } else {
+ d = Convert.ToDouble(v, CultureInfo.InvariantCulture);
+ }
+ } else {
+ d = 0;
+ }
+ } catch {
+ d = 0;
+ }
+ return d;
+ }
+
+ /// <summary>
+ /// OOXML requires that "," , and & be escaped, but ' and " should *not* be escaped, nor should
+ /// any extended Unicode characters. This function only encodes the required characters.
+ /// System.Security.SecurityElement.Escape() escapes ' and " as ' and ", so it cannot
+ /// be used reliably. System.Web.HttpUtility.HtmlEncode overreaches as well and uses the numeric
+ /// escape equivalent.
+ /// </summary>
+ /// <param name="s"></param>
+ /// <returns></returns>
+ internal static string ExcelEscapeString(string s) {
+ return s.Replace("&", "&").Replace("<", "<").Replace(">", ">");
+ }
+
+ /// <summary>
+ /// Return true if preserve space attribute is set.
+ /// </summary>
+ /// <param name="sw"></param>
+ /// <param name="t"></param>
+ /// <returns></returns>
+ internal static void ExcelEncodeString(StreamWriter sw, string t) {
+ if (Regex.IsMatch(t, "(_x[0-9A-F]{4,4}_)")) {
+ var match = Regex.Match(t, "(_x[0-9A-F]{4,4}_)");
+ int indexAdd = 0;
+ while (match.Success) {
+ t = t.Insert(match.Index + indexAdd, "_x005F");
+ indexAdd += 6;
+ match = match.NextMatch();
+ }
+ }
+ for (int i = 0; i < t.Length; i++) {
+ if (t[i] <= 0x1f
+ && t[i] != '\t'
+ && t[i] != '\n'
+ && t[i]
+ != '\r') //Not Tab, CR or LF
+ {
+ sw.Write("_x00{0}_", (t[i] < 0xf ? "0" : "") + ((int)t[i]).ToString("X"));
+ } else {
+ sw.Write(t[i]);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Return true if preserve space attribute is set.
+ /// </summary>
+ /// <param name="sb"></param>
+ /// <param name="t"></param>
+ /// <returns></returns>
+ internal static void ExcelEncodeString(StringBuilder sb, string t, bool encodeTabCrlf = false) {
+ if (Regex.IsMatch(t, "(_x[0-9A-F]{4,4}_)")) {
+ var match = Regex.Match(t, "(_x[0-9A-F]{4,4}_)");
+ int indexAdd = 0;
+ while (match.Success) {
+ t = t.Insert(match.Index + indexAdd, "_x005F");
+ indexAdd += 6;
+ match = match.NextMatch();
+ }
+ }
+ for (int i = 0; i < t.Length; i++) {
+ if (t[i] <= 0x1f
+ && ((t[i] != '\t' && t[i] != '\n' && t[i] != '\r' && encodeTabCrlf == false)
+ || encodeTabCrlf)) //Not Tab, CR or LF
+ {
+ sb.AppendFormat("_x00{0}_", (t[i] < 0xf ? "0" : "") + ((int)t[i]).ToString("X"));
+ } else {
+ sb.Append(t[i]);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Return true if preserve space attribute is set.
+ /// </summary>
+ /// <param name="sb"></param>
+ /// <param name="t"></param>
+ /// <returns></returns>
+ internal static string ExcelEncodeString(string t) {
+ StringBuilder sb = new StringBuilder();
+ t = t.Replace("\r\n", "\n"); //For some reason can't table name have cr in them. Replace with nl
+ ExcelEncodeString(sb, t, true);
+ return sb.ToString();
+ }
+
+ internal static string ExcelDecodeString(string t) {
+ var match = Regex.Match(t, "(_x005F|_x[0-9A-F]{4,4}_)");
+ if (!match.Success) {
+ return t;
+ }
+
+ var useNextValue = false;
+ var ret = new StringBuilder();
+ var prevIndex = 0;
+ while (match.Success) {
+ if (prevIndex < match.Index) {
+ ret.Append(t.Substring(prevIndex, match.Index - prevIndex));
+ }
+ if (!useNextValue && match.Value == "_x005F") {
+ useNextValue = true;
+ } else {
+ if (useNextValue) {
+ ret.Append(match.Value);
+ useNextValue = false;
+ } else {
+ ret.Append((char)int.Parse(match.Value.Substring(2, 4), NumberStyles.AllowHexSpecifier));
+ }
+ }
+ prevIndex = match.Index + match.Length;
+ match = match.NextMatch();
+ }
+ ret.Append(t.Substring(prevIndex, t.Length - prevIndex));
+ return ret.ToString();
+ }
+}
diff --git a/AppsheetEpplus/Utils/IArgument.cs b/AppsheetEpplus/Utils/IArgument.cs
new file mode 100644
index 0000000..9622d01
--- /dev/null
+++ b/AppsheetEpplus/Utils/IArgument.cs
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Added 2011-01-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// An argument
+/// </summary>
+/// <typeparam name="T">Argument Type</typeparam>
+public interface IArgument<T> {
+ T Value { get; }
+}
diff --git a/AppsheetEpplus/Utils/IExcelCell.cs b/AppsheetEpplus/Utils/IExcelCell.cs
new file mode 100644
index 0000000..005ed03
--- /dev/null
+++ b/AppsheetEpplus/Utils/IExcelCell.cs
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-16
+ *******************************************************************************/
+
+using System;
+
+namespace AppsheetEpplus;
+
+internal interface IExcelCell {
+ object Value { get; set; }
+
+ string StyleName { get; }
+
+ int StyleID { get; set; }
+
+ ExcelStyle Style { get; }
+
+ Uri Hyperlink { get; set; }
+
+ string Formula { get; set; }
+
+ string FormulaR1C1 { get; set; }
+}
diff --git a/AppsheetEpplus/Utils/IValidationResult.cs b/AppsheetEpplus/Utils/IValidationResult.cs
new file mode 100644
index 0000000..70c1df9
--- /dev/null
+++ b/AppsheetEpplus/Utils/IValidationResult.cs
@@ -0,0 +1,7 @@
+namespace AppsheetEpplus;
+
+public interface IValidationResult {
+ void IsTrue();
+
+ void IsFalse();
+}
diff --git a/AppsheetEpplus/Utils/SqRefUtility.cs b/AppsheetEpplus/Utils/SqRefUtility.cs
new file mode 100644
index 0000000..94f853e
--- /dev/null
+++ b/AppsheetEpplus/Utils/SqRefUtility.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Text.RegularExpressions;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Class for handling translation between ExcelAddresses and sqref addresses.
+/// </summary>
+public static class SqRefUtility {
+ /// <summary>
+ /// Transforms an address to a valid sqRef address.
+ /// </summary>
+ /// <param name="address">The address to transform</param>
+ /// <returns>A valid SqRef address</returns>
+ public static string ToSqRefAddress(string address) {
+ ArgumentException.ThrowIfNullOrEmpty(address);
+ address = address.Replace(",", " ");
+ address = new Regex("[ ]+").Replace(address, " ");
+ return address;
+ }
+
+ /// <summary>
+ /// Transforms an sqRef address into a excel address
+ /// </summary>
+ /// <param name="address">The address to transform</param>
+ /// <returns>A valid excel address</returns>
+ public static string FromSqRefAddress(string address) {
+ ArgumentException.ThrowIfNullOrEmpty(address);
+ address = address.Replace(" ", ",");
+ return address;
+ }
+}
diff --git a/AppsheetEpplus/Utils/UriHelper.cs b/AppsheetEpplus/Utils/UriHelper.cs
new file mode 100644
index 0000000..8356ab1
--- /dev/null
+++ b/AppsheetEpplus/Utils/UriHelper.cs
@@ -0,0 +1,69 @@
+using System;
+
+namespace AppsheetEpplus;
+
+internal class UriHelper {
+ internal static Uri ResolvePartUri(Uri sourceUri, Uri targetUri) {
+ if (targetUri.OriginalString.StartsWith("/")) {
+ return targetUri;
+ }
+ string[] source = sourceUri.OriginalString.Split('/');
+ string[] target = targetUri.OriginalString.Split('/');
+
+ int t = target.Length - 1;
+ int s;
+ if (sourceUri.OriginalString.EndsWith(
+ "/")) //is the source a directory?
+ {
+ s = source.Length - 1;
+ } else {
+ s = source.Length - 2;
+ }
+
+ string file = target[t--];
+
+ while (t >= 0) {
+ if (target[t] == ".") {
+ break;
+ }
+ if (target[t] == "..") {
+ s--;
+ t--;
+ } else {
+ file = target[t--] + "/" + file;
+ }
+ }
+ if (s >= 0) {
+ for (int i = s; i >= 0; i--) {
+ file = source[i] + "/" + file;
+ }
+ }
+ return new(file, UriKind.RelativeOrAbsolute);
+ }
+
+ internal static Uri GetRelativeUri(Uri worksheetUri, Uri uri) {
+ string[] source = worksheetUri.OriginalString.Split('/');
+ string[] target = uri.OriginalString.Split('/');
+
+ int slen;
+ if (worksheetUri.OriginalString.EndsWith("/")) {
+ slen = source.Length;
+ } else {
+ slen = source.Length - 1;
+ }
+ int i = 0;
+ while (i < slen && i < target.Length && source[i] == target[i]) {
+ i++;
+ }
+
+ string dirUp = "";
+ for (int s = i; s < slen; s++) {
+ dirUp += "../";
+ }
+ string file = "";
+ for (int t = i; t < target.Length; t++) {
+ file += (file == "" ? "" : "/") + target[t];
+ }
+ return new(dirUp + file, UriKind.Relative);
+ }
+}
diff --git a/AppsheetEpplus/Utils/ValidationResult.cs b/AppsheetEpplus/Utils/ValidationResult.cs
new file mode 100644
index 0000000..73086ee
--- /dev/null
+++ b/AppsheetEpplus/Utils/ValidationResult.cs
@@ -0,0 +1,35 @@
+using System;
+
+namespace AppsheetEpplus;
+
+public class ValidationResult : IValidationResult {
+ public ValidationResult(bool result)
+ : this(result, null) {}
+
+ public ValidationResult(bool result, string errorMessage) {
+ _result = result;
+ _errorMessage = errorMessage;
+ }
+
+ private readonly bool _result;
+ private readonly string _errorMessage;
+
+ private void Throw() {
+ if (string.IsNullOrEmpty(_errorMessage)) {
+ throw new InvalidOperationException();
+ }
+ throw new InvalidOperationException(_errorMessage);
+ }
+
+ void IValidationResult.IsTrue() {
+ if (!_result) {
+ Throw();
+ }
+ }
+
+ void IValidationResult.IsFalse() {
+ if (_result) {
+ Throw();
+ }
+ }
+}
diff --git a/AppsheetEpplus/XmlHelper.cs b/AppsheetEpplus/XmlHelper.cs
new file mode 100644
index 0000000..44e6905
--- /dev/null
+++ b/AppsheetEpplus/XmlHelper.cs
@@ -0,0 +1,627 @@
+/*******************************************************************************
+ * 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 Initial Release 2009-10-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ * Eyal Seagull Add "CreateComplexNode" 2012-04-03
+ * Eyal Seagull Add "DeleteTopNode" 2012-04-13
+ *******************************************************************************/
+
+using System;
+using System.Collections.Immutable;
+using System.Globalization;
+using System.IO;
+using System.Text;
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+/// <summary>
+/// Help class containing XML functions.
+/// Can be Inherited
+/// </summary>
+public abstract class XmlHelper {
+ internal delegate int ChangedEventHandler(StyleBase sender, StyleChangeEventArgs e);
+
+ internal XmlHelper(XmlNamespaceManager nameSpaceManager) {
+ TopNode = null;
+ NameSpaceManager = nameSpaceManager;
+ }
+
+ internal XmlHelper(XmlNamespaceManager nameSpaceManager, XmlNode topNode) {
+ TopNode = topNode;
+ NameSpaceManager = nameSpaceManager;
+ }
+
+ //internal bool ChangedFlag;
+ internal XmlNamespaceManager NameSpaceManager { get; set; }
+
+ internal XmlNode TopNode { get; set; }
+
+ /// <summary>
+ /// Schema order list
+ /// </summary>
+ protected virtual ImmutableArray<string> SchemaNodeOrder => ImmutableArray<string>.Empty;
+
+ internal XmlNode CreateNode(string path) {
+ if (path == "") {
+ return TopNode;
+ }
+ return CreateNode(path, false);
+ }
+
+ internal XmlNode CreateNode(string path, bool insertFirst) {
+ XmlNode node = TopNode;
+ XmlNode prependNode = null;
+ foreach (string subPath in path.Split('/')) {
+ XmlNode subNode = node.SelectSingleNode(subPath, NameSpaceManager);
+ if (subNode == null) {
+ string nodeName;
+ string nodePrefix;
+
+ string nameSpaceUri;
+ string[] nameSplit = subPath.Split(':');
+
+ if (SchemaNodeOrder.Length > 0 && subPath[0] != '@') {
+ insertFirst = false;
+ prependNode = GetPrependNode(subPath, node);
+ }
+
+ if (nameSplit.Length > 1) {
+ nodePrefix = nameSplit[0];
+ if (nodePrefix[0] == '@') {
+ nodePrefix = nodePrefix.Substring(1, nodePrefix.Length - 1);
+ }
+ nameSpaceUri = NameSpaceManager.LookupNamespace(nodePrefix);
+ nodeName = nameSplit[1];
+ } else {
+ nodePrefix = "";
+ nameSpaceUri = "";
+ nodeName = nameSplit[0];
+ }
+ if (subPath.StartsWith("@")) {
+ XmlAttribute addedAtt = node.OwnerDocument.CreateAttribute(
+ subPath.Substring(1, subPath.Length - 1),
+ nameSpaceUri); //nameSpaceURI
+ node.Attributes.Append(addedAtt);
+ } else {
+ if (nodePrefix == "") {
+ subNode = node.OwnerDocument.CreateElement(nodeName, nameSpaceUri);
+ } else {
+ if (nodePrefix == ""
+ || (node.OwnerDocument != null
+ && node.OwnerDocument.DocumentElement != null
+ && node.OwnerDocument.DocumentElement.NamespaceURI == nameSpaceUri
+ && node.OwnerDocument.DocumentElement.Prefix == "")) {
+ subNode = node.OwnerDocument.CreateElement(nodeName, nameSpaceUri);
+ } else {
+ subNode = node.OwnerDocument.CreateElement(nodePrefix, nodeName, nameSpaceUri);
+ }
+ }
+ if (prependNode != null) {
+ node.InsertBefore(subNode, prependNode);
+ prependNode = null;
+ } else if (insertFirst) {
+ node.PrependChild(subNode);
+ } else {
+ node.AppendChild(subNode);
+ }
+ }
+ }
+ node = subNode;
+ }
+ return node;
+ }
+
+ /// <summary>
+ /// Options to insert a node in the XmlDocument
+ /// </summary>
+ internal enum eNodeInsertOrder {
+ /// <summary>
+ /// Insert as first node of "topNode"
+ /// </summary>
+ First,
+
+ /// <summary>
+ /// Insert as the last child of "topNode"
+ /// </summary>
+ Last,
+
+ /// <summary>
+ /// Insert after the "referenceNode"
+ /// </summary>
+ After,
+
+ /// <summary>
+ /// Insert before the "referenceNode"
+ /// </summary>
+ Before,
+
+ /// <summary>
+ /// Use the Schema List to insert in the right order. If the Schema list
+ /// is null or empty, consider "Last" as the selected option
+ /// </summary>
+ SchemaOrder,
+ }
+
+ /// <summary>
+ /// Create a complex node. Insert the node according to the <paramref name="path"/>
+ /// using the <paramref name="topNode"/> as the parent
+ /// </summary>
+ /// <param name="topNode"></param>
+ /// <param name="path"></param>
+ /// <returns></returns>
+ internal XmlNode CreateComplexNode(XmlNode topNode, string path) {
+ return CreateComplexNode(topNode, path, eNodeInsertOrder.SchemaOrder, null);
+ }
+
+ /// <summary>
+ /// Creates complex XML nodes
+ /// </summary>
+ /// <remarks>
+ /// 1. "d:conditionalFormatting"
+ /// 1.1. Creates/find the first "conditionalFormatting" node
+ ///
+ /// 2. "d:conditionalFormatting/@sqref"
+ /// 2.1. Creates/find the first "conditionalFormatting" node
+ /// 2.2. Creates (if not exists) the @sqref attribute
+ ///
+ /// 3. "d:conditionalFormatting/@id='7'/@sqref='A9:B99'"
+ /// 3.1. Creates/find the first "conditionalFormatting" node
+ /// 3.2. Creates/update its @id attribute to "7"
+ /// 3.3. Creates/update its @sqref attribute to "A9:B99"
+ ///
+ /// 4. "d:conditionalFormatting[@id='7']/@sqref='X1:X5'"
+ /// 4.1. Creates/find the first "conditionalFormatting" node with @id=7
+ /// 4.2. Creates/update its @sqref attribute to "X1:X5"
+ ///
+ /// 5. "d:conditionalFormatting[@id='7']/@id='8'/@sqref='X1:X5'/d:cfRule/@id='AB'"
+ /// 5.1. Creates/find the first "conditionalFormatting" node with @id=7
+ /// 5.2. Set its @id attribute to "8"
+ /// 5.2. Creates/update its @sqref attribute and set it to "X1:X5"
+ /// 5.3. Creates/find the first "cfRule" node (inside the node)
+ /// 5.4. Creates/update its @id attribute to "AB"
+ ///
+ /// 6. "d:cfRule/@id=''"
+ /// 6.1. Creates/find the first "cfRule" node
+ /// 6.1. Remove the @id attribute
+ /// </remarks>
+ /// <param name="topNode"></param>
+ /// <param name="path"></param>
+ /// <param name="nodeInsertOrder"></param>
+ /// <param name="referenceNode"></param>
+ /// <returns>The last node creates/found</returns>
+ internal XmlNode CreateComplexNode(
+ XmlNode topNode,
+ string path,
+ eNodeInsertOrder nodeInsertOrder,
+ XmlNode referenceNode) {
+ // Path is obrigatory
+ if ((path == null) || (path == string.Empty)) {
+ return topNode;
+ }
+
+ XmlNode node = topNode;
+
+ //TODO: BUG: when the "path" contains "/" in an attrribue value, it gives an error.
+
+ // Separate the XPath to Nodes and Attributes
+ foreach (string subPath in path.Split('/')) {
+ // The subPath can be any one of those:
+ // nodeName
+ // x:nodeName
+ // nodeName[find criteria]
+ // x:nodeName[find criteria]
+ // @attribute
+ // @attribute='attribute value'
+
+ // Check if the subPath has at least one character
+ if (subPath.Length > 0) {
+ // Check if the subPath is an attribute (with or without value)
+ if (subPath.StartsWith("@")) {
+ // @attribute --> Create attribute
+ // @attribute='' --> Remove attribute
+ // @attribute='attribute value' --> Create attribute + update value
+ string[] attributeSplit = subPath.Split('=');
+ string attributeName = attributeSplit[0].Substring(1, attributeSplit[0].Length - 1);
+ string attributeValue = null; // Null means no attribute value
+
+ // Check if we have an attribute value to set
+ if (attributeSplit.Length > 1) {
+ // Remove the ' or " from the attribute value
+ attributeValue = attributeSplit[1].Replace("'", "").Replace("\"", "");
+ }
+
+ // Get the attribute (if exists)
+ XmlAttribute attribute = (XmlAttribute)(node.Attributes.GetNamedItem(attributeName));
+
+ // Remove the attribute if value is empty (not null)
+ if (attributeValue == string.Empty) {
+ // Only if the attribute exists
+ if (attribute != null) {
+ node.Attributes.Remove(attribute);
+ }
+ } else {
+ // Create the attribue if does not exists
+ if (attribute == null) {
+ // Create the attribute
+ attribute = node.OwnerDocument.CreateAttribute(attributeName);
+
+ // Add it to the current node
+ node.Attributes.Append(attribute);
+ }
+
+ // Update the attribute value
+ if (attributeValue != null) {
+ node.Attributes[attributeName].Value = attributeValue;
+ }
+ }
+ } else {
+ // nodeName
+ // x:nodeName
+ // nodeName[find criteria]
+ // x:nodeName[find criteria]
+
+ // Look for the node (with or without filter criteria)
+ XmlNode subNode = node.SelectSingleNode(subPath, NameSpaceManager);
+
+ // Check if the node does not exists
+ if (subNode == null) {
+ string nodeName;
+ string nodePrefix;
+ string[] nameSplit = subPath.Split(':');
+ string nameSpaceUri;
+
+ // Check if the name has a prefix like "d:nodeName"
+ if (nameSplit.Length > 1) {
+ nodePrefix = nameSplit[0];
+ nameSpaceUri = NameSpaceManager.LookupNamespace(nodePrefix);
+ nodeName = nameSplit[1];
+ } else {
+ nodePrefix = string.Empty;
+ nameSpaceUri = string.Empty;
+ nodeName = nameSplit[0];
+ }
+
+ // Check if we have a criteria part in the node name
+ if (nodeName.IndexOf("[") > 0) {
+ // remove the criteria from the node name
+ nodeName = nodeName.Substring(0, nodeName.IndexOf("["));
+ }
+
+ if (nodePrefix == string.Empty) {
+ subNode = node.OwnerDocument.CreateElement(nodeName, nameSpaceUri);
+ } else {
+ if (node.OwnerDocument != null
+ && node.OwnerDocument.DocumentElement != null
+ && node.OwnerDocument.DocumentElement.NamespaceURI == nameSpaceUri
+ && node.OwnerDocument.DocumentElement.Prefix == string.Empty) {
+ subNode = node.OwnerDocument.CreateElement(nodeName, nameSpaceUri);
+ } else {
+ subNode = node.OwnerDocument.CreateElement(nodePrefix, nodeName, nameSpaceUri);
+ }
+ }
+
+ // Check if we need to use the "SchemaOrder"
+ if (nodeInsertOrder == eNodeInsertOrder.SchemaOrder) {
+ // Check if the Schema Order List is empty
+ if (SchemaNodeOrder.Length == 0) {
+ // Use the "Insert Last" option when Schema Order List is empty
+ nodeInsertOrder = eNodeInsertOrder.Last;
+ } else {
+ // Find the prepend node in order to insert
+ referenceNode = GetPrependNode(nodeName, node);
+
+ if (referenceNode != null) {
+ nodeInsertOrder = eNodeInsertOrder.Before;
+ } else {
+ nodeInsertOrder = eNodeInsertOrder.Last;
+ }
+ }
+ }
+
+ switch (nodeInsertOrder) {
+ case eNodeInsertOrder.After:
+ node.InsertAfter(subNode, referenceNode);
+ referenceNode = null;
+ break;
+
+ case eNodeInsertOrder.Before:
+ node.InsertBefore(subNode, referenceNode);
+ referenceNode = null;
+ break;
+
+ case eNodeInsertOrder.First:
+ node.PrependChild(subNode);
+ break;
+
+ case eNodeInsertOrder.Last:
+ node.AppendChild(subNode);
+ break;
+ }
+ }
+
+ // Make the newly created node the top node when the rest of the path
+ // is being evaluated. So newly created nodes will be the children of the
+ // one we just created.
+ node = subNode;
+ }
+ }
+ }
+
+ // Return the last created/found node
+ return node;
+ }
+
+ /// <summary>
+ /// return Prepend node
+ /// </summary>
+ /// <param name="nodeName">name of the node to check</param>
+ /// <param name="node">Topnode to check children</param>
+ /// <returns></returns>
+ private XmlNode GetPrependNode(string nodeName, XmlNode node) {
+ int pos = GetNodePos(nodeName);
+ if (pos < 0) {
+ return null;
+ }
+ XmlNode prependNode = null;
+ foreach (XmlNode childNode in node.ChildNodes) {
+ int childPos = GetNodePos(childNode.Name);
+ if (childPos
+ > -1) //Found?
+ {
+ if (childPos
+ > pos) //Position is before
+ {
+ prependNode = childNode;
+ break;
+ }
+ }
+ }
+ return prependNode;
+ }
+
+ private int GetNodePos(string nodeName) {
+ int ix = nodeName.IndexOf(":");
+ if (ix > 0) {
+ nodeName = nodeName.Substring(ix + 1, nodeName.Length - (ix + 1));
+ }
+ for (int i = 0; i < SchemaNodeOrder.Length; i++) {
+ if (nodeName == SchemaNodeOrder[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ internal void DeleteAllNode(string path) {
+ string[] split = path.Split('/');
+ XmlNode node = TopNode;
+ foreach (string s in split) {
+ node = node.SelectSingleNode(s, NameSpaceManager);
+ if (node != null) {
+ if (node is XmlAttribute attribute) {
+ attribute.OwnerElement.Attributes.Remove(attribute);
+ } else {
+ node.ParentNode.RemoveChild(node);
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ internal void DeleteNode(string path) {
+ var node = TopNode.SelectSingleNode(path, NameSpaceManager);
+ if (node != null) {
+ if (node is XmlAttribute att) {
+ att.OwnerElement.Attributes.Remove(att);
+ } else {
+ node.ParentNode.RemoveChild(node);
+ }
+ }
+ }
+
+ internal void SetXmlNodeString(string path, string value) {
+ SetXmlNodeString(TopNode, path, value, false, false);
+ }
+
+ internal void SetXmlNodeString(string path, string value, bool removeIfBlank) {
+ SetXmlNodeString(TopNode, path, value, removeIfBlank, false);
+ }
+
+ internal void SetXmlNodeString(XmlNode node, string path, string value, bool removeIfBlank) {
+ SetXmlNodeString(node, path, value, removeIfBlank, false);
+ }
+
+ internal void SetXmlNodeString(
+ XmlNode node,
+ string path,
+ string value,
+ bool removeIfBlank,
+ bool insertFirst) {
+ if (node == null) {
+ return;
+ }
+ if (value == "" && removeIfBlank) {
+ DeleteAllNode(path);
+ } else {
+ XmlNode nameNode = node.SelectSingleNode(path, NameSpaceManager);
+ if (nameNode == null) {
+ CreateNode(path, insertFirst);
+ nameNode = node.SelectSingleNode(path, NameSpaceManager);
+ }
+ //if (nameNode.InnerText != value) HasChanged();
+ nameNode.InnerText = value;
+ }
+ }
+
+ internal void SetXmlNodeBool(string path, bool value) {
+ SetXmlNodeString(TopNode, path, value ? "1" : "0", false, false);
+ }
+
+ internal void SetXmlNodeBool(string path, bool value, bool removeIf) {
+ if (value == removeIf) {
+ var node = TopNode.SelectSingleNode(path, NameSpaceManager);
+ if (node != null) {
+ if (node is XmlAttribute attribute) {
+ var elem = attribute.OwnerElement;
+ elem.ParentNode.RemoveChild(elem);
+ } else {
+ TopNode.RemoveChild(node);
+ }
+ }
+ } else {
+ SetXmlNodeString(TopNode, path, value ? "1" : "0", false, false);
+ }
+ }
+
+ internal bool ExistNode(string path) {
+ if (TopNode == null || TopNode.SelectSingleNode(path, NameSpaceManager) == null) {
+ return false;
+ }
+ return true;
+ }
+
+ internal bool? GetXmlNodeBoolNullable(string path) {
+ var value = GetXmlNodeString(path);
+ if (string.IsNullOrEmpty(value)) {
+ return null;
+ }
+ return GetXmlNodeBool(path);
+ }
+
+ internal bool GetXmlNodeBool(string path) {
+ return GetXmlNodeBool(path, false);
+ }
+
+ internal bool GetXmlNodeBool(string path, bool blankValue) {
+ string value = GetXmlNodeString(path);
+ if (value == "1"
+ || value == "-1"
+ || value.Equals("true", StringComparison.InvariantCultureIgnoreCase)) {
+ return true;
+ }
+ if (value == "") {
+ return blankValue;
+ }
+ return false;
+ }
+
+ internal int GetXmlNodeInt(string path) {
+ if (int.TryParse(GetXmlNodeString(path), out var i)) {
+ return i;
+ }
+ return int.MinValue;
+ }
+
+ internal int? GetXmlNodeIntNull(string path) {
+ string s = GetXmlNodeString(path);
+ if (s != "" && int.TryParse(s, out var i)) {
+ return i;
+ }
+ return null;
+ }
+
+ internal decimal GetXmlNodeDecimal(string path) {
+ if (decimal.TryParse(
+ GetXmlNodeString(path),
+ NumberStyles.Any,
+ CultureInfo.InvariantCulture,
+ out var d)) {
+ return d;
+ }
+ return 0;
+ }
+
+ internal decimal? GetXmlNodeDecimalNull(string path) {
+ if (decimal.TryParse(
+ GetXmlNodeString(path),
+ NumberStyles.Any,
+ CultureInfo.InvariantCulture,
+ out var d)) {
+ return d;
+ }
+ return null;
+ }
+
+ internal double? GetXmlNodeDoubleNull(string path) {
+ string s = GetXmlNodeString(path);
+ if (s == "") {
+ return null;
+ }
+ if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out var v)) {
+ return v;
+ }
+ return null;
+ }
+
+ internal double GetXmlNodeDouble(string path) {
+ string s = GetXmlNodeString(path);
+ if (s == "") {
+ return double.NaN;
+ }
+ if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out var v)) {
+ return v;
+ }
+ return double.NaN;
+ }
+
+ internal string GetXmlNodeString(XmlNode node, string path) {
+ if (node == null) {
+ return "";
+ }
+
+ XmlNode nameNode = node.SelectSingleNode(path, NameSpaceManager);
+
+ if (nameNode != null) {
+ if (nameNode.NodeType == XmlNodeType.Attribute) {
+ return nameNode.Value ?? "";
+ }
+ return nameNode.InnerText;
+ }
+ return "";
+ }
+
+ internal string GetXmlNodeString(string path) {
+ return GetXmlNodeString(TopNode, path);
+ }
+
+ internal static void LoadXmlSafe(XmlDocument xmlDoc, Stream stream) {
+ XmlReaderSettings settings = new XmlReaderSettings();
+ //Disable entity parsing (to aviod xmlbombs, External Entity Attacks etc).
+ settings.ProhibitDtd = true;
+ XmlReader reader = XmlReader.Create(stream, settings);
+ xmlDoc.Load(reader);
+ }
+
+ internal static void LoadXmlSafe(XmlDocument xmlDoc, string xml, Encoding encoding) {
+ var stream = new MemoryStream(encoding.GetBytes(xml));
+ LoadXmlSafe(xmlDoc, stream);
+ }
+}
diff --git a/AppsheetEpplus/XmlHelperFactory.cs b/AppsheetEpplus/XmlHelperFactory.cs
new file mode 100644
index 0000000..9de58cf
--- /dev/null
+++ b/AppsheetEpplus/XmlHelperFactory.cs
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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
+ * ******************************************************************************
+ * Mats Alm Initial Release 2011-05-01
+ * Jan Källman License changed GPL-->LGPL 2011-12-27
+ *******************************************************************************/
+
+using System.Xml;
+
+namespace AppsheetEpplus;
+
+internal class XmlHelperInstance : XmlHelper {
+ internal XmlHelperInstance(XmlNamespaceManager namespaceManager)
+ : base(namespaceManager) {}
+
+ internal XmlHelperInstance(XmlNamespaceManager namespaceManager, XmlNode topNode)
+ : base(namespaceManager, topNode) {}
+}
+
+internal static class XmlHelperFactory {
+ internal static XmlHelper Create(XmlNamespaceManager namespaceManager) {
+ return new XmlHelperInstance(namespaceManager);
+ }
+
+ internal static XmlHelper Create(XmlNamespaceManager namespaceManager, XmlNode topNode) {
+ return new XmlHelperInstance(namespaceManager, topNode);
+ }
+}
diff --git a/EPPlus.sln b/EPPlus.sln
index d838aaf..f19d997 100644
--- a/EPPlus.sln
+++ b/EPPlus.sln
@@ -9,22 +9,18 @@
LocalTestRun.testrunconfig = LocalTestRun.testrunconfig
EndProjectSection
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EPPlusSDK", "EPPlus\EPPlusSDK.csproj", "{256597F1-67E5-478D-B5B8-3BBB47CB3D3F}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetCoreTests", "NetCoreTests\NetCoreTests.csproj", "{7D59FAA6-A53F-4672-8387-9281731509F2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EpplusFormulaParser", "EpplusFormulaParser\EpplusFormulaParser.csproj", "{5411F24B-D58C-40F5-9300-E02C28154A4C}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppsheetEpplus", "AppsheetEpplus\AppsheetEpplus.csproj", "{7B288026-5502-4A39-BF41-77E086F3E4A3}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {256597F1-67E5-478D-B5B8-3BBB47CB3D3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {256597F1-67E5-478D-B5B8-3BBB47CB3D3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {256597F1-67E5-478D-B5B8-3BBB47CB3D3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {256597F1-67E5-478D-B5B8-3BBB47CB3D3F}.Release|Any CPU.Build.0 = Release|Any CPU
{7D59FAA6-A53F-4672-8387-9281731509F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7D59FAA6-A53F-4672-8387-9281731509F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7D59FAA6-A53F-4672-8387-9281731509F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -33,6 +29,10 @@
{5411F24B-D58C-40F5-9300-E02C28154A4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5411F24B-D58C-40F5-9300-E02C28154A4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5411F24B-D58C-40F5-9300-E02C28154A4C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7B288026-5502-4A39-BF41-77E086F3E4A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7B288026-5502-4A39-BF41-77E086F3E4A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7B288026-5502-4A39-BF41-77E086F3E4A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7B288026-5502-4A39-BF41-77E086F3E4A3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/EPPlus/CellStore.cs b/EPPlus/CellStore.cs
deleted file mode 100644
index 684cf3b..0000000
--- a/EPPlus/CellStore.cs
+++ /dev/null
@@ -1,1491 +0,0 @@
-/*******************************************************************************
- * 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 2012-11-25
- *******************************************************************************/
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using OfficeOpenXml;
-
-internal class IndexBase : IComparable<IndexBase> {
- internal short Index;
-
- public int CompareTo(IndexBase other) {
- return Index < other.Index
- ? -1
- : Index > other.Index
- ? 1
- : 0;
- }
-}
-
-internal class IndexItem : IndexBase {
- internal int IndexPointer { get; set; }
-}
-
-internal class ColumnIndex : IndexBase {
- private readonly IndexBase _searchIx = new();
-
- internal int GetPosition(int row) {
- var page = (short)(row >> CellStore<int>._pageBits);
- _searchIx.Index = page;
- var res =
- (_pages != null
- && page >= 0
- && page < PageCount
- && page < _pages.Length
- && _pages[page] != null
- && _pages[page].Index == page)
- ? page
- : Array.BinarySearch(_pages, 0, PageCount, _searchIx);
- if (res >= 0) {
- GetPage(row, ref res);
- return res;
- }
- var p = ~res;
-
- if (GetPage(row, ref p)) {
- return p;
- }
- return res;
- }
-
- private bool GetPage(int row, ref int res) {
- if (res < PageCount && _pages[res].MinIndex <= row && _pages[res].MaxIndex >= row) {
- return true;
- }
- if (res + 1 < PageCount && (_pages[res + 1].MinIndex <= row)) {
- do {
- res++;
- } while (res + 1 < PageCount && _pages[res + 1].MinIndex <= row);
- //if (res + 1 < PageCount && _pages[res + 1].MaxIndex >= Row)
- //{
- return true;
- //}
- //else
- //{
- // return false;
- //}
- }
- if (res - 1 >= 0 && _pages[res - 1].MaxIndex >= row) {
- do {
- res--;
- } while (res - 1 > 0 && _pages[res - 1].MaxIndex >= row);
- //if (res > 0)
- //{
- return true;
- //}
- //else
- //{
- // return false;
- //}
- }
- return false;
- }
-
- internal int GetNextRow(int row) {
- //var page = (int)((ulong)row >> CellStore<int>.pageBits);
- var p = GetPosition(row);
- if (p < 0) {
- p = ~p;
- if (p >= PageCount) {
- return -1;
- }
- if (_pages[p].IndexOffset + _pages[p].Rows[0].Index < row) {
- if (p + 1 >= PageCount) {
- return -1;
- }
- return _pages[p + 1].IndexOffset + _pages[p].Rows[0].Index;
- }
- return _pages[p].IndexOffset + _pages[p].Rows[0].Index;
- }
- if (p < PageCount) {
- var r = _pages[p].GetNextRow(row);
- if (r >= 0) {
- return _pages[p].IndexOffset + _pages[p].Rows[r].Index;
- } else {
- if (++p < PageCount) {
- return _pages[p].IndexOffset + _pages[p].Rows[0].Index;
- } else {
- return -1;
- }
- }
- }
- return -1;
- }
-
- internal PageIndex[] _pages = new PageIndex[CellStore<int>._pagesPerColumnMin];
- internal int PageCount;
-}
-
-internal class PageIndex : IndexBase {
- private readonly IndexBase _searchIx = new();
-
- public PageIndex() {
- Rows = new IndexItem[CellStore<int>._pageSizeMin];
- RowCount = 0;
- }
-
- public PageIndex(IndexItem[] rows, int count) {
- Rows = rows;
- RowCount = count;
- }
-
- public PageIndex(PageIndex pageItem, int start, int size)
- : this(pageItem, start, size, pageItem.Index, pageItem.Offset) {}
-
- public PageIndex(PageIndex pageItem, int start, int size, short index, int offset) {
- Rows = new IndexItem[CellStore<int>.GetSize(size)];
- Array.Copy(pageItem.Rows, start, Rows, 0, size);
- RowCount = size;
- Index = index;
- Offset = offset;
- }
-
- internal int Offset;
-
- internal int IndexOffset => IndexExpanded + Offset;
-
- internal int IndexExpanded => (Index << CellStore<int>._pageBits);
-
- internal IndexItem[] Rows { get; set; }
-
- internal int RowCount;
-
- internal int GetPosition(int offset) {
- _searchIx.Index = (short)offset;
- return (Rows != null
- && offset > 0
- && offset - 1 < RowCount
- && offset - 1 < Rows.Length
- && Rows[offset - 1] != null
- && Rows[offset - 1].Index == offset)
- ? offset - 1
- : Array.BinarySearch(Rows, 0, RowCount, _searchIx);
- }
-
- internal int GetNextRow(int row) {
- int offset = row - IndexOffset;
- var o = GetPosition(offset);
- if (o < 0) {
- o = ~o;
- if (o < RowCount) {
- return o;
- }
- return -1;
- }
- return o;
- }
-
- public int MinIndex {
- get {
- if (Rows.Length > 0) {
- return IndexOffset + Rows[0].Index;
- }
- return -1;
- }
- }
-
- public int MaxIndex {
- get {
- if (RowCount > 0) {
- return IndexOffset + Rows[RowCount - 1].Index;
- }
- return -1;
- }
- }
-
- public int GetIndex(int pos) {
- return IndexOffset + Rows[pos].Index;
- }
-}
-
-/// <summary>
-/// This is the store for all Rows, Columns and Cells.
-/// It is a Dictionary implementation that allows you to change the Key (the RowID, ColumnID or CellID )
-/// </summary>
-internal class CellStore<T> {
- /**** Size constants ****/
- internal const int _pageBits = 10; //13bits=8192 Note: Maximum is 13 bits since short is used (PageMax=16K)
- internal const int _pageSize = 1 << _pageBits;
- internal const int _pageSizeMin = 1 << 10;
- internal const int _pageSizeMax = _pageSize << 1; //Double page size
- internal const int _colSizeMin = 32;
- internal const int _pagesPerColumnMin = 32;
-
- private List<T> _values = new();
- internal ColumnIndex[] _columnIndex = new ColumnIndex[_colSizeMin];
- internal IndexBase _searchIx = new();
- internal int ColumnCount;
-
- ~CellStore() {
- if (_values != null) {
- _values.Clear();
- _values = null;
- }
- _columnIndex = null;
- }
-
- internal int GetPosition(int column) {
- _searchIx.Index = (short)column;
- return (_columnIndex != null
- && column > 0
- && column - 1 < ColumnCount
- && column - 1 < _columnIndex.Length
- && _columnIndex[column - 1] != null
- && _columnIndex[column - 1].Index == column)
- ? column - 1
- : Array.BinarySearch(_columnIndex, 0, ColumnCount, _searchIx);
- }
-
- internal bool GetDimension(out int fromRow, out int fromCol, out int toRow, out int toCol) {
- if (ColumnCount == 0) {
- fromRow = fromCol = toRow = toCol = 0;
- return false;
- }
- fromCol = _columnIndex[0].Index;
- var fromIndex = 0;
- if (fromCol <= 0 && ColumnCount > 1) {
- fromCol = _columnIndex[1].Index;
- fromIndex = 1;
- } else if (ColumnCount == 1 && fromCol <= 0) {
- fromRow = fromCol = toRow = toCol = 0;
- return false;
- }
- var col = ColumnCount - 1;
- while (col > 0) {
- if (_columnIndex[col].PageCount == 0
- || _columnIndex[col]._pages[0].RowCount > 1
- || _columnIndex[col]._pages[0].Rows[0].Index > 0) {
- break;
- }
- col--;
- }
- toCol = _columnIndex[col].Index;
- if (toCol == 0) {
- fromRow = fromCol = toRow = toCol = 0;
- return false;
- }
- fromRow = toRow = 0;
-
- for (int c = fromIndex; c < ColumnCount; c++) {
- int first,
- last;
- if (_columnIndex[c].PageCount == 0) {
- continue;
- }
- if (_columnIndex[c]._pages[0].RowCount > 0 && _columnIndex[c]._pages[0].Rows[0].Index > 0) {
- first = _columnIndex[c]._pages[0].IndexOffset + _columnIndex[c]._pages[0].Rows[0].Index;
- } else {
- if (_columnIndex[c]._pages[0].RowCount > 1) {
- first = _columnIndex[c]._pages[0].IndexOffset + _columnIndex[c]._pages[0].Rows[1].Index;
- } else if (_columnIndex[c].PageCount > 1) {
- first = _columnIndex[c]._pages[0].IndexOffset + _columnIndex[c]._pages[1].Rows[0].Index;
- } else {
- first = 0;
- }
- }
- var lp = _columnIndex[c].PageCount - 1;
- while (_columnIndex[c]._pages[lp].RowCount == 0 && lp != 0) {
- lp--;
- }
- var p = _columnIndex[c]._pages[lp];
- if (p.RowCount > 0) {
- last = p.IndexOffset + p.Rows[p.RowCount - 1].Index;
- } else {
- last = first;
- }
- if (first > 0 && (first < fromRow || fromRow == 0)) {
- fromRow = first;
- }
- if (first > 0 && (last > toRow || toRow == 0)) {
- toRow = last;
- }
- }
- if (fromRow <= 0 || toRow <= 0) {
- fromRow = fromCol = toRow = toCol = 0;
- return false;
- }
- return true;
- }
-
- internal int FindNext(int column) {
- var c = GetPosition(column);
- if (c < 0) {
- return ~c;
- }
- return c;
- }
-
- internal T GetValue(int row, int column) {
- int i = GetPointer(row, column);
- if (i >= 0) {
- return _values[i];
- }
- return default(T);
- }
-
- private int GetPointer(int row, int column) {
- var col = GetPosition(column);
- if (col >= 0) {
- var pos = _columnIndex[col].GetPosition(row);
- if (pos >= 0 && pos < _columnIndex[col].PageCount) {
- var pageItem = _columnIndex[col]._pages[pos];
- if (pageItem.MinIndex > row) {
- pos--;
- if (pos < 0) {
- return -1;
- }
- pageItem = _columnIndex[col]._pages[pos];
- }
- short ix = (short)(row - pageItem.IndexOffset);
- _searchIx.Index = ix;
- var cellPos =
- (pageItem.Rows != null
- && ix > 0
- && ix - 1 < pageItem.RowCount
- && ix - 1 < pageItem.Rows.Length
- && pageItem.Rows[ix - 1] != null
- && pageItem.Rows[ix - 1].Index == ix)
- ? ix - 1
- : Array.BinarySearch(pageItem.Rows, 0, pageItem.RowCount, _searchIx);
- if (cellPos >= 0) {
- return pageItem.Rows[cellPos].IndexPointer;
- } //Cell does not exist
- return -1;
- } //Page does not exist
- return -1;
- } //Column does not exist
- return -1;
- }
-
- internal bool Exists(int row, int column) {
- return GetPointer(row, column) >= 0;
- }
-
- internal bool Exists(int row, int column, ref T value) {
- var p = GetPointer(row, column);
- if (p >= 0) {
- value = _values[p];
- return true;
- }
- return false;
- }
-
- internal void SetValue(int row, int column, T value) {
- var col =
- (_columnIndex != null
- && column > 0
- && column - 1 < ColumnCount
- && column - 1 < _columnIndex.Length
- && _columnIndex[column - 1] != null
- && _columnIndex[column - 1].Index == column)
- ? column - 1
- : Array.BinarySearch(
- _columnIndex,
- 0,
- ColumnCount,
- new IndexBase {
- Index = (short)(column),
- });
- var page = (short)(row >> _pageBits);
- if (col >= 0) {
- //var pos = Array.BinarySearch(_columnIndex[col].Pages, 0, _columnIndex[col].Count, new IndexBase() { Index = page });
- var pos = _columnIndex[col].GetPosition(row);
- if (pos < 0) {
- pos = ~pos;
- if (pos - 1 < 0 || _columnIndex[col]._pages[pos - 1].IndexOffset + _pageSize - 1 < row) {
- AddPage(_columnIndex[col], pos, page);
- } else {
- pos--;
- }
- }
- if (pos >= _columnIndex[col].PageCount) {
- AddPage(_columnIndex[col], pos, page);
- }
- var pageItem = _columnIndex[col]._pages[pos];
- if (pageItem.IndexOffset > row) {
- pos--;
- page--;
- if (pos < 0) {
- throw (new("Unexpected error when setting value"));
- }
- pageItem = _columnIndex[col]._pages[pos];
- }
-
- short ix = (short)(row - ((pageItem.Index << _pageBits) + pageItem.Offset));
- _searchIx.Index = ix;
- var cellPos =
- (pageItem.Rows != null
- && ix >= 0
- && ix < pageItem.RowCount
- && ix < pageItem.Rows.Length
- && pageItem.Rows[ix] != null
- && pageItem.Rows[ix].Index == ix)
- ? ix
- : Array.BinarySearch(pageItem.Rows, 0, pageItem.RowCount, _searchIx);
- if (cellPos < 0) {
- cellPos = ~cellPos;
- AddCell(_columnIndex[col], pos, cellPos, ix, value);
- } else {
- _values[pageItem.Rows[cellPos].IndexPointer] = value;
- }
- } else //Column does not exist
- {
- col = ~col;
- AddColumn(col, column);
- AddPage(_columnIndex[col], 0, page);
- short ix = (short)(row - (page << _pageBits));
- AddCell(_columnIndex[col], 0, 0, ix, value);
- }
- }
-
- internal void Insert(int fromRow, int fromCol, int rows, int columns) {
- if (columns > 0) {
- var col = GetPosition(fromCol);
- if (col < 0) {
- col = ~col;
- }
- for (var c = col; c < ColumnCount; c++) {
- _columnIndex[c].Index += (short)columns;
- }
- } else {
- var page = fromRow >> _pageBits;
- for (int c = 0; c < ColumnCount; c++) {
- var column = _columnIndex[c];
- var pagePos = column.GetPosition(fromRow);
- if (pagePos >= 0) {
- if (fromRow >= column._pages[pagePos].MinIndex
- && fromRow
- <= column._pages[pagePos].MaxIndex) //The row is inside the page
- {
- int offset = fromRow - column._pages[pagePos].IndexOffset;
- var rowPos = column._pages[pagePos].GetPosition(offset);
- if (rowPos < 0) {
- rowPos = ~rowPos;
- }
- UpdateIndexOffset(column, pagePos, rowPos, fromRow, rows);
- } else if (column._pages[pagePos].MinIndex > fromRow - 1
- && pagePos
- > 0) //The row is on the page before.
- {
- int offset = fromRow - ((page - 1) << _pageBits);
- var rowPos = column._pages[pagePos - 1].GetPosition(offset);
- if (rowPos > 0 && pagePos > 0) {
- UpdateIndexOffset(column, pagePos - 1, rowPos, fromRow, rows);
- }
- } else if (column.PageCount >= pagePos + 1) {
- int offset = fromRow - column._pages[pagePos].IndexOffset;
- var rowPos = column._pages[pagePos].GetPosition(offset);
- if (rowPos < 0) {
- rowPos = ~rowPos;
- }
- if (column._pages[pagePos].RowCount > rowPos) {
- UpdateIndexOffset(column, pagePos, rowPos, fromRow, rows);
- } else {
- UpdateIndexOffset(column, pagePos + 1, 0, fromRow, rows);
- }
- }
- } else {
- UpdateIndexOffset(column, ~pagePos, 0, fromRow, rows);
- }
- }
- }
- }
-
- internal void Clear(int fromRow, int fromCol, int rows, int columns) {
- Delete(fromRow, fromCol, rows, columns, false);
- }
-
- internal void Delete(int fromRow, int fromCol, int rows, int columns) {
- Delete(fromRow, fromCol, rows, columns, true);
- }
-
- internal void Delete(int fromRow, int fromCol, int rows, int columns, bool shift) {
- if (columns > 0 && fromRow == 1 && rows >= ExcelPackage.MaxRows) {
- DeleteColumns(fromCol, columns, shift);
- } else {
- var toCol = fromCol + columns - 1;
- var pageFromRow = fromRow >> _pageBits;
- for (int c = 0; c < ColumnCount; c++) {
- var column = _columnIndex[c];
- if (column.Index >= fromCol) {
- if (column.Index > toCol) {
- break;
- }
- var pagePos = column.GetPosition(fromRow);
- if (pagePos < 0) {
- pagePos = ~pagePos;
- }
- if (pagePos < column.PageCount) {
- var page = column._pages[pagePos];
- if (shift
- && page.RowCount > 0
- && page.MinIndex > fromRow
- && page.MaxIndex >= fromRow + rows) {
- var o = page.MinIndex - fromRow;
- if (o < rows) {
- rows -= o;
- page.Offset -= o;
- UpdatePageOffset(column, pagePos, o);
- } else {
- page.Offset -= rows;
- UpdatePageOffset(column, pagePos, rows);
- continue;
- }
- }
- if (page.RowCount > 0
- && page.MinIndex <= fromRow + rows - 1
- && page.MaxIndex
- >= fromRow) //The row is inside the page
- {
- var endRow = fromRow + rows;
- var delEndRow = DeleteCells(column._pages[pagePos], fromRow, endRow, shift);
- if (shift && delEndRow != fromRow) {
- UpdatePageOffset(column, pagePos, delEndRow - fromRow);
- }
- if (endRow > delEndRow
- && pagePos < column.PageCount
- && column._pages[pagePos].MinIndex < endRow) {
- pagePos = (delEndRow == fromRow ? pagePos : pagePos + 1);
- var rowsLeft = DeletePage(
- shift ? fromRow : delEndRow,
- endRow - delEndRow,
- column,
- pagePos,
- shift);
- //if (shift) UpdatePageOffset(column, pagePos, endRow - fromRow - rowsLeft);
- if (rowsLeft > 0) {
- var fr = shift ? fromRow : endRow - rowsLeft;
- pagePos = column.GetPosition(fr);
- DeleteCells(column._pages[pagePos], fr, shift ? fr + rowsLeft : endRow, shift);
- if (shift) {
- UpdatePageOffset(column, pagePos, rowsLeft);
- }
- }
- }
- } else if (pagePos > 0
- && column._pages[pagePos].IndexOffset
- > fromRow) //The row is on the page before.
- {
- int offset = fromRow + rows - 1 - ((pageFromRow - 1) << _pageBits);
- var rowPos = column._pages[pagePos - 1].GetPosition(offset);
- if (rowPos > 0 && pagePos > 0) {
- if (shift) {
- UpdateIndexOffset(column, pagePos - 1, rowPos, fromRow + rows - 1, -rows);
- }
- }
- } else {
- if (shift && pagePos + 1 < column.PageCount) {
- UpdateIndexOffset(
- column,
- pagePos + 1,
- 0,
- column._pages[pagePos + 1].MinIndex,
- -rows);
- }
- }
- }
- }
- }
- }
- }
-
- private void UpdatePageOffset(ColumnIndex column, int pagePos, int rows) {
- //Update Pageoffset
-
- if (++pagePos < column.PageCount) {
- for (int p = pagePos; p < column.PageCount; p++) {
- if (column._pages[p].Offset - rows <= -_pageSize) {
- column._pages[p].Index--;
- column._pages[p].Offset -= rows - _pageSize;
- } else {
- column._pages[p].Offset -= rows;
- }
- }
-
- if (Math.Abs(column._pages[pagePos].Offset) > _pageSize
- || Math.Abs(column._pages[pagePos].Rows[column._pages[pagePos].RowCount - 1].Index)
- > _pageSizeMax) //Split or Merge???
- {
- ResetPageOffset(column, pagePos, rows);
- }
- }
- }
-
- private void ResetPageOffset(ColumnIndex column, int pagePos, int rows) {
- PageIndex fromPage = column._pages[pagePos];
- PageIndex toPage;
- short pageAdd = 0;
- if (fromPage.Offset < -_pageSize) {
- toPage = column._pages[pagePos - 1];
- pageAdd = -1;
- if (fromPage.Index - 1 == toPage.Index) {
- if (fromPage.IndexOffset
- + fromPage.Rows[fromPage.RowCount - 1].Index
- - toPage.IndexOffset
- + toPage.Rows[0].Index
- <= _pageSizeMax) {
- MergePage(column, pagePos - 1);
- }
- } else //No page after
- {
- fromPage.Index -= pageAdd;
- fromPage.Offset += _pageSize;
- }
- } else if (fromPage.Offset > _pageSize) {
- toPage = column._pages[pagePos + 1];
- pageAdd = 1;
- if (fromPage.Index + 1 == toPage.Index) {} else {
- fromPage.Index += pageAdd;
- fromPage.Offset += _pageSize;
- }
- }
- }
-
- private int DeletePage(int fromRow, int rows, ColumnIndex column, int pagePos, bool shift) {
- PageIndex page = column._pages[pagePos];
- var startRows = rows;
- while (page != null
- && page.MinIndex >= fromRow
- && ((shift && page.MaxIndex < fromRow + rows)
- || (!shift && page.MaxIndex < fromRow + startRows))) {
- //Delete entire page.
- var delSize = page.MaxIndex - page.MinIndex + 1;
- rows -= delSize;
- var prevOffset = page.Offset;
- Array.Copy(
- column._pages,
- pagePos + 1,
- column._pages,
- pagePos,
- column.PageCount - pagePos + 1);
- column.PageCount--;
- if (column.PageCount == 0) {
- return 0;
- }
- if (shift) {
- for (int i = pagePos; i < column.PageCount; i++) {
- column._pages[i].Offset -= delSize;
- if (column._pages[i].Offset <= -_pageSize) {
- column._pages[i].Index--;
- column._pages[i].Offset += _pageSize;
- }
- }
- }
- if (column.PageCount > pagePos) {
- page = column._pages[pagePos];
- //page.Offset = pagePos == 0 ? 1 : prevOffset; //First page can only reference to rows starting from Index == 1
- } else {
- //No more pages, return 0
- return 0;
- }
- }
- return rows;
- }
-
- private int DeleteCells(PageIndex page, int fromRow, int toRow, bool shift) {
- var fromPos = page.GetPosition(fromRow - (page.IndexOffset));
- if (fromPos < 0) {
- fromPos = ~fromPos;
- }
- var maxRow = page.MaxIndex;
- var offset = toRow - page.IndexOffset;
- if (offset > _pageSizeMax) {
- offset = _pageSizeMax;
- }
- var toPos = page.GetPosition(offset);
- if (toPos < 0) {
- toPos = ~toPos;
- }
-
- if (fromPos <= toPos && fromPos < page.RowCount && page.GetIndex(fromPos) < toRow) {
- if (toRow > page.MaxIndex) {
- if (fromRow
- == page.MinIndex) //Delete entire page, late in the page delete method
- {
- return fromRow;
- }
- var r = page.MaxIndex;
- var deletedRow = page.RowCount - fromPos;
- page.RowCount -= deletedRow;
- return r + 1;
- }
- var rows = toRow - fromRow;
- if (shift) {
- UpdateRowIndex(page, toPos, rows);
- }
- Array.Copy(page.Rows, toPos, page.Rows, fromPos, page.RowCount - toPos);
- page.RowCount -= toPos - fromPos;
-
- return toRow;
- }
- if (shift) {
- UpdateRowIndex(page, toPos, toRow - fromRow);
- }
- return toRow < maxRow ? toRow : maxRow;
- }
-
- private static void UpdateRowIndex(PageIndex page, int toPos, int rows) {
- for (int r = toPos; r < page.RowCount; r++) {
- page.Rows[r].Index -= (short)rows;
- }
- }
-
- private void DeleteColumns(int fromCol, int columns, bool shift) {
- var fPos = GetPosition(fromCol);
- if (fPos < 0) {
- fPos = ~fPos;
- }
- int tPos = fPos;
- for (var c = fPos; c <= ColumnCount; c++) {
- tPos = c;
- if (tPos == ColumnCount || _columnIndex[c].Index >= fromCol + columns) {
- break;
- }
- }
-
- if (ColumnCount <= fPos) {
- return;
- }
-
- if (_columnIndex[fPos].Index >= fromCol && _columnIndex[fPos].Index <= fromCol + columns) {
- if (tPos < ColumnCount) {
- Array.Copy(_columnIndex, tPos, _columnIndex, fPos, ColumnCount - tPos);
- }
- ColumnCount -= (tPos - fPos);
- }
- if (shift) {
- for (var c = fPos; c < ColumnCount; c++) {
- _columnIndex[c].Index -= (short)columns;
- }
- }
- }
-
- private void UpdateIndexOffset(ColumnIndex column, int pagePos, int rowPos, int row, int rows) {
- if (pagePos >= column.PageCount) {
- return; //A page after last cell.
- }
- var page = column._pages[pagePos];
- if (rows > _pageSize) {
- short addPages = (short)(rows >> _pageBits);
- int offset = +(rows - (_pageSize * addPages));
- for (int p = pagePos + 1; p < column.PageCount; p++) {
- if (column._pages[p].Offset + offset > _pageSize) {
- column._pages[p].Index += (short)(addPages + 1);
- column._pages[p].Offset += offset - _pageSize;
- } else {
- column._pages[p].Index += addPages;
- column._pages[p].Offset += offset;
- }
- }
-
- var size = page.RowCount - rowPos;
- if (page.RowCount > rowPos) {
- if (column.PageCount - 1
- == pagePos) //No page after, create a new one.
- {
- //Copy rows to next page.
- var newPage = CopyNew(page, rowPos, size);
- newPage.Index = (short)((row + rows) >> _pageBits);
- newPage.Offset = row + rows - (newPage.Index * _pageSize) - newPage.Rows[0].Index;
- if (newPage.Offset > _pageSize) {
- newPage.Index++;
- newPage.Offset -= _pageSize;
- }
- AddPage(column, pagePos + 1, newPage);
- page.RowCount = rowPos;
- } else {
- if (column._pages[pagePos + 1].RowCount + size
- > _pageSizeMax) //Split Page
- {
- SplitPageInsert(column, pagePos, rowPos, rows, size, addPages);
- } else //Copy Page.
- {
- CopyMergePage(page, rowPos, rows, size, column._pages[pagePos + 1]);
- }
- }
- }
- } else {
- //Add to Pages.
- for (int r = rowPos; r < page.RowCount; r++) {
- page.Rows[r].Index += (short)rows;
- }
- if (page.Offset + page.Rows[page.RowCount - 1].Index
- >= _pageSizeMax) //Can not be larger than the max size of the page.
- {
- AdjustIndex(column, pagePos);
- if (page.Offset + page.Rows[page.RowCount - 1].Index >= _pageSizeMax) {
- pagePos = SplitPage(column, pagePos);
- }
- //IndexItem[] newRows = new IndexItem[GetSize(page.RowCount - page.Rows[r].Index)];
- //var newPage = new PageIndex(newRows, r);
- //newPage.Index = (short)(pagePos + 1);
- //TODO: MoveRows to next page.
- }
-
- for (int p = pagePos + 1; p < column.PageCount; p++) {
- if (column._pages[p].Offset + rows < _pageSize) {
- column._pages[p].Offset += rows;
- } else {
- column._pages[p].Index++;
- column._pages[p].Offset = (column._pages[p].Offset + rows) % _pageSize;
- }
- }
- }
- }
-
- private void SplitPageInsert(
- ColumnIndex column,
- int pagePos,
- int rowPos,
- int rows,
- int size,
- int addPages) {
- var newRows = new IndexItem[GetSize(size)];
- var page = column._pages[pagePos];
-
- var rStart = -1;
- for (int r = rowPos; r < page.RowCount; r++) {
- if (page.IndexExpanded - (page.Rows[r].Index + rows) > _pageSize) {
- rStart = r;
- break;
- }
- page.Rows[r].Index += (short)rows;
- }
- var rc = page.RowCount - rStart;
- page.RowCount = rStart;
- if (rc > 0) {
- //Copy to a new page
- var row = page.IndexOffset;
- var newPage = CopyNew(page, rStart, rc);
- var ix = (short)(page.Index + addPages);
- var offset = page.IndexOffset + rows - (ix * _pageSize);
- if (offset > _pageSize) {
- ix += (short)(offset / _pageSize);
- offset %= _pageSize;
- }
- newPage.Index = ix;
- newPage.Offset = offset;
- AddPage(column, pagePos + 1, newPage);
- }
-
- //Copy from next Row
- }
-
- private void CopyMergePage(PageIndex page, int rowPos, int rows, int size, PageIndex toPage) {
- var startRow = page.IndexOffset + page.Rows[rowPos].Index + rows;
- var newRows = new IndexItem[GetSize(toPage.RowCount + size)];
- page.RowCount -= size;
- Array.Copy(page.Rows, rowPos, newRows, 0, size);
- for (int r = 0; r < size; r++) {
- newRows[r].Index += (short)(page.IndexOffset + rows - toPage.IndexOffset);
- }
-
- Array.Copy(toPage.Rows, 0, newRows, size, toPage.RowCount);
- toPage.Rows = newRows;
- toPage.RowCount += size;
- }
-
- private void MergePage(ColumnIndex column, int pagePos) {
- PageIndex page1 = column._pages[pagePos];
- PageIndex page2 = column._pages[pagePos + 1];
-
- var newPage = new PageIndex(page1, 0, page1.RowCount + page2.RowCount);
- newPage.RowCount = page1.RowCount + page2.RowCount;
- Array.Copy(page1.Rows, 0, newPage.Rows, 0, page1.RowCount);
- Array.Copy(page2.Rows, 0, newPage.Rows, page1.RowCount, page2.RowCount);
- for (int r = page1.RowCount; r < newPage.RowCount; r++) {
- newPage.Rows[r].Index += (short)(page2.IndexOffset - page1.IndexOffset);
- }
-
- column._pages[pagePos] = newPage;
- column.PageCount--;
-
- if (column.PageCount > (pagePos + 1)) {
- Array.Copy(
- column._pages,
- pagePos + 2,
- column._pages,
- pagePos + 1,
- column.PageCount - (pagePos + 1));
- for (int p = pagePos + 1; p < column.PageCount; p++) {
- column._pages[p].Index--;
- column._pages[p].Offset += _pageSize;
- }
- }
- }
-
- private PageIndex CopyNew(PageIndex pageFrom, int rowPos, int size) {
- IndexItem[] newRows = new IndexItem[GetSize(size)];
- Array.Copy(pageFrom.Rows, rowPos, newRows, 0, size);
- return new(newRows, size);
- }
-
- internal static int GetSize(int size) {
- var newSize = 256;
- while (newSize < size) {
- newSize <<= 1;
- }
- return newSize;
- }
-
- private void AddCell(ColumnIndex columnIndex, int pagePos, int pos, short ix, T value) {
- PageIndex pageItem = columnIndex._pages[pagePos];
- if (pageItem.RowCount == pageItem.Rows.Length) {
- if (pageItem.RowCount
- == _pageSizeMax) //Max size-->Split
- {
- pagePos = SplitPage(columnIndex, pagePos);
- if (columnIndex._pages[pagePos - 1].RowCount > pos) {
- pagePos--;
- } else {
- pos -= columnIndex._pages[pagePos - 1].RowCount;
- }
- pageItem = columnIndex._pages[pagePos];
- } else //Expand to double size.
- {
- var rowsTmp = new IndexItem[pageItem.Rows.Length << 1];
- Array.Copy(pageItem.Rows, 0, rowsTmp, 0, pageItem.RowCount);
- pageItem.Rows = rowsTmp;
- }
- }
- if (pos < pageItem.RowCount) {
- Array.Copy(pageItem.Rows, pos, pageItem.Rows, pos + 1, pageItem.RowCount - pos);
- }
- pageItem.Rows[pos] = new() {
- Index = ix,
- IndexPointer = _values.Count,
- };
- _values.Add(value);
- pageItem.RowCount++;
- }
-
- private int SplitPage(ColumnIndex columnIndex, int pagePos) {
- var page = columnIndex._pages[pagePos];
- if (page.Offset != 0) {
- var offset = page.Offset;
- page.Offset = 0;
- for (int r = 0; r < page.RowCount; r++) {
- page.Rows[r].Index -= (short)offset;
- }
- }
- //Find Split pos
- int splitPos = 0;
- for (int r = 0; r < page.RowCount; r++) {
- if (page.Rows[r].Index > _pageSize) {
- splitPos = r;
- break;
- }
- }
- var newPage = new PageIndex(page, 0, splitPos);
- var nextPage = new PageIndex(
- page,
- splitPos,
- page.RowCount - splitPos,
- (short)(page.Index + 1),
- page.Offset);
-
- for (int r = 0; r < nextPage.RowCount; r++) {
- nextPage.Rows[r].Index = (short)(nextPage.Rows[r].Index - _pageSize);
- }
-
- columnIndex._pages[pagePos] = newPage;
- if (columnIndex.PageCount + 1 > columnIndex._pages.Length) {
- var pageTmp = new PageIndex[columnIndex._pages.Length << 1];
- Array.Copy(columnIndex._pages, 0, pageTmp, 0, columnIndex.PageCount);
- columnIndex._pages = pageTmp;
- }
- Array.Copy(
- columnIndex._pages,
- pagePos + 1,
- columnIndex._pages,
- pagePos + 2,
- columnIndex.PageCount - pagePos - 1);
- columnIndex._pages[pagePos + 1] = nextPage;
- page = nextPage;
- //pos -= PageSize;
- columnIndex.PageCount++;
- return pagePos + 1;
- }
-
- private PageIndex AdjustIndex(ColumnIndex columnIndex, int pagePos) {
- PageIndex page = columnIndex._pages[pagePos];
- //First Adjust indexes
- if (page.Offset + page.Rows[0].Index >= _pageSize
- || page.Offset >= _pageSize
- || page.Rows[0].Index >= _pageSize) {
- page.Index++;
- page.Offset -= _pageSize;
- } else if (page.Offset + page.Rows[0].Index <= -_pageSize
- || page.Offset <= -_pageSize
- || page.Rows[0].Index <= -_pageSize) {
- page.Index--;
- page.Offset += _pageSize;
- }
- return page;
- }
-
- private void AddPage(ColumnIndex column, int pos, short index) {
- AddPage(column, pos);
- column._pages[pos] = new() {
- Index = index,
- };
- if (pos > 0) {
- var pp = column._pages[pos - 1];
- if (pp.RowCount > 0 && pp.Rows[pp.RowCount - 1].Index > _pageSize) {
- column._pages[pos].Offset = pp.Rows[pp.RowCount - 1].Index - _pageSize;
- }
- }
- }
-
- /// <summary>
- /// Add a new page to the collection
- /// </summary>
- /// <param name="column">The column</param>
- /// <param name="pos">Position</param>
- /// <param name="page">The new page object to add</param>
- private void AddPage(ColumnIndex column, int pos, PageIndex page) {
- AddPage(column, pos);
- column._pages[pos] = page;
- }
-
- /// <summary>
- /// Add a new page to the collection
- /// </summary>
- /// <param name="column">The column</param>
- /// <param name="pos">Position</param>
- private void AddPage(ColumnIndex column, int pos) {
- if (column.PageCount == column._pages.Length) {
- var pageTmp = new PageIndex[column._pages.Length * 2];
- Array.Copy(column._pages, 0, pageTmp, 0, column.PageCount);
- column._pages = pageTmp;
- }
- if (pos < column.PageCount) {
- Array.Copy(column._pages, pos, column._pages, pos + 1, column.PageCount - pos);
- }
- column.PageCount++;
- }
-
- private void AddColumn(int pos, int column) {
- if (ColumnCount == _columnIndex.Length) {
- var colTmp = new ColumnIndex[_columnIndex.Length * 2];
- Array.Copy(_columnIndex, 0, colTmp, 0, ColumnCount);
- _columnIndex = colTmp;
- }
- if (pos < ColumnCount) {
- Array.Copy(_columnIndex, pos, _columnIndex, pos + 1, ColumnCount - pos);
- }
- _columnIndex[pos] = new() {
- Index = (short)(column),
- };
- ColumnCount++;
- }
-
- internal bool NextCell(ref int row, ref int col) {
- return NextCell(ref row, ref col, 0, 0, ExcelPackage.MaxRows, ExcelPackage.MaxColumns);
- }
-
- internal bool NextCell(
- ref int row,
- ref int col,
- int minRow,
- int minColPos,
- int maxRow,
- int maxColPos) {
- if (minColPos >= ColumnCount) {
- return false;
- }
- if (maxColPos >= ColumnCount) {
- maxColPos = ColumnCount - 1;
- }
- var c = GetPosition(col);
- if (c >= 0) {
- if (c > maxColPos) {
- if (col <= minColPos) {
- return false;
- }
- col = minColPos;
- return NextCell(ref row, ref col);
- }
- var r = GetNextCell(ref row, ref c, minColPos, maxRow, maxColPos);
- col = _columnIndex[c].Index;
- return r;
- }
- c = ~c;
- if (c > _columnIndex[c].Index) {
- if (col <= minColPos) {
- return false;
- }
- col = minColPos;
- return NextCell(ref row, ref col, minRow, minColPos, maxRow, maxColPos);
- }
- {
- var r = GetNextCell(ref c, ref row, minColPos, maxRow, maxColPos);
- col = _columnIndex[c].Index;
- return r;
- }
- }
-
- internal bool GetNextCell(
- ref int row,
- ref int colPos,
- int startColPos,
- int endRow,
- int endColPos) {
- if (ColumnCount == 0) {
- return false;
- }
- if (++colPos < ColumnCount && colPos <= endColPos) {
- var r = _columnIndex[colPos].GetNextRow(row);
- if (r
- == row) //Exists next Row
- {
- return true;
- }
- int minRow,
- minCol;
- if (r > row) {
- minRow = r;
- minCol = colPos;
- } else {
- minRow = int.MaxValue;
- minCol = 0;
- }
-
- var c = colPos + 1;
- while (c < ColumnCount && c <= endColPos) {
- r = _columnIndex[c].GetNextRow(row);
- if (r
- == row) //Exists next Row
- {
- colPos = c;
- return true;
- }
- if (r > row && r < minRow) {
- minRow = r;
- minCol = c;
- }
- c++;
- }
- c = startColPos;
- if (row < endRow) {
- row++;
- while (c < colPos) {
- r = _columnIndex[c].GetNextRow(row);
- if (r
- == row) //Exists next Row
- {
- colPos = c;
- return true;
- }
- if (r > row && (r < minRow || (r == minRow && c < minCol)) && r <= endRow) {
- minRow = r;
- minCol = c;
- }
- c++;
- }
- }
-
- if (minRow == int.MaxValue || minRow > endRow) {
- return false;
- }
- row = minRow;
- colPos = minCol;
- return true;
- }
- if (colPos <= startColPos || row >= endRow) {
- return false;
- }
- colPos = startColPos - 1;
- row++;
- return GetNextCell(ref row, ref colPos, startColPos, endRow, endColPos);
- }
-
- internal bool PrevCell(ref int row, ref int col) {
- return PrevCell(ref row, ref col, 0, 0, ExcelPackage.MaxRows, ExcelPackage.MaxColumns);
- }
-
- private bool PrevCell(
- ref int row,
- ref int col,
- int minRow,
- int minColPos,
- int maxRow,
- int maxColPos) {
- if (minColPos >= ColumnCount) {
- return false;
- }
- if (maxColPos >= ColumnCount) {
- maxColPos = ColumnCount - 1;
- }
- var c = GetPosition(col);
- if (c >= 0) {
- if (c == 0) {
- if (col >= maxColPos) {
- return false;
- }
- if (row == minRow) {
- return false;
- }
- row--;
- col = maxColPos;
- return PrevCell(ref row, ref col, minRow, minColPos, maxRow, maxColPos);
- }
- var ret = GetPrevCell(ref row, ref c, minRow, minColPos, maxColPos);
- if (ret) {
- col = _columnIndex[c].Index;
- }
- return ret;
- }
- c = ~c;
- if (c == 0) {
- if (col >= maxColPos || row <= 0) {
- return false;
- }
- col = maxColPos;
- row--;
- return PrevCell(ref row, ref col, minRow, minColPos, maxRow, maxColPos);
- }
- {
- var ret = GetPrevCell(ref row, ref c, minRow, minColPos, maxColPos);
- if (ret) {
- col = _columnIndex[c].Index;
- }
- return ret;
- }
- }
-
- internal bool GetPrevCell(
- ref int row,
- ref int colPos,
- int startRow,
- int startColPos,
- int endColPos) {
- if (ColumnCount == 0) {
- return false;
- }
- if (--colPos >= startColPos)
- // if (++colPos < ColumnCount && colPos <= endColPos)
- {
- var r = _columnIndex[colPos].GetNextRow(row);
- if (r
- == row) //Exists next Row
- {
- return true;
- }
- int minRow,
- minCol;
- if (r > row && r >= startRow) {
- minRow = r;
- minCol = colPos;
- } else {
- minRow = int.MaxValue;
- minCol = 0;
- }
-
- var c = colPos - 1;
- if (c >= startColPos) {
- while (c >= startColPos) {
- r = _columnIndex[c].GetNextRow(row);
- if (r
- == row) //Exists next Row
- {
- colPos = c;
- return true;
- }
- if (r > row && r < minRow && r >= startRow) {
- minRow = r;
- minCol = c;
- }
- c--;
- }
- }
- if (row > startRow) {
- c = endColPos;
- row--;
- while (c > colPos) {
- r = _columnIndex[c].GetNextRow(row);
- if (r
- == row) //Exists next Row
- {
- colPos = c;
- return true;
- }
- if (r > row && r < minRow && r >= startRow) {
- minRow = r;
- minCol = c;
- }
- c--;
- }
- }
- if (minRow == int.MaxValue || startRow < minRow) {
- return false;
- }
- row = minRow;
- colPos = minCol;
- return true;
- }
- colPos = ColumnCount;
- row--;
- if (row < startRow) {
- return false;
- }
- return GetPrevCell(ref colPos, ref row, startRow, startColPos, endColPos);
- }
-}
-
-internal class CellsStoreEnumerator<T> : IEnumerable<T>, IEnumerator<T> {
- private readonly CellStore<T> _cellStore;
- private int row,
- colPos;
- private int[] pagePos,
- cellPos;
- private readonly int _startRow;
- private readonly int _startCol;
- private readonly int _endRow;
- private readonly int _endCol;
- private int minRow,
- minColPos,
- maxRow,
- maxColPos;
-
- public CellsStoreEnumerator(CellStore<T> cellStore)
- : this(cellStore, 0, 0, ExcelPackage.MaxRows, ExcelPackage.MaxColumns) {}
-
- public CellsStoreEnumerator(
- CellStore<T> cellStore,
- int startRow,
- int startCol,
- int endRow,
- int endCol) {
- _cellStore = cellStore;
-
- _startRow = startRow;
- _startCol = startCol;
- _endRow = endRow;
- _endCol = endCol;
-
- Init();
- }
-
- internal void Init() {
- minRow = _startRow;
- maxRow = _endRow;
-
- minColPos = _cellStore.GetPosition(_startCol);
- if (minColPos < 0) {
- minColPos = ~minColPos;
- }
- maxColPos = _cellStore.GetPosition(_endCol);
- if (maxColPos < 0) {
- maxColPos = ~maxColPos - 1;
- }
- row = minRow;
- colPos = minColPos - 1;
-
- var cols = maxColPos - minColPos + 1;
- pagePos = new int[cols];
- cellPos = new int[cols];
- for (int i = 0; i < cols; i++) {
- pagePos[i] = -1;
- cellPos[i] = -1;
- }
- }
-
- internal int Row => row;
-
- internal int Column {
- get {
- if (colPos == -1) {
- MoveNext();
- }
- if (colPos == -1) {
- return 0;
- }
- return _cellStore._columnIndex[colPos].Index;
- }
- }
-
- internal T Value {
- get => _cellStore.GetValue(row, Column);
- set => _cellStore.SetValue(row, Column, value);
- }
-
- internal bool Next() {
- return _cellStore.GetNextCell(ref row, ref colPos, minColPos, maxRow, maxColPos);
- }
-
- public string CellAddress => ExcelCellBase.GetAddress(Row, Column);
-
- public IEnumerator<T> GetEnumerator() {
- Reset();
- return this;
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- Reset();
- return this;
- }
-
- public T Current => Value;
-
- public void Dispose() {}
-
- object IEnumerator.Current {
- get {
- Reset();
- return this;
- }
- }
-
- public bool MoveNext() {
- return Next();
- }
-
- public void Reset() {
- Init();
- }
-}
-
-internal class FlagCellStore : CellStore<byte> {
- internal void SetFlagValue(int row, int col, bool value, CellFlags cellFlags) {
- CellFlags currentValue = (CellFlags)GetValue(row, col);
- if (value) {
- SetValue(row, col, (byte)(currentValue | cellFlags)); // add the CellFlag bit
- } else {
- SetValue(row, col, (byte)(currentValue & ~cellFlags)); // remove the CellFlag bit
- }
- }
-
- internal bool GetFlagValue(int row, int col, CellFlags cellFlags) {
- return !(((byte)cellFlags & GetValue(row, col)) == 0);
- }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingAverageGroup.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingAverageGroup.cs
deleted file mode 100644
index 77efc3f..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingAverageGroup.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingAverageGroup
-/// </summary>
-public interface IExcelConditionalFormattingAverageGroup : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBeginsWith.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBeginsWith.cs
deleted file mode 100644
index 8bc7c8f..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBeginsWith.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingBeginsWith
-/// </summary>
-public interface IExcelConditionalFormattingBeginsWith
- : IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithText {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBetween.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBetween.cs
deleted file mode 100644
index 6d56a9e..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBetween.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingBetween
-/// </summary>
-public interface IExcelConditionalFormattingBetween
- : IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula2 {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingColorScaleGroup.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingColorScaleGroup.cs
deleted file mode 100644
index 8f33fc0..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingColorScaleGroup.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingColorScaleGroup
-/// </summary>
-public interface IExcelConditionalFormattingColorScaleGroup : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsBlanks.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsBlanks.cs
deleted file mode 100644
index 4d05109..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsBlanks.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingContainsBlanks
-/// </summary>
-public interface IExcelConditionalFormattingContainsBlanks : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsErrors.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsErrors.cs
deleted file mode 100644
index a668e11..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsErrors.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingContainsErrors
-/// </summary>
-public interface IExcelConditionalFormattingContainsErrors : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsText.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsText.cs
deleted file mode 100644
index 5919f90..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsText.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingContainsText
-/// </summary>
-public interface IExcelConditionalFormattingContainsText
- : IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithText {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDataBarGroup.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDataBarGroup.cs
deleted file mode 100644
index 91abb7d..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDataBarGroup.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingDataBar
-/// </summary>
-public interface IExcelConditionalFormattingDataBarGroup : IExcelConditionalFormattingRule {
- /// <summary>
- /// ShowValue
- /// </summary>
- bool ShowValue { get; set; }
-
- /// <summary>
- /// Databar Low Value
- /// </summary>
- ExcelConditionalFormattingIconDataBarValue LowValue { get; }
-
- /// <summary>
- /// Databar High Value
- /// </summary>
- ExcelConditionalFormattingIconDataBarValue HighValue { get; }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDuplicateValues.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDuplicateValues.cs
deleted file mode 100644
index 32427f9..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDuplicateValues.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingDuplicateValues
-/// </summary>
-public interface IExcelConditionalFormattingDuplicateValues : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEndsWith.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEndsWith.cs
deleted file mode 100644
index d45c296..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEndsWith.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingEndsWith
-/// </summary>
-public interface IExcelConditionalFormattingEndsWith
- : IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithText {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEqual.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEqual.cs
deleted file mode 100644
index 91c9663..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEqual.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingEqual
-/// </summary>
-public interface IExcelConditionalFormattingEqual
- : IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingExpression.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingExpression.cs
deleted file mode 100644
index aa23a69..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingExpression.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingExpression
-/// </summary>
-public interface IExcelConditionalFormattingExpression
- : IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFiveIconSet.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFiveIconSet.cs
deleted file mode 100644
index 2954b3e..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFiveIconSet.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingFiveIconSet
-/// </summary>eExcelconditionalFormatting4IconsSetType
-public interface IExcelConditionalFormattingFiveIconSet
- : IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting5IconsSetType> {
- /// <summary>
- /// Icon5 (part of the 5 Icon Set)
- /// </summary>
- ExcelConditionalFormattingIconDataBarValue Icon5 { get; }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFourIconSet.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFourIconSet.cs
deleted file mode 100644
index 67da2ba..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFourIconSet.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingFourIconSet
-/// </summary>
-public interface IExcelConditionalFormattingFourIconSet<T>
- : IExcelConditionalFormattingThreeIconSet<T> {
- /// <summary>
- /// Icon4 (part of the 4 ou 5 Icon Set)
- /// </summary>
- ExcelConditionalFormattingIconDataBarValue Icon4 { get; }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThan.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThan.cs
deleted file mode 100644
index 9287f3f..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThan.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingGreaterThan
-/// </summary>
-public interface IExcelConditionalFormattingGreaterThan
- : IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThanOrEqual.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThanOrEqual.cs
deleted file mode 100644
index aa084cc..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThanOrEqual.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingGreaterThanOrEqual
-/// </summary>
-public interface IExcelConditionalFormattingGreaterThanOrEqual
- : IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingIconSetGroup.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingIconSetGroup.cs
deleted file mode 100644
index 770d75b..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingIconSetGroup.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingIconSetGroup
-/// </summary>
-public interface IExcelConditionalFormattingIconSetGroup<T> : IExcelConditionalFormattingRule {
- /// <summary>
- /// Reverse
- /// </summary>
- bool Reverse { get; set; }
-
- /// <summary>
- /// ShowValue
- /// </summary>
- bool ShowValue { get; set; }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThan.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThan.cs
deleted file mode 100644
index 162a16c..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThan.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingLessThan
-/// </summary>
-public interface IExcelConditionalFormattingLessThan
- : IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThanOrEqual.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThanOrEqual.cs
deleted file mode 100644
index fce6064..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThanOrEqual.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingGreaterThanOrEqual
-/// </summary>
-public interface IExcelConditionalFormattingLessThanOrEqual
- : IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotBetween.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotBetween.cs
deleted file mode 100644
index a017b81..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotBetween.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingNotBetween
-/// </summary>
-public interface IExcelConditionalFormattingNotBetween
- : IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula2 {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsBlanks.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsBlanks.cs
deleted file mode 100644
index 4743b3b..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsBlanks.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingNotContainsBlanks
-/// </summary>
-public interface IExcelConditionalFormattingNotContainsBlanks : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsErrors.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsErrors.cs
deleted file mode 100644
index aa42a1c..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsErrors.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingNotContainsErrors
-/// </summary>
-public interface IExcelConditionalFormattingNotContainsErrors : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsText.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsText.cs
deleted file mode 100644
index 5a427f4..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsText.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingNotContainsText
-/// </summary>
-public interface IExcelConditionalFormattingNotContainsText
- : IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithText {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotEqual.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotEqual.cs
deleted file mode 100644
index f20f33a..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotEqual.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingNotEqual
-/// </summary>
-public interface IExcelConditionalFormattingNotEqual
- : IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingRule.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingRule.cs
deleted file mode 100644
index e88b5af..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingRule.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.Style.Dxf;
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// Interface for conditional formatting rule
-/// </summary>
-public interface IExcelConditionalFormattingRule {
- /// <summary>
- /// The 'cfRule' XML node
- /// </summary>
- XmlNode Node { get; }
-
- /// <summary>
- /// Type of conditional formatting rule. ST_CfType §18.18.12.
- /// </summary>
- eExcelConditionalFormattingRuleType Type { get; }
-
- /// <summary>
- /// <para>Range over which these conditional formatting rules apply.</para>
- /// <para>The possible values for this attribute are defined by the
- /// ST_Sqref simple type (§18.18.76).</para>
- /// </summary>
- ExcelAddress Address { get; set; }
-
- /// <summary>
- /// The priority of this conditional formatting rule. This value is used to determine
- /// which format should be evaluated and rendered. Lower numeric values are higher
- /// priority than higher numeric values, where 1 is the highest priority.
- /// </summary>
- int Priority { get; set; }
-
- /// <summary>
- /// If this flag is 1, no rules with lower priority shall be applied over this rule,
- /// when this rule evaluates to true.
- /// </summary>
- bool StopIfTrue { get; set; }
-
- ///// <summary>
- ///// <para>This is an index to a dxf element in the Styles Part indicating which cell
- ///// formatting to apply when the conditional formatting rule criteria is met.</para>
- ///// <para>The possible values for this attribute are defined by the ST_DxfId simple type
- ///// (§18.18.25).</para>
- ///// </summary>
- // int DxfId { get; set; }
- /// <summary>
- /// Gives access to the differencial styling (DXF) for the rule.
- /// </summary>
- ExcelDxfStyleConditionalFormatting Style { get; }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingStdDevGroup.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingStdDevGroup.cs
deleted file mode 100644
index 1aca982..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingStdDevGroup.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingStdDevGroup
-/// </summary>
-public interface IExcelConditionalFormattingStdDevGroup
- : IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithStdDev {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeColorScale.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeColorScale.cs
deleted file mode 100644
index eca66d1..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeColorScale.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingThreeColorScale
-/// </summary>
-public interface IExcelConditionalFormattingThreeColorScale
- : IExcelConditionalFormattingTwoColorScale {
- /// <summary>
- /// Three Color Scale Middle Value
- /// </summary>
- ExcelConditionalFormattingColorScaleValue MiddleValue { get; set; }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeIconSet.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeIconSet.cs
deleted file mode 100644
index 0fdc397..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeIconSet.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingThreeIconSet
-/// </summary>
-public interface IExcelConditionalFormattingThreeIconSet<T>
- : IExcelConditionalFormattingIconSetGroup<T> {
- /// <summary>
- /// Icon1 (part of the 3, 4 ou 5 Icon Set)
- /// </summary>
- ExcelConditionalFormattingIconDataBarValue Icon1 { get; }
-
- /// <summary>
- /// Icon2 (part of the 3, 4 ou 5 Icon Set)
- /// </summary>
- ExcelConditionalFormattingIconDataBarValue Icon2 { get; }
-
- /// <summary>
- /// Icon3 (part of the 3, 4 ou 5 Icon Set)
- /// </summary>
- ExcelConditionalFormattingIconDataBarValue Icon3 { get; }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTimePeriodGroup.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTimePeriodGroup.cs
deleted file mode 100644
index 266c1b8..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTimePeriodGroup.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingTimePeriod
-/// </summary>
-public interface IExcelConditionalFormattingTimePeriodGroup : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTopBottomGroup.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTopBottomGroup.cs
deleted file mode 100644
index 234d925..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTopBottomGroup.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingTopBottomGroup
-/// </summary>
-public interface IExcelConditionalFormattingTopBottomGroup
- : IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithRank {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTwoColorScale.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTwoColorScale.cs
deleted file mode 100644
index 2662b9a..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTwoColorScale.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingTwoColorScale
-/// </summary>
-public interface IExcelConditionalFormattingTwoColorScale
- : IExcelConditionalFormattingColorScaleGroup {
- /// <summary>
- /// Two Color Scale Low Value
- /// </summary>
- ExcelConditionalFormattingColorScaleValue LowValue { get; set; }
-
- /// <summary>
- /// Two Color Scale High Value
- /// </summary>
- ExcelConditionalFormattingColorScaleValue HighValue { get; set; }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingUniqueValues.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingUniqueValues.cs
deleted file mode 100644
index ee55553..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingUniqueValues.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingUniqueValues
-/// </summary>
-public interface IExcelConditionalFormattingUniqueValues : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula.cs
deleted file mode 100644
index d612008..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingWithFormula
-/// </summary>
-public interface IExcelConditionalFormattingWithFormula {
- /// <summary>
- /// Formula Attribute
- /// </summary>
- string Formula { get; set; }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula2.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula2.cs
deleted file mode 100644
index b7a940a..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula2.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingWithFormula2
-/// </summary>
-public interface IExcelConditionalFormattingWithFormula2 : IExcelConditionalFormattingWithFormula {
- /// <summary>
- /// Formula2 Attribute
- /// </summary>
- string Formula2 { get; set; }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithRank.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithRank.cs
deleted file mode 100644
index de220ed..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithRank.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingWithRank
-/// </summary>
-public interface IExcelConditionalFormattingWithRank {
- /// <summary>
- /// Rank Attribute
- /// </summary>
- UInt16 Rank { get; set; }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithReverse.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithReverse.cs
deleted file mode 100644
index 405a8a5..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithReverse.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingWithReverse
-/// </summary>
-public interface IExcelConditionalFormattingWithReverse {
- /// <summary>
- /// Reverse Attribute
- /// </summary>
- bool Reverse { get; set; }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithShowValue.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithShowValue.cs
deleted file mode 100644
index 479627b..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithShowValue.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingWithShowValue
-/// </summary>
-public interface IExcelConditionalFormattingWithShowValue {
- /// <summary>
- /// ShowValue Attribute
- /// </summary>
- bool ShowValue { get; set; }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithStdDev.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithStdDev.cs
deleted file mode 100644
index d3cf330..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithStdDev.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingWithStdDev
-/// </summary>
-public interface IExcelConditionalFormattingWithStdDev {
- /// <summary>
- /// StdDev Attribute
- /// </summary>
- UInt16 StdDev { get; set; }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithText.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithText.cs
deleted file mode 100644
index bfe91a4..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithText.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-
-/// <summary>
-/// IExcelConditionalFormattingWithText
-/// </summary>
-public interface IExcelConditionalFormattingWithText {
- /// <summary>
- /// Text Attribute
- /// </summary>
- string Text { get; set; }
-}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IRangeConditionalFormatting.cs b/EPPlus/ConditionalFormatting/Contracts/IRangeConditionalFormatting.cs
deleted file mode 100644
index bd84006..0000000
--- a/EPPlus/ConditionalFormatting/Contracts/IRangeConditionalFormatting.cs
+++ /dev/null
@@ -1,286 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting 2012-04-03
- *******************************************************************************/
-
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// Provides functionality for adding Conditional Formatting to a range (<see cref="ExcelRangeBase"/>).
-/// Each method will return a configurable condtional formatting type.
-/// </summary>
-public interface IRangeConditionalFormatting {
- /// <summary>
- /// Adds a Above Average rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingAverageGroup AddAboveAverage();
-
- /// <summary>
- /// Adds a Above Or Equal Average rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingAverageGroup AddAboveOrEqualAverage();
-
- /// <summary>
- /// Adds a Below Average rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingAverageGroup AddBelowAverage();
-
- /// <summary>
- /// Adds a Below Or Equal Average rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingAverageGroup AddBelowOrEqualAverage();
-
- /// <summary>
- /// Adds a Above StdDev rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingStdDevGroup AddAboveStdDev();
-
- /// <summary>
- /// Adds a Below StdDev rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingStdDevGroup AddBelowStdDev();
-
- /// <summary>
- /// Adds a Bottom rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTopBottomGroup AddBottom();
-
- /// <summary>
- /// Adds a Bottom Percent rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTopBottomGroup AddBottomPercent();
-
- /// <summary>
- /// Adds a Top rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTopBottomGroup AddTop();
-
- /// <summary>
- /// Adds a Top Percent rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTopBottomGroup AddTopPercent();
-
- /// <summary>
- /// Adds a Last 7 Days rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddLast7Days();
-
- /// <summary>
- /// Adds a Last Month rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddLastMonth();
-
- /// <summary>
- /// Adds a Last Week rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddLastWeek();
-
- /// <summary>
- /// Adds a Next Month rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddNextMonth();
-
- /// <summary>
- /// Adds a Next Week rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddNextWeek();
-
- /// <summary>
- /// Adds a This Month rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddThisMonth();
-
- /// <summary>
- /// Adds a This Week rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddThisWeek();
-
- /// <summary>
- /// Adds a Today rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddToday();
-
- /// <summary>
- /// Adds a Tomorrow rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddTomorrow();
-
- /// <summary>
- /// Adds a Yesterday rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddYesterday();
-
- /// <summary>
- /// Adds a Begins With rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingBeginsWith AddBeginsWith();
-
- /// <summary>
- /// Adds a Between rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingBetween AddBetween();
-
- /// <summary>
- /// Adds a ContainsBlanks rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingContainsBlanks AddContainsBlanks();
-
- /// <summary>
- /// Adds a ContainsErrors rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingContainsErrors AddContainsErrors();
-
- /// <summary>
- /// Adds a ContainsText rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingContainsText AddContainsText();
-
- /// <summary>
- /// Adds a DuplicateValues rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingDuplicateValues AddDuplicateValues();
-
- /// <summary>
- /// Adds a EndsWith rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingEndsWith AddEndsWith();
-
- /// <summary>
- /// Adds a Equal rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingEqual AddEqual();
-
- /// <summary>
- /// Adds a Expression rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingExpression AddExpression();
-
- /// <summary>
- /// Adds a GreaterThan rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingGreaterThan AddGreaterThan();
-
- /// <summary>
- /// Adds a GreaterThanOrEqual rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingGreaterThanOrEqual AddGreaterThanOrEqual();
-
- /// <summary>
- /// Adds a LessThan rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingLessThan AddLessThan();
-
- /// <summary>
- /// Adds a LessThanOrEqual rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingLessThanOrEqual AddLessThanOrEqual();
-
- /// <summary>
- /// Adds a NotBetween rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingNotBetween AddNotBetween();
-
- /// <summary>
- /// Adds a NotContainsBlanks rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingNotContainsBlanks AddNotContainsBlanks();
-
- /// <summary>
- /// Adds a NotContainsErrors rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingNotContainsErrors AddNotContainsErrors();
-
- /// <summary>
- /// Adds a NotContainsText rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingNotContainsText AddNotContainsText();
-
- /// <summary>
- /// Adds a NotEqual rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingNotEqual AddNotEqual();
-
- /// <summary>
- /// Adds a UniqueValues rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingUniqueValues AddUniqueValues();
-
- /// <summary>
- /// Adds a <see cref="ExcelConditionalFormattingThreeColorScale"/> to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingThreeColorScale AddThreeColorScale();
-
- /// <summary>
- /// Adds a <see cref="ExcelConditionalFormattingTwoColorScale"/> to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTwoColorScale AddTwoColorScale();
-}
diff --git a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingCollection.cs b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingCollection.cs
deleted file mode 100644
index 8717d2e..0000000
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingCollection.cs
+++ /dev/null
@@ -1,781 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting 2012-04-03
- *******************************************************************************/
-
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// Collection of <see cref="ExcelConditionalFormattingRule"/>.
-/// This class is providing the API for EPPlus conditional formatting.
-/// </summary>
-/// <remarks>
-/// <para>
-/// The public methods of this class (Add[...]ConditionalFormatting) will create a ConditionalFormatting/CfRule entry in the worksheet. When this
-/// Conditional Formatting has been created changes to the properties will affect the workbook immediately.
-/// </para>
-/// <para>
-/// Each type of Conditional Formatting Rule has diferente set of properties.
-/// </para>
-/// <code>
-/// // Add a Three Color Scale conditional formatting
-/// var cf = worksheet.ConditionalFormatting.AddThreeColorScale(new ExcelAddress("A1:C10"));
-/// // Set the conditional formatting properties
-/// cf.LowValue.Type = ExcelConditionalFormattingValueObjectType.Min;
-/// cf.LowValue.Color = Color.White;
-/// cf.MiddleValue.Type = ExcelConditionalFormattingValueObjectType.Percent;
-/// cf.MiddleValue.Value = 50;
-/// cf.MiddleValue.Color = Color.Blue;
-/// cf.HighValue.Type = ExcelConditionalFormattingValueObjectType.Max;
-/// cf.HighValue.Color = Color.Black;
-/// </code>
-/// </remarks>
-public class ExcelConditionalFormattingCollection
- : XmlHelper,
- IEnumerable<IExcelConditionalFormattingRule> {
- private readonly List<IExcelConditionalFormattingRule> _rules = new();
- private readonly ExcelWorksheet _worksheet;
-
- protected override ImmutableArray<string> SchemaNodeOrder =>
- ExcelWorksheet.WorksheetSchemaNodeOrder;
-
- /// <summary>
- /// Initialize the <see cref="ExcelConditionalFormattingCollection"/>
- /// </summary>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingCollection(ExcelWorksheet worksheet)
- : base(worksheet.NameSpaceManager, worksheet.WorksheetXml.DocumentElement) {
- Require.Argument(worksheet).IsNotNull("worksheet");
-
- _worksheet = worksheet;
-
- // Look for all the <conditionalFormatting>
- var conditionalFormattingNodes = TopNode.SelectNodes(
- "//" + ExcelConditionalFormattingConstants.Paths._conditionalFormatting,
- _worksheet.NameSpaceManager);
-
- // Check if we found at least 1 node
- if ((conditionalFormattingNodes != null) && (conditionalFormattingNodes.Count > 0)) {
- // Foreach <conditionalFormatting>
- foreach (XmlNode conditionalFormattingNode in conditionalFormattingNodes) {
- // Check if @sqref attribute exists
- if (conditionalFormattingNode.Attributes[ExcelConditionalFormattingConstants
- .Attributes
- ._sqref] == null) {
- throw new(ExcelConditionalFormattingConstants.Errors._missingSqrefAttribute);
- }
-
- // Get the @sqref attribute
- ExcelAddress address = new ExcelAddress(
- conditionalFormattingNode.Attributes[ExcelConditionalFormattingConstants
- .Attributes
- ._sqref].Value);
-
- // Check for all the <cfRules> nodes and load them
- var cfRuleNodes = conditionalFormattingNode.SelectNodes(
- ExcelConditionalFormattingConstants.Paths._cfRule,
- _worksheet.NameSpaceManager);
-
- // Foreach <cfRule> inside the current <conditionalFormatting>
- foreach (XmlNode cfRuleNode in cfRuleNodes) {
- // Check if @type attribute exists
- if (cfRuleNode.Attributes[ExcelConditionalFormattingConstants.Attributes._type] == null) {
- throw new(ExcelConditionalFormattingConstants.Errors._missingTypeAttribute);
- }
-
- // Check if @priority attribute exists
- if (cfRuleNode.Attributes[ExcelConditionalFormattingConstants.Attributes._priority]
- == null) {
- throw new(ExcelConditionalFormattingConstants.Errors._missingPriorityAttribute);
- }
-
- // Get the <cfRule> main attributes
- string typeAttribute = ExcelConditionalFormattingHelper.GetAttributeString(
- cfRuleNode,
- ExcelConditionalFormattingConstants.Attributes._type);
-
- int priority = ExcelConditionalFormattingHelper.GetAttributeInt(
- cfRuleNode,
- ExcelConditionalFormattingConstants.Attributes._priority);
-
- // Transform the @type attribute to EPPlus Rule Type (slighty diferente)
- var type = ExcelConditionalFormattingRuleType.GetTypeByAttrbiute(
- typeAttribute,
- cfRuleNode,
- _worksheet.NameSpaceManager);
-
- // Create the Rule according to the correct type, address and priority
- var cfRule = ExcelConditionalFormattingRuleFactory.Create(
- type,
- address,
- priority,
- _worksheet,
- cfRuleNode);
-
- // Add the new rule to the list
- if (cfRule != null) {
- _rules.Add(cfRule);
- }
- }
- }
- }
- }
-
- private void EnsureRootElementExists() {
- // Find the <worksheet> node
- if (_worksheet.WorksheetXml.DocumentElement == null) {
- throw new(ExcelConditionalFormattingConstants.Errors._missingWorksheetNode);
- }
- }
-
- /// <summary>
- /// Validates address - not empty (collisions are allowded)
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- private ExcelAddress ValidateAddress(ExcelAddress address) {
- Require.Argument(address).IsNotNull("address");
-
- //TODO: Are there any other validation we need to do?
- return address;
- }
-
- /// <summary>
- /// Get the next priority sequencial number
- /// </summary>
- /// <returns></returns>
- private int GetNextPriority() {
- // Consider zero as the last priority when we have no CF rules
- int lastPriority = 0;
-
- // Search for the last priority
- foreach (var cfRule in _rules) {
- if (cfRule.Priority > lastPriority) {
- lastPriority = cfRule.Priority;
- }
- }
-
- // Our next priority is the last plus one
- return lastPriority + 1;
- }
-
- /// <summary>
- /// Number of validations
- /// </summary>
- public int Count => _rules.Count;
-
- /// <summary>
- /// Index operator, returns by 0-based index
- /// </summary>
- /// <param name="index"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingRule this[int index] {
- get => _rules[index];
- set => _rules[index] = value;
- }
-
- /// <summary>
- /// Get the 'cfRule' enumerator
- /// </summary>
- /// <returns></returns>
- IEnumerator<IExcelConditionalFormattingRule> IEnumerable<IExcelConditionalFormattingRule>.GetEnumerator() {
- return _rules.GetEnumerator();
- }
-
- /// <summary>
- /// Get the 'cfRule' enumerator
- /// </summary>
- /// <returns></returns>
- IEnumerator IEnumerable.GetEnumerator() {
- return _rules.GetEnumerator();
- }
-
- /// <summary>
- /// Removes all 'cfRule' from the collection and from the XML.
- /// <remarks>
- /// This is the same as removing all the 'conditionalFormatting' nodes.
- /// </remarks>
- /// </summary>
- public void RemoveAll() {
- // Look for all the <conditionalFormatting> nodes
- var conditionalFormattingNodes = TopNode.SelectNodes(
- "//" + ExcelConditionalFormattingConstants.Paths._conditionalFormatting,
- _worksheet.NameSpaceManager);
-
- // Remove all the <conditionalFormatting> nodes one by one
- foreach (XmlNode conditionalFormattingNode in conditionalFormattingNodes) {
- conditionalFormattingNode.ParentNode.RemoveChild(conditionalFormattingNode);
- }
-
- // Clear the <cfRule> item list
- _rules.Clear();
- }
-
- /// <summary>
- /// Remove a Conditional Formatting Rule by its object
- /// </summary>
- /// <param name="item"></param>
- public void Remove(IExcelConditionalFormattingRule item) {
- Require.Argument(item).IsNotNull("item");
-
- try {
- // Point to the parent node
- var oldParentNode = item.Node.ParentNode;
-
- // Remove the <cfRule> from the old <conditionalFormatting> parent node
- oldParentNode.RemoveChild(item.Node);
-
- // Check if the old <conditionalFormatting> parent node has <cfRule> node inside it
- if (!oldParentNode.HasChildNodes) {
- // Remove the old parent node
- oldParentNode.ParentNode.RemoveChild(oldParentNode);
- }
-
- _rules.Remove(item);
- } catch {
- throw new(ExcelConditionalFormattingConstants.Errors._invalidRemoveRuleOperation);
- }
- }
-
- /// <summary>
- /// Remove a Conditional Formatting Rule by its 0-based index
- /// </summary>
- /// <param name="index"></param>
- public void RemoveAt(int index) {
- Require.Argument(index).IsInRange(0, Count - 1, "index");
-
- Remove(this[index]);
- }
-
- /// <summary>
- /// Remove a Conditional Formatting Rule by its priority
- /// </summary>
- /// <param name="priority"></param>
- public void RemoveByPriority(int priority) {
- try {
- Remove(RulesByPriority(priority));
- } catch {}
- }
-
- /// <summary>
- /// Get a rule by its priority
- /// </summary>
- /// <param name="priority"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingRule RulesByPriority(int priority) {
- return _rules.Find(x => x.Priority == priority);
- }
-
- /// <summary>
- /// Add rule (internal)
- /// </summary>
- /// <param name="type"></param>
- /// <param name="address"></param>
- /// <returns></returns>F
- internal IExcelConditionalFormattingRule AddRule(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address) {
- Require.Argument(address).IsNotNull("address");
-
- address = ValidateAddress(address);
- EnsureRootElementExists();
-
- // Create the Rule according to the correct type, address and priority
- IExcelConditionalFormattingRule cfRule = ExcelConditionalFormattingRuleFactory.Create(
- type,
- address,
- GetNextPriority(),
- _worksheet,
- null);
-
- // Add the newly created rule to the list
- _rules.Add(cfRule);
-
- // Return the newly created rule
- return cfRule;
- }
-
- /// <summary>
- /// Add AboveAverage Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingAverageGroup AddAboveAverage(ExcelAddress address) {
- return (IExcelConditionalFormattingAverageGroup)AddRule(
- eExcelConditionalFormattingRuleType.AboveAverage,
- address);
- }
-
- /// <summary>
- /// Add AboveOrEqualAverage Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingAverageGroup AddAboveOrEqualAverage(ExcelAddress address) {
- return (IExcelConditionalFormattingAverageGroup)AddRule(
- eExcelConditionalFormattingRuleType.AboveOrEqualAverage,
- address);
- }
-
- /// <summary>
- /// Add BelowAverage Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingAverageGroup AddBelowAverage(ExcelAddress address) {
- return (IExcelConditionalFormattingAverageGroup)AddRule(
- eExcelConditionalFormattingRuleType.BelowAverage,
- address);
- }
-
- /// <summary>
- /// Add BelowOrEqualAverage Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingAverageGroup AddBelowOrEqualAverage(ExcelAddress address) {
- return (IExcelConditionalFormattingAverageGroup)AddRule(
- eExcelConditionalFormattingRuleType.BelowOrEqualAverage,
- address);
- }
-
- /// <summary>
- /// Add AboveStdDev Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingStdDevGroup AddAboveStdDev(ExcelAddress address) {
- return (IExcelConditionalFormattingStdDevGroup)AddRule(
- eExcelConditionalFormattingRuleType.AboveStdDev,
- address);
- }
-
- /// <summary>
- /// Add BelowStdDev Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingStdDevGroup AddBelowStdDev(ExcelAddress address) {
- return (IExcelConditionalFormattingStdDevGroup)AddRule(
- eExcelConditionalFormattingRuleType.BelowStdDev,
- address);
- }
-
- /// <summary>
- /// Add Bottom Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingTopBottomGroup AddBottom(ExcelAddress address) {
- return (IExcelConditionalFormattingTopBottomGroup)AddRule(
- eExcelConditionalFormattingRuleType.Bottom,
- address);
- }
-
- /// <summary>
- /// Add BottomPercent Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingTopBottomGroup AddBottomPercent(ExcelAddress address) {
- return (IExcelConditionalFormattingTopBottomGroup)AddRule(
- eExcelConditionalFormattingRuleType.BottomPercent,
- address);
- }
-
- /// <summary>
- /// Add Top Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingTopBottomGroup AddTop(ExcelAddress address) {
- return (IExcelConditionalFormattingTopBottomGroup)AddRule(
- eExcelConditionalFormattingRuleType.Top,
- address);
- }
-
- /// <summary>
- /// Add TopPercent Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingTopBottomGroup AddTopPercent(ExcelAddress address) {
- return (IExcelConditionalFormattingTopBottomGroup)AddRule(
- eExcelConditionalFormattingRuleType.TopPercent,
- address);
- }
-
- /// <summary>
- /// Add Last7Days Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddLast7Days(ExcelAddress address) {
- return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
- eExcelConditionalFormattingRuleType.Last7Days,
- address);
- }
-
- /// <summary>
- /// Add LastMonth Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddLastMonth(ExcelAddress address) {
- return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
- eExcelConditionalFormattingRuleType.LastMonth,
- address);
- }
-
- /// <summary>
- /// Add LastWeek Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddLastWeek(ExcelAddress address) {
- return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
- eExcelConditionalFormattingRuleType.LastWeek,
- address);
- }
-
- /// <summary>
- /// Add NextMonth Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddNextMonth(ExcelAddress address) {
- return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
- eExcelConditionalFormattingRuleType.NextMonth,
- address);
- }
-
- /// <summary>
- /// Add NextWeek Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddNextWeek(ExcelAddress address) {
- return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
- eExcelConditionalFormattingRuleType.NextWeek,
- address);
- }
-
- /// <summary>
- /// Add ThisMonth Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddThisMonth(ExcelAddress address) {
- return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
- eExcelConditionalFormattingRuleType.ThisMonth,
- address);
- }
-
- /// <summary>
- /// Add ThisWeek Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddThisWeek(ExcelAddress address) {
- return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
- eExcelConditionalFormattingRuleType.ThisWeek,
- address);
- }
-
- /// <summary>
- /// Add Today Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddToday(ExcelAddress address) {
- return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
- eExcelConditionalFormattingRuleType.Today,
- address);
- }
-
- /// <summary>
- /// Add Tomorrow Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddTomorrow(ExcelAddress address) {
- return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
- eExcelConditionalFormattingRuleType.Tomorrow,
- address);
- }
-
- /// <summary>
- /// Add Yesterday Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddYesterday(ExcelAddress address) {
- return (IExcelConditionalFormattingTimePeriodGroup)AddRule(
- eExcelConditionalFormattingRuleType.Yesterday,
- address);
- }
-
- /// <summary>
- /// Add BeginsWith Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingBeginsWith AddBeginsWith(ExcelAddress address) {
- return (IExcelConditionalFormattingBeginsWith)AddRule(
- eExcelConditionalFormattingRuleType.BeginsWith,
- address);
- }
-
- /// <summary>
- /// Add Between Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingBetween AddBetween(ExcelAddress address) {
- return (IExcelConditionalFormattingBetween)AddRule(
- eExcelConditionalFormattingRuleType.Between,
- address);
- }
-
- /// <summary>
- /// Add ContainsBlanks Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingContainsBlanks AddContainsBlanks(ExcelAddress address) {
- return (IExcelConditionalFormattingContainsBlanks)AddRule(
- eExcelConditionalFormattingRuleType.ContainsBlanks,
- address);
- }
-
- /// <summary>
- /// Add ContainsErrors Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingContainsErrors AddContainsErrors(ExcelAddress address) {
- return (IExcelConditionalFormattingContainsErrors)AddRule(
- eExcelConditionalFormattingRuleType.ContainsErrors,
- address);
- }
-
- /// <summary>
- /// Add ContainsText Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingContainsText AddContainsText(ExcelAddress address) {
- return (IExcelConditionalFormattingContainsText)AddRule(
- eExcelConditionalFormattingRuleType.ContainsText,
- address);
- }
-
- /// <summary>
- /// Add DuplicateValues Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingDuplicateValues AddDuplicateValues(ExcelAddress address) {
- return (IExcelConditionalFormattingDuplicateValues)AddRule(
- eExcelConditionalFormattingRuleType.DuplicateValues,
- address);
- }
-
- /// <summary>
- /// Add EndsWith Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingEndsWith AddEndsWith(ExcelAddress address) {
- return (IExcelConditionalFormattingEndsWith)AddRule(
- eExcelConditionalFormattingRuleType.EndsWith,
- address);
- }
-
- /// <summary>
- /// Add Equal Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingEqual AddEqual(ExcelAddress address) {
- return (IExcelConditionalFormattingEqual)AddRule(
- eExcelConditionalFormattingRuleType.Equal,
- address);
- }
-
- /// <summary>
- /// Add Expression Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingExpression AddExpression(ExcelAddress address) {
- return (IExcelConditionalFormattingExpression)AddRule(
- eExcelConditionalFormattingRuleType.Expression,
- address);
- }
-
- /// <summary>
- /// Add GreaterThan Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingGreaterThan AddGreaterThan(ExcelAddress address) {
- return (IExcelConditionalFormattingGreaterThan)AddRule(
- eExcelConditionalFormattingRuleType.GreaterThan,
- address);
- }
-
- /// <summary>
- /// Add GreaterThanOrEqual Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingGreaterThanOrEqual AddGreaterThanOrEqual(ExcelAddress address) {
- return (IExcelConditionalFormattingGreaterThanOrEqual)AddRule(
- eExcelConditionalFormattingRuleType.GreaterThanOrEqual,
- address);
- }
-
- /// <summary>
- /// Add LessThan Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingLessThan AddLessThan(ExcelAddress address) {
- return (IExcelConditionalFormattingLessThan)AddRule(
- eExcelConditionalFormattingRuleType.LessThan,
- address);
- }
-
- /// <summary>
- /// Add LessThanOrEqual Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingLessThanOrEqual AddLessThanOrEqual(ExcelAddress address) {
- return (IExcelConditionalFormattingLessThanOrEqual)AddRule(
- eExcelConditionalFormattingRuleType.LessThanOrEqual,
- address);
- }
-
- /// <summary>
- /// Add NotBetween Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingNotBetween AddNotBetween(ExcelAddress address) {
- return (IExcelConditionalFormattingNotBetween)AddRule(
- eExcelConditionalFormattingRuleType.NotBetween,
- address);
- }
-
- /// <summary>
- /// Add NotContainsBlanks Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingNotContainsBlanks AddNotContainsBlanks(ExcelAddress address) {
- return (IExcelConditionalFormattingNotContainsBlanks)AddRule(
- eExcelConditionalFormattingRuleType.NotContainsBlanks,
- address);
- }
-
- /// <summary>
- /// Add NotContainsErrors Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingNotContainsErrors AddNotContainsErrors(ExcelAddress address) {
- return (IExcelConditionalFormattingNotContainsErrors)AddRule(
- eExcelConditionalFormattingRuleType.NotContainsErrors,
- address);
- }
-
- /// <summary>
- /// Add NotContainsText Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingNotContainsText AddNotContainsText(ExcelAddress address) {
- return (IExcelConditionalFormattingNotContainsText)AddRule(
- eExcelConditionalFormattingRuleType.NotContainsText,
- address);
- }
-
- /// <summary>
- /// Add NotEqual Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingNotEqual AddNotEqual(ExcelAddress address) {
- return (IExcelConditionalFormattingNotEqual)AddRule(
- eExcelConditionalFormattingRuleType.NotEqual,
- address);
- }
-
- /// <summary>
- /// Add Unique Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingUniqueValues AddUniqueValues(ExcelAddress address) {
- return (IExcelConditionalFormattingUniqueValues)AddRule(
- eExcelConditionalFormattingRuleType.UniqueValues,
- address);
- }
-
- /// <summary>
- /// Add ThreeColorScale Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingThreeColorScale AddThreeColorScale(ExcelAddress address) {
- return (IExcelConditionalFormattingThreeColorScale)AddRule(
- eExcelConditionalFormattingRuleType.ThreeColorScale,
- address);
- }
-
- /// <summary>
- /// Add TwoColorScale Rule
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingTwoColorScale AddTwoColorScale(ExcelAddress address) {
- return (IExcelConditionalFormattingTwoColorScale)AddRule(
- eExcelConditionalFormattingRuleType.TwoColorScale,
- address);
- }
-}
diff --git a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingColorScaleValue.cs b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingColorScaleValue.cs
deleted file mode 100644
index 59376e7..0000000
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingColorScaleValue.cs
+++ /dev/null
@@ -1,408 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Immutable;
-using System.Xml;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// 18.3.1.11 cfvo (Conditional Format Value Object)
-/// Describes the values of the interpolation points in a gradient scale.
-/// </summary>
-public class ExcelConditionalFormattingColorScaleValue : XmlHelper {
- private eExcelConditionalFormattingValueObjectPosition _position;
- private eExcelConditionalFormattingRuleType _ruleType;
- private readonly ExcelWorksheet _worksheet;
-
- protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
- ExcelConditionalFormattingConstants.Nodes._cfvo,
- ExcelConditionalFormattingConstants.Nodes._color,
- ];
-
- /// <summary>
- /// Initialize the cfvo (§18.3.1.11) node
- /// </summary>
- /// <param name="position"></param>
- /// <param name="type"></param>
- /// <param name="color"></param>
- /// <param name="value"></param>
- /// <param name="formula"></param>
- /// <param name="ruleType"></param>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode">The cfvo (§18.3.1.11) node parent. Can be any of the following:
- /// colorScale (§18.3.1.16); dataBar (§18.3.1.28); iconSet (§18.3.1.49)</param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingColorScaleValue(
- eExcelConditionalFormattingValueObjectPosition position,
- eExcelConditionalFormattingValueObjectType type,
- double value,
- string formula,
- eExcelConditionalFormattingRuleType ruleType,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(namespaceManager, itemElementNode) {
- Require.Argument(priority).IsInRange(1, int.MaxValue, "priority");
- Require.Argument(address).IsNotNull("address");
- Require.Argument(worksheet).IsNotNull("worksheet");
-
- // Save the worksheet for private methods to use
- _worksheet = worksheet;
-
- // Check if the parent does not exists
- if (itemElementNode == null) {
- // Get the parent node path by the rule type
- string parentNodePath = ExcelConditionalFormattingValueObjectType.GetParentPathByRuleType(
- ruleType);
-
- // Check for en error (rule type does not have <cfvo>)
- if (parentNodePath == string.Empty) {
- throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoParentNode);
- }
-
- // Point to the <cfvo> parent node
- itemElementNode = _worksheet.WorksheetXml.SelectSingleNode(
- string.Format(
- "//{0}[{1}='{2}']/{3}[{4}='{5}']/{6}",
- // {0}
- ExcelConditionalFormattingConstants.Paths._conditionalFormatting,
- // {1}
- ExcelConditionalFormattingConstants.Paths._sqrefAttribute,
- // {2}
- address.Address,
- // {3}
- ExcelConditionalFormattingConstants.Paths._cfRule,
- // {4}
- ExcelConditionalFormattingConstants.Paths._priorityAttribute,
- // {5}
- priority,
- // {6}
- parentNodePath),
- _worksheet.NameSpaceManager);
-
- // Check for en error (rule type does not have <cfvo>)
- if (itemElementNode == null) {
- throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoParentNode);
- }
- }
-
- // Point to the <cfvo> parent node (<colorScale>, <dataBar> or <iconSet>)
- // This is different than normal, as TopNode does not point to the node itself but to
- // its PARENT. Later, in the CreateNodeByOrdem method the TopNode will be updated.
- TopNode = itemElementNode;
-
- // Save the attributes
- Position = position;
- RuleType = ruleType;
- Type = type;
- Value = value;
- Formula = formula;
- }
-
- /// <summary>
- /// Initialize the <see cref="ExcelConditionalFormattingColorScaleValue"/>
- /// </summary>
- /// <param name="position"></param>
- /// <param name="type"></param>
- /// <param name="color"></param>
- /// <param name="value"></param>
- /// <param name="formula"></param>
- /// <param name="ruleType"></param>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingColorScaleValue(
- eExcelConditionalFormattingValueObjectPosition position,
- eExcelConditionalFormattingValueObjectType type,
- double value,
- string formula,
- eExcelConditionalFormattingRuleType ruleType,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNamespaceManager namespaceManager)
- : this(
- position,
- type,
- value,
- formula,
- ruleType,
- address,
- priority,
- worksheet,
- null,
- namespaceManager) {}
-
- /// <summary>
- /// Initialize the <see cref="ExcelConditionalFormattingColorScaleValue"/>
- /// </summary>
- /// <param name="position"></param>
- /// <param name="type"></param>
- /// <param name="color"></param>
- /// <param name="ruleType"></param>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingColorScaleValue(
- eExcelConditionalFormattingValueObjectPosition position,
- eExcelConditionalFormattingValueObjectType type,
- eExcelConditionalFormattingRuleType ruleType,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNamespaceManager namespaceManager)
- : this(
- position,
- type,
- 0,
- null,
- ruleType,
- address,
- priority,
- worksheet,
- null,
- namespaceManager) {}
-
- /// <summary>
- /// Get the node order (1, 2 ou 3) according to the Position (Low, Middle and High)
- /// and the Rule Type (TwoColorScale ou ThreeColorScale).
- /// </summary>
- /// <returns></returns>
- private int GetNodeOrder() {
- return ExcelConditionalFormattingValueObjectType.GetOrderByPosition(Position, RuleType);
- }
-
- /// <summary>
- /// Create the 'cfvo'/'color' nodes in the right order. They should appear like this:
- /// "cfvo" --> Low Value (value object)
- /// "cfvo" --> Middle Value (value object)
- /// "cfvo" --> High Value (value object)
- /// "color" --> Low Value (color)
- /// "color" --> Middle Value (color)
- /// "color" --> High Value (color)
- /// </summary>
- /// <param name="nodeType"></param>
- /// <param name="attributePath"></param>
- /// <param name="attributeValue"></param>
- private void CreateNodeByOrdem(
- eExcelConditionalFormattingValueObjectNodeType nodeType,
- string attributePath,
- string attributeValue) {
- // Save the current TopNode
- XmlNode currentTopNode = TopNode;
-
- string nodePath = ExcelConditionalFormattingValueObjectType.GetNodePathByNodeType(nodeType);
- int nodeOrder = GetNodeOrder();
- eNodeInsertOrder nodeInsertOrder = eNodeInsertOrder.SchemaOrder;
- XmlNode referenceNode = null;
-
- if (nodeOrder > 1) {
- // Find the node just before the one we need to include
- referenceNode = TopNode.SelectSingleNode(
- string.Format(
- "{0}[position()={1}]",
- // {0}
- nodePath,
- // {1}
- nodeOrder - 1),
- _worksheet.NameSpaceManager);
-
- // Only if the prepend node exists than insert after
- if (referenceNode != null) {
- nodeInsertOrder = eNodeInsertOrder.After;
- }
- }
-
- // Create the node in the right order
- var node = CreateComplexNode(
- TopNode,
- string.Format(
- "{0}[position()={1}]",
- // {0}
- nodePath,
- // {1}
- nodeOrder),
- nodeInsertOrder,
- referenceNode);
-
- // Point to the new node as the temporary TopNode (we need it for the XmlHelper functions)
- TopNode = node;
-
- // Add/Remove the attribute (if the attributeValue is empty then it will be removed)
- SetXmlNodeString(node, attributePath, attributeValue, true);
-
- // Point back to the <cfvo>/<color> parent node
- TopNode = currentTopNode;
- }
-
- /// <summary>
- ///
- /// </summary>
- internal eExcelConditionalFormattingValueObjectPosition Position {
- get => _position;
- set => _position = value;
- }
-
- /// <summary>
- ///
- /// </summary>
- internal eExcelConditionalFormattingRuleType RuleType {
- get => _ruleType;
- set => _ruleType = value;
- }
-
- /// <summary>
- ///
- /// </summary>
- public eExcelConditionalFormattingValueObjectType Type {
- get {
- var typeAttribute = GetXmlNodeString(
- string.Format(
- "{0}[position()={1}]/{2}",
- // {0}
- ExcelConditionalFormattingConstants.Paths._cfvo,
- // {1}
- GetNodeOrder(),
- // {2}
- ExcelConditionalFormattingConstants.Paths._typeAttribute));
-
- return ExcelConditionalFormattingValueObjectType.GetTypeByAttrbiute(typeAttribute);
- }
- set {
- CreateNodeByOrdem(
- eExcelConditionalFormattingValueObjectNodeType.Cfvo,
- ExcelConditionalFormattingConstants.Paths._typeAttribute,
- ExcelConditionalFormattingValueObjectType.GetAttributeByType(value));
-
- bool removeValAttribute = false;
-
- // Make sure unnecessary attributes are removed (occures when we change
- // the value object type)
- switch (Type) {
- case eExcelConditionalFormattingValueObjectType.Min:
- case eExcelConditionalFormattingValueObjectType.Max:
- removeValAttribute = true;
- break;
- }
-
- // Check if we need to remove the @val attribute
- if (removeValAttribute) {
- string nodePath = ExcelConditionalFormattingValueObjectType.GetNodePathByNodeType(
- eExcelConditionalFormattingValueObjectNodeType.Cfvo);
- int nodeOrder = GetNodeOrder();
-
- // Remove the attribute (removed when the value = '')
- CreateComplexNode(
- TopNode,
- string.Format(
- "{0}[position()={1}]/{2}=''",
- // {0}
- nodePath,
- // {1}
- nodeOrder,
- // {2}
- ExcelConditionalFormattingConstants.Paths._valAttribute));
- }
- }
- }
-
- /// <summary>
- /// Get/Set the 'cfvo' node @val attribute
- /// </summary>
- public Double Value {
- get =>
- GetXmlNodeDouble(
- string.Format(
- "{0}[position()={1}]/{2}",
- // {0}
- ExcelConditionalFormattingConstants.Paths._cfvo,
- // {1}
- GetNodeOrder(),
- // {2}
- ExcelConditionalFormattingConstants.Paths._valAttribute));
- set {
- string valueToStore = string.Empty;
-
- // Only some types use the @val attribute
- if ((Type == eExcelConditionalFormattingValueObjectType.Num)
- || (Type == eExcelConditionalFormattingValueObjectType.Percent)
- || (Type == eExcelConditionalFormattingValueObjectType.Percentile)) {
- valueToStore = value.ToString();
- }
-
- CreateNodeByOrdem(
- eExcelConditionalFormattingValueObjectNodeType.Cfvo,
- ExcelConditionalFormattingConstants.Paths._valAttribute,
- valueToStore);
- }
- }
-
- /// <summary>
- /// Get/Set the Formula of the Object Value (uses the same attribute as the Value)
- /// </summary>
- public string Formula {
- get {
- // Return empty if the Object Value type is not Formula
- if (Type != eExcelConditionalFormattingValueObjectType.Formula) {
- return string.Empty;
- }
-
- // Excel stores the formula in the @val attribute
- return GetXmlNodeString(
- string.Format(
- "{0}[position()={1}]/{2}",
- // {0}
- ExcelConditionalFormattingConstants.Paths._cfvo,
- // {1}
- GetNodeOrder(),
- // {2}
- ExcelConditionalFormattingConstants.Paths._valAttribute));
- }
- set {
- // Only store the formula if the Object Value type is Formula
- if (Type == eExcelConditionalFormattingValueObjectType.Formula) {
- CreateNodeByOrdem(
- eExcelConditionalFormattingValueObjectNodeType.Cfvo,
- ExcelConditionalFormattingConstants.Paths._valAttribute,
- value ?? string.Empty);
- }
- }
- }
-}
diff --git a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingConstants.cs b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingConstants.cs
deleted file mode 100644
index 938c6cd..0000000
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingConstants.cs
+++ /dev/null
@@ -1,259 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// The conditional formatting constants
-/// </summary>
-internal static class ExcelConditionalFormattingConstants {
- internal class Errors {
- internal const string _commaSeparatedAddresses =
- "Multiple addresses may not be commaseparated, use space instead";
- internal const string _invalidPriority = "Invalid priority number. Must be bigger than zero";
- internal const string _invalidRemoveRuleOperation = "Invalid remove rule operation";
- internal const string _missingCfvoNode = "Missing 'cfvo' node in Conditional Formatting";
- internal const string _missingCfvoParentNode =
- "Missing 'cfvo' parent node in Conditional Formatting";
- internal const string _missingConditionalFormattingNode =
- "Missing 'conditionalFormatting' node in Conditional Formatting";
- internal const string _missingItemRuleList =
- "Missing item with address '{0}' in Conditional Formatting Rule List";
- internal const string _missingPriorityAttribute =
- "Missing 'priority' attribute in Conditional Formatting Rule";
- internal const string _missingRuleType =
- "Missing eExcelConditionalFormattingRuleType Type in Conditional Formatting";
- internal const string _missingSqrefAttribute =
- "Missing 'sqref' attribute in Conditional Formatting";
- internal const string _missingTypeAttribute =
- "Missing 'type' attribute in Conditional Formatting Rule";
- internal const string _missingWorksheetNode = "Missing 'worksheet' node";
- internal const string _nonSupportedRuleType = "Non supported conditionalFormattingType: {0}";
- internal const string _unexistentCfvoTypeAttribute =
- "Unexistent eExcelConditionalFormattingValueObjectType attribute in Conditional Formatting";
- internal const string _unexistentOperatorTypeAttribute =
- "Unexistent eExcelConditionalFormattingOperatorType attribute in Conditional Formatting";
- internal const string _unexistentTimePeriodTypeAttribute =
- "Unexistent eExcelConditionalFormattingTimePeriodType attribute in Conditional Formatting";
- internal const string _unexpectedRuleTypeAttribute =
- "Unexpected eExcelConditionalFormattingRuleType attribute in Conditional Formatting Rule";
- internal const string _wrongNumberCfvoColorNodes =
- "Wrong number of 'cfvo'/'color' nodes in Conditional Formatting Rule";
- }
-
- internal class Nodes {
- internal const string _worksheet = "worksheet";
- internal const string _conditionalFormatting = "conditionalFormatting";
- internal const string _cfRule = "cfRule";
- internal const string _colorScale = "colorScale";
- internal const string _cfvo = "cfvo";
- internal const string _color = "color";
- internal const string _dataBar = "dataBar";
- internal const string _iconSet = "iconSet";
- internal const string _formula = "formula";
- }
-
- internal class Attributes {
- internal const string _aboveAverage = "aboveAverage";
- internal const string _bottom = "bottom";
- internal const string _dxfId = "dxfId";
- internal const string _equalAverage = "equalAverage";
- internal const string _iconSet = "iconSet";
- internal const string _operator = "operator";
- internal const string _percent = "percent";
- internal const string _priority = "priority";
- internal const string _rank = "rank";
- internal const string _reverse = "reverse";
- internal const string _rgb = "rgb";
- internal const string _showValue = "showValue";
- internal const string _sqref = "sqref";
- internal const string _stdDev = "stdDev";
- internal const string _stopIfTrue = "stopIfTrue";
- internal const string _text = "text";
- internal const string _theme = "theme";
- internal const string _timePeriod = "timePeriod";
- internal const string _tint = "tint";
- internal const string _type = "type";
- internal const string _val = "val";
- }
-
- internal class Paths {
- // Main node and attributes
- internal const string _worksheet = "d:" + Nodes._worksheet;
-
- // <conditionalFormatting> §18.3.1.18 node
- // can appear more than once in a worksheet
- internal const string _conditionalFormatting = "d:" + Nodes._conditionalFormatting;
-
- // <cfRule> §18.3.1.10 node
- // can appear more than once in a <conditionalFormatting>
- internal const string _cfRule = "d:" + Nodes._cfRule;
-
- // <colorScale> §18.3.1.16 node
- internal const string _colorScale = "d:" + Nodes._colorScale;
-
- // <cfvo> §18.3.1.11 node
- internal const string _cfvo = "d:" + Nodes._cfvo;
-
- // <color> §18.3.1.15 node
- internal const string _color = "d:" + Nodes._color;
-
- // <dataBar> §18.3.1.28 node
- internal const string _dataBar = "d:" + Nodes._dataBar;
-
- // <iconSet> §18.3.1.49 node
- internal const string _iconSet = "d:" + Nodes._iconSet;
-
- // <formula> §18.3.1.43 node
- internal const string _formula = "d:" + Nodes._formula;
-
- // Attributes (for all the nodes)
- internal const string _aboveAverageAttribute = "@" + Attributes._aboveAverage;
- internal const string _bottomAttribute = "@" + Attributes._bottom;
- internal const string _dxfIdAttribute = "@" + Attributes._dxfId;
- internal const string _equalAverageAttribute = "@" + Attributes._equalAverage;
- internal const string _iconSetAttribute = "@" + Attributes._iconSet;
- internal const string _operatorAttribute = "@" + Attributes._operator;
- internal const string _percentAttribute = "@" + Attributes._percent;
- internal const string _priorityAttribute = "@" + Attributes._priority;
- internal const string _rankAttribute = "@" + Attributes._rank;
- internal const string _reverseAttribute = "@" + Attributes._reverse;
- internal const string _rgbAttribute = "@" + Attributes._rgb;
- internal const string _showValueAttribute = "@" + Attributes._showValue;
- internal const string _sqrefAttribute = "@" + Attributes._sqref;
- internal const string _stdDevAttribute = "@" + Attributes._stdDev;
- internal const string _stopIfTrueAttribute = "@" + Attributes._stopIfTrue;
- internal const string _textAttribute = "@" + Attributes._text;
- internal const string _themeAttribute = "@" + Attributes._theme;
- internal const string _timePeriodAttribute = "@" + Attributes._timePeriod;
- internal const string _tintAttribute = "@" + Attributes._tint;
- internal const string _typeAttribute = "@" + Attributes._type;
- internal const string _valAttribute = "@" + Attributes._val;
- }
-
- internal class RuleType {
- internal const string _aboveAverage = "aboveAverage";
- internal const string _beginsWith = "beginsWith";
- internal const string _cellIs = "cellIs";
- internal const string _colorScale = "colorScale";
- internal const string _containsBlanks = "containsBlanks";
- internal const string _containsErrors = "containsErrors";
- internal const string _containsText = "containsText";
- internal const string _dataBar = "dataBar";
- internal const string _duplicateValues = "duplicateValues";
- internal const string _endsWith = "endsWith";
- internal const string _expression = "expression";
- internal const string _iconSet = "iconSet";
- internal const string _notContainsBlanks = "notContainsBlanks";
- internal const string _notContainsErrors = "notContainsErrors";
- internal const string _notContainsText = "notContainsText";
- internal const string _timePeriod = "timePeriod";
- internal const string _top10 = "top10";
- internal const string _uniqueValues = "uniqueValues";
-
- // EPPlus Extended Types
- internal const string _aboveOrEqualAverage = "aboveOrEqualAverage";
- internal const string _aboveStdDev = "aboveStdDev";
- internal const string _belowAverage = "belowAverage";
- internal const string _belowOrEqualAverage = "belowOrEqualAverage";
- internal const string _belowStdDev = "belowStdDev";
- internal const string _between = "between";
- internal const string _bottom = "bottom";
- internal const string _bottomPercent = "bottomPercent";
- internal const string _equal = "equal";
- internal const string _greaterThan = "greaterThan";
- internal const string _greaterThanOrEqual = "greaterThanOrEqual";
- internal const string _iconSet3 = "iconSet3";
- internal const string _iconSet4 = "iconSet4";
- internal const string _iconSet5 = "iconSet5";
- internal const string _last7Days = "last7Days";
- internal const string _lastMonth = "lastMonth";
- internal const string _lastWeek = "lastWeek";
- internal const string _lessThan = "lessThan";
- internal const string _lessThanOrEqual = "lessThanOrEqual";
- internal const string _nextMonth = "nextMonth";
- internal const string _nextWeek = "nextWeek";
- internal const string _notBetween = "notBetween";
- internal const string _notEqual = "notEqual";
- internal const string _thisMonth = "thisMonth";
- internal const string _thisWeek = "thisWeek";
- internal const string _threeColorScale = "threeColorScale";
- internal const string _today = "today";
- internal const string _tomorrow = "tomorrow";
- internal const string _top = "top";
- internal const string _topPercent = "topPercent";
- internal const string _twoColorScale = "twoColorScale";
- internal const string _yesterday = "yesterday";
- }
-
- internal class CfvoType {
- internal const string _min = "min";
- internal const string _max = "max";
- internal const string _num = "num";
- internal const string _formula = "formula";
- internal const string _percent = "percent";
- internal const string _percentile = "percentile";
- }
-
- internal class Operators {
- internal const string _beginsWith = "beginsWith";
- internal const string _between = "between";
- internal const string _containsText = "containsText";
- internal const string _endsWith = "endsWith";
- internal const string _equal = "equal";
- internal const string _greaterThan = "greaterThan";
- internal const string _greaterThanOrEqual = "greaterThanOrEqual";
- internal const string _lessThan = "lessThan";
- internal const string _lessThanOrEqual = "lessThanOrEqual";
- internal const string _notBetween = "notBetween";
- internal const string _notContains = "notContains";
- internal const string _notEqual = "notEqual";
- }
-
- internal class TimePeriods {
- internal const string _last7Days = "last7Days";
- internal const string _lastMonth = "lastMonth";
- internal const string _lastWeek = "lastWeek";
- internal const string _nextMonth = "nextMonth";
- internal const string _nextWeek = "nextWeek";
- internal const string _thisMonth = "thisMonth";
- internal const string _thisWeek = "thisWeek";
- internal const string _today = "today";
- internal const string _tomorrow = "tomorrow";
- internal const string _yesterday = "yesterday";
- }
-
- internal class Colors {
- internal const string _cfvoLowValue = "#FFF8696B";
- internal const string _cfvoMiddleValue = "#FFFFEB84";
- internal const string _cfvoHighValue = "#FF63BE7B";
- }
-}
diff --git a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingEnums.cs b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingEnums.cs
deleted file mode 100644
index 8885f5c..0000000
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingEnums.cs
+++ /dev/null
@@ -1,753 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// Enum for Conditional Format Type ST_CfType §18.18.12. With some changes.
-/// </summary>
-public enum eExcelConditionalFormattingRuleType {
- /// <summary>
- /// This conditional formatting rule highlights cells that are above the average
- /// for all values in the range.
- /// </summary>
- /// <remarks>AboveAverage Excel CF Rule Type</remarks>
- AboveAverage,
-
- /// <summary>
- /// This conditional formatting rule highlights cells that are above or equal
- /// the average for all values in the range.
- /// </summary>
- /// <remarks>AboveAverage Excel CF Rule Type</remarks>
- AboveOrEqualAverage,
-
- /// <summary>
- /// This conditional formatting rule highlights cells that are below the average
- /// for all values in the range.
- /// </summary>
- /// <remarks>AboveAverage Excel CF Rule Type</remarks>
- BelowAverage,
-
- /// <summary>
- /// This conditional formatting rule highlights cells that are below or equal
- /// the average for all values in the range.
- /// </summary>
- /// <remarks>AboveAverage Excel CF Rule Type</remarks>
- BelowOrEqualAverage,
-
- /// <summary>
- /// This conditional formatting rule highlights cells that are above the standard
- /// deviationa for all values in the range.
- /// <remarks>AboveAverage Excel CF Rule Type</remarks>
- /// </summary>
- AboveStdDev,
-
- /// <summary>
- /// This conditional formatting rule highlights cells that are below the standard
- /// deviationa for all values in the range.
- /// </summary>
- /// <remarks>AboveAverage Excel CF Rule Type</remarks>
- BelowStdDev,
-
- /// <summary>
- /// This conditional formatting rule highlights cells whose values fall in the
- /// bottom N bracket as specified.
- /// </summary>
- /// <remarks>Top10 Excel CF Rule Type</remarks>
- Bottom,
-
- /// <summary>
- /// This conditional formatting rule highlights cells whose values fall in the
- /// bottom N percent as specified.
- /// </summary>
- /// <remarks>Top10 Excel CF Rule Type</remarks>
- BottomPercent,
-
- /// <summary>
- /// This conditional formatting rule highlights cells whose values fall in the
- /// top N bracket as specified.
- /// </summary>
- /// <remarks>Top10 Excel CF Rule Type</remarks>
- Top,
-
- /// <summary>
- /// This conditional formatting rule highlights cells whose values fall in the
- /// top N percent as specified.
- /// </summary>
- /// <remarks>Top10 Excel CF Rule Type</remarks>
- TopPercent,
-
- /// <summary>
- /// This conditional formatting rule highlights cells containing dates in the
- /// last 7 days.
- /// </summary>
- /// <remarks>TimePeriod Excel CF Rule Type</remarks>
- Last7Days,
-
- /// <summary>
- /// This conditional formatting rule highlights cells containing dates in the
- /// last month.
- /// </summary>
- /// <remarks>TimePeriod Excel CF Rule Type</remarks>
- LastMonth,
-
- /// <summary>
- /// This conditional formatting rule highlights cells containing dates in the
- /// last week.
- /// </summary>
- /// <remarks>TimePeriod Excel CF Rule Type</remarks>
- LastWeek,
-
- /// <summary>
- /// This conditional formatting rule highlights cells containing dates in the
- /// next month.
- /// </summary>
- /// <remarks>TimePeriod Excel CF Rule Type</remarks>
- NextMonth,
-
- /// <summary>
- /// This conditional formatting rule highlights cells containing dates in the
- /// next week.
- /// </summary>
- /// <remarks>TimePeriod Excel CF Rule Type</remarks>
- NextWeek,
-
- /// <summary>
- /// This conditional formatting rule highlights cells containing dates in this
- /// month.
- /// </summary>
- /// <remarks>TimePeriod Excel CF Rule Type</remarks>
- ThisMonth,
-
- /// <summary>
- /// This conditional formatting rule highlights cells containing dates in this
- /// week.
- /// </summary>
- /// <remarks>TimePeriod Excel CF Rule Type</remarks>
- ThisWeek,
-
- /// <summary>
- /// This conditional formatting rule highlights cells containing today dates.
- /// </summary>
- /// <remarks>TimePeriod Excel CF Rule Type</remarks>
- Today,
-
- /// <summary>
- /// This conditional formatting rule highlights cells containing tomorrow dates.
- /// </summary>
- /// <remarks>TimePeriod Excel CF Rule Type</remarks>
- Tomorrow,
-
- /// <summary>
- /// This conditional formatting rule highlights cells containing yesterday dates.
- /// </summary>
- /// <remarks>TimePeriod Excel CF Rule Type</remarks>
- Yesterday,
-
- /// <summary>
- /// This conditional formatting rule highlights cells in the range that begin with
- /// the given text.
- /// </summary>
- /// <remarks>
- /// Equivalent to using the LEFT() sheet function and comparing values.
- /// </remarks>
- /// <remarks>BeginsWith Excel CF Rule Type</remarks>
- BeginsWith,
-
- /// <summary>
- /// This conditional formatting rule highlights cells in the range between the
- /// given two formulas.
- /// </summary>
- /// <remarks>CellIs Excel CF Rule Type</remarks>
- Between,
-
- /// <summary>
- /// This conditional formatting rule highlights cells that are completely blank.
- /// </summary>
- /// <remarks>
- /// Equivalent of using LEN(TRIM()). This means that if the cell contains only
- /// characters that TRIM() would remove, then it is considered blank. An empty cell
- /// is also considered blank.
- /// </remarks>
- /// <remarks>ContainsBlanks Excel CF Rule Type</remarks>
- ContainsBlanks,
-
- /// <summary>
- /// This conditional formatting rule highlights cells with formula errors.
- /// </summary>
- /// <remarks>
- /// Equivalent to using ISERROR() sheet function to determine if there is
- /// a formula error.
- /// </remarks>
- /// <remarks>ContainsErrors Excel CF Rule Type</remarks>
- ContainsErrors,
-
- /// <summary>
- /// This conditional formatting rule highlights cells in the range that begin with
- /// the given text.
- /// </summary>
- /// <remarks>
- /// Equivalent to using the LEFT() sheet function and comparing values.
- /// </remarks>
- /// <remarks>ContainsText Excel CF Rule Type</remarks>
- ContainsText,
-
- /// <summary>
- /// This conditional formatting rule highlights duplicated values.
- /// </summary>
- /// <remarks>DuplicateValues Excel CF Rule Type</remarks>
- DuplicateValues,
-
- /// <summary>
- /// This conditional formatting rule highlights cells ending with given text.
- /// </summary>
- /// <remarks>
- /// Equivalent to using the RIGHT() sheet function and comparing values.
- /// </remarks>
- /// <remarks>EndsWith Excel CF Rule Type</remarks>
- EndsWith,
-
- /// <summary>
- /// This conditional formatting rule highlights cells equals to with given formula.
- /// </summary>
- /// <remarks>CellIs Excel CF Rule Type</remarks>
- Equal,
-
- /// <summary>
- /// This conditional formatting rule contains a formula to evaluate. When the
- /// formula result is true, the cell is highlighted.
- /// </summary>
- /// <remarks>Expression Excel CF Rule Type</remarks>
- Expression,
-
- /// <summary>
- /// This conditional formatting rule highlights cells greater than the given formula.
- /// </summary>
- /// <remarks>CellIs Excel CF Rule Type</remarks>
- GreaterThan,
-
- /// <summary>
- /// This conditional formatting rule highlights cells greater than or equal the
- /// given formula.
- /// </summary>
- /// <remarks>CellIs Excel CF Rule Type</remarks>
- GreaterThanOrEqual,
-
- /// <summary>
- /// This conditional formatting rule highlights cells less than the given formula.
- /// </summary>
- /// <remarks>CellIs Excel CF Rule Type</remarks>
- LessThan,
-
- /// <summary>
- /// This conditional formatting rule highlights cells less than or equal the
- /// given formula.
- /// </summary>
- /// <remarks>CellIs Excel CF Rule Type</remarks>
- LessThanOrEqual,
-
- /// <summary>
- /// This conditional formatting rule highlights cells outside the range in
- /// given two formulas.
- /// </summary>
- /// <remarks>CellIs Excel CF Rule Type</remarks>
- NotBetween,
-
- /// <summary>
- /// This conditional formatting rule highlights cells that does not contains the
- /// given formula.
- /// </summary>
- /// <remarks>CellIs Excel CF Rule Type</remarks>
- NotContains,
-
- /// <summary>
- /// This conditional formatting rule highlights cells that are not blank.
- /// </summary>
- /// <remarks>
- /// Equivalent of using LEN(TRIM()). This means that if the cell contains only
- /// characters that TRIM() would remove, then it is considered blank. An empty cell
- /// is also considered blank.
- /// </remarks>
- /// <remarks>NotContainsBlanks Excel CF Rule Type</remarks>
- NotContainsBlanks,
-
- /// <summary>
- /// This conditional formatting rule highlights cells without formula errors.
- /// </summary>
- /// <remarks>
- /// Equivalent to using ISERROR() sheet function to determine if there is a
- /// formula error.
- /// </remarks>
- /// <remarks>NotContainsErrors Excel CF Rule Type</remarks>
- NotContainsErrors,
-
- /// <summary>
- /// This conditional formatting rule highlights cells that do not contain
- /// the given text.
- /// </summary>
- /// <remarks>
- /// Equivalent to using the SEARCH() sheet function.
- /// </remarks>
- /// <remarks>NotContainsText Excel CF Rule Type</remarks>
- NotContainsText,
-
- /// <summary>
- /// This conditional formatting rule highlights cells not equals to with
- /// given formula.
- /// </summary>
- /// <remarks>CellIs Excel CF Rule Type</remarks>
- NotEqual,
-
- /// <summary>
- /// This conditional formatting rule highlights unique values in the range.
- /// </summary>
- /// <remarks>UniqueValues Excel CF Rule Type</remarks>
- UniqueValues,
-
- /// <summary>
- /// Three Color Scale (Low, Middle and High Color Scale)
- /// </summary>
- /// <remarks>ColorScale Excel CF Rule Type</remarks>
- ThreeColorScale,
-
- /// <summary>
- /// Two Color Scale (Low and High Color Scale)
- /// </summary>
- /// <remarks>ColorScale Excel CF Rule Type</remarks>
- TwoColorScale,
-
- /// <summary>
- /// This conditional formatting rule applies a 3 set icons to cells according
- /// to their values.
- /// </summary>
- /// <remarks>IconSet Excel CF Rule Type</remarks>
- ThreeIconSet,
-
- /// <summary>
- /// This conditional formatting rule applies a 4 set icons to cells according
- /// to their values.
- /// </summary>
- /// <remarks>IconSet Excel CF Rule Type</remarks>
- FourIconSet,
-
- /// <summary>
- /// This conditional formatting rule applies a 5 set icons to cells according
- /// to their values.
- /// </summary>
- /// <remarks>IconSet Excel CF Rule Type</remarks>
- FiveIconSet,
-
- /// <summary>
- /// This conditional formatting rule displays a gradated data bar in the range of cells.
- /// </summary>
- /// <remarks>DataBar Excel CF Rule Type</remarks>
- DataBar,
-}
-
-/// <summary>
-/// Enum for Conditional Format Value Object Type ST_CfvoType §18.18.13
-/// </summary>
-public enum eExcelConditionalFormattingValueObjectType {
- /// <summary>
- /// Formula
- /// </summary>
- Formula,
-
- /// <summary>
- /// Maximum Value
- /// </summary>
- Max,
-
- /// <summary>
- /// Minimum Value
- /// </summary>
- Min,
-
- /// <summary>
- /// Number Value
- /// </summary>
- Num,
-
- /// <summary>
- /// Percent
- /// </summary>
- Percent,
-
- /// <summary>
- /// Percentile
- /// </summary>
- Percentile,
-}
-
-/// <summary>
-/// Enum for Conditional Formatting Value Object Position
-/// </summary>
-public enum eExcelConditionalFormattingValueObjectPosition {
- /// <summary>
- /// The lower position for both TwoColorScale and ThreeColorScale
- /// </summary>
- Low,
-
- /// <summary>
- /// The middle position only for ThreeColorScale
- /// </summary>
- Middle,
-
- /// <summary>
- /// The highest position for both TwoColorScale and ThreeColorScale
- /// </summary>
- High,
-}
-
-/// <summary>
-/// Enum for Conditional Formatting Value Object Node Type
-/// </summary>
-public enum eExcelConditionalFormattingValueObjectNodeType {
- /// <summary>
- /// 'cfvo' node
- /// </summary>
- Cfvo,
-
- /// <summary>
- /// 'color' node
- /// </summary>
- Color,
-}
-
-/// <summary>
-/// Enum for Conditional Formatting Operartor Type ST_ConditionalFormattingOperator §18.18.15
-/// </summary>
-public enum eExcelConditionalFormattingOperatorType {
- /// <summary>
- /// Begins With. 'Begins with' operator
- /// </summary>
- BeginsWith,
-
- /// <summary>
- /// Between. 'Between' operator
- /// </summary>
- Between,
-
- /// <summary>
- /// Contains. 'Contains' operator
- /// </summary>
- ContainsText,
-
- /// <summary>
- /// Ends With. 'Ends with' operator
- /// </summary>
- EndsWith,
-
- /// <summary>
- /// Equal. 'Equal to' operator
- /// </summary>
- Equal,
-
- /// <summary>
- /// Greater Than. 'Greater than' operator
- /// </summary>
- GreaterThan,
-
- /// <summary>
- /// Greater Than Or Equal. 'Greater than or equal to' operator
- /// </summary>
- GreaterThanOrEqual,
-
- /// <summary>
- /// Less Than. 'Less than' operator
- /// </summary>
- LessThan,
-
- /// <summary>
- /// Less Than Or Equal. 'Less than or equal to' operator
- /// </summary>
- LessThanOrEqual,
-
- /// <summary>
- /// Not Between. 'Not between' operator
- /// </summary>
- NotBetween,
-
- /// <summary>
- /// Does Not Contain. 'Does not contain' operator
- /// </summary>
- NotContains,
-
- /// <summary>
- /// Not Equal. 'Not equal to' operator
- /// </summary>
- NotEqual,
-}
-
-/// <summary>
-/// Enum for Conditional Formatting Time Period Type ST_TimePeriod §18.18.82
-/// </summary>
-public enum eExcelConditionalFormattingTimePeriodType {
- /// <summary>
- /// Last 7 Days. A date in the last seven days.
- /// </summary>
- Last7Days,
-
- /// <summary>
- /// Last Month. A date occuring in the last calendar month.
- /// </summary>
- LastMonth,
-
- /// <summary>
- /// Last Week. A date occuring last week.
- /// </summary>
- LastWeek,
-
- /// <summary>
- /// Next Month. A date occuring in the next calendar month.
- /// </summary>
- NextMonth,
-
- /// <summary>
- /// Next Week. A date occuring next week.
- /// </summary>
- NextWeek,
-
- /// <summary>
- /// This Month. A date occuring in this calendar month.
- /// </summary>
- ThisMonth,
-
- /// <summary>
- /// This Week. A date occuring this week.
- /// </summary>
- ThisWeek,
-
- /// <summary>
- /// Today. Today's date.
- /// </summary>
- Today,
-
- /// <summary>
- /// Tomorrow. Tomorrow's date.
- /// </summary>
- Tomorrow,
-
- /// <summary>
- /// Yesterday. Yesterday's date.
- /// </summary>
- Yesterday,
-}
-
-/// <summary>
-/// 18.18.42 ST_IconSetType (Icon Set Type) - Only 3 icons
-/// </summary>
-public enum eExcelconditionalFormatting3IconsSetType {
- /// <summary>
- /// (3 Arrows) 3 arrows icon set.
- /// </summary>
- Arrows,
-
- /// <summary>
- /// (3 Arrows (Gray)) 3 gray arrows icon set.
- /// </summary>
- ArrowsGray,
-
- /// <summary>
- /// (3 Flags) 3 flags icon set.
- /// </summary>
- Flags,
-
- /// <summary>
- /// (3 Signs) 3 signs icon set.
- /// </summary>
- Signs,
-
- /// <summary>
- /// (3 Symbols Circled) 3 symbols icon set.
- /// </summary>
- Symbols,
-
- /// <summary>
- /// (3 Symbols) 3 Symbols icon set.
- /// </summary>
- Symbols2,
-
- /// <summary>
- /// (3 Traffic Lights) 3 traffic lights icon set (#1).
- /// </summary>
- TrafficLights1,
-
- /// <summary>
- /// (3 Traffic Lights Black) 3 traffic lights icon set with thick black border.
- /// </summary>
- TrafficLights2,
-}
-
-/// <summary>
-/// 18.18.42 ST_IconSetType (Icon Set Type) - Only 4 icons
-/// </summary>
-public enum eExcelconditionalFormatting4IconsSetType {
- /// <summary>
- /// (4 Arrows) 4 arrows icon set.
- /// </summary>
- Arrows,
-
- /// <summary>
- /// (4 Arrows (Gray)) 4 gray arrows icon set.
- /// </summary>
- ArrowsGray,
-
- /// <summary>
- /// (4 Ratings) 4 ratings icon set.
- /// </summary>
- Rating,
-
- /// <summary>
- /// (4 Red To Black) 4 'red to black' icon set.
- /// </summary>
- RedToBlack,
-
- /// <summary>
- /// (4 Traffic Lights) 4 traffic lights icon set.
- /// </summary>
- TrafficLights,
-}
-
-/// <summary>
-/// 18.18.42 ST_IconSetType (Icon Set Type) - Only 5 icons
-/// </summary>
-public enum eExcelconditionalFormatting5IconsSetType {
- /// <summary>
- /// (5 Arrows) 5 arrows icon set.
- /// </summary>
- Arrows,
-
- /// <summary>
- /// (5 Arrows (Gray)) 5 gray arrows icon set.
- /// </summary>
- ArrowsGray,
-
- /// <summary>
- /// (5 Quarters) 5 quarters icon set.
- /// </summary>
- Quarters,
-
- /// <summary>
- /// (5 Ratings Icon Set) 5 rating icon set.
- /// </summary>
- Rating,
-}
-
-/// <summary>
-/// 18.18.42 ST_IconSetType (Icon Set Type)
-/// </summary>
-public enum eExcelconditionalFormattingIconsSetType {
- /// <summary>
- /// (3 Arrows) 3 arrows icon set.
- /// </summary>
- ThreeArrows,
-
- /// <summary>
- /// (3 Arrows (Gray)) 3 gray arrows icon set.
- /// </summary>
- ThreeArrowsGray,
-
- /// <summary>
- /// (3 Flags) 3 flags icon set.
- /// </summary>
- ThreeFlags,
-
- /// <summary>
- /// (3 Signs) 3 signs icon set.
- /// </summary>
- ThreeSigns,
-
- /// <summary>
- /// (3 Symbols Circled) 3 symbols icon set.
- /// </summary>
- ThreeSymbols,
-
- /// <summary>
- /// (3 Symbols) 3 Symbols icon set.
- /// </summary>
- ThreeSymbols2,
-
- /// <summary>
- /// (3 Traffic Lights) 3 traffic lights icon set (#1).
- /// </summary>
- ThreeTrafficLights1,
-
- /// <summary>
- /// (3 Traffic Lights Black) 3 traffic lights icon set with thick black border.
- /// </summary>
- ThreeTrafficLights2,
-
- /// <summary>
- /// (4 Arrows) 4 arrows icon set.
- /// </summary>
- FourArrows,
-
- /// <summary>
- /// (4 Arrows (Gray)) 4 gray arrows icon set.
- /// </summary>
- FourArrowsGray,
-
- /// <summary>
- /// (4 Ratings) 4 ratings icon set.
- /// </summary>
- FourRating,
-
- /// <summary>
- /// (4 Red To Black) 4 'red to black' icon set.
- /// </summary>
- FourRedToBlack,
-
- /// <summary>
- /// (4 Traffic Lights) 4 traffic lights icon set.
- /// </summary>
- FourTrafficLights,
-
- /// <summary>
- /// (5 Arrows) 5 arrows icon set.
- /// </summary>
- FiveArrows,
-
- /// <summary>
- /// (5 Arrows (Gray)) 5 gray arrows icon set.
- /// </summary>
- FiveArrowsGray,
-
- /// <summary>
- /// (5 Quarters) 5 quarters icon set.
- /// </summary>
- FiveQuarters,
-
- /// <summary>
- /// (5 Ratings Icon Set) 5 rating icon set.
- /// </summary>
- FiveRating,
-}
diff --git a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingHelper.cs b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingHelper.cs
deleted file mode 100644
index ba97c3d..0000000
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingHelper.cs
+++ /dev/null
@@ -1,204 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System;
-using System.Globalization;
-using System.Text.RegularExpressions;
-using System.Xml;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// Conditional formatting helper
-/// </summary>
-internal static class ExcelConditionalFormattingHelper {
- /// <summary>
- /// Check and fix an address (string address)
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public static string CheckAndFixRangeAddress(string address) {
- if (address.Contains(',')) {
- throw new FormatException(
- ExcelConditionalFormattingConstants.Errors._commaSeparatedAddresses);
- }
-
- address = address.ToUpper(CultureInfo.InvariantCulture);
-
- if (Regex.IsMatch(address, "[A-Z]+:[A-Z]+")) {
- address = AddressUtility.ParseEntireColumnSelections(address);
- }
-
- return address;
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="node"></param>
- /// <param name="attribute"></param>
- /// <returns></returns>
- public static string GetAttributeString(XmlNode node, string attribute) {
- try {
- var value = node.Attributes[attribute].Value;
- return value ?? string.Empty;
- } catch {
- return string.Empty;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="node"></param>
- /// <param name="attribute"></param>
- /// <returns></returns>
- public static int GetAttributeInt(XmlNode node, string attribute) {
- try {
- var value = node.Attributes[attribute].Value;
- return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
- } catch {
- return int.MinValue;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="node"></param>
- /// <param name="attribute"></param>
- /// <returns></returns>
- public static int? GetAttributeIntNullable(XmlNode node, string attribute) {
- try {
- if (node.Attributes[attribute] == null) {
- return null;
- }
- var value = node.Attributes[attribute].Value;
- return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
- } catch {
- return null;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="node"></param>
- /// <param name="attribute"></param>
- /// <returns></returns>
- public static bool GetAttributeBool(XmlNode node, string attribute) {
- try {
- var value = node.Attributes[attribute].Value;
- return (value == "1"
- || value == "-1"
- || value.Equals("TRUE", StringComparison.InvariantCultureIgnoreCase));
- } catch {
- return false;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="node"></param>
- /// <param name="attribute"></param>
- /// <returns></returns>
- public static bool? GetAttributeBoolNullable(XmlNode node, string attribute) {
- try {
- if (node.Attributes[attribute] == null) {
- return null;
- }
- var value = node.Attributes[attribute].Value;
- return (value == "1"
- || value == "-1"
- || value.Equals("TRUE", StringComparison.InvariantCultureIgnoreCase));
- } catch {
- return null;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="node"></param>
- /// <param name="attribute"></param>
- /// <returns></returns>
- public static double GetAttributeDouble(XmlNode node, string attribute) {
- try {
- var value = node.Attributes[attribute].Value;
- return double.Parse(value, NumberStyles.Number, CultureInfo.InvariantCulture);
- } catch {
- return double.NaN;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="node"></param>
- /// <param name="attribute"></param>
- /// <returns></returns>
- public static decimal GetAttributeDecimal(XmlNode node, string attribute) {
- try {
- var value = node.Attributes[attribute].Value;
- return decimal.Parse(value, NumberStyles.Any, CultureInfo.InvariantCulture);
- } catch {
- return decimal.MinValue;
- }
- }
-
- /// <summary>
- /// Encode to XML (special characteres: ' " > < &)
- /// </summary>
- /// <param name="s"></param>
- /// <returns></returns>
- public static string EncodeXml(this string s) {
- return s.Replace("&", "&")
- .Replace("<", "<")
- .Replace(">", ">")
- .Replace("\"", """)
- .Replace("'", "'");
- }
-
- /// <summary>
- /// Decode from XML (special characteres: ' " > < &)
- /// </summary>
- /// <param name="s"></param>
- /// <returns></returns>
- public static string DecodeXml(this string s) {
- return s.Replace("'", "'")
- .Replace("\"", """)
- .Replace(">", ">")
- .Replace("<", "<")
- .Replace("&", "&");
- }
-}
diff --git a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingIconDatabarValue.cs b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingIconDatabarValue.cs
deleted file mode 100644
index c38d095..0000000
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingIconDatabarValue.cs
+++ /dev/null
@@ -1,290 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Immutable;
-using System.Drawing;
-using System.Globalization;
-using System.Xml;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// 18.3.1.11 cfvo (Conditional Format Value Object)
-/// Describes the values of the interpolation points in a gradient scale.
-/// </summary>
-public class ExcelConditionalFormattingIconDataBarValue : XmlHelper {
- private eExcelConditionalFormattingRuleType _ruleType;
- private readonly ExcelWorksheet _worksheet;
-
- /// <summary>
- /// Initialize the cfvo (§18.3.1.11) node
- /// </summary>
- /// <param name="type"></param>
- /// <param name="value"></param>
- /// <param name="formula"></param>
- /// <param name="ruleType"></param>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode">The cfvo (§18.3.1.11) node parent. Can be any of the following:
- /// colorScale (§18.3.1.16); dataBar (§18.3.1.28); iconSet (§18.3.1.49)</param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingIconDataBarValue(
- eExcelConditionalFormattingValueObjectType type,
- double value,
- string formula,
- eExcelConditionalFormattingRuleType ruleType,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : this(ruleType, address, worksheet, itemElementNode, namespaceManager) {
- Require.Argument(priority).IsInRange(1, int.MaxValue, "priority");
-
- // Check if the parent does not exists
- if (itemElementNode == null) {
- // Get the parent node path by the rule type
- string parentNodePath = ExcelConditionalFormattingValueObjectType.GetParentPathByRuleType(
- ruleType);
-
- // Check for en error (rule type does not have <cfvo>)
- if (parentNodePath == string.Empty) {
- throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoParentNode);
- }
-
- // Point to the <cfvo> parent node
- itemElementNode = _worksheet.WorksheetXml.SelectSingleNode(
- string.Format(
- "//{0}[{1}='{2}']/{3}[{4}='{5}']/{6}",
- // {0}
- ExcelConditionalFormattingConstants.Paths._conditionalFormatting,
- // {1}
- ExcelConditionalFormattingConstants.Paths._sqrefAttribute,
- // {2}
- address.Address,
- // {3}
- ExcelConditionalFormattingConstants.Paths._cfRule,
- // {4}
- ExcelConditionalFormattingConstants.Paths._priorityAttribute,
- // {5}
- priority,
- // {6}
- parentNodePath),
- _worksheet.NameSpaceManager);
-
- // Check for en error (rule type does not have <cfvo>)
- if (itemElementNode == null) {
- throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoParentNode);
- }
- }
-
- TopNode = itemElementNode;
-
- // Save the attributes
- RuleType = ruleType;
- Type = type;
- Value = value;
- Formula = formula;
- }
-
- protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
- ExcelConditionalFormattingConstants.Nodes._cfvo,
- ];
-
- /// <summary>
- /// Initialize the cfvo (§18.3.1.11) node
- /// </summary>
- /// <param name="ruleType"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode">The cfvo (§18.3.1.11) node parent. Can be any of the following:
- /// colorScale (§18.3.1.16); dataBar (§18.3.1.28); iconSet (§18.3.1.49)</param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingIconDataBarValue(
- eExcelConditionalFormattingRuleType ruleType,
- ExcelAddress address,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(namespaceManager, itemElementNode) {
- Require.Argument(address).IsNotNull("address");
- Require.Argument(worksheet).IsNotNull("worksheet");
-
- // Save the worksheet for private methods to use
- _worksheet = worksheet;
-
- //Check if the parent does not exists
- if (itemElementNode == null) {
- // Get the parent node path by the rule type
- string parentNodePath = ExcelConditionalFormattingValueObjectType.GetParentPathByRuleType(
- ruleType);
-
- // Check for en error (rule type does not have <cfvo>)
- if (parentNodePath == string.Empty) {
- throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoParentNode);
- }
- }
- RuleType = ruleType;
- }
-
- /// <summary>
- /// Initialize the <see cref="ExcelConditionalFormattingColorScaleValue"/>
- /// </summary>
- /// <param name="type"></param>
- /// <param name="value"></param>
- /// <param name="formula"></param>
- /// <param name="ruleType"></param>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingIconDataBarValue(
- eExcelConditionalFormattingValueObjectType type,
- double value,
- string formula,
- eExcelConditionalFormattingRuleType ruleType,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNamespaceManager namespaceManager)
- : this(
- type,
- value,
- formula,
- ruleType,
- address,
- priority,
- worksheet,
- null,
- namespaceManager) {}
-
- /// <summary>
- /// Initialize the <see cref="ExcelConditionalFormattingColorScaleValue"/>
- /// </summary>
- /// <param name="type"></param>
- /// <param name="color"></param>
- /// <param name="ruleType"></param>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingIconDataBarValue(
- eExcelConditionalFormattingValueObjectType type,
- Color color,
- eExcelConditionalFormattingRuleType ruleType,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNamespaceManager namespaceManager)
- : this(type, 0, null, ruleType, address, priority, worksheet, null, namespaceManager) {}
-
- /// <summary>
- ///
- /// </summary>
- internal eExcelConditionalFormattingRuleType RuleType {
- get => _ruleType;
- set => _ruleType = value;
- }
-
- /// <summary>
- ///
- /// </summary>
- public eExcelConditionalFormattingValueObjectType Type {
- get {
- var typeAttribute = GetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths._typeAttribute);
-
- return ExcelConditionalFormattingValueObjectType.GetTypeByAttrbiute(typeAttribute);
- }
- set {
- if ((_ruleType == eExcelConditionalFormattingRuleType.ThreeIconSet
- || _ruleType == eExcelConditionalFormattingRuleType.FourIconSet
- || _ruleType == eExcelConditionalFormattingRuleType.FiveIconSet)
- && (value == eExcelConditionalFormattingValueObjectType.Min
- || value == eExcelConditionalFormattingValueObjectType.Max)) {
- throw (new ArgumentException("Value type can't be Min or Max for icon sets"));
- }
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths._typeAttribute,
- value.ToString().ToLower(CultureInfo.InvariantCulture));
- }
- }
-
- /// <summary>
- /// Get/Set the 'cfvo' node @val attribute
- /// </summary>
- public Double Value {
- get {
- if ((Type == eExcelConditionalFormattingValueObjectType.Num)
- || (Type == eExcelConditionalFormattingValueObjectType.Percent)
- || (Type == eExcelConditionalFormattingValueObjectType.Percentile)) {
- return GetXmlNodeDouble(ExcelConditionalFormattingConstants.Paths._valAttribute);
- }
- return 0;
- }
- set {
- string valueToStore = string.Empty;
-
- // Only some types use the @val attribute
- if ((Type == eExcelConditionalFormattingValueObjectType.Num)
- || (Type == eExcelConditionalFormattingValueObjectType.Percent)
- || (Type == eExcelConditionalFormattingValueObjectType.Percentile)) {
- valueToStore = value.ToString(CultureInfo.InvariantCulture);
- }
-
- SetXmlNodeString(ExcelConditionalFormattingConstants.Paths._valAttribute, valueToStore);
- }
- }
-
- /// <summary>
- /// Get/Set the Formula of the Object Value (uses the same attribute as the Value)
- /// </summary>
- public string Formula {
- get {
- // Return empty if the Object Value type is not Formula
- if (Type != eExcelConditionalFormattingValueObjectType.Formula) {
- return string.Empty;
- }
-
- // Excel stores the formula in the @val attribute
- return GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._valAttribute);
- }
- set {
- // Only store the formula if the Object Value type is Formula
- if (Type == eExcelConditionalFormattingValueObjectType.Formula) {
- SetXmlNodeString(ExcelConditionalFormattingConstants.Paths._valAttribute, value);
- }
- }
- }
-}
diff --git a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingOperatorType.cs b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingOperatorType.cs
deleted file mode 100644
index c513d8d..0000000
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingOperatorType.cs
+++ /dev/null
@@ -1,131 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-17
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// Functions related to the <see cref="ExcelConditionalFormattingOperatorType"/>
-/// </summary>
-internal static class ExcelConditionalFormattingOperatorType {
- /// <summary>
- ///
- /// </summary>
- /// <param name="type"></param>
- /// <returns></returns>
- internal static string GetAttributeByType(eExcelConditionalFormattingOperatorType type) {
- switch (type) {
- case eExcelConditionalFormattingOperatorType.BeginsWith:
- return ExcelConditionalFormattingConstants.Operators._beginsWith;
-
- case eExcelConditionalFormattingOperatorType.Between:
- return ExcelConditionalFormattingConstants.Operators._between;
-
- case eExcelConditionalFormattingOperatorType.ContainsText:
- return ExcelConditionalFormattingConstants.Operators._containsText;
-
- case eExcelConditionalFormattingOperatorType.EndsWith:
- return ExcelConditionalFormattingConstants.Operators._endsWith;
-
- case eExcelConditionalFormattingOperatorType.Equal:
- return ExcelConditionalFormattingConstants.Operators._equal;
-
- case eExcelConditionalFormattingOperatorType.GreaterThan:
- return ExcelConditionalFormattingConstants.Operators._greaterThan;
-
- case eExcelConditionalFormattingOperatorType.GreaterThanOrEqual:
- return ExcelConditionalFormattingConstants.Operators._greaterThanOrEqual;
-
- case eExcelConditionalFormattingOperatorType.LessThan:
- return ExcelConditionalFormattingConstants.Operators._lessThan;
-
- case eExcelConditionalFormattingOperatorType.LessThanOrEqual:
- return ExcelConditionalFormattingConstants.Operators._lessThanOrEqual;
-
- case eExcelConditionalFormattingOperatorType.NotBetween:
- return ExcelConditionalFormattingConstants.Operators._notBetween;
-
- case eExcelConditionalFormattingOperatorType.NotContains:
- return ExcelConditionalFormattingConstants.Operators._notContains;
-
- case eExcelConditionalFormattingOperatorType.NotEqual:
- return ExcelConditionalFormattingConstants.Operators._notEqual;
- }
-
- return string.Empty;
- }
-
- /// <summary>
- ///
- /// </summary>
- /// param name="attribute"
- /// <returns></returns>
- internal static eExcelConditionalFormattingOperatorType GetTypeByAttribute(string attribute) {
- switch (attribute) {
- case ExcelConditionalFormattingConstants.Operators._beginsWith:
- return eExcelConditionalFormattingOperatorType.BeginsWith;
-
- case ExcelConditionalFormattingConstants.Operators._between:
- return eExcelConditionalFormattingOperatorType.Between;
-
- case ExcelConditionalFormattingConstants.Operators._containsText:
- return eExcelConditionalFormattingOperatorType.ContainsText;
-
- case ExcelConditionalFormattingConstants.Operators._endsWith:
- return eExcelConditionalFormattingOperatorType.EndsWith;
-
- case ExcelConditionalFormattingConstants.Operators._equal:
- return eExcelConditionalFormattingOperatorType.Equal;
-
- case ExcelConditionalFormattingConstants.Operators._greaterThan:
- return eExcelConditionalFormattingOperatorType.GreaterThan;
-
- case ExcelConditionalFormattingConstants.Operators._greaterThanOrEqual:
- return eExcelConditionalFormattingOperatorType.GreaterThanOrEqual;
-
- case ExcelConditionalFormattingConstants.Operators._lessThan:
- return eExcelConditionalFormattingOperatorType.LessThan;
-
- case ExcelConditionalFormattingConstants.Operators._lessThanOrEqual:
- return eExcelConditionalFormattingOperatorType.LessThanOrEqual;
-
- case ExcelConditionalFormattingConstants.Operators._notBetween:
- return eExcelConditionalFormattingOperatorType.NotBetween;
-
- case ExcelConditionalFormattingConstants.Operators._notContains:
- return eExcelConditionalFormattingOperatorType.NotContains;
-
- case ExcelConditionalFormattingConstants.Operators._notEqual:
- return eExcelConditionalFormattingOperatorType.NotEqual;
- }
-
- throw new(ExcelConditionalFormattingConstants.Errors._unexistentOperatorTypeAttribute);
- }
-}
diff --git a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingRuleFactory.cs b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingRuleFactory.cs
deleted file mode 100644
index 6bc7563..0000000
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingRuleFactory.cs
+++ /dev/null
@@ -1,359 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting 2012-04-03
- *******************************************************************************/
-
-using System;
-using System.Xml;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// Factory class for ExcelConditionalFormatting.
-/// </summary>
-internal static class ExcelConditionalFormattingRuleFactory {
- public static ExcelConditionalFormattingRule Create(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode) {
- Require.Argument(type);
- Require.Argument(address).IsNotNull("address");
- Require.Argument(priority).IsInRange(1, int.MaxValue, "priority");
- Require.Argument(worksheet).IsNotNull("worksheet");
-
- // According the conditional formatting rule type
- switch (type) {
- case eExcelConditionalFormattingRuleType.AboveAverage:
- return new ExcelConditionalFormattingAboveAverage(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.AboveOrEqualAverage:
- return new ExcelConditionalFormattingAboveOrEqualAverage(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.BelowAverage:
- return new ExcelConditionalFormattingBelowAverage(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.BelowOrEqualAverage:
- return new ExcelConditionalFormattingBelowOrEqualAverage(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.AboveStdDev:
- return new ExcelConditionalFormattingAboveStdDev(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.BelowStdDev:
- return new ExcelConditionalFormattingBelowStdDev(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.Bottom:
- return new ExcelConditionalFormattingBottom(address, priority, worksheet, itemElementNode);
-
- case eExcelConditionalFormattingRuleType.BottomPercent:
- return new ExcelConditionalFormattingBottomPercent(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.Top:
- return new ExcelConditionalFormattingTop(address, priority, worksheet, itemElementNode);
-
- case eExcelConditionalFormattingRuleType.TopPercent:
- return new ExcelConditionalFormattingTopPercent(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.Last7Days:
- return new ExcelConditionalFormattingLast7Days(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.LastMonth:
- return new ExcelConditionalFormattingLastMonth(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.LastWeek:
- return new ExcelConditionalFormattingLastWeek(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.NextMonth:
- return new ExcelConditionalFormattingNextMonth(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.NextWeek:
- return new ExcelConditionalFormattingNextWeek(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.ThisMonth:
- return new ExcelConditionalFormattingThisMonth(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.ThisWeek:
- return new ExcelConditionalFormattingThisWeek(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.Today:
- return new ExcelConditionalFormattingToday(address, priority, worksheet, itemElementNode);
-
- case eExcelConditionalFormattingRuleType.Tomorrow:
- return new ExcelConditionalFormattingTomorrow(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.Yesterday:
- return new ExcelConditionalFormattingYesterday(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.BeginsWith:
- return new ExcelConditionalFormattingBeginsWith(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.Between:
- return new ExcelConditionalFormattingBetween(address, priority, worksheet, itemElementNode);
-
- case eExcelConditionalFormattingRuleType.ContainsBlanks:
- return new ExcelConditionalFormattingContainsBlanks(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.ContainsErrors:
- return new ExcelConditionalFormattingContainsErrors(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.ContainsText:
- return new ExcelConditionalFormattingContainsText(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.DuplicateValues:
- return new ExcelConditionalFormattingDuplicateValues(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.EndsWith:
- return new ExcelConditionalFormattingEndsWith(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.Equal:
- return new ExcelConditionalFormattingEqual(address, priority, worksheet, itemElementNode);
-
- case eExcelConditionalFormattingRuleType.Expression:
- return new ExcelConditionalFormattingExpression(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.GreaterThan:
- return new ExcelConditionalFormattingGreaterThan(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.GreaterThanOrEqual:
- return new ExcelConditionalFormattingGreaterThanOrEqual(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.LessThan:
- return new ExcelConditionalFormattingLessThan(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.LessThanOrEqual:
- return new ExcelConditionalFormattingLessThanOrEqual(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.NotBetween:
- return new ExcelConditionalFormattingNotBetween(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.NotContainsBlanks:
- return new ExcelConditionalFormattingNotContainsBlanks(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.NotContainsErrors:
- return new ExcelConditionalFormattingNotContainsErrors(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.NotContainsText:
- return new ExcelConditionalFormattingNotContainsText(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.NotEqual:
- return new ExcelConditionalFormattingNotEqual(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.UniqueValues:
- return new ExcelConditionalFormattingUniqueValues(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.ThreeColorScale:
- return new ExcelConditionalFormattingThreeColorScale(
- address,
- priority,
- worksheet,
- itemElementNode);
-
- case eExcelConditionalFormattingRuleType.TwoColorScale:
- return new ExcelConditionalFormattingTwoColorScale(
- address,
- priority,
- worksheet,
- itemElementNode);
- case eExcelConditionalFormattingRuleType.ThreeIconSet:
- return new ExcelConditionalFormattingThreeIconSet(
- address,
- priority,
- worksheet,
- itemElementNode,
- null);
- case eExcelConditionalFormattingRuleType.FourIconSet:
- return new ExcelConditionalFormattingFourIconSet(
- address,
- priority,
- worksheet,
- itemElementNode,
- null);
- case eExcelConditionalFormattingRuleType.FiveIconSet:
- return new ExcelConditionalFormattingFiveIconSet(
- address,
- priority,
- worksheet,
- itemElementNode,
- null);
- case eExcelConditionalFormattingRuleType.DataBar:
- return new ExcelConditionalFormattingDataBar(
- eExcelConditionalFormattingRuleType.DataBar,
- address,
- priority,
- worksheet,
- itemElementNode,
- null);
-
- //TODO: Add DataBar
- }
-
- throw new InvalidOperationException(
- string.Format(
- ExcelConditionalFormattingConstants.Errors._nonSupportedRuleType,
- type.ToString()));
- }
-}
diff --git a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingRuleType.cs b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingRuleType.cs
deleted file mode 100644
index 8168caa..0000000
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingRuleType.cs
+++ /dev/null
@@ -1,494 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// Functions related to the ExcelConditionalFormattingRule
-/// </summary>
-internal static class ExcelConditionalFormattingRuleType {
- /// <summary>
- ///
- /// </summary>
- /// <param name="attribute"></param>
- /// <param name="topNode"></param>
- /// <param name="nameSpaceManager"></param>
- /// <returns></returns>
- internal static eExcelConditionalFormattingRuleType GetTypeByAttrbiute(
- string attribute,
- XmlNode topNode,
- XmlNamespaceManager nameSpaceManager) {
- switch (attribute) {
- case ExcelConditionalFormattingConstants.RuleType._aboveAverage:
- return GetAboveAverageType(topNode, nameSpaceManager);
-
- case ExcelConditionalFormattingConstants.RuleType._top10:
- return GetTop10Type(topNode, nameSpaceManager);
-
- case ExcelConditionalFormattingConstants.RuleType._timePeriod:
- return GetTimePeriodType(topNode, nameSpaceManager);
- case ExcelConditionalFormattingConstants.RuleType._cellIs:
- return GetCellIs((XmlElement)topNode);
- case ExcelConditionalFormattingConstants.RuleType._beginsWith:
- return eExcelConditionalFormattingRuleType.BeginsWith;
-
- //case ExcelConditionalFormattingConstants.RuleType.Between:
- // return eExcelConditionalFormattingRuleType.Between;
-
- case ExcelConditionalFormattingConstants.RuleType._containsBlanks:
- return eExcelConditionalFormattingRuleType.ContainsBlanks;
-
- case ExcelConditionalFormattingConstants.RuleType._containsErrors:
- return eExcelConditionalFormattingRuleType.ContainsErrors;
-
- case ExcelConditionalFormattingConstants.RuleType._containsText:
- return eExcelConditionalFormattingRuleType.ContainsText;
-
- case ExcelConditionalFormattingConstants.RuleType._duplicateValues:
- return eExcelConditionalFormattingRuleType.DuplicateValues;
-
- case ExcelConditionalFormattingConstants.RuleType._endsWith:
- return eExcelConditionalFormattingRuleType.EndsWith;
-
- //case ExcelConditionalFormattingConstants.RuleType.Equal:
- // return eExcelConditionalFormattingRuleType.Equal;
-
- case ExcelConditionalFormattingConstants.RuleType._expression:
- return eExcelConditionalFormattingRuleType.Expression;
-
- //case ExcelConditionalFormattingConstants.RuleType.GreaterThan:
- // return eExcelConditionalFormattingRuleType.GreaterThan;
-
- //case ExcelConditionalFormattingConstants.RuleType.GreaterThanOrEqual:
- // return eExcelConditionalFormattingRuleType.GreaterThanOrEqual;
-
- //case ExcelConditionalFormattingConstants.RuleType.LessThan:
- // return eExcelConditionalFormattingRuleType.LessThan;
-
- //case ExcelConditionalFormattingConstants.RuleType.LessThanOrEqual:
- // return eExcelConditionalFormattingRuleType.LessThanOrEqual;
-
- //case ExcelConditionalFormattingConstants.RuleType.NotBetween:
- // return eExcelConditionalFormattingRuleType.NotBetween;
-
- case ExcelConditionalFormattingConstants.RuleType._notContainsBlanks:
- return eExcelConditionalFormattingRuleType.NotContainsBlanks;
-
- case ExcelConditionalFormattingConstants.RuleType._notContainsErrors:
- return eExcelConditionalFormattingRuleType.NotContainsErrors;
-
- case ExcelConditionalFormattingConstants.RuleType._notContainsText:
- return eExcelConditionalFormattingRuleType.NotContainsText;
-
- //case ExcelConditionalFormattingConstants.RuleType.NotEqual:
- // return eExcelConditionalFormattingRuleType.NotEqual;
-
- case ExcelConditionalFormattingConstants.RuleType._uniqueValues:
- return eExcelConditionalFormattingRuleType.UniqueValues;
-
- case ExcelConditionalFormattingConstants.RuleType._colorScale:
- return GetColorScaleType(topNode, nameSpaceManager);
- case ExcelConditionalFormattingConstants.RuleType._iconSet:
- return GetIconSetType(topNode, nameSpaceManager);
- case ExcelConditionalFormattingConstants.RuleType._dataBar:
- return eExcelConditionalFormattingRuleType.DataBar;
- }
-
- throw new(ExcelConditionalFormattingConstants.Errors._unexpectedRuleTypeAttribute);
- }
-
- private static eExcelConditionalFormattingRuleType GetCellIs(XmlElement node) {
- switch (node.GetAttribute("operator")) {
- case ExcelConditionalFormattingConstants.Operators._beginsWith:
- return eExcelConditionalFormattingRuleType.BeginsWith;
- case ExcelConditionalFormattingConstants.Operators._between:
- return eExcelConditionalFormattingRuleType.Between;
-
- case ExcelConditionalFormattingConstants.Operators._containsText:
- return eExcelConditionalFormattingRuleType.ContainsText;
-
- case ExcelConditionalFormattingConstants.Operators._endsWith:
- return eExcelConditionalFormattingRuleType.EndsWith;
-
- case ExcelConditionalFormattingConstants.Operators._equal:
- return eExcelConditionalFormattingRuleType.Equal;
-
- case ExcelConditionalFormattingConstants.Operators._greaterThan:
- return eExcelConditionalFormattingRuleType.GreaterThan;
-
- case ExcelConditionalFormattingConstants.Operators._greaterThanOrEqual:
- return eExcelConditionalFormattingRuleType.GreaterThanOrEqual;
-
- case ExcelConditionalFormattingConstants.Operators._lessThan:
- return eExcelConditionalFormattingRuleType.LessThan;
-
- case ExcelConditionalFormattingConstants.Operators._lessThanOrEqual:
- return eExcelConditionalFormattingRuleType.LessThanOrEqual;
-
- case ExcelConditionalFormattingConstants.Operators._notBetween:
- return eExcelConditionalFormattingRuleType.NotBetween;
-
- case ExcelConditionalFormattingConstants.Operators._notContains:
- return eExcelConditionalFormattingRuleType.NotContains;
-
- case ExcelConditionalFormattingConstants.Operators._notEqual:
- return eExcelConditionalFormattingRuleType.NotEqual;
- default:
- throw new(ExcelConditionalFormattingConstants.Errors._unexistentOperatorTypeAttribute);
- }
- }
-
- private static eExcelConditionalFormattingRuleType GetIconSetType(
- XmlNode topNode,
- XmlNamespaceManager nameSpaceManager) {
- var node = topNode.SelectSingleNode("d:iconSet/@iconSet", nameSpaceManager);
- if (node == null) {
- return eExcelConditionalFormattingRuleType.ThreeIconSet;
- }
- var v = node.Value;
-
- if (v[0] == '3') {
- return eExcelConditionalFormattingRuleType.ThreeIconSet;
- }
- if (v[0] == '4') {
- return eExcelConditionalFormattingRuleType.FourIconSet;
- }
- return eExcelConditionalFormattingRuleType.FiveIconSet;
- }
-
- /// <summary>
- /// Get the "colorScale" rule type according to the number of "cfvo" and "color" nodes.
- /// If we have excatly 2 "cfvo" and "color" childs, then we return "twoColorScale"
- /// </summary>
- /// <returns>TwoColorScale or ThreeColorScale</returns>
- internal static eExcelConditionalFormattingRuleType GetColorScaleType(
- XmlNode topNode,
- XmlNamespaceManager nameSpaceManager) {
- // Get the <cfvo> nodes
- var cfvoNodes = topNode.SelectNodes(
- string.Format(
- "{0}/{1}",
- ExcelConditionalFormattingConstants.Paths._colorScale,
- ExcelConditionalFormattingConstants.Paths._cfvo),
- nameSpaceManager);
-
- // Get the <color> nodes
- var colorNodes = topNode.SelectNodes(
- string.Format(
- "{0}/{1}",
- ExcelConditionalFormattingConstants.Paths._colorScale,
- ExcelConditionalFormattingConstants.Paths._color),
- nameSpaceManager);
-
- // We determine if it is "TwoColorScale" or "ThreeColorScale" by the
- // number of <cfvo> and <color> inside the <colorScale> node
- if ((cfvoNodes == null)
- || (cfvoNodes.Count < 2)
- || (cfvoNodes.Count > 3)
- || (colorNodes == null)
- || (colorNodes.Count < 2)
- || (colorNodes.Count > 3)
- || (cfvoNodes.Count != colorNodes.Count)) {
- throw new(ExcelConditionalFormattingConstants.Errors._wrongNumberCfvoColorNodes);
- }
-
- // Return the corresponding rule type (TwoColorScale or ThreeColorScale)
- return (cfvoNodes.Count == 2)
- ? eExcelConditionalFormattingRuleType.TwoColorScale
- : eExcelConditionalFormattingRuleType.ThreeColorScale;
- }
-
- /// <summary>
- /// Get the "aboveAverage" rule type according to the follwoing attributes:
- /// "AboveAverage", "EqualAverage" and "StdDev".
- ///
- /// @StdDev greater than "0" == AboveStdDev
- /// @StdDev less than "0" == BelowStdDev
- /// @AboveAverage = "1"/null and @EqualAverage = "0"/null == AboveAverage
- /// @AboveAverage = "1"/null and @EqualAverage = "1" == AboveOrEqualAverage
- /// @AboveAverage = "0" and @EqualAverage = "0"/null == BelowAverage
- /// @AboveAverage = "0" and @EqualAverage = "1" == BelowOrEqualAverage
- /// /// </summary>
- /// <returns>AboveAverage, AboveOrEqualAverage, BelowAverage or BelowOrEqualAverage</returns>
- internal static eExcelConditionalFormattingRuleType GetAboveAverageType(
- XmlNode topNode,
- XmlNamespaceManager nameSpaceManager) {
- // Get @StdDev attribute
- int? stdDev = ExcelConditionalFormattingHelper.GetAttributeIntNullable(
- topNode,
- ExcelConditionalFormattingConstants.Attributes._stdDev);
-
- if (stdDev > 0) {
- // @StdDev > "0" --> AboveStdDev
- return eExcelConditionalFormattingRuleType.AboveStdDev;
- }
-
- if (stdDev < 0) {
- // @StdDev < "0" --> BelowStdDev
- return eExcelConditionalFormattingRuleType.BelowStdDev;
- }
-
- // Get @AboveAverage attribute
- bool? isAboveAverage = ExcelConditionalFormattingHelper.GetAttributeBoolNullable(
- topNode,
- ExcelConditionalFormattingConstants.Attributes._aboveAverage);
-
- // Get @EqualAverage attribute
- bool? isEqualAverage = ExcelConditionalFormattingHelper.GetAttributeBoolNullable(
- topNode,
- ExcelConditionalFormattingConstants.Attributes._equalAverage);
-
- if ((isAboveAverage == null) || (isAboveAverage == true)) {
- if (isEqualAverage == true) {
- // @AboveAverage = "1"/null and @EqualAverage = "1" == AboveOrEqualAverage
- return eExcelConditionalFormattingRuleType.AboveOrEqualAverage;
- }
-
- // @AboveAverage = "1"/null and @EqualAverage = "0"/null == AboveAverage
- return eExcelConditionalFormattingRuleType.AboveAverage;
- }
-
- if (isEqualAverage == true) {
- // @AboveAverage = "0" and @EqualAverage = "1" == BelowOrEqualAverage
- return eExcelConditionalFormattingRuleType.BelowOrEqualAverage;
- }
-
- // @AboveAverage = "0" and @EqualAverage = "0"/null == BelowAverage
- return eExcelConditionalFormattingRuleType.BelowAverage;
- }
-
- /// <summary>
- /// Get the "top10" rule type according to the follwoing attributes:
- /// "Bottom" and "Percent"
- ///
- /// @Bottom = "1" and @Percent = "0"/null == Bottom
- /// @Bottom = "1" and @Percent = "1" == BottomPercent
- /// @Bottom = "0"/null and @Percent = "0"/null == Top
- /// @Bottom = "0"/null and @Percent = "1" == TopPercent
- /// /// </summary>
- /// <returns>Top, TopPercent, Bottom or BottomPercent</returns>
- public static eExcelConditionalFormattingRuleType GetTop10Type(
- XmlNode topNode,
- XmlNamespaceManager nameSpaceManager) {
- // Get @Bottom attribute
- bool? isBottom = ExcelConditionalFormattingHelper.GetAttributeBoolNullable(
- topNode,
- ExcelConditionalFormattingConstants.Attributes._bottom);
-
- // Get @Percent attribute
- bool? isPercent = ExcelConditionalFormattingHelper.GetAttributeBoolNullable(
- topNode,
- ExcelConditionalFormattingConstants.Attributes._percent);
-
- if (isBottom == true) {
- if (isPercent == true) {
- // @Bottom = "1" and @Percent = "1" == BottomPercent
- return eExcelConditionalFormattingRuleType.BottomPercent;
- }
-
- // @Bottom = "1" and @Percent = "0"/null == Bottom
- return eExcelConditionalFormattingRuleType.Bottom;
- }
-
- if (isPercent == true) {
- // @Bottom = "0"/null and @Percent = "1" == TopPercent
- return eExcelConditionalFormattingRuleType.TopPercent;
- }
-
- // @Bottom = "0"/null and @Percent = "0"/null == Top
- return eExcelConditionalFormattingRuleType.Top;
- }
-
- /// <summary>
- /// Get the "timePeriod" rule type according to "TimePeriod" attribute.
- /// /// </summary>
- /// <returns>Last7Days, LastMonth etc.</returns>
- public static eExcelConditionalFormattingRuleType GetTimePeriodType(
- XmlNode topNode,
- XmlNamespaceManager nameSpaceManager) {
- eExcelConditionalFormattingTimePeriodType timePeriod =
- ExcelConditionalFormattingTimePeriodType.GetTypeByAttribute(
- ExcelConditionalFormattingHelper.GetAttributeString(
- topNode,
- ExcelConditionalFormattingConstants.Attributes._timePeriod));
-
- switch (timePeriod) {
- case eExcelConditionalFormattingTimePeriodType.Last7Days:
- return eExcelConditionalFormattingRuleType.Last7Days;
-
- case eExcelConditionalFormattingTimePeriodType.LastMonth:
- return eExcelConditionalFormattingRuleType.LastMonth;
-
- case eExcelConditionalFormattingTimePeriodType.LastWeek:
- return eExcelConditionalFormattingRuleType.LastWeek;
-
- case eExcelConditionalFormattingTimePeriodType.NextMonth:
- return eExcelConditionalFormattingRuleType.NextMonth;
-
- case eExcelConditionalFormattingTimePeriodType.NextWeek:
- return eExcelConditionalFormattingRuleType.NextWeek;
-
- case eExcelConditionalFormattingTimePeriodType.ThisMonth:
- return eExcelConditionalFormattingRuleType.ThisMonth;
-
- case eExcelConditionalFormattingTimePeriodType.ThisWeek:
- return eExcelConditionalFormattingRuleType.ThisWeek;
-
- case eExcelConditionalFormattingTimePeriodType.Today:
- return eExcelConditionalFormattingRuleType.Today;
-
- case eExcelConditionalFormattingTimePeriodType.Tomorrow:
- return eExcelConditionalFormattingRuleType.Tomorrow;
-
- case eExcelConditionalFormattingTimePeriodType.Yesterday:
- return eExcelConditionalFormattingRuleType.Yesterday;
- }
-
- throw new(ExcelConditionalFormattingConstants.Errors._unexistentTimePeriodTypeAttribute);
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="type"></param>
- /// <returns></returns>
- public static string GetAttributeByType(eExcelConditionalFormattingRuleType type) {
- switch (type) {
- case eExcelConditionalFormattingRuleType.AboveAverage:
- case eExcelConditionalFormattingRuleType.AboveOrEqualAverage:
- case eExcelConditionalFormattingRuleType.BelowAverage:
- case eExcelConditionalFormattingRuleType.BelowOrEqualAverage:
- case eExcelConditionalFormattingRuleType.AboveStdDev:
- case eExcelConditionalFormattingRuleType.BelowStdDev:
- return ExcelConditionalFormattingConstants.RuleType._aboveAverage;
-
- case eExcelConditionalFormattingRuleType.Bottom:
- case eExcelConditionalFormattingRuleType.BottomPercent:
- case eExcelConditionalFormattingRuleType.Top:
- case eExcelConditionalFormattingRuleType.TopPercent:
- return ExcelConditionalFormattingConstants.RuleType._top10;
-
- case eExcelConditionalFormattingRuleType.Last7Days:
- case eExcelConditionalFormattingRuleType.LastMonth:
- case eExcelConditionalFormattingRuleType.LastWeek:
- case eExcelConditionalFormattingRuleType.NextMonth:
- case eExcelConditionalFormattingRuleType.NextWeek:
- case eExcelConditionalFormattingRuleType.ThisMonth:
- case eExcelConditionalFormattingRuleType.ThisWeek:
- case eExcelConditionalFormattingRuleType.Today:
- case eExcelConditionalFormattingRuleType.Tomorrow:
- case eExcelConditionalFormattingRuleType.Yesterday:
- return ExcelConditionalFormattingConstants.RuleType._timePeriod;
-
- case eExcelConditionalFormattingRuleType.Between:
- case eExcelConditionalFormattingRuleType.Equal:
- case eExcelConditionalFormattingRuleType.GreaterThan:
- case eExcelConditionalFormattingRuleType.GreaterThanOrEqual:
- case eExcelConditionalFormattingRuleType.LessThan:
- case eExcelConditionalFormattingRuleType.LessThanOrEqual:
- case eExcelConditionalFormattingRuleType.NotBetween:
- case eExcelConditionalFormattingRuleType.NotEqual:
- return ExcelConditionalFormattingConstants.RuleType._cellIs;
-
- case eExcelConditionalFormattingRuleType.ThreeIconSet:
- case eExcelConditionalFormattingRuleType.FourIconSet:
- case eExcelConditionalFormattingRuleType.FiveIconSet:
- return ExcelConditionalFormattingConstants.RuleType._iconSet;
-
- case eExcelConditionalFormattingRuleType.ThreeColorScale:
- case eExcelConditionalFormattingRuleType.TwoColorScale:
- return ExcelConditionalFormattingConstants.RuleType._colorScale;
-
- case eExcelConditionalFormattingRuleType.BeginsWith:
- return ExcelConditionalFormattingConstants.RuleType._beginsWith;
-
- case eExcelConditionalFormattingRuleType.ContainsBlanks:
- return ExcelConditionalFormattingConstants.RuleType._containsBlanks;
-
- case eExcelConditionalFormattingRuleType.ContainsErrors:
- return ExcelConditionalFormattingConstants.RuleType._containsErrors;
-
- case eExcelConditionalFormattingRuleType.ContainsText:
- return ExcelConditionalFormattingConstants.RuleType._containsText;
-
- case eExcelConditionalFormattingRuleType.DuplicateValues:
- return ExcelConditionalFormattingConstants.RuleType._duplicateValues;
-
- case eExcelConditionalFormattingRuleType.EndsWith:
- return ExcelConditionalFormattingConstants.RuleType._endsWith;
-
- case eExcelConditionalFormattingRuleType.Expression:
- return ExcelConditionalFormattingConstants.RuleType._expression;
-
- case eExcelConditionalFormattingRuleType.NotContainsBlanks:
- return ExcelConditionalFormattingConstants.RuleType._notContainsBlanks;
-
- case eExcelConditionalFormattingRuleType.NotContainsErrors:
- return ExcelConditionalFormattingConstants.RuleType._notContainsErrors;
-
- case eExcelConditionalFormattingRuleType.NotContainsText:
- return ExcelConditionalFormattingConstants.RuleType._notContainsText;
-
- case eExcelConditionalFormattingRuleType.UniqueValues:
- return ExcelConditionalFormattingConstants.RuleType._uniqueValues;
-
- case eExcelConditionalFormattingRuleType.DataBar:
- return ExcelConditionalFormattingConstants.RuleType._dataBar;
- }
-
- throw new(ExcelConditionalFormattingConstants.Errors._missingRuleType);
- }
-
- /// <summary>
- /// Return cfvo §18.3.1.11 parent according to the rule type
- /// </summary>
- /// <param name="type"></param>
- /// <returns></returns>
- public static string GetCfvoParentPathByType(eExcelConditionalFormattingRuleType type) {
- switch (type) {
- case eExcelConditionalFormattingRuleType.TwoColorScale:
- case eExcelConditionalFormattingRuleType.ThreeColorScale:
- return ExcelConditionalFormattingConstants.Paths._colorScale;
-
- case eExcelConditionalFormattingRuleType.ThreeIconSet:
- case eExcelConditionalFormattingRuleType.FourIconSet:
- case eExcelConditionalFormattingRuleType.FiveIconSet:
- return ExcelConditionalFormattingConstants.RuleType._iconSet;
-
- case eExcelConditionalFormattingRuleType.DataBar:
- return ExcelConditionalFormattingConstants.RuleType._dataBar;
- }
-
- throw new(ExcelConditionalFormattingConstants.Errors._missingRuleType);
- }
-}
diff --git a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingTimePeriodType.cs b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingTimePeriodType.cs
deleted file mode 100644
index c93a82d..0000000
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingTimePeriodType.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-17
- *******************************************************************************/
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// Functions related to the <see cref="ExcelConditionalFormattingTimePeriodType"/>
-/// </summary>
-internal static class ExcelConditionalFormattingTimePeriodType {
- /// <summary>
- ///
- /// </summary>
- /// <param name="type"></param>
- /// <returns></returns>
- public static string GetAttributeByType(eExcelConditionalFormattingTimePeriodType type) {
- switch (type) {
- case eExcelConditionalFormattingTimePeriodType.Last7Days:
- return ExcelConditionalFormattingConstants.TimePeriods._last7Days;
-
- case eExcelConditionalFormattingTimePeriodType.LastMonth:
- return ExcelConditionalFormattingConstants.TimePeriods._lastMonth;
-
- case eExcelConditionalFormattingTimePeriodType.LastWeek:
- return ExcelConditionalFormattingConstants.TimePeriods._lastWeek;
-
- case eExcelConditionalFormattingTimePeriodType.NextMonth:
- return ExcelConditionalFormattingConstants.TimePeriods._nextMonth;
-
- case eExcelConditionalFormattingTimePeriodType.NextWeek:
- return ExcelConditionalFormattingConstants.TimePeriods._nextWeek;
-
- case eExcelConditionalFormattingTimePeriodType.ThisMonth:
- return ExcelConditionalFormattingConstants.TimePeriods._thisMonth;
-
- case eExcelConditionalFormattingTimePeriodType.ThisWeek:
- return ExcelConditionalFormattingConstants.TimePeriods._thisWeek;
-
- case eExcelConditionalFormattingTimePeriodType.Today:
- return ExcelConditionalFormattingConstants.TimePeriods._today;
-
- case eExcelConditionalFormattingTimePeriodType.Tomorrow:
- return ExcelConditionalFormattingConstants.TimePeriods._tomorrow;
-
- case eExcelConditionalFormattingTimePeriodType.Yesterday:
- return ExcelConditionalFormattingConstants.TimePeriods._yesterday;
- }
-
- return string.Empty;
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="attribute"></param>
- /// <returns></returns>
- public static eExcelConditionalFormattingTimePeriodType GetTypeByAttribute(string attribute) {
- switch (attribute) {
- case ExcelConditionalFormattingConstants.TimePeriods._last7Days:
- return eExcelConditionalFormattingTimePeriodType.Last7Days;
-
- case ExcelConditionalFormattingConstants.TimePeriods._lastMonth:
- return eExcelConditionalFormattingTimePeriodType.LastMonth;
-
- case ExcelConditionalFormattingConstants.TimePeriods._lastWeek:
- return eExcelConditionalFormattingTimePeriodType.LastWeek;
-
- case ExcelConditionalFormattingConstants.TimePeriods._nextMonth:
- return eExcelConditionalFormattingTimePeriodType.NextMonth;
-
- case ExcelConditionalFormattingConstants.TimePeriods._nextWeek:
- return eExcelConditionalFormattingTimePeriodType.NextWeek;
-
- case ExcelConditionalFormattingConstants.TimePeriods._thisMonth:
- return eExcelConditionalFormattingTimePeriodType.ThisMonth;
-
- case ExcelConditionalFormattingConstants.TimePeriods._thisWeek:
- return eExcelConditionalFormattingTimePeriodType.ThisWeek;
-
- case ExcelConditionalFormattingConstants.TimePeriods._today:
- return eExcelConditionalFormattingTimePeriodType.Today;
-
- case ExcelConditionalFormattingConstants.TimePeriods._tomorrow:
- return eExcelConditionalFormattingTimePeriodType.Tomorrow;
-
- case ExcelConditionalFormattingConstants.TimePeriods._yesterday:
- return eExcelConditionalFormattingTimePeriodType.Yesterday;
- }
-
- throw new(ExcelConditionalFormattingConstants.Errors._unexistentTimePeriodTypeAttribute);
- }
-}
diff --git a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingValueObjectType.cs b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingValueObjectType.cs
deleted file mode 100644
index 22d9356..0000000
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingValueObjectType.cs
+++ /dev/null
@@ -1,199 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting Adaption 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// Functions related to the <see cref="ExcelConditionalFormattingColorScaleValue"/>
-/// </summary>
-internal static class ExcelConditionalFormattingValueObjectType {
- /// <summary>
- /// Get the sequencial order of a cfvo/color by its position.
- /// </summary>
- /// <param name="position"></param>
- /// <param name="ruleType"></param>
- /// <returns>1, 2 or 3</returns>
- internal static int GetOrderByPosition(
- eExcelConditionalFormattingValueObjectPosition position,
- eExcelConditionalFormattingRuleType ruleType) {
- switch (position) {
- case eExcelConditionalFormattingValueObjectPosition.Low:
- return 1;
-
- case eExcelConditionalFormattingValueObjectPosition.Middle:
- return 2;
-
- case eExcelConditionalFormattingValueObjectPosition.High:
- // Check if the rule type is TwoColorScale.
- if (ruleType == eExcelConditionalFormattingRuleType.TwoColorScale) {
- // There are only "Low" and "High". So "High" is the second
- return 2;
- }
-
- // There are "Low", "Middle" and "High". So "High" is the third
- return 3;
- }
-
- return 0;
- }
-
- /// <summary>
- /// Get the CFVO type by its @type attribute
- /// </summary>
- /// <param name="attribute"></param>
- /// <returns></returns>
- public static eExcelConditionalFormattingValueObjectType GetTypeByAttrbiute(string attribute) {
- switch (attribute) {
- case ExcelConditionalFormattingConstants.CfvoType._min:
- return eExcelConditionalFormattingValueObjectType.Min;
-
- case ExcelConditionalFormattingConstants.CfvoType._max:
- return eExcelConditionalFormattingValueObjectType.Max;
-
- case ExcelConditionalFormattingConstants.CfvoType._num:
- return eExcelConditionalFormattingValueObjectType.Num;
-
- case ExcelConditionalFormattingConstants.CfvoType._formula:
- return eExcelConditionalFormattingValueObjectType.Formula;
-
- case ExcelConditionalFormattingConstants.CfvoType._percent:
- return eExcelConditionalFormattingValueObjectType.Percent;
-
- case ExcelConditionalFormattingConstants.CfvoType._percentile:
- return eExcelConditionalFormattingValueObjectType.Percentile;
- }
-
- throw new(ExcelConditionalFormattingConstants.Errors._unexistentCfvoTypeAttribute);
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="position"></param>
- ///<param name="ruleType"></param>
- /// <param name="topNode"></param>
- /// <param name="nameSpaceManager"></param>
- /// <returns></returns>
- public static XmlNode GetCfvoNodeByPosition(
- eExcelConditionalFormattingValueObjectPosition position,
- eExcelConditionalFormattingRuleType ruleType,
- XmlNode topNode,
- XmlNamespaceManager nameSpaceManager) {
- // Get the corresponding <cfvo> node (by the position)
- var node = topNode.SelectSingleNode(
- string.Format(
- "{0}[position()={1}]",
- // {0}
- ExcelConditionalFormattingConstants.Paths._cfvo,
- // {1}
- GetOrderByPosition(position, ruleType)),
- nameSpaceManager);
-
- if (node == null) {
- throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoNode);
- }
-
- return node;
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="type"></param>
- /// <returns></returns>
- public static string GetAttributeByType(eExcelConditionalFormattingValueObjectType type) {
- switch (type) {
- case eExcelConditionalFormattingValueObjectType.Min:
- return ExcelConditionalFormattingConstants.CfvoType._min;
-
- case eExcelConditionalFormattingValueObjectType.Max:
- return ExcelConditionalFormattingConstants.CfvoType._max;
-
- case eExcelConditionalFormattingValueObjectType.Num:
- return ExcelConditionalFormattingConstants.CfvoType._num;
-
- case eExcelConditionalFormattingValueObjectType.Formula:
- return ExcelConditionalFormattingConstants.CfvoType._formula;
-
- case eExcelConditionalFormattingValueObjectType.Percent:
- return ExcelConditionalFormattingConstants.CfvoType._percent;
-
- case eExcelConditionalFormattingValueObjectType.Percentile:
- return ExcelConditionalFormattingConstants.CfvoType._percentile;
- }
-
- return string.Empty;
- }
-
- /// <summary>
- /// Get the cfvo (§18.3.1.11) node parent by the rule type. Can be any of the following:
- /// "colorScale" (§18.3.1.16); "dataBar" (§18.3.1.28); "iconSet" (§18.3.1.49)
- /// </summary>
- /// <param name="ruleType"></param>
- /// <returns></returns>
- public static string GetParentPathByRuleType(eExcelConditionalFormattingRuleType ruleType) {
- switch (ruleType) {
- case eExcelConditionalFormattingRuleType.TwoColorScale:
- case eExcelConditionalFormattingRuleType.ThreeColorScale:
- return ExcelConditionalFormattingConstants.Paths._colorScale;
-
- case eExcelConditionalFormattingRuleType.ThreeIconSet:
- case eExcelConditionalFormattingRuleType.FourIconSet:
- case eExcelConditionalFormattingRuleType.FiveIconSet:
- return ExcelConditionalFormattingConstants.Paths._iconSet;
-
- case eExcelConditionalFormattingRuleType.DataBar:
- return ExcelConditionalFormattingConstants.Paths._dataBar;
- }
-
- return string.Empty;
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="nodeType"></param>
- /// <returns></returns>
- public static string GetNodePathByNodeType(
- eExcelConditionalFormattingValueObjectNodeType nodeType) {
- switch (nodeType) {
- case eExcelConditionalFormattingValueObjectNodeType.Cfvo:
- return ExcelConditionalFormattingConstants.Paths._cfvo;
-
- case eExcelConditionalFormattingValueObjectNodeType.Color:
- return ExcelConditionalFormattingConstants.Paths._color;
- }
-
- return string.Empty;
- }
-}
diff --git a/EPPlus/ConditionalFormatting/RangeConditionalFormatting.cs b/EPPlus/ConditionalFormatting/RangeConditionalFormatting.cs
deleted file mode 100644
index 6fcc305..0000000
--- a/EPPlus/ConditionalFormatting/RangeConditionalFormatting.cs
+++ /dev/null
@@ -1,380 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Conditional Formatting 2012-04-03
- *******************************************************************************/
-
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-internal class RangeConditionalFormatting : IRangeConditionalFormatting {
- public ExcelWorksheet _worksheet;
- public ExcelAddress _address;
-
- public RangeConditionalFormatting(ExcelWorksheet worksheet, ExcelAddress address) {
- Require.Argument(worksheet).IsNotNull("worksheet");
- Require.Argument(address).IsNotNull("address");
-
- _worksheet = worksheet;
- _address = address;
- }
-
- /// <summary>
- /// Add AboveOrEqualAverage Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingAverageGroup AddAboveAverage() {
- return _worksheet.ConditionalFormatting.AddAboveAverage(_address);
- }
-
- /// <summary>
- /// Add AboveOrEqualAverage Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingAverageGroup AddAboveOrEqualAverage() {
- return _worksheet.ConditionalFormatting.AddAboveOrEqualAverage(_address);
- }
-
- /// <summary>
- /// Add BelowOrEqualAverage Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingAverageGroup AddBelowAverage() {
- return _worksheet.ConditionalFormatting.AddBelowAverage(_address);
- }
-
- /// <summary>
- /// Add BelowOrEqualAverage Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingAverageGroup AddBelowOrEqualAverage() {
- return _worksheet.ConditionalFormatting.AddBelowOrEqualAverage(_address);
- }
-
- /// <summary>
- /// Add AboveStdDev Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingStdDevGroup AddAboveStdDev() {
- return _worksheet.ConditionalFormatting.AddAboveStdDev(_address);
- }
-
- /// <summary>
- /// Add BelowStdDev Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingStdDevGroup AddBelowStdDev() {
- return _worksheet.ConditionalFormatting.AddBelowStdDev(_address);
- }
-
- /// <summary>
- /// Add Bottom Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTopBottomGroup AddBottom() {
- return _worksheet.ConditionalFormatting.AddBottom(_address);
- }
-
- /// <summary>
- /// Add BottomPercent Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTopBottomGroup AddBottomPercent() {
- return _worksheet.ConditionalFormatting.AddBottomPercent(_address);
- }
-
- /// <summary>
- /// Add Top Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTopBottomGroup AddTop() {
- return _worksheet.ConditionalFormatting.AddTop(_address);
- }
-
- /// <summary>
- /// Add TopPercent Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTopBottomGroup AddTopPercent() {
- return _worksheet.ConditionalFormatting.AddTopPercent(_address);
- }
-
- /// <summary>
- /// Add Last7Days Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddLast7Days() {
- return _worksheet.ConditionalFormatting.AddLast7Days(_address);
- }
-
- /// <summary>
- /// Add LastMonth Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddLastMonth() {
- return _worksheet.ConditionalFormatting.AddLastMonth(_address);
- }
-
- /// <summary>
- /// Add LastWeek Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddLastWeek() {
- return _worksheet.ConditionalFormatting.AddLastWeek(_address);
- }
-
- /// <summary>
- /// Add NextMonth Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddNextMonth() {
- return _worksheet.ConditionalFormatting.AddNextMonth(_address);
- }
-
- /// <summary>
- /// Add NextWeek Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddNextWeek() {
- return _worksheet.ConditionalFormatting.AddNextWeek(_address);
- }
-
- /// <summary>
- /// Add ThisMonth Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddThisMonth() {
- return _worksheet.ConditionalFormatting.AddThisMonth(_address);
- }
-
- /// <summary>
- /// Add ThisWeek Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddThisWeek() {
- return _worksheet.ConditionalFormatting.AddThisWeek(_address);
- }
-
- /// <summary>
- /// Add Today Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddToday() {
- return _worksheet.ConditionalFormatting.AddToday(_address);
- }
-
- /// <summary>
- /// Add Tomorrow Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddTomorrow() {
- return _worksheet.ConditionalFormatting.AddTomorrow(_address);
- }
-
- /// <summary>
- /// Add Yesterday Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddYesterday() {
- return _worksheet.ConditionalFormatting.AddYesterday(_address);
- }
-
- /// <summary>
- /// Add BeginsWith Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingBeginsWith AddBeginsWith() {
- return _worksheet.ConditionalFormatting.AddBeginsWith(_address);
- }
-
- /// <summary>
- /// Add Between Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingBetween AddBetween() {
- return _worksheet.ConditionalFormatting.AddBetween(_address);
- }
-
- /// <summary>
- /// Add ContainsBlanks Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingContainsBlanks AddContainsBlanks() {
- return _worksheet.ConditionalFormatting.AddContainsBlanks(_address);
- }
-
- /// <summary>
- /// Add ContainsErrors Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingContainsErrors AddContainsErrors() {
- return _worksheet.ConditionalFormatting.AddContainsErrors(_address);
- }
-
- /// <summary>
- /// Add ContainsText Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingContainsText AddContainsText() {
- return _worksheet.ConditionalFormatting.AddContainsText(_address);
- }
-
- /// <summary>
- /// Add DuplicateValues Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingDuplicateValues AddDuplicateValues() {
- return _worksheet.ConditionalFormatting.AddDuplicateValues(_address);
- }
-
- /// <summary>
- /// Add EndsWith Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingEndsWith AddEndsWith() {
- return _worksheet.ConditionalFormatting.AddEndsWith(_address);
- }
-
- /// <summary>
- /// Add Equal Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingEqual AddEqual() {
- return _worksheet.ConditionalFormatting.AddEqual(_address);
- }
-
- /// <summary>
- /// Add Expression Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingExpression AddExpression() {
- return _worksheet.ConditionalFormatting.AddExpression(_address);
- }
-
- /// <summary>
- /// Add GreaterThan Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingGreaterThan AddGreaterThan() {
- return _worksheet.ConditionalFormatting.AddGreaterThan(_address);
- }
-
- /// <summary>
- /// Add GreaterThanOrEqual Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingGreaterThanOrEqual AddGreaterThanOrEqual() {
- return _worksheet.ConditionalFormatting.AddGreaterThanOrEqual(_address);
- }
-
- /// <summary>
- /// Add LessThan Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingLessThan AddLessThan() {
- return _worksheet.ConditionalFormatting.AddLessThan(_address);
- }
-
- /// <summary>
- /// Add LessThanOrEqual Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingLessThanOrEqual AddLessThanOrEqual() {
- return _worksheet.ConditionalFormatting.AddLessThanOrEqual(_address);
- }
-
- /// <summary>
- /// Add NotBetween Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingNotBetween AddNotBetween() {
- return _worksheet.ConditionalFormatting.AddNotBetween(_address);
- }
-
- /// <summary>
- /// Add NotContainsBlanks Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingNotContainsBlanks AddNotContainsBlanks() {
- return _worksheet.ConditionalFormatting.AddNotContainsBlanks(_address);
- }
-
- /// <summary>
- /// Add NotContainsErrors Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingNotContainsErrors AddNotContainsErrors() {
- return _worksheet.ConditionalFormatting.AddNotContainsErrors(_address);
- }
-
- /// <summary>
- /// Add NotContainsText Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingNotContainsText AddNotContainsText() {
- return _worksheet.ConditionalFormatting.AddNotContainsText(_address);
- }
-
- /// <summary>
- /// Add NotEqual Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingNotEqual AddNotEqual() {
- return _worksheet.ConditionalFormatting.AddNotEqual(_address);
- }
-
- /// <summary>
- /// Add UniqueValues Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingUniqueValues AddUniqueValues() {
- return _worksheet.ConditionalFormatting.AddUniqueValues(_address);
- }
-
- /// <summary>
- /// Add ThreeColorScale Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingThreeColorScale AddThreeColorScale() {
- return (IExcelConditionalFormattingThreeColorScale)(_worksheet.ConditionalFormatting.AddRule(
- eExcelConditionalFormattingRuleType.ThreeColorScale,
- _address));
- }
-
- /// <summary>
- /// Add TwoColorScale Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTwoColorScale AddTwoColorScale() {
- return (IExcelConditionalFormattingTwoColorScale)(_worksheet.ConditionalFormatting.AddRule(
- eExcelConditionalFormattingRuleType.TwoColorScale,
- _address));
- }
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveAverage.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveAverage.cs
deleted file mode 100644
index cf90b06..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveAverage.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingAboveAverage
-/// </summary>
-public class ExcelConditionalFormattingAboveAverage : ExcelConditionalFormattingAverageGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingAboveAverage(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.AboveAverage,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- AboveAverage = true;
- EqualAverage = false;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingAboveAverage(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingAboveAverage(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveOrEqualAverage.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveOrEqualAverage.cs
deleted file mode 100644
index dcbf944..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveOrEqualAverage.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingAboveOrEqualAverage
-/// </summary>
-public class ExcelConditionalFormattingAboveOrEqualAverage
- : ExcelConditionalFormattingAverageGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingAboveOrEqualAverage(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.AboveOrEqualAverage,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- AboveAverage = true;
- EqualAverage = true;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingAboveOrEqualAverage(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingAboveOrEqualAverage(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveStdDev.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveStdDev.cs
deleted file mode 100644
index bd905e1..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveStdDev.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingAboveStdDev
-/// </summary>
-public class ExcelConditionalFormattingAboveStdDev
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingStdDevGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingAboveStdDev(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.AboveStdDev,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- AboveAverage = true;
- StdDev = 1;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingAboveStdDev(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingAboveStdDev(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAverageGroup.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAverageGroup.cs
deleted file mode 100644
index 34076ba..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAverageGroup.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingAverageGroup
-/// </summary>
-public class ExcelConditionalFormattingAverageGroup
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingAverageGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="type"></param>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingAverageGroup(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- type,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {}
-
- /// <summary>
- ///
- /// </summary>
- ///<param name="type"></param>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingAverageGroup(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(type, address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- ///<param name="type"></param>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingAverageGroup(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(type, address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBeginsWith.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBeginsWith.cs
deleted file mode 100644
index d8cdd26..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBeginsWith.cs
+++ /dev/null
@@ -1,112 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingBeginsWith
-/// </summary>
-public class ExcelConditionalFormattingBeginsWith
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingBeginsWith {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingBeginsWith(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.BeginsWith,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.BeginsWith;
- Text = string.Empty;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingBeginsWith(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingBeginsWith(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-
- /// <summary>
- /// The text to search in the beginning of the cell
- /// </summary>
- public string Text {
- get => GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute);
- set {
- SetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute, value);
-
- Formula = string.Format(
- "LEFT({0},LEN(\"{1}\"))=\"{1}\"",
- Address.Start.Address,
- value.Replace("\"", "\"\""));
- }
- }
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowAverage.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowAverage.cs
deleted file mode 100644
index ef68fc1..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowAverage.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingBelowAverage
-/// </summary>
-public class ExcelConditionalFormattingBelowAverage : ExcelConditionalFormattingAverageGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingBelowAverage(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.BelowAverage,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- AboveAverage = false;
- EqualAverage = false;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingBelowAverage(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingBelowAverage(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowOrEqualAverage.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowOrEqualAverage.cs
deleted file mode 100644
index 4d8cd67..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowOrEqualAverage.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingBelowOrEqualAverage
-/// </summary>
-public class ExcelConditionalFormattingBelowOrEqualAverage
- : ExcelConditionalFormattingAverageGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingBelowOrEqualAverage(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.BelowOrEqualAverage,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- AboveAverage = false;
- EqualAverage = true;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingBelowOrEqualAverage(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingBelowOrEqualAverage(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowStdDev.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowStdDev.cs
deleted file mode 100644
index 8291319..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowStdDev.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingBelowStdDev
-/// </summary>
-public class ExcelConditionalFormattingBelowStdDev
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingStdDevGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingBelowStdDev(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.BelowStdDev,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- AboveAverage = false;
- StdDev = 1;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingBelowStdDev(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingBelowStdDev(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBetween.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBetween.cs
deleted file mode 100644
index fb1bb73..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBetween.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingBetween
-/// </summary>
-public class ExcelConditionalFormattingBetween
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingBetween {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingBetween(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.Between,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.Between;
- Formula = string.Empty;
- Formula2 = string.Empty;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingBetween(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingBetween(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottom.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottom.cs
deleted file mode 100644
index ae9e861..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottom.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingBottom
-/// </summary>
-public class ExcelConditionalFormattingBottom
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingTopBottomGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingBottom(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.Bottom,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Bottom = true;
- Percent = false;
- Rank = 10; // Last 10 values
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingBottom(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingBottom(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottomPercent.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottomPercent.cs
deleted file mode 100644
index 719901f..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottomPercent.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingBottomPercent
-/// </summary>
-public class ExcelConditionalFormattingBottomPercent
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingTopBottomGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingBottomPercent(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.BottomPercent,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Bottom = true;
- Percent = true;
- Rank = 10; // Last 10 percent
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingBottomPercent(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingBottomPercent(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsBlanks.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsBlanks.cs
deleted file mode 100644
index d5eafe0..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsBlanks.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingContainsBlanks
-/// </summary>
-public class ExcelConditionalFormattingContainsBlanks
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingContainsBlanks {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingContainsBlanks(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.ContainsBlanks,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Formula = string.Format("LEN(TRIM({0}))=0", Address.Start.Address);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingContainsBlanks(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingContainsBlanks(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsErrors.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsErrors.cs
deleted file mode 100644
index f5d65f9..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsErrors.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingContainsErrors
-/// </summary>
-public class ExcelConditionalFormattingContainsErrors
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingContainsErrors {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingContainsErrors(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.ContainsErrors,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Formula = string.Format("ISERROR({0})", Address.Start.Address);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingContainsErrors(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingContainsErrors(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsText.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsText.cs
deleted file mode 100644
index ed433cc..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsText.cs
+++ /dev/null
@@ -1,112 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingContainsText
-/// </summary>
-public class ExcelConditionalFormattingContainsText
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingContainsText {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingContainsText(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.ContainsText,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.ContainsText;
- Text = string.Empty;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingContainsText(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingContainsText(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-
- /// <summary>
- /// The text to search inside the cell
- /// </summary>
- public string Text {
- get => GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute);
- set {
- SetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute, value);
-
- Formula = string.Format(
- "NOT(ISERROR(SEARCH(\"{1}\",{0})))",
- Address.Start.Address,
- value.Replace("\"", "\"\""));
- }
- }
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingDataBar.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingDataBar.cs
deleted file mode 100644
index 6c37773..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingDataBar.cs
+++ /dev/null
@@ -1,156 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Collections.Immutable;
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// Databar
-/// </summary>
-public class ExcelConditionalFormattingDataBar
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingDataBarGroup {
- protected override ImmutableArray<string> SchemaNodeOrder { get; } = ["cfvo", "color"];
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="type"></param>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingDataBar(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- type,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- //Create the <dataBar> node inside the <cfRule> node
- if (itemElementNode != null && itemElementNode.HasChildNodes) {
- bool high = false;
- foreach (XmlNode node in itemElementNode.SelectNodes("d:dataBar/d:cfvo", NameSpaceManager)) {
- if (high == false) {
- LowValue = new(type, address, worksheet, node, namespaceManager);
- high = true;
- } else {
- HighValue = new(type, address, worksheet, node, namespaceManager);
- }
- }
- } else {
- var iconSetNode = CreateComplexNode(Node, ExcelConditionalFormattingConstants.Paths._dataBar);
-
- var lowNode = iconSetNode.OwnerDocument.CreateElement(
- ExcelConditionalFormattingConstants.Paths._cfvo,
- ExcelPackage._schemaMain);
- iconSetNode.AppendChild(lowNode);
- LowValue = new(
- eExcelConditionalFormattingValueObjectType.Min,
- 0,
- "",
- eExcelConditionalFormattingRuleType.DataBar,
- address,
- priority,
- worksheet,
- lowNode,
- namespaceManager);
-
- var highNode = iconSetNode.OwnerDocument.CreateElement(
- ExcelConditionalFormattingConstants.Paths._cfvo,
- ExcelPackage._schemaMain);
- iconSetNode.AppendChild(highNode);
- HighValue = new(
- eExcelConditionalFormattingValueObjectType.Max,
- 0,
- "",
- eExcelConditionalFormattingRuleType.DataBar,
- address,
- priority,
- worksheet,
- highNode,
- namespaceManager);
- }
- Type = type;
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="type"></param>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingDataBar(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(type, address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="type"></param>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingDataBar(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(type, address, priority, worksheet, null, null) {}
-
- private const string _showValuePath = "d:dataBar/@showValue";
-
- public bool ShowValue {
- get => GetXmlNodeBool(_showValuePath, true);
- set => SetXmlNodeBool(_showValuePath, value);
- }
-
- public ExcelConditionalFormattingIconDataBarValue LowValue { get; internal set; }
-
- public ExcelConditionalFormattingIconDataBarValue HighValue { get; internal set; }
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingDuplicateValues.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingDuplicateValues.cs
deleted file mode 100644
index ecba659..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingDuplicateValues.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingDuplicateValues
-/// </summary>
-public class ExcelConditionalFormattingDuplicateValues
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingDuplicateValues {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingDuplicateValues(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.DuplicateValues,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingDuplicateValues(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingDuplicateValues(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingEndsWith.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingEndsWith.cs
deleted file mode 100644
index 39d2a2b..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingEndsWith.cs
+++ /dev/null
@@ -1,112 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingEndsWith
-/// </summary>
-public class ExcelConditionalFormattingEndsWith
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingEndsWith {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingEndsWith(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.EndsWith,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.EndsWith;
- Text = string.Empty;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingEndsWith(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingEndsWith(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-
- /// <summary>
- /// The text to search in the end of the cell
- /// </summary>
- public string Text {
- get => GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute);
- set {
- SetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute, value);
-
- Formula = string.Format(
- "RIGHT({0},LEN(\"{1}\"))=\"{1}\"",
- Address.Start.Address,
- value.Replace("\"", "\"\""));
- }
- }
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingEqual.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingEqual.cs
deleted file mode 100644
index ddade06..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingEqual.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingEqual
-/// </summary>
-public class ExcelConditionalFormattingEqual
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingEqual {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingEqual(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.Equal,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.Equal;
- Formula = string.Empty;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingEqual(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingEqual(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingExpression.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingExpression.cs
deleted file mode 100644
index ce887c5..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingExpression.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingExpression
-/// </summary>
-public class ExcelConditionalFormattingExpression
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingExpression {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingExpression(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.Expression,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Formula = string.Empty;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingExpression(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingExpression(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingFiveIconSet.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingFiveIconSet.cs
deleted file mode 100644
index e75f49a..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingFiveIconSet.cs
+++ /dev/null
@@ -1,149 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingThreeIconSet
-/// </summary>
-public class ExcelConditionalFormattingFiveIconSet
- : ExcelConditionalFormattingIconSetBase<eExcelconditionalFormatting5IconsSetType>,
- IExcelConditionalFormattingFiveIconSet {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingFiveIconSet(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.FiveIconSet,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode != null && itemElementNode.HasChildNodes) {
- XmlNode iconNode4 = TopNode.SelectSingleNode(
- "d:iconSet/d:cfvo[position()=4]",
- NameSpaceManager);
- Icon4 = new(
- eExcelConditionalFormattingRuleType.FiveIconSet,
- address,
- worksheet,
- iconNode4,
- namespaceManager);
-
- XmlNode iconNode5 = TopNode.SelectSingleNode(
- "d:iconSet/d:cfvo[position()=5]",
- NameSpaceManager);
- Icon5 = new(
- eExcelConditionalFormattingRuleType.FiveIconSet,
- address,
- worksheet,
- iconNode5,
- namespaceManager);
- } else {
- XmlNode iconSetNode = TopNode.SelectSingleNode("d:iconSet", NameSpaceManager);
- var iconNode4 = iconSetNode.OwnerDocument.CreateElement(
- ExcelConditionalFormattingConstants.Paths._cfvo,
- ExcelPackage._schemaMain);
- iconSetNode.AppendChild(iconNode4);
-
- Icon4 = new(
- eExcelConditionalFormattingValueObjectType.Percent,
- 60,
- "",
- eExcelConditionalFormattingRuleType.ThreeIconSet,
- address,
- priority,
- worksheet,
- iconNode4,
- namespaceManager);
-
- var iconNode5 = iconSetNode.OwnerDocument.CreateElement(
- ExcelConditionalFormattingConstants.Paths._cfvo,
- ExcelPackage._schemaMain);
- iconSetNode.AppendChild(iconNode5);
-
- Icon5 = new(
- eExcelConditionalFormattingValueObjectType.Percent,
- 80,
- "",
- eExcelConditionalFormattingRuleType.ThreeIconSet,
- address,
- priority,
- worksheet,
- iconNode5,
- namespaceManager);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingFiveIconSet(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingFiveIconSet(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-
- public ExcelConditionalFormattingIconDataBarValue Icon5 { get; internal set; }
-
- public ExcelConditionalFormattingIconDataBarValue Icon4 { get; internal set; }
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingFourIconSet.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingFourIconSet.cs
deleted file mode 100644
index 10bd1b3..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingFourIconSet.cs
+++ /dev/null
@@ -1,121 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingThreeIconSet
-/// </summary>
-public class ExcelConditionalFormattingFourIconSet
- : ExcelConditionalFormattingIconSetBase<eExcelconditionalFormatting4IconsSetType>,
- IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType> {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingFourIconSet(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.FourIconSet,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode != null && itemElementNode.HasChildNodes) {
- XmlNode iconNode4 = TopNode.SelectSingleNode(
- "d:iconSet/d:cfvo[position()=4]",
- NameSpaceManager);
- Icon4 = new(
- eExcelConditionalFormattingRuleType.FourIconSet,
- address,
- worksheet,
- iconNode4,
- namespaceManager);
- } else {
- XmlNode iconSetNode = TopNode.SelectSingleNode("d:iconSet", NameSpaceManager);
- var iconNode4 = iconSetNode.OwnerDocument.CreateElement(
- ExcelConditionalFormattingConstants.Paths._cfvo,
- ExcelPackage._schemaMain);
- iconSetNode.AppendChild(iconNode4);
-
- Icon4 = new(
- eExcelConditionalFormattingValueObjectType.Percent,
- 75,
- "",
- eExcelConditionalFormattingRuleType.ThreeIconSet,
- address,
- priority,
- worksheet,
- iconNode4,
- namespaceManager);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingFourIconSet(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingFourIconSet(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-
- public ExcelConditionalFormattingIconDataBarValue Icon4 { get; internal set; }
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThan.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThan.cs
deleted file mode 100644
index 9e57c1e..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThan.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingGreaterThan
-/// </summary>
-public class ExcelConditionalFormattingGreaterThan
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingGreaterThan {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingGreaterThan(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.GreaterThan,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.GreaterThan;
- Formula = string.Empty;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingGreaterThan(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingGreaterThan(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThanOrEqual.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThanOrEqual.cs
deleted file mode 100644
index 1a83939..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThanOrEqual.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingGreaterThanOrEqual
-/// </summary>
-public class ExcelConditionalFormattingGreaterThanOrEqual
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingGreaterThanOrEqual {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingGreaterThanOrEqual(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.GreaterThanOrEqual,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.GreaterThanOrEqual;
- Formula = string.Empty;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingGreaterThanOrEqual(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingGreaterThanOrEqual(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLast7Days.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLast7Days.cs
deleted file mode 100644
index 100f6da..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLast7Days.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingLast7Days
-/// </summary>
-public class ExcelConditionalFormattingLast7Days : ExcelConditionalFormattingTimePeriodGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingLast7Days(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.Last7Days,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- TimePeriod = eExcelConditionalFormattingTimePeriodType.Last7Days;
- Formula = string.Format(
- "AND(TODAY()-FLOOR({0},1)<=6,FLOOR({0},1)<=TODAY())",
- Address.Start.Address);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingLast7Days(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingLast7Days(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastMonth.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastMonth.cs
deleted file mode 100644
index 3888e32..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastMonth.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingLastMonth
-/// </summary>
-public class ExcelConditionalFormattingLastMonth : ExcelConditionalFormattingTimePeriodGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingLastMonth(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.LastMonth,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- TimePeriod = eExcelConditionalFormattingTimePeriodType.LastMonth;
- Formula = string.Format(
- "AND(MONTH({0})=MONTH(EDATE(TODAY(),0-1)),YEAR({0})=YEAR(EDATE(TODAY(),0-1)))",
- Address.Start.Address);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingLastMonth(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingLastMonth(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastWeek.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastWeek.cs
deleted file mode 100644
index 9edbe40..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastWeek.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingLastWeek
-/// </summary>
-public class ExcelConditionalFormattingLastWeek : ExcelConditionalFormattingTimePeriodGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingLastWeek(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.LastWeek,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- TimePeriod = eExcelConditionalFormattingTimePeriodType.LastWeek;
- Formula = string.Format(
- "AND(TODAY()-ROUNDDOWN({0},0)>=(WEEKDAY(TODAY())),TODAY()-ROUNDDOWN({0},0)<(WEEKDAY(TODAY())+7))",
- Address.Start.Address);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingLastWeek(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingLastWeek(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThan.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThan.cs
deleted file mode 100644
index 5695da9..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThan.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingLessThan
-/// </summary>
-public class ExcelConditionalFormattingLessThan
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingLessThan {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingLessThan(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.LessThan,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.LessThan;
- Formula = string.Empty;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingLessThan(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingLessThan(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThanOrEqual.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThanOrEqual.cs
deleted file mode 100644
index 3e54630..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThanOrEqual.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingLessThanOrEqual
-/// </summary>
-public class ExcelConditionalFormattingLessThanOrEqual
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingLessThanOrEqual {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingLessThanOrEqual(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.LessThanOrEqual,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.LessThanOrEqual;
- Formula = string.Empty;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingLessThanOrEqual(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingLessThanOrEqual(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextMonth.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextMonth.cs
deleted file mode 100644
index a7a23e6..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextMonth.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingNextMonth
-/// </summary>
-public class ExcelConditionalFormattingNextMonth : ExcelConditionalFormattingTimePeriodGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingNextMonth(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.NextMonth,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- TimePeriod = eExcelConditionalFormattingTimePeriodType.NextMonth;
- Formula = string.Format(
- "AND(MONTH({0})=MONTH(EDATE(TODAY(),0+1)), YEAR({0})=YEAR(EDATE(TODAY(),0+1)))",
- Address.Start.Address);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingNextMonth(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingNextMonth(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextWeek.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextWeek.cs
deleted file mode 100644
index 1c01b87..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextWeek.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingNextWeek
-/// </summary>
-public class ExcelConditionalFormattingNextWeek : ExcelConditionalFormattingTimePeriodGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingNextWeek(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.NextWeek,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- TimePeriod = eExcelConditionalFormattingTimePeriodType.NextWeek;
- Formula = string.Format(
- "AND(ROUNDDOWN({0},0)-TODAY()>(7-WEEKDAY(TODAY())),ROUNDDOWN({0},0)-TODAY()<(15-WEEKDAY(TODAY())))",
- Address.Start.Address);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingNextWeek(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingNextWeek(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotBetween.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotBetween.cs
deleted file mode 100644
index afa0de5..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotBetween.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingNotBetween
-/// </summary>
-public class ExcelConditionalFormattingNotBetween
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingNotBetween {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingNotBetween(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.NotBetween,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.NotBetween;
- Formula = string.Empty;
- Formula2 = string.Empty;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingNotBetween(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingNotBetween(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsBlanks.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsBlanks.cs
deleted file mode 100644
index babf13b..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsBlanks.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingNotContainsBlanks
-/// </summary>
-public class ExcelConditionalFormattingNotContainsBlanks
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingNotContainsBlanks {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingNotContainsBlanks(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.NotContainsBlanks,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Formula = string.Format("LEN(TRIM({0}))>0", Address.Start.Address);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingNotContainsBlanks(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingNotContainsBlanks(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsErrors.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsErrors.cs
deleted file mode 100644
index e6fa828..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsErrors.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingNotContainsErrors
-/// </summary>
-public class ExcelConditionalFormattingNotContainsErrors
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingNotContainsErrors {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingNotContainsErrors(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.NotContainsErrors,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Formula = string.Format("NOT(ISERROR({0}))", Address.Start.Address);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingNotContainsErrors(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingNotContainsErrors(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsText.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsText.cs
deleted file mode 100644
index 1b86511..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsText.cs
+++ /dev/null
@@ -1,112 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingNotContainsText
-/// </summary>
-public class ExcelConditionalFormattingNotContainsText
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingNotContainsText {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingNotContainsText(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.NotContainsText,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.NotContains;
- Text = string.Empty;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingNotContainsText(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingNotContainsText(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-
- /// <summary>
- /// The text to search inside the cell
- /// </summary>
- public string Text {
- get => GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute);
- set {
- SetXmlNodeString(ExcelConditionalFormattingConstants.Paths._textAttribute, value);
-
- Formula = string.Format(
- "ISERROR(SEARCH(\"{1}\",{0}))",
- Address.Start.Address,
- value.Replace("\"", "\"\""));
- }
- }
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotEqual.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotEqual.cs
deleted file mode 100644
index 8782151..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotEqual.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingNotEqual
-/// </summary>
-public class ExcelConditionalFormattingNotEqual
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingNotEqual {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingNotEqual(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.NotEqual,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.NotEqual;
- Formula = string.Empty;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingNotEqual(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingNotEqual(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingRule.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingRule.cs
deleted file mode 100644
index 082da63..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingRule.cs
+++ /dev/null
@@ -1,492 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Immutable;
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-using OfficeOpenXml.Style.Dxf;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-///
-/// </summary>
-public abstract class ExcelConditionalFormattingRule : XmlHelper, IExcelConditionalFormattingRule {
- private eExcelConditionalFormattingRuleType? _type;
- private readonly ExcelWorksheet _worksheet;
-
- /// <summary>
- /// Sinalize that we are in a Cnaging Priorities opeartion so that we won't enter
- /// a recursive loop.
- /// </summary>
- private static bool _changingPriority;
-
- protected override ImmutableArray<string> SchemaNodeOrder =>
- ExcelWorksheet.WorksheetSchemaNodeOrder;
-
- /// <summary>
- /// Initialize the <see cref="ExcelConditionalFormattingRule"/>
- /// </summary>
- /// <param name="type"></param>
- /// <param name="address"></param>
- /// <param name="priority">Used also as the cfRule unique key</param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingRule(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(namespaceManager, itemElementNode) {
- Require.Argument(address).IsNotNull("address");
- Require.Argument(priority).IsInRange(1, int.MaxValue, "priority");
- Require.Argument(worksheet).IsNotNull("worksheet");
-
- _type = type;
- _worksheet = worksheet;
-
- if (itemElementNode == null) {
- // Create/Get the <cfRule> inside <conditionalFormatting>
- itemElementNode = CreateComplexNode(
- _worksheet.WorksheetXml.DocumentElement,
- string.Format(
- "{0}[{1}='{2}']/{1}='{2}'/{3}[{4}='{5}']/{4}='{5}'",
- //{0}
- ExcelConditionalFormattingConstants.Paths._conditionalFormatting,
- // {1}
- ExcelConditionalFormattingConstants.Paths._sqrefAttribute,
- // {2}
- address.AddressSpaceSeparated, //CF node don't what to have comma between multi addresses, use space instead.
- // {3}
- ExcelConditionalFormattingConstants.Paths._cfRule,
- //{4}
- ExcelConditionalFormattingConstants.Paths._priorityAttribute,
- //{5}
- priority));
- }
-
- // Point to <cfRule>
- TopNode = itemElementNode;
-
- Address = address;
- Priority = priority;
- Type = type;
- if (DxfId >= 0) {
- worksheet.Workbook.Styles.Dxfs[DxfId].AllowChange = true; //This Id is referenced by CF, so we can use it when we save.
- _style = worksheet.Workbook.Styles.Dxfs[DxfId].Clone(); //Clone, so it can be altered without effecting other dxf styles
- }
- }
-
- /// <summary>
- /// Initialize the <see cref="ExcelConditionalFormattingRule"/>
- /// </summary>
- /// <param name="type"></param>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingRule(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNamespaceManager namespaceManager)
- : this(type, address, priority, worksheet, null, namespaceManager) {}
-
- /// <summary>
- /// Get the <cfRule> node
- /// </summary>
- public XmlNode Node => TopNode;
-
- /// <summary>
- /// Address of the conditional formatting rule
- /// </summary>
- /// <remarks>
- /// The address is stores in a parent node called <conditionalFormatting> in the
- /// @sqref attribute. Excel groups rules that have the same address inside one node.
- /// </remarks>
- public ExcelAddress Address {
- get =>
- new(Node.ParentNode.Attributes[ExcelConditionalFormattingConstants.Attributes._sqref].Value);
- set {
- // Check if the address is to be changed
- if (Address.Address != value.Address) {
- // Save the old parente node
- XmlNode oldNode = Node;
- XmlNode oldParentNode = Node.ParentNode;
-
- // Create/Get the new <conditionalFormatting> parent node
- XmlNode newParentNode = CreateComplexNode(
- _worksheet.WorksheetXml.DocumentElement,
- string.Format(
- "{0}[{1}='{2}']/{1}='{2}'",
- //{0}
- ExcelConditionalFormattingConstants.Paths._conditionalFormatting,
- // {1}
- ExcelConditionalFormattingConstants.Paths._sqrefAttribute,
- // {2}
- value.AddressSpaceSeparated));
-
- // Move the <cfRule> node to the new <conditionalFormatting> parent node
- TopNode = newParentNode.AppendChild(Node);
-
- // Check if the old <conditionalFormatting> parent node has <cfRule> node inside it
- if (!oldParentNode.HasChildNodes) {
- // Remove the old parent node
- oldParentNode.ParentNode.RemoveChild(oldParentNode);
- }
- }
- }
- }
-
- /// <summary>
- /// Type of conditional formatting rule. ST_CfType §18.18.12.
- /// </summary>
- public eExcelConditionalFormattingRuleType Type {
- get {
- // Transform the @type attribute to EPPlus Rule Type (slighty diferente)
- if (_type == null) {
- _type = ExcelConditionalFormattingRuleType.GetTypeByAttrbiute(
- GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._typeAttribute),
- TopNode,
- _worksheet.NameSpaceManager);
- }
- return (eExcelConditionalFormattingRuleType)_type;
- }
- internal set {
- _type = value;
- // Transform the EPPlus Rule Type to @type attribute (slighty diferente)
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths._typeAttribute,
- ExcelConditionalFormattingRuleType.GetAttributeByType(value),
- true);
- }
- }
-
- /// <summary>
- /// The priority of this conditional formatting rule. This value is used to determine
- /// which format should be evaluated and rendered. Lower numeric values are higher
- /// priority than higher numeric values, where 1 is the highest priority.
- /// </summary>
- public int Priority {
- get => GetXmlNodeInt(ExcelConditionalFormattingConstants.Paths._priorityAttribute);
- set {
- // Save the current CF rule priority
- int priority = Priority;
-
- // Check if the @priority is to be changed
- if (priority != value) {
- // Check if we are not already inside a "Change Priority" operation
- if (!_changingPriority) {
- if (value < 1) {
- throw new IndexOutOfRangeException(
- ExcelConditionalFormattingConstants.Errors._invalidPriority);
- }
-
- // Sinalize that we are already changing cfRules priorities
- _changingPriority = true;
-
- // Check if we lowered the priority
- if (priority > value) {
- for (int i = priority - 1; i >= value; i--) {
- var cfRule = _worksheet.ConditionalFormatting.RulesByPriority(i);
-
- if (cfRule != null) {
- cfRule.Priority++;
- }
- }
- } else {
- for (int i = priority + 1; i <= value; i++) {
- var cfRule = _worksheet.ConditionalFormatting.RulesByPriority(i);
-
- if (cfRule != null) {
- cfRule.Priority--;
- }
- }
- }
-
- // Sinalize that we are no longer changing cfRules priorities
- _changingPriority = false;
- }
-
- // Change the priority in the XML
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths._priorityAttribute,
- value.ToString(),
- true);
- }
- }
- }
-
- /// <summary>
- /// If this flag is true, no rules with lower priority shall be applied over this rule,
- /// when this rule evaluates to true.
- /// </summary>
- public bool StopIfTrue {
- get => GetXmlNodeBool(ExcelConditionalFormattingConstants.Paths._stopIfTrueAttribute);
- set =>
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths._stopIfTrueAttribute,
- value ? "1" : string.Empty,
- true);
- }
-
- /// <summary>
- /// DxfId Style Attribute
- /// </summary>
- internal int DxfId {
- get => GetXmlNodeInt(ExcelConditionalFormattingConstants.Paths._dxfIdAttribute);
- set =>
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths._dxfIdAttribute,
- (value == int.MinValue) ? string.Empty : value.ToString(),
- true);
- }
-
- internal ExcelDxfStyleConditionalFormatting _style;
-
- public ExcelDxfStyleConditionalFormatting Style {
- get {
- if (_style == null) {
- _style = new(NameSpaceManager, null, _worksheet.Workbook.Styles);
- }
- return _style;
- }
- }
-
- /// <summary>
- /// StdDev (zero is not allowed and will be converted to 1)
- /// </summary>
- public UInt16 StdDev {
- get =>
- Convert.ToUInt16(GetXmlNodeInt(ExcelConditionalFormattingConstants.Paths._stdDevAttribute));
- set =>
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths._stdDevAttribute,
- (value == 0) ? "1" : value.ToString(),
- true);
- }
-
- /// <summary>
- /// Rank (zero is not allowed and will be converted to 1)
- /// </summary>
- public UInt16 Rank {
- get =>
- Convert.ToUInt16(GetXmlNodeInt(ExcelConditionalFormattingConstants.Paths._rankAttribute));
- set =>
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths._rankAttribute,
- (value == 0) ? "1" : value.ToString(),
- true);
- }
-
- /// <summary>
- /// AboveAverage
- /// </summary>
- internal protected bool? AboveAverage {
- get {
- bool? aboveAverage = GetXmlNodeBoolNullable(
- ExcelConditionalFormattingConstants.Paths._aboveAverageAttribute);
-
- // Above Avarege if TRUE or if attribute does not exists
- return (aboveAverage == true) || (aboveAverage == null);
- }
- set {
- string aboveAverageValue = string.Empty;
-
- // Only the types that needs the @AboveAverage
- if ((_type == eExcelConditionalFormattingRuleType.BelowAverage)
- || (_type == eExcelConditionalFormattingRuleType.BelowOrEqualAverage)
- || (_type == eExcelConditionalFormattingRuleType.BelowStdDev)) {
- aboveAverageValue = "0";
- }
-
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths._aboveAverageAttribute,
- aboveAverageValue,
- true);
- }
- }
-
- /// <summary>
- /// EqualAverage
- /// </summary>
- internal protected bool? EqualAverage {
- get {
- bool? equalAverage = GetXmlNodeBoolNullable(
- ExcelConditionalFormattingConstants.Paths._equalAverageAttribute);
-
- // Equal Avarege only if TRUE
- return (equalAverage == true);
- }
- set {
- string equalAverageValue = string.Empty;
-
- // Only the types that needs the @EqualAverage
- if ((_type == eExcelConditionalFormattingRuleType.AboveOrEqualAverage)
- || (_type == eExcelConditionalFormattingRuleType.BelowOrEqualAverage)) {
- equalAverageValue = "1";
- }
-
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths._equalAverageAttribute,
- equalAverageValue,
- true);
- }
- }
-
- /// <summary>
- /// Bottom attribute
- /// </summary>
- internal protected bool? Bottom {
- get {
- bool? bottom = GetXmlNodeBoolNullable(
- ExcelConditionalFormattingConstants.Paths._bottomAttribute);
-
- // Bottom if TRUE
- return (bottom == true);
- }
- set {
- string bottomValue = string.Empty;
-
- // Only the types that needs the @Bottom
- if ((_type == eExcelConditionalFormattingRuleType.Bottom)
- || (_type == eExcelConditionalFormattingRuleType.BottomPercent)) {
- bottomValue = "1";
- }
-
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths._bottomAttribute,
- bottomValue,
- true);
- }
- }
-
- /// <summary>
- /// Percent attribute
- /// </summary>
- internal protected bool? Percent {
- get {
- bool? percent = GetXmlNodeBoolNullable(
- ExcelConditionalFormattingConstants.Paths._percentAttribute);
-
- // Bottom if TRUE
- return (percent == true);
- }
- set {
- string percentValue = string.Empty;
-
- // Only the types that needs the @Bottom
- if ((_type == eExcelConditionalFormattingRuleType.BottomPercent)
- || (_type == eExcelConditionalFormattingRuleType.TopPercent)) {
- percentValue = "1";
- }
-
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths._percentAttribute,
- percentValue,
- true);
- }
- }
-
- /// <summary>
- /// TimePeriod
- /// </summary>
- internal protected eExcelConditionalFormattingTimePeriodType TimePeriod {
- get =>
- ExcelConditionalFormattingTimePeriodType.GetTypeByAttribute(
- GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._timePeriodAttribute));
- set =>
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths._timePeriodAttribute,
- ExcelConditionalFormattingTimePeriodType.GetAttributeByType(value),
- true);
- }
-
- /// <summary>
- /// Operator
- /// </summary>
- internal protected eExcelConditionalFormattingOperatorType Operator {
- get =>
- ExcelConditionalFormattingOperatorType.GetTypeByAttribute(
- GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._operatorAttribute));
- set =>
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths._operatorAttribute,
- ExcelConditionalFormattingOperatorType.GetAttributeByType(value),
- true);
- }
-
- /// <summary>
- /// Formula
- /// </summary>
- public string Formula {
- get => GetXmlNodeString(ExcelConditionalFormattingConstants.Paths._formula);
- set => SetXmlNodeString(ExcelConditionalFormattingConstants.Paths._formula, value);
- }
-
- /// <summary>
- /// Formula2
- /// </summary>
- public string Formula2 {
- get =>
- GetXmlNodeString(
- string.Format(
- "{0}[position()=2]",
- // {0}
- ExcelConditionalFormattingConstants.Paths._formula));
- set {
- // Create/Get the first <formula> node (ensure that it exists)
- var firstNode = CreateComplexNode(
- TopNode,
- string.Format(
- "{0}[position()=1]",
- // {0}
- ExcelConditionalFormattingConstants.Paths._formula));
-
- // Create/Get the seconde <formula> node (ensure that it exists)
- var secondNode = CreateComplexNode(
- TopNode,
- string.Format(
- "{0}[position()=2]",
- // {0}
- ExcelConditionalFormattingConstants.Paths._formula));
-
- // Save the formula in the second <formula> node
- secondNode.InnerText = value;
- }
- }
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisMonth.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisMonth.cs
deleted file mode 100644
index db86666..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisMonth.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingThisMonth
-/// </summary>
-public class ExcelConditionalFormattingThisMonth : ExcelConditionalFormattingTimePeriodGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingThisMonth(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.ThisMonth,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- TimePeriod = eExcelConditionalFormattingTimePeriodType.ThisMonth;
- Formula = string.Format(
- "AND(MONTH({0})=MONTH(TODAY()), YEAR({0})=YEAR(TODAY()))",
- Address.Start.Address);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingThisMonth(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingThisMonth(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisWeek.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisWeek.cs
deleted file mode 100644
index 1635e36..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisWeek.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingThisWeek
-/// </summary>
-public class ExcelConditionalFormattingThisWeek : ExcelConditionalFormattingTimePeriodGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingThisWeek(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.ThisWeek,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- TimePeriod = eExcelConditionalFormattingTimePeriodType.ThisWeek;
- Formula = string.Format(
- "AND(TODAY()-ROUNDDOWN({0},0)<=WEEKDAY(TODAY())-1,ROUNDDOWN({0},0)-TODAY()<=7-WEEKDAY(TODAY()))",
- Address.Start.Address);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingThisWeek(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingThisWeek(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeColorScale.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeColorScale.cs
deleted file mode 100644
index 23c8d02..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeColorScale.cs
+++ /dev/null
@@ -1,142 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingThreeColorScale
-/// </summary>
-public class ExcelConditionalFormattingThreeColorScale
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingThreeColorScale {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingThreeColorScale(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.ThreeColorScale,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- // Create the <colorScale> node inside the <cfRule> node
- var colorScaleNode = CreateComplexNode(
- Node,
- ExcelConditionalFormattingConstants.Paths._colorScale);
-
- // LowValue default
- LowValue = new(
- eExcelConditionalFormattingValueObjectPosition.Low,
- eExcelConditionalFormattingValueObjectType.Min,
- eExcelConditionalFormattingRuleType.ThreeColorScale,
- address,
- priority,
- worksheet,
- NameSpaceManager);
-
- // MiddleValue default
- MiddleValue = new(
- eExcelConditionalFormattingValueObjectPosition.Middle,
- eExcelConditionalFormattingValueObjectType.Percent,
- 50,
- string.Empty,
- eExcelConditionalFormattingRuleType.ThreeColorScale,
- address,
- priority,
- worksheet,
- NameSpaceManager);
-
- // HighValue default
- HighValue = new(
- eExcelConditionalFormattingValueObjectPosition.High,
- eExcelConditionalFormattingValueObjectType.Max,
- eExcelConditionalFormattingRuleType.ThreeColorScale,
- address,
- priority,
- worksheet,
- NameSpaceManager);
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingThreeColorScale(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingThreeColorScale(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-
- /// <summary>
- /// Low Value for Three Color Scale Object Value
- /// </summary>
- public ExcelConditionalFormattingColorScaleValue LowValue { get; set; }
-
- /// <summary>
- /// Middle Value for Three Color Scale Object Value
- /// </summary>
- public ExcelConditionalFormattingColorScaleValue MiddleValue { get; set; }
-
- /// <summary>
- /// High Value for Three Color Scale Object Value
- /// </summary>
- public ExcelConditionalFormattingColorScaleValue HighValue { get; set; }
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeIconSet.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeIconSet.cs
deleted file mode 100644
index bcf19e1..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeIconSet.cs
+++ /dev/null
@@ -1,278 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System;
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-public class ExcelConditionalFormattingThreeIconSet
- : ExcelConditionalFormattingIconSetBase<eExcelconditionalFormatting3IconsSetType> {
- internal ExcelConditionalFormattingThreeIconSet(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.ThreeIconSet,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {}
-}
-
-/// <summary>
-/// ExcelConditionalFormattingThreeIconSet
-/// </summary>
-public class ExcelConditionalFormattingIconSetBase<T>
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingThreeIconSet<T> {
- /// <summary>
- ///
- /// </summary>
- /// <param name="type"></param>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingIconSetBase(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- type,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode != null && itemElementNode.HasChildNodes) {
- int pos = 1;
- foreach (XmlNode node in itemElementNode.SelectNodes("d:iconSet/d:cfvo", NameSpaceManager)) {
- if (pos == 1) {
- Icon1 = new(type, address, worksheet, node, namespaceManager);
- } else if (pos == 2) {
- Icon2 = new(type, address, worksheet, node, namespaceManager);
- } else if (pos == 3) {
- Icon3 = new(type, address, worksheet, node, namespaceManager);
- } else {
- break;
- }
- pos++;
- }
- } else {
- var iconSetNode = CreateComplexNode(Node, ExcelConditionalFormattingConstants.Paths._iconSet);
-
- //Create the <iconSet> node inside the <cfRule> node
- double spann;
- if (type == eExcelConditionalFormattingRuleType.ThreeIconSet) {
- spann = 3;
- } else if (type == eExcelConditionalFormattingRuleType.FourIconSet) {
- spann = 4;
- } else {
- spann = 5;
- }
-
- var iconNode1 = iconSetNode.OwnerDocument.CreateElement(
- ExcelConditionalFormattingConstants.Paths._cfvo,
- ExcelPackage._schemaMain);
- iconSetNode.AppendChild(iconNode1);
- Icon1 = new(
- eExcelConditionalFormattingValueObjectType.Percent,
- 0,
- "",
- eExcelConditionalFormattingRuleType.ThreeIconSet,
- address,
- priority,
- worksheet,
- iconNode1,
- namespaceManager);
-
- var iconNode2 = iconSetNode.OwnerDocument.CreateElement(
- ExcelConditionalFormattingConstants.Paths._cfvo,
- ExcelPackage._schemaMain);
- iconSetNode.AppendChild(iconNode2);
- Icon2 = new(
- eExcelConditionalFormattingValueObjectType.Percent,
- Math.Round(100D / spann, 0),
- "",
- eExcelConditionalFormattingRuleType.ThreeIconSet,
- address,
- priority,
- worksheet,
- iconNode2,
- namespaceManager);
-
- var iconNode3 = iconSetNode.OwnerDocument.CreateElement(
- ExcelConditionalFormattingConstants.Paths._cfvo,
- ExcelPackage._schemaMain);
- iconSetNode.AppendChild(iconNode3);
- Icon3 = new(
- eExcelConditionalFormattingValueObjectType.Percent,
- Math.Round(100D * (2D / spann), 0),
- "",
- eExcelConditionalFormattingRuleType.ThreeIconSet,
- address,
- priority,
- worksheet,
- iconNode3,
- namespaceManager);
- Type = type;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- ///<param name="type"></param>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingIconSetBase(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(type, address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- ///<param name="type"></param>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingIconSetBase(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(type, address, priority, worksheet, null, null) {}
-
- /// <summary>
- /// Settings for icon 1 in the iconset
- /// </summary>
- public ExcelConditionalFormattingIconDataBarValue Icon1 { get; internal set; }
-
- /// <summary>
- /// Settings for icon 2 in the iconset
- /// </summary>
- public ExcelConditionalFormattingIconDataBarValue Icon2 { get; internal set; }
-
- /// <summary>
- /// Settings for icon 2 in the iconset
- /// </summary>
- public ExcelConditionalFormattingIconDataBarValue Icon3 { get; internal set; }
-
- private const string _reversePath = "d:iconSet/@reverse";
-
- /// <summary>
- /// Reverse the order of the icons
- /// </summary>
- public bool Reverse {
- get => GetXmlNodeBool(_reversePath, false);
- set => SetXmlNodeBool(_reversePath, value);
- }
-
- private const string _showValuePath = "d:iconSet/@showValue";
-
- /// <summary>
- /// If the cell values are visible
- /// </summary>
- public bool ShowValue {
- get => GetXmlNodeBool(_showValuePath, true);
- set => SetXmlNodeBool(_showValuePath, value);
- }
-
- private const string _iconSetPath = "d:iconSet/@iconSet";
-
- private string GetIconSetString(T value) {
- if (Type == eExcelConditionalFormattingRuleType.FourIconSet) {
- switch (value.ToString()) {
- case "Arrows":
- return "4Arrows";
- case "ArrowsGray":
- return "4ArrowsGray";
- case "Rating":
- return "4Rating";
- case "RedToBlack":
- return "4RedToBlack";
- case "TrafficLights":
- return "4TrafficLights";
- default:
- throw (new ArgumentException("Invalid type"));
- }
- }
- if (Type == eExcelConditionalFormattingRuleType.FiveIconSet) {
- switch (value.ToString()) {
- case "Arrows":
- return "5Arrows";
- case "ArrowsGray":
- return "5ArrowsGray";
- case "Quarters":
- return "5Quarters";
- case "Rating":
- return "5Rating";
- default:
- throw (new ArgumentException("Invalid type"));
- }
- }
- switch (value.ToString()) {
- case "Arrows":
- return "3Arrows";
- case "ArrowsGray":
- return "3ArrowsGray";
- case "Flags":
- return "3Flags";
- case "Signs":
- return "3Signs";
- case "Symbols":
- return "3Symbols";
- case "Symbols2":
- return "3Symbols2";
- case "TrafficLights1":
- return "3TrafficLights1";
- case "TrafficLights2":
- return "3TrafficLights2";
- default:
- throw (new ArgumentException("Invalid type"));
- }
- }
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTimePeriodGroup.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTimePeriodGroup.cs
deleted file mode 100644
index 52fe1ab..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTimePeriodGroup.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingTimePeriodGroup
-/// </summary>
-public class ExcelConditionalFormattingTimePeriodGroup
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingTimePeriodGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="type"></param>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingTimePeriodGroup(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- type,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="type"></param>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingTimePeriodGroup(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(type, address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="type"></param>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingTimePeriodGroup(
- eExcelConditionalFormattingRuleType type,
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(type, address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingToday.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingToday.cs
deleted file mode 100644
index b2d1755..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingToday.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingToday
-/// </summary>
-public class ExcelConditionalFormattingToday : ExcelConditionalFormattingTimePeriodGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingToday(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.Today,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- TimePeriod = eExcelConditionalFormattingTimePeriodType.Today;
- Formula = string.Format("FLOOR({0},1)=TODAY()", Address.Start.Address);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingToday(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingToday(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTomorrow.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTomorrow.cs
deleted file mode 100644
index fcfab71..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTomorrow.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingTomorrow
-/// </summary>
-public class ExcelConditionalFormattingTomorrow : ExcelConditionalFormattingTimePeriodGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingTomorrow(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.Tomorrow,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- TimePeriod = eExcelConditionalFormattingTimePeriodType.Tomorrow;
- Formula = string.Format("FLOOR({0},1)=TODAY()+1", Address.Start.Address);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingTomorrow(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingTomorrow(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTop.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTop.cs
deleted file mode 100644
index 5672d2d..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTop.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingTop
-/// </summary>
-public class ExcelConditionalFormattingTop
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingTopBottomGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingTop(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.Top,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Bottom = false;
- Percent = false;
- Rank = 10; // First 10 values
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingTop(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingTop(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTopPercent.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTopPercent.cs
deleted file mode 100644
index 0d4a06c..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTopPercent.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingTopPercent
-/// </summary>
-public class ExcelConditionalFormattingTopPercent
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingTopBottomGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingTopPercent(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.TopPercent,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- Bottom = false;
- Percent = true;
- Rank = 10; // First 10 percent
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingTopPercent(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingTopPercent(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTwoColorScale.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTwoColorScale.cs
deleted file mode 100644
index 691f0dd..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTwoColorScale.cs
+++ /dev/null
@@ -1,141 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingTwoColorScale
-/// </summary>
-public class ExcelConditionalFormattingTwoColorScale
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingTwoColorScale {
- /// <summary>
- /// Private Low Value
- /// </summary>
- private ExcelConditionalFormattingColorScaleValue _lowValue;
-
- /// <summary>
- /// Private High Value
- /// </summary>
- private ExcelConditionalFormattingColorScaleValue _highValue;
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingTwoColorScale(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.TwoColorScale,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- // Create the <colorScale> node inside the <cfRule> node
- var colorScaleNode = CreateComplexNode(
- Node,
- ExcelConditionalFormattingConstants.Paths._colorScale);
-
- // LowValue default
- LowValue = new(
- eExcelConditionalFormattingValueObjectPosition.Low,
- eExcelConditionalFormattingValueObjectType.Min,
- eExcelConditionalFormattingRuleType.TwoColorScale,
- address,
- priority,
- worksheet,
- NameSpaceManager);
-
- // HighValue default
- HighValue = new(
- eExcelConditionalFormattingValueObjectPosition.High,
- eExcelConditionalFormattingValueObjectType.Max,
- eExcelConditionalFormattingRuleType.TwoColorScale,
- address,
- priority,
- worksheet,
- NameSpaceManager);
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingTwoColorScale(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingTwoColorScale(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-
- /// <summary>
- /// Low Value for Two Color Scale Object Value
- /// </summary>
- public ExcelConditionalFormattingColorScaleValue LowValue {
- get => _lowValue;
- set => _lowValue = value;
- }
-
- /// <summary>
- /// High Value for Two Color Scale Object Value
- /// </summary>
- public ExcelConditionalFormattingColorScaleValue HighValue {
- get => _highValue;
- set => _highValue = value;
- }
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingUniqueValues.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingUniqueValues.cs
deleted file mode 100644
index ff0ba0d..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingUniqueValues.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingUniqueValues
-/// </summary>
-public class ExcelConditionalFormattingUniqueValues
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingUniqueValues {
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingUniqueValues(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.UniqueValues,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingUniqueValues(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingUniqueValues(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingYesterday.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingYesterday.cs
deleted file mode 100644
index a5701ec..0000000
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingYesterday.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Eyal Seagull Added 2012-04-03
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.ConditionalFormatting;
-
-/// <summary>
-/// ExcelConditionalFormattingYesterday
-/// </summary>
-public class ExcelConditionalFormattingYesterday : ExcelConditionalFormattingTimePeriodGroup {
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingYesterday(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(
- eExcelConditionalFormattingRuleType.Yesterday,
- address,
- priority,
- worksheet,
- itemElementNode,
- namespaceManager ?? worksheet.NameSpaceManager) {
- if (itemElementNode
- == null) //Set default values and create attributes if needed
- {
- TimePeriod = eExcelConditionalFormattingTimePeriodType.Yesterday;
- Formula = string.Format("FLOOR({0},1)=TODAY()-1", Address.Start.Address);
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingYesterday(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet,
- XmlNode itemElementNode)
- : this(address, priority, worksheet, itemElementNode, null) {}
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingYesterday(
- ExcelAddress address,
- int priority,
- ExcelWorksheet worksheet)
- : this(address, priority, worksheet, null, null) {}
-}
diff --git a/EPPlus/DataValidation/Contracts/IExcelDataValidation.cs b/EPPlus/DataValidation/Contracts/IExcelDataValidation.cs
deleted file mode 100644
index 7917008..0000000
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidation.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-namespace OfficeOpenXml.DataValidation.Contracts;
-
-/// <summary>
-/// Interface for data validation
-/// </summary>
-public interface IExcelDataValidation {
- /// <summary>
- /// Address of data validation
- /// </summary>
- ExcelAddress Address { get; }
-
- /// <summary>
- /// Validation type
- /// </summary>
- ExcelDataValidationType ValidationType { get; }
-
- /// <summary>
- /// Controls how Excel will handle invalid values.
- /// </summary>
- ExcelDataValidationWarningStyle ErrorStyle { get; }
-
- /// <summary>
- /// True if input message should be shown
- /// </summary>
- bool? AllowBlank { get; set; }
-
- /// <summary>
- /// True if input message should be shown
- /// </summary>
- bool? ShowInputMessage { get; set; }
-
- /// <summary>
- /// True if error message should be shown.
- /// </summary>
- bool? ShowErrorMessage { get; set; }
-
- /// <summary>
- /// Title of error message box (see property ShowErrorMessage)
- /// </summary>
- string ErrorTitle { get; set; }
-
- /// <summary>
- /// Error message box text (see property ShowErrorMessage)
- /// </summary>
- string Error { get; set; }
-
- /// <summary>
- /// Title of info box if input message should be shown (see property ShowInputMessage)
- /// </summary>
- string PromptTitle { get; set; }
-
- /// <summary>
- /// Info message text (see property ShowErrorMessage)
- /// </summary>
- string Prompt { get; set; }
-
- /// <summary>
- /// True if the current validation type allows operator.
- /// </summary>
- bool AllowsOperator { get; }
-
- /// <summary>
- /// Validates the state of the validation.
- /// </summary>
- void Validate();
-}
diff --git a/EPPlus/DataValidation/Contracts/IExcelDataValidationAny.cs b/EPPlus/DataValidation/Contracts/IExcelDataValidationAny.cs
deleted file mode 100644
index c3b6bfd..0000000
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationAny.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Raziq York Added 2014-08-08
- *******************************************************************************/
-
-namespace OfficeOpenXml.DataValidation.Contracts;
-
-/// <summary>
-/// Data validation interface for Any value validation.
-/// </summary>
-public interface IExcelDataValidationAny : IExcelDataValidation {}
diff --git a/EPPlus/DataValidation/Contracts/IExcelDataValidationCustom.cs b/EPPlus/DataValidation/Contracts/IExcelDataValidationCustom.cs
deleted file mode 100644
index f567ce4..0000000
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationCustom.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation.Contracts;
-
-/// <summary>
-/// Data validation interface for custom validation.
-/// </summary>
-public interface IExcelDataValidationCustom
- : IExcelDataValidationWithFormula<IExcelDataValidationFormula>,
- IExcelDataValidationWithOperator {}
diff --git a/EPPlus/DataValidation/Contracts/IExcelDataValidationDateTime.cs b/EPPlus/DataValidation/Contracts/IExcelDataValidationDateTime.cs
deleted file mode 100644
index 6ab40d0..0000000
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationDateTime.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation.Contracts;
-
-/// <summary>
-/// Validation interface for datetime validations
-/// </summary>
-public interface IExcelDataValidationDateTime
- : IExcelDataValidationWithFormula2<IExcelDataValidationFormulaDateTime>,
- IExcelDataValidationWithOperator {}
diff --git a/EPPlus/DataValidation/Contracts/IExcelDataValidationDecimal.cs b/EPPlus/DataValidation/Contracts/IExcelDataValidationDecimal.cs
deleted file mode 100644
index 48983ed..0000000
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationDecimal.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation.Contracts;
-
-/// <summary>
-/// Data validation interface for decimal values
-/// </summary>
-public interface IExcelDataValidationDecimal
- : IExcelDataValidationWithFormula2<IExcelDataValidationFormulaDecimal>,
- IExcelDataValidationWithOperator {}
diff --git a/EPPlus/DataValidation/Contracts/IExcelDataValidationInt.cs b/EPPlus/DataValidation/Contracts/IExcelDataValidationInt.cs
deleted file mode 100644
index 9d984e2..0000000
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationInt.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation.Contracts;
-
-public interface IExcelDataValidationInt
- : IExcelDataValidationWithFormula2<IExcelDataValidationFormulaInt>,
- IExcelDataValidationWithOperator {}
diff --git a/EPPlus/DataValidation/Contracts/IExcelDataValidationList.cs b/EPPlus/DataValidation/Contracts/IExcelDataValidationList.cs
deleted file mode 100644
index 13bb5a9..0000000
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationList.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation.Contracts;
-
-public interface IExcelDataValidationList
- : IExcelDataValidationWithFormula<IExcelDataValidationFormulaList> {}
diff --git a/EPPlus/DataValidation/Contracts/IExcelDataValidationTime.cs b/EPPlus/DataValidation/Contracts/IExcelDataValidationTime.cs
deleted file mode 100644
index 4c57587..0000000
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationTime.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation.Contracts;
-
-/// <summary>
-/// Data validation interface for time validation.
-/// </summary>
-public interface IExcelDataValidationTime
- : IExcelDataValidationWithFormula2<IExcelDataValidationFormulaTime>,
- IExcelDataValidationWithOperator {}
diff --git a/EPPlus/DataValidation/Contracts/IExcelDataValidationWithFormula.cs b/EPPlus/DataValidation/Contracts/IExcelDataValidationWithFormula.cs
deleted file mode 100644
index b93dd30..0000000
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationWithFormula.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation.Contracts;
-
-public interface IExcelDataValidationWithFormula<T> : IExcelDataValidation
- where T : IExcelDataValidationFormula {
- T Formula { get; }
-}
diff --git a/EPPlus/DataValidation/Contracts/IExcelDataValidationWithFormula2.cs b/EPPlus/DataValidation/Contracts/IExcelDataValidationWithFormula2.cs
deleted file mode 100644
index 2f6692b..0000000
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationWithFormula2.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation.Contracts;
-
-/// <summary>
-/// Interface for a data validation with two formulas
-/// </summary>
-/// <typeparam name="T"></typeparam>
-public interface IExcelDataValidationWithFormula2<T> : IExcelDataValidationWithFormula<T>
- where T : IExcelDataValidationFormula {
- /// <summary>
- /// Formula 2
- /// </summary>
- T Formula2 { get; }
-}
diff --git a/EPPlus/DataValidation/Contracts/IExcelDataValidationWithOperator.cs b/EPPlus/DataValidation/Contracts/IExcelDataValidationWithOperator.cs
deleted file mode 100644
index 2604079..0000000
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationWithOperator.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-namespace OfficeOpenXml.DataValidation.Contracts;
-
-/// <summary>
-/// Represents a validation with an operator
-/// </summary>
-public interface IExcelDataValidationWithOperator {
- /// <summary>
- /// Operator type
- /// </summary>
- ExcelDataValidationOperator Operator { get; }
-}
diff --git a/EPPlus/DataValidation/ExcelDataValidation.cs b/EPPlus/DataValidation/ExcelDataValidation.cs
deleted file mode 100644
index 1e5f445..0000000
--- a/EPPlus/DataValidation/ExcelDataValidation.cs
+++ /dev/null
@@ -1,285 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Collections.Immutable;
-using System.Globalization;
-using System.Text.RegularExpressions;
-using System.Xml;
-using OfficeOpenXml.DataValidation.Contracts;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// Excel datavalidation
-/// </summary>
-public abstract class ExcelDataValidation : XmlHelper, IExcelDataValidation {
- private const string _itemElementNodeName = "d:dataValidation";
-
- private readonly string _errorStylePath = "@errorStyle";
- private readonly string _errorTitlePath = "@errorTitle";
- private readonly string _errorPath = "@error";
- private readonly string _promptTitlePath = "@promptTitle";
- private readonly string _promptPath = "@prompt";
- private readonly string _operatorPath = "@operator";
- private readonly string _showErrorMessagePath = "@showErrorMessage";
- private readonly string _showInputMessagePath = "@showInputMessage";
- private readonly string _typeMessagePath = "@type";
- private readonly string _sqrefPath = "@sqref";
- private readonly string _allowBlankPath = "@allowBlank";
- protected readonly string _formula1Path = "d:formula1";
- protected readonly string _formula2Path = "d:formula2";
-
- protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
- "type",
- "errorStyle",
- "operator",
- "allowBlank",
- "showInputMessage",
- "showErrorMessage",
- "errorTitle",
- "error",
- "promptTitle",
- "prompt",
- "sqref",
- "formula1",
- "formula2",
- ];
-
- internal ExcelDataValidation(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType)
- : this(worksheet, address, validationType, null) {}
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet">worksheet that owns the validation</param>
- /// <param name="itemElementNode">Xml top node (dataValidations)</param>
- /// <param name="validationType">Data validation type</param>
- /// <param name="address">address for data validation</param>
- internal ExcelDataValidation(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode)
- : this(worksheet, address, validationType, itemElementNode, null) {}
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet">worksheet that owns the validation</param>
- /// <param name="itemElementNode">Xml top node (dataValidations) when importing xml</param>
- /// <param name="validationType">Data validation type</param>
- /// <param name="address">address for data validation</param>
- /// <param name="namespaceManager">Xml Namespace manager</param>
- internal ExcelDataValidation(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(namespaceManager ?? worksheet.NameSpaceManager) {
- Require.Argument(address).IsNotNullOrEmpty("address");
- address = CheckAndFixRangeAddress(address);
- if (itemElementNode == null) {
- //var xmlDoc = worksheet.WorksheetXml;
- TopNode = worksheet.WorksheetXml.SelectSingleNode(
- "//d:dataValidations",
- worksheet.NameSpaceManager);
- // did not succeed using the XmlHelper methods here... so I'm creating the new node using XmlDocument...
- var nsUri = NameSpaceManager.LookupNamespace("d");
- //itemElementNode = TopNode.OwnerDocument.CreateElement(_itemElementNodeName, nsUri);
- itemElementNode = TopNode.OwnerDocument.CreateElement(
- _itemElementNodeName.Split(':')[1],
- nsUri);
- TopNode.AppendChild(itemElementNode);
- }
- TopNode = itemElementNode;
- ValidationType = validationType;
- Address = new(address);
- }
-
- private string CheckAndFixRangeAddress(string address) {
- if (address.Contains(',')) {
- throw new FormatException("Multiple addresses may not be commaseparated, use space instead");
- }
- address = address.ToUpper(CultureInfo.InvariantCulture);
- if (Regex.IsMatch(address, "[A-Z]+:[A-Z]+")) {
- address = AddressUtility.ParseEntireColumnSelections(address);
- }
- return address;
- }
-
- private void SetNullableBoolValue(string path, bool? val) {
- if (val.HasValue) {
- SetXmlNodeBool(path, val.Value);
- } else {
- DeleteNode(path);
- }
- }
-
- /// <summary>
- /// This method will validate the state of the validation
- /// </summary>
- /// <exception cref="InvalidOperationException">If the state breaks the rules of the validation</exception>
- public virtual void Validate() {
- var address = Address.Address;
- // validate Formula1
- if (string.IsNullOrEmpty(Formula1Internal)) {
- throw new InvalidOperationException(
- "Validation of " + address + " failed: Formula1 cannot be empty");
- }
- }
-
- /// <summary>
- /// True if the validation type allows operator to be set.
- /// </summary>
- public bool AllowsOperator => ValidationType.AllowOperator;
-
- /// <summary>
- /// Address of data validation
- /// </summary>
- public ExcelAddress Address {
- get => new(GetXmlNodeString(_sqrefPath));
- private set {
- var address = AddressUtility.ParseEntireColumnSelections(value.Address);
- SetXmlNodeString(_sqrefPath, address);
- }
- }
-
- /// <summary>
- /// Validation type
- /// </summary>
- public ExcelDataValidationType ValidationType {
- get {
- var typeString = GetXmlNodeString(_typeMessagePath);
- return ExcelDataValidationType.GetBySchemaName(typeString);
- }
- private set => SetXmlNodeString(_typeMessagePath, value.SchemaName, true);
- }
-
- /// <summary>
- /// Operator for comparison between the entered value and Formula/Formulas.
- /// </summary>
- public ExcelDataValidationOperator Operator {
- get {
- var operatorString = GetXmlNodeString(_operatorPath);
- return Enum.TryParse<ExcelDataValidationOperator>(operatorString, true, out var op)
- ? op
- : ExcelDataValidationOperator.Any;
- }
- }
-
- /// <summary>
- /// Warning style
- /// </summary>
- public ExcelDataValidationWarningStyle ErrorStyle {
- get {
- var errorStyleString = GetXmlNodeString(_errorStylePath);
- return Enum.TryParse<ExcelDataValidationWarningStyle>(errorStyleString, true, out var style)
- ? style
- : ExcelDataValidationWarningStyle.Undefined;
- }
- }
-
- /// <summary>
- /// True if blanks should be allowed
- /// </summary>
- public bool? AllowBlank {
- get => GetXmlNodeBoolNullable(_allowBlankPath);
- set => SetNullableBoolValue(_allowBlankPath, value);
- }
-
- /// <summary>
- /// True if input message should be shown
- /// </summary>
- public bool? ShowInputMessage {
- get => GetXmlNodeBoolNullable(_showInputMessagePath);
- set => SetNullableBoolValue(_showInputMessagePath, value);
- }
-
- /// <summary>
- /// True if error message should be shown
- /// </summary>
- public bool? ShowErrorMessage {
- get => GetXmlNodeBoolNullable(_showErrorMessagePath);
- set => SetNullableBoolValue(_showErrorMessagePath, value);
- }
-
- /// <summary>
- /// Title of error message box
- /// </summary>
- public string ErrorTitle {
- get => GetXmlNodeString(_errorTitlePath);
- set => SetXmlNodeString(_errorTitlePath, value);
- }
-
- /// <summary>
- /// Error message box text
- /// </summary>
- public string Error {
- get => GetXmlNodeString(_errorPath);
- set => SetXmlNodeString(_errorPath, value);
- }
-
- public string PromptTitle {
- get => GetXmlNodeString(_promptTitlePath);
- set => SetXmlNodeString(_promptTitlePath, value);
- }
-
- public string Prompt {
- get => GetXmlNodeString(_promptPath);
- set => SetXmlNodeString(_promptPath, value);
- }
-
- /// <summary>
- /// Formula 1
- /// </summary>
- protected string Formula1Internal => GetXmlNodeString(_formula1Path);
-
- /// <summary>
- /// Formula 2
- /// </summary>
- protected string Formula2Internal => GetXmlNodeString(_formula2Path);
-
- protected void SetValue<T>(T? val, string path)
- where T : struct {
- if (!val.HasValue) {
- DeleteNode(path);
- }
- var stringValue = val.Value.ToString().Replace(',', '.');
- SetXmlNodeString(path, stringValue);
- }
-}
diff --git a/EPPlus/DataValidation/ExcelDataValidationAny.cs b/EPPlus/DataValidation/ExcelDataValidationAny.cs
deleted file mode 100644
index 8d00268..0000000
--- a/EPPlus/DataValidation/ExcelDataValidationAny.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Raziq York Added 2014-08-08
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.DataValidation.Contracts;
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// Any value validation.
-/// </summary>
-public class ExcelDataValidationAny : ExcelDataValidation, IExcelDataValidationAny {
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- internal ExcelDataValidationAny(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType)
- : base(worksheet, address, validationType) {}
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelDataValidationAny(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode)
- : base(worksheet, address, validationType, itemElementNode) {}
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelDataValidationAny(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(worksheet, address, validationType, itemElementNode, namespaceManager) {}
-
- /// <summary>
- /// This method will validate the state of the validation
- /// </summary>
- public override void Validate() {}
-}
diff --git a/EPPlus/DataValidation/ExcelDataValidationCollection.cs b/EPPlus/DataValidation/ExcelDataValidationCollection.cs
deleted file mode 100644
index 3c186a5..0000000
--- a/EPPlus/DataValidation/ExcelDataValidationCollection.cs
+++ /dev/null
@@ -1,361 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Mats Alm Applying patch submitted 2011-11-14
- * by Ted Heatherington
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- * Raziq York Added support for Any type 2014-08-08
-*******************************************************************************/
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Xml;
-using OfficeOpenXml.DataValidation.Contracts;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// <para>
-/// Collection of <see cref="ExcelDataValidation"/>. This class is providing the API for EPPlus data validation.
-/// </para>
-/// <para>
-/// The public methods of this class (Add[...]Validation) will create a datavalidation entry in the worksheet. When this
-/// validation has been created changes to the properties will affect the workbook immediately.
-/// </para>
-/// <para>
-/// Each type of validation has either a formula or a typed value/values, except for custom validation which has a formula only.
-/// </para>
-/// <code>
-/// // Add a date time validation
-/// var validation = worksheet.DataValidation.AddDateTimeValidation("A1");
-/// // set validation properties
-/// validation.ShowErrorMessage = true;
-/// validation.ErrorTitle = "An invalid date was entered";
-/// validation.Error = "The date must be between 2011-01-31 and 2011-12-31";
-/// validation.Prompt = "Enter date here";
-/// validation.Formula.Value = DateTime.Parse("2011-01-01");
-/// validation.Formula2.Value = DateTime.Parse("2011-12-31");
-/// validation.Operator = ExcelDataValidationOperator.between;
-/// </code>
-/// </summary>
-public class ExcelDataValidationCollection : XmlHelper, IEnumerable<IExcelDataValidation> {
- private readonly List<IExcelDataValidation> _validations = new();
- private readonly ExcelWorksheet _worksheet;
-
- private const string _dataValidationPath = "//d:dataValidations";
- private readonly string DataValidationItemsPath = string.Format(
- "{0}/d:dataValidation",
- _dataValidationPath);
-
- protected override ImmutableArray<string> SchemaNodeOrder =>
- ExcelWorksheet.WorksheetSchemaNodeOrder;
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- internal ExcelDataValidationCollection(ExcelWorksheet worksheet)
- : base(worksheet.NameSpaceManager, worksheet.WorksheetXml.DocumentElement) {
- Require.Argument(worksheet).IsNotNull("worksheet");
- _worksheet = worksheet;
-
- // check existing nodes and load them
- var dataValidationNodes = worksheet.WorksheetXml.SelectNodes(
- DataValidationItemsPath,
- worksheet.NameSpaceManager);
- if (dataValidationNodes != null && dataValidationNodes.Count > 0) {
- foreach (XmlNode node in dataValidationNodes) {
- if (node.Attributes["sqref"] == null) {
- continue;
- }
-
- var addr = node.Attributes["sqref"].Value;
-
- var typeSchema = node.Attributes["type"] != null ? node.Attributes["type"].Value : "";
-
- var type = ExcelDataValidationType.GetBySchemaName(typeSchema);
- _validations.Add(ExcelDataValidationFactory.Create(type, worksheet, addr, node));
- }
- }
- }
-
- private void EnsureRootElementExists() {
- var node = _worksheet.WorksheetXml.SelectSingleNode(
- _dataValidationPath,
- _worksheet.NameSpaceManager);
- if (node == null) {
- CreateNode(_dataValidationPath.TrimStart('/'));
- }
- }
-
- /// <summary>
- /// Validates address - not empty, collisions
- /// </summary>
- /// <param name="address"></param>
- /// <param name="validatingValidation"></param>
- private void ValidateAddress(string address, IExcelDataValidation validatingValidation) {
- Require.Argument(address).IsNotNullOrEmpty("address");
-
- // ensure that the new address does not collide with an existing validation.
- var newAddress = new ExcelAddress(address);
- if (_validations.Count > 0) {
- foreach (var validation in _validations) {
- if (validatingValidation != null && validatingValidation == validation) {
- continue;
- }
- var result = validation.Address.Collide(newAddress);
- if (result != ExcelAddressBase.eAddressCollition.No) {
- throw new InvalidOperationException(
- string.Format(
- "The address ({0}) collides with an existing validation ({1})",
- address,
- validation.Address.Address));
- }
- }
- }
- }
-
- private void ValidateAddress(string address) {
- ValidateAddress(address, null);
- }
-
- /// <summary>
- /// Validates all data validations.
- /// </summary>
- internal void ValidateAll() {
- foreach (var validation in _validations) {
- validation.Validate();
-
- ValidateAddress(validation.Address.Address, validation);
- }
- }
-
- /// <summary>
- /// Adds a <see cref="ExcelDataValidationAny"/> to the worksheet.
- /// </summary>
- /// <param name="address">The range/address to validate</param>
- /// <returns></returns>
- public IExcelDataValidationAny AddAnyValidation(string address) {
- ValidateAddress(address);
- EnsureRootElementExists();
- var item = new ExcelDataValidationAny(_worksheet, address, ExcelDataValidationType.Any);
- _validations.Add(item);
- return item;
- }
-
- /// <summary>
- /// Adds an <see cref="IExcelDataValidationInt"/> to the worksheet. Whole means that the only accepted values
- /// are integer values.
- /// </summary>
- /// <param name="address">the range/address to validate</param>
- public IExcelDataValidationInt AddIntegerValidation(string address) {
- ValidateAddress(address);
- EnsureRootElementExists();
- var item = new ExcelDataValidationInt(_worksheet, address, ExcelDataValidationType.Whole);
- _validations.Add(item);
- return item;
- }
-
- /// <summary>
- /// Addes an <see cref="IExcelDataValidationDecimal"/> to the worksheet. The only accepted values are
- /// decimal values.
- /// </summary>
- /// <param name="address">The range/address to validate</param>
- /// <returns></returns>
- public IExcelDataValidationDecimal AddDecimalValidation(string address) {
- ValidateAddress(address);
- EnsureRootElementExists();
- var item = new ExcelDataValidationDecimal(_worksheet, address, ExcelDataValidationType.Decimal);
- _validations.Add(item);
- return item;
- }
-
- /// <summary>
- /// Adds an <see cref="IExcelDataValidationList"/> to the worksheet. The accepted values are defined
- /// in a list.
- /// </summary>
- /// <param name="address">The range/address to validate</param>
- /// <returns></returns>
- public IExcelDataValidationList AddListValidation(string address) {
- ValidateAddress(address);
- EnsureRootElementExists();
- var item = new ExcelDataValidationList(_worksheet, address, ExcelDataValidationType.List);
- _validations.Add(item);
- return item;
- }
-
- /// <summary>
- /// Adds an <see cref="IExcelDataValidationInt"/> regarding text length to the worksheet.
- /// </summary>
- /// <param name="address">The range/address to validate</param>
- /// <returns></returns>
- public IExcelDataValidationInt AddTextLengthValidation(string address) {
- ValidateAddress(address);
- EnsureRootElementExists();
- var item = new ExcelDataValidationInt(_worksheet, address, ExcelDataValidationType.TextLength);
- _validations.Add(item);
- return item;
- }
-
- /// <summary>
- /// Adds an <see cref="IExcelDataValidationDateTime"/> to the worksheet.
- /// </summary>
- /// <param name="address">The range/address to validate</param>
- /// <returns></returns>
- public IExcelDataValidationDateTime AddDateTimeValidation(string address) {
- ValidateAddress(address);
- EnsureRootElementExists();
- var item = new ExcelDataValidationDateTime(
- _worksheet,
- address,
- ExcelDataValidationType.DateTime);
- _validations.Add(item);
- return item;
- }
-
- public IExcelDataValidationTime AddTimeValidation(string address) {
- ValidateAddress(address);
- EnsureRootElementExists();
- var item = new ExcelDataValidationTime(_worksheet, address, ExcelDataValidationType.Time);
- _validations.Add(item);
- return item;
- }
-
- /// <summary>
- /// Adds a <see cref="ExcelDataValidationCustom"/> to the worksheet.
- /// </summary>
- /// <param name="address">The range/address to validate</param>
- /// <returns></returns>
- public IExcelDataValidationCustom AddCustomValidation(string address) {
- ValidateAddress(address);
- EnsureRootElementExists();
- var item = new ExcelDataValidationCustom(_worksheet, address, ExcelDataValidationType.Custom);
- _validations.Add(item);
- return item;
- }
-
- /// <summary>
- /// Removes an <see cref="ExcelDataValidation"/> from the collection.
- /// </summary>
- /// <param name="item">The item to remove</param>
- /// <returns>True if remove succeeds, otherwise false</returns>
- /// <exception cref="ArgumentNullException">if <paramref name="item"/> is null</exception>
- public bool Remove(IExcelDataValidation item) {
- if (!(item is ExcelDataValidation validation)) {
- throw new InvalidCastException(
- "The supplied item must inherit OfficeOpenXml.DataValidation.ExcelDataValidation");
- }
- Require.Argument(item).IsNotNull("item");
- TopNode.RemoveChild(validation.TopNode);
- return _validations.Remove(validation);
- }
-
- /// <summary>
- /// Number of validations
- /// </summary>
- public int Count => _validations.Count;
-
- /// <summary>
- /// Index operator, returns by 0-based index
- /// </summary>
- /// <param name="index"></param>
- /// <returns></returns>
- public IExcelDataValidation this[int index] {
- get => _validations[index];
- set => _validations[index] = value;
- }
-
- /// <summary>
- /// Index operator, returns a data validation which address partly or exactly matches the searched address.
- /// </summary>
- /// <param name="address">A cell address or range</param>
- /// <returns>A <see cref="ExcelDataValidation"/> or null if no match</returns>
- public IExcelDataValidation this[string address] {
- get {
- var searchedAddress = new ExcelAddress(address);
- return _validations.Find(x =>
- x.Address.Collide(searchedAddress) != ExcelAddressBase.eAddressCollition.No);
- }
- }
-
- /// <summary>
- /// Returns all validations that matches the supplied predicate <paramref name="match"/>.
- /// </summary>
- /// <param name="match">predicate to filter out matching validations</param>
- /// <returns></returns>
- public IEnumerable<IExcelDataValidation> FindAll(Predicate<IExcelDataValidation> match) {
- return _validations.FindAll(match);
- }
-
- /// <summary>
- /// Returns the first matching validation.
- /// </summary>
- /// <param name="match"></param>
- /// <returns></returns>
- public IExcelDataValidation Find(Predicate<IExcelDataValidation> match) {
- return _validations.Find(match);
- }
-
- /// <summary>
- /// Removes all validations from the collection.
- /// </summary>
- public void Clear() {
- DeleteAllNode(DataValidationItemsPath.TrimStart('/'));
- _validations.Clear();
- }
-
- /// <summary>
- /// Removes the validations that matches the predicate
- /// </summary>
- /// <param name="match"></param>
- public void RemoveAll(Predicate<IExcelDataValidation> match) {
- var matches = _validations.FindAll(match);
- foreach (var m in matches) {
- if (!(m is ExcelDataValidation validation)) {
- throw new InvalidCastException(
- "The supplied item must inherit OfficeOpenXml.DataValidation.ExcelDataValidation");
- }
- TopNode
- .SelectSingleNode(_dataValidationPath.TrimStart('/'), NameSpaceManager)
- .RemoveChild(validation.TopNode);
- }
- _validations.RemoveAll(match);
- }
-
- IEnumerator<IExcelDataValidation> IEnumerable<IExcelDataValidation>.GetEnumerator() {
- return _validations.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- return _validations.GetEnumerator();
- }
-}
diff --git a/EPPlus/DataValidation/ExcelDataValidationCustom.cs b/EPPlus/DataValidation/ExcelDataValidationCustom.cs
deleted file mode 100644
index f98b2f6..0000000
--- a/EPPlus/DataValidation/ExcelDataValidationCustom.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.DataValidation.Contracts;
-using OfficeOpenXml.DataValidation.Formulas;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// Custom validation, i.e. a formula.
-/// </summary>
-public class ExcelDataValidationCustom
- : ExcelDataValidationWithFormula<IExcelDataValidationFormula>,
- IExcelDataValidationCustom {
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- internal ExcelDataValidationCustom(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType)
- : base(worksheet, address, validationType) {
- Formula = new ExcelDataValidationFormulaCustom(NameSpaceManager, TopNode, _formula1Path);
- }
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelDataValidationCustom(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode)
- : base(worksheet, address, validationType, itemElementNode) {
- Formula = new ExcelDataValidationFormulaCustom(NameSpaceManager, TopNode, _formula1Path);
- }
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelDataValidationCustom(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(worksheet, address, validationType, itemElementNode, namespaceManager) {
- Formula = new ExcelDataValidationFormulaCustom(NameSpaceManager, TopNode, _formula1Path);
- }
-}
diff --git a/EPPlus/DataValidation/ExcelDataValidationDateTime.cs b/EPPlus/DataValidation/ExcelDataValidationDateTime.cs
deleted file mode 100644
index c72a83d..0000000
--- a/EPPlus/DataValidation/ExcelDataValidationDateTime.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Xml;
-using OfficeOpenXml.DataValidation.Contracts;
-using OfficeOpenXml.DataValidation.Formulas;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// Validation for <see cref="DateTime"/>.
-/// </summary>
-public class ExcelDataValidationDateTime
- : ExcelDataValidationWithFormula2<IExcelDataValidationFormulaDateTime>,
- IExcelDataValidationDateTime {
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- internal ExcelDataValidationDateTime(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType)
- : base(worksheet, address, validationType) {
- Formula = new ExcelDataValidationFormulaDateTime(NameSpaceManager, TopNode, _formula1Path);
- Formula2 = new ExcelDataValidationFormulaDateTime(NameSpaceManager, TopNode, _formula2Path);
- }
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelDataValidationDateTime(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode)
- : base(worksheet, address, validationType, itemElementNode) {
- Formula = new ExcelDataValidationFormulaDateTime(NameSpaceManager, TopNode, _formula1Path);
- Formula2 = new ExcelDataValidationFormulaDateTime(NameSpaceManager, TopNode, _formula2Path);
- }
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelDataValidationDateTime(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(worksheet, address, validationType, itemElementNode, namespaceManager) {
- Formula = new ExcelDataValidationFormulaDateTime(NameSpaceManager, TopNode, _formula1Path);
- Formula2 = new ExcelDataValidationFormulaDateTime(NameSpaceManager, TopNode, _formula2Path);
- }
-}
diff --git a/EPPlus/DataValidation/ExcelDataValidationDecimal.cs b/EPPlus/DataValidation/ExcelDataValidationDecimal.cs
deleted file mode 100644
index 1e8e8af..0000000
--- a/EPPlus/DataValidation/ExcelDataValidationDecimal.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.DataValidation.Contracts;
-using OfficeOpenXml.DataValidation.Formulas;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// Data validation for decimal values
-/// </summary>
-public class ExcelDataValidationDecimal
- : ExcelDataValidationWithFormula2<IExcelDataValidationFormulaDecimal>,
- IExcelDataValidationDecimal {
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- internal ExcelDataValidationDecimal(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType)
- : base(worksheet, address, validationType) {
- Formula = new ExcelDataValidationFormulaDecimal(NameSpaceManager, TopNode, _formula1Path);
- Formula2 = new ExcelDataValidationFormulaDecimal(NameSpaceManager, TopNode, _formula2Path);
- }
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelDataValidationDecimal(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode)
- : base(worksheet, address, validationType, itemElementNode) {
- Formula = new ExcelDataValidationFormulaDecimal(NameSpaceManager, TopNode, _formula1Path);
- Formula2 = new ExcelDataValidationFormulaDecimal(NameSpaceManager, TopNode, _formula2Path);
- }
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager">For test purposes</param>
- internal ExcelDataValidationDecimal(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(worksheet, address, validationType, itemElementNode, namespaceManager) {
- Formula = new ExcelDataValidationFormulaDecimal(NameSpaceManager, TopNode, _formula1Path);
- Formula2 = new ExcelDataValidationFormulaDecimal(NameSpaceManager, TopNode, _formula2Path);
- }
-}
diff --git a/EPPlus/DataValidation/ExcelDataValidationFactory.cs b/EPPlus/DataValidation/ExcelDataValidationFactory.cs
deleted file mode 100644
index 86dcba6..0000000
--- a/EPPlus/DataValidation/ExcelDataValidationFactory.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- * Raziq York Added support for Any type 2014-08-08
- *******************************************************************************/
-
-using System;
-using System.Xml;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// Factory class for ExcelDataValidation.
-/// </summary>
-internal static class ExcelDataValidationFactory {
- /// <summary>
- /// Creates an instance of <see cref="ExcelDataValidation"/> out of the given parameters.
- /// </summary>
- /// <param name="type"></param>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="itemElementNode"></param>
- /// <returns></returns>
- public static ExcelDataValidation Create(
- ExcelDataValidationType type,
- ExcelWorksheet worksheet,
- string address,
- XmlNode itemElementNode) {
- Require.Argument(type).IsNotNull("validationType");
- switch (type.Type) {
- case eDataValidationType.Any:
- return new ExcelDataValidationAny(worksheet, address, type, itemElementNode);
- case eDataValidationType.TextLength:
- case eDataValidationType.Whole:
- return new ExcelDataValidationInt(worksheet, address, type, itemElementNode);
- case eDataValidationType.Decimal:
- return new ExcelDataValidationDecimal(worksheet, address, type, itemElementNode);
- case eDataValidationType.List:
- return new ExcelDataValidationList(worksheet, address, type, itemElementNode);
- case eDataValidationType.DateTime:
- return new ExcelDataValidationDateTime(worksheet, address, type, itemElementNode);
- case eDataValidationType.Time:
- return new ExcelDataValidationTime(worksheet, address, type, itemElementNode);
- case eDataValidationType.Custom:
- return new ExcelDataValidationCustom(worksheet, address, type, itemElementNode);
- default:
- throw new InvalidOperationException("Non supported validationtype: " + type.Type);
- }
- }
-}
diff --git a/EPPlus/DataValidation/ExcelDataValidationInt.cs b/EPPlus/DataValidation/ExcelDataValidationInt.cs
deleted file mode 100644
index 12cdb94..0000000
--- a/EPPlus/DataValidation/ExcelDataValidationInt.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.DataValidation.Contracts;
-using OfficeOpenXml.DataValidation.Formulas;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// Data validation for integer values.
-/// </summary>
-public class ExcelDataValidationInt
- : ExcelDataValidationWithFormula2<IExcelDataValidationFormulaInt>,
- IExcelDataValidationInt {
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- internal ExcelDataValidationInt(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType)
- : base(worksheet, address, validationType) {
- Formula = new ExcelDataValidationFormulaInt(worksheet.NameSpaceManager, TopNode, _formula1Path);
- Formula2 = new ExcelDataValidationFormulaInt(
- worksheet.NameSpaceManager,
- TopNode,
- _formula2Path);
- }
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelDataValidationInt(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode)
- : base(worksheet, address, validationType, itemElementNode) {
- Formula = new ExcelDataValidationFormulaInt(worksheet.NameSpaceManager, TopNode, _formula1Path);
- Formula2 = new ExcelDataValidationFormulaInt(
- worksheet.NameSpaceManager,
- TopNode,
- _formula2Path);
- }
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager">For test purposes</param>
- internal ExcelDataValidationInt(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(worksheet, address, validationType, itemElementNode, namespaceManager) {
- Formula = new ExcelDataValidationFormulaInt(NameSpaceManager, TopNode, _formula1Path);
- Formula2 = new ExcelDataValidationFormulaInt(NameSpaceManager, TopNode, _formula2Path);
- }
-}
diff --git a/EPPlus/DataValidation/ExcelDataValidationList.cs b/EPPlus/DataValidation/ExcelDataValidationList.cs
deleted file mode 100644
index e9dbdf1..0000000
--- a/EPPlus/DataValidation/ExcelDataValidationList.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.DataValidation.Contracts;
-using OfficeOpenXml.DataValidation.Formulas;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// This class represents an List data validation.
-/// </summary>
-public class ExcelDataValidationList
- : ExcelDataValidationWithFormula<IExcelDataValidationFormulaList>,
- IExcelDataValidationList {
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- internal ExcelDataValidationList(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType)
- : base(worksheet, address, validationType) {
- Formula = new ExcelDataValidationFormulaList(NameSpaceManager, TopNode, _formula1Path);
- }
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelDataValidationList(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode)
- : base(worksheet, address, validationType, itemElementNode) {
- Formula = new ExcelDataValidationFormulaList(NameSpaceManager, TopNode, _formula1Path);
- }
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager">Namespace manager, for test purposes</param>
- internal ExcelDataValidationList(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(worksheet, address, validationType, itemElementNode, namespaceManager) {
- Formula = new ExcelDataValidationFormulaList(NameSpaceManager, TopNode, _formula1Path);
- }
-}
diff --git a/EPPlus/DataValidation/ExcelDataValidationOperator.cs b/EPPlus/DataValidation/ExcelDataValidationOperator.cs
deleted file mode 100644
index a6f3fe2..0000000
--- a/EPPlus/DataValidation/ExcelDataValidationOperator.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// Operator for comparison between Formula and Formula2 in a validation.
-/// </summary>
-public enum ExcelDataValidationOperator {
- Any,
- Equal,
- NotEqual,
- LessThan,
- LessThanOrEqual,
- GreaterThan,
- GreaterThanOrEqual,
- Between,
- NotBetween,
-}
diff --git a/EPPlus/DataValidation/ExcelDataValidationTime.cs b/EPPlus/DataValidation/ExcelDataValidationTime.cs
deleted file mode 100644
index 3c37d13..0000000
--- a/EPPlus/DataValidation/ExcelDataValidationTime.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.DataValidation.Contracts;
-using OfficeOpenXml.DataValidation.Formulas;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// Validation for times (<see cref="OfficeOpenXml.DataValidation.ExcelTime"/>).
-/// </summary>
-public class ExcelDataValidationTime
- : ExcelDataValidationWithFormula2<IExcelDataValidationFormulaTime>,
- IExcelDataValidationTime {
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- internal ExcelDataValidationTime(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType)
- : base(worksheet, address, validationType) {
- Formula = new ExcelDataValidationFormulaTime(NameSpaceManager, TopNode, _formula1Path);
- Formula2 = new ExcelDataValidationFormulaTime(NameSpaceManager, TopNode, _formula2Path);
- }
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelDataValidationTime(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode)
- : base(worksheet, address, validationType, itemElementNode) {
- Formula = new ExcelDataValidationFormulaTime(NameSpaceManager, TopNode, _formula1Path);
- Formula2 = new ExcelDataValidationFormulaTime(NameSpaceManager, TopNode, _formula2Path);
- }
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelDataValidationTime(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(worksheet, address, validationType, itemElementNode, namespaceManager) {
- Formula = new ExcelDataValidationFormulaTime(NameSpaceManager, TopNode, _formula1Path);
- Formula2 = new ExcelDataValidationFormulaTime(NameSpaceManager, TopNode, _formula2Path);
- }
-}
diff --git a/EPPlus/DataValidation/ExcelDataValidationType.cs b/EPPlus/DataValidation/ExcelDataValidationType.cs
deleted file mode 100644
index cdcc99c..0000000
--- a/EPPlus/DataValidation/ExcelDataValidationType.cs
+++ /dev/null
@@ -1,261 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- * Raziq York Added support for Any type 2014-08-08
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// Enum for available data validation types
-/// </summary>
-public enum eDataValidationType {
- /// <summary>
- /// Any value
- /// </summary>
- Any,
-
- /// <summary>
- /// Integer value
- /// </summary>
- Whole,
-
- /// <summary>
- /// Decimal values
- /// </summary>
- Decimal,
-
- /// <summary>
- /// List of values
- /// </summary>
- List,
-
- /// <summary>
- /// Text length validation
- /// </summary>
- TextLength,
-
- /// <summary>
- /// DateTime validation
- /// </summary>
- DateTime,
-
- /// <summary>
- /// Time validation
- /// </summary>
- Time,
-
- /// <summary>
- /// Custom validation
- /// </summary>
- Custom,
-}
-
-internal static class DataValidationSchemaNames {
- public const string Any = "";
- public const string Whole = "whole";
- public const string Decimal = "decimal";
- public const string List = "list";
- public const string TextLength = "textLength";
- public const string Date = "date";
- public const string Time = "time";
- public const string Custom = "custom";
-}
-
-/// <summary>
-/// Types of datavalidation
-/// </summary>
-public class ExcelDataValidationType {
- private ExcelDataValidationType(
- eDataValidationType validationType,
- bool allowOperator,
- string schemaName) {
- Type = validationType;
- AllowOperator = allowOperator;
- SchemaName = schemaName;
- }
-
- /// <summary>
- /// Validation type
- /// </summary>
- public eDataValidationType Type { get; private set; }
-
- internal string SchemaName { get; private set; }
-
- /// <summary>
- /// This type allows operator to be set
- /// </summary>
- internal bool AllowOperator { get; private set; }
-
- internal static ExcelDataValidationType GetBySchemaName(string schemaName) {
- switch (schemaName) {
- case DataValidationSchemaNames.Any:
- return Any;
- case DataValidationSchemaNames.Whole:
- return Whole;
- case DataValidationSchemaNames.Decimal:
- return Decimal;
- case DataValidationSchemaNames.List:
- return List;
- case DataValidationSchemaNames.TextLength:
- return TextLength;
- case DataValidationSchemaNames.Date:
- return DateTime;
- case DataValidationSchemaNames.Time:
- return Time;
- case DataValidationSchemaNames.Custom:
- return Custom;
- default:
- throw new ArgumentException("Invalid schemaname: " + schemaName);
- }
- }
-
- /// <summary>
- /// Overridden Equals, compares on internal validation type
- /// </summary>
- /// <param name="obj"></param>
- /// <returns></returns>
- public override bool Equals(object obj) {
- if (!(obj is ExcelDataValidationType type)) {
- return false;
- }
- return type.Type == Type;
- }
-
- /// <summary>
- /// Overrides GetHashCode()
- /// </summary>
- /// <returns></returns>
- public override int GetHashCode() {
- return base.GetHashCode();
- }
-
- /// <summary>
- /// Integer values
- /// </summary>
- private static ExcelDataValidationType _any;
-
- public static ExcelDataValidationType Any {
- get {
- if (_any == null) {
- _any = new(eDataValidationType.Any, false, DataValidationSchemaNames.Any);
- }
- return _any;
- }
- }
-
- /// <summary>
- /// Integer values
- /// </summary>
- private static ExcelDataValidationType _whole;
-
- public static ExcelDataValidationType Whole {
- get {
- if (_whole == null) {
- _whole = new(eDataValidationType.Whole, true, DataValidationSchemaNames.Whole);
- }
- return _whole;
- }
- }
-
- /// <summary>
- /// List of allowed values
- /// </summary>
- private static ExcelDataValidationType _list;
-
- public static ExcelDataValidationType List {
- get {
- if (_list == null) {
- _list = new(eDataValidationType.List, false, DataValidationSchemaNames.List);
- }
- return _list;
- }
- }
-
- private static ExcelDataValidationType _decimal;
-
- public static ExcelDataValidationType Decimal {
- get {
- if (_decimal == null) {
- _decimal = new(eDataValidationType.Decimal, true, DataValidationSchemaNames.Decimal);
- }
- return _decimal;
- }
- }
-
- private static ExcelDataValidationType _textLength;
-
- public static ExcelDataValidationType TextLength {
- get {
- if (_textLength == null) {
- _textLength = new(
- eDataValidationType.TextLength,
- true,
- DataValidationSchemaNames.TextLength);
- }
- return _textLength;
- }
- }
-
- private static ExcelDataValidationType _dateTime;
-
- public static ExcelDataValidationType DateTime {
- get {
- if (_dateTime == null) {
- _dateTime = new(eDataValidationType.DateTime, true, DataValidationSchemaNames.Date);
- }
- return _dateTime;
- }
- }
-
- private static ExcelDataValidationType _time;
-
- public static ExcelDataValidationType Time {
- get {
- if (_time == null) {
- _time = new(eDataValidationType.Time, true, DataValidationSchemaNames.Time);
- }
- return _time;
- }
- }
-
- private static ExcelDataValidationType _custom;
-
- public static ExcelDataValidationType Custom {
- get {
- if (_custom == null) {
- _custom = new(eDataValidationType.Custom, true, DataValidationSchemaNames.Custom);
- }
- return _custom;
- }
- }
-}
diff --git a/EPPlus/DataValidation/ExcelDataValidationWarningStyle.cs b/EPPlus/DataValidation/ExcelDataValidationWarningStyle.cs
deleted file mode 100644
index ae808bb..0000000
--- a/EPPlus/DataValidation/ExcelDataValidationWarningStyle.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// warning style, controls how Excel will handle invalid changes.
-/// </summary>
-public enum ExcelDataValidationWarningStyle {
- /// <summary>
- /// warning style will be excluded
- /// </summary>
- Undefined,
-
- /// <summary>
- /// stop warning style, invalid changes will not be accepted
- /// </summary>
- Stop,
-
- /// <summary>
- /// warning will be presented when an attempt to an invalid change is done, but the change will be accepted.
- /// </summary>
- Warning,
-
- /// <summary>
- /// information warning style.
- /// </summary>
- Information,
-}
diff --git a/EPPlus/DataValidation/ExcelDataValidationWithFormula.cs b/EPPlus/DataValidation/ExcelDataValidationWithFormula.cs
deleted file mode 100644
index 7c20825..0000000
--- a/EPPlus/DataValidation/ExcelDataValidationWithFormula.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Xml;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// A validation containing a formula
-/// </summary>
-/// <typeparam name="T"></typeparam>
-public class ExcelDataValidationWithFormula<T> : ExcelDataValidation
- where T : IExcelDataValidationFormula {
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- internal ExcelDataValidationWithFormula(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType)
- : this(worksheet, address, validationType, null) {}
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet">Worksheet that owns the validation</param>
- /// <param name="itemElementNode">Xml top node (dataValidations)</param>
- /// <param name="validationType">Data validation type</param>
- /// <param name="address">address for data validation</param>
- internal ExcelDataValidationWithFormula(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode)
- : base(worksheet, address, validationType, itemElementNode) {}
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet">Worksheet that owns the validation</param>
- /// <param name="itemElementNode">Xml top node (dataValidations)</param>
- /// <param name="validationType">Data validation type</param>
- /// <param name="address">address for data validation</param>
- /// <param name="namespaceManager">for test purposes</param>
- internal ExcelDataValidationWithFormula(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(worksheet, address, validationType, itemElementNode, namespaceManager) {}
-
- /// <summary>
- /// Formula - Either a {T} value (except for custom validation) or a spreadsheet formula
- /// </summary>
- public T Formula { get; protected set; }
-
- public override void Validate() {
- base.Validate();
- if (Operator == ExcelDataValidationOperator.Between
- || Operator == ExcelDataValidationOperator.NotBetween) {
- if (string.IsNullOrEmpty(Formula2Internal)) {
- throw new InvalidOperationException(
- "Validation of "
- + Address.Address
- + " failed: Formula2 must be set if operator is 'between' or 'notBetween'");
- }
- }
- }
-}
diff --git a/EPPlus/DataValidation/ExcelDataValidationWithFormula2.cs b/EPPlus/DataValidation/ExcelDataValidationWithFormula2.cs
deleted file mode 100644
index 3b9b7c0..0000000
--- a/EPPlus/DataValidation/ExcelDataValidationWithFormula2.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation;
-
-public class ExcelDataValidationWithFormula2<T> : ExcelDataValidationWithFormula<T>
- where T : IExcelDataValidationFormula {
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="address"></param>
- /// <param name="validationType"></param>
- internal ExcelDataValidationWithFormula2(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType)
- : this(worksheet, address, validationType, null) {}
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet">Worksheet that owns the validation</param>
- /// <param name="itemElementNode">Xml top node (dataValidations)</param>
- /// <param name="validationType">Data validation type</param>
- /// <param name="address">address for data validation</param>
- internal ExcelDataValidationWithFormula2(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode)
- : base(worksheet, address, validationType, itemElementNode) {}
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet">Worksheet that owns the validation</param>
- /// <param name="itemElementNode">Xml top node (dataValidations)</param>
- /// <param name="validationType">Data validation type</param>
- /// <param name="address">address for data validation</param>
- /// <param name="namespaceManager">for test purposes</param>
- internal ExcelDataValidationWithFormula2(
- ExcelWorksheet worksheet,
- string address,
- ExcelDataValidationType validationType,
- XmlNode itemElementNode,
- XmlNamespaceManager namespaceManager)
- : base(worksheet, address, validationType, itemElementNode, namespaceManager) {}
-
- /// <summary>
- /// Formula - Either a {T} value or a spreadsheet formula
- /// </summary>
- public T Formula2 { get; protected set; }
-}
diff --git a/EPPlus/DataValidation/ExcelTime.cs b/EPPlus/DataValidation/ExcelTime.cs
deleted file mode 100644
index 783eb17..0000000
--- a/EPPlus/DataValidation/ExcelTime.cs
+++ /dev/null
@@ -1,224 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Globalization;
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// Represents a time between 00:00:00 and 23:59:59
-/// </summary>
-public class ExcelTime {
- private event EventHandler TimeChangedEvent;
-
- private readonly decimal SecondsPerDay = 3600 * 24;
- private readonly decimal SecondsPerHour = 3600;
- private readonly decimal SecondsPerMinute = 60;
-
- /// <summary>
- /// Max number of decimals when rounding.
- /// </summary>
- public const int NumberOfDecimals = 15;
-
- /// <summary>
- /// Default constructor
- /// </summary>
- public ExcelTime() {}
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="value">An existing time for initialization</param>
- public ExcelTime(decimal value) {
- if (value < 0M) {
- throw new ArgumentException("Value cannot be less than 0");
- }
- if (value >= 1M) {
- throw new ArgumentException("Value cannot be greater or equal to 1");
- }
- Init(value);
- }
-
- private void Init(decimal value) {
- // handle hour
- decimal totalSeconds = value * SecondsPerDay;
- decimal hour = Math.Floor(totalSeconds / SecondsPerHour);
- Hour = (int)hour;
-
- // handle minute
- decimal remainingSeconds = totalSeconds - (hour * SecondsPerHour);
- decimal minute = Math.Floor(remainingSeconds / SecondsPerMinute);
- Minute = (int)minute;
-
- // handle second
- remainingSeconds = totalSeconds - (hour * SecondsPerHour) - (minute * SecondsPerMinute);
- decimal second = Math.Round(remainingSeconds, MidpointRounding.AwayFromZero);
- // Second might be rounded to 60... the SetSecond method handles that.
- SetSecond((int)second);
- }
-
- /// <summary>
- /// If we are unlucky second might be rounded up to 60. This will have the minute to be raised and might affect the hour.
- /// </summary>
- /// <param name="value"></param>
- private void SetSecond(int value) {
- if (value == 60) {
- Second = 0;
- var minute = Minute + 1;
- SetMinute(minute);
- } else {
- Second = value;
- }
- }
-
- private void SetMinute(int value) {
- if (value == 60) {
- Minute = 0;
- var hour = Hour + 1;
- SetHour(hour);
- } else {
- Minute = value;
- }
- }
-
- private void SetHour(int value) {
- if (value == 24) {
- Hour = 0;
- }
- }
-
- internal event EventHandler TimeChanged {
- add => TimeChangedEvent += value;
- remove => TimeChangedEvent -= value;
- }
-
- private void OnTimeChanged() {
- if (TimeChangedEvent != null) {
- TimeChangedEvent(this, EventArgs.Empty);
- }
- }
-
- private int _hour;
-
- /// <summary>
- /// Hour between 0 and 23
- /// </summary>
- public int Hour {
- get => _hour;
- set {
- if (value < 0) {
- throw new InvalidOperationException("Value for hour cannot be negative");
- }
- if (value > 23) {
- throw new InvalidOperationException("Value for hour cannot be greater than 23");
- }
- _hour = value;
- OnTimeChanged();
- }
- }
-
- private int _minute;
-
- /// <summary>
- /// Minute between 0 and 59
- /// </summary>
- public int Minute {
- get => _minute;
- set {
- if (value < 0) {
- throw new InvalidOperationException("Value for minute cannot be negative");
- }
- if (value > 59) {
- throw new InvalidOperationException("Value for minute cannot be greater than 59");
- }
- _minute = value;
- OnTimeChanged();
- }
- }
-
- private int? _second;
-
- /// <summary>
- /// Second between 0 and 59
- /// </summary>
- public int? Second {
- get => _second;
- set {
- if (value < 0) {
- throw new InvalidOperationException("Value for second cannot be negative");
- }
- if (value > 59) {
- throw new InvalidOperationException("Value for second cannot be greater than 59");
- }
- _second = value;
- OnTimeChanged();
- }
- }
-
- private decimal Round(decimal value) {
- return Math.Round(value, NumberOfDecimals);
- }
-
- private decimal ToSeconds() {
- var result = Hour * SecondsPerHour;
- result += Minute * SecondsPerMinute;
- result += Second ?? 0;
- return result;
- }
-
- /// <summary>
- /// Returns the excel decimal representation of a time.
- /// </summary>
- /// <returns></returns>
- public decimal ToExcelTime() {
- var seconds = ToSeconds();
- return Round(seconds / SecondsPerDay);
- }
-
- /// <summary>
- /// Returns the excel decimal representation of a time as a string.
- /// </summary>
- /// <returns></returns>
- public string ToExcelString() {
- return ToExcelTime().ToString(CultureInfo.InvariantCulture);
- }
-
- public override string ToString() {
- var second = Second ?? 0;
- return string.Format(
- "{0}:{1}:{2}",
- Hour < 10 ? "0" + Hour : Hour.ToString(),
- Minute < 10 ? "0" + Minute : Minute.ToString(),
- second < 10 ? "0" + second : second.ToString());
- }
-}
diff --git a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormula.cs b/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormula.cs
deleted file mode 100644
index fee785c..0000000
--- a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormula.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-namespace OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-/// <summary>
-/// Interface for a data validation formula
-/// </summary>
-public interface IExcelDataValidationFormula {
- /// <summary>
- /// An excel formula
- /// </summary>
- string ExcelFormula { get; set; }
-}
diff --git a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDateTime.cs b/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDateTime.cs
deleted file mode 100644
index 2cc6df2..0000000
--- a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDateTime.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-/// <summary>
-/// Validation formula interface for <see cref="DateTime"/>
-/// </summary>
-public interface IExcelDataValidationFormulaDateTime
- : IExcelDataValidationFormulaWithValue<DateTime?> {}
diff --git a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDecimal.cs b/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDecimal.cs
deleted file mode 100644
index 0a87a75..0000000
--- a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDecimal.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-namespace OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-/// <summary>
-/// Interface for a data validation formula of <see cref="System.Single">float</see> value
-/// </summary>
-public interface IExcelDataValidationFormulaDecimal
- : IExcelDataValidationFormulaWithValue<double?> {}
diff --git a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaInt.cs b/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaInt.cs
deleted file mode 100644
index 47ecfaa..0000000
--- a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaInt.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-namespace OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-/// <summary>
-/// Interface for a data validation formula of <see cref="System.Int32"/> value
-/// </summary>
-public interface IExcelDataValidationFormulaInt : IExcelDataValidationFormulaWithValue<int?> {}
diff --git a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaList.cs b/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaList.cs
deleted file mode 100644
index 6a799b4..0000000
--- a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaList.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-/// <summary>
-/// Interface for a data validation of list type
-/// </summary>
-public interface IExcelDataValidationFormulaList : IExcelDataValidationFormula {
- /// <summary>
- /// A list of value strings.
- /// </summary>
- IList<string> Values { get; }
-}
diff --git a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaTime.cs b/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaTime.cs
deleted file mode 100644
index a9f1f5d..0000000
--- a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaTime.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-namespace OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-public interface IExcelDataValidationFormulaTime
- : IExcelDataValidationFormulaWithValue<ExcelTime> {}
diff --git a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaWithValue.cs b/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaWithValue.cs
deleted file mode 100644
index 21b937b..0000000
--- a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaWithValue.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-namespace OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-/// <summary>
-/// Interface for a formula with a value
-/// </summary>
-/// <typeparam name="T"></typeparam>
-public interface IExcelDataValidationFormulaWithValue<T> : IExcelDataValidationFormula {
- /// <summary>
- /// The value.
- /// </summary>
- T Value { get; set; }
-}
diff --git a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormula.cs b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormula.cs
deleted file mode 100644
index bbc9819..0000000
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormula.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Xml;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.DataValidation.Formulas;
-
-/// <summary>
-/// Enumeration representing the state of an <see cref="ExcelDataValidationFormulaValue{T}"/>
-/// </summary>
-internal enum FormulaState {
- /// <summary>
- /// Value is set
- /// </summary>
- Value,
-
- /// <summary>
- /// Formula is set
- /// </summary>
- Formula,
-}
-
-/// <summary>
-/// Base class for a formula
-/// </summary>
-internal abstract class ExcelDataValidationFormula : XmlHelper {
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="namespaceManager">Namespacemanger of the worksheet</param>
- /// <param name="topNode">validation top node</param>
- /// <param name="formulaPath">xml path of the current formula</param>
- public ExcelDataValidationFormula(
- XmlNamespaceManager namespaceManager,
- XmlNode topNode,
- string formulaPath)
- : base(namespaceManager, topNode) {
- Require.Argument(formulaPath).IsNotNullOrEmpty("formulaPath");
- FormulaPath = formulaPath;
- }
-
- private string _formula;
-
- protected string FormulaPath { get; private set; }
-
- /// <summary>
- /// State of the validationformula, i.e. tells if value or formula is set
- /// </summary>
- protected FormulaState State { get; set; }
-
- /// <summary>
- /// A formula which output must match the current validation type
- /// </summary>
- public string ExcelFormula {
- get => _formula;
- set {
- if (!string.IsNullOrEmpty(value)) {
- ResetValue();
- State = FormulaState.Formula;
- }
- if (value != null && value.Length > 255) {
- throw new InvalidOperationException(
- "The length of a DataValidation formula cannot exceed 255 characters");
- }
- //var val = SqRefUtility.ToSqRefAddress(value);
- _formula = value;
- SetXmlNodeString(FormulaPath, value);
- }
- }
-
- internal abstract void ResetValue();
-
- /// <summary>
- /// This value will be stored in the xml. Can be overridden by subclasses
- /// </summary>
- internal virtual string GetXmlValue() {
- if (State == FormulaState.Formula) {
- return ExcelFormula;
- }
- return GetValueAsString();
- }
-
- /// <summary>
- /// Returns the value as a string. Must be implemented by subclasses
- /// </summary>
- /// <returns></returns>
- protected abstract string GetValueAsString();
-}
diff --git a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaCustom.cs b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaCustom.cs
deleted file mode 100644
index 1072535..0000000
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaCustom.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation.Formulas;
-
-/// <summary>
-///
-/// </summary>
-internal class ExcelDataValidationFormulaCustom
- : ExcelDataValidationFormula,
- IExcelDataValidationFormula {
- public ExcelDataValidationFormulaCustom(
- XmlNamespaceManager namespaceManager,
- XmlNode topNode,
- string formulaPath)
- : base(namespaceManager, topNode, formulaPath) {
- var value = GetXmlNodeString(formulaPath);
- if (!string.IsNullOrEmpty(value)) {
- ExcelFormula = value;
- }
- State = FormulaState.Formula;
- }
-
- internal override string GetXmlValue() {
- return ExcelFormula;
- }
-
- protected override string GetValueAsString() {
- return ExcelFormula;
- }
-
- internal override void ResetValue() {
- ExcelFormula = null;
- }
-}
diff --git a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaDateTime.cs b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaDateTime.cs
deleted file mode 100644
index 3dbc85d..0000000
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaDateTime.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Globalization;
-using System.Xml;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation.Formulas;
-
-internal class ExcelDataValidationFormulaDateTime
- : ExcelDataValidationFormulaValue<DateTime?>,
- IExcelDataValidationFormulaDateTime {
- public ExcelDataValidationFormulaDateTime(
- XmlNamespaceManager namespaceManager,
- XmlNode topNode,
- string formulaPath)
- : base(namespaceManager, topNode, formulaPath) {
- var value = GetXmlNodeString(formulaPath);
- if (!string.IsNullOrEmpty(value)) {
- if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var oADate)) {
- Value = DateTime.FromOADate(oADate);
- } else {
- ExcelFormula = value;
- }
- }
- }
-
- protected override string GetValueAsString() {
- return Value.HasValue
- ? Value.Value.ToOADate().ToString(CultureInfo.InvariantCulture)
- : string.Empty;
- }
-}
diff --git a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaDecimal.cs b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaDecimal.cs
deleted file mode 100644
index 995c459..0000000
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaDecimal.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Globalization;
-using System.Xml;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation.Formulas;
-
-/// <summary>
-///
-/// </summary>
-internal class ExcelDataValidationFormulaDecimal
- : ExcelDataValidationFormulaValue<double?>,
- IExcelDataValidationFormulaDecimal {
- public ExcelDataValidationFormulaDecimal(
- XmlNamespaceManager namespaceManager,
- XmlNode topNode,
- string formulaPath)
- : base(namespaceManager, topNode, formulaPath) {
- var value = GetXmlNodeString(formulaPath);
- if (!string.IsNullOrEmpty(value)) {
- if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var dValue)) {
- Value = dValue;
- } else {
- ExcelFormula = value;
- }
- }
- }
-
- protected override string GetValueAsString() {
- return Value.HasValue
- ? Value.Value.ToString("R15", CultureInfo.InvariantCulture)
- : string.Empty;
- }
-}
diff --git a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaInt.cs b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaInt.cs
deleted file mode 100644
index 6bd31d2..0000000
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaInt.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation.Formulas;
-
-internal class ExcelDataValidationFormulaInt
- : ExcelDataValidationFormulaValue<int?>,
- IExcelDataValidationFormulaInt {
- public ExcelDataValidationFormulaInt(
- XmlNamespaceManager namespaceManager,
- XmlNode topNode,
- string formulaPath)
- : base(namespaceManager, topNode, formulaPath) {
- var value = GetXmlNodeString(formulaPath);
- if (!string.IsNullOrEmpty(value)) {
- if (int.TryParse(value, out var intValue)) {
- Value = intValue;
- } else {
- ExcelFormula = value;
- }
- }
- }
-
- protected override string GetValueAsString() {
- return Value.HasValue ? Value.Value.ToString() : string.Empty;
- }
-}
diff --git a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaList.cs b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaList.cs
deleted file mode 100644
index 55e554b..0000000
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaList.cs
+++ /dev/null
@@ -1,192 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Text;
-using System.Xml;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.DataValidation.Formulas;
-
-internal class ExcelDataValidationFormulaList
- : ExcelDataValidationFormula,
- IExcelDataValidationFormulaList {
- private class DataValidationList : IList<string>, ICollection {
- private readonly IList<string> _items = new List<string>();
- private EventHandler<EventArgs> _listChanged;
-
- public event EventHandler<EventArgs> ListChanged {
- add => _listChanged += value;
- remove => _listChanged -= value;
- }
-
- private void OnListChanged() {
- if (_listChanged != null) {
- _listChanged(this, EventArgs.Empty);
- }
- }
-
- int IList<string>.IndexOf(string item) {
- return _items.IndexOf(item);
- }
-
- void IList<string>.Insert(int index, string item) {
- _items.Insert(index, item);
- OnListChanged();
- }
-
- void IList<string>.RemoveAt(int index) {
- _items.RemoveAt(index);
- OnListChanged();
- }
-
- string IList<string>.this[int index] {
- get => _items[index];
- set {
- _items[index] = value;
- OnListChanged();
- }
- }
-
- void ICollection<string>.Add(string item) {
- _items.Add(item);
- OnListChanged();
- }
-
- void ICollection<string>.Clear() {
- _items.Clear();
- OnListChanged();
- }
-
- bool ICollection<string>.Contains(string item) {
- return _items.Contains(item);
- }
-
- void ICollection<string>.CopyTo(string[] array, int arrayIndex) {
- _items.CopyTo(array, arrayIndex);
- }
-
- int ICollection<string>.Count => _items.Count;
-
- bool ICollection<string>.IsReadOnly => false;
-
- bool ICollection<string>.Remove(string item) {
- var retVal = _items.Remove(item);
- OnListChanged();
- return retVal;
- }
-
- IEnumerator<string> IEnumerable<string>.GetEnumerator() {
- return _items.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- return _items.GetEnumerator();
- }
-
- public void CopyTo(Array array, int index) {
- _items.CopyTo((string[])array, index);
- }
-
- int ICollection.Count => _items.Count;
-
- public bool IsSynchronized => ((ICollection)_items).IsSynchronized;
-
- public object SyncRoot => ((ICollection)_items).SyncRoot;
- }
-
- public ExcelDataValidationFormulaList(
- XmlNamespaceManager namespaceManager,
- XmlNode itemNode,
- string formulaPath)
- : base(namespaceManager, itemNode, formulaPath) {
- Require.Argument(formulaPath).IsNotNullOrEmpty("formulaPath");
- _formulaPath = formulaPath;
- var values = new DataValidationList();
- values.ListChanged += values_ListChanged;
- Values = values;
- SetInitialValues();
- }
-
- private readonly string _formulaPath;
-
- private void SetInitialValues() {
- var value = GetXmlNodeString(_formulaPath);
- if (!string.IsNullOrEmpty(value)) {
- if (value.StartsWith("\"") && value.EndsWith("\"")) {
- value = value.TrimStart('"').TrimEnd('"');
- var items = value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- foreach (var item in items) {
- Values.Add(item);
- }
- } else {
- ExcelFormula = value;
- }
- }
- }
-
- private void values_ListChanged(object sender, EventArgs e) {
- if (Values.Count > 0) {
- State = FormulaState.Value;
- }
- var valuesAsString = GetValueAsString();
- // Excel supports max 255 characters in this field.
- if (valuesAsString.Length > 255) {
- throw new InvalidOperationException(
- "The total length of a DataValidation list cannot exceed 255 characters");
- }
- SetXmlNodeString(_formulaPath, valuesAsString);
- }
-
- public IList<string> Values { get; private set; }
-
- protected override string GetValueAsString() {
- var sb = new StringBuilder();
- foreach (var val in Values) {
- if (sb.Length == 0) {
- sb.Append("\"");
- sb.Append(val);
- } else {
- sb.AppendFormat(",{0}", val);
- }
- }
- sb.Append("\"");
- return sb.ToString();
- }
-
- internal override void ResetValue() {
- Values.Clear();
- }
-}
diff --git a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaTime.cs b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaTime.cs
deleted file mode 100644
index 54d9844..0000000
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaTime.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Globalization;
-using System.Xml;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-
-namespace OfficeOpenXml.DataValidation.Formulas;
-
-internal class ExcelDataValidationFormulaTime
- : ExcelDataValidationFormulaValue<ExcelTime>,
- IExcelDataValidationFormulaTime {
- public ExcelDataValidationFormulaTime(
- XmlNamespaceManager namespaceManager,
- XmlNode topNode,
- string formulaPath)
- : base(namespaceManager, topNode, formulaPath) {
- var value = GetXmlNodeString(formulaPath);
- if (!string.IsNullOrEmpty(value)) {
- if (decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var time)) {
- Value = new(time);
- } else {
- Value = new();
- ExcelFormula = value;
- }
- } else {
- Value = new();
- }
- Value.TimeChanged += Value_TimeChanged;
- }
-
- private void Value_TimeChanged(object sender, EventArgs e) {
- SetXmlNodeString(FormulaPath, Value.ToExcelString());
- }
-
- protected override string GetValueAsString() {
- if (State == FormulaState.Value) {
- return Value.ToExcelString();
- }
- return string.Empty;
- }
-
- internal override void ResetValue() {
- Value = new();
- }
-}
diff --git a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaValue.cs b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaValue.cs
deleted file mode 100644
index 8490c7a..0000000
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaValue.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-08
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.DataValidation.Formulas;
-
-/// <summary>
-/// This class represents a validation formula. Its value can be specified as a value of the specified datatype or as a formula.
-/// </summary>
-/// <typeparam name="T"></typeparam>
-internal abstract class ExcelDataValidationFormulaValue<T> : ExcelDataValidationFormula {
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="namespaceManager">Namespacemanger of the worksheet</param>
- /// <param name="topNode">validation top node</param>
- /// <param name="formulaPath">xml path of the current formula</param>
- public ExcelDataValidationFormulaValue(
- XmlNamespaceManager namespaceManager,
- XmlNode topNode,
- string formulaPath)
- : base(namespaceManager, topNode, formulaPath) {}
-
- private T _value;
-
- /// <summary>
- /// Typed value
- /// </summary>
- public T Value {
- get => _value;
- set {
- State = FormulaState.Value;
- _value = value;
- SetXmlNodeString(FormulaPath, GetValueAsString());
- }
- }
-
- internal override void ResetValue() {
- Value = default(T);
- }
-}
diff --git a/EPPlus/DataValidation/IRangeDataValidation.cs b/EPPlus/DataValidation/IRangeDataValidation.cs
deleted file mode 100644
index 0002560..0000000
--- a/EPPlus/DataValidation/IRangeDataValidation.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-03-23
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using OfficeOpenXml.DataValidation.Contracts;
-
-namespace OfficeOpenXml.DataValidation;
-
-/// <summary>
-/// Provides functionality for adding datavalidation to a range (<see cref="ExcelRangeBase"/>). Each method will
-/// return a configurable validation.
-/// </summary>
-public interface IRangeDataValidation {
- /// <summary>
- /// Adds a <see cref="IExcelDataValidationAny"/> to the range.
- /// </summary>
- /// <returns>A <see cref="ExcelDataValidationAny"/> that can be configured for any validation</returns>
- IExcelDataValidationAny AddAnyDataValidation();
-
- /// <summary>
- /// Adds a <see cref="IExcelDataValidationInt"/> to the range
- /// </summary>
- /// <returns>A <see cref="ExcelDataValidationInt"/> that can be configured for integer data validation</returns>
- IExcelDataValidationInt AddIntegerDataValidation();
-
- /// <summary>
- /// Adds a <see cref="ExcelDataValidationDecimal"/> to the range
- /// </summary>
- /// <returns>A <see cref="ExcelDataValidationDecimal"/> that can be configured for decimal data validation</returns>
- IExcelDataValidationDecimal AddDecimalDataValidation();
-
- /// <summary>
- /// Adds a <see cref="ExcelDataValidationDateTime"/> to the range
- /// </summary>
- /// <returns>A <see cref="ExcelDataValidationDecimal"/> that can be configured for datetime data validation</returns>
- IExcelDataValidationDateTime AddDateTimeDataValidation();
-
- /// <summary>
- /// Adds a <see cref="IExcelDataValidationList"/> to the range
- /// </summary>
- /// <returns>A <see cref="ExcelDataValidationList"/> that can be configured for datetime data validation</returns>
- IExcelDataValidationList AddListDataValidation();
-
- /// <summary>
- /// Adds a <see cref="IExcelDataValidationInt"/> regarding text length validation to the range.
- /// </summary>
- /// <returns></returns>
- IExcelDataValidationInt AddTextLengthDataValidation();
-
- /// <summary>
- /// Adds a <see cref="IExcelDataValidationTime"/> to the range.
- /// </summary>
- /// <returns>A <see cref="IExcelDataValidationTime"/> that can be configured for time data validation</returns>
- IExcelDataValidationTime AddTimeDataValidation();
-
- /// <summary>
- /// Adds a <see cref="IExcelDataValidationCustom"/> to the range.
- /// </summary>
- /// <returns>A <see cref="IExcelDataValidationCustom"/> that can be configured for custom validation</returns>
- IExcelDataValidationCustom AddCustomDataValidation();
-}
diff --git a/EPPlus/DataValidation/RangeDataValidation.cs b/EPPlus/DataValidation/RangeDataValidation.cs
deleted file mode 100644
index b09d219..0000000
--- a/EPPlus/DataValidation/RangeDataValidation.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-03-23
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using OfficeOpenXml.DataValidation.Contracts;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.DataValidation;
-
-internal class RangeDataValidation : IRangeDataValidation {
- public RangeDataValidation(ExcelWorksheet worksheet, string address) {
- Require.Argument(worksheet).IsNotNull("worksheet");
- Require.Argument(address).IsNotNullOrEmpty("address");
- _worksheet = worksheet;
- _address = address;
- }
-
- private readonly ExcelWorksheet _worksheet;
- private readonly string _address;
-
- public IExcelDataValidationAny AddAnyDataValidation() {
- return _worksheet.DataValidations.AddAnyValidation(_address);
- }
-
- public IExcelDataValidationInt AddIntegerDataValidation() {
- return _worksheet.DataValidations.AddIntegerValidation(_address);
- }
-
- public IExcelDataValidationDecimal AddDecimalDataValidation() {
- return _worksheet.DataValidations.AddDecimalValidation(_address);
- }
-
- public IExcelDataValidationDateTime AddDateTimeDataValidation() {
- return _worksheet.DataValidations.AddDateTimeValidation(_address);
- }
-
- public IExcelDataValidationList AddListDataValidation() {
- return _worksheet.DataValidations.AddListValidation(_address);
- }
-
- public IExcelDataValidationInt AddTextLengthDataValidation() {
- return _worksheet.DataValidations.AddTextLengthValidation(_address);
- }
-
- public IExcelDataValidationTime AddTimeDataValidation() {
- return _worksheet.DataValidations.AddTimeValidation(_address);
- }
-
- public IExcelDataValidationCustom AddCustomDataValidation() {
- return _worksheet.DataValidations.AddCustomValidation(_address);
- }
-}
diff --git a/EPPlus/Drawing/Vml/ExcelVmlDrawingBase.cs b/EPPlus/Drawing/Vml/ExcelVmlDrawingBase.cs
deleted file mode 100644
index ade7974..0000000
--- a/EPPlus/Drawing/Vml/ExcelVmlDrawingBase.cs
+++ /dev/null
@@ -1,153 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2010-06-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System.Collections.Immutable;
-using System.Xml;
-
-namespace OfficeOpenXml.Drawing.Vml;
-
-/// <summary>
-/// Horizontal Alingment
-/// </summary>
-public enum eTextAlignHorizontalVml {
- Left,
- Center,
- Right,
-}
-
-/// <summary>
-/// Vertical Alingment
-/// </summary>
-public enum eTextAlignVerticalVml {
- Top,
- Center,
- Bottom,
-}
-
-/// <summary>
-/// Linestyle
-/// </summary>
-public enum eLineStyleVml {
- Solid,
- Round,
- Square,
- Dash,
- DashDot,
- LongDash,
- LongDashDot,
- LongDashDotDot,
-}
-
-/// <summary>
-/// Drawing object used for comments
-/// </summary>
-public class ExcelVmlDrawingBase : XmlHelper {
- protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
- "fill",
- "stroke",
- "shadow",
- "path",
- "textbox",
- "ClientData",
- "MoveWithCells",
- "SizeWithCells",
- "Anchor",
- "Locked",
- "AutoFill",
- "LockText",
- "TextHAlign",
- "TextVAlign",
- "Row",
- "Column",
- "Visible",
- ];
-
- internal ExcelVmlDrawingBase(XmlNode topNode, XmlNamespaceManager ns)
- : base(ns, topNode) {}
-
- public string Id {
- get => GetXmlNodeString("@id");
- set => SetXmlNodeString("@id", value);
- }
-
- /// <summary>
- /// Alternative text to be displayed instead of a graphic.
- /// </summary>
- public string AlternativeText {
- get => GetXmlNodeString("@alt");
- set => SetXmlNodeString("@alt", value);
- }
-
- protected bool GetStyle(string style, string key, out string value) {
- string[] styles = style.Split(';');
- foreach (string s in styles) {
- if (s.IndexOf(':') > 0) {
- string[] split = s.Split(':');
- if (split[0] == key) {
- value = split[1];
- return true;
- }
- } else if (s == key) {
- value = "";
- return true;
- }
- }
- value = "";
- return false;
- }
-
- protected string SetStyle(string style, string key, string value) {
- string[] styles = style.Split(';');
- string newStyle = "";
- bool changed = false;
- foreach (string s in styles) {
- string[] split = s.Split(':');
- if (split[0].Trim() == key) {
- if (value.Trim()
- != "") //If blank remove the item
- {
- newStyle += key + ':' + value;
- }
- changed = true;
- } else {
- newStyle += s;
- }
- newStyle += ';';
- }
- if (!changed) {
- newStyle += key + ':' + value;
- } else {
- newStyle = style.Substring(0, style.Length - 1);
- }
- return newStyle;
- }
-}
diff --git a/EPPlus/Drawing/Vml/ExcelVmlDrawingBaseCollection.cs b/EPPlus/Drawing/Vml/ExcelVmlDrawingBaseCollection.cs
deleted file mode 100644
index a0bd7e1..0000000
--- a/EPPlus/Drawing/Vml/ExcelVmlDrawingBaseCollection.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2010-06-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System;
-using System.Xml;
-using OfficeOpenXml.Packaging;
-
-namespace OfficeOpenXml.Drawing.Vml;
-
-public class ExcelVmlDrawingBaseCollection {
- internal ExcelVmlDrawingBaseCollection(ExcelPackage pck, ExcelWorksheet ws, Uri uri) {
- VmlDrawingXml.PreserveWhitespace = false;
-
- NameTable nt = new NameTable();
- NameSpaceManager = new(nt);
- NameSpaceManager.AddNamespace("v", ExcelPackage._schemaMicrosoftVml);
- NameSpaceManager.AddNamespace("o", ExcelPackage._schemaMicrosoftOffice);
- NameSpaceManager.AddNamespace("x", ExcelPackage._schemaMicrosoftExcel);
- Uri = uri;
- if (uri == null) {
- Part = null;
- } else {
- Part = pck.Package.GetPart(uri);
- XmlHelper.LoadXmlSafe(VmlDrawingXml, Part.GetStream());
- }
- }
-
- internal XmlDocument VmlDrawingXml { get; set; } = new();
-
- internal Uri Uri { get; set; }
- internal string RelId { get; set; }
- internal ZipPackagePart Part { get; set; }
- internal XmlNamespaceManager NameSpaceManager { get; set; }
-}
diff --git a/EPPlus/Drawing/Vml/ExcelVmlDrawingComment.cs b/EPPlus/Drawing/Vml/ExcelVmlDrawingComment.cs
deleted file mode 100644
index 7eecb26..0000000
--- a/EPPlus/Drawing/Vml/ExcelVmlDrawingComment.cs
+++ /dev/null
@@ -1,232 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2010-06-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System.Collections.Immutable;
-using System.Xml;
-
-namespace OfficeOpenXml.Drawing.Vml;
-
-/// <summary>
-/// Drawing object used for comments
-/// </summary>
-public class ExcelVmlDrawingComment : ExcelVmlDrawingBase, IRangeId {
- protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
- "fill",
- "stroke",
- "shadow",
- "path",
- "textbox",
- "ClientData",
- "MoveWithCells",
- "SizeWithCells",
- "Anchor",
- "Locked",
- "AutoFill",
- "LockText",
- "TextHAlign",
- "TextVAlign",
- "Row",
- "Column",
- "Visible",
- ];
-
- internal ExcelVmlDrawingComment(XmlNode topNode, ExcelRangeBase range, XmlNamespaceManager ns)
- : base(topNode, ns) {
- Range = range;
- }
-
- internal ExcelRangeBase Range { get; set; }
-
- /// <summary>
- /// Address in the worksheet
- /// </summary>
- public string Address => Range.Address;
-
- private const string _verticalAlignmentPath = "x:ClientData/x:TextVAlign";
-
- /// <summary>
- /// Vertical alignment for text
- /// </summary>
- public eTextAlignVerticalVml VerticalAlignment {
- get {
- switch (GetXmlNodeString(_verticalAlignmentPath)) {
- case "Center":
- return eTextAlignVerticalVml.Center;
- case "Bottom":
- return eTextAlignVerticalVml.Bottom;
- default:
- return eTextAlignVerticalVml.Top;
- }
- }
- set {
- switch (value) {
- case eTextAlignVerticalVml.Center:
- SetXmlNodeString(_verticalAlignmentPath, "Center");
- break;
- case eTextAlignVerticalVml.Bottom:
- SetXmlNodeString(_verticalAlignmentPath, "Bottom");
- break;
- default:
- DeleteNode(_verticalAlignmentPath);
- break;
- }
- }
- }
-
- private const string _horizontalAlignmentPath = "x:ClientData/x:TextHAlign";
-
- /// <summary>
- /// Horizontal alignment for text
- /// </summary>
- public eTextAlignHorizontalVml HorizontalAlignment {
- get {
- switch (GetXmlNodeString(_horizontalAlignmentPath)) {
- case "Center":
- return eTextAlignHorizontalVml.Center;
- case "Right":
- return eTextAlignHorizontalVml.Right;
- default:
- return eTextAlignHorizontalVml.Left;
- }
- }
- set {
- switch (value) {
- case eTextAlignHorizontalVml.Center:
- SetXmlNodeString(_horizontalAlignmentPath, "Center");
- break;
- case eTextAlignHorizontalVml.Right:
- SetXmlNodeString(_horizontalAlignmentPath, "Right");
- break;
- default:
- DeleteNode(_horizontalAlignmentPath);
- break;
- }
- }
- }
-
- private const string _visiblePath = "x:ClientData/x:Visible";
-
- /// <summary>
- /// If the drawing object is visible.
- /// </summary>
- public bool Visible {
- get => (TopNode.SelectSingleNode(_visiblePath, NameSpaceManager) != null);
- set {
- if (value) {
- CreateNode(_visiblePath);
- Style = SetStyle(Style, "visibility", "visible");
- } else {
- DeleteNode(_visiblePath);
- Style = SetStyle(Style, "visibility", "hidden");
- }
- }
- }
-
- private const string _textboxStylePath = "v:textbox/@style";
-
- /// <summary>
- /// Autofits the drawingobject
- /// </summary>
- public bool AutoFit {
- get {
- GetStyle(GetXmlNodeString(_textboxStylePath), "mso-fit-shape-to-text", out var value);
- return value == "t";
- }
- set =>
- SetXmlNodeString(
- _textboxStylePath,
- SetStyle(GetXmlNodeString(_textboxStylePath), "mso-fit-shape-to-text", value ? "t" : ""));
- }
-
- private const string _lockedPath = "x:ClientData/x:Locked";
-
- /// <summary>
- /// If the object is locked when the sheet is protected
- /// </summary>
- public bool Locked {
- get => GetXmlNodeBool(_lockedPath, false);
- set => SetXmlNodeBool(_lockedPath, value, false);
- }
-
- private const string _lockTextPath = "x:ClientData/x:LockText";
-
- /// <summary>
- /// Specifies that the object's text is locked
- /// </summary>
- public bool LockText {
- get => GetXmlNodeBool(_lockTextPath, false);
- set => SetXmlNodeBool(_lockTextPath, value, false);
- }
-
- private ExcelVmlDrawingPosition _from;
-
- /// <summary>
- /// From position. For comments only when Visible=true.
- /// </summary>
- public ExcelVmlDrawingPosition From {
- get {
- if (_from == null) {
- _from = new(
- NameSpaceManager,
- TopNode.SelectSingleNode("x:ClientData", NameSpaceManager),
- 0);
- }
- return _from;
- }
- }
-
- private ExcelVmlDrawingPosition _to;
-
- /// <summary>
- /// To position. For comments only when Visible=true.
- /// </summary>
- public ExcelVmlDrawingPosition To {
- get {
- if (_to == null) {
- _to = new(NameSpaceManager, TopNode.SelectSingleNode("x:ClientData", NameSpaceManager), 4);
- }
- return _to;
- }
- }
-
- private const string _stylePath = "@style";
-
- internal string Style {
- get => GetXmlNodeString(_stylePath);
- set => SetXmlNodeString(_stylePath, value);
- }
-
- ulong IRangeId.RangeID {
- get => ExcelCellBase.GetCellId(Range.Worksheet.SheetID, Range.Start.Row, Range.Start.Column);
- set {}
- }
-}
diff --git a/EPPlus/Drawing/Vml/ExcelVmlDrawingCommentCollection.cs b/EPPlus/Drawing/Vml/ExcelVmlDrawingCommentCollection.cs
deleted file mode 100644
index deb294c..0000000
--- a/EPPlus/Drawing/Vml/ExcelVmlDrawingCommentCollection.cs
+++ /dev/null
@@ -1,188 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2010-06-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Xml;
-
-namespace OfficeOpenXml.Drawing.Vml;
-
-internal class ExcelVmlDrawingCommentCollection : ExcelVmlDrawingBaseCollection, IEnumerable {
- internal RangeCollection _drawings;
-
- internal ExcelVmlDrawingCommentCollection(ExcelPackage pck, ExcelWorksheet ws, Uri uri)
- : base(pck, ws, uri) {
- if (uri == null) {
- VmlDrawingXml.LoadXml(CreateVmlDrawings());
- _drawings = new(new());
- } else {
- AddDrawingsFromXml(ws);
- }
- }
-
- protected void AddDrawingsFromXml(ExcelWorksheet ws) {
- var nodes = VmlDrawingXml.SelectNodes("//v:shape", NameSpaceManager);
- var list = new List<IRangeId>();
- foreach (XmlNode node in nodes) {
- var rowNode = node.SelectSingleNode("x:ClientData/x:Row", NameSpaceManager);
- var colNode = node.SelectSingleNode("x:ClientData/x:Column", NameSpaceManager);
- if (rowNode != null && colNode != null) {
- var row = int.Parse(rowNode.InnerText) + 1;
- var col = int.Parse(colNode.InnerText) + 1;
- list.Add(new ExcelVmlDrawingComment(node, ws.Cells[row, col], NameSpaceManager));
- } else {
- list.Add(new ExcelVmlDrawingComment(node, ws.Cells[1, 1], NameSpaceManager));
- }
- }
- list.Sort((r1, r2) =>
- (r1.RangeID < r2.RangeID
- ? -1
- : r1.RangeID > r2.RangeID
- ? 1
- : 0)); //Vml drawings are not sorted. Sort to avoid missmatches.
- _drawings = new(list);
- }
-
- private string CreateVmlDrawings() {
- string vml = string.Format(
- "<xml xmlns:v=\"{0}\" xmlns:o=\"{1}\" xmlns:x=\"{2}\">",
- ExcelPackage._schemaMicrosoftVml,
- ExcelPackage._schemaMicrosoftOffice,
- ExcelPackage._schemaMicrosoftExcel);
-
- vml += "<o:shapelayout v:ext=\"edit\">";
- vml += "<o:idmap v:ext=\"edit\" data=\"1\"/>";
- vml += "</o:shapelayout>";
-
- vml +=
- "<v:shapetype id=\"_x0000_t202\" coordsize=\"21600,21600\" o:spt=\"202\" path=\"m,l,21600r21600,l21600,xe\">";
- vml += "<v:stroke joinstyle=\"miter\" />";
- vml += "<v:path gradientshapeok=\"t\" o:connecttype=\"rect\" />";
- vml += "</v:shapetype>";
- vml += "</xml>";
-
- return vml;
- }
-
- internal ExcelVmlDrawingComment Add(ExcelRangeBase cell) {
- XmlNode node = AddDrawing(cell);
- var draw = new ExcelVmlDrawingComment(node, cell, NameSpaceManager);
- _drawings.Add(draw);
- return draw;
- }
-
- private XmlNode AddDrawing(ExcelRangeBase cell) {
- int row = cell.Start.Row,
- col = cell.Start.Column;
- var node = VmlDrawingXml.CreateElement("v", "shape", ExcelPackage._schemaMicrosoftVml);
-
- var id = ExcelCellBase.GetCellId(cell.Worksheet.SheetID, cell._fromRow, cell._fromCol);
- var ix = _drawings.IndexOf(id);
- if (ix < 0 && (~ix < _drawings.Count)) {
- ix = ~ix;
- var prevDraw = _drawings[ix] as ExcelVmlDrawingBase;
- prevDraw.TopNode.ParentNode.InsertBefore(node, prevDraw.TopNode);
- } else {
- VmlDrawingXml.DocumentElement.AppendChild(node);
- }
-
- node.SetAttribute("id", GetNewId());
- node.SetAttribute("type", "#_x0000_t202");
- node.SetAttribute("style", "position:absolute;z-index:1; visibility:hidden");
- //node.SetAttribute("style", "position:absolute; margin-left:59.25pt;margin-top:1.5pt;width:108pt;height:59.25pt;z-index:1; visibility:hidden");
- node.SetAttribute("fillcolor", "#ffffe1");
- node.SetAttribute("insetmode", ExcelPackage._schemaMicrosoftOffice, "auto");
-
- string vml = "<v:fill color2=\"#ffffe1\" />";
- vml += "<v:shadow on=\"t\" color=\"black\" obscured=\"t\" />";
- vml += "<v:path o:connecttype=\"none\" />";
- vml += "<v:textbox style=\"mso-direction-alt:auto\">";
- vml += "<div style=\"text-align:left\" />";
- vml += "</v:textbox>";
- vml += "<x:ClientData ObjectType=\"Note\">";
- vml += "<x:MoveWithCells />";
- vml += "<x:SizeWithCells />";
- vml += string.Format(
- "<x:Anchor>{0}, 15, {1}, 2, {2}, 31, {3}, 1</x:Anchor>",
- col,
- row - 1,
- col + 2,
- row + 3);
- vml += "<x:AutoFill>False</x:AutoFill>";
- vml += string.Format("<x:Row>{0}</x:Row>", row - 1);
- ;
- vml += string.Format("<x:Column>{0}</x:Column>", col - 1);
- vml += "</x:ClientData>";
-
- node.InnerXml = vml;
- return node;
- }
-
- private int _nextID;
-
- /// <summary>
- /// returns the next drawing id.
- /// </summary>
- /// <returns></returns>
- internal string GetNewId() {
- if (_nextID == 0) {
- foreach (ExcelVmlDrawingComment draw in this) {
- if (draw.Id.Length > 3 && draw.Id.StartsWith("vml")) {
- if (int.TryParse(draw.Id.Substring(3, draw.Id.Length - 3), out var id)) {
- if (id > _nextID) {
- _nextID = id;
- }
- }
- }
- }
- }
- _nextID++;
- return "vml" + _nextID;
- }
-
- internal ExcelVmlDrawingBase this[ulong rangeId] => _drawings[rangeId] as ExcelVmlDrawingComment;
-
- internal bool ContainsKey(ulong rangeId) {
- return _drawings.ContainsKey(rangeId);
- }
-
- internal int Count => _drawings.Count;
-
- public IEnumerator GetEnumerator() {
- return _drawings;
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- return _drawings;
- }
-}
diff --git a/EPPlus/Drawing/Vml/ExcelVmlDrawingPosition.cs b/EPPlus/Drawing/Vml/ExcelVmlDrawingPosition.cs
deleted file mode 100644
index ec28659..0000000
--- a/EPPlus/Drawing/Vml/ExcelVmlDrawingPosition.cs
+++ /dev/null
@@ -1,101 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2010-06-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.Drawing.Vml;
-
-/// <summary>
-/// The position of a VML drawing. Used for comments
-/// </summary>
-public class ExcelVmlDrawingPosition : XmlHelper {
- private readonly int _startPos;
-
- internal ExcelVmlDrawingPosition(XmlNamespaceManager ns, XmlNode topNode, int startPos)
- : base(ns, topNode) {
- _startPos = startPos;
- }
-
- /// <summary>
- /// Row. Zero based
- /// </summary>
- public int Row {
- get => GetNumber(2);
- set => SetNumber(2, value);
- }
-
- /// <summary>
- /// Row offset in pixels. Zero based
- /// </summary>
- public int RowOffset {
- get => GetNumber(3);
- set => SetNumber(3, value);
- }
-
- /// <summary>
- /// Column. Zero based
- /// </summary>
- public int Column {
- get => GetNumber(0);
- set => SetNumber(0, value);
- }
-
- /// <summary>
- /// Column offset. Zero based
- /// </summary>
- public int ColumnOffset {
- get => GetNumber(1);
- set => SetNumber(1, value);
- }
-
- private void SetNumber(int pos, int value) {
- string anchor = GetXmlNodeString("x:Anchor");
- string[] numbers = anchor.Split(',');
- if (numbers.Length == 8) {
- numbers[_startPos + pos] = value.ToString();
- } else {
- throw (new("Anchor element is invalid in vmlDrawing"));
- }
- SetXmlNodeString("x:Anchor", string.Join(",", numbers));
- }
-
- private int GetNumber(int pos) {
- string anchor = GetXmlNodeString("x:Anchor");
- string[] numbers = anchor.Split(',');
- if (numbers.Length == 8) {
- if (int.TryParse(numbers[_startPos + pos], out var ret)) {
- return ret;
- }
- }
- throw (new("Anchor element is invalid in vmlDrawing"));
- }
-}
diff --git a/EPPlus/EPPlus.csproj b/EPPlus/EPPlus.csproj
deleted file mode 100644
index 3cec524..0000000
--- a/EPPlus/EPPlus.csproj
+++ /dev/null
@@ -1,842 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.30729</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{7B288026-5502-4A39-BF41-77E086F3E4A3}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>OfficeOpenXml</RootNamespace>
- <AssemblyName>EPPlus</AssemblyName>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>OpenOfficeXml.snk</AssemblyOriginatorKeyFile>
- <SccProjectName>
- </SccProjectName>
- <SccLocalPath>
- </SccLocalPath>
- <SccAuxPath>
- </SccAuxPath>
- <SccProvider>
- </SccProvider>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <UpgradeBackupLocation>
- </UpgradeBackupLocation>
- <OldToolsVersion>3.5</OldToolsVersion>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile>
- </TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <DocumentationFile>bin\Debug\EPPlus.XML</DocumentationFile>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <NoWarn>
- </NoWarn>
- <Prefer32Bit>false</Prefer32Bit>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <DocumentationFile>bin\Release\EPPlus.XML</DocumentationFile>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <Prefer32Bit>false</Prefer32Bit>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core">
- <HintPath>C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll</HintPath>
- </Reference>
- <Reference Include="System.Data" />
- <Reference Include="System.Drawing" />
- <Reference Include="System.Security" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="CellStore.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingAverageGroup.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingBeginsWith.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingBetween.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingColorScaleGroup.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingContainsBlanks.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingContainsErrors.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingContainsText.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingDataBarGroup.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingDuplicateValues.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingEndsWith.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingEqual.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingExpression.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingGreaterThan.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingGreaterThanOrEqual.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingThreeIconSet.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingFourIconSet.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingFiveIconSet.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingIconSetGroup.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingThreeColorScale.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingLessThan.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingLessThanOrEqual.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingNotBetween.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingNotContainsBlanks.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingNotContainsErrors.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingNotContainsText.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingNotEqual.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingStdDevGroup.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingTimePeriodGroup.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingTopBottomGroup.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingTwoColorScale.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingUniqueValues.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingWithFormula.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingWithFormula2.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingWithRank.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingWithReverse.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingWithShowValue.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingWithStdDev.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingWithText.cs" />
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingIconDataBarValue.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingDataBar.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingFiveIconSet.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingFourIconSet.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingAboveStdDev.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingAboveOrEqualAverage.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingAverageGroup.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingAboveAverage.cs" />
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingCollection.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingOperatorType.cs" />
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingRuleFactory.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingConstants.cs" />
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingTimePeriodType.cs" />
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingColorScaleValue.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingEnums.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingValueObjectType.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingBeginsWith.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingBelowAverage.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingBelowOrEqualAverage.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingBelowStdDev.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingBetween.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingBottom.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingBottomPercent.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingContainsBlanks.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingContainsErrors.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingContainsText.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingDuplicateValues.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingEndsWith.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingEqual.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingExpression.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingGreaterThan.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingGreaterThanOrEqual.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingLast7Days.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingLastMonth.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingLastWeek.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingLessThan.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingLessThanOrEqual.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingNextMonth.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingNextWeek.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingNotBetween.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingNotContainsBlanks.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingNotContainsErrors.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingNotContainsText.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingNotEqual.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingRule.cs" />
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingRuleType.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingThisMonth.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingThisWeek.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingThreeColorScale.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingThreeIconSet.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingTimePeriodGroup.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingToday.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingTomorrow.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingTop.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingTopPercent.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingTwoColorScale.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingRule.cs" />
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingHelper.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IRangeConditionalFormatting.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\RangeConditionalFormatting.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingUniqueValues.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingYesterday.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidation.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationAny.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationCustom.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationDateTime.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationDecimal.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationInt.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationList.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationTime.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationWithFormula.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationWithFormula2.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationWithOperator.cs" />
- <Compile Include="DataValidation\ExcelDataValidationAny.cs" />
- <Compile Include="DataValidation\ExcelDataValidationCustom.cs" />
- <Compile Include="DataValidation\ExcelDataValidationDateTime.cs" />
- <Compile Include="DataValidation\ExcelDataValidationFactory.cs" />
- <Compile Include="DataValidation\ExcelDataValidationTime.cs" />
- <Compile Include="DataValidation\ExcelDataValidationWithFormula.cs" />
- <Compile Include="DataValidation\ExcelDataValidationWithFormula2.cs" />
- <Compile Include="DataValidation\ExcelTime.cs" />
- <Compile Include="DataValidation\Formulas\Contracts\IExcelDataValidationFormula.cs" />
- <Compile Include="DataValidation\Formulas\Contracts\IExcelDataValidationFormulaDateTime.cs" />
- <Compile Include="DataValidation\Formulas\Contracts\IExcelDataValidationFormulaTime.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormula.cs" />
- <Compile Include="DataValidation\Formulas\Contracts\IExcelDataValidationFormulaList.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormulaCustom.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormulaDateTime.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormulaList.cs" />
- <Compile Include="DataValidation\Formulas\Contracts\IExcelDataValidationFormulaWithValue.cs" />
- <Compile Include="DataValidation\Formulas\Contracts\IExcelDataValidationFormulaDecimal.cs" />
- <Compile Include="DataValidation\Formulas\Contracts\IExcelDataValidationFormulaInt.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormulaTime.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormulaValue.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormulaDecimal.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormulaInt.cs" />
- <Compile Include="DataValidation\ExcelDataValidationOperator.cs" />
- <Compile Include="DataValidation\ExcelDataValidationWarningStyle.cs" />
- <Compile Include="DataValidation\ExcelDataValidationDecimal.cs" />
- <Compile Include="DataValidation\ExcelDataValidationList.cs" />
- <Compile Include="DataValidation\ExcelDataValidationInt.cs" />
- <Compile Include="DataValidation\IRangeDataValidation.cs" />
- <Compile Include="DataValidation\RangeDataValidation.cs" />
- <Compile Include="Drawing\Chart\ExcelBarChartSerie.cs" />
- <Compile Include="Drawing\Chart\ExcelSurfaceChartSerie.cs" />
- <Compile Include="Drawing\Chart\ExcelSurfaceChart.cs" />
- <Compile Include="Drawing\Chart\ExcelRadarChart.cs" />
- <Compile Include="Drawing\Chart\ExcelBubbleChartSerie.cs" />
- <Compile Include="Drawing\Chart\ExcelLineChartSerie.cs" />
- <Compile Include="Drawing\Chart\ExcelChart.cs" />
- <Compile Include="Drawing\Chart\ExcelChartCollection.cs" />
- <Compile Include="Drawing\Chart\ExcelChartTrendline.cs" />
- <Compile Include="Drawing\Chart\ExcelBubbleChart.cs" />
- <Compile Include="Drawing\Chart\ExcelChartSurface.cs" />
- <Compile Include="Drawing\ExcelDrawingBase.cs" />
- <Compile Include="Drawing\ExcelPicture.cs" />
- <Compile Include="Drawing\Chart\ExcelRadarChartSerie.cs" />
- <Compile Include="Drawing\Vml\ExcelVmlDrawingPictureCollection.cs" />
- <Compile Include="Drawing\Vml\ExcelVmlDrawingCommentCollection.cs" />
- <Compile Include="Drawing\Vml\ExcelVmlDrawingPicture.cs" />
- <Compile Include="Drawing\Vml\ExcelVmlDrawingBase.cs" />
- <Compile Include="Encryption\EncryptionHandler.cs" />
- <Compile Include="Encryption\EncryptionHeader.cs" />
- <Compile Include="Encryption\EncryptionInfo.cs" />
- <Compile Include="Encryption\EncryptionVerifier.cs" />
- <Compile Include="ExcelBackgroundImage.cs" />
- <Compile Include="DataValidation\ExcelDataValidation.cs" />
- <Compile Include="DataValidation\ExcelDataValidationCollection.cs" />
- <Compile Include="DataValidation\ExcelDataValidationType.cs" />
- <Compile Include="ExcelEncryption.cs" />
- <Compile Include="ExcelProtectedRange.cs" />
- <Compile Include="ExcelProtectedRangeCollection.cs" />
- <Compile Include="ExcelStyleCollection.cs" />
- <Compile Include="ExcelColumn.cs" />
- <Compile Include="Drawing\ExcelDrawings.cs" />
- <Compile Include="ExcelHeaderFooter.cs" />
- <Compile Include="ExcelPackage.cs" />
- <Compile Include="ExcelRange.cs" />
- <Compile Include="ExcelRow.cs" />
- <Compile Include="Drawing\ExcelShape.cs" />
- <Compile Include="ExcelStyles.cs" />
- <Compile Include="ExcelProtection.cs" />
- <Compile Include="ExcelTextFormat.cs" />
- <Compile Include="FormulaParsing\CalculateExtentions.cs" />
- <Compile Include="FormulaParsing\DependencyChain\DependenyChainFactory.cs" />
- <Compile Include="FormulaParsing\DependencyChain\DependencyChain.cs" />
- <Compile Include="FormulaParsing\DependencyChain\FormulaCell.cs" />
- <Compile Include="FormulaParsing\EpplusExcelDataProvider.cs" />
- <Compile Include="FormulaParsing\ExcelCalculationOption.cs" />
- <Compile Include="FormulaParsing\ExcelCell.cs" />
- <Compile Include="FormulaParsing\ExcelDataProvider.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\AddressTranslator.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\CellReferenceProvider.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\ExcelAddressInfo.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\ExcelAddressUtil.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\ExcelReferenceType.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\FormulaDependencies.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\FormulaDependency.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\FormulaDependencyFactory.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\IndexToAddressTranslator.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\LookupValueMatcher.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\NumericExpressionEvaluator.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\RangeAddress.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\RangeAddressFactory.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\ValueMatcher.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\WildCardValueMatcher.cs" />
- <Compile Include="FormulaParsing\ExcelValues.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\CompileResultValidator.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\CompileResultValidators.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\CellStateHelper.cs" />
- <Compile Include="FormulaParsing\Excel\ExcelCellState.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\ArgumentCollectionUtil.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\ArgumentParser.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\ArgumentParserFactory.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\ArgumentParsers.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\BoolArgumentParser.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\BuiltInFunctions.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\CollectionFlattener.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\DatabaseFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\Daverage.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\Dcount.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\DcountA.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\Dget.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\Dmax.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\Dmin.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\Dsum.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\Dvar.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="FormulaParsing\Excel\Functions\Database\Dvarp.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\ExcelDatabase.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\ExcelDatabaseCriteria.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\ExcelDatabaseCriteriaField.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\ExcelDatabaseField.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\ExcelDatabaseRow.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\RowMatcher.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Date.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\DateParsingFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\DateStringParser.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Day.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Days360.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Edate.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Eomonth.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Hour.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\IsoWeekNum.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Weeknum.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Minute.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Month.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Now.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Second.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Time.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\TimeBaseFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\TimeStringParser.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Today.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Weekday.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Workday.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Year.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Yearfrac.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DecimalCompileResultValidator.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DoubleArgumentParser.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DoubleEnumerableArgConverter.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\ErrorHandlingFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\ExcelFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\FunctionArgument.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\FunctionRepository.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\FunctionsModule.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\HiddenValuesHandlingFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\IFunctionModule.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\IFunctionNameProvider.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\ErrorType.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsBlank.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsErr.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsError.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsEven.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsLogical.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsNa.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsNonText.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsNumber.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsOdd.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsText.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\N.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\Na.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\IntArgumentParser.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\And.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\False.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\If.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\IfError.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\IfNa.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\Not.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\Or.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\True.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Abs.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Acos.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Acosh.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Asin.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Asinh.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Atan.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Atan2.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Atanh.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Average.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\AverageA.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\AverageIf.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\AverageIfs.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Ceiling.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Cos.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Cosh.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Count.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\CountA.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\CountBlank.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\CountIf.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\CountIfs.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Degrees.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Exp.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Fact.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Floor.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Large.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Ln.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Log.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Log10.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\MathHelper.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Max.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Maxa.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Median.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Min.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Mina.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Mod.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\MultipleRangeCriteriasFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Pi.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Power.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Product.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Quotient.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Rand.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\RandBetween.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Round.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Rounddown.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Roundup.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Sign.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Sin.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Sinh.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Small.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Sqrt.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\SqrtPi.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Stdev.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\StdevP.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Subtotal.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Sum.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\SumIf.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\SumIfs.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\SumProduct.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Sumsq.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Tan.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Tanh.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Trunc.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Var.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\VarMethods.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\VarP.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Numeric\CInt.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\ObjectEnumerableArgConverter.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Address.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\ArrayLookupNavigator.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Choose.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Column.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Columns.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\ExcelLookupNavigator.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\HLookup.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Index.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Indirect.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Lookup.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\LookupArguments.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\LookupDirection.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\LookupFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\LookupNavigator.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\LookupNavigatorFactory.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Match.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Offset.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Row.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Rows.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\VLookup.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\CharFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Concatenate.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\CStr.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Exact.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Find.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Fixed.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Hyperlink.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Left.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Len.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Lower.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Rept.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Text.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Mid.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Proper.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Replace.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Right.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Substitute.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\T.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Upper.cs" />
- <Compile Include="FormulaParsing\Excel\Operators\IOperator.cs" />
- <Compile Include="FormulaParsing\Excel\Operators\Operator.cs" />
- <Compile Include="FormulaParsing\Excel\Operators\Operators.cs" />
- <Compile Include="FormulaParsing\Excel\Operators\OperatorsDict.cs" />
- <Compile Include="FormulaParsing\Exceptions\CircularReferenceException.cs" />
- <Compile Include="FormulaParsing\Exceptions\ExcelErrorCodes.cs" />
- <Compile Include="FormulaParsing\Exceptions\ExcelErrorValueException.cs" />
- <Compile Include="FormulaParsing\Exceptions\UnrecognizedTokenException.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\AtomicExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\BooleanExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\CompileResult.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\CompileResultFactory.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\CompileStrategy\CompileStrategy.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\CompileStrategy\CompileStrategyFactory.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\CompileStrategy\DefaultCompileStrategy.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\CompileStrategy\ICompileStrategyFactory.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\CompileStrategy\StringConcatStrategy.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ExcelErrorExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\DataType.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\DateExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\DecimalExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\EnumerableExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ExcelAddressExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\Expression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ExpressionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ConstantExpressions.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ExpressionConverter.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ExpressionFactory.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ExpressionGraph.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ExpressionGraphBuilder.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionArgumentExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\DefaultCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\ErrorHandlingFunctionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\FunctionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\FunctionCompilerFactory.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\IfErrorFunctionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\IfFunctionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\IfNaFunctionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\LookupFunctionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\GroupExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\IExpressionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\IExpressionConverter.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\IExpressionFactory.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\IExpressionGraphBuilder.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\IntegerExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\NamedValueExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\StringExpression.cs" />
- <Compile Include="FormulaParsing\FormulaParser.cs" />
- <Compile Include="FormulaParsing\FormulaParserManager.cs" />
- <Compile Include="FormulaParsing\Logging\IFormulaParserLogger.cs" />
- <Compile Include="FormulaParsing\INameValueProvider.cs" />
- <Compile Include="FormulaParsing\IParsingLifetimeEventHandler.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\FunctionNameProvider.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\ILexer.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\ISourceCodeTokenizer.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\ISyntacticAnalyzer.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\ITokenFactory.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\ITokenSeparatorProvider.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\Lexer.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\SourceCodeTokenizer.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\SyntacticAnalyzer.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\Token.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\TokenFactory.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\TokenizerContext.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\TokenSeparatorProvider.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\TokenType.cs" />
- <Compile Include="FormulaParsing\EpplusNameValueProvider.cs" />
- <Compile Include="FormulaParsing\Logging\LoggerFactory.cs" />
- <Compile Include="FormulaParsing\Logging\TextFileLogger.cs" />
- <Compile Include="FormulaParsing\NameValueProvider.cs" />
- <Compile Include="FormulaParsing\ParsedValue.cs" />
- <Compile Include="FormulaParsing\ParsingConfiguration.cs" />
- <Compile Include="FormulaParsing\ParsingContext.cs" />
- <Compile Include="FormulaParsing\ParsingScope.cs" />
- <Compile Include="FormulaParsing\ParsingScopes.cs" />
- <Compile Include="FormulaParsing\Utilities\ArgumentInfo.cs" />
- <Compile Include="FormulaParsing\Utilities\ExtensionMethods.cs" />
- <Compile Include="FormulaParsing\Utilities\IdProvider.cs" />
- <Compile Include="FormulaParsing\Utilities\IntegerIdProvider.cs" />
- <Compile Include="FormulaParsing\Utilities\RegexConstants.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="FormulaParsing\Utilities\Require.cs" />
- <Compile Include="Packaging\DotNetZip\ComHelper.cs" />
- <Compile Include="Packaging\DotNetZip\CRC32.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\EncryptionAlgorithm.cs" />
- <Compile Include="Packaging\DotNetZip\Events.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Exceptions.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ExtractExistingFileAction.cs" />
- <Compile Include="Packaging\DotNetZip\FileSelector.cs" />
- <Compile Include="Packaging\DotNetZip\OffsetStream.cs" />
- <Compile Include="Packaging\DotNetZip\Shared.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\WinZipAes.cs" />
- <Compile Include="Packaging\DotNetZip\ZipConstants.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipCrypto.cs" />
- <Compile Include="Packaging\DotNetZip\ZipDirEntry.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipEntry.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipEntry.Extract.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipEntry.Read.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipEntry.Write.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipEntrySource.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipErrorAction.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipFile.AddUpdate.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.Check.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.Events.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.Extract.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.Read.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.Save.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.SaveSelfExtractor.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.Selector.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.x-IEnumerable.cs" />
- <Compile Include="Packaging\DotNetZip\ZipInputStream.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipOutputStream.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipSegmentedStream.cs" />
- <Compile Include="Packaging\DotNetZip\Zlib\Deflate.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\DeflateStream.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\GZipStream.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\Inflate.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\InfTree.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\ParallelDeflateOutputStream.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\Tree.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\Zlib.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\ZlibBaseStream.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\ZlibCodec.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\ZlibConstants.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\ZlibStream.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="RangeCollection.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Utils\ConvertUtil.cs" />
- <Compile Include="Utils\UriHelper.cs" />
- <Compile Include="Packaging\ZipPackage.cs" />
- <Compile Include="VBA\ExcelVbaModule.cs" />
- <Compile Include="VBA\ExcelVbaModuleAttribute.cs" />
- <Compile Include="VBA\ExcelVbaModuleCollection.cs" />
- <Compile Include="VBA\ExcelVbaProject.cs" />
- <Compile Include="ExcelWorkbookView.cs" />
- <Compile Include="ExcelWorksheetView.cs" />
- <Compile Include="Style\Dxf\DxfStyleBase.cs" />
- <Compile Include="Style\Dxf\ExcelDxfBorder.cs" />
- <Compile Include="Style\Dxf\ExcelDxfBorderItem.cs" />
- <Compile Include="Style\Dxf\ExcelDxfColor.cs" />
- <Compile Include="Style\Dxf\ExcelDxfFill.cs" />
- <Compile Include="Style\Dxf\ExcelDxfFontBase.cs" />
- <Compile Include="Style\Dxf\ExcelDxfNumberFormat.cs" />
- <Compile Include="Style\Dxf\ExcelDxfStyle.cs" />
- <Compile Include="Style\ExcelGradientFill.cs" />
- <Compile Include="Style\XmlAccess\ExcelGradientFillXml.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTableFieldGroup.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTableFieldItem.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTablePageFieldSettings.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTableDataField.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTableFieldCollection.cs" />
- <Compile Include="Style\IStyle.cs" />
- <Compile Include="OfficeProperties.cs" />
- <Compile Include="ExcelWorkbook.cs" />
- <Compile Include="ExcelWorksheet.cs" />
- <Compile Include="ExcelWorksheets.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- <Compile Include="Style\XmlAccess\ExcelBorderXml.cs" />
- <Compile Include="Style\XmlAccess\ExcelBorderItemXml.cs" />
- <Compile Include="Style\XmlAccess\ExcelXfsXml.cs" />
- <Compile Include="Style\XmlAccess\ExcelNamedStyleXml.cs" />
- <Compile Include="Style\XmlAccess\ExcelColorXml.cs" />
- <Compile Include="Style\XmlAccess\ExcelFillXml.cs" />
- <Compile Include="Style\XmlAccess\ExcelFontXml.cs" />
- <Compile Include="Style\XmlAccess\ExcelNumberFormatXml.cs" />
- <Compile Include="Style\StyleChangeEventArgs.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotCacheDefinition.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTableField.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTableCollection.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTable.cs" />
- <Compile Include="Table\ExcelTableColumnCollection.cs" />
- <Compile Include="Table\ExcelTable.cs" />
- <Compile Include="Table\ExcelTableCollection.cs" />
- <Compile Include="Table\ExcelTableColumn.cs" />
- <Compile Include="Utils\AddressUtility.cs" />
- <Compile Include="Utils\Argument.cs" />
- <Compile Include="Utils\ArgumentExtensions.cs" />
- <Compile Include="Utils\CompoundDocument.cs" />
- <Compile Include="Utils\IArgument.cs" />
- <Compile Include="Utils\Require.cs" />
- <Compile Include="Utils\SqRefUtility.cs" />
- <Compile Include="VBA\ExcelVbaProtection.cs" />
- <Compile Include="VBA\ExcelVbaReference.cs" />
- <Compile Include="VBA\ExcelVbaSignature.cs" />
- <Compile Include="XmlHelper.cs" />
- <Compile Include="XmlHelperFactory.cs" />
- <Compile Include="Packaging\ZipPackagePart.cs" />
- <Compile Include="Packaging\ZipPackageRelationship.cs" />
- <Compile Include="Packaging\ZipPackageRelationshipCollection.cs" />
- <Compile Include="Packaging\ZipPackageRelationshipBase.cs" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Drawing\Chart\ExcelLineChart.cs" />
- <Compile Include="Drawing\Vml\ExcelVmlDrawingComment.cs" />
- <Compile Include="Drawing\Vml\ExcelVmlDrawingPosition.cs" />
- <Compile Include="Drawing\Vml\ExcelVmlDrawingBaseCollection.cs" />
- <Compile Include="ExcelAddress.cs" />
- <Compile Include="ExcelCellAddress.cs" />
- <Compile Include="ExcelComment.cs" />
- <Compile Include="ExcelCommentCollection.cs" />
- <Compile Include="ExcelSheetProtection.cs" />
- <Compile Include="Drawing\Chart\ExcelChartLegend.cs" />
- <Compile Include="Drawing\Chart\ExcelChartPlotArea.cs" />
- <Compile Include="Drawing\Chart\ExcelChartSerieDataLabel.cs" />
- <Compile Include="Drawing\Chart\ExcelScatterChartSerie.cs" />
- <Compile Include="Drawing\Chart\ExcelChartTitle.cs" />
- <Compile Include="Drawing\ExcelDrawingBorder.cs" />
- <Compile Include="Drawing\Chart\ExcelOfPieChart.cs" />
- <Compile Include="Drawing\ExcelDrawingFill.cs" />
- <Compile Include="Drawing\Chart\ExcelPieChartSerie.cs" />
- <Compile Include="Drawing\ExcelView3D.cs" />
- <Compile Include="Drawing\Chart\ExcelBarChart.cs" />
- <Compile Include="Drawing\Chart\ExcelChartAxis.cs" />
- <Compile Include="Drawing\Chart\ExcelChartDataLabel.cs" />
- <Compile Include="Drawing\Chart\ExcelChartSerie.cs" />
- <Compile Include="Drawing\Chart\ExcelChartSeries.cs" />
- <Compile Include="Drawing\Chart\ExcelDoughnutChart.cs" />
- <Compile Include="Drawing\Chart\ExcelPieChart.cs" />
- <Compile Include="Drawing\Chart\ExcelScatterChart.cs" />
- <Compile Include="ExcelCellBase.cs" />
- <Compile Include="ExcelHyperLink.cs" />
- <Compile Include="ExcelNamedRange.cs" />
- <Compile Include="ExcelNamedRangeCollection.cs" />
- <Compile Include="ExcelPrinterSettings.cs" />
- <Compile Include="ExcelRangeBase.cs" />
- <Compile Include="IRangeID.cs" />
- <Compile Include="Style\ExcelParagraph.cs" />
- <Compile Include="Style\ExcelParagraphCollection.cs" />
- <Compile Include="Style\ExcelBorder.cs" />
- <Compile Include="Style\ExcelBorderItem.cs" />
- <Compile Include="Style\ExcelColor.cs" />
- <Compile Include="Style\ExcelFill.cs" />
- <Compile Include="Style\ExcelRichText.cs" />
- <Compile Include="Style\ExcelRichTextCollection.cs" />
- <Compile Include="Utils\IExcelCell.cs" />
- <Compile Include="Style\ExcelStyle.cs" />
- <Compile Include="Style\ExcelFont.cs" />
- <Compile Include="Style\XmlAccess\StyleXmlHelper.cs" />
- <Compile Include="Style\ExcelNumberFormat.cs" />
- <Compile Include="Style\StyleBase.cs" />
- <Compile Include="Style\ExcelTextFont.cs" />
- </ItemGroup>
- <ItemGroup>
- <None Include="OpenOfficeXml.snk" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <ItemGroup>
- <Compile Include="ConditionalFormatting\CF Implementation.cs" />
- </ItemGroup>
- <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
- <PropertyGroup>
- <PostBuildEvent>
- </PostBuildEvent>
- <PreBuildEvent>
- </PreBuildEvent>
- </PropertyGroup>
-</Project>
\ No newline at end of file
diff --git a/EPPlus/EPPlusNet4.csproj b/EPPlus/EPPlusNet4.csproj
deleted file mode 100644
index 3f7b3b0..0000000
--- a/EPPlus/EPPlusNet4.csproj
+++ /dev/null
@@ -1,860 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.30729</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{BE4A6343-F411-44A3-8D6F-F40747ED7BA5}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>OfficeOpenXml</RootNamespace>
- <AssemblyName>EPPlus</AssemblyName>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>OpenOfficeXml.snk</AssemblyOriginatorKeyFile>
- <SccProjectName>
- </SccProjectName>
- <SccLocalPath>
- </SccLocalPath>
- <SccAuxPath>
- </SccAuxPath>
- <SccProvider>
- </SccProvider>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <UpgradeBackupLocation>
- </UpgradeBackupLocation>
- <OldToolsVersion>3.5</OldToolsVersion>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile>Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug4\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <DocumentationFile>bin\Debug4\EPPlus.XML</DocumentationFile>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <NoWarn>15191, CS1591</NoWarn>
- <Prefer32Bit>false</Prefer32Bit>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release4\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <DocumentationFile>bin\Release4\EPPlus.XML</DocumentationFile>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <Prefer32Bit>false</Prefer32Bit>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DevTest|AnyCPU'">
- <OutputPath>bin\</OutputPath>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="PresentationCore" />
- <Reference Include="System" />
- <Reference Include="System.Core">
- <HintPath>C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll</HintPath>
- </Reference>
- <Reference Include="System.Data" />
- <Reference Include="System.Drawing" />
- <Reference Include="System.Security" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="CellStore.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingAverageGroup.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingBeginsWith.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingBetween.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingColorScaleGroup.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingContainsBlanks.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingContainsErrors.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingContainsText.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingDataBarGroup.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingDuplicateValues.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingEndsWith.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingEqual.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingExpression.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingGreaterThan.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingGreaterThanOrEqual.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingThreeIconSet.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingFourIconSet.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingFiveIconSet.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingIconSetGroup.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingThreeColorScale.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingLessThan.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingLessThanOrEqual.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingNotBetween.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingNotContainsBlanks.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingNotContainsErrors.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingNotContainsText.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingNotEqual.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingStdDevGroup.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingTimePeriodGroup.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingTopBottomGroup.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingTwoColorScale.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingUniqueValues.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingWithFormula.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingWithFormula2.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingWithRank.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingWithReverse.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingWithShowValue.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingWithStdDev.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingWithText.cs" />
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingIconDataBarValue.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingDataBar.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingFiveIconSet.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingFourIconSet.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingAboveStdDev.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingAboveOrEqualAverage.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingAverageGroup.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingAboveAverage.cs" />
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingCollection.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingOperatorType.cs" />
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingRuleFactory.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingConstants.cs" />
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingTimePeriodType.cs" />
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingColorScaleValue.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingEnums.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingValueObjectType.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingBeginsWith.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingBelowAverage.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingBelowOrEqualAverage.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingBelowStdDev.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingBetween.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingBottom.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingBottomPercent.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingContainsBlanks.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingContainsErrors.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingContainsText.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingDuplicateValues.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingEndsWith.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingEqual.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingExpression.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingGreaterThan.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingGreaterThanOrEqual.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingLast7Days.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingLastMonth.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingLastWeek.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingLessThan.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingLessThanOrEqual.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingNextMonth.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingNextWeek.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingNotBetween.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingNotContainsBlanks.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingNotContainsErrors.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingNotContainsText.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingNotEqual.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingRule.cs" />
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingRuleType.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingThisMonth.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingThisWeek.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingThreeColorScale.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingThreeIconSet.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingTimePeriodGroup.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingToday.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingTomorrow.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingTop.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingTopPercent.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingTwoColorScale.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IExcelConditionalFormattingRule.cs" />
- <Compile Include="ConditionalFormatting\ExcelConditionalFormattingHelper.cs" />
- <Compile Include="ConditionalFormatting\Contracts\IRangeConditionalFormatting.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\RangeConditionalFormatting.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingUniqueValues.cs" />
- <Compile Include="ConditionalFormatting\Rules\ExcelConditionalFormattingYesterday.cs" />
- <Compile Include="FontSize.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidation.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationAny.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationCustom.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationDateTime.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationDecimal.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationInt.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationList.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationTime.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationWithFormula.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationWithFormula2.cs" />
- <Compile Include="DataValidation\Contracts\IExcelDataValidationWithOperator.cs" />
- <Compile Include="DataValidation\ExcelDataValidationAny.cs" />
- <Compile Include="DataValidation\ExcelDataValidationCustom.cs" />
- <Compile Include="DataValidation\ExcelDataValidationDateTime.cs" />
- <Compile Include="DataValidation\ExcelDataValidationFactory.cs" />
- <Compile Include="DataValidation\ExcelDataValidationTime.cs" />
- <Compile Include="DataValidation\ExcelDataValidationWithFormula.cs" />
- <Compile Include="DataValidation\ExcelDataValidationWithFormula2.cs" />
- <Compile Include="DataValidation\ExcelTime.cs" />
- <Compile Include="DataValidation\Formulas\Contracts\IExcelDataValidationFormula.cs" />
- <Compile Include="DataValidation\Formulas\Contracts\IExcelDataValidationFormulaDateTime.cs" />
- <Compile Include="DataValidation\Formulas\Contracts\IExcelDataValidationFormulaTime.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormula.cs" />
- <Compile Include="DataValidation\Formulas\Contracts\IExcelDataValidationFormulaList.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormulaCustom.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormulaDateTime.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormulaList.cs" />
- <Compile Include="DataValidation\Formulas\Contracts\IExcelDataValidationFormulaWithValue.cs" />
- <Compile Include="DataValidation\Formulas\Contracts\IExcelDataValidationFormulaDecimal.cs" />
- <Compile Include="DataValidation\Formulas\Contracts\IExcelDataValidationFormulaInt.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormulaTime.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormulaValue.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormulaDecimal.cs" />
- <Compile Include="DataValidation\Formulas\ExcelDataValidationFormulaInt.cs" />
- <Compile Include="DataValidation\ExcelDataValidationOperator.cs" />
- <Compile Include="DataValidation\ExcelDataValidationWarningStyle.cs" />
- <Compile Include="DataValidation\ExcelDataValidationDecimal.cs" />
- <Compile Include="DataValidation\ExcelDataValidationList.cs" />
- <Compile Include="DataValidation\ExcelDataValidationInt.cs" />
- <Compile Include="DataValidation\IRangeDataValidation.cs" />
- <Compile Include="DataValidation\RangeDataValidation.cs" />
- <Compile Include="Drawing\Chart\ExcelBarChartSerie.cs" />
- <Compile Include="Drawing\Chart\ExcelSurfaceChartSerie.cs" />
- <Compile Include="Drawing\Chart\ExcelSurfaceChart.cs" />
- <Compile Include="Drawing\Chart\ExcelRadarChart.cs" />
- <Compile Include="Drawing\Chart\ExcelBubbleChartSerie.cs" />
- <Compile Include="Drawing\Chart\ExcelLineChartSerie.cs" />
- <Compile Include="Drawing\Chart\ExcelChart.cs" />
- <Compile Include="Drawing\Chart\ExcelChartCollection.cs" />
- <Compile Include="Drawing\Chart\ExcelChartTrendline.cs" />
- <Compile Include="Drawing\Chart\ExcelBubbleChart.cs" />
- <Compile Include="Drawing\Chart\ExcelChartSurface.cs" />
- <Compile Include="Drawing\ExcelDrawingBase.cs" />
- <Compile Include="Drawing\ExcelDrawingLineEnd.cs" />
- <Compile Include="Drawing\ExcelPicture.cs" />
- <Compile Include="Drawing\Chart\ExcelRadarChartSerie.cs" />
- <Compile Include="Drawing\Vml\ExcelVmlDrawingPictureCollection.cs" />
- <Compile Include="Drawing\Vml\ExcelVmlDrawingCommentCollection.cs" />
- <Compile Include="Drawing\Vml\ExcelVmlDrawingPicture.cs" />
- <Compile Include="Drawing\Vml\ExcelVmlDrawingBase.cs" />
- <Compile Include="Encryption\EncryptionHandler.cs" />
- <Compile Include="Encryption\EncryptionHeader.cs" />
- <Compile Include="Encryption\EncryptionInfo.cs" />
- <Compile Include="Encryption\EncryptionVerifier.cs" />
- <Compile Include="ExcelBackgroundImage.cs" />
- <Compile Include="DataValidation\ExcelDataValidation.cs" />
- <Compile Include="DataValidation\ExcelDataValidationCollection.cs" />
- <Compile Include="DataValidation\ExcelDataValidationType.cs" />
- <Compile Include="ExcelEncryption.cs" />
- <Compile Include="ExcelProtectedRange.cs" />
- <Compile Include="ExcelProtectedRangeCollection.cs" />
- <Compile Include="ExcelRangeCopyOptionFlags.cs" />
- <Compile Include="ExcelStyleCollection.cs" />
- <Compile Include="ExcelColumn.cs" />
- <Compile Include="Drawing\ExcelDrawings.cs" />
- <Compile Include="ExcelHeaderFooter.cs" />
- <Compile Include="ExcelPackage.cs" />
- <Compile Include="ExcelRange.cs" />
- <Compile Include="ExcelRow.cs" />
- <Compile Include="Drawing\ExcelShape.cs" />
- <Compile Include="ExcelStyles.cs" />
- <Compile Include="ExcelProtection.cs" />
- <Compile Include="ExcelTextFormat.cs" />
- <Compile Include="FormulaParsing\CalculateExtentions.cs" />
- <Compile Include="FormulaParsing\DependencyChain\DependenyChainFactory.cs" />
- <Compile Include="FormulaParsing\DependencyChain\DependencyChain.cs" />
- <Compile Include="FormulaParsing\DependencyChain\FormulaCell.cs" />
- <Compile Include="FormulaParsing\EpplusExcelDataProvider.cs" />
- <Compile Include="FormulaParsing\ExcelCalculationOption.cs" />
- <Compile Include="FormulaParsing\ExcelCell.cs" />
- <Compile Include="FormulaParsing\ExcelDataProvider.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\AddressTranslator.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\CellReferenceProvider.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\ExcelAddressInfo.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\ExcelAddressUtil.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\ExcelReferenceType.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\ExpressionEvaluator.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\FormulaDependencies.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\FormulaDependency.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\FormulaDependencyFactory.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\IndexToAddressTranslator.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\LookupValueMatcher.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\RangeAddress.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\RangeAddressFactory.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\ValueMatcher.cs" />
- <Compile Include="FormulaParsing\ExcelUtilities\WildCardValueMatcher.cs" />
- <Compile Include="FormulaParsing\ExcelValues.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\CompileResultValidator.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\CompileResultValidators.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\CellStateHelper.cs" />
- <Compile Include="FormulaParsing\Excel\ExcelCellState.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\ArgumentCollectionUtil.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\ArgumentParser.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\ArgumentParserFactory.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\ArgumentParsers.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\BoolArgumentParser.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\BuiltInFunctions.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\CollectionFlattener.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\DatabaseFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\Daverage.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\Dcount.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\DcountA.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\Dget.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\Dmax.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\Dmin.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\Dsum.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\Dvar.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="FormulaParsing\Excel\Functions\Database\Dvarp.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\ExcelDatabase.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\ExcelDatabaseCriteria.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\ExcelDatabaseCriteriaField.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\ExcelDatabaseField.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\ExcelDatabaseRow.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Database\RowMatcher.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Date.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\DateParsingFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\DateStringParser.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\DateValue.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Day.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Days360.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Edate.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Eomonth.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Hour.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\IsoWeekNum.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\TimeValue.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Weeknum.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Minute.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Month.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Now.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Second.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Time.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\TimeBaseFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\TimeStringParser.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Today.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Weekday.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Workday.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Year.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DateTime\Yearfrac.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DecimalCompileResultValidator.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DoubleArgumentParser.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\DoubleEnumerableArgConverter.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\ErrorHandlingFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\ExcelFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\FunctionArgument.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\FunctionRepository.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\FunctionsModule.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\HiddenValuesHandlingFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\IFunctionModule.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\IFunctionNameProvider.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\ErrorType.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsBlank.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsErr.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsError.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsEven.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsLogical.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsNa.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsNonText.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsNumber.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsOdd.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\IsText.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\N.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Information\Na.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\IntArgumentParser.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\And.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\False.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\If.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\IfError.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\IfNa.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\Not.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\Or.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Logical\True.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Abs.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Acos.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Acosh.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Asin.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Asinh.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Atan.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Atan2.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Atanh.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Average.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\AverageA.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\AverageIf.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\AverageIfs.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Ceiling.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Cos.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Cosh.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Count.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\CountA.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\CountBlank.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\CountIf.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\CountIfs.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Degrees.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Exp.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Fact.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Floor.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Large.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Ln.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Log.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Log10.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\MathHelper.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Max.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Maxa.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Median.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Min.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Mina.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Mod.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\MultipleRangeCriteriasFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Pi.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Power.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Product.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Quotient.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Rank.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Rand.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\RandBetween.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Round.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Rounddown.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Roundup.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Sign.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Sin.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Sinh.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Small.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Sqrt.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\SqrtPi.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Stdev.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\StdevP.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Subtotal.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Sum.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\SumIf.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\SumIfs.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\SumProduct.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Sumsq.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Tan.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Tanh.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Trunc.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\Var.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\VarMethods.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Math\VarP.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Numeric\CInt.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\ObjectEnumerableArgConverter.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Address.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\ArrayLookupNavigator.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Choose.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Column.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Columns.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\ExcelLookupNavigator.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\HLookup.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Index.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Indirect.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Lookup.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\LookupArguments.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\LookupDirection.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\LookupFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\LookupNavigator.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\LookupNavigatorFactory.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Match.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Offset.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Row.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\Rows.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\RefAndLookup\VLookup.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\CharFunction.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Concatenate.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\CStr.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Exact.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Find.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Fixed.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Hyperlink.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Left.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Len.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Lower.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Rept.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Search.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Text.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Mid.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Proper.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Replace.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Right.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Substitute.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\T.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Upper.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\Text\Value.cs" />
- <Compile Include="FormulaParsing\Excel\Operators\IOperator.cs" />
- <Compile Include="FormulaParsing\Excel\Operators\Operator.cs" />
- <Compile Include="FormulaParsing\Excel\Operators\Operators.cs" />
- <Compile Include="FormulaParsing\Excel\Operators\OperatorsDict.cs" />
- <Compile Include="FormulaParsing\Exceptions\CircularReferenceException.cs" />
- <Compile Include="FormulaParsing\Exceptions\ExcelErrorCodes.cs" />
- <Compile Include="FormulaParsing\Exceptions\ExcelErrorValueException.cs" />
- <Compile Include="FormulaParsing\Exceptions\UnrecognizedTokenException.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\AtomicExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\BooleanExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\CompileResult.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\CompileResultFactory.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\CompileStrategy\CompileStrategy.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\CompileStrategy\CompileStrategyFactory.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\CompileStrategy\DefaultCompileStrategy.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\CompileStrategy\ICompileStrategyFactory.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\CompileStrategy\StringConcatStrategy.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ExcelErrorExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\DataType.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\DateExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\DecimalExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\EnumerableExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ExcelAddressExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\Expression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ExpressionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ConstantExpressions.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ExpressionConverter.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ExpressionFactory.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ExpressionGraph.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\ExpressionGraphBuilder.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionArgumentExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\DefaultCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\ErrorHandlingFunctionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\FunctionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\FunctionCompilerFactory.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\IfErrorFunctionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\IfFunctionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\IfNaFunctionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionCompilers\LookupFunctionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\FunctionExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\GroupExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\IExpressionCompiler.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\IExpressionConverter.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\IExpressionFactory.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\IExpressionGraphBuilder.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\IntegerExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\NamedValueExpression.cs" />
- <Compile Include="FormulaParsing\ExpressionGraph\StringExpression.cs" />
- <Compile Include="FormulaParsing\FormulaParser.cs" />
- <Compile Include="FormulaParsing\FormulaParserManager.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\ITokenIndexProvider.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\TokenHandler.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\TokenSeparatorHandlers\BracketHandler.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\TokenSeparatorHandlers\MultipleCharSeparatorHandler.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\TokenSeparatorHandlers\SeparatorHandler.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\TokenSeparatorHandlers\SheetnameHandler.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\TokenSeparatorHandlers\StringHandler.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\TokenSeparatorHandlers\TokenSeparatorHandler.cs" />
- <Compile Include="FormulaParsing\Logging\IFormulaParserLogger.cs" />
- <Compile Include="FormulaParsing\INameValueProvider.cs" />
- <Compile Include="FormulaParsing\IParsingLifetimeEventHandler.cs" />
- <Compile Include="FormulaParsing\Excel\Functions\FunctionNameProvider.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\ILexer.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\ISourceCodeTokenizer.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\ISyntacticAnalyzer.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\ITokenFactory.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\ITokenSeparatorProvider.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\Lexer.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\SourceCodeTokenizer.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\SyntacticAnalyzer.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\Token.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\TokenFactory.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\TokenizerContext.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\TokenSeparatorProvider.cs" />
- <Compile Include="FormulaParsing\LexicalAnalysis\TokenType.cs" />
- <Compile Include="FormulaParsing\EpplusNameValueProvider.cs" />
- <Compile Include="FormulaParsing\Logging\LoggerFactory.cs" />
- <Compile Include="FormulaParsing\Logging\TextFileLogger.cs" />
- <Compile Include="FormulaParsing\NameValueProvider.cs" />
- <Compile Include="FormulaParsing\ParsedValue.cs" />
- <Compile Include="FormulaParsing\ParsingConfiguration.cs" />
- <Compile Include="FormulaParsing\ParsingContext.cs" />
- <Compile Include="FormulaParsing\ParsingScope.cs" />
- <Compile Include="FormulaParsing\ParsingScopes.cs" />
- <Compile Include="FormulaParsing\Utilities\ArgumentInfo.cs" />
- <Compile Include="FormulaParsing\Utilities\ExtensionMethods.cs" />
- <Compile Include="FormulaParsing\Utilities\IdProvider.cs" />
- <Compile Include="FormulaParsing\Utilities\IntegerIdProvider.cs" />
- <Compile Include="FormulaParsing\Utilities\RegexConstants.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="FormulaParsing\Utilities\Require.cs" />
- <Compile Include="Packaging\DotNetZip\ComHelper.cs" />
- <Compile Include="Packaging\DotNetZip\CRC32.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\EncryptionAlgorithm.cs" />
- <Compile Include="Packaging\DotNetZip\Events.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Exceptions.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ExtractExistingFileAction.cs" />
- <Compile Include="Packaging\DotNetZip\FileSelector.cs" />
- <Compile Include="Packaging\DotNetZip\OffsetStream.cs" />
- <Compile Include="Packaging\DotNetZip\Shared.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\WinZipAes.cs" />
- <Compile Include="Packaging\DotNetZip\ZipConstants.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipCrypto.cs" />
- <Compile Include="Packaging\DotNetZip\ZipDirEntry.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipEntry.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipEntry.Extract.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipEntry.Read.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipEntry.Write.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipEntrySource.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipErrorAction.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipFile.AddUpdate.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.Check.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.Events.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.Extract.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.Read.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.Save.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.SaveSelfExtractor.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.Selector.cs" />
- <Compile Include="Packaging\DotNetZip\ZipFile.x-IEnumerable.cs" />
- <Compile Include="Packaging\DotNetZip\ZipInputStream.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipOutputStream.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\ZipSegmentedStream.cs" />
- <Compile Include="Packaging\DotNetZip\Zlib\Deflate.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\DeflateStream.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\GZipStream.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\Inflate.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\InfTree.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\ParallelDeflateOutputStream.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\Tree.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\Zlib.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\ZlibBaseStream.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\ZlibCodec.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\ZlibConstants.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Packaging\DotNetZip\Zlib\ZlibStream.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="RangeCollection.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Utils\ConvertUtil.cs" />
- <Compile Include="Utils\UriHelper.cs" />
- <Compile Include="Packaging\ZipPackage.cs" />
- <Compile Include="VBA\ExcelVbaModule.cs" />
- <Compile Include="VBA\ExcelVbaModuleAttribute.cs" />
- <Compile Include="VBA\ExcelVbaModuleCollection.cs" />
- <Compile Include="VBA\ExcelVbaProject.cs" />
- <Compile Include="ExcelWorkbookView.cs" />
- <Compile Include="ExcelWorksheetView.cs" />
- <Compile Include="Style\Dxf\DxfStyleBase.cs" />
- <Compile Include="Style\Dxf\ExcelDxfBorder.cs" />
- <Compile Include="Style\Dxf\ExcelDxfBorderItem.cs" />
- <Compile Include="Style\Dxf\ExcelDxfColor.cs" />
- <Compile Include="Style\Dxf\ExcelDxfFill.cs" />
- <Compile Include="Style\Dxf\ExcelDxfFontBase.cs" />
- <Compile Include="Style\Dxf\ExcelDxfNumberFormat.cs" />
- <Compile Include="Style\Dxf\ExcelDxfStyle.cs" />
- <Compile Include="Style\ExcelGradientFill.cs" />
- <Compile Include="Style\XmlAccess\ExcelGradientFillXml.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTableFieldGroup.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTableFieldItem.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTablePageFieldSettings.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTableDataField.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTableFieldCollection.cs" />
- <Compile Include="Style\IStyle.cs" />
- <Compile Include="OfficeProperties.cs" />
- <Compile Include="ExcelWorkbook.cs" />
- <Compile Include="ExcelWorksheet.cs" />
- <Compile Include="ExcelWorksheets.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- <Compile Include="Style\XmlAccess\ExcelBorderXml.cs" />
- <Compile Include="Style\XmlAccess\ExcelBorderItemXml.cs" />
- <Compile Include="Style\XmlAccess\ExcelXfsXml.cs" />
- <Compile Include="Style\XmlAccess\ExcelNamedStyleXml.cs" />
- <Compile Include="Style\XmlAccess\ExcelColorXml.cs" />
- <Compile Include="Style\XmlAccess\ExcelFillXml.cs" />
- <Compile Include="Style\XmlAccess\ExcelFontXml.cs" />
- <Compile Include="Style\XmlAccess\ExcelNumberFormatXml.cs" />
- <Compile Include="Style\StyleChangeEventArgs.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotCacheDefinition.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTableField.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTableCollection.cs" />
- <Compile Include="Table\PivotTable\ExcelPivotTable.cs" />
- <Compile Include="Table\ExcelTableColumnCollection.cs" />
- <Compile Include="Table\ExcelTable.cs" />
- <Compile Include="Table\ExcelTableCollection.cs" />
- <Compile Include="Table\ExcelTableColumn.cs" />
- <Compile Include="Utils\AddressUtility.cs" />
- <Compile Include="Utils\Argument.cs" />
- <Compile Include="Utils\ArgumentExtensions.cs" />
- <Compile Include="Utils\CompoundDocument.cs" />
- <Compile Include="Utils\IArgument.cs" />
- <Compile Include="Utils\Require.cs" />
- <Compile Include="Utils\SqRefUtility.cs" />
- <Compile Include="VBA\ExcelVbaProtection.cs" />
- <Compile Include="VBA\ExcelVbaReference.cs" />
- <Compile Include="VBA\ExcelVbaSignature.cs" />
- <Compile Include="XmlHelper.cs" />
- <Compile Include="XmlHelperFactory.cs" />
- <Compile Include="Packaging\ZipPackagePart.cs" />
- <Compile Include="Packaging\ZipPackageRelationship.cs" />
- <Compile Include="Packaging\ZipPackageRelationshipCollection.cs" />
- <Compile Include="Packaging\ZipPackageRelationshipBase.cs" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Drawing\Chart\ExcelLineChart.cs" />
- <Compile Include="Drawing\Vml\ExcelVmlDrawingComment.cs" />
- <Compile Include="Drawing\Vml\ExcelVmlDrawingPosition.cs" />
- <Compile Include="Drawing\Vml\ExcelVmlDrawingBaseCollection.cs" />
- <Compile Include="ExcelAddress.cs" />
- <Compile Include="ExcelCellAddress.cs" />
- <Compile Include="ExcelComment.cs" />
- <Compile Include="ExcelCommentCollection.cs" />
- <Compile Include="ExcelSheetProtection.cs" />
- <Compile Include="Drawing\Chart\ExcelChartLegend.cs" />
- <Compile Include="Drawing\Chart\ExcelChartPlotArea.cs" />
- <Compile Include="Drawing\Chart\ExcelChartSerieDataLabel.cs" />
- <Compile Include="Drawing\Chart\ExcelScatterChartSerie.cs" />
- <Compile Include="Drawing\Chart\ExcelChartTitle.cs" />
- <Compile Include="Drawing\ExcelDrawingBorder.cs" />
- <Compile Include="Drawing\Chart\ExcelOfPieChart.cs" />
- <Compile Include="Drawing\ExcelDrawingFill.cs" />
- <Compile Include="Drawing\Chart\ExcelPieChartSerie.cs" />
- <Compile Include="Drawing\ExcelView3D.cs" />
- <Compile Include="Drawing\Chart\ExcelBarChart.cs" />
- <Compile Include="Drawing\Chart\ExcelChartAxis.cs" />
- <Compile Include="Drawing\Chart\ExcelChartDataLabel.cs" />
- <Compile Include="Drawing\Chart\ExcelChartSerie.cs" />
- <Compile Include="Drawing\Chart\ExcelChartSeries.cs" />
- <Compile Include="Drawing\Chart\ExcelDoughnutChart.cs" />
- <Compile Include="Drawing\Chart\ExcelPieChart.cs" />
- <Compile Include="Drawing\Chart\ExcelScatterChart.cs" />
- <Compile Include="ExcelCellBase.cs" />
- <Compile Include="ExcelHyperLink.cs" />
- <Compile Include="ExcelNamedRange.cs" />
- <Compile Include="ExcelNamedRangeCollection.cs" />
- <Compile Include="ExcelPrinterSettings.cs" />
- <Compile Include="ExcelRangeBase.cs" />
- <Compile Include="IRangeID.cs" />
- <Compile Include="Style\ExcelParagraph.cs" />
- <Compile Include="Style\ExcelParagraphCollection.cs" />
- <Compile Include="Style\ExcelBorder.cs" />
- <Compile Include="Style\ExcelBorderItem.cs" />
- <Compile Include="Style\ExcelColor.cs" />
- <Compile Include="Style\ExcelFill.cs" />
- <Compile Include="Style\ExcelRichText.cs" />
- <Compile Include="Style\ExcelRichTextCollection.cs" />
- <Compile Include="Utils\IExcelCell.cs" />
- <Compile Include="Style\ExcelStyle.cs" />
- <Compile Include="Style\ExcelFont.cs" />
- <Compile Include="Style\XmlAccess\StyleXmlHelper.cs" />
- <Compile Include="Style\ExcelNumberFormat.cs" />
- <Compile Include="Style\StyleBase.cs" />
- <Compile Include="Style\ExcelTextFont.cs" />
- </ItemGroup>
- <ItemGroup>
- <None Include="OpenOfficeXml.snk" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <ItemGroup>
- <Compile Include="ConditionalFormatting\CF Implementation.cs" />
- </ItemGroup>
- <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
- <PropertyGroup>
- <PostBuildEvent>
- </PostBuildEvent>
- <PreBuildEvent>
- </PreBuildEvent>
- </PropertyGroup>
-</Project>
\ No newline at end of file
diff --git a/EPPlus/EPPlusSDK.csproj b/EPPlus/EPPlusSDK.csproj
deleted file mode 100644
index 2a2e866..0000000
--- a/EPPlus/EPPlusSDK.csproj
+++ /dev/null
@@ -1,9 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
- <PropertyGroup>
- <TargetFramework>net8.0</TargetFramework>
- <RootNamespace>OfficeOpenXml</RootNamespace>
- <AssemblyName>EPPlus</AssemblyName>
- <PackageId>Appsheet.EPPlus</PackageId>
- <Version>1.0.6</Version>
- </PropertyGroup>
-</Project>
diff --git a/EPPlus/ExcelAddress.cs b/EPPlus/ExcelAddress.cs
deleted file mode 100644
index 51ad999..0000000
--- a/EPPlus/ExcelAddress.cs
+++ /dev/null
@@ -1,1216 +0,0 @@
-/*******************************************************************************
- * 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 18-MAR-2010
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-
-namespace OfficeOpenXml;
-
-public class ExcelTableAddress {
- public string Name { get; set; }
-
- public string ColumnSpan { get; set; }
-
- public bool IsAll { get; set; }
-
- public bool IsHeader { get; set; }
-
- public bool IsData { get; set; }
-
- public bool IsTotals { get; set; }
-
- public bool IsThisRow { get; set; }
-}
-
-/// <summary>
-/// A range address
-/// </summary>
-/// <remarks>Examples of addresses are "A1" "B1:C2" "A:A" "1:1" "A1:E2,G3:G5" </remarks>
-public class ExcelAddressBase : ExcelCellBase {
- protected internal int _fromRow = -1,
- _toRow,
- _fromCol,
- _toCol;
- protected internal bool _fromRowFixed,
- _fromColFixed,
- _toRowFixed,
- _toColFixed;
- protected internal string _wb;
- protected internal string _ws;
- protected internal string _address;
-
- protected internal event EventHandler AddressChange;
-
- internal enum eAddressCollition {
- No,
- Partly,
- Inside,
- Equal,
- }
-
- internal enum eShiftType {
- Right,
- Down,
- EntireRow,
- EntireColumn,
- }
-
- internal ExcelAddressBase() {}
-
- /// <summary>
- /// Creates an Address object
- /// </summary>
- /// <param name="fromRow">start row</param>
- /// <param name="fromCol">start column</param>
- /// <param name="toRow">End row</param>
- /// <param name="toColumn">End column</param>
- public ExcelAddressBase(int fromRow, int fromCol, int toRow, int toColumn) {
- _fromRow = fromRow;
- _toRow = toRow;
- _fromCol = fromCol;
- _toCol = toColumn;
- Validate();
-
- _address = GetAddress(_fromRow, _fromCol, _toRow, _toCol);
- }
-
- /// <summary>
- /// Creates an Address object
- /// </summary>
- /// <param name="fromRow">start row</param>
- /// <param name="fromCol">start column</param>
- /// <param name="toRow">End row</param>
- /// <param name="toColumn">End column</param>
- /// <param name="fromRowFixed">start row fixed</param>
- /// <param name="fromColFixed">start column fixed</param>
- /// <param name="toRowFixed">End row fixed</param>
- /// <param name="toColFixed">End column fixed</param>
- public ExcelAddressBase(
- int fromRow,
- int fromCol,
- int toRow,
- int toColumn,
- bool fromRowFixed,
- bool fromColFixed,
- bool toRowFixed,
- bool toColFixed) {
- _fromRow = fromRow;
- _toRow = toRow;
- _fromCol = fromCol;
- _toCol = toColumn;
- _fromRowFixed = fromRowFixed;
- _fromColFixed = fromColFixed;
- _toRowFixed = toRowFixed;
- _toColFixed = toColFixed;
- Validate();
-
- _address = GetAddress(
- _fromRow,
- _fromCol,
- _toRow,
- _toCol,
- _fromRowFixed,
- fromColFixed,
- _toRowFixed,
- _toColFixed);
- }
-
- /// <summary>
- /// Creates an Address object
- /// </summary>
- /// <remarks>Examples of addresses are "A1" "B1:C2" "A:A" "1:1" "A1:E2,G3:G5" </remarks>
- /// <param name="address">The Excel Address</param>
- public ExcelAddressBase(string address) {
- SetAddress(address);
- }
-
- /// <summary>
- /// Creates an Address object
- /// </summary>
- /// <remarks>Examples of addresses are "A1" "B1:C2" "A:A" "1:1" "A1:E2,G3:G5" </remarks>
- /// <param name="address">The Excel Address</param>
- /// <param name="pck">Reference to the package to find information about tables and names</param>
- /// <param name="referenceAddress">The address</param>
- protected ExcelAddressBase(
- string address,
- ExcelWorkbook workbook,
- ExcelAddressBase referenceAddress) {
- SetAddress(address);
- SetRcFromTable(workbook, referenceAddress);
- }
-
- internal void SetRcFromTable(ExcelWorkbook workbook, ExcelAddressBase referenceAddress) {
- if (string.IsNullOrEmpty(_wb) && Table != null) {
- foreach (var ws in workbook.Worksheets) {
- foreach (var t in ws.Tables) {
- if (t.Name.Equals(Table.Name, StringComparison.InvariantCultureIgnoreCase)) {
- _ws = ws.Name;
- if (Table.IsAll) {
- _fromRow = t.Address._fromRow;
- _toRow = t.Address._toRow;
- } else {
- if (Table.IsThisRow) {
- if (referenceAddress == null) {
- _fromRow = -1;
- _toRow = -1;
- } else {
- _fromRow = referenceAddress._fromRow;
- _toRow = _fromRow;
- }
- } else if (Table.IsHeader && Table.IsData) {
- _fromRow = t.Address._fromRow;
- _toRow = t.ShowTotal ? t.Address._toRow - 1 : t.Address._toRow;
- } else if (Table.IsData && Table.IsTotals) {
- _fromRow = t.ShowHeader ? t.Address._fromRow + 1 : t.Address._fromRow;
- _toRow = t.Address._toRow;
- } else if (Table.IsHeader) {
- _fromRow = t.ShowHeader ? t.Address._fromRow : -1;
- _toRow = t.ShowHeader ? t.Address._fromRow : -1;
- } else if (Table.IsTotals) {
- _fromRow = t.ShowTotal ? t.Address._toRow : -1;
- _toRow = t.ShowTotal ? t.Address._toRow : -1;
- } else {
- _fromRow = t.ShowHeader ? t.Address._fromRow + 1 : t.Address._fromRow;
- _toRow = t.ShowTotal ? t.Address._toRow - 1 : t.Address._toRow;
- }
- }
-
- if (string.IsNullOrEmpty(Table.ColumnSpan)) {
- _fromCol = t.Address._fromCol;
- _toCol = t.Address._toCol;
- return;
- }
- var col = t.Address._fromCol;
- var cols = Table.ColumnSpan.Split(':');
- foreach (var c in t.Columns) {
- if (_fromCol <= 0
- && cols[0]
- .Equals(
- c.Name,
- StringComparison.InvariantCultureIgnoreCase)) //Issue15063 Add invariant igore case
- {
- _fromCol = col;
- if (cols.Length == 1) {
- _toCol = _fromCol;
- return;
- }
- } else if (cols.Length > 1
- && _fromCol > 0
- && cols[1]
- .Equals(
- c.Name,
- StringComparison.InvariantCultureIgnoreCase)) //Issue15063 Add invariant igore case
- {
- _toCol = col;
- return;
- }
-
- col++;
- }
- }
- }
- }
- }
- }
-
- /// <summary>
- /// Address is an defined name
- /// </summary>
- /// <param name="address">the name</param>
- /// <param name="isName">Should always be true</param>
- internal ExcelAddressBase(string address, bool isName) {
- if (isName) {
- _address = address;
- _fromRow = -1;
- _fromCol = -1;
- _toRow = -1;
- _toCol = -1;
- _start = null;
- _end = null;
- } else {
- SetAddress(address);
- }
- }
-
- protected internal void SetAddress(string address) {
- address = address.Trim();
- if (address.StartsWith("'")) {
- SetWbWs(address);
- } else if (address.StartsWith(
- "[")) //Remove any external reference
- {
- SetWbWs(address);
- } else {
- _address = address;
- }
- if (_address.IndexOfAny(new[] { ',', '!', '[' }) > -1) {
- //Advanced address. Including Sheet or multi or table.
- ExtractAddress(_address);
- } else {
- //Simple address
- GetRowColFromAddress(
- _address,
- out _fromRow,
- out _fromCol,
- out _toRow,
- out _toCol,
- out _fromRowFixed,
- out _fromColFixed,
- out _toRowFixed,
- out _toColFixed);
- _addresses = null;
- _start = null;
- _end = null;
- }
- _address = address;
- Validate();
- }
-
- internal void ChangeAddress() {
- if (AddressChange != null) {
- AddressChange(this, new());
- }
- }
-
- private void SetWbWs(string address) {
- int pos = 0;
-
- // Get Workbook, if any
- if (address[pos] == '[') {
- pos = address.IndexOf("]");
- _wb = address.Substring(1, pos - 1);
- pos++;
- } else {
- _wb = "";
- }
-
- // Get Worksheet
- if (address[pos] == '\'') {
- int startPos = pos;
- pos = address.IndexOf("'", pos + 1);
- while (pos < address.Length && address[pos + 1] == '\'') {
- pos = address.IndexOf("'", pos + 2);
- }
- _ws = address.Substring(startPos + 1, pos - startPos - 1).Replace("''", "'");
- pos++;
- } else {
- int startPos = pos;
- pos = address.IndexOf("!", pos);
- if (pos > -1) {
- _ws = address.Substring(startPos, pos - startPos);
- }
- }
-
- // Get Address
- pos = address.IndexOf("!", pos);
- if (pos > -1) {
- _address = address.Substring(pos + 1);
- } else {
- _address = "";
- }
- }
-
- internal void ChangeWorksheet(string wsName, string newWs) {
- if (_ws == wsName) {
- _ws = newWs;
- }
- var fullAddress = GetAddress();
-
- if (Addresses != null) {
- foreach (var a in Addresses) {
- if (a._ws == wsName) {
- a._ws = newWs;
- fullAddress += "," + a.GetAddress();
- } else {
- fullAddress += "," + a._address;
- }
- }
- }
- _address = fullAddress;
- }
-
- private string GetAddress() {
- var adr = "";
- if (string.IsNullOrEmpty(_wb)) {
- adr = "[" + _wb + "]";
- }
-
- if (string.IsNullOrEmpty(_ws)) {
- adr += string.Format("'{0}'!", _ws);
- }
- adr += GetAddress(_fromRow, _fromCol, _toRow, _toCol);
- return adr;
- }
-
- private ExcelCellAddress _start;
-
- /// <summary>
- /// Gets the row and column of the top left cell.
- /// </summary>
- /// <value>The start row column.</value>
- public ExcelCellAddress Start {
- get {
- if (_start == null) {
- _start = new(_fromRow, _fromCol);
- }
- return _start;
- }
- }
-
- private ExcelCellAddress _end;
-
- /// <summary>
- /// Gets the row and column of the bottom right cell.
- /// </summary>
- /// <value>The end row column.</value>
- public ExcelCellAddress End {
- get {
- if (_end == null) {
- _end = new(_toRow, _toCol);
- }
- return _end;
- }
- }
-
- private ExcelTableAddress _table;
-
- public ExcelTableAddress Table => _table;
-
- /// <summary>
- /// The address for the range
- /// </summary>
- public virtual string Address => _address;
-
- /// <summary>
- /// If the address is a defined name
- /// </summary>
- public bool IsName => _fromRow < 0;
-
- /// <summary>
- /// Returns the address text
- /// </summary>
- /// <returns></returns>
- public override string ToString() {
- return _address;
- }
-
- private string _firstAddress;
-
- /// <summary>
- /// returns the first address if the address is a multi address.
- /// A1:A2,B1:B2 returns A1:A2
- /// </summary>
- internal string FirstAddress {
- get {
- if (string.IsNullOrEmpty(_firstAddress)) {
- return _address;
- }
- return _firstAddress;
- }
- }
-
- internal string AddressSpaceSeparated => _address.Replace(',', ' '); //Conditional formatting and a few other places use space as separator for mulit addresses.
-
- /// <summary>
- /// Validate the address
- /// </summary>
- protected void Validate() {
- if (_fromRow > _toRow || _fromCol > _toCol) {
- throw new ArgumentOutOfRangeException(
- "Start cell Address must be less or equal to End cell address");
- }
- }
-
- internal string WorkSheet => _ws;
-
- protected internal List<ExcelAddress> _addresses;
-
- internal virtual List<ExcelAddress> Addresses => _addresses;
-
- private bool ExtractAddress(string fullAddress) {
- var brackPos = new Stack<int>();
- var bracketParts = new List<string>();
- string first = "",
- second = "";
- bool isText = false,
- hasSheet = false;
- try {
- if (fullAddress == "#REF!") {
- SetAddress(ref fullAddress, ref second, ref hasSheet);
- return true;
- }
- if (fullAddress.StartsWith("!")) {
- // invalid address!
- return false;
- }
- for (int i = 0; i < fullAddress.Length; i++) {
- var c = fullAddress[i];
- if (c == '\'') {
- if (isText && i + 1 < fullAddress.Length && fullAddress[i] == '\'') {
- if (hasSheet) {
- second += c;
- } else {
- first += c;
- }
- }
- isText = !isText;
- } else {
- if (brackPos.Count > 0) {
- if (c == '[' && !isText) {
- brackPos.Push(i);
- } else if (c == ']' && !isText) {
- if (brackPos.Count > 0) {
- var from = brackPos.Pop();
- bracketParts.Add(fullAddress.Substring(from + 1, i - from - 1));
-
- if (brackPos.Count == 0) {
- HandleBrackets(first, second, bracketParts);
- }
- } else {
- //Invalid address!
- return false;
- }
- }
- } else if (c == '[' && !isText) {
- brackPos.Push(i);
- } else if (c == '!' && !isText && !first.EndsWith("#REF") && !second.EndsWith("#REF")) {
- hasSheet = true;
- } else if (c == ',' && !isText) {
- SetAddress(ref first, ref second, ref hasSheet);
- } else {
- if (hasSheet) {
- second += c;
- } else {
- first += c;
- }
- }
- }
- }
- if (Table == null) {
- SetAddress(ref first, ref second, ref hasSheet);
- }
- return true;
- } catch {
- return false;
- }
- }
-
- private void HandleBrackets(string first, string second, List<string> bracketParts) {
- if (!string.IsNullOrEmpty(first)) {
- _table = new();
- Table.Name = first;
- foreach (var s in bracketParts) {
- if (s.IndexOf("[") < 0) {
- switch (s.ToLower(CultureInfo.InvariantCulture)) {
- case "#all":
- _table.IsAll = true;
- break;
- case "#headers":
- _table.IsHeader = true;
- break;
- case "#data":
- _table.IsData = true;
- break;
- case "#totals":
- _table.IsTotals = true;
- break;
- case "#this row":
- _table.IsThisRow = true;
- break;
- default:
- if (string.IsNullOrEmpty(_table.ColumnSpan)) {
- _table.ColumnSpan = s;
- } else {
- _table.ColumnSpan += ":" + s;
- }
- break;
- }
- }
- }
- }
- }
-
- internal eAddressCollition Collide(ExcelAddressBase address) {
- if (address.WorkSheet != WorkSheet && address.WorkSheet != null) {
- return eAddressCollition.No;
- }
-
- if (address._fromRow > _toRow
- || address._fromCol > _toCol
- || _fromRow > address._toRow
- || _fromCol > address._toCol) {
- return eAddressCollition.No;
- }
- if (address._fromRow == _fromRow
- && address._fromCol == _fromCol
- && address._toRow == _toRow
- && address._toCol == _toCol) {
- return eAddressCollition.Equal;
- }
- if (address._fromRow >= _fromRow
- && address._toRow <= _toRow
- && address._fromCol >= _fromCol
- && address._toCol <= _toCol) {
- return eAddressCollition.Inside;
- }
- return eAddressCollition.Partly;
- }
-
- internal ExcelAddressBase AddRow(int row, int rows, bool setFixed = false) {
- if (row > _toRow) {
- return this;
- }
- if (row <= _fromRow) {
- return new(
- (setFixed && _fromRowFixed ? _fromRow : _fromRow + rows),
- _fromCol,
- (setFixed && _toRowFixed ? _toRow : _toRow + rows),
- _toCol,
- _fromRowFixed,
- _fromColFixed,
- _toRowFixed,
- _toColFixed);
- }
- return new(
- _fromRow,
- _fromCol,
- (setFixed && _toRowFixed ? _toRow : _toRow + rows),
- _toCol,
- _fromRowFixed,
- _fromColFixed,
- _toRowFixed,
- _toColFixed);
- }
-
- internal ExcelAddressBase DeleteRow(int row, int rows, bool setFixed = false) {
- if (row
- > _toRow) //After
- {
- return this;
- }
- if (row + rows
- <= _fromRow) //Before
- {
- return new(
- (setFixed && _fromRowFixed ? _fromRow : _fromRow - rows),
- _fromCol,
- (setFixed && _toRowFixed ? _toRow : _toRow - rows),
- _toCol,
- _fromRowFixed,
- _fromColFixed,
- _toRowFixed,
- _toColFixed);
- }
- if (row <= _fromRow
- && row + rows
- > _toRow) //Inside
- {
- return null;
- } //Partly
- if (row <= _fromRow) {
- return new(
- row,
- _fromCol,
- (setFixed && _toRowFixed ? _toRow : _toRow - rows),
- _toCol,
- _fromRowFixed,
- _fromColFixed,
- _toRowFixed,
- _toColFixed);
- }
- return new(
- _fromRow,
- _fromCol,
- (setFixed && _toRowFixed
- ? _toRow
- : _toRow - rows < row
- ? row - 1
- : _toRow - rows),
- _toCol,
- _fromRowFixed,
- _fromColFixed,
- _toRowFixed,
- _toColFixed);
- }
-
- internal ExcelAddressBase AddColumn(int col, int cols, bool setFixed = false) {
- if (col > _toCol) {
- return this;
- }
- if (col <= _fromCol) {
- return new(
- _fromRow,
- (setFixed && _fromColFixed ? _fromCol : _fromCol + cols),
- _toRow,
- (setFixed && _toColFixed ? _toCol : _toCol + cols),
- _fromRowFixed,
- _fromColFixed,
- _toRowFixed,
- _toColFixed);
- }
- return new(
- _fromRow,
- _fromCol,
- _toRow,
- (setFixed && _toColFixed ? _toCol : _toCol + cols),
- _fromRowFixed,
- _fromColFixed,
- _toRowFixed,
- _toColFixed);
- }
-
- internal ExcelAddressBase DeleteColumn(int col, int cols, bool setFixed = false) {
- if (col
- > _toCol) //After
- {
- return this;
- }
- if (col + cols
- <= _fromCol) //Before
- {
- return new(
- _fromRow,
- (setFixed && _fromColFixed ? _fromCol : _fromCol - cols),
- _toRow,
- (setFixed && _toColFixed ? _toCol : _toCol - cols),
- _fromRowFixed,
- _fromColFixed,
- _toRowFixed,
- _toColFixed);
- }
- if (col <= _fromCol
- && col + cols
- > _toCol) //Inside
- {
- return null;
- } //Partly
- if (col <= _fromCol) {
- return new(
- _fromRow,
- col,
- _toRow,
- (setFixed && _toColFixed ? _toCol : _toCol - cols),
- _fromRowFixed,
- _fromColFixed,
- _toRowFixed,
- _toColFixed);
- }
- return new(
- _fromRow,
- _fromCol,
- _toRow,
- (setFixed && _toColFixed
- ? _toCol
- : _toCol - cols < col
- ? col - 1
- : _toCol - cols),
- _fromRowFixed,
- _fromColFixed,
- _toRowFixed,
- _toColFixed);
- }
-
- internal ExcelAddressBase Insert(
- ExcelAddressBase address,
- eShiftType shift /*, out ExcelAddressBase topAddress, out ExcelAddressBase leftAddress, out ExcelAddressBase rightAddress, out ExcelAddressBase bottomAddress*/) {
- //Before or after, no change
- //if ((_toRow > address._fromRow && _toCol > address.column) ||
- // (_fromRow > address._toRow && column > address._toCol))
- if (_toRow < address._fromRow
- || _toCol < address._fromCol
- || (_fromRow > address._toRow && _fromCol > address._toCol)) {
- //topAddress = null;
- //leftAddress = null;
- //rightAddress = null;
- //bottomAddress = null;
- return this;
- }
-
- int rows = address.Rows;
- int cols = address.Columns;
- string retAddress = "";
- if (shift == eShiftType.Right) {
- if (address._fromRow > _fromRow) {
- retAddress = GetAddress(
- _fromRow,
- _fromCol,
- address._fromRow,
- _toCol,
- _fromRowFixed,
- _fromColFixed,
- _toRowFixed,
- _toColFixed);
- }
- if (address._fromCol > _fromCol) {
- retAddress = GetAddress(
- _fromRow < address._fromRow ? _fromRow : address._fromRow,
- _fromCol,
- address._fromRow,
- _toCol,
- _fromRowFixed,
- _fromColFixed,
- _toRowFixed,
- _toColFixed);
- }
- }
- if (_toRow < address._fromRow) {
- if (_fromRow < address._fromRow) {}
- }
- return null;
- }
-
- private void SetAddress(ref string first, ref string second, ref bool hasSheet) {
- string ws,
- address;
- if (hasSheet) {
- ws = first;
- address = second;
- first = "";
- second = "";
- } else {
- address = first;
- ws = "";
- first = "";
- }
- hasSheet = false;
- if (string.IsNullOrEmpty(_firstAddress)) {
- if (string.IsNullOrEmpty(_ws) || !string.IsNullOrEmpty(ws)) {
- _ws = ws;
- }
- _firstAddress = address;
- GetRowColFromAddress(
- address,
- out _fromRow,
- out _fromCol,
- out _toRow,
- out _toCol,
- out _fromRowFixed,
- out _fromColFixed,
- out _toRowFixed,
- out _toColFixed);
- } else {
- if (_addresses == null) {
- _addresses = new();
- }
- _addresses.Add(new(_ws, address));
- }
- }
-
- internal enum AddressType {
- Invalid,
- InternalAddress,
- ExternalAddress,
- InternalName,
- ExternalName,
- Formula,
- }
-
- internal static AddressType IsValid(string address) {
- if (address == "#REF!") {
- return AddressType.Invalid;
- }
- if (double.TryParse(
- address,
- NumberStyles.Any,
- CultureInfo.InvariantCulture,
- out _)) //A double, no valid address
- {
- return AddressType.Invalid;
- }
- if (IsFormula(address)) {
- return AddressType.Formula;
- }
- if (SplitAddress(address, out var wb, out _, out var intAddress)) {
- if (intAddress.Contains(
- "[")) //Table reference
- {
- return string.IsNullOrEmpty(wb) ? AddressType.InternalAddress : AddressType.ExternalAddress;
- }
- if (intAddress.Contains(",")) {
- intAddress = intAddress.Substring(0, intAddress.IndexOf(','));
- }
- if (IsAddress(intAddress)) {
- return string.IsNullOrEmpty(wb) ? AddressType.InternalAddress : AddressType.ExternalAddress;
- }
- return string.IsNullOrEmpty(wb) ? AddressType.InternalName : AddressType.ExternalName;
- }
- return AddressType.Invalid;
- }
-
- private static bool IsAddress(string intAddress) {
- if (string.IsNullOrEmpty(intAddress)) {
- return false;
- }
- var cells = intAddress.Split(':');
- int toRow,
- toCol;
-
- if (!GetRowCol(cells[0], out var fromRow, out var fromCol, false)) {
- return false;
- }
- if (cells.Length > 1) {
- if (!GetRowCol(cells[1], out toRow, out toCol, false)) {
- return false;
- }
- } else {
- toRow = fromRow;
- toCol = fromCol;
- }
- if (fromRow <= toRow
- && fromCol <= toCol
- && fromCol > -1
- && toCol <= ExcelPackage.MaxColumns
- && fromRow > -1
- && toRow <= ExcelPackage.MaxRows) {
- return true;
- }
- return false;
- }
-
- private static bool SplitAddress(
- string address,
- out string wb,
- out string ws,
- out string intAddress) {
- wb = "";
- ws = "";
- intAddress = "";
- var text = "";
- bool isText = false;
- var brackPos = -1;
- for (int i = 0; i < address.Length; i++) {
- if (address[i] == '\'') {
- isText = !isText;
- if (i > 0 && address[i - 1] == '\'') {
- text += "'";
- }
- } else {
- if (address[i] == '!' && !isText) {
- if (text.Length > 0 && text[0] == '[') {
- wb = text.Substring(1, text.IndexOf("]") - 1);
- ws = text.Substring(text.IndexOf("]") + 1);
- } else {
- ws = text;
- }
- intAddress = address.Substring(i + 1);
- return true;
- }
- if (address[i] == '[' && !isText) {
- if (i
- > 0) //Table reference return full address;
- {
- intAddress = address;
- return true;
- }
- brackPos = i;
- } else if (address[i] == ']' && !isText) {
- if (brackPos > -1) {
- wb = text;
- text = "";
- } else {
- return false;
- }
- } else {
- text += address[i];
- }
- }
- }
- intAddress = text;
- return true;
- }
-
- private static bool IsFormula(string address) {
- var isText = false;
- for (int i = 0; i < address.Length; i++) {
- if (address[i] == '\'') {
- isText = !isText;
- } else {
- if (isText == false
- && address
- .Substring(i, 1)
- .IndexOfAny(new[] { '(', ')', '+', '-', '*', '/', '.', '=', '^', '&', '%', '\"' })
- > -1) {
- return true;
- }
- }
- }
- return false;
- }
-
- public int Rows => _toRow - _fromRow + 1;
-
- public int Columns => _toCol - _fromCol + 1;
-
- internal static String GetWorkbookPart(string address) {
- int ix;
- if (address[0] == '[') {
- ix = address.IndexOf(']') + 1;
- if (ix > 0) {
- return address.Substring(1, ix - 2);
- }
- }
- return "";
- }
-
- internal static string GetWorksheetPart(string address, string defaultWorkSheet, ref int endIx) {
- if (address == "") {
- return defaultWorkSheet;
- }
- var ix = 0;
- if (address[0] == '[') {
- ix = address.IndexOf(']') + 1;
- }
- if (ix > 0 && ix < address.Length) {
- if (address[ix] == '\'') {
- return GetString(address, ix, out endIx);
- }
- var ixEnd = address.IndexOf('!', ix);
- if (ixEnd > ix) {
- return address.Substring(ix, ixEnd - ix);
- }
- return defaultWorkSheet;
- }
- return defaultWorkSheet;
- }
-
- internal static void SplitAddress(
- string fullAddress,
- out string wb,
- out string ws,
- out string address,
- string defaultWorksheet = "") {
- wb = GetWorkbookPart(fullAddress);
- int ix = 0;
- ws = GetWorksheetPart(fullAddress, defaultWorksheet, ref ix);
- if (ix < fullAddress.Length) {
- if (fullAddress[ix] == '!') {
- address = fullAddress.Substring(ix + 1);
- } else {
- address = fullAddress.Substring(ix);
- }
- } else {
- address = "";
- }
- }
-
- private static string GetString(string address, int ix, out int endIx) {
- var strIx = address.IndexOf("''");
- while (strIx > -1) {
- strIx = address.IndexOf("''");
- }
- endIx = address.IndexOf("'");
- return address.Substring(ix, endIx - ix).Replace("''", "'");
- }
-
- internal bool IsValidRowCol() {
- return !(_fromRow > _toRow
- || _fromCol > _toCol
- || _fromRow < 1
- || _fromCol < 1
- || _toRow > ExcelPackage.MaxRows
- || _toCol > ExcelPackage.MaxColumns);
- }
-}
-
-/// <summary>
-/// Range address with the address property readonly
-/// </summary>
-public class ExcelAddress : ExcelAddressBase {
- internal ExcelAddress() {}
-
- public ExcelAddress(int fromRow, int fromCol, int toRow, int toColumn)
- : base(fromRow, fromCol, toRow, toColumn) {
- _ws = "";
- }
-
- public ExcelAddress(string address)
- : base(address) {}
-
- internal ExcelAddress(string ws, string address)
- : base(address) {
- if (string.IsNullOrEmpty(_ws)) {
- _ws = ws;
- }
- }
-
- internal ExcelAddress(string ws, string address, bool isName)
- : base(address, isName) {
- if (string.IsNullOrEmpty(_ws)) {
- _ws = ws;
- }
- }
-
- public ExcelAddress(string address, ExcelWorkbook workbook, ExcelAddressBase referenceAddress)
- : base(address, workbook, referenceAddress) {}
-
- /// <summary>
- /// The address for the range
- /// </summary>
- /// <remarks>Examples of addresses are "A1" "B1:C2" "A:A" "1:1" "A1:E2,G3:G5" </remarks>
- public new string Address {
- get {
- if (string.IsNullOrEmpty(_address) && _fromRow > 0) {
- _address = GetAddress(_fromRow, _fromCol, _toRow, _toCol);
- }
- return _address;
- }
- set {
- SetAddress(value);
- ChangeAddress();
- }
- }
-}
-
-public class ExcelFormulaAddress : ExcelAddressBase {
- private bool _fromRowFixed,
- _toRowFixed,
- _fromColFixed,
- _toColFixed;
-
- public ExcelFormulaAddress(int fromRow, int fromCol, int toRow, int toColumn)
- : base(fromRow, fromCol, toRow, toColumn) {
- _ws = "";
- }
-
- public ExcelFormulaAddress(string address)
- : base(address) {
- SetFixed();
- }
-
- private void SetFixed() {
- if (Address.IndexOf("[") >= 0) {
- return;
- }
- var address = FirstAddress;
- if (_fromRow == _toRow && _fromCol == _toCol) {
- GetFixed(address, out _fromRowFixed, out _fromColFixed);
- } else {
- var cells = address.Split(':');
- GetFixed(cells[0], out _fromRowFixed, out _fromColFixed);
- GetFixed(cells[1], out _toRowFixed, out _toColFixed);
- }
- }
-
- private void GetFixed(string address, out bool rowFixed, out bool colFixed) {
- rowFixed = colFixed = false;
- var ix = address.IndexOf('$');
- while (ix > -1) {
- ix++;
- if (ix < address.Length) {
- if (address[ix] >= '0' && address[ix] <= '9') {
- rowFixed = true;
- break;
- }
- colFixed = true;
- }
- ix = address.IndexOf('$', ix);
- }
- }
-
- /// <summary>
- /// The address for the range
- /// </summary>
- /// <remarks>Examples of addresses are "A1" "B1:C2" "A:A" "1:1" "A1:E2,G3:G5" </remarks>
- public new string Address {
- get {
- if (string.IsNullOrEmpty(_address) && _fromRow > 0) {
- _address = GetAddress(
- _fromRow,
- _fromCol,
- _toRow,
- _toCol,
- _fromRowFixed,
- _toRowFixed,
- _fromColFixed,
- _toColFixed);
- }
- return _address;
- }
- set {
- SetAddress(value);
- ChangeAddress();
- SetFixed();
- }
- }
-
- internal new List<ExcelFormulaAddress> _addresses;
-
- public new List<ExcelFormulaAddress> Addresses {
- get {
- if (_addresses == null) {
- _addresses = new();
- }
- return _addresses;
- }
- }
-
- internal string GetOffset(int row, int column) {
- int fromRow = _fromRow,
- fromCol = _fromCol,
- toRow = _toRow,
- tocol = _toCol;
- var isMulti = (fromRow != toRow || fromCol != tocol);
- if (!_fromRowFixed) {
- fromRow += row;
- }
- if (!_fromColFixed) {
- fromCol += column;
- }
- if (isMulti) {
- if (!_toRowFixed) {
- toRow += row;
- }
- if (!_toColFixed) {
- tocol += column;
- }
- } else {
- toRow = fromRow;
- tocol = fromCol;
- }
- string a = GetAddress(
- fromRow,
- fromCol,
- toRow,
- tocol,
- _fromRowFixed,
- _fromColFixed,
- _toRowFixed,
- _toColFixed);
- if (Addresses != null) {
- foreach (var sa in Addresses) {
- a += "," + sa.GetOffset(row, column);
- }
- }
- return a;
- }
-}
diff --git a/EPPlus/ExcelCellAddress.cs b/EPPlus/ExcelCellAddress.cs
deleted file mode 100644
index b765a73..0000000
--- a/EPPlus/ExcelCellAddress.cs
+++ /dev/null
@@ -1,133 +0,0 @@
-/*******************************************************************************
- * 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
- *******************************************************************************
- * Starnuto Di Topo & Jan Källman Initial Release 2010-03-14
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// A single cell address
-/// </summary>
-public class ExcelCellAddress {
- public ExcelCellAddress()
- : this(1, 1) {}
-
- private int _row;
- private int _column;
- private string _address;
-
- /// <summary>
- /// Initializes a new instance of the ExcelCellAddress class.
- /// </summary>
- /// <param name="row">The row.</param>
- /// <param name="column">The column.</param>
- public ExcelCellAddress(int row, int column) {
- Row = row;
- Column = column;
- }
-
- /// <summary>
- /// Initializes a new instance of the ExcelCellAddress class.
- /// </summary>
- ///<param name="address">The address</param>
- public ExcelCellAddress(string address) {
- Address = address;
- }
-
- /// <summary>
- /// Row
- /// </summary>
- public int Row {
- get => _row;
- private set {
- if (value <= 0) {
- throw new ArgumentOutOfRangeException("value", "Row cannot be less than 1.");
- }
- _row = value;
- if (_column > 0) {
- _address = ExcelCellBase.GetAddress(_row, _column);
- } else {
- _address = "#REF!";
- }
- }
- }
-
- /// <summary>
- /// Column
- /// </summary>
- public int Column {
- get => _column;
- private set {
- if (value <= 0) {
- throw new ArgumentOutOfRangeException("value", "Column cannot be less than 1.");
- }
- _column = value;
- if (_row > 0) {
- _address = ExcelCellBase.GetAddress(_row, _column);
- } else {
- _address = "#REF!";
- }
- }
- }
-
- /// <summary>
- /// Celladdress
- /// </summary>
- public string Address {
- get => _address;
- internal set {
- _address = value;
- ExcelCellBase.GetRowColFromAddress(_address, out _row, out _column);
- }
- }
-
- /// <summary>
- /// If the address is an invalid reference (#REF!)
- /// </summary>
- public bool IsRef => _row <= 0;
-
- /// <summary>
- /// Returns the letter corresponding to the supplied 1-based column index.
- /// </summary>
- /// <param name="column">Index of the column (1-based)</param>
- /// <returns>The corresponding letter, like A for 1.</returns>
- public static string GetColumnLetter(int column) {
- if (column > ExcelPackage.MaxColumns || column < 1) {
- throw new InvalidOperationException(
- "Invalid 1-based column index: "
- + column
- + ". Valid range is 1 to "
- + ExcelPackage.MaxColumns);
- }
- return ExcelCellBase.GetColumnLetter(column);
- }
-}
diff --git a/EPPlus/ExcelCellBase.cs b/EPPlus/ExcelCellBase.cs
deleted file mode 100644
index 5a0b25e..0000000
--- a/EPPlus/ExcelCellBase.cs
+++ /dev/null
@@ -1,1255 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using OfficeOpenXml.FormulaParsing;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Base class containing cell address manipulating methods.
-/// </summary>
-public abstract class ExcelCellBase {
- /// <summary>
- /// Get the sheet, row and column from the CellID
- /// </summary>
- /// <param name="cellId"></param>
- /// <param name="sheet"></param>
- /// <param name="row"></param>
- /// <param name="col"></param>
- static internal void SplitCellId(ulong cellId, out int sheet, out int row, out int col) {
- sheet = (int)(cellId % 0x8000);
- col = ((int)(cellId >> 15) & 0x3FF);
- row = ((int)(cellId >> 29));
- }
-
- /// <summary>
- /// Get the cellID for the cell.
- /// </summary>
- /// <param name="sheetId"></param>
- /// <param name="row"></param>
- /// <param name="col"></param>
- /// <returns></returns>
- internal static ulong GetCellId(int sheetId, int row, int col) {
- return ((ulong)sheetId) + (((ulong)col) << 15) + (((ulong)row) << 29);
- }
-
- private delegate string AddressTranslator(
- string part,
- int row,
- int col,
- int rowIncr,
- int colIncr);
-
- /// <summary>
- /// Translates a R1C1 to an absolut address/Formula
- /// </summary>
- /// <param name="value">Address</param>
- /// <param name="row">Current row</param>
- /// <param name="col">Current column</param>
- /// <returns>The RC address</returns>
- public static string TranslateFromR1C1(string value, int row, int col) {
- return Translate(value, ToAbs, row, col, -1, -1);
- }
-
- /// <summary>
- /// Translates a R1C1 to an absolut address/Formula: Version 1
- /// </summary>
- /// <param name="value">Address</param>
- /// <param name="row">Current row</param>
- /// <param name="col">Current column</param>
- /// <returns>The RC address</returns>
- public static string TranslateFromR1C1_V1(string value, int row, int col) {
- return Translate_V1(value, ToAbs_V1, row, col, -1, -1);
- }
-
- /// <summary>
- /// Translates a absolut address to R1C1 Format
- /// </summary>
- /// <param name="value">R1C1 Address</param>
- /// <param name="row">Current row</param>
- /// <param name="col">Current column</param>
- /// <returns>The absolut address/Formula</returns>
- public static string TranslateToR1C1(string value, int row, int col) {
- return Translate(value, ToR1C1, row, col, -1, -1);
- }
-
- /// <summary>
- /// Translates a absolute address to R1C1 Format : Version 1
- /// </summary>
- /// <param name="value">R1C1 Address</param>
- /// <param name="row">Current row</param>
- /// <param name="col">Current column</param>
- /// <returns>The absolut address/Formula</returns>
- public static string TranslateToR1C1_V1(string value, int row, int col) {
- return Translate_V1(value, ToR1C1_V1, row, col, -1, -1);
- }
-
- /// <summary>
- /// Translates betweein R1C1 or absolute addresses : Version 1
- /// </summary>
- /// <param name="value">The addresss/function</param>
- /// <param name="addressTranslator">The translating function</param>
- /// <param name="row"></param>
- /// <param name="col"></param>
- /// <param name="rowIncr"></param>
- /// <param name="colIncr"></param>
- /// <returns></returns>
- private static string Translate(
- string value,
- AddressTranslator addressTranslator,
- int row,
- int col,
- int rowIncr,
- int colIncr) {
- if (value == "") {
- return "";
- }
- bool isText = false;
- string ret = "";
- string part = "";
- char prevTq = (char)0;
- for (int pos = 0; pos < value.Length; pos++) {
- char c = value[pos];
- if (c == '"' || c == '\'') {
- if (isText && prevTq != c) {
- ret += c;
- continue;
- }
-
- if (isText == false && part != "" && prevTq == c) {
- ret += addressTranslator(part, row, col, rowIncr, colIncr);
- part = "";
- }
- prevTq = c;
- isText = !isText;
- ret += c;
- } else if (isText) {
- ret += c;
- } else {
- if ((c == '-'
- || c == '+'
- || c == '*'
- || c == '/'
- || c == '='
- || c == '^'
- || c == ','
- || c == ':'
- || c == '<'
- || c == '>'
- || c == '('
- || c == ')'
- || c == '!'
- || c == ' '
- || c == '&'
- || c == '%')
- && (pos == 0
- || value[pos - 1]
- != '[')) //Last part to allow for R1C1 style [-x]
- {
- ret += addressTranslator(part, row, col, rowIncr, colIncr) + c;
- part = "";
- } else {
- part += c;
- }
- }
- }
- if (part != "") {
- ret += addressTranslator(part, row, col, rowIncr, colIncr);
- }
- return ret;
- }
-
- private static string Translate_V1(
- string value,
- AddressTranslator addressTranslator,
- int row,
- int col,
- int rowIncr,
- int colIncr) {
- if (value == "") {
- return "";
- }
- bool isText = false;
- string ret = "";
- string part = "";
- char prevTq = (char)0;
- value = value.Replace("\n", ""); // Eliminate new line characters in the formula
- for (int pos = 0; pos < value.Length; pos++) {
- char c = value[pos];
- if (c == '"' || c == '\'') {
- if (isText && prevTq != c) {
- ret += c;
- continue;
- }
-
- if (isText == false && part != "" && prevTq == c) {
- ret += addressTranslator(part, row, col, rowIncr, colIncr);
- part = "";
- }
- prevTq = c;
- isText = !isText;
- ret += c;
- } else if (isText) {
- ret += c;
- } else if (c
- == ':') // Keep Range expressions together
- {
- part += c;
- } else {
- if ((c == '-'
- || c == '+'
- || c == '*'
- || c == '/'
- || c == '='
- || c == '^'
- || c == ','
- || c == '<'
- || c == '>'
- || c == '('
- || c == ')'
- || c == '!'
- || c == ' '
- || c == '&'
- || c == '%')
- && (pos == 0
- || value[pos - 1]
- != '[')) //Last part to allow for R1C1 style [-x]
- {
- ret += addressTranslator(part, row, col, rowIncr, colIncr) + c;
- part = "";
- } else {
- part += c;
- }
- }
- }
- if (part != "") {
- ret += addressTranslator(part, row, col, rowIncr, colIncr);
- }
- return ret;
- }
-
- /// <summary>
- /// Translate to R1C1
- /// </summary>
- /// <param name="part">the value to be translated</param>
- /// <param name="row"></param>
- /// <param name="col"></param>
- /// <param name="rowIncr"></param>
- /// <param name="colIncr"></param>
- /// <returns></returns>
- private static string ToR1C1(string part, int row, int col, int rowIncr, int colIncr) {
- string ret = "R";
- if (GetRowCol(part, out var addrRow, out var addrCol, false)) {
- if (addrRow == 0 || addrCol == 0) {
- return part;
- }
- if (part.IndexOf('$', 1) > 0) {
- ret += addrRow.ToString();
- } else if (addrRow - row != 0) {
- ret += string.Format("[{0}]", addrRow - row);
- }
-
- if (part.StartsWith("$")) {
- return ret + "C" + addrCol;
- }
- if (addrCol - col != 0) {
- return ret + "C" + string.Format("[{0}]", addrCol - col);
- }
- return ret + "C";
- }
- return part;
- }
-
- private static string ToR1C1_V1(string part, int row, int col, int rowIncr, int colIncr) {
- // Handle range expressions
- if ((part.Length > 1) && (part.IndexOf(':', 1) > 0)) {
- return RangeToR1C1_V1(part, row, col, rowIncr, colIncr);
- }
-
- string ret = "R";
- if (GetRowCol(part, out var addrRow, out var addrCol, false)) {
- if (addrRow == 0 || addrCol == 0) {
- return part;
- }
- if (part.IndexOf('$', 1) > 0) {
- ret += addrRow.ToString();
- } else if (addrRow - row != 0) {
- ret += string.Format("[{0}]", addrRow - row);
- }
-
- if (part.StartsWith("$")) {
- return ret + "C" + addrCol;
- }
- if (addrCol - col != 0) {
- return ret + "C" + string.Format("[{0}]", addrCol - col);
- }
- return ret + "C";
- }
- return part;
- }
-
- private static string RangeToR1C1_V1(string part, int row, int col, int rowIncr, int colIncr) {
- // Split range expression
- string[] cellValues = part.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
-
- // Convert range expressions
- string result = "";
- result += RangeCellToR1C1_V1(cellValues[0], row, col, rowIncr, colIncr);
- result += ":";
- result +=
- (cellValues.Length > 1)
- ? RangeCellToR1C1_V1(cellValues[1], row, col, rowIncr, colIncr)
- : "";
-
- // Return converted range expression
- return result;
- }
-
- private static string RangeCellToR1C1_V1(
- string part,
- int row,
- int col,
- int rowIncr,
- int colIncr) {
- string result = "";
- if (GetRowCol_V1(
- part,
- out var addrRow,
- out var addrCol,
- false,
- out var fixedRow,
- out var fixedCol)) {
- if (addrRow > 0) {
- result += "R";
- if (fixedRow) {
- // Absolute row
- result += addrRow.ToString();
- } else if (addrRow - row != 0) {
- // Relative row
- result += string.Format("[{0}]", addrRow - row);
- }
- }
-
- if (addrCol > 0) {
- result += "C";
- if (fixedCol) {
- // Absolute column
- result += addrCol;
- } else if (addrCol - col != 0) {
- // Relative column
- result += string.Format("[{0}]", addrCol - col);
- }
- }
- return result;
- }
- return part;
- }
-
- /// <summary>
- /// Translates to absolute address
- /// </summary>
- /// <param name="part"></param>
- /// <param name="row"></param>
- /// <param name="col"></param>
- /// <param name="rowIncr"></param>
- /// <param name="colIncr"></param>
- /// <returns></returns>
- ///
- private static string ToAbs(string part, int row, int col, int rowIncr, int colIncr) {
- string check = part.ToUpper(CultureInfo.InvariantCulture);
-
- int rStart = check.IndexOf("R");
- if (rStart != 0) {
- return part;
- }
- if (part.Length
- == 1) //R
- {
- return GetAddress(row, col);
- }
-
- int cStart = check.IndexOf("C");
- bool absoluteRow;
- if (cStart == -1) {
- int rNum = GetRc(part, row, out absoluteRow);
- if (rNum > int.MinValue) {
- return GetAddress(rNum, absoluteRow, col, false);
- }
- return part;
- } else {
- int rNum = GetRc(part.Substring(1, cStart - 1), row, out absoluteRow);
- int cNum = GetRc(
- part.Substring(cStart + 1, part.Length - cStart - 1),
- col,
- out var absoluteCol);
- if (rNum > int.MinValue && cNum > int.MinValue) {
- return GetAddress(rNum, absoluteRow, cNum, absoluteCol);
- }
- return part;
- }
- }
-
- private static string ToAbs_V1(string part, int row, int col, int rowIncr, int colIncr) {
- bool absoluteCol = false;
- bool absoluteRow = false;
- int colNum = -1;
- int rowNum = -1;
- int num;
- int numLength;
- int pos = 0;
-
- // Handle range expressions
- if ((part.Length > 1) && (part.IndexOf(':', 1) > 0)) {
- return RangeToA1_V1(part, row, col, rowIncr, colIncr);
- }
-
- // Ensure part is present
- if (string.IsNullOrWhiteSpace(part)) {
- return "";
- }
-
- // Convert to upper case
- string check = part.ToUpper(CultureInfo.InvariantCulture);
-
- // Parse "R", if any
- if (pos < part.Length && check[pos] == 'R') {
- pos += 1;
-
- if (pos >= part.Length) {
- // Only "R" present
- absoluteRow = false;
- rowNum = row;
- } else if (pos < part.Length && check[pos] == 'C') {
- // "R" followed by "C"
- absoluteRow = false;
- rowNum = row;
- } else if (pos < part.Length && check[pos] == '[') {
- // "R" followed by relative row number
- pos += 1;
- num = GetNumber_V1(check.Substring(pos, part.Length - pos), out numLength);
- if (num == Int32.MinValue) {
- return part;
- }
- pos += numLength;
-
- if (pos < part.Length && check[pos] == ']') {
- pos += 1;
- } else {
- return part;
- }
-
- absoluteRow = false;
- rowNum = row + num;
- } else if (pos < part.Length) {
- // "R" followed by absolute row number
- num = GetNumber_V1(check.Substring(pos, part.Length - pos), out numLength);
- if (rowNum == Int32.MinValue) {
- return part;
- }
- pos += numLength;
-
- absoluteRow = true;
- rowNum = num;
- }
- }
-
- // Parse "C", if any
- if (pos < part.Length && check[pos] == 'C') {
- pos += 1;
-
- if (pos >= part.Length) {
- // Only "C" present
- absoluteCol = false;
- colNum = col;
- } else if (pos < part.Length && check[pos] == '[') {
- // "C" followed by relative column number
- pos += 1;
- num = GetNumber_V1(check.Substring(pos, part.Length - pos), out numLength);
- if (num == Int32.MinValue) {
- return part;
- }
- pos += numLength;
-
- if (pos < part.Length && check[pos] == ']') {
- pos += 1;
- } else {
- return part;
- }
-
- absoluteCol = false;
- colNum = col + num;
- } else if (pos < part.Length) {
- // "C" followed by absolute column number
- num = GetNumber_V1(check.Substring(pos, part.Length - pos), out numLength);
- if (num == Int32.MinValue) {
- return part;
- }
- pos += numLength;
-
- absoluteCol = true;
- colNum = num;
- }
- }
-
- // Ensure nothing remains unparsed
- if (pos < part.Length) {
- return part;
- }
-
- // Exit if neither row nor column is present
- if ((rowNum == Int32.MinValue) && (colNum == Int32.MinValue)) {
- return part;
- }
-
- // Append column
- string result = "";
- if (colNum >= 0) {
- if (absoluteCol) {
- result += "$";
- }
- result += GetColumnLetter(colNum);
- }
-
- // Append row
- if (rowNum >= 0) {
- if (absoluteRow) {
- result += "$";
- }
- result += rowNum.ToString();
- }
-
- // Return result
- return result;
- }
-
- private static int GetNumber_V1(string value, out int length) {
- // Get number length
- length = 0;
-
- // Ensure value is present
- if (string.IsNullOrWhiteSpace(value)) {
- return Int32.MinValue;
- }
-
- // Check for sign
- if ((length < value.Length) && ((value[length] == '-') || (value[length] == '+'))) {
- length += 1;
- }
-
- // Get number length
- while (length < value.Length && value[length] >= '0' && value[length] <= '9') {
- length += 1;
- }
-
- // No number found
- if (length == 0) {
- return Int32.MinValue;
- }
-
- // Return number value
- return (int.TryParse(value.Substring(0, length), out var result)) ? result : Int32.MinValue;
- }
-
- private static string RangeToA1_V1(string part, int row, int col, int rowIncr, int colIncr) {
- // Split range expression
- string[] cellValues = part.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
-
- // Convert range expressions
- string result = "";
- result += ToAbs_V1(cellValues[0], row, col, rowIncr, colIncr);
- result += ":";
- result += ToAbs_V1(cellValues[1], row, col, rowIncr, colIncr);
-
- // Return converted range expression
- return result;
- }
-
- /// <summary>
- /// Get the offset value for RC format
- /// </summary>
- /// <param name="value"></param>
- /// <param name="offsetValue"></param>
- /// <param name="fixedAddr"></param>
- /// <returns></returns>
- ///
- private static int GetRc(string value, int offsetValue, out bool fixedAddr) {
- if (value == "") {
- fixedAddr = false;
- return offsetValue;
- }
- int num;
- if (value[0] == '['
- && value[value.Length - 1]
- == ']') //Offset?
- {
- fixedAddr = false;
- if (int.TryParse(value.Substring(1, value.Length - 2), out num)) {
- return (offsetValue + num);
- }
- return int.MinValue;
- }
- // Absolute address
- fixedAddr = true;
- if (int.TryParse(value, out num)) {
- return num;
- }
- return int.MinValue;
- }
-
- /// <summary>
- /// Returns the character representation of the numbered column
- /// </summary>
- /// <param name="iColumnNumber">The number of the column</param>
- /// <returns>The letter representing the column</returns>
- protected internal static string GetColumnLetter(int iColumnNumber) {
- return GetColumnLetter(iColumnNumber, false);
- }
-
- protected internal static string GetColumnLetter(int iColumnNumber, bool fixedCol) {
- if (iColumnNumber < 1) {
- //throw new Exception("Column number is out of range");
- return "#REF!";
- }
-
- string sCol = "";
- do {
- sCol = ((char)('A' + ((iColumnNumber - 1) % 26))) + sCol;
- iColumnNumber = (iColumnNumber - ((iColumnNumber - 1) % 26)) / 26;
- } while (iColumnNumber > 0);
- return fixedCol ? "$" + sCol : sCol;
- }
-
- internal static bool GetRowColFromAddress(
- string cellAddress,
- out int fromRow,
- out int fromColumn,
- out int toRow,
- out int toColumn) {
- bool fixedFromRow,
- fixedFromColumn,
- fixedToRow,
- fixedToColumn;
- return GetRowColFromAddress(
- cellAddress,
- out fromRow,
- out fromColumn,
- out toRow,
- out toColumn,
- out fixedFromRow,
- out fixedFromColumn,
- out fixedToRow,
- out fixedToColumn);
- }
-
- /// <summary>
- /// Get the row/columns for a Cell-address
- /// </summary>
- /// <param name="cellAddress">The address</param>
- /// <param name="fromRow">Returns the to column</param>
- /// <param name="fromColumn">Returns the from column</param>
- /// <param name="toRow">Returns the to row</param>
- /// <param name="toColumn">Returns the from row</param>
- /// <param name="fixedFromRow">Is the from row fixed?</param>
- /// <param name="fixedFromColumn">Is the from column fixed?</param>
- /// <param name="fixedToRow">Is the to row fixed?</param>
- /// <param name="fixedToColumn">Is the to column fixed?</param>
- /// <returns></returns>
- internal static bool GetRowColFromAddress(
- string cellAddress,
- out int fromRow,
- out int fromColumn,
- out int toRow,
- out int toColumn,
- out bool fixedFromRow,
- out bool fixedFromColumn,
- out bool fixedToRow,
- out bool fixedToColumn) {
- bool ret;
- if (cellAddress.IndexOf('[')
- > 0) //External reference or reference to Table or Pivottable.
- {
- fromRow = -1;
- fromColumn = -1;
- toRow = -1;
- toColumn = -1;
- fixedFromRow = false;
- fixedFromColumn = false;
- fixedToRow = false;
- fixedToColumn = false;
- return false;
- }
-
- cellAddress = cellAddress.ToUpper(CultureInfo.InvariantCulture);
- //This one can be removed when the worksheet Select format is fixed
- if (cellAddress.IndexOf(' ') > 0) {
- cellAddress = cellAddress.Substring(0, cellAddress.IndexOf(' '));
- }
-
- if (cellAddress.IndexOf(':') < 0) {
- ret = GetRowColFromAddress(
- cellAddress,
- out fromRow,
- out fromColumn,
- out fixedFromRow,
- out fixedFromColumn);
- toColumn = fromColumn;
- toRow = fromRow;
- fixedToRow = fixedFromRow;
- fixedToColumn = fixedFromColumn;
- } else {
- string[] cells = cellAddress.Split(':');
- ret = GetRowColFromAddress(
- cells[0],
- out fromRow,
- out fromColumn,
- out fixedFromRow,
- out fixedFromColumn);
- if (ret) {
- ret = GetRowColFromAddress(
- cells[1],
- out toRow,
- out toColumn,
- out fixedToRow,
- out fixedToColumn);
- } else {
- GetRowColFromAddress(cells[1], out toRow, out toColumn, out fixedToRow, out fixedToColumn);
- }
-
- if (fromColumn <= 0) {
- fromColumn = 1;
- }
- if (fromRow <= 0) {
- fromRow = 1;
- }
- if (toColumn <= 0) {
- toColumn = ExcelPackage.MaxColumns;
- }
- if (toRow <= 0) {
- toRow = ExcelPackage.MaxRows;
- }
- }
- return ret;
- }
-
- /// <summary>
- /// Get the row/column for n Cell-address
- /// </summary>
- /// <param name="cellAddress">The address</param>
- /// <param name="row">Returns Tthe row</param>
- /// <param name="column">Returns the column</param>
- /// <returns>true if valid</returns>
- internal static bool GetRowColFromAddress(string cellAddress, out int row, out int column) {
- return GetRowCol(cellAddress, out row, out column, true);
- }
-
- internal static bool GetRowColFromAddress(
- string cellAddress,
- out int row,
- out int col,
- out bool fixedRow,
- out bool fixedCol) {
- return GetRowCol(cellAddress, out row, out col, true, out fixedRow, out fixedCol);
- }
-
- /// <summary>
- /// Get the row/column for a Cell-address
- /// </summary>
- /// <param name="address">the address</param>
- /// <param name="row">returns the row</param>
- /// <param name="col">returns the column</param>
- /// <param name="throwException">throw exception if invalid, otherwise returns false</param>
- /// <returns></returns>
- internal static bool GetRowCol(string address, out int row, out int col, bool throwException) {
- bool fixedRow,
- fixedCol;
- return GetRowCol(address, out row, out col, throwException, out fixedRow, out fixedCol);
- }
-
- internal static bool GetRowCol(
- string address,
- out int row,
- out int col,
- bool throwException,
- out bool fixedRow,
- out bool fixedCol) {
- bool colPart = true;
- int colStartIx = 0;
- int colLength = 0;
- col = 0;
- row = 0;
- fixedRow = false;
- fixedCol = false;
-
- if (address.EndsWith("#REF!")) {
- row = 0;
- col = 0;
- return true;
- }
-
- int sheetMarkerIndex = address.IndexOf('!');
- if (sheetMarkerIndex >= 0) {
- colStartIx = sheetMarkerIndex + 1;
- }
- address = address.ToUpper(CultureInfo.InvariantCulture);
- for (int i = colStartIx; i < address.Length; i++) {
- char c = address[i];
- if (colPart && (c >= 'A' && c <= 'Z') && colLength <= 3) {
- col *= 26;
- col += c - 64;
- colLength++;
- } else if (c >= '0' && c <= '9') {
- row *= 10;
- row += c - 48;
- colPart = false;
- } else if (c == '$') {
- if (i == colStartIx) {
- colStartIx++;
- fixedCol = true;
- } else {
- colPart = false;
- fixedRow = true;
- }
- } else {
- row = 0;
- col = 0;
- if (throwException) {
- throw (new(string.Format("Invalid Address format {0}", address)));
- }
- return false;
- }
- }
- return row != 0 || col != 0;
- }
-
- internal static bool GetRowCol_V1(
- string address,
- out int row,
- out int col,
- bool throwException,
- out bool fixedRow,
- out bool fixedCol) {
- bool colPart = true;
- bool isFixed = false;
- int colStartIx = 0;
- int colLength = 0;
- col = 0;
- row = 0;
- fixedRow = false;
- fixedCol = false;
-
- if (address.EndsWith("#REF!")) {
- row = 0;
- col = 0;
- return true;
- }
-
- int sheetMarkerIndex = address.IndexOf('!');
- if (sheetMarkerIndex >= 0) {
- colStartIx = sheetMarkerIndex + 1;
- }
- address = address.ToUpper(CultureInfo.InvariantCulture);
- for (int i = colStartIx; i < address.Length; i++) {
- char c = address[i];
- if (c == '$') {
- // Absolute address
- isFixed = true;
- } else if (colPart && (c >= 'A' && c <= 'Z') && colLength <= 3) {
- // Column portion of address
- if (isFixed) {
- fixedCol = true;
- isFixed = false;
- }
-
- col *= 26;
- col += c - 64;
- colLength++;
- } else if (c >= '0' && c <= '9') {
- // Row portion of address
- if (isFixed) {
- fixedRow = true;
- isFixed = false;
- }
-
- row *= 10;
- row += c - 48;
- colPart = false;
- } else {
- row = 0;
- col = 0;
- if (throwException) {
- throw (new(string.Format("Invalid Address format {0}", address)));
- }
- return false;
- }
- }
- return row != 0 || col != 0;
- }
-
- private static int GetColumn(string sCol) {
- int col = 0;
- int len = sCol.Length - 1;
- for (int i = len; i >= 0; i--) {
- col += (sCol[i] - 64) * (int)(Math.Pow(26, len - i));
- }
- return col;
- }
-
- /// <summary>
- /// Returns the AlphaNumeric representation that Excel expects for a Cell Address
- /// </summary>
- /// <param name="row">The number of the row</param>
- /// <param name="column">The number of the column in the worksheet</param>
- /// <returns>The cell address in the format A1</returns>
- public static string GetAddress(int row, int column) {
- return GetAddress(row, column, false);
- }
-
- /// <summary>
- /// Returns the AlphaNumeric representation that Excel expects for a Cell Address
- /// </summary>
- /// <param name="row">The number of the row</param>
- /// <param name="column">The number of the column in the worksheet</param>
- /// <param name="absoluteRow">Absolute row</param>
- /// <param name="absoluteCol">Absolute column</param>
- /// <returns>The cell address in the format A1</returns>
- public static string GetAddress(int row, bool absoluteRow, int column, bool absoluteCol) {
- return (absoluteCol ? "$" : "") + GetColumnLetter(column) + (absoluteRow ? "$" : "") + row;
- }
-
- /// <summary>
- /// Returns the AlphaNumeric representation that Excel expects for a Cell Address
- /// </summary>
- /// <param name="row">The number of the row</param>
- /// <param name="column">The number of the column in the worksheet</param>
- /// <param name="absolute">Get an absolute address ($A$1)</param>
- /// <returns>The cell address in the format A1</returns>
- public static string GetAddress(int row, int column, bool absolute) {
- if (row == 0 || column == 0) {
- return "#REF!";
- }
- if (absolute) {
- return ("$" + GetColumnLetter(column) + "$" + row);
- }
- return (GetColumnLetter(column) + row);
- }
-
- /// <summary>
- /// Returns the AlphaNumeric representation that Excel expects for a Cell Address
- /// </summary>
- /// <param name="fromRow">From row number</param>
- /// <param name="fromColumn">From column number</param>
- /// <param name="toRow">To row number</param>
- /// <param name="toColumn">From column number</param>
- /// <returns>The cell address in the format A1</returns>
- public static string GetAddress(int fromRow, int fromColumn, int toRow, int toColumn) {
- return GetAddress(fromRow, fromColumn, toRow, toColumn, false);
- }
-
- /// <summary>
- /// Returns the AlphaNumeric representation that Excel expects for a Cell Address
- /// </summary>
- /// <param name="fromRow">From row number</param>
- /// <param name="fromColumn">From column number</param>
- /// <param name="toRow">To row number</param>
- /// <param name="toColumn">From column number</param>
- /// <param name="absolute">if true address is absolute (like $A$1)</param>
- /// <returns>The cell address in the format A1</returns>
- public static string GetAddress(
- int fromRow,
- int fromColumn,
- int toRow,
- int toColumn,
- bool absolute) {
- if (fromRow == toRow && fromColumn == toColumn) {
- return GetAddress(fromRow, fromColumn, absolute);
- }
- if (fromRow == 1 && toRow == ExcelPackage.MaxRows) {
- var absChar = absolute ? "$" : "";
- return absChar + GetColumnLetter(fromColumn) + ":" + absChar + GetColumnLetter(toColumn);
- }
- if (fromColumn == 1 && toColumn == ExcelPackage.MaxColumns) {
- var absChar = absolute ? "$" : "";
- return absChar + fromRow + ":" + absChar + toRow;
- }
- return GetAddress(fromRow, fromColumn, absolute) + ":" + GetAddress(toRow, toColumn, absolute);
- }
-
- /// <summary>
- /// Returns the AlphaNumeric representation that Excel expects for a Cell Address
- /// </summary>
- /// <param name="fromRow">From row number</param>
- /// <param name="fromColumn">From column number</param>
- /// <param name="toRow">To row number</param>
- /// <param name="toColumn">From column number</param>
- /// <param name="fixedFromColumn"></param>
- /// <param name="fixedFromRow"></param>
- /// <param name="fixedToColumn"></param>
- /// <param name="fixedToRow"></param>
- /// <returns>The cell address in the format A1</returns>
- public static string GetAddress(
- int fromRow,
- int fromColumn,
- int toRow,
- int toColumn,
- bool fixedFromRow,
- bool fixedFromColumn,
- bool fixedToRow,
- bool fixedToColumn) {
- if (fromRow == toRow && fromColumn == toColumn) {
- return GetAddress(fromRow, fixedFromRow, fromColumn, fixedFromColumn);
- }
- if (fromRow == 1 && toRow == ExcelPackage.MaxRows) {
- return GetColumnLetter(fromColumn, fixedFromColumn)
- + ":"
- + GetColumnLetter(toColumn, fixedToColumn);
- }
- if (fromColumn == 1 && toColumn == ExcelPackage.MaxColumns) {
- return (fixedFromRow ? "$" : "") + fromRow + ":" + (fixedToRow ? "$" : "") + toRow;
- }
- return GetAddress(fromRow, fixedFromRow, fromColumn, fixedFromColumn)
- + ":"
- + GetAddress(toRow, fixedToRow, toColumn, fixedToColumn);
- }
-
- /// <summary>
- /// Get the full address including the worksheet name
- /// </summary>
- /// <param name="worksheetName">The name of the worksheet</param>
- /// <param name="address">The address</param>
- /// <returns>The full address</returns>
- public static string GetFullAddress(string worksheetName, string address) {
- return GetFullAddress(worksheetName, address, true);
- }
-
- internal static string GetFullAddress(string worksheetName, string address, bool fullRowCol) {
- if (address.IndexOf("!") == -1 || address == "#REF!") {
- if (fullRowCol) {
- string[] cells = address.Split(':');
- if (cells.Length > 0) {
- address = string.Format("'{0}'!{1}", worksheetName, cells[0]);
- if (cells.Length > 1) {
- address += string.Format(":{0}", cells[1]);
- }
- }
- } else {
- var a = new ExcelAddressBase(address);
- if ((a._fromRow == 1 && a._toRow == ExcelPackage.MaxRows)
- || (a._fromCol == 1 && a._toCol == ExcelPackage.MaxColumns)) {
- address = string.Format(
- "'{0}'!{1}{2}:{3}{4}",
- worksheetName,
- GetColumnLetter(a._fromCol),
- a._fromRow,
- GetColumnLetter(a._toCol),
- a._toRow);
- } else {
- address = GetFullAddress(worksheetName, address, true);
- }
- }
- }
- return address;
- }
-
- public static bool IsValidAddress(string address) {
- address = address.ToUpper(CultureInfo.InvariantCulture);
- string r1 = "",
- c1 = "",
- r2 = "",
- c2 = "";
- bool isSecond = false;
- for (int i = 0; i < address.Length; i++) {
- if (address[i] >= 'A' && address[i] <= 'Z') {
- if (isSecond == false) {
- if (r1 != "") {
- return false;
- }
- c1 += address[i];
- if (c1.Length > 3) {
- return false;
- }
- } else {
- if (r2 != "") {
- return false;
- }
- c2 += address[i];
- if (c2.Length > 3) {
- return false;
- }
- }
- } else if (address[i] >= '0' && address[i] <= '9') {
- if (isSecond == false) {
- r1 += address[i];
- if (r1.Length > 7) {
- return false;
- }
- } else {
- r2 += address[i];
- if (r2.Length > 7) {
- return false;
- }
- }
- } else if (address[i] == ':') {
- isSecond = true;
- } else if (address[i] == '$') {
- if (i == address.Length - 1 || address[i + 1] == ':') {
- return false;
- }
- } else {
- return false;
- }
- }
-
- if (r1 != ""
- && c1 != ""
- && r2 == ""
- && c2
- == "") //Single Cell
- {
- return (GetColumn(c1) <= ExcelPackage.MaxColumns && int.Parse(r1) <= ExcelPackage.MaxRows);
- }
- if (r1 != ""
- && r2 != ""
- && c1 != ""
- && c2
- != "") //Range
- {
- var iR2 = int.Parse(r2);
- var iC2 = GetColumn(c2);
-
- return GetColumn(c1) <= iC2
- && int.Parse(r1) <= iR2
- && iC2 <= ExcelPackage.MaxColumns
- && iR2 <= ExcelPackage.MaxRows;
- }
- if (r1 == ""
- && r2 == ""
- && c1 != ""
- && c2
- != "") //Full Column
- {
- var c2N = GetColumn(c2);
- return (GetColumn(c1) <= c2N && c2N <= ExcelPackage.MaxColumns);
- }
- if (r1 != "" && r2 != "" && c1 == "" && c2 == "") {
- var iR2 = int.Parse(r2);
-
- return int.Parse(r1) <= iR2 && iR2 <= ExcelPackage.MaxRows;
- }
- return false;
- }
-
- /// <summary>
- /// Checks that a cell address (e.g. A5) is valid.
- /// </summary>
- /// <param name="cellAddress">The alphanumeric cell address</param>
- /// <returns>True if the cell address is valid</returns>
- public static bool IsValidCellAddress(string cellAddress) {
- bool result = false;
- try {
- if (GetRowColFromAddress(cellAddress, out var row, out var col)) {
- if (row > 0 && col > 0 && row <= ExcelPackage.MaxRows && col <= ExcelPackage.MaxColumns) {
- result = true;
- } else {
- result = false;
- }
- }
- } catch {}
- return result;
- }
-
- /// <summary>
- /// Updates the Excel formula so that all the cellAddresses are incremented by the row and column increments
- /// if they fall after the afterRow and afterColumn.
- /// Supports inserting rows and columns into existing templates.
- /// </summary>
- /// <param name="formula">The Excel formula</param>
- /// <param name="rowIncrement">The amount to increment the cell reference by</param>
- /// <param name="colIncrement">The amount to increment the cell reference by</param>
- /// <param name="afterRow">Only change rows after this row</param>
- /// <param name="afterColumn">Only change columns after this column</param>
- /// <returns></returns>
- internal static string UpdateFormulaReferences(
- string formula,
- int rowIncrement,
- int colIncrement,
- int afterRow,
- int afterColumn,
- bool setFixed = false) {
- //return Translate(Formula, AddToRowColumnTranslator, afterRow, afterColumn, rowIncrement, colIncrement);
- var d = new Dictionary<string, object>();
- try {
- var sct = new SourceCodeTokenizer(FunctionNameProvider.Empty, NameValueProvider.Empty);
- var tokens = sct.Tokenize(formula);
- String f = "";
- foreach (var t in tokens) {
- if (t.TokenType == TokenType.ExcelAddress) {
- var a = new ExcelAddressBase(t.Value);
-
- if (!String.IsNullOrEmpty(
- a._ws)) // Bug 15339
- {
- // This is from a different worksheet, thus no update is required
- f += a.Address;
- continue;
- }
-
- if (rowIncrement > 0) {
- a = a.AddRow(afterRow, rowIncrement, setFixed);
- } else if (rowIncrement < 0) {
- a = a.DeleteRow(afterRow, -rowIncrement, setFixed);
- }
- if (colIncrement > 0) {
- a = a.AddColumn(afterColumn, colIncrement, setFixed);
- } else if (colIncrement < 0) {
- a = a.DeleteColumn(afterColumn, -colIncrement, setFixed);
- }
- if (a == null || !a.IsValidRowCol()) {
- f += "#REF!";
- } else {
- f += a.Address;
- }
- } else {
- f += t.Value;
- }
- }
- return f;
- } catch //Invalid formula, skip updateing addresses
- {
- return formula;
- }
- }
-}
diff --git a/EPPlus/ExcelColumn.cs b/EPPlus/ExcelColumn.cs
deleted file mode 100644
index 889c682..0000000
--- a/EPPlus/ExcelColumn.cs
+++ /dev/null
@@ -1,253 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan K�llman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.Style;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Represents one or more columns within the worksheet
-/// </summary>
-public class ExcelColumn : IRangeId {
- private readonly ExcelWorksheet _worksheet;
- private readonly XmlElement _colElement = null;
-
- /// <summary>
- /// Creates a new instance of the ExcelColumn class.
- /// For internal use only!
- /// </summary>
- /// <param name="worksheet"></param>
- /// <param name="col"></param>
- protected internal ExcelColumn(ExcelWorksheet worksheet, int col) {
- _worksheet = worksheet;
- _columnMin = col;
- _columnMax = col;
- _width = _worksheet.DefaultColWidth;
- }
-
- internal int _columnMin;
-
- /// <summary>
- /// Sets the first column the definition refers to.
- /// </summary>
- public int ColumnMin => _columnMin;
-
- //set { _columnMin=value; }
- internal int _columnMax;
-
- /// <summary>
- /// Sets the last column the definition refers to.
- /// </summary>
- public int ColumnMax {
- get => _columnMax;
- set {
- if (value < _columnMin && value > ExcelPackage.MaxColumns) {
- throw new("ColumnMax out of range");
- }
-
- var cse = new CellsStoreEnumerator<object>(
- _worksheet._values,
- 0,
- 0,
- 0,
- ExcelPackage.MaxColumns);
- while (cse.Next()) {
- var c = cse.Value as ExcelColumn;
- if (cse.Column > _columnMin && c.ColumnMax <= value && cse.Column != _columnMin) {
- throw new(string.Format("ColumnMax can not span over existing column {0}.", c.ColumnMin));
- }
- }
- _columnMax = value;
- }
- }
-
- /// <summary>
- /// Internal range id for the column
- /// </summary>
- internal ulong ColumnID => GetColumnId(_worksheet.SheetID, ColumnMin);
-
- /// <summary>
- /// Allows the column to be hidden in the worksheet
- /// </summary>
- internal bool _hidden;
- public bool Hidden {
- get => _hidden;
- set => _hidden = value;
- }
-
- internal double VisualWidth {
- get {
- if (_hidden || (Collapsed && OutlineLevel > 0)) {
- return 0;
- }
- return _width;
- }
- }
- internal double _width;
-
- /// <summary>
- /// Sets the width of the column in the worksheet
- /// </summary>
- public double Width {
- get => _width;
- set {
- _width = value;
-
- if (_hidden && value != 0) {
- _hidden = false;
- }
- }
- }
-
- /// <summary>
- /// If set to true a column automaticlly resize(grow wider) when a user inputs numbers in a cell.
- /// </summary>
- public bool BestFit { get; set; }
-
- /// <summary>
- /// If the column is collapsed in outline mode
- /// </summary>
- public bool Collapsed { get; set; }
-
- /// <summary>
- /// Outline level. Zero if no outline
- /// </summary>
- public int OutlineLevel { get; set; }
-
- /// <summary>
- /// Phonetic
- /// </summary>
- public bool Phonetic { get; set; }
-
- /// <summary>
- /// The Style applied to the whole column. Only effects cells with no individual style set.
- /// Use Range object if you want to set specific styles.
- /// </summary>
- public ExcelStyle Style {
- get {
- string letter = ExcelCellBase.GetColumnLetter(ColumnMin);
- string endLetter = ExcelCellBase.GetColumnLetter(ColumnMax);
- return _worksheet.Workbook.Styles.GetStyleObject(
- StyleID,
- _worksheet.PositionID,
- letter + ":" + endLetter);
- }
- }
- internal string _styleName = "";
-
- /// <summary>
- /// Sets the style for the entire column using a style name.
- /// </summary>
- public string StyleName {
- get => _styleName;
- set {
- StyleID = _worksheet.Workbook.Styles.GetStyleIdFromName(value);
- _styleName = value;
- }
- }
-
- //internal int _styleID = 0;
- /// <summary>
- /// Sets the style for the entire column using the style ID.
- /// </summary>
- public int StyleID {
- get => _worksheet._styles.GetValue(0, ColumnMin);
- set => _worksheet._styles.SetValue(0, ColumnMin, value);
- }
-
- /// <summary>
- /// Adds a manual page break after the column.
- /// </summary>
- public bool PageBreak { get; set; }
- public bool Merged {
- get => _worksheet.MergedCells[ColumnMin, 0] != null;
- set => _worksheet.MergedCells.Add(new(1, ColumnMin, ExcelPackage.MaxRows, ColumnMax), true);
- }
-
- /// <summary>
- /// Returns the range of columns covered by the column definition.
- /// </summary>
- /// <returns>A string describing the range of columns covered by the column definition.</returns>
- public override string ToString() {
- return string.Format(
- "Column Range: {0} to {1}",
- _colElement.GetAttribute("min"),
- _colElement.GetAttribute("min"));
- }
-
- /// <summary>
- /// Get the internal RangeID
- /// </summary>
- /// <param name="sheetId">Sheet no</param>
- /// <param name="column">Column</param>
- /// <returns></returns>
- internal static ulong GetColumnId(int sheetId, int column) {
- return ((ulong)sheetId) + (((ulong)column) << 15);
- }
-
- ulong IRangeId.RangeID {
- get => ColumnID;
- set {
- int prevColMin = _columnMin;
- _columnMin = ((int)(value >> 15) & 0x3FF);
- _columnMax += prevColMin - ColumnMin;
- //Todo:More Validation
- if (_columnMax > ExcelPackage.MaxColumns) {
- _columnMax = ExcelPackage.MaxColumns;
- }
- }
- }
-
- /// <summary>
- /// Copies the current column to a new worksheet
- /// </summary>
- /// <param name="added">The worksheet where the copy will be created</param>
- internal ExcelColumn Clone(ExcelWorksheet added) {
- return Clone(added, ColumnMin);
- }
-
- internal ExcelColumn Clone(ExcelWorksheet added, int col) {
- ExcelColumn newCol = added.Column(col);
- newCol.ColumnMax = ColumnMax;
- newCol.BestFit = BestFit;
- newCol.Collapsed = Collapsed;
- newCol.OutlineLevel = OutlineLevel;
- newCol.PageBreak = PageBreak;
- newCol.Phonetic = Phonetic;
- newCol._styleName = _styleName;
- newCol.StyleID = StyleID;
- newCol.Width = Width;
- newCol.Hidden = Hidden;
- return newCol;
- }
-}
diff --git a/EPPlus/ExcelComment.cs b/EPPlus/ExcelComment.cs
deleted file mode 100644
index 74df866..0000000
--- a/EPPlus/ExcelComment.cs
+++ /dev/null
@@ -1,141 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Xml;
-using OfficeOpenXml.Drawing.Vml;
-using OfficeOpenXml.Style;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// An Excel Cell Comment
-/// </summary>
-public class ExcelComment : ExcelVmlDrawingComment {
- private readonly XmlHelper _commentHelper;
- private readonly string _text;
-
- internal ExcelComment(XmlNamespaceManager ns, XmlNode commentTopNode, ExcelRangeBase cell)
- : base(null, cell, cell.Worksheet.VmlDrawingsComments.NameSpaceManager) {
- //_commentHelper = new XmlHelper(ns, commentTopNode);
- _commentHelper = XmlHelperFactory.Create(ns, commentTopNode);
- var textElem = commentTopNode.SelectSingleNode("d:text", ns);
- if (textElem == null) {
- textElem = commentTopNode.OwnerDocument.CreateElement("text", ExcelPackage._schemaMain);
- commentTopNode.AppendChild(textElem);
- }
- if (!cell.Worksheet._vmlDrawings.ContainsKey(
- ExcelCellBase.GetCellId(cell.Worksheet.SheetID, cell.Start.Row, cell.Start.Column))) {
- cell.Worksheet._vmlDrawings.Add(cell);
- }
-
- TopNode = cell.Worksheet.VmlDrawingsComments[ExcelCellBase.GetCellId(
- cell.Worksheet.SheetID,
- cell.Start.Row,
- cell.Start.Column)].TopNode;
- RichText = new(ns, textElem);
- var tNode = textElem.SelectSingleNode("d:t", ns);
- if (tNode != null) {
- _text = tNode.InnerText;
- }
- }
-
- private const string _authorsPath = "d:comments/d:authors";
- private const string _authorPath = "d:comments/d:authors/d:author";
-
- /// <summary>
- /// Author
- /// </summary>
- public string Author {
- get {
- int authorRef = _commentHelper.GetXmlNodeInt("@authorId");
- return _commentHelper.TopNode.OwnerDocument
- .SelectSingleNode(
- string.Format("{0}[{1}]", _authorPath, authorRef + 1),
- _commentHelper.NameSpaceManager)
- .InnerText;
- }
- }
-
- private int GetAuthor(string value) {
- int authorRef = 0;
- bool found = false;
- foreach (XmlElement node in _commentHelper.TopNode.OwnerDocument.SelectNodes(
- _authorPath,
- _commentHelper.NameSpaceManager)) {
- if (node.InnerText == value) {
- found = true;
- break;
- }
- authorRef++;
- }
- if (!found) {
- var elem = _commentHelper.TopNode.OwnerDocument.CreateElement(
- "d",
- "author",
- ExcelPackage._schemaMain);
- _commentHelper.TopNode.OwnerDocument
- .SelectSingleNode(_authorsPath, _commentHelper.NameSpaceManager)
- .AppendChild(elem);
- elem.InnerText = value;
- }
- return authorRef;
- }
-
- /// <summary>
- /// The comment text
- /// </summary>
- public string Text {
- get {
- if (!string.IsNullOrEmpty(RichText.Text)) {
- return RichText.Text;
- }
- return _text;
- }
- }
-
- /// <summary>
- /// Sets the font of the first richtext item.
- /// </summary>
- public ExcelRichText Font {
- get {
- if (RichText.Count > 0) {
- return RichText[0];
- }
- return null;
- }
- }
-
- /// <summary>
- /// Richtext collection
- /// </summary>
- internal ExcelRichTextCollection RichText { get; set; }
-}
diff --git a/EPPlus/ExcelCommentCollection.cs b/EPPlus/ExcelCommentCollection.cs
deleted file mode 100644
index 70a4820..0000000
--- a/EPPlus/ExcelCommentCollection.cs
+++ /dev/null
@@ -1,145 +0,0 @@
-/*******************************************************************************
- * 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 License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Xml;
-using OfficeOpenXml.Packaging;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Collection of Excelcomment objects
-/// </summary>
-public class ExcelCommentCollection : IEnumerable, IDisposable {
- internal RangeCollection _comments;
-
- internal ExcelCommentCollection(ExcelPackage pck, ExcelWorksheet ws, XmlNamespaceManager ns) {
- CommentXml.PreserveWhitespace = false;
- NameSpaceManager = ns;
- Worksheet = ws;
- CreateXml(pck);
- AddCommentsFromXml();
- }
-
- private void CreateXml(ExcelPackage pck) {
- var commentParts = Worksheet.Part.GetRelationshipsByType(ExcelPackage._schemaComment);
- bool isLoaded = false;
- CommentXml = new();
- foreach (var commentPart in commentParts) {
- Uri = UriHelper.ResolvePartUri(commentPart.SourceUri, commentPart.TargetUri);
- Part = pck.Package.GetPart(Uri);
- XmlHelper.LoadXmlSafe(CommentXml, Part.GetStream());
- RelId = commentPart.Id;
- isLoaded = true;
- }
- //Create a new document
- if (!isLoaded) {
- CommentXml.LoadXml(
- "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><comments xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"><authors /><commentList /></comments>");
- Uri = null;
- }
- }
-
- private void AddCommentsFromXml() {
- var lst = new List<IRangeId>();
- foreach (XmlElement node in CommentXml.SelectNodes(
- "//d:commentList/d:comment",
- NameSpaceManager)) {
- var comment = new ExcelComment(
- NameSpaceManager,
- node,
- new(Worksheet, node.GetAttribute("ref")));
- lst.Add(comment);
- }
- _comments = new(lst);
- }
-
- /// <summary>
- /// Access to the comment xml document
- /// </summary>
- public XmlDocument CommentXml { get; set; } = new();
-
- internal Uri Uri { get; set; }
-
- internal string RelId { get; set; }
-
- internal XmlNamespaceManager NameSpaceManager { get; set; }
-
- internal ZipPackagePart Part { get; set; }
-
- /// <summary>
- /// A reference to the worksheet object
- /// </summary>
- public ExcelWorksheet Worksheet { get; set; }
-
- /// <summary>
- /// Number of comments in the collection
- /// </summary>
- public int Count => _comments.Count;
-
- /// <summary>
- /// Indexer for the comments collection
- /// </summary>
- /// <param name="index">The index</param>
- /// <returns>The comment</returns>
- public ExcelComment this[int index] {
- get {
- if (index < 0 || index >= _comments.Count) {
- throw (new ArgumentOutOfRangeException("Comment index out of range"));
- }
- return _comments[index] as ExcelComment;
- }
- }
-
- /// <summary>
- /// Indexer for the comments collection
- /// </summary>
- /// <param name="cell">The cell</param>
- /// <returns>The comment</returns>
- public ExcelComment this[ExcelCellAddress cell] {
- get {
- ulong cellId = ExcelCellBase.GetCellId(Worksheet.SheetID, cell.Row, cell.Column);
- if (_comments.IndexOf(cellId) >= 0) {
- return _comments[cellId] as ExcelComment;
- }
- return null;
- }
- }
-
- void IDisposable.Dispose() {}
-
- IEnumerator IEnumerable.GetEnumerator() {
- return _comments;
- }
-}
diff --git a/EPPlus/ExcelHyperLink.cs b/EPPlus/ExcelHyperLink.cs
deleted file mode 100644
index dc4aa3b..0000000
--- a/EPPlus/ExcelHyperLink.cs
+++ /dev/null
@@ -1,137 +0,0 @@
-/*******************************************************************************
- * 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 this class 2010-01-24
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// HyperlinkClass
-/// </summary>
-public class ExcelHyperLink : Uri {
- /// <summary>
- /// A new hyperlink with the specified URI
- /// </summary>
- /// <param name="uriString">The URI</param>
- public ExcelHyperLink(string uriString)
- : base(uriString) {
- OriginalUri = this;
- }
-
- /// <summary>
- /// A new hyperlink with the specified URI. This syntax is obsolete
- /// </summary>
- /// <param name="uriString">The URI</param>
- /// <param name="dontEscape"></param>
- [Obsolete(
- "base constructor 'System.Uri.Uri(string, bool)' is obsolete: 'The constructor has been deprecated. Please use new ExcelHyperLink(string). The dontEscape parameter is deprecated and is always false.")]
- public ExcelHyperLink(string uriString, bool dontEscape)
- : base(uriString, dontEscape) {
- OriginalUri = this;
- }
-
- /// <summary>
- /// A new hyperlink with the specified URI and kind
- /// </summary>
- /// <param name="uriString">The URI</param>
- /// <param name="uriKind">Kind (absolute/relative or indeterminate)</param>
- public ExcelHyperLink(string uriString, UriKind uriKind)
- : base(uriString, uriKind) {
- OriginalUri = this;
- }
-
- /// <summary>
- /// Sheet internal reference
- /// </summary>
- /// <param name="referenceAddress">Address</param>
- /// <param name="display">Displayed text</param>
- public ExcelHyperLink(string referenceAddress, string display)
- : base(
- "xl://internal") //URI is not used on internal links so put a dummy uri here.
- {
- _referenceAddress = referenceAddress;
- _display = display;
- }
-
- private string _referenceAddress;
-
- /// <summary>
- /// The Excel address for internal links.
- /// </summary>
- public string ReferenceAddress {
- get => _referenceAddress;
- set => _referenceAddress = value;
- }
-
- private string _display = "";
-
- /// <summary>
- /// Displayed text
- /// </summary>
- public string Display {
- get => _display;
- set => _display = value;
- }
-
- /// <summary>
- /// Tooltip
- /// </summary>
- public string ToolTip { get; set; }
-
- private int _colSpann;
-
- /// <summary>
- /// If the hyperlink spans multiple columns
- /// </summary>
- public int ColSpann {
- get => _colSpann;
- set => _colSpann = value;
- }
-
- private int _rowSpann;
-
- /// <summary>
- /// If the hyperlink spans multiple rows
- /// </summary>
- public int RowSpann {
- get => _rowSpann;
- set => _rowSpann = value;
- }
-
- /// <summary>
- /// Used to handle non absolute URI's.
- /// Is used if IsAblsoluteUri is true. The base URI will have a dummy value of xl://nonAbsolute.
- /// </summary>
- public Uri OriginalUri { get; internal set; }
-
- internal string RId { get; set; }
-}
diff --git a/EPPlus/ExcelNamedRange.cs b/EPPlus/ExcelNamedRange.cs
deleted file mode 100644
index 96337ae..0000000
--- a/EPPlus/ExcelNamedRange.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-/*******************************************************************************
- * 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 this class 2010-01-28
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// A named range.
-/// </summary>
-public sealed class ExcelNamedRange : ExcelRangeBase {
- private readonly ExcelWorksheet _sheet;
-
- /// <summary>
- /// A named range
- /// </summary>
- /// <param name="name">The name</param>
- /// <param name="nameSheet">The sheet containing the name. null if its a global name</param>
- /// <param name="sheet">Sheet where the address points</param>
- /// <param name="address">The address</param>
- /// <param name="index">The index in the collection</param>
- public ExcelNamedRange(
- string name,
- ExcelWorksheet nameSheet,
- ExcelWorksheet sheet,
- string address,
- int index)
- : base(sheet, address) {
- Name = name;
- _sheet = nameSheet;
- Index = index;
- }
-
- internal ExcelNamedRange(string name, ExcelWorkbook wb, ExcelWorksheet nameSheet, int index)
- : base(wb, nameSheet, name, true) {
- Name = name;
- _sheet = nameSheet;
- Index = index;
- }
-
- /// <summary>
- /// Name of the range
- /// </summary>
- public string Name { get; internal set; }
-
- /// <summary>
- /// Is the named range local for the sheet
- /// </summary>
- public int LocalSheetId {
- get {
- if (_sheet == null) {
- return -1;
- }
- return _sheet.PositionID - 1;
- }
- }
-
- internal int Index { get; set; }
-
- /// <summary>
- /// Is the name hidden
- /// </summary>
- public bool IsNameHidden { get; set; }
-
- /// <summary>
- /// A comment for the Name
- /// </summary>
- public string NameComment { get; set; }
-
- internal object NameValue { get; set; }
-
- internal string NameFormula { get; set; }
-
- public override string ToString() {
- return Name;
- }
-}
diff --git a/EPPlus/ExcelNamedRangeCollection.cs b/EPPlus/ExcelNamedRangeCollection.cs
deleted file mode 100644
index 3584a54..0000000
--- a/EPPlus/ExcelNamedRangeCollection.cs
+++ /dev/null
@@ -1,206 +0,0 @@
-/*******************************************************************************
- * 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 this class 2010-01-28
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Collection for named ranges
-/// </summary>
-public class ExcelNamedRangeCollection : IEnumerable<ExcelNamedRange> {
- internal ExcelWorksheet _ws;
- internal ExcelWorkbook _wb;
-
- internal ExcelNamedRangeCollection(ExcelWorkbook wb) {
- _wb = wb;
- _ws = null;
- }
-
- internal ExcelNamedRangeCollection(ExcelWorkbook wb, ExcelWorksheet ws) {
- _wb = wb;
- _ws = ws;
- }
-
- private readonly List<ExcelNamedRange> _list = new();
- private readonly Dictionary<string, int> _dic = new(StringComparer.InvariantCultureIgnoreCase);
-
- /// <summary>
- /// Add a new named range
- /// </summary>
- /// <param name="name">The name</param>
- /// <param name="range">The range</param>
- /// <returns></returns>
- public ExcelNamedRange Add(string name, ExcelRangeBase range) {
- ExcelNamedRange item;
- if (range.IsName) {
- item = new(name, _wb, _ws, _dic.Count);
- } else {
- item = new(name, _ws, range.Worksheet, range.Address, _dic.Count);
- }
-
- AddName(name, item);
-
- return item;
- }
-
- private void AddName(string name, ExcelNamedRange item) {
- // Is 'Name' already present
- if (_dic.ContainsKey(name)) {
- int index = _dic[name];
- if ((0 <= index) && (index < _list.Count)) {
- ExcelNamedRange listItem = _list[index];
- if ((listItem != null)
- && (listItem.FullAddress != null)
- && (listItem.FullAddress == item.FullAddress)) {
- return;
- }
-
- //throw new Exception(string.Format("Name '{0}' is defined in the worksheet more than once. First as '{1}' and second as '{2}'.", Name, listItem.FullAddress, item.FullAddress));
- return;
- }
-
- //throw new Exception(string.Format("Name '{0}' is defined in the worksheet more than once.", Name));
- return;
- }
-
- _dic.Add(name, _list.Count);
- _list.Add(item);
- }
-
- /// <summary>
- /// Add a defined name referencing value
- /// </summary>
- /// <param name="name"></param>
- /// <param name="value"></param>
- /// <returns></returns>
- public ExcelNamedRange AddValue(string name, object value) {
- var item = new ExcelNamedRange(name, _wb, _ws, _dic.Count);
- item.NameValue = value;
- AddName(name, item);
- return item;
- }
-
- /// <summary>
- /// Add a defined name referencing a formula -- the method name contains a typo.
- /// This method is obsolete and will be removed in the future.
- /// Use <see cref="AddFormula"/>
- /// </summary>
- /// <param name="name"></param>
- /// <param name="formula"></param>
- /// <returns></returns>
- [Obsolete("Call AddFormula() instead. See Issue Tracker Id #14687")]
- public ExcelNamedRange AddFormla(string name, string formula) {
- return AddFormula(name, formula);
- }
-
- /// <summary>
- /// Add a defined name referencing a formula
- /// </summary>
- /// <param name="name"></param>
- /// <param name="formula"></param>
- /// <returns></returns>
- public ExcelNamedRange AddFormula(string name, string formula) {
- var item = new ExcelNamedRange(name, _wb, _ws, _dic.Count);
- item.NameFormula = formula;
- AddName(name, item);
- return item;
- }
-
- /// <summary>
- /// Remove a defined name from the collection
- /// </summary>
- /// <param name="name">The name</param>
- public void Remove(string name) {
- if (_dic.ContainsKey(name)) {
- var ix = _dic[name];
-
- for (int i = ix + 1; i < _list.Count; i++) {
- _dic.Remove(_list[i].Name);
- _list[i].Index--;
- _dic.Add(_list[i].Name, _list[i].Index);
- }
- _dic.Remove(name);
- _list.RemoveAt(ix);
- }
- }
-
- /// <summary>
- /// Checks collection for the presence of a key
- /// </summary>
- /// <param name="key">key to search for</param>
- /// <returns>true if the key is in the collection</returns>
- public bool ContainsKey(string key) {
- return _dic.ContainsKey(key);
- }
-
- /// <summary>
- /// The current number of items in the collection
- /// </summary>
- public int Count => _dic.Count;
-
- /// <summary>
- /// Name indexer
- /// </summary>
- /// <param name="name">The name (key) for a Named range</param>
- /// <returns>a reference to the range</returns>
- /// <remarks>
- /// Throws a KeyNotFoundException if the key is not in the collection.
- /// </remarks>
- public ExcelNamedRange this[string name] => _list[_dic[name]];
-
- public ExcelNamedRange this[int index] => _list[index];
-
- /// <summary>
- /// Implement interface method IEnumerator<ExcelNamedRange> GetEnumerator()
- /// </summary>
- /// <returns></returns>
- public IEnumerator<ExcelNamedRange> GetEnumerator() {
- return _list.GetEnumerator();
- }
-
- /// <summary>
- /// Implement interface method IEnumeratable GetEnumerator()
- /// </summary>
- /// <returns></returns>
- IEnumerator IEnumerable.GetEnumerator() {
- return _list.GetEnumerator();
- }
-
- internal void Clear() {
- while (Count > 0) {
- Remove(_list[0].Name);
- }
- }
-}
diff --git a/EPPlus/ExcelPackage.cs b/EPPlus/ExcelPackage.cs
deleted file mode 100644
index 7d12a0e..0000000
--- a/EPPlus/ExcelPackage.cs
+++ /dev/null
@@ -1,215 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Starnuto Di Topo & Jan Källman Added stream constructors
- * and Load method Save as
- * stream 2010-03-14
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.IO;
-using System.Xml;
-using OfficeOpenXml.Packaging;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Represents an Excel XLSX file package.
-/// This is the top-level object to access all parts of the document.
-/// </summary>
-public sealed class ExcelPackage {
- /// <summary>
- /// Extention Schema types
- /// </summary>
- internal const string _schemaXmlExtension = "application/xml";
- internal const string _schemaRelsExtension =
- "application/vnd.openxmlformats-package.relationships+xml";
-
- /// <summary>
- /// Main Xml schema name
- /// </summary>
- internal const string _schemaMain = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
-
- /// <summary>
- /// Relationship schema name
- /// </summary>
- internal const string _schemaRelationships =
- "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
-
- internal const string _schemaMicrosoftVml = "urn:schemas-microsoft-com:vml";
- internal const string _schemaMicrosoftOffice = "urn:schemas-microsoft-com:office:office";
- internal const string _schemaMicrosoftExcel = "urn:schemas-microsoft-com:office:excel";
-
- internal const string _schemaChart = "http://schemas.openxmlformats.org/drawingml/2006/chart";
- internal const string _schemaHyperlink =
- "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
- internal const string _schemaComment =
- "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
-
- //Office properties
- internal const string _schemaCore =
- "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
- internal const string _schemaExtended =
- "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
- internal const string _schemaCustom =
- "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";
- internal const string _schemaDc = "http://purl.org/dc/elements/1.1/";
- internal const string _schemaDcTerms = "http://purl.org/dc/terms/";
- internal const string _schemaDcmiType = "http://purl.org/dc/dcmitype/";
- internal const string _schemaXsi = "http://www.w3.org/2001/XMLSchema-instance";
- internal const string _schemaVt =
- "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes";
-
- internal const string _contentTypeSharedString =
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml";
-
- /// <summary>
- /// Maximum number of columns in a worksheet (16384).
- /// </summary>
- public const int MaxColumns = 16384;
-
- /// <summary>
- /// Maximum number of rows in a worksheet (1048576).
- /// </summary>
- public const int MaxRows = 1048576;
-
- /// <summary>
- /// Create a new, empty package.
- /// </summary>
- public ExcelPackage() {
- Package = new();
- Workbook = new(this, CreateDefaultNsm());
- }
-
- /// <summary>
- /// Create a new instance of the ExcelPackage class based on an existing file.
- /// </summary>
- public ExcelPackage(FileInfo newFile) {
- using var inputStream = newFile.OpenRead();
- Package = new(inputStream);
- Workbook = new(this, CreateDefaultNsm());
- }
-
- /// <summary>
- /// Create a new instance of the ExcelPackage class based on a stream.
- /// </summary>
- public ExcelPackage(Stream newStream) {
- Package = new(newStream);
- Workbook = new(this, CreateDefaultNsm());
- }
-
- internal ZipPackage Package { get; }
-
- /// <summary>
- /// Returns a reference to the workbook component within the package.
- /// All worksheets and cells can be accessed through the workbook.
- /// </summary>
- public ExcelWorkbook Workbook { get; }
-
- private XmlNamespaceManager CreateDefaultNsm() {
- // Create a NamespaceManager to handle the default namespace,
- // and create a prefix for the default namespace:
- NameTable nt = new NameTable();
- var ns = new XmlNamespaceManager(nt);
- ns.AddNamespace(string.Empty, _schemaMain);
- ns.AddNamespace("d", _schemaMain);
- ns.AddNamespace("r", _schemaRelationships);
- ns.AddNamespace("c", _schemaChart);
- ns.AddNamespace("vt", _schemaVt);
- // extended properties (app.xml)
- ns.AddNamespace("xp", _schemaExtended);
- // custom properties
- ns.AddNamespace("ctp", _schemaCustom);
- // core properties
- ns.AddNamespace("cp", _schemaCore);
- // core property namespaces
- ns.AddNamespace("dc", _schemaDc);
- ns.AddNamespace("dcterms", _schemaDcTerms);
- ns.AddNamespace("dcmitype", _schemaDcmiType);
- ns.AddNamespace("xsi", _schemaXsi);
- return ns;
- }
-
- internal XmlDocument GetXmlDocument(Uri uri) {
- var xmlDocument = new XmlDocument();
- var part = Package.GetPart(uri);
- XmlHelper.LoadXmlSafe(xmlDocument, part.GetStream());
- part.SaveHandler = writer => xmlDocument.Save(writer);
- return xmlDocument;
- }
-
- internal ZipPackageRelationship CreateXmlDocument(
- Uri uri,
- string contentType,
- string relationship,
- XmlDocument newDoc) {
- Package.CreatePart(uri, contentType, newDoc.Save);
- return Package.CreateRelationship(
- UriHelper.GetRelativeUri(new("/xl", UriKind.Relative), uri),
- TargetMode.Internal,
- relationship);
- }
-
- internal XmlDocument GetOrCreateXmlDocument(
- Uri uri,
- string contentType,
- string relationship,
- Func<XmlDocument> createDocument) {
- if (Package.PartExists(uri)) {
- return GetXmlDocument(uri);
- }
- var newDoc = createDocument();
- CreateXmlDocument(uri, contentType, relationship, newDoc);
- return newDoc;
- }
-
- internal XmlDocument GetOrCreateXmlDocument(
- Uri uri,
- string contentType,
- string relationship,
- string initialDocumentXml) =>
- GetOrCreateXmlDocument(
- uri,
- contentType,
- relationship,
- () => {
- var emptyDocument = new XmlDocument();
- emptyDocument.LoadXml(initialDocumentXml);
- return emptyDocument;
- });
-
- public byte[] GetAsByteArray() {
- var result = new MemoryStream();
- Workbook.Save();
- Package.Save(result);
- return result.ToArray();
- }
-}
diff --git a/EPPlus/ExcelProtectedRange.cs b/EPPlus/ExcelProtectedRange.cs
deleted file mode 100644
index f89c544..0000000
--- a/EPPlus/ExcelProtectedRange.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System.Xml;
-
-namespace OfficeOpenXml;
-
-public class ExcelProtectedRange : XmlHelper {
- public string Name => GetXmlNodeString("@name");
-
- private ExcelAddress _address;
-
- public ExcelAddress Address => _address ??= new(GetXmlNodeString("@sqref"));
-
- internal ExcelProtectedRange(XmlNamespaceManager ns, XmlNode topNode)
- : base(ns, topNode) {}
-}
diff --git a/EPPlus/ExcelProtectedRangeCollection.cs b/EPPlus/ExcelProtectedRangeCollection.cs
deleted file mode 100644
index 0b95ccf..0000000
--- a/EPPlus/ExcelProtectedRangeCollection.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-using System.Xml;
-
-namespace OfficeOpenXml;
-
-public class ExcelProtectedRangeCollection : XmlHelper, IEnumerable<ExcelProtectedRange> {
- internal ExcelProtectedRangeCollection(XmlNamespaceManager nsm, XmlNode topNode)
- : base(nsm, topNode) {
- foreach (XmlNode protectedRangeNode in topNode.SelectNodes(
- "d:protectedRanges/d:protectedRange",
- nsm)) {
- if (!(protectedRangeNode is XmlElement)) {
- continue;
- }
- _baseList.Add(new(nsm, topNode));
- }
- }
-
- private readonly List<ExcelProtectedRange> _baseList = new();
-
- public ExcelProtectedRange this[int index] => _baseList[index];
-
- IEnumerator<ExcelProtectedRange> IEnumerable<ExcelProtectedRange>.GetEnumerator() {
- return _baseList.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- return _baseList.GetEnumerator();
- }
-}
diff --git a/EPPlus/ExcelProtection.cs b/EPPlus/ExcelProtection.cs
deleted file mode 100644
index 5d0c943..0000000
--- a/EPPlus/ExcelProtection.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-/*******************************************************************************
- * 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 10-AUG-2010
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Collections.Immutable;
-using System.Xml;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Sets protection on the workbook level
-///<seealso cref="ExcelEncryption"/>
-///<seealso cref="ExcelSheetProtection"/>
-/// </summary>
-public class ExcelProtection : XmlHelper {
- protected override ImmutableArray<string> SchemaNodeOrder =>
- ExcelWorkbook.WorkbookSchemaNodeOrder;
-
- internal ExcelProtection(XmlNamespaceManager ns, XmlNode topNode)
- : base(ns, topNode) {}
-
- private const string _lockStructurePath = "d:workbookProtection/@lockStructure";
-
- /// <summary>
- /// Locks the structure,which prevents users from adding or deleting worksheets or from displaying hidden worksheets.
- /// </summary>
- public bool LockStructure {
- get => GetXmlNodeBool(_lockStructurePath, false);
- set => SetXmlNodeBool(_lockStructurePath, value, false);
- }
-
- private const string _lockWindowsPath = "d:workbookProtection/@lockWindows";
-
- /// <summary>
- /// Locks the position of the workbook window.
- /// </summary>
- public bool LockWindows {
- get => GetXmlNodeBool(_lockWindowsPath, false);
- set => SetXmlNodeBool(_lockWindowsPath, value, false);
- }
-
- private const string _lockRevisionPath = "d:workbookProtection/@lockRevision";
-
- /// <summary>
- /// Lock the workbook for revision
- /// </summary>
- public bool LockRevision {
- get => GetXmlNodeBool(_lockRevisionPath, false);
- set => SetXmlNodeBool(_lockRevisionPath, value, false);
- }
-}
diff --git a/EPPlus/ExcelRange.cs b/EPPlus/ExcelRange.cs
deleted file mode 100644
index 92352fc..0000000
--- a/EPPlus/ExcelRange.cs
+++ /dev/null
@@ -1,123 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// A range of cells.
-/// </summary>
-public class ExcelRange : ExcelRangeBase {
- internal ExcelRange(ExcelWorksheet sheet)
- : base(sheet) {}
-
- internal ExcelRange(ExcelWorksheet sheet, string address)
- : base(sheet, address) {}
-
- internal ExcelRange(ExcelWorksheet sheet, int fromRow, int fromCol, int toRow, int toCol)
- : base(sheet) {
- _fromRow = fromRow;
- _fromCol = fromCol;
- _toRow = toRow;
- _toCol = toCol;
- }
-
- /// <summary>
- /// Access the range using an address
- /// </summary>
- /// <param name="address">The address</param>
- /// <returns>A range object</returns>
- public ExcelRange this[string address] {
- get {
- if (_worksheet.Names.ContainsKey(address)) {
- if (_worksheet.Names[address].IsName) {
- return null;
- }
- Address = _worksheet.Names[address].Address;
- } else {
- Address = address;
- }
- return this;
- }
- }
-
- /// <summary>
- /// Access a single cell
- /// </summary>
- /// <param name="row">The row</param>
- /// <param name="col">The column</param>
- /// <returns>A range object</returns>
- public ExcelRange this[int row, int col] {
- get {
- ValidateRowCol(row, col);
-
- _fromCol = col;
- _fromRow = row;
- _toCol = col;
- _toRow = row;
- Address = GetAddress(_fromRow, _fromCol);
- return this;
- }
- }
-
- /// <summary>
- /// Access a range of cells
- /// </summary>
- /// <param name="fromRow">Start row</param>
- /// <param name="fromCol">Start column</param>
- /// <param name="toRow">End Row</param>
- /// <param name="toCol">End Column</param>
- /// <returns></returns>
- public ExcelRange this[int fromRow, int fromCol, int toRow, int toCol] {
- get {
- ValidateRowCol(fromRow, fromCol);
- ValidateRowCol(toRow, toCol);
-
- _fromCol = fromCol;
- _fromRow = fromRow;
- _toCol = toCol;
- _toRow = toRow;
- Address = GetAddress(_fromRow, _fromCol, _toRow, _toCol);
- return this;
- }
- }
-
- private static void ValidateRowCol(int row, int col) {
- if (row < 1 || row > ExcelPackage.MaxRows) {
- throw (new ArgumentException("Row out of range"));
- }
- if (col < 1 || col > ExcelPackage.MaxColumns) {
- throw (new ArgumentException("Column out of range"));
- }
- }
-}
diff --git a/EPPlus/ExcelRangeBase.cs b/EPPlus/ExcelRangeBase.cs
deleted file mode 100644
index 9c82531..0000000
--- a/EPPlus/ExcelRangeBase.cs
+++ /dev/null
@@ -1,1535 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2010-01-28
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- * Eyal Seagull Conditional Formatting 2012-04-03
- *******************************************************************************/
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Security;
-using System.Text;
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting;
-using OfficeOpenXml.DataValidation;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-using OfficeOpenXml.Style;
-using OfficeOpenXml.Style.XmlAccess;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// A range of cells
-/// </summary>
-public class ExcelRangeBase
- : ExcelAddress,
- IExcelCell,
- IDisposable,
- IEnumerable<ExcelRangeBase>,
- IEnumerator<ExcelRangeBase> {
- /// <summary>
- /// Reference to the worksheet
- /// </summary>
- protected ExcelWorksheet _worksheet;
- internal ExcelWorkbook _workbook;
-
- private delegate void ChangePropHandler(SetValueHandler method, object value);
-
- private delegate void SetValueHandler(object value, int row, int col);
-
- private ChangePropHandler _changePropMethod;
- private int _styleID;
-
- private class CopiedCell {
- internal int Row { get; set; }
-
- internal int Column { get; set; }
-
- internal object Value { get; set; }
-
- internal string Type { get; set; }
-
- internal object Formula { get; set; }
-
- internal int? StyleID { get; set; }
-
- internal Uri HyperLink { get; set; }
-
- internal ExcelComment Comment { get; set; }
-
- internal Byte Flag { get; set; }
- }
-
- //private class CopiedFlag
- //{
- // internal int Row { get; set; }
- // internal int Column { get; set; }
- // internal Byte Flag { get; set; }
- //}
-
-
- internal ExcelRangeBase(ExcelWorksheet worksheet) {
- _worksheet = worksheet;
- _ws = _worksheet.Name;
- _workbook = _worksheet.Workbook;
- AddressChange += ExcelRangeBase_AddressChange;
- SetDelegate();
- }
-
- private void ExcelRangeBase_AddressChange(object sender, EventArgs e) {
- if (Table != null) {
- SetRcFromTable(_workbook, null);
- }
- SetDelegate();
- }
-
- internal ExcelRangeBase(ExcelWorksheet worksheet, string address)
- : base(worksheet == null ? "" : worksheet.Name, address) {
- _worksheet = worksheet;
- _workbook = worksheet.Workbook;
- SetRcFromTable(_workbook, null);
- if (string.IsNullOrEmpty(_ws)) {
- _ws = _worksheet == null ? "" : _worksheet.Name;
- }
- AddressChange += ExcelRangeBase_AddressChange;
- SetDelegate();
- }
-
- internal ExcelRangeBase(ExcelWorkbook wb, ExcelWorksheet xlWorksheet, string address, bool isName)
- : base(xlWorksheet == null ? "" : xlWorksheet.Name, address, isName) {
- SetRcFromTable(wb, null);
- _worksheet = xlWorksheet;
- _workbook = wb;
- if (string.IsNullOrEmpty(_ws)) {
- _ws = xlWorksheet?.Name;
- }
- AddressChange += ExcelRangeBase_AddressChange;
- SetDelegate();
- }
-
- ~ExcelRangeBase() {
- //this.AddressChange -= new EventHandler(ExcelRangeBase_AddressChange);
- }
-
- private void SetDelegate() {
- if (_fromRow == -1) {
- _changePropMethod = SetUnknown;
- }
- //Single cell
- else if (_fromRow == _toRow && _fromCol == _toCol && Addresses == null) {
- _changePropMethod = SetSingle;
- }
- //Range (ex A1:A2)
- else if (Addresses == null) {
- _changePropMethod = SetRange;
- }
- //Multi Range (ex A1:A2,C1:C2)
- else {
- _changePropMethod = SetMultiRange;
- }
- }
-
- /// <summary>
- /// We dont know the address yet. Set the delegate first time a property is set.
- /// </summary>
- /// <param name="valueMethod"></param>
- /// <param name="value"></param>
- private void SetUnknown(SetValueHandler valueMethod, object value) {
- //Address is not set use, selected range
- if (_fromRow == -1) {
- SetToSelectedRange();
- }
- SetDelegate();
- _changePropMethod(valueMethod, value);
- }
-
- /// <summary>
- /// Set a single cell
- /// </summary>
- /// <param name="valueMethod"></param>
- /// <param name="value"></param>
- private void SetSingle(SetValueHandler valueMethod, object value) {
- valueMethod(value, _fromRow, _fromCol);
- }
-
- /// <summary>
- /// Set a range
- /// </summary>
- /// <param name="valueMethod"></param>
- /// <param name="value"></param>
- private void SetRange(SetValueHandler valueMethod, object value) {
- SetValueAddress(this, valueMethod, value);
- }
-
- /// <summary>
- /// Set a multirange (A1:A2,C1:C2)
- /// </summary>
- /// <param name="valueMethod"></param>
- /// <param name="value"></param>
- private void SetMultiRange(SetValueHandler valueMethod, object value) {
- SetValueAddress(this, valueMethod, value);
- foreach (var address in Addresses) {
- SetValueAddress(address, valueMethod, value);
- }
- }
-
- /// <summary>
- /// Set the property for an address
- /// </summary>
- /// <param name="address"></param>
- /// <param name="valueMethod"></param>
- /// <param name="value"></param>
- private void SetValueAddress(ExcelAddress address, SetValueHandler valueMethod, object value) {
- IsRangeValid("");
- if (_fromRow == 1
- && _fromCol == 1
- && _toRow == ExcelPackage.MaxRows
- && _toCol
- == ExcelPackage.MaxColumns) //Full sheet (ex ws.Cells.Value=0). Set value for A1 only to avoid hanging
- {
- throw (new ArgumentException(
- "Can't reference all cells. Please use the indexer to set the range"));
- }
- for (int col = address.Start.Column; col <= address.End.Column; col++) {
- for (int row = address.Start.Row; row <= address.End.Row; row++) {
- valueMethod(value, row, col);
- }
- }
- }
-
- private void Set_StyleID(object value, int row, int col) {
- _worksheet._styles.SetValue(row, col, (int)value);
- }
-
- private void Set_Value(object value, int row, int col) {
- //ExcelCell c = _worksheet.Cell(row, col);
- var sfi = _worksheet._formulas.GetValue(row, col);
- if (sfi is int) {
- SplitFormulas(_worksheet.Cells[row, col]);
- }
- if (sfi != null) {
- _worksheet._formulas.SetValue(row, col, string.Empty);
- }
- _worksheet._values.SetValue(row, col, value);
- }
-
- private void Set_Formula(object value, int row, int col) {
- //ExcelCell c = _worksheet.Cell(row, col);
- var f = _worksheet._formulas.GetValue(row, col);
- if (f is int i && i >= 0) {
- SplitFormulas(_worksheet.Cells[row, col]);
- }
-
- string formula = (value == null ? string.Empty : value.ToString());
- if (formula == string.Empty) {
- _worksheet._formulas.SetValue(row, col, string.Empty);
- } else {
- if (formula[0] == '=') {
- value = formula.Substring(1, formula.Length - 1); // remove any starting equalsign.
- }
- _worksheet._formulas.SetValue(row, col, formula);
- _worksheet._values.SetValue(row, col, null);
- }
- }
-
- /// <summary>
- /// Handles shared formulas
- /// </summary>
- /// <param name="value">The formula</param>
- /// <param name="address">The address of the formula</param>
- /// <param name="isArray">If the forumla is an array formula.</param>
- private void Set_SharedFormula(string value, ExcelAddress address, bool isArray) {
- if (_fromRow == 1
- && _fromCol == 1
- && _toRow == ExcelPackage.MaxRows
- && _toCol
- == ExcelPackage.MaxColumns) //Full sheet (ex ws.Cells.Value=0). Set value for A1 only to avoid hanging
- {
- throw (new InvalidOperationException("Can't set a formula for the entire worksheet"));
- }
- if (address.Start.Row == address.End.Row
- && address.Start.Column == address.End.Column
- && !isArray) //is it really a shared formula? Arrayformulas can be one cell only
- {
- //Nope, single cell. Set the formula
- Set_Formula(value, address.Start.Row, address.Start.Column);
- return;
- }
- //RemoveFormuls(address);
- CheckAndSplitSharedFormula(address);
- ExcelWorksheet.Formulas f = new ExcelWorksheet.Formulas(SourceCodeTokenizer.Default);
- f.Formula = value;
- f.Index = _worksheet.GetMaxShareFunctionIndex(isArray);
- f.Address = address.FirstAddress;
- f.StartCol = address.Start.Column;
- f.StartRow = address.Start.Row;
- f.IsArray = isArray;
-
- _worksheet._sharedFormulas.Add(f.Index, f);
- //_worksheet.Cell(address.Start.Row, address.Start.Column).SharedFormulaID = f.Index;
- //_worksheet.Cell(address.Start.Row, address.Start.Column).Formula = value;
-
- for (int col = address.Start.Column; col <= address.End.Column; col++) {
- for (int row = address.Start.Row; row <= address.End.Row; row++) {
- //_worksheet.Cell(row, col).SharedFormulaID = f.Index;
- _worksheet._formulas.SetValue(row, col, f.Index);
- _worksheet._values.SetValue(row, col, null);
- }
- }
- }
-
- private void Set_HyperLink(object value, int row, int col) {
- //_worksheet.Cell(row, col).Hyperlink = value as Uri;
- if (value is Uri uri) {
- _worksheet._hyperLinks.SetValue(row, col, uri);
-
- if (uri is ExcelHyperLink link) {
- _worksheet._values.SetValue(row, col, link.Display);
- } else {
- _worksheet._values.SetValue(row, col, uri.OriginalString);
- }
- } else {
- _worksheet._hyperLinks.SetValue(row, col, null);
- _worksheet._values.SetValue(row, col, null);
- }
- }
-
- private void Set_IsArrayFormula(object value, int row, int col) {
- _worksheet._flags.SetFlagValue(row, col, (bool)value, CellFlags.ArrayFormula);
- }
-
- private void Set_IsRichText(object value, int row, int col) {
- //_worksheet.Cell(row, col).IsRichText = (bool)value;
- _worksheet._flags.SetFlagValue(row, col, (bool)value, CellFlags.RichText);
- }
-
- private void Exists_Comment(object value, int row, int col) {
- ulong cellId = GetCellId(_worksheet.SheetID, row, col);
- if (_worksheet.Comments._comments.ContainsKey(cellId)) {
- throw (new InvalidOperationException(
- string.Format(
- "Cell {0} already contain a comment.",
- new ExcelCellAddress(row, col).Address)));
- }
- }
-
- private void SetToSelectedRange() {
- if (_worksheet.View.SelectedRange == "") {
- Address = "A1";
- } else {
- Address = _worksheet.View.SelectedRange;
- }
- }
-
- private void IsRangeValid(string type) {
- if (_fromRow <= 0) {
- if (_address == "") {
- SetToSelectedRange();
- } else {
- if (type == "") {
- throw (new InvalidOperationException(
- string.Format("Range is not valid for this operation: {0}", _address)));
- }
- throw (new InvalidOperationException(
- string.Format("Range is not valid for {0} : {1}", type, _address)));
- }
- }
- }
-
- /// <summary>
- /// The styleobject for the range.
- /// </summary>
- public ExcelStyle Style {
- get {
- IsRangeValid("styling");
- int s = 0;
- if (!_worksheet._styles.Exists(
- _fromRow,
- _fromCol,
- ref s)) //Cell exists
- {
- if (!_worksheet._styles.Exists(
- _fromRow,
- 0,
- ref s)) //No, check Row style
- {
- var c = Worksheet.GetColumn(_fromCol);
- if (c == null) {
- s = 0;
- } else {
- s = c.StyleID;
- }
- }
- }
- return _worksheet.Workbook.Styles.GetStyleObject(s, _worksheet.PositionID, Address);
- }
- }
-
- /// <summary>
- /// The named style
- /// </summary>
- public string StyleName {
- get {
- IsRangeValid("styling");
- int xfId;
- if (_fromRow == 1 && _toRow == ExcelPackage.MaxRows) {
- xfId = GetColumnStyle(_fromCol);
- } else if (_fromCol == 1 && _toCol == ExcelPackage.MaxColumns) {
- xfId = 0;
- if (!_worksheet._styles.Exists(_fromRow, 0, ref xfId)) {
- xfId = GetColumnStyle(_fromCol);
- }
- } else {
- xfId = 0;
- if (!_worksheet._styles.Exists(_fromRow, _fromCol, ref xfId)) {
- if (!_worksheet._styles.Exists(_fromRow, 0, ref xfId)) {
- xfId = GetColumnStyle(_fromCol);
- }
- }
- }
- int nsId;
- if (xfId <= 0) {
- nsId = Style.Styles.CellXfs[0].XfId;
- } else {
- nsId = Style.Styles.CellXfs[xfId].XfId;
- }
- foreach (var ns in Style.Styles.NamedStyles) {
- if (ns.StyleXfId == nsId) {
- return ns.Name;
- }
- }
-
- return "";
- }
- set {
- _styleID = _worksheet.Workbook.Styles.GetStyleIdFromName(value);
- int col = _fromCol;
- if (_fromRow == 1
- && _toRow
- == ExcelPackage.MaxRows) //Full column
- {
- ExcelColumn column;
- //Get the startcolumn
- //ulong colID = ExcelColumn.GetColumnID(_worksheet.SheetID, column);
- var c = _worksheet.GetValue(0, _fromCol);
- if (c == null) {
- column = _worksheet.Column(_fromCol);
- //if (_worksheet._values.PrevCell(ref row, ref col))
- //{
- // var prevCol = (ExcelColumn)_worksheet._values.GetValue(row, col);
- // column = prevCol.Clone(_worksheet, column);
- // prevCol.ColumnMax = column - 1;
- //}
- } else {
- column = (ExcelColumn)c;
- }
-
- column.StyleName = value;
- column.StyleID = _styleID;
-
- //var index = _worksheet._columns.IndexOf(colID);
- var cols = new CellsStoreEnumerator<object>(_worksheet._values, 0, _fromCol + 1, 0, _toCol);
- if (cols.Next()) {
- col = _fromCol;
- while (column.ColumnMin <= _toCol) {
- if (column.ColumnMax > _toCol) {
- var newCol = _worksheet.CopyColumn(column, _toCol + 1, column.ColumnMax);
- column.ColumnMax = _toCol;
- }
-
- column._styleName = value;
- column.StyleID = _styleID;
-
- if (cols.Value == null) {
- break;
- }
- var nextCol = (ExcelColumn)cols.Value;
- if (column.ColumnMax < nextCol.ColumnMax - 1) {
- column.ColumnMax = nextCol.ColumnMax - 1;
- }
- column = nextCol;
- cols.Next();
- }
- }
- if (column.ColumnMax < _toCol) {
- column.ColumnMax = _toCol;
- }
- //if (column.ColumnMin == column)
- //{
- // column.ColumnMax = _toCol;
- //}
- //else if (column._columnMax < _toCol)
- //{
- // var newCol = _worksheet.Column(column._columnMax + 1) as ExcelColumn;
- // newCol._columnMax = _toCol;
-
- // newCol._styleID = _styleID;
- // newCol._styleName = value;
- //}
- if (_fromCol == 1
- && _toCol
- == ExcelPackage.MaxColumns) //FullRow
- {
- var rows = new CellsStoreEnumerator<object>(
- _worksheet._values,
- 1,
- 0,
- ExcelPackage.MaxRows,
- 0);
- rows.Next();
- while (rows.Value != null) {
- _worksheet._styles.SetValue(rows.Row, 0, _styleID);
- if (!rows.Next()) {
- break;
- }
- }
- }
- } else if (_fromCol == 1
- && _toCol
- == ExcelPackage.MaxColumns) //FullRow
- {
- for (int r = _fromRow; r <= _toRow; r++) {
- _worksheet.Row(r)._styleName = value;
- _worksheet.Row(r).StyleID = _styleID;
- }
- }
-
- if (!((_fromRow == 1 && _toRow == ExcelPackage.MaxRows)
- || (_fromCol == 1
- && _toCol
- == ExcelPackage.MaxColumns))) //Cell specific
- {
- for (int c = _fromCol; c <= _toCol; c++) {
- for (int r = _fromRow; r <= _toRow; r++) {
- _worksheet._styles.SetValue(r, c, _styleID);
- }
- }
- } else //Only set name on created cells. (uncreated cells is set on full row or full column).
- {
- var cells = new CellsStoreEnumerator<object>(
- _worksheet._values,
- _fromRow,
- _fromCol,
- _toRow,
- _toCol);
- while (cells.Next()) {
- _worksheet._styles.SetValue(cells.Row, cells.Column, _styleID);
- }
- }
- //_changePropMethod(Set_StyleName, value);
- }
- }
-
- private int GetColumnStyle(int col) {
- object c = null;
- if (_worksheet._values.Exists(0, col, ref c)) {
- return (c as ExcelColumn).StyleID;
- }
- int row = 0;
- if (_worksheet._values.PrevCell(ref row, ref col)) {
- var column = _worksheet._values.GetValue(row, col) as ExcelColumn;
- if (column.ColumnMax >= col) {
- return _worksheet._styles.GetValue(row, col);
- }
- }
- return 0;
- }
-
- /// <summary>
- /// The style ID.
- /// It is not recomended to use this one. Use Named styles as an alternative.
- /// If you do, make sure that you use the Style.UpdateXml() method to update any new styles added to the workbook.
- /// </summary>
- public int StyleID {
- get {
- int s = 0;
- if (!_worksheet._styles.Exists(_fromRow, _fromCol, ref s)) {
- if (!_worksheet._styles.Exists(_fromRow, 0, ref s)) {
- s = _worksheet._styles.GetValue(0, _fromCol);
- }
- }
- return s;
- }
- set => _changePropMethod(Set_StyleID, value);
- }
-
- /// <summary>
- /// Set the range to a specific value
- /// </summary>
- public object Value {
- get {
- if (IsName) {
- if (_worksheet == null) {
- return _workbook._names[_address].NameValue;
- }
- return _worksheet.Names[_address].NameValue;
- }
- if (_fromRow == _toRow && _fromCol == _toCol) {
- return _worksheet.GetValue(_fromRow, _fromCol);
- }
- return GetValueArray();
- }
- set {
- if (IsName) {
- if (_worksheet == null) {
- _workbook._names[_address].NameValue = value;
- } else {
- _worksheet.Names[_address].NameValue = value;
- }
- } else {
- _changePropMethod(Set_Value, value);
- }
- }
- }
-
- private object GetValueArray() {
- ExcelAddressBase addr;
- if (_fromRow == 1
- && _fromCol == 1
- && _toRow == ExcelPackage.MaxRows
- && _toCol == ExcelPackage.MaxColumns) {
- addr = _worksheet.Dimension;
- if (addr == null) {
- return null;
- }
- } else {
- addr = this;
- }
- object[,] v = new object[addr._toRow - addr._fromRow + 1, addr._toCol - addr._fromCol + 1];
-
- for (int col = addr._fromCol; col <= addr._toCol; col++) {
- for (int row = addr._fromRow; row <= addr._toRow; row++) {
- if (_worksheet._values.Exists(row, col)) {
- if (_worksheet._flags.GetFlagValue(row, col, CellFlags.RichText)) {
- v[row - addr._fromRow, col - addr._fromCol] = GetRichText(row, col).Text;
- } else {
- v[row - addr._fromRow, col - addr._fromCol] = _worksheet._values.GetValue(row, col);
- }
- }
- }
- }
- return v;
- }
-
- /// <summary>
- /// Returns the formatted value.
- /// </summary>
- public string Text => GetFormattedText(false);
-
- private string GetFormattedText(bool forWidthCalc) {
- object v = Value;
- if (v == null) {
- return "";
- }
- var styles = Worksheet.Workbook.Styles;
- var nfId = styles.CellXfs[StyleID].NumberFormatId;
- ExcelNumberFormatXml.ExcelFormatTranslator nf = null;
- for (int i = 0; i < styles.NumberFormats.Count; i++) {
- if (nfId == styles.NumberFormats[i].NumFmtId) {
- nf = styles.NumberFormats[i].FormatTranslator;
- break;
- }
- }
-
- string format,
- textFormat;
- if (forWidthCalc) {
- format = nf.NetFormatForWidth;
- textFormat = nf.NetTextFormatForWidth;
- } else {
- format = nf.NetFormat;
- textFormat = nf.NetTextFormat;
- }
-
- return FormatValue(v, nf, format, textFormat);
- }
-
- internal static string FormatValue(
- object v,
- ExcelNumberFormatXml.ExcelFormatTranslator nf,
- string format,
- string textFormat) {
- if (v is decimal || v.GetType().IsPrimitive) {
- double d;
- try {
- d = Convert.ToDouble(v);
- } catch {
- return "";
- }
-
- if (nf.DataType == ExcelNumberFormatXml.eFormatType.Number) {
- if (string.IsNullOrEmpty(nf.FractionFormat)) {
- return d.ToString(format, nf.Culture);
- }
- return nf.FormatFraction(d);
- }
- if (nf.DataType == ExcelNumberFormatXml.eFormatType.DateTime) {
- var date = DateTime.FromOADate(d);
- return date.ToString(format, nf.Culture);
- }
- } else if (v is DateTime time) {
- if (nf.DataType == ExcelNumberFormatXml.eFormatType.DateTime) {
- return time.ToString(format, nf.Culture);
- }
- double d = time.ToOADate();
- if (string.IsNullOrEmpty(nf.FractionFormat)) {
- return d.ToString(format, nf.Culture);
- }
- return nf.FormatFraction(d);
- } else if (v is TimeSpan span) {
- if (nf.DataType == ExcelNumberFormatXml.eFormatType.DateTime) {
- return new DateTime(span.Ticks).ToString(format, nf.Culture);
- }
- double d = (new DateTime(span.Ticks)).ToOADate();
- if (string.IsNullOrEmpty(nf.FractionFormat)) {
- return d.ToString(format, nf.Culture);
- }
- return nf.FormatFraction(d);
- } else {
- if (textFormat == "") {
- return v.ToString();
- }
- return string.Format(textFormat, v);
- }
- return v.ToString();
- }
-
- /// <summary>
- /// Gets or sets a formula for a range.
- /// </summary>
- public string Formula {
- get {
- if (IsName) {
- if (_worksheet == null) {
- return _workbook._names[_address].NameFormula;
- }
- return _worksheet.Names[_address].NameFormula;
- }
- return _worksheet.GetFormula(_fromRow, _fromCol);
- }
- set {
- if (IsName) {
- if (_worksheet == null) {
- _workbook._names[_address].NameFormula = value;
- } else {
- _worksheet.Names[_address].NameFormula = value;
- }
- } else {
- if (value == null || value.Trim() == "") {
- //Set the cells to null
- Value = null;
- } else if (_fromRow == _toRow && _fromCol == _toCol) {
- Set_Formula(value, _fromRow, _fromCol);
- } else {
- Set_SharedFormula(value, this, false);
- if (Addresses != null) {
- foreach (var address in Addresses) {
- Set_SharedFormula(value, address, false);
- }
- }
- }
- }
- }
- }
-
- /// <summary>
- /// Gets or Set a formula in R1C1 format.
- /// </summary>
- public string FormulaR1C1 {
- get {
- IsRangeValid("FormulaR1C1");
- return _worksheet.GetFormulaR1C1(_fromRow, _fromCol);
- }
- set {
- IsRangeValid("FormulaR1C1");
- if (value.Length > 0 && value[0] == '=') {
- value = value.Substring(1, value.Length - 1); // remove any starting equalsign.
- }
-
- if (value == null || value.Trim() == "") {
- //Set the cells to null
- _worksheet.Cells[TranslateFromR1C1(value, _fromRow, _fromCol)].Value = null;
- } else if (Addresses == null) {
- Set_SharedFormula(TranslateFromR1C1(value, _fromRow, _fromCol), this, false);
- } else {
- Set_SharedFormula(
- TranslateFromR1C1(value, _fromRow, _fromCol),
- new(WorkSheet, FirstAddress),
- false);
- foreach (var address in Addresses) {
- Set_SharedFormula(
- TranslateFromR1C1(value, address.Start.Row, address.Start.Column),
- address,
- false);
- }
- }
- }
- }
-
- /// <summary>
- /// Gets or Set a formula in R1C1 format.
- ///
- public string FormulaR1C1_V1 {
- get {
- IsRangeValid("FormulaR1C1");
- return _worksheet.GetFormulaR1C1_V1(_fromRow, _fromCol);
- }
- }
-
- public string ArrayFormulaAddress {
- get {
- IsRangeValid("FormulaR1C1");
- return _worksheet.GetArrayFormulaAddress(_fromRow, _fromCol);
- }
- }
-
- /// <summary>
- /// Set the hyperlink property for a range of cells
- /// </summary>
- public Uri Hyperlink {
- get {
- IsRangeValid("formulaR1C1");
- return _worksheet._hyperLinks.GetValue(_fromRow, _fromCol);
- }
- set => _changePropMethod(Set_HyperLink, value);
- }
-
- /// <summary>
- /// If the cells in the range are merged.
- /// </summary>
- public bool Merge {
- get {
- IsRangeValid("merging");
- for (int col = _fromCol; col <= _toCol; col++) {
- for (int row = _fromRow; row <= _toRow; row++) {
- if (_worksheet.MergedCells[row, col] == null) {
- return false;
- }
- //if (!_worksheet._flags.GetFlagValue(row, col, CellFlags.Merged))
- //{
- // return false;
- //}
- }
- }
- return true;
- }
- set {
- IsRangeValid("merging");
- //SetMerge(value, FirstAddress);
- if (value) {
- _worksheet.MergedCells.Add(new(FirstAddress), true);
- if (Addresses != null) {
- foreach (var address in Addresses) {
- _worksheet.MergedCells.Add(address, true);
- //SetMerge(value, address._address);
- }
- }
- } else {
- _worksheet.MergedCells.Clear(this);
- if (Addresses != null) {
- foreach (var address in Addresses) {
- _worksheet.MergedCells.Clear(address);
- ;
- }
- }
- }
- }
- }
-
- //private void SetMerge(bool value, string address)
- //{
- // if (!value)
- // {
- // if (_worksheet.MergedCells.List.Contains(address))
- // {
- // SetCellMerge(false, address);
- // _worksheet.MergedCells.List.Remove(address);
- // }
- // else if (!CheckMergeDiff(false, address))
- // {
- // throw (new Exception("Range is not fully merged.Specify the exact range"));
- // }
- // }
- // else
- // {
- // if (CheckMergeDiff(false, address))
- // {
- // SetCellMerge(true, address);
- // _worksheet.MergedCells.List.Add(address);
- // }
- // else
- // {
- // if (!_worksheet.MergedCells.List.Contains(address))
- // {
- // throw (new Exception("Cells are already merged"));
- // }
- // }
- // }
- //}
- /// <summary>
- /// Set an autofilter for the range
- /// </summary>
- public bool AutoFilter {
- get {
- IsRangeValid("autofilter");
- ExcelAddressBase address = _worksheet.AutoFilterAddress;
- if (address == null) {
- return false;
- }
- if (_fromRow >= address.Start.Row
- && _toRow <= address.End.Row
- && _fromCol >= address.Start.Column
- && _toCol <= address.End.Column) {
- return true;
- }
- return false;
- }
- set {
- IsRangeValid("autofilter");
- _worksheet.AutoFilterAddress = this;
- if (_worksheet.Names.ContainsKey("_xlnm._FilterDatabase")) {
- _worksheet.Names.Remove("_xlnm._FilterDatabase");
- }
- var result = _worksheet.Names.Add("_xlnm._FilterDatabase", this);
- result.IsNameHidden = true;
- }
- }
-
- /// <summary>
- /// If the value is in richtext format.
- /// </summary>
- public bool IsRichText {
- get {
- IsRangeValid("richtext");
- return _worksheet._flags.GetFlagValue(_fromRow, _fromCol, CellFlags.RichText);
- }
- set => _changePropMethod(Set_IsRichText, value);
- }
-
- /// <summary>
- /// Is the range a part of an Arrayformula
- /// </summary>
- public bool IsArrayFormula {
- get {
- IsRangeValid("arrayformulas");
- return _worksheet._flags.GetFlagValue(_fromRow, _fromCol, CellFlags.ArrayFormula);
- }
- set => _changePropMethod(Set_IsArrayFormula, value);
- }
-
- private ExcelRichTextCollection _rtc;
-
- /// <summary>
- /// Cell value is richtext formatted.
- /// Richtext-property only apply to the left-top cell of the range.
- /// </summary>
- public ExcelRichTextCollection RichText {
- get {
- IsRangeValid("richtext");
- if (_rtc == null) {
- _rtc = GetRichText(_fromRow, _fromCol);
- }
- return _rtc;
- }
- }
-
- private ExcelRichTextCollection GetRichText(int row, int col) {
- XmlDocument xml = new XmlDocument();
- var v = _worksheet._values.GetValue(row, col);
- var isRt = _worksheet._flags.GetFlagValue(row, col, CellFlags.RichText);
- if (v != null) {
- if (isRt) {
- XmlHelper.LoadXmlSafe(
- xml,
- "<d:si xmlns:d=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" >"
- + v
- + "</d:si>",
- Encoding.UTF8);
- } else {
- xml.LoadXml(
- "<d:si xmlns:d=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" ><d:r><d:t>"
- + SecurityElement.Escape(v.ToString())
- + "</d:t></d:r></d:si>");
- }
- } else {
- xml.LoadXml("<d:si xmlns:d=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" />");
- }
- var rtc = new ExcelRichTextCollection(
- _worksheet.NameSpaceManager,
- xml.SelectSingleNode("d:si", _worksheet.NameSpaceManager),
- this);
- return rtc;
- }
-
- /// <summary>
- /// returns the comment object of the first cell in the range
- /// </summary>
- public ExcelComment Comment {
- get {
- IsRangeValid("comments");
- ulong cellId = GetCellId(_worksheet.SheetID, _fromRow, _fromCol);
- if (_worksheet.Comments._comments.ContainsKey(cellId)) {
- return _worksheet._comments._comments[cellId] as ExcelComment;
- }
- return null;
- }
- }
-
- /// <summary>
- /// WorkSheet object
- /// </summary>
- public ExcelWorksheet Worksheet => _worksheet;
-
- /// <summary>
- /// Address including sheetname
- /// </summary>
- public string FullAddress {
- get {
- string fullAddress = GetFullAddress(_worksheet.Name, _address);
- if (Addresses != null) {
- foreach (var a in Addresses) {
- fullAddress += "," + GetFullAddress(_worksheet.Name, a.Address);
- ;
- }
- }
- return fullAddress;
- }
- }
-
- /// <summary>
- /// Address including sheetname
- /// </summary>
- public string FullAddressAbsolute {
- get {
- string wbwsRef = string.IsNullOrEmpty(_wb) ? _ws : "[" + _wb.Replace("'", "''") + "]" + _ws;
- string fullAddress = GetFullAddress(
- wbwsRef,
- GetAddress(_fromRow, _fromCol, _toRow, _toCol, true));
- if (Addresses != null) {
- foreach (var a in Addresses) {
- fullAddress +=
- ","
- + GetFullAddress(
- wbwsRef,
- GetAddress(a.Start.Row, a.Start.Column, a.End.Row, a.End.Column, true));
- ;
- }
- }
- return fullAddress;
- }
- }
-
- /// <summary>
- /// Address including sheetname
- /// </summary>
- internal string FullAddressAbsoluteNoFullRowCol {
- get {
- string wbwsRef = string.IsNullOrEmpty(_wb) ? _ws : "[" + _wb.Replace("'", "''") + "]" + _ws;
- string fullAddress = GetFullAddress(
- wbwsRef,
- GetAddress(_fromRow, _fromCol, _toRow, _toCol, true),
- false);
- if (Addresses != null) {
- foreach (var a in Addresses) {
- fullAddress +=
- ","
- + GetFullAddress(
- wbwsRef,
- GetAddress(a.Start.Row, a.Start.Column, a.End.Row, a.End.Column, true),
- false);
- ;
- }
- }
- return fullAddress;
- }
- }
-
- /// <summary>
- /// Set the value without altering the richtext property
- /// </summary>
- /// <param name="value">the value</param>
- internal void SetValueRichText(object value) {
- if (_fromRow == 1
- && _fromCol == 1
- && _toRow == ExcelPackage.MaxRows
- && _toCol
- == ExcelPackage.MaxColumns) //Full sheet (ex ws.Cells.Value=0). Set value for A1 only to avoid hanging
- {
- //_worksheet.Cell(1, 1).SetValueRichText(value);
- SetValue(value, 1, 1);
- } else {
- //for (int col = _fromCol; col <= _toCol; col++)
- //{
- // for (int row = _fromRow; row <= _toRow; row++)
- // {
- //_worksheet.Cell(row, col).SetValueRichText(value);
- SetValue(value, _fromRow, _fromCol);
- //}
- //}
- }
- }
-
- private void SetValue(object value, int row, int col) {
- _worksheet.SetValue(row, col, value);
- // if (value is string) _worksheet._types.SetValue(row, col, "S"); else _worksheet._types.SetValue(row, col, "");
- _worksheet._formulas.SetValue(row, col, "");
- }
-
- internal void SetSharedFormulaId(int id) {
- for (int col = _fromCol; col <= _toCol; col++) {
- for (int row = _fromRow; row <= _toRow; row++) {
- _worksheet._formulas.SetValue(row, col, id);
- }
- }
- }
-
- private void CheckAndSplitSharedFormula(ExcelAddressBase address) {
- for (int col = address._fromCol; col <= address._toCol; col++) {
- for (int row = address._fromRow; row <= address._toRow; row++) {
- var f = _worksheet._formulas.GetValue(row, col);
- if (f is int i && i >= 0) {
- SplitFormulas(address);
- return;
- }
- }
- }
- }
-
- private void SplitFormulas(ExcelAddressBase address) {
- List<int> formulas = new List<int>();
- for (int col = address._fromCol; col <= address._toCol; col++) {
- for (int row = address._fromRow; row <= address._toRow; row++) {
- var f = _worksheet._formulas.GetValue(row, col);
- if (f is int id) {
- if (id >= 0 && !formulas.Contains(id)) {
- if (_worksheet._sharedFormulas[id].IsArray
- && Collide(_worksheet.Cells[_worksheet._sharedFormulas[id].Address])
- == eAddressCollition.Partly) // If the formula is an array formula and its on the inside the overwriting range throw an exception
- {
- throw (new InvalidOperationException("Can not overwrite a part of an array-formula"));
- }
- formulas.Add(id);
- }
- }
- }
- }
-
- foreach (int ix in formulas) {
- SplitFormula(address, ix);
- }
-
- ////Clear any formula references inside the refered range
- //_worksheet._formulas.Clear(address._fromRow, address._toRow, address._toRow - address._fromRow + 1, address._toCol - address.column + 1);
- }
-
- private void SplitFormula(ExcelAddressBase address, int ix) {
- var f = _worksheet._sharedFormulas[ix];
- var fRange = _worksheet.Cells[f.Address];
- var collide = address.Collide(fRange);
-
- //The formula is inside the currenct range, remove it
- if (collide == eAddressCollition.Equal || collide == eAddressCollition.Inside) {
- _worksheet._sharedFormulas.Remove(ix);
- return;
- //fRange.SetSharedFormulaID(int.MinValue);
- }
- var firstCellCollide = address.Collide(
- new(fRange._fromRow, fRange._fromCol, fRange._fromRow, fRange._fromCol));
- if (collide == eAddressCollition.Partly
- && (firstCellCollide == eAddressCollition.Inside
- || firstCellCollide
- == eAddressCollition.Equal)) //Do we need to split? Only if the functions first row is inside the new range.
- {
- //The formula partly collides with the current range
- bool fIsSet = false;
- string formulaR1C1 = fRange.FormulaR1C1;
- //Top Range
- if (fRange._fromRow < _fromRow) {
- f.Address = GetAddress(fRange._fromRow, fRange._fromCol, _fromRow - 1, fRange._toCol);
- fIsSet = true;
- }
- //Left Range
- if (fRange._fromCol < address._fromCol) {
- if (fIsSet) {
- f = new(SourceCodeTokenizer.Default);
- f.Index = _worksheet.GetMaxShareFunctionIndex(false);
- f.StartCol = fRange._fromCol;
- f.IsArray = false;
- _worksheet._sharedFormulas.Add(f.Index, f);
- } else {
- fIsSet = true;
- }
- if (fRange._fromRow < address._fromRow) {
- f.StartRow = address._fromRow;
- } else {
- f.StartRow = fRange._fromRow;
- }
- if (fRange._toRow < address._toRow) {
- f.Address = GetAddress(f.StartRow, f.StartCol, fRange._toRow, address._fromCol - 1);
- } else {
- f.Address = GetAddress(f.StartRow, f.StartCol, address._toRow, address._fromCol - 1);
- }
- f.Formula = TranslateFromR1C1(formulaR1C1, f.StartRow, f.StartCol);
- _worksheet.Cells[f.Address].SetSharedFormulaId(f.Index);
- }
- //Right Range
- if (fRange._toCol > address._toCol) {
- if (fIsSet) {
- f = new(SourceCodeTokenizer.Default);
- f.Index = _worksheet.GetMaxShareFunctionIndex(false);
- f.IsArray = false;
- _worksheet._sharedFormulas.Add(f.Index, f);
- } else {
- fIsSet = true;
- }
- f.StartCol = address._toCol + 1;
- if (address._fromRow < fRange._fromRow) {
- f.StartRow = fRange._fromRow;
- } else {
- f.StartRow = address._fromRow;
- }
-
- if (fRange._toRow < address._toRow) {
- f.Address = GetAddress(f.StartRow, f.StartCol, fRange._toRow, fRange._toCol);
- } else {
- f.Address = GetAddress(f.StartRow, f.StartCol, address._toRow, fRange._toCol);
- }
- f.Formula = TranslateFromR1C1(formulaR1C1, f.StartRow, f.StartCol);
- _worksheet.Cells[f.Address].SetSharedFormulaId(f.Index);
- }
- //Bottom Range
- if (fRange._toRow > address._toRow) {
- if (fIsSet) {
- f = new(SourceCodeTokenizer.Default);
- f.Index = _worksheet.GetMaxShareFunctionIndex(false);
- f.IsArray = false;
- _worksheet._sharedFormulas.Add(f.Index, f);
- }
-
- f.StartCol = fRange._fromCol;
- f.StartRow = _toRow + 1;
-
- f.Formula = TranslateFromR1C1(formulaR1C1, f.StartRow, f.StartCol);
-
- f.Address = GetAddress(f.StartRow, f.StartCol, fRange._toRow, fRange._toCol);
- _worksheet.Cells[f.Address].SetSharedFormulaId(f.Index);
- }
- }
- }
-
- private object ConvertData(ExcelTextFormat format, string v, int col, bool isText) {
- if (isText && (format.DataTypes == null || format.DataTypes.Length < col)) {
- return v;
- }
-
- double d;
- DateTime dt;
- if (format.DataTypes == null
- || format.DataTypes.Length <= col
- || format.DataTypes[col] == eDataTypes.Unknown) {
- string v2 = v.EndsWith("%") ? v.Substring(0, v.Length - 1) : v;
- if (double.TryParse(v2, NumberStyles.Any, format.Culture, out d)) {
- if (v2 == v) {
- return d;
- }
- return d / 100;
- }
- if (DateTime.TryParse(v, format.Culture, DateTimeStyles.None, out dt)) {
- return dt;
- }
- return v;
- }
- switch (format.DataTypes[col]) {
- case eDataTypes.Number:
- if (double.TryParse(v, NumberStyles.Any, format.Culture, out d)) {
- return d;
- }
- return v;
- case eDataTypes.DateTime:
- if (DateTime.TryParse(v, format.Culture, DateTimeStyles.None, out dt)) {
- return dt;
- }
- return v;
- case eDataTypes.Percent:
- string v2 = v.EndsWith("%") ? v.Substring(0, v.Length - 1) : v;
- if (double.TryParse(v2, NumberStyles.Any, format.Culture, out d)) {
- return d / 100;
- }
- return v;
-
- default:
- return v;
- }
- }
-
- /// <summary>
- /// Conditional Formatting for this range.
- /// </summary>
- public IRangeConditionalFormatting ConditionalFormatting =>
- new RangeConditionalFormatting(_worksheet, new(Address));
-
- /// <summary>
- /// Data validation for this range.
- /// </summary>
- public IRangeDataValidation DataValidation => new RangeDataValidation(_worksheet, Address);
-
- /// <summary>
- /// Get the strongly typed value of the cell.
- /// </summary>
- /// <typeparam name="T">The type</typeparam>
- /// <returns>The value. If the value can't be converted to the specified type, the default value will be returned</returns>
- public T GetValue<T>() {
- return _worksheet.GetTypedValue<T>(Value);
- }
-
- /// <summary>
- /// Get a range with an offset from the top left cell.
- /// The new range has the same dimensions as the current range
- /// </summary>
- /// <param name="rowOffset">Row Offset</param>
- /// <param name="columnOffset">Column Offset</param>
- /// <returns></returns>
- public ExcelRangeBase Offset(int rowOffset, int columnOffset) {
- if (_fromRow + rowOffset < 1
- || _fromCol + columnOffset < 1
- || _fromRow + rowOffset > ExcelPackage.MaxRows
- || _fromCol + columnOffset > ExcelPackage.MaxColumns) {
- throw (new ArgumentOutOfRangeException("Offset value out of range"));
- }
- string address = GetAddress(
- _fromRow + rowOffset,
- _fromCol + columnOffset,
- _toRow + rowOffset,
- _toCol + columnOffset);
- return new(_worksheet, address);
- }
-
- /// <summary>
- /// Get a range with an offset from the top left cell.
- /// </summary>
- /// <param name="rowOffset">Row Offset</param>
- /// <param name="columnOffset">Column Offset</param>
- /// <param name="numberOfRows">Number of rows. Minimum 1</param>
- /// <param name="numberOfColumns">Number of colums. Minimum 1</param>
- /// <returns></returns>
- public ExcelRangeBase Offset(
- int rowOffset,
- int columnOffset,
- int numberOfRows,
- int numberOfColumns) {
- if (numberOfRows < 1 || numberOfColumns < 1) {
- throw (new("Number of rows/columns must be greater than 0"));
- }
- numberOfRows--;
- numberOfColumns--;
- if (_fromRow + rowOffset < 1
- || _fromCol + columnOffset < 1
- || _fromRow + rowOffset > ExcelPackage.MaxRows
- || _fromCol + columnOffset > ExcelPackage.MaxColumns
- || _fromRow + rowOffset + numberOfRows < 1
- || _fromCol + columnOffset + numberOfColumns < 1
- || _fromRow + rowOffset + numberOfRows > ExcelPackage.MaxRows
- || _fromCol + columnOffset + numberOfColumns > ExcelPackage.MaxColumns) {
- throw (new ArgumentOutOfRangeException("Offset value out of range"));
- }
- string address = GetAddress(
- _fromRow + rowOffset,
- _fromCol + columnOffset,
- _fromRow + rowOffset + numberOfRows,
- _fromCol + columnOffset + numberOfColumns);
- return new(_worksheet, address);
- }
-
- /// <summary>
- /// Clear all cells
- /// </summary>
- public void Clear() {
- Delete(this, false);
- }
-
- /// <summary>
- /// Creates an array-formula.
- /// </summary>
- /// <param name="arrayFormula">The formula</param>
- public void CreateArrayFormula(string arrayFormula) {
- if (Addresses != null) {
- throw (new("An Arrayformula can not have more than one address"));
- }
- Set_SharedFormula(arrayFormula, this, true);
- }
-
- //private void Clear(ExcelAddressBase Range)
- //{
- // Clear(Range, true);
- //}
- internal void Delete(ExcelAddressBase range, bool shift) {
- //DeleteCheckMergedCells(Range);
- _worksheet.MergedCells.Clear(range);
- //First find the start cell
- int fromRow,
- fromCol;
- var d = Worksheet.Dimension;
- if (d != null
- && range._fromRow <= d._fromRow
- && range._toRow
- >= d._toRow) //EntireRow?
- {
- fromRow = 0;
- } else {
- fromRow = range._fromRow;
- }
- if (d != null
- && range._fromCol <= d._fromCol
- && range._toCol
- >= d._toCol) //EntireRow?
- {
- fromCol = 0;
- } else {
- fromCol = range._fromCol;
- }
-
- var rows = range._toRow - fromRow + 1;
- var cols = range._toCol - fromCol + 1;
-
- _worksheet._values.Delete(fromRow, fromCol, rows, cols, shift);
- _worksheet._types.Delete(fromRow, fromCol, rows, cols, shift);
- _worksheet._styles.Delete(fromRow, fromCol, rows, cols, shift);
- _worksheet._formulas.Delete(fromRow, fromCol, rows, cols, shift);
- _worksheet._hyperLinks.Delete(fromRow, fromCol, rows, cols, shift);
- _worksheet._flags.Delete(fromRow, fromCol, rows, cols, shift);
- _worksheet._commentsStore.Delete(fromRow, fromCol, rows, cols, shift);
-
- //if(shift)
- //{
- // _worksheet.AdjustFormulasRow(fromRow, rows);
- //}
-
- //Clear multi addresses as well
- if (Addresses != null) {
- foreach (var sub in Addresses) {
- Delete(sub, shift);
- }
- }
- }
-
- public void Dispose() {}
-
- //int _index;
- //ulong _toCellId;
- //int _enumAddressIx;
- private CellsStoreEnumerator<object> cellEnum;
-
- public IEnumerator<ExcelRangeBase> GetEnumerator() {
- Reset();
- return this;
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- Reset();
- return this;
- }
-
- /// <summary>
- /// The current range when enumerating
- /// </summary>
- public ExcelRangeBase Current => new(_worksheet, GetAddress(cellEnum.Row, cellEnum.Column));
-
- /// <summary>
- /// The current range when enumerating
- /// </summary>
- object IEnumerator.Current =>
- new ExcelRangeBase(_worksheet, GetAddress(cellEnum.Row, cellEnum.Column));
-
- private int _enumAddressIx = -1;
-
- public bool MoveNext() {
- if (cellEnum.Next()) {
- return true;
- }
- if (_addresses != null) {
- _enumAddressIx++;
- if (_enumAddressIx < _addresses.Count) {
- cellEnum = new(
- _worksheet._values,
- _addresses[_enumAddressIx]._fromRow,
- _addresses[_enumAddressIx]._fromCol,
- _addresses[_enumAddressIx]._toRow,
- _addresses[_enumAddressIx]._toCol);
- return MoveNext();
- }
- return false;
- }
- return false;
- }
-
- public void Reset() {
- _enumAddressIx = -1;
- cellEnum = new(_worksheet._values, _fromRow, _fromCol, _toRow, _toCol);
- }
-
- //private void GetNextIndexEnum(int fromRow, int fromCol, int toRow, int toCol)
- //{
- // if (_index >= _worksheet._cells.Count) return;
- // ExcelCell cell = _worksheet._cells[_index] as ExcelCell;
- // while (cell.Column > toCol || cell.Column < fromCol)
- // {
- // if (cell.Column < fromCol)
- // {
- // _index = _worksheet._cells.IndexOf(ExcelAddress.GetCellID(_worksheet.SheetID, cell.Row, fromCol));
- // }
- // else
- // {
- // _index = _worksheet._cells.IndexOf(ExcelAddress.GetCellID(_worksheet.SheetID, cell.Row + 1, fromCol));
- // }
-
- // if (_index < 0)
- // {
- // _index = ~_index;
- // }
- // if (_index >= _worksheet._cells.Count || _worksheet._cells[_index].RangeID > _toCellId)
- // {
- // break;
- // }
- // cell = _worksheet._cells[_index] as ExcelCell;
- // }
- //}
-
- //private void GetStartIndexEnum(int fromRow, int fromCol, int toRow, int toCol)
- //{
- // _index = _worksheet._cells.IndexOf(ExcelCellBase.GetCellID(_worksheet.SheetID, fromRow, fromCol));
- // _toCellId = ExcelCellBase.GetCellID(_worksheet.SheetID, toRow, toCol);
- // if (_index < 0)
- // {
- // _index = ~_index;
- // }
- // _index--;
- //}
-}
diff --git a/EPPlus/ExcelRangeCopyOptionFlags.cs b/EPPlus/ExcelRangeCopyOptionFlags.cs
deleted file mode 100644
index 684a49c..0000000
--- a/EPPlus/ExcelRangeCopyOptionFlags.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Flag enum, specify all flags that you want to exclude from the copy.
-/// </summary>
-[Flags]
-public enum ExcelRangeCopyOptionFlags {
- /// <summary>
- /// Exclude formulas from being copied
- /// </summary>
- ExcludeFormulas = 0x1,
-}
diff --git a/EPPlus/ExcelRow.cs b/EPPlus/ExcelRow.cs
deleted file mode 100644
index f4336c7..0000000
--- a/EPPlus/ExcelRow.cs
+++ /dev/null
@@ -1,258 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan K�llman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Xml;
-using OfficeOpenXml.Style;
-
-namespace OfficeOpenXml;
-
-internal class RowInternal {
- internal double Height = -1;
- internal bool Hidden;
- internal bool Collapsed;
- internal short OutlineLevel;
- internal bool PageBreak;
- internal bool Phonetic;
- internal bool CustomHeight;
-}
-
-/// <summary>
-/// Represents an individual row in the spreadsheet.
-/// </summary>
-public class ExcelRow : IRangeId {
- private readonly ExcelWorksheet _worksheet;
- private readonly XmlElement _rowElement = null;
-
- /// <summary>
- /// Internal RowID.
- /// </summary>
- [Obsolete]
- public ulong RowID => GetRowId(_worksheet.SheetID, Row);
-
- /// <summary>
- /// Creates a new instance of the ExcelRow class.
- /// For internal use only!
- /// </summary>
- /// <param name="worksheet">The parent worksheet</param>
- /// <param name="row">The row number</param>
- internal ExcelRow(ExcelWorksheet worksheet, int row) {
- _worksheet = worksheet;
- Row = row;
- }
-
- /// <summary>
- /// Provides access to the node representing the row.
- /// </summary>
- internal XmlNode Node => (_rowElement);
-
- /// <summary>
- /// Allows the row to be hidden in the worksheet
- /// </summary>
- public bool Hidden {
- get {
- var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
- if (r == null) {
- return false;
- }
- return r.Hidden;
- }
- set {
- var r = GetRowInternal();
- r.Hidden = value;
- }
- }
-
- /// <summary>
- /// Sets the height of the row
- /// </summary>
- public double Height {
- get {
- var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
- if (r == null || r.Height < 0) {
- return _worksheet.DefaultRowHeight;
- }
- return r.Height;
- }
- set {
- var r = GetRowInternal();
- r.Height = value;
-
- if (r.Hidden && value != 0) {
- Hidden = false;
- }
- r.CustomHeight = (value != _worksheet.DefaultRowHeight);
- }
- }
-
- /// <summary>
- /// Set to true if You don't want the row to Autosize
- /// </summary>
- public bool CustomHeight {
- get {
- var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
- if (r == null) {
- return false;
- }
- return r.CustomHeight;
- }
- set {
- var r = GetRowInternal();
- r.CustomHeight = value;
- }
- }
-
- internal string _styleName = "";
-
- /// <summary>
- /// Sets the style for the entire column using a style name.
- /// </summary>
- public string StyleName {
- get => _styleName;
- set {
- StyleID = _worksheet.Workbook.Styles.GetStyleIdFromName(value);
- _styleName = value;
- }
- }
-
- /// <summary>
- /// Sets the style for the entire row using the style ID.
- /// </summary>
- public int StyleID {
- get => _worksheet._styles.GetValue(Row, 0);
- set => _worksheet._styles.SetValue(Row, 0, value);
- }
-
- /// <summary>
- /// Rownumber
- /// </summary>
- public int Row { get; set; }
-
- /// <summary>
- /// If outline level is set this tells that the row is collapsed
- /// </summary>
- public bool Collapsed {
- get {
- var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
- if (r == null) {
- return false;
- }
- return r.Collapsed;
- }
- set {
- var r = GetRowInternal();
- r.Collapsed = value;
- }
- }
-
- /// <summary>
- /// Outline level.
- /// </summary>
- public int OutlineLevel {
- get {
- var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
- if (r == null) {
- return 0;
- }
- return r.OutlineLevel;
- }
- set {
- var r = GetRowInternal();
- r.OutlineLevel = (short)value;
- }
- }
-
- private RowInternal GetRowInternal() {
- var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
- if (r == null) {
- r = new();
- _worksheet._values.SetValue(Row, 0, r);
- }
- return r;
- }
-
- /// <summary>
- /// Show phonetic Information
- /// </summary>
- public bool Phonetic {
- get {
- var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
- if (r == null) {
- return false;
- }
- return r.Phonetic;
- }
- set {
- var r = GetRowInternal();
- r.Phonetic = value;
- }
- }
-
- /// <summary>
- /// The Style applied to the whole row. Only effekt cells with no individual style set.
- /// Use ExcelRange object if you want to set specific styles.
- /// </summary>
- public ExcelStyle Style =>
- _worksheet.Workbook.Styles.GetStyleObject(StyleID, _worksheet.PositionID, Row + ":" + Row);
-
- /// <summary>
- /// Adds a manual page break after the row.
- /// </summary>
- public bool PageBreak {
- get {
- var r = (RowInternal)_worksheet._values.GetValue(Row, 0);
- if (r == null) {
- return false;
- }
- return r.PageBreak;
- }
- set {
- var r = GetRowInternal();
- r.PageBreak = value;
- }
- }
-
- public bool Merged {
- get => _worksheet.MergedCells[Row, 0] != null;
- set => _worksheet.MergedCells.Add(new(Row, 1, Row, ExcelPackage.MaxColumns), true);
- }
-
- internal static ulong GetRowId(int sheetId, int row) {
- return ((ulong)sheetId) + (((ulong)row) << 29);
- }
-
- [Obsolete]
- ulong IRangeId.RangeID {
- get => RowID;
- set => Row = ((int)(value >> 29));
- }
-}
diff --git a/EPPlus/ExcelSheetProtection.cs b/EPPlus/ExcelSheetProtection.cs
deleted file mode 100644
index 0b2cb09..0000000
--- a/EPPlus/ExcelSheetProtection.cs
+++ /dev/null
@@ -1,217 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2010-03-14
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Collections.Immutable;
-using System.Xml;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Sheet protection
-///<seealso cref="ExcelEncryption"/>
-///<seealso cref="ExcelProtection"/>
-/// </summary>
-public sealed class ExcelSheetProtection : XmlHelper {
- protected override ImmutableArray<string> SchemaNodeOrder =>
- ExcelWorksheet.WorksheetSchemaNodeOrder;
-
- internal ExcelSheetProtection(XmlNamespaceManager nsm, XmlNode topNode)
- : base(nsm, topNode) {}
-
- private const string _isProtectedPath = "d:sheetProtection/@sheet";
-
- /// <summary>
- /// If the worksheet is protected.
- /// </summary>
- public bool IsProtected {
- get => GetXmlNodeBool(_isProtectedPath, false);
- set {
- SetXmlNodeBool(_isProtectedPath, value, false);
- if (value) {
- AllowEditObject = true;
- AllowEditScenarios = true;
- } else {
- DeleteAllNode(_isProtectedPath); //delete the whole sheetprotection node
- }
- }
- }
-
- private const string _allowSelectLockedCellsPath = "d:sheetProtection/@selectLockedCells";
-
- /// <summary>
- /// Allow users to select locked cells
- /// </summary>
- public bool AllowSelectLockedCells {
- get => !GetXmlNodeBool(_allowSelectLockedCellsPath, false);
- set => SetXmlNodeBool(_allowSelectLockedCellsPath, !value, false);
- }
-
- private const string _allowSelectUnlockedCellsPath = "d:sheetProtection/@selectUnlockedCells";
-
- /// <summary>
- /// Allow users to select unlocked cells
- /// </summary>
- public bool AllowSelectUnlockedCells {
- get => !GetXmlNodeBool(_allowSelectUnlockedCellsPath, false);
- set => SetXmlNodeBool(_allowSelectUnlockedCellsPath, !value, false);
- }
-
- private const string _allowObjectPath = "d:sheetProtection/@objects";
-
- /// <summary>
- /// Allow users to edit objects
- /// </summary>
- public bool AllowEditObject {
- get => !GetXmlNodeBool(_allowObjectPath, false);
- set => SetXmlNodeBool(_allowObjectPath, !value, false);
- }
-
- private const string _allowScenariosPath = "d:sheetProtection/@scenarios";
-
- /// <summary>
- /// Allow users to edit senarios
- /// </summary>
- public bool AllowEditScenarios {
- get => !GetXmlNodeBool(_allowScenariosPath, false);
- set => SetXmlNodeBool(_allowScenariosPath, !value, false);
- }
-
- private const string _allowFormatCellsPath = "d:sheetProtection/@formatCells";
-
- /// <summary>
- /// Allow users to format cells
- /// </summary>
- public bool AllowFormatCells {
- get => !GetXmlNodeBool(_allowFormatCellsPath, true);
- set => SetXmlNodeBool(_allowFormatCellsPath, !value, true);
- }
-
- private const string _allowFormatColumnsPath = "d:sheetProtection/@formatColumns";
-
- /// <summary>
- /// Allow users to Format columns
- /// </summary>
- public bool AllowFormatColumns {
- get => !GetXmlNodeBool(_allowFormatColumnsPath, true);
- set => SetXmlNodeBool(_allowFormatColumnsPath, !value, true);
- }
-
- private const string _allowFormatRowsPath = "d:sheetProtection/@formatRows";
-
- /// <summary>
- /// Allow users to Format rows
- /// </summary>
- public bool AllowFormatRows {
- get => !GetXmlNodeBool(_allowFormatRowsPath, true);
- set => SetXmlNodeBool(_allowFormatRowsPath, !value, true);
- }
-
- private const string _allowInsertColumnsPath = "d:sheetProtection/@insertColumns";
-
- /// <summary>
- /// Allow users to insert columns
- /// </summary>
- public bool AllowInsertColumns {
- get => !GetXmlNodeBool(_allowInsertColumnsPath, true);
- set => SetXmlNodeBool(_allowInsertColumnsPath, !value, true);
- }
-
- private const string _allowInsertRowsPath = "d:sheetProtection/@insertRows";
-
- /// <summary>
- /// Allow users to Format rows
- /// </summary>
- public bool AllowInsertRows {
- get => !GetXmlNodeBool(_allowInsertRowsPath, true);
- set => SetXmlNodeBool(_allowInsertRowsPath, !value, true);
- }
-
- private const string _allowInsertHyperlinksPath = "d:sheetProtection/@insertHyperlinks";
-
- /// <summary>
- /// Allow users to insert hyperlinks
- /// </summary>
- public bool AllowInsertHyperlinks {
- get => !GetXmlNodeBool(_allowInsertHyperlinksPath, true);
- set => SetXmlNodeBool(_allowInsertHyperlinksPath, !value, true);
- }
-
- private const string _allowDeleteColumns = "d:sheetProtection/@deleteColumns";
-
- /// <summary>
- /// Allow users to delete columns
- /// </summary>
- public bool AllowDeleteColumns {
- get => !GetXmlNodeBool(_allowDeleteColumns, true);
- set => SetXmlNodeBool(_allowDeleteColumns, !value, true);
- }
-
- private const string _allowDeleteRowsPath = "d:sheetProtection/@deleteRows";
-
- /// <summary>
- /// Allow users to delete rows
- /// </summary>
- public bool AllowDeleteRows {
- get => !GetXmlNodeBool(_allowDeleteRowsPath, true);
- set => SetXmlNodeBool(_allowDeleteRowsPath, !value, true);
- }
-
- private const string _allowSortPath = "d:sheetProtection/@sort";
-
- /// <summary>
- /// Allow users to sort a range
- /// </summary>
- public bool AllowSort {
- get => !GetXmlNodeBool(_allowSortPath, true);
- set => SetXmlNodeBool(_allowSortPath, !value, true);
- }
-
- private const string _allowAutoFilterPath = "d:sheetProtection/@autoFilter";
-
- /// <summary>
- /// Allow users to use autofilters
- /// </summary>
- public bool AllowAutoFilter {
- get => !GetXmlNodeBool(_allowAutoFilterPath, true);
- set => SetXmlNodeBool(_allowAutoFilterPath, !value, true);
- }
-
- private const string _allowPivotTablesPath = "d:sheetProtection/@pivotTables";
-
- /// <summary>
- /// Allow users to use pivottables
- /// </summary>
- public bool AllowPivotTables {
- get => !GetXmlNodeBool(_allowPivotTablesPath, true);
- set => SetXmlNodeBool(_allowPivotTablesPath, !value, true);
- }
-}
diff --git a/EPPlus/ExcelStyleCollection.cs b/EPPlus/ExcelStyleCollection.cs
deleted file mode 100644
index b544547..0000000
--- a/EPPlus/ExcelStyleCollection.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Xml;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Base collection class for styles.
-/// </summary>
-/// <typeparam name="T">The style type</typeparam>
-public class ExcelStyleCollection<T> : IEnumerable<T> {
- public ExcelStyleCollection() {
- _setNextIdManual = false;
- }
-
- private readonly bool _setNextIdManual;
-
- public ExcelStyleCollection(bool setNextIdManual) {
- _setNextIdManual = setNextIdManual;
- }
-
- public XmlNode TopNode { get; set; }
-
- internal List<T> _list = new();
- private readonly Dictionary<string, int> _dic = new(StringComparer.InvariantCultureIgnoreCase);
- internal int NextId;
-
- public IEnumerator<T> GetEnumerator() {
- return _list.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- return _list.GetEnumerator();
- }
-
- public T this[int positionId] => _list[positionId];
-
- public int Count => _list.Count;
-
- //internal int Add(T item)
- //{
- // _list.Add(item);
- // if (_setNextIdManual) NextId++;
- // return _list.Count-1;
- //}
- internal int Add(string key, T item) {
- _list.Add(item);
- if (!_dic.ContainsKey(key.ToLower(CultureInfo.InvariantCulture))) {
- _dic.Add(key.ToLower(CultureInfo.InvariantCulture), _list.Count - 1);
- }
- if (_setNextIdManual) {
- NextId++;
- }
- return _list.Count - 1;
- }
-
- /// <summary>
- /// Finds the key
- /// </summary>
- /// <param name="key">the key to be found</param>
- /// <param name="obj">The found object.</param>
- /// <returns>True if found</returns>
- internal bool FindById(string key, ref T obj) {
- if (_dic.ContainsKey(key)) {
- obj = _list[_dic[key.ToLower(CultureInfo.InvariantCulture)]];
- return true;
- }
- return false;
- }
-
- /// <summary>
- /// Find Index
- /// </summary>
- /// <param name="key"></param>
- /// <returns></returns>
- internal int FindIndexById(string key) {
- if (_dic.ContainsKey(key)) {
- return _dic[key];
- }
- return int.MinValue;
- }
-
- internal bool ExistsKey(string key) {
- return _dic.ContainsKey(key);
- }
-
- internal void Sort(Comparison<T> c) {
- _list.Sort(c);
- }
-}
diff --git a/EPPlus/ExcelStyles.cs b/EPPlus/ExcelStyles.cs
deleted file mode 100644
index 6bb75ff..0000000
--- a/EPPlus/ExcelStyles.cs
+++ /dev/null
@@ -1,874 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan K�llman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Linq;
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting;
-using OfficeOpenXml.Style;
-using OfficeOpenXml.Style.Dxf;
-using OfficeOpenXml.Style.XmlAccess;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Containts all shared cell styles for a workbook
-/// </summary>
-public sealed class ExcelStyles : XmlHelper {
- private const string _numberFormatsPath = "d:styleSheet/d:numFmts";
- private const string _fontsPath = "d:styleSheet/d:fonts";
- private const string _fillsPath = "d:styleSheet/d:fills";
- private const string _bordersPath = "d:styleSheet/d:borders";
- private const string _cellStyleXfsPath = "d:styleSheet/d:cellStyleXfs";
- private const string _cellXfsPath = "d:styleSheet/d:cellXfs";
- private const string _cellStylesPath = "d:styleSheet/d:cellStyles";
- private const string _dxfsPath = "d:styleSheet/d:dxfs";
-
- //internal Dictionary<int, ExcelXfs> Styles = new Dictionary<int, ExcelXfs>();
- private readonly XmlDocument _styleXml;
- private readonly ExcelWorkbook _wb;
- private readonly XmlNamespaceManager _nameSpaceManager;
- internal int _nextDfxNumFmtID = 164;
-
- protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
- "numFmts",
- "fonts",
- "fills",
- "borders",
- "cellStyleXfs",
- "cellXfs",
- "cellStyles",
- "dxfs",
- ];
-
- internal ExcelStyles(XmlNamespaceManager nameSpaceManager, XmlDocument xml, ExcelWorkbook wb)
- : base(nameSpaceManager, xml) {
- _styleXml = xml;
- _wb = wb;
- _nameSpaceManager = nameSpaceManager;
- LoadFromDocument();
- }
-
- /// <summary>
- /// Loads the style XML to memory
- /// </summary>
- private void LoadFromDocument() {
- //NumberFormats
- ExcelNumberFormatXml.AddBuildIn(NameSpaceManager, NumberFormats);
- XmlNode numNode = _styleXml.SelectSingleNode(_numberFormatsPath, _nameSpaceManager);
- if (numNode != null) {
- foreach (XmlNode n in numNode) {
- ExcelNumberFormatXml nf = new ExcelNumberFormatXml(_nameSpaceManager, n);
- NumberFormats.Add(nf.Id, nf);
- if (nf.NumFmtId >= NumberFormats.NextId) {
- NumberFormats.NextId = nf.NumFmtId + 1;
- }
- }
- }
-
- //Fonts
- XmlNode fontNode = _styleXml.SelectSingleNode(_fontsPath, _nameSpaceManager);
- foreach (XmlNode n in fontNode) {
- ExcelFontXml f = new ExcelFontXml(_nameSpaceManager, n);
- Fonts.Add(f.Id, f);
- }
-
- //Fills
- XmlNode fillNode = _styleXml.SelectSingleNode(_fillsPath, _nameSpaceManager);
- foreach (XmlNode n in fillNode) {
- ExcelFillXml f;
- if (n.FirstChild != null && n.FirstChild.LocalName == "gradientFill") {
- f = new ExcelGradientFillXml(_nameSpaceManager, n);
- } else {
- f = new(_nameSpaceManager, n);
- }
- Fills.Add(f.Id, f);
- }
-
- //Borders
- XmlNode borderNode = _styleXml.SelectSingleNode(_bordersPath, _nameSpaceManager);
- foreach (XmlNode n in borderNode) {
- ExcelBorderXml b = new ExcelBorderXml(_nameSpaceManager, n);
- Borders.Add(b.Id, b);
- }
-
- //cellStyleXfs
- XmlNode styleXfsNode = _styleXml.SelectSingleNode(_cellStyleXfsPath, _nameSpaceManager);
- if (styleXfsNode != null) {
- foreach (XmlNode n in styleXfsNode) {
- ExcelXfs item = new ExcelXfs(_nameSpaceManager, n, this);
- CellStyleXfs.Add(item.Id, item);
- }
- }
-
- XmlNode styleNode = _styleXml.SelectSingleNode(_cellXfsPath, _nameSpaceManager);
- for (int i = 0; i < styleNode.ChildNodes.Count; i++) {
- XmlNode n = styleNode.ChildNodes[i];
- ExcelXfs item = new ExcelXfs(_nameSpaceManager, n, this);
- CellXfs.Add(item.Id, item);
- }
-
- //cellStyle
- XmlNode namedStyleNode = _styleXml.SelectSingleNode(_cellStylesPath, _nameSpaceManager);
- if (namedStyleNode != null) {
- foreach (XmlNode n in namedStyleNode) {
- ExcelNamedStyleXml item = new ExcelNamedStyleXml(_nameSpaceManager, n, this);
- NamedStyles.Add(item.Name, item);
- }
- }
-
- //dxfsPath
- XmlNode dxfsNode = _styleXml.SelectSingleNode(_dxfsPath, _nameSpaceManager);
- if (dxfsNode != null) {
- foreach (XmlNode x in dxfsNode) {
- ExcelDxfStyleConditionalFormatting item = new ExcelDxfStyleConditionalFormatting(
- _nameSpaceManager,
- x,
- this);
- Dxfs.Add(item.Id, item);
- }
- }
- }
-
- internal ExcelStyle GetStyleObject(int id, int positionId, string address) {
- if (id < 0) {
- id = 0;
- }
- return new(this, PropertyChange, positionId, address, id);
- }
-
- /// <summary>
- /// Handels changes of properties on the style objects
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- /// <returns></returns>
- internal int PropertyChange(StyleBase sender, StyleChangeEventArgs e) {
- var address = new ExcelAddressBase(e.Address);
- var ws = _wb.Worksheets[e.PositionID];
- Dictionary<int, int> styleCashe = new Dictionary<int, int>();
- //Set single address
- SetStyleAddress(sender, e, address, ws, ref styleCashe);
- if (address.Addresses != null) {
- //Handle multiaddresses
- foreach (var innerAddress in address.Addresses) {
- SetStyleAddress(sender, e, innerAddress, ws, ref styleCashe);
- }
- }
- return 0;
- }
-
- private void SetStyleAddress(
- StyleBase sender,
- StyleChangeEventArgs e,
- ExcelAddressBase address,
- ExcelWorksheet ws,
- ref Dictionary<int, int> styleCashe) {
- if (address.Start.Column == 0 || address.Start.Row == 0) {
- throw (new("error address"));
- }
- //Columns
- if (address.Start.Row == 1 && address.End.Row == ExcelPackage.MaxRows) {
- ExcelColumn column;
- int col = address.Start.Column,
- row = 0;
- //Get the startcolumn
- if (!ws._values.Exists(0, address.Start.Column)) {
- column = ws.Column(address.Start.Column);
- } else {
- column = (ExcelColumn)ws._values.GetValue(0, address.Start.Column);
- }
-
- while (column.ColumnMin <= address.End.Column) {
- if (column.ColumnMax > address.End.Column) {
- var newCol = ws.CopyColumn(column, address.End.Column + 1, column.ColumnMax);
- column.ColumnMax = address.End.Column;
- }
- var s = ws._styles.GetValue(0, column.ColumnMin);
- if (styleCashe.ContainsKey(s)) {
- ws.SetStyle(0, column.ColumnMin, styleCashe[s]);
- } else {
- ExcelXfs st = CellXfs[s];
- int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
- styleCashe.Add(s, newId);
- ws.SetStyle(0, column.ColumnMin, newId);
- }
-
- //index++;
-
- if (!ws._values.NextCell(ref row, ref col) || row > 0) {
- column._columnMax = address.End.Column;
- break;
- }
- column = (ws._values.GetValue(0, col) as ExcelColumn);
- }
-
- if (column._columnMax < address.End.Column) {
- var newCol = ws.Column(column._columnMax + 1);
- newCol._columnMax = address.End.Column;
-
- var s = ws._styles.GetValue(0, column.ColumnMin);
- if (styleCashe.ContainsKey(s)) {
- ws.SetStyle(0, column.ColumnMin, styleCashe[s]);
- } else {
- ExcelXfs st = CellXfs[s];
- int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
- styleCashe.Add(s, newId);
- ws.SetStyle(0, column.ColumnMin, newId);
- }
-
- column._columnMax = address.End.Column;
- }
-
- //Set for individual cells in the span. We loop all cells here since the cells are sorted with columns first.
- var cse = new CellsStoreEnumerator<int>(
- ws._styles,
- 1,
- address._fromCol,
- address._toRow,
- address._toCol);
- while (cse.Next()) {
- if (cse.Column >= address.Start.Column && cse.Column <= address.End.Column) {
- if (styleCashe.ContainsKey(cse.Value)) {
- ws.SetStyle(cse.Row, cse.Column, styleCashe[cse.Value]);
- } else {
- ExcelXfs st = CellXfs[cse.Value];
- int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
- styleCashe.Add(cse.Value, newId);
- cse.Value = newId;
- //ws.SetStyle(cse.Row, cse.Column, newId);
- }
- }
- }
-
- //Update cells with styled columns
- cse = new(ws._styles, 1, 0, address._toRow, 0);
- while (cse.Next()) {
- for (int c = address._fromRow; c <= address._toCol; c++) {
- if (!ws._styles.Exists(cse.Row, c)) {
- if (styleCashe.ContainsKey(cse.Value)) {
- ws.SetStyle(cse.Row, c, styleCashe[cse.Value]);
- } else {
- ExcelXfs st = CellXfs[cse.Value];
- int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
- styleCashe.Add(cse.Value, newId);
- ws.SetStyle(cse.Row, c, newId);
- }
- }
- }
- }
- }
- //Rows
- else if (address.Start.Column == 1 && address.End.Column == ExcelPackage.MaxColumns) {
- for (int rowNum = address.Start.Row; rowNum <= address.End.Row; rowNum++) {
- var s = ws._styles.GetValue(rowNum, 0);
- if (s == 0) {
- //iterate all columns and set the row to the style of the last column
- var cse = new CellsStoreEnumerator<int>(ws._styles, 0, 1, 0, ExcelPackage.MaxColumns);
- while (cse.Next()) {
- s = cse.Value;
- var c = ws._values.GetValue(cse.Row, cse.Column) as ExcelColumn;
- if (c != null && c.ColumnMax < ExcelPackage.MaxColumns) {
- for (int col = c.ColumnMin; col < c.ColumnMax; col++) {
- if (!ws._styles.Exists(rowNum, col)) {
- ws._styles.SetValue(rowNum, col, s);
- }
- }
- }
- }
- ws.SetStyle(rowNum, 0, s);
- }
- if (styleCashe.ContainsKey(s)) {
- ws.SetStyle(rowNum, 0, styleCashe[s]);
- } else {
- ExcelXfs st = CellXfs[s];
- int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
- styleCashe.Add(s, newId);
- ws._styles.SetValue(rowNum, 0, newId);
- ws.SetStyle(rowNum, 0, newId);
- }
- }
-
- //Update individual cells
- var cse2 = new CellsStoreEnumerator<int>(
- ws._styles,
- address._fromRow,
- address._fromCol,
- address._toRow,
- address._toCol);
- while (cse2.Next()) {
- var s = cse2.Value;
- if (styleCashe.ContainsKey(s)) {
- ws.SetStyle(cse2.Row, cse2.Column, styleCashe[s]);
- } else {
- ExcelXfs st = CellXfs[s];
- int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
- styleCashe.Add(s, newId);
- cse2.Value = newId;
- }
- }
-
- //Update cells with styled rows
- cse2 = new(ws._styles, 0, 1, 0, address._toCol);
- while (cse2.Next()) {
- for (int r = address._fromRow; r <= address._toRow; r++) {
- if (!ws._styles.Exists(r, cse2.Column)) {
- var s = cse2.Value;
- if (styleCashe.ContainsKey(s)) {
- ws.SetStyle(r, cse2.Column, styleCashe[s]);
- } else {
- ExcelXfs st = CellXfs[s];
- int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
- styleCashe.Add(s, newId);
- ws.SetStyle(r, cse2.Column, newId);
- }
- }
- }
- }
- } else //Cellrange
- {
- for (int col = address.Start.Column; col <= address.End.Column; col++) {
- for (int row = address.Start.Row; row <= address.End.Row; row++) {
- var s = GetStyleId(ws, row, col);
- if (styleCashe.ContainsKey(s)) {
- ws.SetStyle(row, col, styleCashe[s]);
- } else {
- ExcelXfs st = CellXfs[s];
- int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
- styleCashe.Add(s, newId);
- ws.SetStyle(row, col, newId);
- }
- }
- }
- }
- }
-
- internal int GetStyleId(ExcelWorksheet ws, int row, int col) {
- int v = 0;
- if (ws._styles.Exists(row, col, ref v)) {
- return v;
- }
- if (ws._styles.Exists(
- row,
- 0,
- ref v)) //First Row
- {
- return v;
- } // then column
- if (ws._styles.Exists(0, col, ref v)) {
- return v;
- }
- int r = 0,
- c = col;
- if (ws._values.PrevCell(ref r, ref c)) {
- var column = ws._values.GetValue(0, c) as ExcelColumn;
- if (column != null
- && column.ColumnMax
- >= col) //Fixes issue 15174
- {
- return ws._styles.GetValue(0, c);
- }
- return 0;
- }
- return 0;
- }
-
- /// <summary>
- /// Handles property changes on Named styles.
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- /// <returns></returns>
- internal int NamedStylePropertyChange(StyleBase sender, StyleChangeEventArgs e) {
- int index = NamedStyles.FindIndexById(e.Address);
- if (index >= 0) {
- int newId = CellStyleXfs[NamedStyles[index].StyleXfId]
- .GetNewId(CellStyleXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
- int prevIx = NamedStyles[index].StyleXfId;
- NamedStyles[index].StyleXfId = newId;
- NamedStyles[index].Style.Index = newId;
-
- NamedStyles[index].XfId = int.MinValue;
- foreach (var style in CellXfs) {
- if (style.XfId == prevIx) {
- style.XfId = newId;
- }
- }
- }
- return 0;
- }
-
- public ExcelStyleCollection<ExcelNumberFormatXml> NumberFormats = new();
- public ExcelStyleCollection<ExcelFontXml> Fonts = new();
- public ExcelStyleCollection<ExcelFillXml> Fills = new();
- public ExcelStyleCollection<ExcelBorderXml> Borders = new();
- public ExcelStyleCollection<ExcelXfs> CellStyleXfs = new();
- public ExcelStyleCollection<ExcelXfs> CellXfs = new();
- public ExcelStyleCollection<ExcelNamedStyleXml> NamedStyles = new();
- public ExcelStyleCollection<ExcelDxfStyleConditionalFormatting> Dxfs = new();
-
- internal string Id => "";
-
- public ExcelNamedStyleXml CreateNamedStyle(string name) {
- return CreateNamedStyle(name, null);
- }
-
- public ExcelNamedStyleXml CreateNamedStyle(string name, ExcelStyle template) {
- if (_wb.Styles.NamedStyles.ExistsKey(name)) {
- throw new(string.Format("Key {0} already exists in collection", name));
- }
-
- ExcelNamedStyleXml style;
- style = new(NameSpaceManager, this);
- int xfIdCopy,
- positionId;
- ExcelStyles styles;
- if (template == null) {
- // style.Style = new ExcelStyle(this, NamedStylePropertyChange, -1, name, 0);
- xfIdCopy = 0;
- positionId = -1;
- styles = this;
- } else {
- if (template.PositionID < 0 && template.Styles == this) {
- xfIdCopy = template.Index;
- positionId = template.PositionID;
- styles = this;
- //style.Style = new ExcelStyle(this, NamedStylePropertyChange, Template.PositionID, name, Template.Index);
- //style.StyleXfId = Template.Index;
- } else {
- xfIdCopy = template.XfId;
- positionId = -1;
- styles = template.Styles;
- }
- }
- //Clone namedstyle
- int styleXfId = CloneStyle(styles, xfIdCopy, true);
- //Close cells style
- CellStyleXfs[styleXfId].XfId = CellStyleXfs.Count - 1;
- int xfid = CloneStyle(styles, xfIdCopy, false, true); //Always add a new style (We create a new named style here)
- CellXfs[xfid].XfId = styleXfId;
- style.Style = new(this, NamedStylePropertyChange, positionId, name, styleXfId);
- style.StyleXfId = styleXfId;
-
- style.Name = name;
- int ix = _wb.Styles.NamedStyles.Add(style.Name, style);
- style.Style.SetIndex(ix);
- //style.Style.XfId = ix;
- return style;
- }
-
- public void UpdateXml() {
- RemoveUnusedStyles();
-
- //NumberFormat
- XmlNode nfNode = _styleXml.SelectSingleNode(_numberFormatsPath, _nameSpaceManager);
- if (nfNode == null) {
- CreateNode(_numberFormatsPath, true);
- nfNode = _styleXml.SelectSingleNode(_numberFormatsPath, _nameSpaceManager);
- } else {
- nfNode.RemoveAll();
- }
-
- int count = 0;
- int normalIx = NamedStyles.FindIndexById("Normal");
- if (NamedStyles.Count > 0
- && normalIx >= 0
- && NamedStyles[normalIx].Style.Numberformat.NumFmtID >= 164) {
- ExcelNumberFormatXml nf = NumberFormats[NumberFormats.FindIndexById(
- NamedStyles[normalIx].Style.Numberformat.Id)];
- nfNode.AppendChild(
- nf.CreateXmlNode(_styleXml.CreateElement("numFmt", ExcelPackage._schemaMain)));
- nf.newID = count++;
- }
- foreach (ExcelNumberFormatXml nf in NumberFormats) {
- if (!nf.BuildIn /*&& nf.newID<0*/) //Buildin formats are not updated.
- {
- nfNode.AppendChild(
- nf.CreateXmlNode(_styleXml.CreateElement("numFmt", ExcelPackage._schemaMain)));
- nf.newID = count;
- count++;
- }
- }
- (nfNode as XmlElement).SetAttribute("count", count.ToString());
-
- //Font
- count = 0;
- XmlNode fntNode = _styleXml.SelectSingleNode(_fontsPath, _nameSpaceManager);
- fntNode.RemoveAll();
-
- //Normal should be first in the collection
- if (NamedStyles.Count > 0 && normalIx >= 0 && NamedStyles[normalIx].Style.Font.Index > 0) {
- ExcelFontXml fnt = Fonts[NamedStyles[normalIx].Style.Font.Index];
- fntNode.AppendChild(
- fnt.CreateXmlNode(_styleXml.CreateElement("font", ExcelPackage._schemaMain)));
- fnt.newID = count++;
- }
-
- foreach (ExcelFontXml fnt in Fonts) {
- if (fnt.useCnt
- > 0 /* && fnt.newID<0*/) {
- fntNode.AppendChild(
- fnt.CreateXmlNode(_styleXml.CreateElement("font", ExcelPackage._schemaMain)));
- fnt.newID = count;
- count++;
- }
- }
- (fntNode as XmlElement).SetAttribute("count", count.ToString());
-
- //Fills
- count = 0;
- XmlNode fillsNode = _styleXml.SelectSingleNode(_fillsPath, _nameSpaceManager);
- fillsNode.RemoveAll();
- Fills[0].useCnt = 1; //Must exist (none);
- Fills[1].useCnt = 1; //Must exist (gray125);
- foreach (ExcelFillXml fill in Fills) {
- if (fill.useCnt > 0) {
- fillsNode.AppendChild(
- fill.CreateXmlNode(_styleXml.CreateElement("fill", ExcelPackage._schemaMain)));
- fill.newID = count;
- count++;
- }
- }
-
- (fillsNode as XmlElement).SetAttribute("count", count.ToString());
-
- //Borders
- count = 0;
- XmlNode bordersNode = _styleXml.SelectSingleNode(_bordersPath, _nameSpaceManager);
- bordersNode.RemoveAll();
- Borders[0].useCnt = 1; //Must exist blank;
- foreach (ExcelBorderXml border in Borders) {
- if (border.useCnt > 0) {
- bordersNode.AppendChild(
- border.CreateXmlNode(_styleXml.CreateElement("border", ExcelPackage._schemaMain)));
- border.newID = count;
- count++;
- }
- }
- (bordersNode as XmlElement).SetAttribute("count", count.ToString());
-
- XmlNode styleXfsNode = _styleXml.SelectSingleNode(_cellStyleXfsPath, _nameSpaceManager);
- if (styleXfsNode == null && NamedStyles.Count > 0) {
- CreateNode(_cellStyleXfsPath);
- styleXfsNode = _styleXml.SelectSingleNode(_cellStyleXfsPath, _nameSpaceManager);
- }
- if (NamedStyles.Count > 0) {
- styleXfsNode.RemoveAll();
- }
- //NamedStyles
- count = normalIx > -1 ? 1 : 0; //If we have a normal style, we make sure it's added first.
-
- XmlNode cellStyleNode = _styleXml.SelectSingleNode(_cellStylesPath, _nameSpaceManager);
- if (cellStyleNode != null) {
- cellStyleNode.RemoveAll();
- }
- XmlNode cellXfsNode = _styleXml.SelectSingleNode(_cellXfsPath, _nameSpaceManager);
- cellXfsNode.RemoveAll();
-
- if (NamedStyles.Count > 0 && normalIx >= 0) {
- NamedStyles[normalIx].newID = 0;
- AddNamedStyle(0, styleXfsNode, cellXfsNode, NamedStyles[normalIx]);
- }
- foreach (ExcelNamedStyleXml style in NamedStyles) {
- if (!style.Name.Equals("normal", StringComparison.InvariantCultureIgnoreCase)) {
- AddNamedStyle(count++, styleXfsNode, cellXfsNode, style);
- } else {
- style.newID = 0;
- }
- cellStyleNode.AppendChild(
- style.CreateXmlNode(_styleXml.CreateElement("cellStyle", ExcelPackage._schemaMain)));
- }
- if (cellStyleNode != null) {
- (cellStyleNode as XmlElement).SetAttribute("count", count.ToString());
- }
- if (styleXfsNode != null) {
- (styleXfsNode as XmlElement).SetAttribute("count", count.ToString());
- }
-
- //CellStyle
- int xfix = 0;
- foreach (ExcelXfs xf in CellXfs) {
- if (xf.useCnt > 0 && !(normalIx >= 0 && NamedStyles[normalIx].XfId == xfix)) {
- cellXfsNode.AppendChild(
- xf.CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage._schemaMain)));
- xf.newID = count;
- count++;
- }
- xfix++;
- }
- (cellXfsNode as XmlElement).SetAttribute("count", count.ToString());
-
- //Set dxf styling for conditional Formatting
- XmlNode dxfsNode = _styleXml.SelectSingleNode(_dxfsPath, _nameSpaceManager);
- foreach (var ws in _wb.Worksheets) {
- if (ws is ExcelChartsheet) {
- continue;
- }
- foreach (var cf in ws.ConditionalFormatting) {
- if (cf.Style.HasValue) {
- int ix = Dxfs.FindIndexById(cf.Style.Id);
- if (ix < 0) {
- ((ExcelConditionalFormattingRule)cf).DxfId = Dxfs.Count;
- Dxfs.Add(cf.Style.Id, cf.Style);
- var elem = ((XmlDocument)TopNode).CreateElement("d", "dxf", ExcelPackage._schemaMain);
- cf.Style.CreateNodes(new XmlHelperInstance(NameSpaceManager, elem), "");
- dxfsNode.AppendChild(elem);
- } else {
- ((ExcelConditionalFormattingRule)cf).DxfId = ix;
- }
- }
- }
- }
- if (dxfsNode != null) {
- (dxfsNode as XmlElement).SetAttribute("count", Dxfs.Count.ToString());
- }
- }
-
- private void AddNamedStyle(
- int id,
- XmlNode styleXfsNode,
- XmlNode cellXfsNode,
- ExcelNamedStyleXml style) {
- var styleXfs = CellStyleXfs[style.StyleXfId];
- styleXfsNode.AppendChild(
- styleXfs.CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage._schemaMain), true));
- styleXfs.newID = id;
- styleXfs.XfId = style.StyleXfId;
-
- var ix = CellXfs.FindIndexById(styleXfs.Id);
- if (ix < 0) {
- cellXfsNode.AppendChild(
- styleXfs.CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage._schemaMain)));
- } else {
- if (id < 0) {
- CellXfs[ix].XfId = id;
- }
- cellXfsNode.AppendChild(
- CellXfs[ix].CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage._schemaMain)));
- CellXfs[ix].useCnt = 0;
- CellXfs[ix].newID = id;
- }
-
- if (style.XfId >= 0) {
- style.XfId = CellXfs[style.XfId].newID;
- } else {
- style.XfId = 0;
- }
- }
-
- private void RemoveUnusedStyles() {
- CellXfs[0].useCnt = 1; //First item is allways used.
- foreach (ExcelWorksheet sheet in _wb.Worksheets) {
- var cse = new CellsStoreEnumerator<int>(sheet._styles);
- while (cse.Next()) {
- var v = cse.Value;
- if (v >= 0) {
- CellXfs[v].useCnt++;
- }
- }
- }
- foreach (ExcelNamedStyleXml ns in NamedStyles) {
- CellStyleXfs[ns.StyleXfId].useCnt++;
- }
-
- foreach (ExcelXfs xf in CellXfs) {
- if (xf.useCnt > 0) {
- if (xf.FontId >= 0) {
- Fonts[xf.FontId].useCnt++;
- }
- if (xf.FillId >= 0) {
- Fills[xf.FillId].useCnt++;
- }
- if (xf.BorderId >= 0) {
- Borders[xf.BorderId].useCnt++;
- }
- }
- }
- foreach (ExcelXfs xf in CellStyleXfs) {
- if (xf.useCnt > 0) {
- if (xf.FontId >= 0) {
- Fonts[xf.FontId].useCnt++;
- }
- if (xf.FillId >= 0) {
- Fills[xf.FillId].useCnt++;
- }
- if (xf.BorderId >= 0) {
- Borders[xf.BorderId].useCnt++;
- }
- }
- }
- }
-
- internal int GetStyleIdFromName(string name) {
- int i = NamedStyles.FindIndexById(name);
- if (i >= 0) {
- int id = NamedStyles[i].XfId;
- if (id < 0) {
- int styleXfId = NamedStyles[i].StyleXfId;
- ExcelXfs newStyle = CellStyleXfs[styleXfId].Copy();
- newStyle.XfId = styleXfId;
- id = CellXfs.FindIndexById(newStyle.Id);
- if (id < 0) {
- id = CellXfs.Add(newStyle.Id, newStyle);
- }
- NamedStyles[i].XfId = id;
- }
- return id;
- }
- return 0;
- //throw(new Exception("Named style does not exist"));
- }
-
- private string GetXmlNode(XmlNode node) {
- if (node == null) {
- return "";
- }
- if (node.Value != null) {
- return node.Value;
- }
- return "";
- }
-
- internal int CloneStyle(ExcelStyles style, int styleId) {
- return CloneStyle(style, styleId, false, false);
- }
-
- internal int CloneStyle(ExcelStyles style, int styleId, bool isNamedStyle) {
- return CloneStyle(style, styleId, isNamedStyle, false);
- }
-
- internal int CloneStyle(ExcelStyles style, int styleId, bool isNamedStyle, bool allwaysAdd) {
- var xfs = isNamedStyle ? style.CellStyleXfs[styleId] : style.CellXfs[styleId];
- ExcelXfs newXfs = xfs.Copy(this);
- //Numberformat
- if (xfs.NumberFormatId > 0) {
- //rake36: Two problems here...
- //rake36: 1. the first time through when format stays equal to String.Empty, it adds a string.empty to the list of Number Formats
- //rake36: 2. when adding a second sheet, if the numberformatid == 164, it finds the 164 added by previous sheets but was using the array index
- //rake36: for the numberformatid
-
- string format = string.Empty;
- foreach (var fmt in style.NumberFormats) {
- if (fmt.NumFmtId == xfs.NumberFormatId) {
- format = fmt.Format;
- break;
- }
- }
- //rake36: Don't add another format if it's blank
- if (!String.IsNullOrEmpty(format)) {
- int ix = NumberFormats.FindIndexById(format);
- if (ix < 0) {
- var item = new ExcelNumberFormatXml(NameSpaceManager) {
- Format = format,
- NumFmtId = NumberFormats.NextId++,
- };
- NumberFormats.Add(format, item);
- //rake36: Use the just added format id
- newXfs.NumberFormatId = item.NumFmtId;
- } else {
- //rake36: Use the format id defined by the index... not the index itself
- newXfs.NumberFormatId = NumberFormats[ix].NumFmtId;
- }
- }
- }
-
- //Font
- if (xfs.FontId > -1) {
- int ix = Fonts.FindIndexById(xfs.Font.Id);
- if (ix < 0) {
- ExcelFontXml item = style.Fonts[xfs.FontId].Copy();
- ix = Fonts.Add(xfs.Font.Id, item);
- }
- newXfs.FontId = ix;
- }
-
- //Border
- if (xfs.BorderId > -1) {
- int ix = Borders.FindIndexById(xfs.Border.Id);
- if (ix < 0) {
- ExcelBorderXml item = style.Borders[xfs.BorderId].Copy();
- ix = Borders.Add(xfs.Border.Id, item);
- }
- newXfs.BorderId = ix;
- }
-
- //Fill
- if (xfs.FillId > -1) {
- int ix = Fills.FindIndexById(xfs.Fill.Id);
- if (ix < 0) {
- var item = style.Fills[xfs.FillId].Copy();
- ix = Fills.Add(xfs.Fill.Id, item);
- }
- newXfs.FillId = ix;
- }
-
- //Named style reference
- if (xfs.XfId > 0) {
- var id = style.CellStyleXfs[xfs.XfId].Id;
- var newId = CellStyleXfs.FindIndexById(id);
- if (newId >= 0) {
- newXfs.XfId = newId;
- } else if (style._wb != _wb
- && allwaysAdd
- == false) //Not the same workbook, copy the namedstyle to the workbook or match the id
- {
- var nsFind = style.NamedStyles.ToDictionary(d => (d.StyleXfId));
- if (nsFind.ContainsKey(xfs.XfId)) {
- var st = nsFind[xfs.XfId];
- if (NamedStyles.ExistsKey(st.Name)) {
- newXfs.XfId = NamedStyles.FindIndexById(st.Name);
- } else {
- var ns = CreateNamedStyle(st.Name, st.Style);
- newXfs.XfId = NamedStyles.Count - 1;
- }
- }
- }
- }
-
- int index;
- if (isNamedStyle) {
- index = CellStyleXfs.Add(newXfs.Id, newXfs);
- } else {
- if (allwaysAdd) {
- index = CellXfs.Add(newXfs.Id, newXfs);
- } else {
- index = CellXfs.FindIndexById(newXfs.Id);
- if (index < 0) {
- index = CellXfs.Add(newXfs.Id, newXfs);
- }
- }
- }
- return index;
- }
-}
diff --git a/EPPlus/ExcelTextFormat.cs b/EPPlus/ExcelTextFormat.cs
deleted file mode 100644
index 8029447..0000000
--- a/EPPlus/ExcelTextFormat.cs
+++ /dev/null
@@ -1,130 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Globalization;
-using System.Text;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Discribes a column when reading a text using the ExcelRangeBase.LoadFromText method
-/// </summary>
-public enum eDataTypes {
- /// <summary>
- /// Let the the import decide.
- /// </summary>
- Unknown,
-
- /// <summary>
- /// Always a string.
- /// </summary>
- String,
-
- /// <summary>
- /// Try to convert it to a number. If it fails then add it as a string.
- /// </summary>
- Number,
-
- /// <summary>
- /// Try to convert it to a date. If it fails then add it as a string.
- /// </summary>
- DateTime,
-
- /// <summary>
- /// Try to convert it to a number and divide with 100.
- /// Removes any tailing percent sign (%). If it fails then add it as a string.
- /// </summary>
- Percent,
-}
-
-/// <summary>
-/// Describes how to split a CSV text. Used by the ExcelRange.LoadFromText method
-/// </summary>
-public class ExcelTextFormat {
- /// <summary>
- /// Describes how to split a CSV text
- ///
- /// Default values
- /// <list>
- /// <listheader><term>Property</term><description>Value</description></listheader>
- /// <item><term>Delimiter</term><description>,</description></item>
- /// <item><term>TextQualifier</term><description>None (\0)</description></item>
- /// <item><term>EOL</term><description>CRLF</description></item>
- /// <item><term>Culture</term><description>CultureInfo.InvariantCulture</description></item>
- /// <item><term>DataTypes</term><description>End of line default CRLF</description></item>
- /// <item><term>SkipLinesBeginning</term><description>0</description></item>
- /// <item><term>SkipLinesEnd</term><description>0</description></item>
- /// <item><term>Encoding</term><description>Encoding.ASCII</description></item>
- /// </list>
- /// </summary>
- public ExcelTextFormat() {}
-
- /// <summary>
- /// Delimiter character
- /// </summary>
- public char Delimiter { get; set; } = ',';
-
- /// <summary>
- /// Text qualifier character
- /// </summary>
- public char TextQualifier { get; set; } = '\0';
-
- /// <summary>
- /// End of line characters. Default CRLF
- /// </summary>
- public string EOL { get; set; } = "\r\n";
-
- /// <summary>
- /// Datatypes list for each column (if column is not present Unknown is assumed)
- /// </summary>
- public eDataTypes[] DataTypes { get; set; } = null;
-
- /// <summary>
- /// Culture used when parsing. Default CultureInfo.InvariantCulture
- /// </summary>
- public CultureInfo Culture { get; set; } = CultureInfo.InvariantCulture;
-
- /// <summary>
- /// Number of lines skiped in the begining of the file. Default 0.
- /// </summary>
- public int SkipLinesBeginning { get; set; } = 0;
-
- /// <summary>
- /// Number of lines skiped at the end of the file. Default 0.
- /// </summary>
- public int SkipLinesEnd { get; set; } = 0;
-
- /// <summary>
- /// Only used when reading files from disk using a FileInfo object. Default AscII
- /// </summary>
- public Encoding Encoding { get; set; } = Encoding.ASCII;
-}
diff --git a/EPPlus/ExcelWorkbook.cs b/EPPlus/ExcelWorkbook.cs
deleted file mode 100644
index c581319..0000000
--- a/EPPlus/ExcelWorkbook.cs
+++ /dev/null
@@ -1,785 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- * Richard Tallent Fix escaping of quotes 2012-10-31
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Globalization;
-using System.IO;
-using System.Text;
-using System.Xml;
-using OfficeOpenXml.FormulaParsing;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-using OfficeOpenXml.Packaging;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// How the application should calculate formulas in the workbook
-/// </summary>
-public enum ExcelCalcMode {
- /// <summary>
- /// Indicates that calculations in the workbook are performed automatically when cell values change.
- /// The application recalculates those cells that are dependent on other cells that contain changed values.
- /// This mode of calculation helps to avoid unnecessary calculations.
- /// </summary>
- Automatic,
-
- /// <summary>
- /// Indicates tables be excluded during automatic calculation
- /// </summary>
- AutomaticNoTable,
-
- /// <summary>
- /// Indicates that calculations in the workbook be triggered manually by the user.
- /// </summary>
- Manual,
-}
-
-/// <summary>
-/// Represents the Excel workbook and provides access to all the
-/// document properties and worksheets within the workbook.
-/// </summary>
-public sealed class ExcelWorkbook : XmlHelper {
- internal class SharedStringItem {
- internal int pos;
- internal string Text;
- internal bool isRichText;
- }
-
- private readonly ExcelPackage _package;
- private ExcelWorksheets _worksheets;
- private OfficeProperties _properties;
-
- private ExcelStyles _styles;
-
- internal static ImmutableArray<string> WorkbookSchemaNodeOrder = [
- "fileVersion",
- "fileSharing",
- "workbookPr",
- "workbookProtection",
- "bookViews",
- "sheets",
- "functionGroups",
- "functionPrototypes",
- "externalReferences",
- "definedNames",
- "calcPr",
- "oleSize",
- "customWorkbookViews",
- "pivotCaches",
- "smartTagPr",
- "smartTagTypes",
- "webPublishing",
- "fileRecoveryPr",
- ];
-
- protected override ImmutableArray<string> SchemaNodeOrder => WorkbookSchemaNodeOrder;
-
- internal ExcelWorkbook(ExcelPackage package, XmlNamespaceManager namespaceManager)
- : base(namespaceManager) {
- _package = package;
- _names = new(this);
- _namespaceManager = namespaceManager;
-
- WorkbookXml = package.GetOrCreateXmlDocument(
- WorkbookUri,
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
- ExcelPackage._schemaRelationships + "/officeDocument",
- () => CreateEmptyWorkbookXml(namespaceManager));
- _stylesXml = package.GetOrCreateXmlDocument(
- StylesUri,
- "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
- ExcelPackage._schemaRelationships + "/styles",
- CreateEmptyStylesXml);
-
- TopNode = WorkbookXml.DocumentElement;
- FullCalcOnLoad = true; //Full calculation on load by default, for both new workbooks and templates.
-
- GetSharedStrings();
- GetExternalReferences();
- GetDefinedNames();
- }
-
- private static XmlDocument CreateEmptyWorkbookXml(XmlNamespaceManager namespaceManager) {
- var result = new XmlDocument(namespaceManager.NameTable);
- var wbElem = result.CreateElement("workbook", ExcelPackage._schemaMain);
-
- // Add the relationships namespace
- wbElem.SetAttribute("xmlns:r", ExcelPackage._schemaRelationships);
- result.AppendChild(wbElem);
-
- // Create the bookViews and workbooks element
- var bookViews = result.CreateElement("bookViews", ExcelPackage._schemaMain);
- wbElem.AppendChild(bookViews);
- var workbookView = result.CreateElement("workbookView", ExcelPackage._schemaMain);
- bookViews.AppendChild(workbookView);
-
- return result;
- }
-
- private static XmlDocument CreateEmptyStylesXml() {
- StringBuilder xml = new StringBuilder(
- "<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">");
- xml.Append("<numFmts />");
- xml.Append("<fonts count=\"1\"><font><sz val=\"11\" /><name val=\"Calibri\" /></font></fonts>");
- xml.Append(
- "<fills><fill><patternFill patternType=\"none\" /></fill><fill><patternFill patternType=\"gray125\" /></fill></fills>");
- xml.Append(
- "<borders><border><left /><right /><top /><bottom /><diagonal /></border></borders>");
- xml.Append("<cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" /></cellStyleXfs>");
- xml.Append("<cellXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" xfId=\"0\" /></cellXfs>");
- xml.Append("<cellStyles><cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\" /></cellStyles>");
- xml.Append("<dxfs count=\"0\" />");
- xml.Append("</styleSheet>");
-
- var result = new XmlDocument();
- result.LoadXml(xml.ToString());
- return result;
- }
-
- internal readonly Dictionary<string, SharedStringItem> _sharedStrings = new(); //Used when reading cells.
- internal List<SharedStringItem> _sharedStringsList = new(); //Used when reading cells.
- internal ExcelNamedRangeCollection _names;
- internal int _nextTableID = int.MinValue;
- internal int _nextPivotTableID = int.MinValue;
- private readonly XmlNamespaceManager _namespaceManager;
- private FormulaParser _formulaParser;
- private FormulaParserManager _parserManager;
- internal CellStore<List<Token>> _formulaTokens;
-
- /// <summary>
- /// Read shared strings to list
- /// </summary>
- private void GetSharedStrings() {
- if (_package.Package.PartExists(SharedStringsUri)) {
- var xml = _package.GetXmlDocument(SharedStringsUri);
- XmlNodeList nl = xml.SelectNodes("//d:sst/d:si", NameSpaceManager);
- _sharedStringsList = new();
- if (nl != null) {
- foreach (XmlNode node in nl) {
- XmlNode n = node.SelectSingleNode("d:t", NameSpaceManager);
- if (n != null) {
- _sharedStringsList.Add(
- new() {
- Text = ConvertUtil.ExcelDecodeString(n.InnerText),
- });
- } else {
- _sharedStringsList.Add(
- new() {
- Text = node.InnerXml,
- isRichText = true,
- });
- }
- }
- }
- //Delete the shared string part, it will be recreated when the package is saved.
- foreach (var rel in Part.GetRelationships()) {
- if (rel.TargetUri.OriginalString.EndsWith(
- "sharedstrings.xml",
- StringComparison.InvariantCultureIgnoreCase)) {
- Part.DeleteRelationship(rel.Id);
- break;
- }
- }
- _package.Package.DeletePart(SharedStringsUri); //Remove the part, it is recreated when saved.
- }
- }
-
- internal void GetDefinedNames() {
- XmlNodeList nl = WorkbookXml.SelectNodes("//d:definedNames/d:definedName", NameSpaceManager);
- if (nl != null) {
- foreach (XmlElement elem in nl) {
- string fullAddress = elem.InnerText;
-
- ExcelWorksheet nameWorksheet;
- if (!int.TryParse(elem.GetAttribute("localSheetId"), out var localSheetId)) {
- localSheetId = -1;
- nameWorksheet = null;
- } else {
- nameWorksheet = Worksheets[localSheetId + 1];
- }
- var addressType = ExcelAddressBase.IsValid(fullAddress);
- ExcelRangeBase range;
- ExcelNamedRange namedRange;
-
- if (fullAddress.IndexOf("[") == 0) {
- int start = fullAddress.IndexOf("[");
- int end = fullAddress.IndexOf("]", start);
- if (start >= 0 && end >= 0) {
- string externalIndex = fullAddress.Substring(start + 1, end - start - 1);
- if (int.TryParse(externalIndex, out var index)) {
- if (index > 0 && index <= _externalReferences.Count) {
- fullAddress =
- fullAddress.Substring(0, start)
- + "["
- + _externalReferences[index - 1]
- + "]"
- + fullAddress.Substring(end + 1);
- }
- }
- }
- }
-
- if (addressType == ExcelAddressBase.AddressType.Invalid
- || addressType == ExcelAddressBase.AddressType.InternalName
- || addressType == ExcelAddressBase.AddressType.ExternalName
- || addressType == ExcelAddressBase.AddressType.Formula
- || addressType
- == ExcelAddressBase
- .AddressType
- .ExternalAddress) //A value or a formula
- {
- range = new(this, nameWorksheet, elem.GetAttribute("name"), true);
- if (nameWorksheet == null) {
- namedRange = _names.Add(elem.GetAttribute("name"), range);
- } else {
- namedRange = nameWorksheet.Names.Add(elem.GetAttribute("name"), range);
- }
-
- if (fullAddress.StartsWith(
- "\"")) //String value
- {
- namedRange.NameValue = fullAddress.Substring(1, fullAddress.Length - 2);
- } else if (double.TryParse(
- fullAddress,
- NumberStyles.Any,
- CultureInfo.InvariantCulture,
- out var value)) {
- namedRange.NameValue = value;
- } else {
- //if (addressType == ExcelAddressBase.AddressType.ExternalAddress || addressType == ExcelAddressBase.AddressType.ExternalName)
- //{
- // var r = new ExcelAddress(fullAddress);
- // namedRange.NameFormula = '\'[' + r._wb
- //}
- //else
- //{
- namedRange.NameFormula = fullAddress;
- //}
- }
- } else {
- ExcelAddress addr = new ExcelAddress(fullAddress, this, null);
- if (localSheetId > -1) {
- if (string.IsNullOrEmpty(addr._ws)) {
- namedRange = Worksheets[localSheetId + 1].Names.Add(
- elem.GetAttribute("name"),
- new(this, Worksheets[localSheetId + 1], fullAddress, false));
- } else {
- namedRange = Worksheets[localSheetId + 1].Names.Add(
- elem.GetAttribute("name"),
- new(this, Worksheets[addr._ws], fullAddress, false));
- }
- } else {
- var ws = Worksheets[addr._ws];
- namedRange = _names.Add(elem.GetAttribute("name"), new(this, ws, fullAddress, false));
- }
- }
- if (elem.GetAttribute("hidden") == "1" && namedRange != null) {
- namedRange.IsNameHidden = true;
- }
- if (!string.IsNullOrEmpty(elem.GetAttribute("comment"))) {
- namedRange.NameComment = elem.GetAttribute("comment");
- }
- }
- }
- }
-
- /// <summary>
- /// Provides access to all the worksheets in the workbook.
- /// </summary>
- public ExcelWorksheets Worksheets {
- get {
- if (_worksheets == null) {
- var sheetsNode = WorkbookXml.DocumentElement.SelectSingleNode(
- "d:sheets",
- _namespaceManager);
- if (sheetsNode == null) {
- sheetsNode = CreateNode("d:sheets");
- }
-
- _worksheets = new(_package, this, _namespaceManager, sheetsNode);
- }
- return (_worksheets);
- }
- }
-
- /// <summary>
- /// Provides access to named ranges
- /// </summary>
- public ExcelNamedRangeCollection Names => _names;
-
- internal FormulaParser FormulaParser {
- get {
- if (_formulaParser == null) {
- _formulaParser = new(new EpplusExcelDataProvider(this));
- }
- return _formulaParser;
- }
- }
-
- public FormulaParserManager FormulaParserManager {
- get {
- if (_parserManager == null) {
- _parserManager = new(FormulaParser);
- }
- return _parserManager;
- }
- }
-
- private ExcelProtection _protection;
-
- /// <summary>
- /// Access properties to protect or unprotect a workbook
- /// </summary>
- public ExcelProtection Protection => _protection ??= new(NameSpaceManager, TopNode);
-
- private ExcelWorkbookView _view;
-
- /// <summary>
- /// Access to workbook view properties
- /// </summary>
- public ExcelWorkbookView View {
- get {
- if (_view == null) {
- _view = new(NameSpaceManager, TopNode, this);
- }
- return _view;
- }
- }
-
- /// <summary>
- /// URI to the workbook inside the package
- /// </summary>
- internal static Uri WorkbookUri { get; } = new("/xl/workbook.xml", UriKind.Relative);
-
- /// <summary>
- /// URI to the styles inside the package
- /// </summary>
- private static Uri StylesUri { get; } = new("/xl/styles.xml", UriKind.Relative);
-
- /// <summary>
- /// URI to the shared strings inside the package
- /// </summary>
- private static Uri SharedStringsUri { get; } = new("/xl/sharedStrings.xml", UriKind.Relative);
-
- /// <summary>
- /// Returns a reference to the workbook's part within the package
- /// </summary>
- internal ZipPackagePart Part => (_package.Package.GetPart(WorkbookUri));
-
- /// <summary>
- /// Provides access to the XML data representing the workbook in the package.
- /// </summary>
- internal XmlDocument WorkbookXml { get; }
-
- private const string _codeModuleNamePath = "d:workbookPr/@codeName";
-
- internal string CodeModuleName {
- get => GetXmlNodeString(_codeModuleNamePath);
- set => SetXmlNodeString(_codeModuleNamePath, value);
- }
-
- internal void CodeNameChange(string value) {
- CodeModuleName = value;
- }
-
- private const string _date1904Path = "d:workbookPr/@date1904";
- internal const double _date1904Offset = 365.5 * 4; // offset to fix 1900 and 1904 differences, 4 OLE years
-
- /// <summary>
- /// The date systems used by Microsoft Excel can be based on one of two different dates. By default, a serial number of 1 in Microsoft Excel represents January 1, 1900.
- /// The default for the serial number 1 can be changed to represent January 2, 1904.
- /// This option was included in Microsoft Excel for Windows to make it compatible with Excel for the Macintosh, which defaults to January 2, 1904.
- /// </summary>
- public bool Date1904 {
- get => GetXmlNodeBool(_date1904Path, false);
- set {
- if (Date1904 != value) {
- // Like Excel when the option it's changed update it all cells with Date format
- foreach (var item in Worksheets) {
- item.UpdateCellsWithDate1904Setting();
- }
- }
-
- SetXmlNodeBool(_date1904Path, value, false);
- }
- }
-
- private readonly XmlDocument _stylesXml;
-
- /// <summary>
- /// Package styles collection. Used internally to access style data.
- /// </summary>
- public ExcelStyles Styles {
- get {
- if (_styles == null) {
- _styles = new(NameSpaceManager, _stylesXml, this);
- }
- return _styles;
- }
- }
-
- /// <summary>
- /// The office document properties
- /// </summary>
- public OfficeProperties Properties {
- get {
- if (_properties == null) {
- // Create a NamespaceManager to handle the default namespace,
- // and create a prefix for the default namespace:
- _properties = new(_package, NameSpaceManager);
- }
- return _properties;
- }
- }
-
- private readonly string _calcModePath = "d:calcPr/@calcMode";
-
- /// <summary>
- /// Calculation mode for the workbook.
- /// </summary>
- public ExcelCalcMode CalcMode {
- get {
- string calcMode = GetXmlNodeString(_calcModePath);
- switch (calcMode) {
- case "autoNoTable":
- return ExcelCalcMode.AutomaticNoTable;
- case "manual":
- return ExcelCalcMode.Manual;
- default:
- return ExcelCalcMode.Automatic;
- }
- }
- set {
- switch (value) {
- case ExcelCalcMode.AutomaticNoTable:
- SetXmlNodeString(_calcModePath, "autoNoTable");
- break;
- case ExcelCalcMode.Manual:
- SetXmlNodeString(_calcModePath, "manual");
- break;
- default:
- SetXmlNodeString(_calcModePath, "auto");
- break;
- }
- }
- }
-
- private const string _fullCalcOnLoadPath = "d:calcPr/@fullCalcOnLoad";
-
- /// <summary>
- /// Should Excel do a full calculation after the workbook has been loaded?
- /// <remarks>This property is always true for both new workbooks and loaded templates(on load). If this is not the wanted behavior set this property to false.</remarks>
- /// </summary>
- public bool FullCalcOnLoad {
- get => GetXmlNodeBool(_fullCalcOnLoadPath);
- set => SetXmlNodeBool(_fullCalcOnLoadPath, value);
- }
-
- internal void Save() {
- if (Worksheets.Count == 0) {
- throw new InvalidOperationException("The workbook must contain at least one worksheet");
- }
-
- DeleteCalcChain();
- UpdateDefinedNamesXml();
-
- // save the style sheet
- Styles.UpdateXml();
-
- // save all the open worksheets
- var isProtected = Protection.LockWindows || Protection.LockStructure;
- foreach (ExcelWorksheet worksheet in Worksheets) {
- if (isProtected && Protection.LockWindows) {
- worksheet.View.WindowProtection = true;
- }
- worksheet.Save();
- }
-
- _package.Package.CreatePart(
- SharedStringsUri,
- ExcelPackage._contentTypeSharedString,
- SaveSharedStringHandler);
- Part.CreateRelationship(
- UriHelper.GetRelativeUri(WorkbookUri, SharedStringsUri),
- TargetMode.Internal,
- ExcelPackage._schemaRelationships + "/sharedStrings");
-
- // Data validation
- ValidateDataValidations();
- }
-
- private void DeleteCalcChain() {
- //Remove the calc chain if it exists.
- Uri uriCalcChain = new Uri("/xl/calcChain.xml", UriKind.Relative);
- if (_package.Package.PartExists(uriCalcChain)) {
- Uri calcChain = new Uri("calcChain.xml", UriKind.Relative);
- foreach (var relationship in Part.GetRelationships()) {
- if (relationship.TargetUri == calcChain) {
- Part.DeleteRelationship(relationship.Id);
- break;
- }
- }
- // delete the calcChain part
- _package.Package.DeletePart(uriCalcChain);
- }
- }
-
- private void ValidateDataValidations() {
- foreach (var sheet in Worksheets) {
- if (!(sheet is ExcelChartsheet)) {
- sheet.DataValidations.ValidateAll();
- }
- }
- }
-
- private void SaveSharedStringHandler(StreamWriter sw) {
- var cache = new StringBuilder();
- cache.AppendFormat(
- "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><sst xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" count=\"{0}\" uniqueCount=\"{0}\">",
- _sharedStrings.Count);
- foreach (string t in _sharedStrings.Keys) {
- SharedStringItem ssi = _sharedStrings[t];
- if (ssi.isRichText) {
- cache.Append("<si>");
- ConvertUtil.ExcelEncodeString(cache, t);
- cache.Append("</si>");
- } else {
- if (t.Length > 0
- && (t[0] == ' '
- || t[t.Length - 1] == ' '
- || t.Contains(" ")
- || t.Contains("\t")
- || t.Contains("\n")
- || t.Contains(
- "\n"))) //Fixes issue 14849
- {
- cache.Append("<si><t xml:space=\"preserve\">");
- } else {
- cache.Append("<si><t>");
- }
- ConvertUtil.ExcelEncodeString(cache, ConvertUtil.ExcelEscapeString(t));
- cache.Append("</t></si>");
- }
- if (cache.Length > 0x600000) {
- sw.Write(cache.ToString());
- cache = new();
- }
- }
- cache.Append("</sst>");
- sw.Write(cache.ToString());
- sw.Flush();
- Part.CreateRelationship(
- UriHelper.GetRelativeUri(WorkbookUri, SharedStringsUri),
- TargetMode.Internal,
- ExcelPackage._schemaRelationships + "/sharedStrings");
- }
-
- private void UpdateDefinedNamesXml() {
- try {
- XmlNode top = WorkbookXml.SelectSingleNode("//d:definedNames", NameSpaceManager);
- if (!ExistsNames()) {
- if (top != null) {
- TopNode.RemoveChild(top);
- }
- return;
- }
- if (top == null) {
- CreateNode("d:definedNames");
- top = WorkbookXml.SelectSingleNode("//d:definedNames", NameSpaceManager);
- } else {
- top.RemoveAll();
- }
- foreach (ExcelNamedRange name in _names) {
- XmlElement elem = WorkbookXml.CreateElement("definedName", ExcelPackage._schemaMain);
- top.AppendChild(elem);
- elem.SetAttribute("name", name.Name);
- if (name.IsNameHidden) {
- elem.SetAttribute("hidden", "1");
- }
- if (!string.IsNullOrEmpty(name.NameComment)) {
- elem.SetAttribute("comment", name.NameComment);
- }
- SetNameElement(name, elem);
- }
- foreach (ExcelWorksheet ws in _worksheets) {
- if (!(ws is ExcelChartsheet)) {
- foreach (ExcelNamedRange name in ws.Names) {
- XmlElement elem = WorkbookXml.CreateElement("definedName", ExcelPackage._schemaMain);
- top.AppendChild(elem);
- elem.SetAttribute("name", name.Name);
- elem.SetAttribute("localSheetId", name.LocalSheetId.ToString());
- if (name.IsNameHidden) {
- elem.SetAttribute("hidden", "1");
- }
- if (!string.IsNullOrEmpty(name.NameComment)) {
- elem.SetAttribute("comment", name.NameComment);
- }
- SetNameElement(name, elem);
- }
- }
- }
- } catch (Exception ex) {
- throw new("Internal error updating named ranges ", ex);
- }
- }
-
- private void SetNameElement(ExcelNamedRange name, XmlElement elem) {
- if (name.IsName) {
- if (string.IsNullOrEmpty(name.NameFormula)) {
- if ((name.NameValue.GetType().IsPrimitive
- || name.NameValue is double
- || name.NameValue is decimal)) {
- elem.InnerText = Convert
- .ToDouble(name.NameValue, CultureInfo.InvariantCulture)
- .ToString("R15", CultureInfo.InvariantCulture);
- } else if (name.NameValue is DateTime time) {
- elem.InnerText = time.ToOADate().ToString(CultureInfo.InvariantCulture);
- } else {
- elem.InnerText = "\"" + name.NameValue + "\"";
- }
- } else {
- elem.InnerText = name.NameFormula;
- }
- } else {
- elem.InnerText = name.FullAddressAbsolute;
- }
- }
-
- /// <summary>
- /// Is their any names in the workbook or in the sheets.
- /// </summary>
- /// <returns>?</returns>
- private bool ExistsNames() {
- if (_names.Count == 0) {
- foreach (ExcelWorksheet ws in Worksheets) {
- if (ws is ExcelChartsheet) {
- continue;
- }
- if (ws.Names.Count > 0) {
- return true;
- }
- }
- } else {
- return true;
- }
- return false;
- }
-
- internal bool ExistsTableName(string name) {
- foreach (var ws in Worksheets) {
- if (ws.Tables._tableNames.ContainsKey(name)) {
- return true;
- }
- }
- return false;
- }
-
- internal bool ExistsPivotTableName(string name) {
- foreach (var ws in Worksheets) {
- if (ws.PivotTables._pivotTableNames.ContainsKey(name)) {
- return true;
- }
- }
- return false;
- }
-
- internal void AddPivotTable(string cacheId, Uri defUri) {
- CreateNode("d:pivotCaches");
-
- XmlElement item = WorkbookXml.CreateElement("pivotCache", ExcelPackage._schemaMain);
- item.SetAttribute("cacheId", cacheId);
- var rel = Part.CreateRelationship(
- UriHelper.ResolvePartUri(WorkbookUri, defUri),
- TargetMode.Internal,
- ExcelPackage._schemaRelationships + "/pivotCacheDefinition");
- item.SetAttribute("id", ExcelPackage._schemaRelationships, rel.Id);
-
- var pivotCaches = WorkbookXml.SelectSingleNode("//d:pivotCaches", NameSpaceManager);
- pivotCaches.AppendChild(item);
- }
-
- internal List<string> _externalReferences = new();
-
- //internal bool _isCalculated=false;
- internal void GetExternalReferences() {
- XmlNodeList nl = WorkbookXml.SelectNodes(
- "//d:externalReferences/d:externalReference",
- NameSpaceManager);
- if (nl != null) {
- foreach (XmlElement elem in nl) {
- string rId = elem.GetAttribute("r:id");
- var rel = Part.GetRelationship(rId);
- var part = _package.Package.GetPart(UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri));
- XmlDocument xmlExtRef = new XmlDocument();
- LoadXmlSafe(xmlExtRef, part.GetStream());
-
- XmlElement book =
- xmlExtRef.SelectSingleNode("//d:externalBook", NameSpaceManager) as XmlElement;
- if (book != null) {
- string rIdExtRef = book.GetAttribute("r:id");
- var relExtRef = part.GetRelationship(rIdExtRef);
- if (relExtRef != null) {
- _externalReferences.Add(relExtRef.TargetUri.OriginalString);
- }
- }
- }
- }
- }
-
- internal void ReadAllTables() {
- if (_nextTableID > 0) {
- return;
- }
- _nextTableID = 1;
- _nextPivotTableID = 1;
- foreach (var ws in Worksheets) {
- if (!(ws
- is ExcelChartsheet)) //Fixes 15273. Chartsheets should be ignored.
- {
- foreach (var tbl in ws.Tables) {
- if (tbl.Id >= _nextTableID) {
- _nextTableID = tbl.Id + 1;
- }
- }
- foreach (var pt in ws.PivotTables) {
- if (pt.CacheID >= _nextPivotTableID) {
- _nextPivotTableID = pt.CacheID + 1;
- }
- }
- }
- }
- }
-}
diff --git a/EPPlus/ExcelWorkbookView.cs b/EPPlus/ExcelWorkbookView.cs
deleted file mode 100644
index 26a2430..0000000
--- a/EPPlus/ExcelWorkbookView.cs
+++ /dev/null
@@ -1,162 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2011-11-02
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Collections.Immutable;
-using System.Globalization;
-using System.Xml;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Access to workbook view properties
-/// </summary>
-public class ExcelWorkbookView : XmlHelper {
- protected override ImmutableArray<string> SchemaNodeOrder =>
- ExcelWorkbook.WorkbookSchemaNodeOrder;
-
- /// <summary>
- /// Creates a new ExcelWorkbookView which provides access to all the
- /// view states of the worksheet.
- /// </summary>
- /// <param name="ns"></param>
- /// <param name="node"></param>
- /// <param name="wb"></param>
- internal ExcelWorkbookView(XmlNamespaceManager ns, XmlNode node, ExcelWorkbook wb)
- : base(ns, node) {}
-
- private const string _leftPath = "d:bookViews/d:workbookView/@xWindow";
-
- /// <summary>
- /// Position of the upper left corner of the workbook window. In twips.
- /// </summary>
- public int Left {
- get => GetXmlNodeInt(_leftPath);
- internal set => SetXmlNodeString(_leftPath, value.ToString());
- }
-
- private const string _topPath = "d:bookViews/d:workbookView/@yWindow";
-
- /// <summary>
- /// Position of the upper left corner of the workbook window. In twips.
- /// </summary>
- public int Top {
- get => GetXmlNodeInt(_topPath);
- internal set => SetXmlNodeString(_topPath, value.ToString());
- }
-
- private const string _widthPath = "d:bookViews/d:workbookView/@windowWidth";
-
- /// <summary>
- /// Width of the workbook window. In twips.
- /// </summary>
- public int Width {
- get => GetXmlNodeInt(_widthPath);
- internal set => SetXmlNodeString(_widthPath, value.ToString());
- }
-
- private const string _heightPath = "d:bookViews/d:workbookView/@windowHeight";
-
- /// <summary>
- /// Height of the workbook window. In twips.
- /// </summary>
- public int Height {
- get => GetXmlNodeInt(_heightPath);
- internal set => SetXmlNodeString(_heightPath, value.ToString());
- }
-
- private const string _minimizedPath = "d:bookViews/d:workbookView/@minimized";
-
- /// <summary>
- /// If true the the workbook window is minimized.
- /// </summary>
- public bool Minimized {
- get => GetXmlNodeBool(_minimizedPath);
- set => SetXmlNodeString(_minimizedPath, value.ToString());
- }
-
- private const string _showverticalscrollPath = "d:bookViews/d:workbookView/@showVerticalScroll";
-
- /// <summary>
- /// Show the vertical scrollbar
- /// </summary>
- public bool ShowVerticalScrollBar {
- get => GetXmlNodeBool(_showverticalscrollPath, true);
- set => SetXmlNodeBool(_showverticalscrollPath, value, true);
- }
-
- private const string _showhorizontalscrPath = "d:bookViews/d:workbookView/@showHorizontalScroll";
-
- /// <summary>
- /// Show the horizontal scrollbar
- /// </summary>
- public bool ShowHorizontalScrollBar {
- get => GetXmlNodeBool(_showhorizontalscrPath, true);
- set => SetXmlNodeBool(_showhorizontalscrPath, value, true);
- }
-
- private const string _showsheettabsPath = "d:bookViews/d:workbookView/@showSheetTabs";
-
- /// <summary>
- /// Show the sheet tabs
- /// </summary>
- public bool ShowSheetTabs {
- get => GetXmlNodeBool(_showsheettabsPath, true);
- set => SetXmlNodeBool(_showsheettabsPath, value, true);
- }
-
- /// <summary>
- /// Set the window position in twips
- /// </summary>
- /// <param name="left"></param>
- /// <param name="top"></param>
- /// <param name="width"></param>
- /// <param name="height"></param>
- public void SetWindowSize(int left, int top, int width, int height) {
- Left = left;
- Top = top;
- Width = width;
- Height = height;
- }
-
- private const string _activetabPath = "d:bookViews/d:workbookView/@activeTab";
-
- public int ActiveTab {
- get {
- var v = GetXmlNodeInt(_activetabPath);
- if (v < 0) {
- return 0;
- }
- return v;
- }
- set => SetXmlNodeString(_activetabPath, value.ToString(CultureInfo.InvariantCulture));
- }
-}
diff --git a/EPPlus/ExcelWorksheet.cs b/EPPlus/ExcelWorksheet.cs
deleted file mode 100644
index 02fe010..0000000
--- a/EPPlus/ExcelWorksheet.cs
+++ /dev/null
@@ -1,3236 +0,0 @@
-/*******************************************************************************
-* 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 Initial Release 2011-11-02
-* Jan Källman Total rewrite 2010-03-01
-* Jan Källman License changed GPL-->LGPL 2011-12-27
-*******************************************************************************/
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.ComponentModel;
-using System.Globalization;
-using System.IO;
-using System.Security;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Xml;
-using OfficeOpenXml.ConditionalFormatting;
-using OfficeOpenXml.DataValidation;
-using OfficeOpenXml.Drawing.Vml;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-using OfficeOpenXml.Packaging;
-using OfficeOpenXml.Style.XmlAccess;
-using OfficeOpenXml.Table;
-using OfficeOpenXml.Table.PivotTable;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Worksheet hidden enumeration
-/// </summary>
-public enum eWorkSheetHidden {
- /// <summary>
- /// The worksheet is visible
- /// </summary>
- Visible,
-
- /// <summary>
- /// The worksheet is hidden but can be shown by the user via the user interface
- /// </summary>
- Hidden,
-
- /// <summary>
- /// The worksheet is hidden and cannot be shown by the user via the user interface
- /// </summary>
- VeryHidden,
-}
-
-[Flags]
-internal enum CellFlags {
- //Merged = 0x1,
- RichText = 0x2,
- SharedFormula = 0x4,
- ArrayFormula = 0x8,
-}
-
-/// <summary>
-/// Represents an Excel Chartsheet and provides access to its properties and methods
-/// </summary>
-public class ExcelChartsheet : ExcelWorksheet {
- public ExcelChartsheet(
- XmlNamespaceManager ns,
- ExcelPackage pck,
- ExcelWorkbook workbook,
- Uri worksheetUri,
- string name,
- int sheetId,
- int positionId,
- eWorkSheetHidden hidden)
- : base(ns, pck, workbook, worksheetUri, name, sheetId, positionId, hidden) {}
-}
-
-/// <summary>
-/// Represents an Excel worksheet and provides access to its properties and methods
-/// </summary>
-public class ExcelWorksheet : XmlHelper, IEqualityComparer<ExcelWorksheet> {
- internal class Formulas {
- public Formulas(ISourceCodeTokenizer tokenizer) {
- _tokenizer = tokenizer;
- }
-
- public static string RemoveDummyFunction(string formula) {
- const string dummyFunctionConcatenate = "\"&\"";
- const string dummyFunctionPrefix = "IFERROR(__xludf.DUMMYFUNCTION(\"";
- const string dummyFunctionSuffix = "\"),";
-
- if (string.IsNullOrEmpty(formula)) {
- return formula;
- }
-
- // Look for Prefix
- if (!formula.StartsWith(dummyFunctionPrefix)) {
- return formula;
- }
-
- // Look for Suffix
- int index = formula.LastIndexOf(dummyFunctionSuffix);
- if (index < 0) {
- return formula;
- }
-
- // Trim Suffix
- formula = formula.Substring(0, index);
-
- // Trim Prefix
- formula = formula.Replace(dummyFunctionPrefix, "");
-
- // Remove string concatentations from long formulas.
- // Google break the quoted string into 254 character segments which are concatenated.
- if (formula.Length >= 254) {
- formula = formula.Replace(dummyFunctionConcatenate, "");
- }
-
- // Replace doubled quotes with single quote
- formula = formula.Replace("\"\"", "\"");
-
- // Return formula
- return formula;
- }
-
- private readonly ISourceCodeTokenizer _tokenizer;
-
- internal int Index { get; set; }
-
- internal string Address { get; set; }
-
- internal bool IsArray { get; set; }
-
- public string Formula { get; set; }
-
- public int StartRow { get; set; }
-
- public int StartCol { get; set; }
-
- private IEnumerable<Token> Tokens { get; set; }
-
- internal string GetFormula(int row, int column, string worksheet) {
- if ((StartRow == row && StartCol == column) || IsArray) {
- return RemoveDummyFunction(Formula);
- }
-
- if (Tokens == null) {
- Tokens = _tokenizer.Tokenize(RemoveDummyFunction(Formula), worksheet);
- }
-
- string f = "";
- foreach (var token in Tokens) {
- if (token.TokenType == TokenType.ExcelAddress) {
- var a = new ExcelFormulaAddress(token.Value);
- f += a.GetOffset(row - StartRow, column - StartCol);
- } else {
- f += token.Value;
- }
- }
- return f;
- }
- }
-
- /// <summary>
- /// Collection containing merged cell addresses
- /// </summary>
- public class MergeCellsCollection : IEnumerable<string> {
- internal MergeCellsCollection() {}
-
- internal readonly CellStore<int> _cells = new();
- private readonly List<string> _list = new();
-
- internal List<string> List => _list;
-
- public string this[int row, int column] {
- get {
- int ix = -1;
- if (_cells.Exists(row, column, ref ix)
- && ix >= 0
- && ix
- < List.Count) //Fixes issue 15075
- {
- return List[ix];
- }
- return null;
- }
- }
-
- public string this[int index] => _list[index];
-
- internal void Add(ExcelAddressBase address, bool doValidate) {
- //Validate
- if (doValidate && Validate(address) == false) {
- throw (new ArgumentException("Can't merge and already merged range"));
- }
- var ix = _list.Count;
- _list.Add(address.Address);
- SetIndex(address, ix);
- }
-
- private bool Validate(ExcelAddressBase address) {
- int ix = 0;
- if (_cells.Exists(address._fromRow, address._fromCol, ref ix)) {
- if (ix >= 0 && ix < _list.Count && _list[ix] != null && address.Address == _list[ix]) {
- return true;
- }
- return false;
- }
-
- var cse = new CellsStoreEnumerator<int>(
- _cells,
- address._fromRow,
- address._fromCol,
- address._toRow,
- address._toCol);
- //cells
- while (cse.Next()) {
- return false;
- }
- //Entire column
- cse = new(_cells, 0, address._fromCol, 0, address._toCol);
- while (cse.Next()) {
- return false;
- }
- //Entire row
- cse = new(_cells, address._fromRow, 0, address._toRow, 0);
- while (cse.Next()) {
- return false;
- }
- return true;
- }
-
- internal void SetIndex(ExcelAddressBase address, int ix) {
- if (address._fromRow == 1
- && address._toRow
- == ExcelPackage.MaxRows) //Entire row
- {
- for (int col = address._fromCol; col <= address._toCol; col++) {
- _cells.SetValue(0, col, ix);
- }
- } else if (address._fromCol == 1
- && address._toCol
- == ExcelPackage.MaxColumns) //Entire row
- {
- for (int row = address._fromRow; row <= address._toRow; row++) {
- _cells.SetValue(row, 0, ix);
- }
- } else {
- for (int col = address._fromCol; col <= address._toCol; col++) {
- for (int row = address._fromRow; row <= address._toRow; row++) {
- _cells.SetValue(row, col, ix);
- }
- }
- }
- }
-
- public int Count => _list.Count;
-
- internal void Remove(string item) {
- _list.Remove(item);
- }
-
- public IEnumerator<string> GetEnumerator() {
- return _list.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- return _list.GetEnumerator();
- }
-
- internal void Clear(ExcelAddressBase destination) {
- var cse = new CellsStoreEnumerator<int>(
- _cells,
- destination._fromRow,
- destination._fromCol,
- destination._toRow,
- destination._toCol);
- var used = new HashSet<int>();
- while (cse.Next()) {
- var v = cse.Value;
- if (!used.Contains(v) && _list[v] != null) {
- var adr = new ExcelAddressBase(_list[v]);
- if (!(destination.Collide(adr) == ExcelAddressBase.eAddressCollition.Inside
- || destination.Collide(adr) == ExcelAddressBase.eAddressCollition.Equal)) {
- throw (new InvalidOperationException(
- string.Format(
- "Can't delete merged cells. A range is partly merged with the deleted range. {0}",
- adr._address)));
- }
- used.Add(v);
- }
- }
-
- _cells.Clear(
- destination._fromRow,
- destination._fromCol,
- destination._toRow - destination._fromRow + 1,
- destination._toCol - destination._fromCol + 1);
- foreach (var i in used) {
- _list[i] = null;
- }
- }
- }
-
- internal readonly CellStore<object> _values = new();
- internal readonly CellStore<string> _types = new();
- internal readonly CellStore<int> _styles = new();
- internal readonly CellStore<object> _formulas = new();
- internal readonly FlagCellStore _flags = new();
- internal CellStore<List<Token>> _formulaTokens;
-
- internal readonly CellStore<Uri> _hyperLinks = new();
- internal readonly CellStore<ExcelComment> _commentsStore = new();
-
- internal readonly Dictionary<int, Formulas> _sharedFormulas = new();
-
- internal readonly ExcelPackage _package;
- private readonly ExcelWorkbook _workbook;
- private ExcelWorksheetView _sheetView;
-
- internal static ImmutableArray<string> WorksheetSchemaNodeOrder = [
- "sheetPr",
- "tabColor",
- "outlinePr",
- "pageSetUpPr",
- "dimension",
- "sheetViews",
- "sheetFormatPr",
- "cols",
- "sheetData",
- "sheetProtection",
- "protectedRanges",
- "scenarios",
- "autoFilter",
- "sortState",
- "dataConsolidate",
- "customSheetViews",
- "customSheetViews",
- "mergeCells",
- "phoneticPr",
- "conditionalFormatting",
- "dataValidations",
- "hyperlinks",
- "printOptions",
- "pageMargins",
- "pageSetup",
- "headerFooter",
- "linePrint",
- "rowBreaks",
- "colBreaks",
- "customProperties",
- "cellWatches",
- "ignoredErrors",
- "smartTags",
- "drawing",
- "legacyDrawing",
- "legacyDrawingHF",
- "picture",
- "oleObjects",
- "activeXControls",
- "webPublishItems",
- "tableParts",
- "extLst",
- ];
-
- protected override ImmutableArray<string> SchemaNodeOrder => WorksheetSchemaNodeOrder;
-
- internal ExcelWorksheet(
- XmlNamespaceManager ns,
- ExcelPackage excelPackage,
- ExcelWorkbook workbook,
- Uri worksheetUri,
- string name,
- int sheetId,
- int positionId,
- eWorkSheetHidden hidden)
- : base(ns, null) {
- _workbook = workbook;
- _package = excelPackage;
- _names = new(Workbook, this);
-
- Hidden = hidden;
- Name = name;
- PositionID = positionId;
- SheetID = sheetId;
-
- Part = _package.Package.GetPart(worksheetUri);
- Part.SaveHandler = SaveHandler;
-
- // First Columns, rows, cells, mergecells, hyperlinks and pagebreakes are loaded from an
- // XmlTextReader to optimize speed.
- using var stream = Part.GetStream();
- var xr = new XmlTextReader(stream);
- xr.ProhibitDtd = true;
- xr.WhitespaceHandling = WhitespaceHandling.None;
- LoadColumns(xr); //columnXml
- long start = stream.Position;
- LoadCells(xr);
- var nextElementLength = GetAttributeLength(xr);
- long end = stream.Position - nextElementLength;
- LoadMergeCells(xr);
- LoadHyperLinks(xr);
- LoadRowPageBreakes(xr);
- LoadColPageBreakes(xr);
-
- // Then the rest of the XML is extracted and loaded into the WorksheetXml document.
- stream.Seek(0, SeekOrigin.Begin);
- var xml = GetWorkSheetXml(stream, start, end, out var encoding);
-
- //first char is invalid sometimes??
- if (xml[0] != '<') {
- LoadXmlSafe(WorksheetXml, xml.Substring(1, xml.Length - 1), encoding);
- } else {
- LoadXmlSafe(WorksheetXml, xml, encoding);
- }
- ClearNodes();
-
- TopNode = WorksheetXml.DocumentElement;
- }
-
- /// <summary>
- /// The Zip.ZipPackagePart for the worksheet within the package
- /// </summary>
- internal ZipPackagePart Part { get; }
-
- /// <summary>
- /// The unique identifier for the worksheet.
- /// </summary>
- internal int SheetID { get; }
-
- /// <summary>
- /// The position of the worksheet.
- /// </summary>
- internal int PositionID { get; }
-
- /// <summary>
- /// Address for autofilter
- /// <seealso cref="ExcelRangeBase.AutoFilter" />
- /// </summary>
- public ExcelAddressBase AutoFilterAddress {
- get {
- CheckSheetType();
- string address = GetXmlNodeString("d:autoFilter/@ref");
- if (address == "") {
- return null;
- }
- return new(address);
- }
- internal set {
- CheckSheetType();
- SetXmlNodeString("d:autoFilter/@ref", value.Address);
- }
- }
-
- internal void CheckSheetType() {
- if (this is ExcelChartsheet) {
- throw (new NotSupportedException(
- "This property or method is not supported for a Chartsheet"));
- }
- }
-
- /// <summary>
- /// Returns a ExcelWorksheetView object that allows you to set the view state properties of the worksheet
- /// </summary>
- public ExcelWorksheetView View {
- get {
- if (_sheetView == null) {
- XmlNode node = TopNode.SelectSingleNode("d:sheetViews/d:sheetView", NameSpaceManager);
- if (node == null) {
- CreateNode("d:sheetViews/d:sheetView"); //this one shouls always exist. but check anyway
- node = TopNode.SelectSingleNode("d:sheetViews/d:sheetView", NameSpaceManager);
- }
- _sheetView = new(NameSpaceManager, node, this);
- }
- return (_sheetView);
- }
- }
-
- /// <summary>
- /// The worksheet's display name as it appears on the tab
- /// </summary>
- public string Name { get; }
-
- private readonly ExcelNamedRangeCollection _names;
-
- /// <summary>
- /// Provides access to named ranges
- /// </summary>
- public ExcelNamedRangeCollection Names {
- get {
- CheckSheetType();
- return _names;
- }
- }
-
- /// <summary>
- /// Indicates if the worksheet is hidden in the workbook
- /// </summary>
- public eWorkSheetHidden Hidden {
- get {
- string state = _workbook.GetXmlNodeString(
- string.Format("d:sheets/d:sheet[@sheetId={0}]/@state", SheetID));
- if (state == "hidden") {
- return eWorkSheetHidden.Hidden;
- }
- if (state == "veryHidden") {
- return eWorkSheetHidden.VeryHidden;
- }
- return eWorkSheetHidden.Visible;
- }
- set {
- if (value == eWorkSheetHidden.Visible) {
- _workbook.DeleteNode(string.Format("d:sheets/d:sheet[@sheetId={0}]/@state", SheetID));
- } else {
- string v;
- v = value.ToString();
- v = v.Substring(0, 1).ToLower(CultureInfo.InvariantCulture) + v.Substring(1);
- _workbook.SetXmlNodeString(
- string.Format("d:sheets/d:sheet[@sheetId={0}]/@state", SheetID),
- v);
- }
- }
- }
-
- private double _defaultRowHeight = double.NaN;
-
- /// <summary>
- /// Get/set the default height of all rows in the worksheet
- /// </summary>
- public double DefaultRowHeight {
- get {
- CheckSheetType();
- if (double.IsNaN(_defaultRowHeight)) {
- _defaultRowHeight = GetXmlNodeDouble("d:sheetFormatPr/@defaultRowHeight");
- if (double.IsNaN(_defaultRowHeight)) {
- _defaultRowHeight = 15; // Excel default height
- }
- }
- return _defaultRowHeight;
- }
- set {
- CheckSheetType();
- _defaultRowHeight = value;
- SetXmlNodeString(
- "d:sheetFormatPr/@defaultRowHeight",
- value.ToString(CultureInfo.InvariantCulture));
- SetXmlNodeBool("d:sheetFormatPr/@customHeight", value != 15);
-
- if (double.IsNaN(GetXmlNodeDouble("d:sheetFormatPr/@defaultColWidth"))) {
- DefaultColWidth = 9.140625;
- }
- }
- }
-
- /// <summary>
- /// Get/set the default width of all rows in the worksheet
- /// </summary>
- public double DefaultColWidth {
- get {
- CheckSheetType();
- double ret = GetXmlNodeDouble("d:sheetFormatPr/@defaultColWidth");
- if (double.IsNaN(ret)) {
- ret = 9.140625; // Excel's default width
- }
- return ret;
- }
- set {
- CheckSheetType();
- SetXmlNodeString(
- "d:sheetFormatPr/@defaultColWidth",
- value.ToString(CultureInfo.InvariantCulture));
-
- if (double.IsNaN(GetXmlNodeDouble("d:sheetFormatPr/@defaultRowHeight"))) {
- DefaultRowHeight = 15;
- }
- }
- }
-
- /** <outlinePr applyStyles="1" summaryBelow="0" summaryRight="0" /> **/
- private const string _outLineSummaryBelowPath = "d:sheetPr/d:outlinePr/@summaryBelow";
-
- /// <summary>
- /// Summary rows below details
- /// </summary>
- public bool OutLineSummaryBelow {
- get {
- CheckSheetType();
- return GetXmlNodeBool(_outLineSummaryBelowPath);
- }
- set {
- CheckSheetType();
- SetXmlNodeString(_outLineSummaryBelowPath, value ? "1" : "0");
- }
- }
-
- private const string _outLineSummaryRightPath = "d:sheetPr/d:outlinePr/@summaryRight";
-
- /// <summary>
- /// Summary rows to right of details
- /// </summary>
- public bool OutLineSummaryRight {
- get {
- CheckSheetType();
- return GetXmlNodeBool(_outLineSummaryRightPath);
- }
- set {
- CheckSheetType();
- SetXmlNodeString(_outLineSummaryRightPath, value ? "1" : "0");
- }
- }
-
- private const string _outLineApplyStylePath = "d:sheetPr/d:outlinePr/@applyStyles";
-
- /// <summary>
- /// Automatic styles
- /// </summary>
- public bool OutLineApplyStyle {
- get {
- CheckSheetType();
- return GetXmlNodeBool(_outLineApplyStylePath);
- }
- set {
- CheckSheetType();
- SetXmlNodeString(_outLineApplyStylePath, value ? "1" : "0");
- }
- }
-
- private const string _codeModuleNamePath = "d:sheetPr/@codeName";
-
- internal string CodeModuleName {
- get => GetXmlNodeString(_codeModuleNamePath);
- set => SetXmlNodeString(_codeModuleNamePath, value);
- }
-
- /// <summary>
- /// The XML document holding the worksheet data.
- /// All column, row, cell, pagebreak, merged cell and hyperlink-data are loaded into memory and removed from the document when loading the document.
- /// </summary>
- internal XmlDocument WorksheetXml { get; } = new();
-
- internal ExcelVmlDrawingCommentCollection _vmlDrawings;
-
- /// <summary>
- /// Vml drawings. underlaying object for comments
- /// </summary>
- internal ExcelVmlDrawingCommentCollection VmlDrawingsComments {
- get {
- if (_vmlDrawings == null) {
- CreateVmlCollection();
- }
- return _vmlDrawings;
- }
- }
-
- internal ExcelCommentCollection _comments;
-
- /// <summary>
- /// Collection of comments
- /// </summary>
- public ExcelCommentCollection Comments {
- get {
- CheckSheetType();
- if (_comments == null) {
- CreateVmlCollection();
- _comments = new(_package, this, NameSpaceManager);
- }
- return _comments;
- }
- }
-
- private void CreateVmlCollection() {
- var vmlNode = WorksheetXml.DocumentElement.SelectSingleNode(
- "d:legacyDrawing/@r:id",
- NameSpaceManager);
- if (vmlNode == null) {
- _vmlDrawings = new(_package, this, null);
- } else {
- if (Part.RelationshipExists(vmlNode.Value)) {
- var rel = Part.GetRelationship(vmlNode.Value);
- var vmlUri = UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri);
-
- _vmlDrawings = new(_package, this, vmlUri);
- _vmlDrawings.RelId = rel.Id;
- }
- }
- }
-
- /// <summary>
- /// Get the lenth of the attributes
- /// Conditional formatting attributes can be extremly long som get length of the attributes to finetune position.
- /// </summary>
- /// <param name="xr"></param>
- /// <returns></returns>
- private int GetAttributeLength(XmlTextReader xr) {
- if (xr.NodeType != XmlNodeType.Element) {
- return 0;
- }
- var length = 0;
-
- for (int i = 0; i < xr.AttributeCount; i++) {
- var a = xr.GetAttribute(i);
- length += string.IsNullOrEmpty(a) ? 0 : a.Length;
- }
- return length;
- }
-
- private void LoadRowPageBreakes(XmlTextReader xr) {
- if (!ReadUntil(xr, "rowBreaks", "colBreaks")) {
- return;
- }
- while (xr.Read()) {
- if (xr.LocalName == "brk") {
- if (xr.NodeType == XmlNodeType.Element) {
- if (int.TryParse(xr.GetAttribute("id"), out var id)) {
- Row(id).PageBreak = true;
- }
- }
- } else {
- break;
- }
- }
- }
-
- private void LoadColPageBreakes(XmlTextReader xr) {
- if (!ReadUntil(xr, "colBreaks")) {
- return;
- }
- while (xr.Read()) {
- if (xr.LocalName == "brk") {
- if (xr.NodeType == XmlNodeType.Element) {
- if (int.TryParse(xr.GetAttribute("id"), out var id)) {
- Column(id).PageBreak = true;
- }
- }
- } else {
- break;
- }
- }
- }
-
- private void ClearNodes() {
- if (WorksheetXml.SelectSingleNode("//d:cols", NameSpaceManager) != null) {
- WorksheetXml.SelectSingleNode("//d:cols", NameSpaceManager).RemoveAll();
- }
- if (WorksheetXml.SelectSingleNode("//d:mergeCells", NameSpaceManager) != null) {
- WorksheetXml.SelectSingleNode("//d:mergeCells", NameSpaceManager).RemoveAll();
- }
- if (WorksheetXml.SelectSingleNode("//d:hyperlinks", NameSpaceManager) != null) {
- WorksheetXml.SelectSingleNode("//d:hyperlinks", NameSpaceManager).RemoveAll();
- }
- if (WorksheetXml.SelectSingleNode("//d:rowBreaks", NameSpaceManager) != null) {
- WorksheetXml.SelectSingleNode("//d:rowBreaks", NameSpaceManager).RemoveAll();
- }
- if (WorksheetXml.SelectSingleNode("//d:colBreaks", NameSpaceManager) != null) {
- WorksheetXml.SelectSingleNode("//d:colBreaks", NameSpaceManager).RemoveAll();
- }
- }
-
- private const int _blocksize = 8192;
-
- private string GetWorkSheetXml(Stream stream, long start, long end, out Encoding encoding) {
- StreamReader sr = new StreamReader(stream);
- int length = 0;
- char[] block;
- int pos;
- StringBuilder sb = new StringBuilder();
- Match startmMatch,
- endMatch;
- do {
- int size = stream.Length < _blocksize ? (int)stream.Length : _blocksize;
- block = new char[size];
- pos = sr.ReadBlock(block, 0, size);
- sb.Append(block, 0, pos);
- length += size;
- } while (length < start + 20 && length < end);
- startmMatch = Regex.Match(sb.ToString(), string.Format("(<[^>]*{0}[^>]*>)", "sheetData"));
- if (!startmMatch.Success) //Not found
- {
- encoding = sr.CurrentEncoding;
- return sb.ToString();
- }
- string s = sb.ToString();
- string xml = s.Substring(0, startmMatch.Index);
- if (startmMatch.Value.EndsWith("/>")) {
- xml += s.Substring(startmMatch.Index, s.Length - startmMatch.Index);
- } else {
- if (sr.Peek() != -1) {
- /**** Fixes issue 14788. Fix by Philip Garrett ****/
- long endSeekStart = end;
-
- while (endSeekStart >= 0) {
- endSeekStart = Math.Max(endSeekStart - _blocksize, 0);
- int size = (int)(end - endSeekStart);
- stream.Seek(endSeekStart, SeekOrigin.Begin);
- block = new char[size];
- sr = new(stream);
- pos = sr.ReadBlock(block, 0, size);
- sb = new();
- sb.Append(block, 0, pos);
- s = sb.ToString();
- endMatch = Regex.Match(s, string.Format("(</[^>]*{0}[^>]*>)", "sheetData"));
- if (endMatch.Success) {
- break;
- }
- }
- }
- endMatch = Regex.Match(s, string.Format("(</[^>]*{0}[^>]*>)", "sheetData"));
- xml +=
- "<sheetData/>"
- + s.Substring(
- endMatch.Index + endMatch.Length,
- s.Length - (endMatch.Index + endMatch.Length));
- }
- if (sr.Peek() > -1) {
- xml += sr.ReadToEnd();
- }
-
- encoding = sr.CurrentEncoding;
- return xml;
- }
-
- private void GetBlockPos(string xml, string tag, ref int start, ref int end) {
- Match startmMatch,
- endMatch;
- startmMatch = Regex.Match(xml.Substring(start), string.Format("(<[^>]*{0}[^>]*>)", tag)); //"<[a-zA-Z:]*" + tag + "[?]*>");
-
- if (!startmMatch.Success) //Not found
- {
- start = -1;
- end = -1;
- return;
- }
- var startPos = startmMatch.Index + start;
- if (startmMatch.Value.Substring(startmMatch.Value.Length - 2, 1) == "/") {
- end = startPos + startmMatch.Length;
- } else {
- endMatch = Regex.Match(xml.Substring(start), string.Format("(</[^>]*{0}[^>]*>)", tag));
- if (endMatch.Success) {
- end = endMatch.Index + endMatch.Length + start;
- }
- }
- start = startPos;
- }
-
- private bool ReadUntil(XmlTextReader xr, params string[] tagName) {
- if (xr.EOF) {
- return false;
- }
- while (!Array.Exists(tagName, tag => xr.LocalName.EndsWith(tag))) {
- xr.Read();
- if (xr.EOF) {
- return false;
- }
- }
- return (xr.LocalName.EndsWith(tagName[0]));
- }
-
- private void LoadColumns(
- XmlTextReader xr) //(string xml)
- {
- var colList = new List<IRangeId>();
- if (ReadUntil(xr, "cols", "sheetData")) {
- //if (xml != "")
- //{
- //var xr=new XmlTextReader(new StringReader(xml));
- while (xr.Read()) {
- if (xr.NodeType == XmlNodeType.Whitespace) {
- continue;
- }
- if (xr.LocalName != "col") {
- break;
- }
- if (xr.NodeType == XmlNodeType.Element) {
- int min = int.Parse(xr.GetAttribute("min"));
-
- ExcelColumn col = new ExcelColumn(this, min);
-
- col.ColumnMax = int.Parse(xr.GetAttribute("max"));
- col.Width =
- xr.GetAttribute("width") == null
- ? 0
- : double.Parse(xr.GetAttribute("width"), CultureInfo.InvariantCulture);
- col.BestFit =
- xr.GetAttribute("bestFit") != null && xr.GetAttribute("bestFit") == "1"
- ? true
- : false;
- col.Collapsed =
- xr.GetAttribute("collapsed") != null && xr.GetAttribute("collapsed") == "1"
- ? true
- : false;
- col.Phonetic =
- xr.GetAttribute("phonetic") != null && xr.GetAttribute("phonetic") == "1"
- ? true
- : false;
- col.OutlineLevel = (short)(xr.GetAttribute("outlineLevel") == null
- ? 0
- : int.Parse(xr.GetAttribute("outlineLevel"), CultureInfo.InvariantCulture));
- col.Hidden =
- xr.GetAttribute("hidden") != null && xr.GetAttribute("hidden") == "1" ? true : false;
- _values.SetValue(0, min, col);
-
- if (!(xr.GetAttribute("style") == null
- || !int.TryParse(xr.GetAttribute("style"), out var style))) {
- _styles.SetValue(0, min, style);
- }
- }
- }
- }
- }
-
- /// <summary>
- /// Load Hyperlinks
- /// </summary>
- /// <param name="xr">The reader</param>
- private void LoadHyperLinks(XmlTextReader xr) {
- if (!ReadUntil(xr, "hyperlinks", "rowBreaks", "colBreaks")) {
- return;
- }
- while (xr.Read()) {
- if (xr.LocalName == "hyperlink") {
- ExcelCellBase.GetRowColFromAddress(
- xr.GetAttribute("ref"),
- out var fromRow,
- out var fromCol,
- out int toRow,
- out var toCol);
- ExcelHyperLink hl = null;
- if (xr.GetAttribute("id", ExcelPackage._schemaRelationships) != null) {
- var rId = xr.GetAttribute("id", ExcelPackage._schemaRelationships);
- var uri = Part.GetRelationship(rId).TargetUri;
-
- // Get Location, if any. EPPlus Bug 15517
- var location = xr.GetAttribute("location");
- location = (string.IsNullOrEmpty(location)) ? "" : "#" + location;
-
- if (uri.IsAbsoluteUri) {
- try {
- hl = new(uri.AbsoluteUri + location);
- } catch {
- hl = new(uri.OriginalString + location, UriKind.Absolute);
- }
- } else {
- hl = new(uri.OriginalString + location, UriKind.Relative);
- }
-
- hl.RId = rId;
- Part.DeleteRelationship(rId); //Delete the relationship, it is recreated when we save the package.
- } else if (xr.GetAttribute("location") != null) {
- hl = new(xr.GetAttribute("location"), xr.GetAttribute("display"));
- hl.RowSpann = toRow - fromRow;
- hl.ColSpann = toCol - fromCol;
- }
-
- string tt = xr.GetAttribute("tooltip");
- if (!string.IsNullOrEmpty(tt)) {
- hl.ToolTip = tt;
- }
- _hyperLinks.SetValue(fromRow, fromCol, hl);
- } else {
- break;
- }
- }
- }
-
- /// <summary>
- /// Load cells
- /// </summary>
- /// <param name="xr">The reader</param>
- private void LoadCells(XmlTextReader xr) {
- //var cellList=new List<IRangeID>();
- //var rowList = new List<IRangeID>();
- //var formulaList = new List<IRangeID>();
- ReadUntil(xr, "sheetData", "mergeCells", "hyperlinks", "rowBreaks", "colBreaks");
- ExcelAddressBase address = null;
- string type = "";
- int style = 0;
- int row = 0;
- int col = 0;
- xr.Read();
-
- while (!xr.EOF) {
- while (xr.NodeType == XmlNodeType.EndElement) {
- xr.Read();
- }
- if (xr.LocalName == "row") {
- var r = xr.GetAttribute("r");
- if (r == null) {
- row++;
- } else {
- row = Convert.ToInt32(r);
- }
-
- if (DoAddRow(xr)) {
- _values.SetValue(row, 0, AddRow(xr, row));
- if (xr.GetAttribute("s") != null) {
- _styles.SetValue(row, 0, int.Parse(xr.GetAttribute("s"), CultureInfo.InvariantCulture));
- }
- }
- xr.Read();
- } else if (xr.LocalName == "c") {
- //if (cell != null) cellList.Add(cell);
- //cell = new ExcelCell(this, xr.GetAttribute("r"));
- var r = xr.GetAttribute("r");
- if (r == null) {
- //Handle cells with no reference
- col++;
- address = new(row, col, row, col);
- } else {
- address = new(r);
- col = address._fromCol;
- }
-
- //Datetype
- if (xr.GetAttribute("t") != null) {
- type = xr.GetAttribute("t");
- _types.SetValue(address._fromRow, address._fromCol, type);
- } else {
- type = "";
- }
- //Style
- if (xr.GetAttribute("s") != null) {
- style = int.Parse(xr.GetAttribute("s"));
- _styles.SetValue(address._fromRow, address._fromCol, style);
- _values.SetValue(address._fromRow, address._fromCol, null); //TODO:Better Performance ??
- } else {
- style = 0;
- }
- xr.Read();
- } else if (xr.LocalName == "v") {
- SetValueFromXml(xr, type, style, address._fromRow, address._fromCol);
-
- xr.Read();
- } else if (xr.LocalName == "f") {
- string t = xr.GetAttribute("t");
- if (t == null) {
- _formulas.SetValue(address._fromRow, address._fromCol, xr.ReadElementContentAsString());
- _values.SetValue(address._fromRow, address._fromCol, null);
- //formulaList.Add(cell);
- } else if (t == "shared") {
- string si = xr.GetAttribute("si");
- if (si != null) {
- var sfIndex = int.Parse(si);
- _formulas.SetValue(address._fromRow, address._fromCol, sfIndex);
- _values.SetValue(address._fromRow, address._fromCol, null);
- string fAddress = xr.GetAttribute("ref");
- string formula = ConvertUtil.ExcelDecodeString(xr.ReadElementContentAsString());
- if (formula != "") {
- _sharedFormulas.Add(
- sfIndex,
- new(SourceCodeTokenizer.Default) {
- Index = sfIndex,
- Formula = formula,
- Address = fAddress,
- StartRow = address._fromRow,
- StartCol = address._fromCol,
- });
- }
- } else {
- xr.Read(); //Something is wrong in the sheet, read next
- }
- } else if (t
- == "array") //TODO: Array functions are not support yet. Read the formula for the start cell only.
- {
- string aAddress = xr.GetAttribute("ref");
- ExcelRange addressRange = new ExcelRange(this, aAddress);
- string formula = xr.ReadElementContentAsString();
- bool isIndexMatchFormula =
- Regex.IsMatch(formula, @"INDEX\(", RegexOptions.IgnoreCase)
- && Regex.IsMatch(formula, @"MATCH\(", RegexOptions.IgnoreCase)
- && !aAddress.Contains(":");
- if (isIndexMatchFormula) {
- addressRange.IsArrayFormula = false;
- for (int colIndex = addressRange.Start.Column;
- colIndex <= addressRange.End.Column;
- colIndex++) {
- for (int rowIndex = addressRange.Start.Row;
- rowIndex <= addressRange.End.Row;
- rowIndex++) {
- var afIndex = GetMaxShareFunctionIndex(true);
- _formulas.SetValue(rowIndex, colIndex, afIndex);
- _values.SetValue(rowIndex, colIndex, null);
- _sharedFormulas.Add(
- afIndex,
- new(SourceCodeTokenizer.Default) {
- Index = afIndex,
- Formula = formula,
- Address = aAddress,
- StartRow = address._fromRow,
- StartCol = address._fromCol,
- IsArray = false,
- });
- }
- }
- } else {
- addressRange.IsArrayFormula = true;
- var afIndex = GetMaxShareFunctionIndex(true);
- for (int colIndex = addressRange.Start.Column;
- colIndex <= addressRange.End.Column;
- colIndex++) {
- for (int rowIndex = addressRange.Start.Row;
- rowIndex <= addressRange.End.Row;
- rowIndex++) {
- _formulas.SetValue(rowIndex, colIndex, afIndex);
- _values.SetValue(rowIndex, colIndex, null);
- }
- }
- _sharedFormulas.Add(
- afIndex,
- new(SourceCodeTokenizer.Default) {
- Index = afIndex,
- Formula = formula,
- Address = aAddress,
- StartRow = address._fromRow,
- StartCol = address._fromCol,
- IsArray = true,
- });
- }
- } else // ??? some other type
- {
- xr.Read(); //Something is wrong in the sheet, read next
- }
- } else if (xr.LocalName
- == "is") //Inline string
- {
- xr.Read();
- if (xr.LocalName == "t") {
- _values.SetValue(
- address._fromRow,
- address._fromCol,
- ConvertUtil.ExcelDecodeString(xr.ReadElementContentAsString()));
- //cell._value = xr.ReadInnerXml();
- } else {
- _values.SetValue(address._fromRow, address._fromCol, xr.ReadOuterXml());
- _types.SetValue(address._fromRow, address._fromCol, "rt");
- _flags.SetFlagValue(address._fromRow, address._fromCol, true, CellFlags.RichText);
- //cell.IsRichText = true;
- }
- } else {
- break;
- }
- }
- }
-
- private bool DoAddRow(XmlTextReader xr) {
- var c = xr.GetAttribute("r") == null ? 0 : 1;
- if (xr.GetAttribute("spans") != null) {
- c++;
- }
- return xr.AttributeCount > c;
- }
-
- /// <summary>
- /// Load merged cells
- /// </summary>
- /// <param name="xr"></param>
- private void LoadMergeCells(XmlTextReader xr) {
- if (ReadUntil(xr, "mergeCells", "hyperlinks", "rowBreaks", "colBreaks") && !xr.EOF) {
- while (xr.Read()) {
- if (xr.LocalName != "mergeCell") {
- break;
- }
- if (xr.NodeType == XmlNodeType.Element) {
- string address = xr.GetAttribute("ref");
- _mergedCells.Add(new ExcelAddress(address), false);
- }
- }
- }
- }
-
- /// <summary>
- /// Update merged cells
- /// </summary>
- /// <param name="sw">The writer</param>
- private void UpdateMergedCells(StreamWriter sw) {
- sw.Write("<mergeCells>");
- foreach (string address in _mergedCells) {
- sw.Write("<mergeCell ref=\"{0}\" />", address);
- }
- sw.Write("</mergeCells>");
- }
-
- /// <summary>
- /// Reads a row from the XML reader
- /// </summary>
- /// <param name="xr">The reader</param>
- /// <param name="row">The row number</param>
- /// <returns></returns>
- private RowInternal AddRow(XmlTextReader xr, int row) {
- return new() {
- Collapsed =
- (xr.GetAttribute("collapsed") != null && xr.GetAttribute("collapsed") == "1"
- ? true
- : false),
- OutlineLevel =
- (xr.GetAttribute("outlineLevel") == null
- ? (short)0
- : short.Parse(xr.GetAttribute("outlineLevel"), CultureInfo.InvariantCulture)),
- Height =
- (xr.GetAttribute("ht") == null
- ? -1
- : double.Parse(xr.GetAttribute("ht"), CultureInfo.InvariantCulture)),
- Hidden =
- (xr.GetAttribute("hidden") != null && xr.GetAttribute("hidden") == "1" ? true : false),
- Phonetic = xr.GetAttribute("ph") != null && xr.GetAttribute("ph") == "1" ? true : false,
- CustomHeight =
- xr.GetAttribute("customHeight") == null ? false : xr.GetAttribute("customHeight") == "1",
- };
- }
-
- private static readonly DateTime _excelEpoch = new(1899, 12, 30);
-
- public static DateTime IncorrectDurationFromOaDate(double value) {
- // This behavior is wrong. Real OADate values have a discontinuity on 30 December 1899.
- // For real OADate values, the negative sign applies only to the integer portion of
- // the float, *not* to the decimal portion. For example, -0.5 and 0.5 both refer to the
- // same date, and -1.5 is actually 1899-12-29 12:00 (1 day before 1899-12-30 00:00
- // plus 0.5 days), *not* 1899-12-28 12:00 (1.5 days before 1899-12-30 00:00).
- //
- // Unfortunately, AppSheet's duration-handling code gets this very wrong, and treats the
- // duration as the offset from 1899-12-30 00:00. This is correct for positive durations,
- // but it's wrong for negative durations. This code tries to fix the bug that exists in
- // AppSheet's duration-handling code here, and it succeeds in some cases and fails in
- // others.
- //
- // This code also breaks date/time handling for dates before 1899-12-30 00:00 in some
- // cases. Specifically, dates end up being offset by one day.
- //
- // Regardless, changing this behavior is risky, so this code simply replicates the
- // existing behavior for
- if (value >= 0) {
- return DateTime.FromOADate(value);
- }
- // This looks like a very complicated way to call TimeSpan.FromDays(value), but
- // TimeSpan.FromDays actually only guarantees millisecond precision, and critically
- // rounding is different on .NET Core, resulting in values like (e.g.) 3:15:00 being
- // incorrectly rounded.
- var offset = DateTime.FromOADate(-value) - _excelEpoch;
- return _excelEpoch - offset;
- }
-
- private void SetValueFromXml(XmlTextReader xr, string type, int styleId, int row, int col) {
- //XmlNode vnode = colNode.SelectSingleNode("d:v", NameSpaceManager);
- //if (vnode == null) return null;
- if (type == "s") {
- int ix = xr.ReadElementContentAsInt();
-
- // Temporary debugging code to locate intermittent 'Index was out of range' exception.
- if (ix < 0) {
- throw new(
- string.Format(
- "ReadElementContentAsInt returned value '{0}' which is less than zero.",
- ix));
- }
- if (ix >= _workbook._sharedStringsList.Count) {
- throw new(
- string.Format(
- "ReadElementContentAsInt returned index value '{0}' which is greater than _sharedStringsList count of {1}.",
- ix,
- _workbook._sharedStringsList.Count));
- }
-
- _values.SetValue(row, col, _workbook._sharedStringsList[ix].Text);
- if (_workbook._sharedStringsList[ix].isRichText) {
- _flags.SetFlagValue(row, col, true, CellFlags.RichText);
- }
- } else if (type == "str") {
- _values.SetValue(row, col, ConvertUtil.ExcelDecodeString(xr.ReadElementContentAsString()));
- } else if (type == "b") {
- _values.SetValue(row, col, (xr.ReadElementContentAsString() != "0"));
- } else if (type == "e") {
- _values.SetValue(row, col, GetErrorType(xr.ReadElementContentAsString()));
- } else {
- string v = xr.ReadElementContentAsString();
- var nf = Workbook.Styles.CellXfs[styleId].NumberFormatId;
- if ((nf >= 20 && nf <= 21)
- || (nf >= 45
- && nf
- <= 47)) // Duration
- {
- if (double.TryParse(v, NumberStyles.Any, CultureInfo.InvariantCulture, out var res)) {
- if (Workbook.Date1904) {
- res += ExcelWorkbook._date1904Offset;
- }
- if (res >= -657435.0 && res < 2958465.9999999) {
- // Get the Duration value expressed as a DateTime.
- _values.SetValue(row, col, IncorrectDurationFromOaDate(res));
- } else {
- // Cope with Google Sheets export of cells having a formula.
- // Rather than exporting the native value, they export the formatted value.
- _values.SetValue(row, col, v);
- }
- } else {
- // Cope with Google Sheets export of cells having a formula.
- // Rather than exporting the native value, they export the formatted value.
- _values.SetValue(row, col, v);
- }
- } else if ((nf >= 14 && nf <= 19)
- || (nf
- == 22)) // DateTime
- {
- if (double.TryParse(v, NumberStyles.Any, CultureInfo.InvariantCulture, out var res)) {
- if (Workbook.Date1904) {
- res += ExcelWorkbook._date1904Offset;
- }
- if (res >= -657435.0 && res < 2958465.9999999) {
- _values.SetValue(row, col, DateTime.FromOADate(res));
- } else {
- // Cope with Google Sheets export of cells having a formula.
- // Rather than exporting the native value, they export the formatted value.
- _values.SetValue(row, col, v);
- }
- } else {
- // Cope with Google Sheets export of cells having a formula.
- // Rather than exporting the native value, they export the formatted value.
- _values.SetValue(row, col, v);
- }
- } else {
- if (double.TryParse(v, NumberStyles.Any, CultureInfo.InvariantCulture, out var d)) {
- _values.SetValue(row, col, d);
- } else {
- // Cope with Google Sheets export of cells having a formula.
- // Rather than exporting the native value, they export the formatted value.
- _values.SetValue(row, col, v);
-
- //_values.SetValue(row, col, double.NaN);
- }
- }
- }
- }
-
- private object GetErrorType(string v) {
- return ExcelErrorValue.Parse(v.ToUpper(CultureInfo.InvariantCulture));
- //switch(v.ToUpper())
- //{
- // case "#DIV/0!":
- // return new ExcelErrorValue.cre(eErrorType.Div0);
- // case "#REF!":
- // return new ExcelErrorValue(eErrorType.Ref);
- // case "#N/A":
- // return new ExcelErrorValue(eErrorType.NA);
- // case "#NAME?":
- // return new ExcelErrorValue(eErrorType.Name);
- // case "#NULL!":
- // return new ExcelErrorValue(eErrorType.Null);
- // case "#NUM!":
- // return new ExcelErrorValue(eErrorType.Num);
- // default:
- // return new ExcelErrorValue(eErrorType.Value);
- //}
- }
-
- ///// <summary>
- ///// Provides access to an individual cell within the worksheet.
- ///// </summary>
- ///// <param name="row">The row number in the worksheet</param>
- ///// <param name="col">The column number in the worksheet</param>
- ///// <returns></returns>
- //internal ExcelCell Cell(int row, int col)
- //{
- // return new ExcelCell(_values, row, col);
- //}
- /// <summary>
- /// Provides access to a range of cells
- /// </summary>
- public ExcelRange Cells {
- get {
- CheckSheetType();
- return new(this, 1, 1, ExcelPackage.MaxRows, ExcelPackage.MaxColumns);
- }
- }
-
- /// <summary>
- /// Provides access to the selected range of cells
- /// </summary>
- public ExcelRange SelectedRange {
- get {
- CheckSheetType();
- return new(this, View.SelectedRange);
- }
- }
-
- private readonly MergeCellsCollection _mergedCells = new();
-
- /// <summary>
- /// Addresses to merged ranges
- /// </summary>
- public MergeCellsCollection MergedCells {
- get {
- CheckSheetType();
- return _mergedCells;
- }
- }
-
- /// <summary>
- /// Provides access to an individual row within the worksheet so you can set its properties.
- /// </summary>
- /// <param name="row">The row number in the worksheet</param>
- /// <returns></returns>
- public ExcelRow Row(int row) {
- //ExcelRow r;
- //ulong id = ExcelRow.GetRowID(_sheetID, row);
- //TODO: Fixa.
- //var v = _values.GetValue(row, 0);
- //if (v!=null)
- //{
- // var ri=(RowInternal)v;
- // r = new ExcelRow(this, row)
- //}
- //else
- //{
- //r = new ExcelRow(this, row);
- //_values.SetValue(row, 0, r);
- //_rows.Add(r);
- //}
- CheckSheetType();
- if (row < 1 || row > ExcelPackage.MaxRows) {
- throw (new ArgumentException("Row number out of bounds"));
- }
- return new(this, row);
- //return r;
- }
-
- /// <summary>
- /// Provides access to an individual column within the worksheet so you can set its properties.
- /// </summary>
- /// <param name="col">The column number in the worksheet</param>
- /// <returns></returns>
- public ExcelColumn Column(int col) {
- CheckSheetType();
- if (col < 1 || col > ExcelPackage.MaxColumns) {
- throw (new ArgumentException("Column number out of bounds"));
- }
- var column = _values.GetValue(0, col) as ExcelColumn;
- if (column != null) {
- if (column.ColumnMin != column.ColumnMax) {
- int maxCol = column.ColumnMax;
- column.ColumnMax = col;
- ExcelColumn copy = CopyColumn(column, col + 1, maxCol);
- }
- } else {
- int r = 0,
- c = col;
- if (_values.PrevCell(ref r, ref c)) {
- column = _values.GetValue(0, c) as ExcelColumn;
- int maxCol = column.ColumnMax;
- if (maxCol >= col) {
- column.ColumnMax = col - 1;
- if (maxCol > col) {
- ExcelColumn newC = CopyColumn(column, col + 1, maxCol);
- }
- return CopyColumn(column, col, col);
- }
- }
- //foreach (ExcelColumn checkColumn in _columns)
- //{
- // if (col > checkColumn.ColumnMin && col <= checkColumn.ColumnMax)
- // {
- // int maxCol = checkColumn.ColumnMax;
- // checkColumn.ColumnMax = col - 1;
- // if (maxCol > col)
- // {
- // ExcelColumn newC = CopyColumn(checkColumn, col + 1, maxCol);
- // }
- // return CopyColumn(checkColumn, col,col);
- // }
- //}
- column = new(this, col);
- _values.SetValue(0, col, column);
- //_columns.Add(column);
- }
- return column;
- }
-
- /// <summary>
- /// Returns the name of the worksheet
- /// </summary>
- /// <returns>The name of the worksheet</returns>
- public override string ToString() {
- return Name;
- }
-
- internal ExcelColumn CopyColumn(ExcelColumn c, int col, int maxCol) {
- ExcelColumn newC = new ExcelColumn(this, col);
- newC.ColumnMax = maxCol < ExcelPackage.MaxColumns ? maxCol : ExcelPackage.MaxColumns;
- if (c.StyleName != "") {
- newC.StyleName = c.StyleName;
- } else {
- newC.StyleID = c.StyleID;
- }
-
- newC.OutlineLevel = c.OutlineLevel;
- newC.Phonetic = c.Phonetic;
- newC.BestFit = c.BestFit;
- //_columns.Add(newC);
- _values.SetValue(0, col, newC);
- newC._width = c._width;
- newC._hidden = c._hidden;
- return newC;
- }
-
- /// <summary>
- /// Make the current worksheet active.
- /// </summary>
- public void Select() {
- View.TabSelected = true;
- //Select(Address, true);
- }
-
- /// <summary>
- /// Selects a range in the worksheet. The active cell is the topmost cell.
- /// Make the current worksheet active.
- /// </summary>
- /// <param name="address">An address range</param>
- public void Select(string address) {
- Select(address, true);
- }
-
- /// <summary>
- /// Selects a range in the worksheet. The actice cell is the topmost cell.
- /// </summary>
- /// <param name="address">A range of cells</param>
- /// <param name="selectSheet">Make the sheet active</param>
- public void Select(string address, bool selectSheet) {
- CheckSheetType();
- int toCol,
- toRow;
- //Get rows and columns and validate as well
- ExcelCellBase.GetRowColFromAddress(
- address,
- out var fromRow,
- out var fromCol,
- out toRow,
- out toCol);
-
- if (selectSheet) {
- View.TabSelected = true;
- }
- View.SelectedRange = address;
- View.ActiveCell = ExcelCellBase.GetAddress(fromRow, fromCol);
- }
-
- /// <summary>
- /// Selects a range in the worksheet. The active cell is the topmost cell of the first address.
- /// Make the current worksheet active.
- /// </summary>
- /// <param name="address">An address range</param>
- public void Select(ExcelAddress address) {
- CheckSheetType();
- Select(address, true);
- }
-
- /// <summary>
- /// Selects a range in the worksheet. The active cell is the topmost cell of the first address.
- /// </summary>
- /// <param name="address">A range of cells</param>
- /// <param name="selectSheet">Make the sheet active</param>
- public void Select(ExcelAddress address, bool selectSheet) {
- CheckSheetType();
- if (selectSheet) {
- View.TabSelected = true;
- }
- string selAddress =
- ExcelCellBase.GetAddress(address.Start.Row, address.Start.Column)
- + ":"
- + ExcelCellBase.GetAddress(address.End.Row, address.End.Column);
- if (address.Addresses != null) {
- foreach (var a in address.Addresses) {
- selAddress +=
- " "
- + ExcelCellBase.GetAddress(a.Start.Row, a.Start.Column)
- + ":"
- + ExcelCellBase.GetAddress(a.End.Row, a.End.Column);
- }
- }
- View.SelectedRange = selAddress;
- View.ActiveCell = ExcelCellBase.GetAddress(address.Start.Row, address.Start.Column);
- }
-
- /// <summary>
- /// Inserts a new row into the spreadsheet. Existing rows below the position are
- /// shifted down. All formula are updated to take account of the new row.
- /// </summary>
- /// <param name="rowFrom">The position of the new row</param>
- /// <param name="rows">Number of rows to insert</param>
- public void InsertRow(int rowFrom, int rows) {
- InsertRow(rowFrom, rows, 0);
- }
-
- /// <summary>
- /// Inserts a new row into the spreadsheet. Existing rows below the position are
- /// shifted down. All formula are updated to take account of the new row.
- /// </summary>
- /// <param name="rowFrom">The position of the new row</param>
- /// <param name="rows">Number of rows to insert.</param>
- /// <param name="copyStylesFromRow">Copy Styles from this row. Applied to all inserted rows</param>
- public void InsertRow(int rowFrom, int rows, int copyStylesFromRow) {
- CheckSheetType();
- var d = Dimension;
-
- if (rowFrom < 1) {
- throw (new ArgumentOutOfRangeException("rowFrom can't be lesser that 1"));
- }
-
- //Check that cells aren't shifted outside the boundries
- if (d != null && d.End.Row > rowFrom && d.End.Row + rows > ExcelPackage.MaxRows) {
- throw (new ArgumentOutOfRangeException(
- "Can't insert. Rows will be shifted outside the boundries of the worksheet."));
- }
-
- _values.Insert(rowFrom, 0, rows, 0);
- _formulas.Insert(rowFrom, 0, rows, 0);
- _styles.Insert(rowFrom, 0, rows, 0);
- _types.Insert(rowFrom, 0, rows, 0);
- _commentsStore.Insert(rowFrom, 0, rows, 0);
- _hyperLinks.Insert(rowFrom, 0, rows, 0);
- _flags.Insert(rowFrom, 0, rows, 0);
-
- foreach (var f in _sharedFormulas.Values) {
- if (f.StartRow >= rowFrom) {
- f.StartRow += rows;
- }
- var a = new ExcelAddressBase(f.Address);
- if (a._fromRow >= rowFrom) {
- a._fromRow += rows;
- a._toRow += rows;
- } else if (a._toRow >= rowFrom) {
- a._toRow += rows;
- }
- f.Address = ExcelCellBase.GetAddress(a._fromRow, a._fromCol, a._toRow, a._toCol);
- f.Formula = ExcelCellBase.UpdateFormulaReferences(f.Formula, rows, 0, rowFrom, 0);
- }
- var cse = new CellsStoreEnumerator<object>(_formulas);
- while (cse.Next()) {
- if (cse.Value is string) {
- cse.Value = ExcelCellBase.UpdateFormulaReferences(
- cse.Value.ToString(),
- rows,
- 0,
- rowFrom,
- 0);
- }
- }
-
- FixMergedCellsRow(rowFrom, rows, false);
- if (copyStylesFromRow > 0) {
- var cseS = new CellsStoreEnumerator<int>(
- _styles,
- copyStylesFromRow,
- 0,
- copyStylesFromRow,
- ExcelPackage.MaxColumns); //Fixes issue 15068 , 15090
- while (cseS.Next()) {
- for (var r = 0; r < rows; r++) {
- _styles.SetValue(rowFrom + r, cseS.Column, cseS.Value);
- }
- }
- }
- foreach (var tbl in Tables) {
- tbl.Address = tbl.Address.AddRow(rowFrom, rows);
- }
- }
-
- /// <summary>
- /// Inserts a new column into the spreadsheet. Existing columns below the position are
- /// shifted down. All formula are updated to take account of the new column.
- /// </summary>
- /// <param name="columnFrom">The position of the new column</param>
- /// <param name="columns">Number of columns to insert</param>
- public void InsertColumn(int columnFrom, int columns) {
- InsertColumn(columnFrom, columns, 0);
- }
-
- ///<summary>
- /// Inserts a new column into the spreadsheet. Existing column to the left are
- /// shifted. All formula are updated to take account of the new column.
- /// </summary>
- /// <param name="columnFrom">The position of the new column</param>
- /// <param name="columns">Number of columns to insert.</param>
- /// <param name="copyStylesFromColumn">Copy Styles from this column. Applied to all inserted columns</param>
- public void InsertColumn(int columnFrom, int columns, int copyStylesFromColumn) {
- CheckSheetType();
- var d = Dimension;
-
- if (columnFrom < 1) {
- throw (new ArgumentOutOfRangeException("columnFrom can't be lesser that 1"));
- }
- //Check that cells aren't shifted outside the boundries
- if (d != null
- && d.End.Column > columnFrom
- && d.End.Column + columns > ExcelPackage.MaxColumns) {
- throw (new ArgumentOutOfRangeException(
- "Can't insert. Columns will be shifted outside the boundries of the worksheet."));
- }
-
- _values.Insert(0, columnFrom, 0, columns);
- _formulas.Insert(0, columnFrom, 0, columns);
- _styles.Insert(0, columnFrom, 0, columns);
- _types.Insert(0, columnFrom, 0, columns);
- _commentsStore.Insert(0, columnFrom, 0, columns);
- _hyperLinks.Insert(0, columnFrom, 0, columns);
- _flags.Insert(0, columnFrom, 0, columns);
-
- foreach (var f in _sharedFormulas.Values) {
- if (f.StartCol >= columnFrom) {
- f.StartCol += columns;
- }
- var a = new ExcelAddressBase(f.Address);
- if (a._fromCol >= columnFrom) {
- a._fromCol += columns;
- a._toCol += columns;
- } else if (a._toCol >= columnFrom) {
- a._toCol += columns;
- }
- f.Address = ExcelCellBase.GetAddress(a._fromRow, a._fromCol, a._toRow, a._toCol);
- f.Formula = ExcelCellBase.UpdateFormulaReferences(f.Formula, 0, columns, 0, columnFrom);
- }
-
- var cse = new CellsStoreEnumerator<object>(_formulas);
- while (cse.Next()) {
- if (cse.Value is string) {
- cse.Value = ExcelCellBase.UpdateFormulaReferences(
- cse.Value.ToString(),
- 0,
- columns,
- 0,
- columnFrom);
- }
- }
-
- FixMergedCellsColumn(columnFrom, columns, false);
-
- var csec = new CellsStoreEnumerator<object>(_values, 0, 1, 0, ExcelPackage.MaxColumns);
- var lst = new List<ExcelColumn>();
- foreach (var col in csec) {
- if (col is ExcelColumn column) {
- lst.Add(column);
- }
- }
-
- for (int i = lst.Count - 1; i >= 0; i--) {
- var c = lst[i];
- if (c._columnMin >= columnFrom) {
- if (c._columnMin + columns <= ExcelPackage.MaxColumns) {
- c._columnMin += columns;
- } else {
- c._columnMin = ExcelPackage.MaxColumns;
- }
-
- if (c._columnMax + columns <= ExcelPackage.MaxColumns) {
- c._columnMax += columns;
- } else {
- c._columnMax = ExcelPackage.MaxColumns;
- }
- } else if (c._columnMax >= columnFrom) {
- var cc = c._columnMax - columnFrom;
- c._columnMax = columnFrom - 1;
- CopyColumn(c, columnFrom + columns, columnFrom + columns + cc);
- }
- }
-
- if (copyStylesFromColumn > 0) {
- for (var c = 0; c < columns; c++) {
- var col = Column(columnFrom + c);
- col.StyleID = Column(copyStylesFromColumn).StyleID;
- }
- }
- //Adjust tables
- foreach (var tbl in Tables) {
- if (columnFrom > tbl.Address.Start.Column && columnFrom <= tbl.Address.End.Column) {
- InsertTableColumns(columnFrom, columns, tbl);
- }
-
- tbl.Address = tbl.Address.AddColumn(columnFrom, columns);
- }
- }
-
- private static void InsertTableColumns(int columnFrom, int columns, ExcelTable tbl) {
- var node = tbl.Columns[0].TopNode.ParentNode;
- var ix = columnFrom - tbl.Address.Start.Column - 1;
- var insPos = node.ChildNodes[ix];
- ix += 2;
- for (int i = 0; i < columns; i++) {
- var name = tbl.Columns.GetUniqueName(
- string.Format("Column{0}", (ix++).ToString(CultureInfo.InvariantCulture)));
- XmlElement tableColumn = (XmlElement)
- tbl.TableXml.CreateNode(XmlNodeType.Element, "tableColumn", ExcelPackage._schemaMain);
- tableColumn.SetAttribute(
- "id",
- (tbl.Columns.Count + i + 1).ToString(CultureInfo.InvariantCulture));
- tableColumn.SetAttribute("name", name);
- insPos = node.InsertAfter(tableColumn, insPos);
- } //Create tbl Column
- tbl._cols = new(tbl);
- }
-
- /// <summary>
- /// Adds a value to the row of merged cells to fix for inserts or deletes
- /// </summary>
- /// <param name="row"></param>
- /// <param name="rows"></param>
- /// <param name="delete"></param>
- private void FixMergedCellsRow(int row, int rows, bool delete) {
- if (delete) {
- _mergedCells._cells.Delete(row, 0, rows, 0);
- } else {
- _mergedCells._cells.Insert(row, 0, rows, 0);
- }
-
- List<int> removeIndex = new List<int>();
- for (int i = 0; i < _mergedCells.Count; i++) {
- if (!string.IsNullOrEmpty(_mergedCells[i])) {
- ExcelAddressBase addr = new(_mergedCells[i]),
- newAddr;
- if (delete) {
- newAddr = addr.DeleteRow(row, rows);
- if (newAddr == null) {
- removeIndex.Add(i);
- continue;
- }
- } else {
- newAddr = addr.AddRow(row, rows);
- if (newAddr.Address != addr.Address) {
- // _mergedCells._cells.Insert(row, 0, rows, 0);
- _mergedCells.SetIndex(newAddr, i);
- }
- }
-
- if (newAddr.Address != addr.Address) {
- _mergedCells.List[i] = newAddr._address;
- }
- }
- }
- for (int i = removeIndex.Count - 1; i >= 0; i--) {
- _mergedCells.List.RemoveAt(removeIndex[i]);
- }
- }
-
- /// <summary>
- /// Adds a value to the row of merged cells to fix for inserts or deletes
- /// </summary>
- /// <param name="column"></param>
- /// <param name="columns"></param>
- /// <param name="delete"></param>
- private void FixMergedCellsColumn(int column, int columns, bool delete) {
- if (delete) {
- _mergedCells._cells.Delete(0, column, 0, columns);
- } else {
- _mergedCells._cells.Insert(0, column, 0, columns);
- }
- List<int> removeIndex = new List<int>();
- for (int i = 0; i < _mergedCells.Count; i++) {
- if (!string.IsNullOrEmpty(_mergedCells[i])) {
- ExcelAddressBase addr = new(_mergedCells[i]),
- newAddr;
- if (delete) {
- newAddr = addr.DeleteColumn(column, columns);
- if (newAddr == null) {
- removeIndex.Add(i);
- continue;
- }
- } else {
- newAddr = addr.AddColumn(column, columns);
- if (newAddr.Address != addr.Address) {
- _mergedCells.SetIndex(newAddr, i);
- }
- }
-
- if (newAddr.Address != addr.Address) {
- _mergedCells.List[i] = newAddr._address;
- }
- }
- }
- for (int i = removeIndex.Count - 1; i >= 0; i--) {
- _mergedCells.List.RemoveAt(removeIndex[i]);
- }
- }
-
- /// <summary>
- /// Delete the specified row from the worksheet.
- /// </summary>
- /// <param name="row">A row to be deleted</param>
- public void DeleteRow(int row) {
- DeleteRow(row, 1);
- }
-
- /// <summary>
- /// Delete the specified row from the worksheet.
- /// </summary>
- /// <param name="rowFrom">The start row</param>
- /// <param name="rows">Number of rows to delete</param>
- public void DeleteRow(int rowFrom, int rows) {
- CheckSheetType();
- if (rowFrom < 1 || rowFrom + rows > ExcelPackage.MaxRows) {
- throw (new ArgumentException(
- "Row out of range. Spans from 1 to "
- + ExcelPackage.MaxRows.ToString(CultureInfo.InvariantCulture)));
- }
- _values.Delete(rowFrom, 0, rows, ExcelPackage.MaxColumns);
- _types.Delete(rowFrom, 0, rows, ExcelPackage.MaxColumns);
- _formulas.Delete(rowFrom, 0, rows, ExcelPackage.MaxColumns);
- _styles.Delete(rowFrom, 0, rows, ExcelPackage.MaxColumns);
- _flags.Delete(rowFrom, 0, rows, ExcelPackage.MaxColumns);
- _commentsStore.Delete(rowFrom, 0, rows, ExcelPackage.MaxColumns);
- _hyperLinks.Delete(rowFrom, 0, rows, ExcelPackage.MaxColumns);
-
- AdjustFormulasRow(rowFrom, rows);
- FixMergedCellsRow(rowFrom, rows, true);
-
- foreach (var tbl in Tables) {
- tbl.Address = tbl.Address.DeleteRow(rowFrom, rows);
- }
- }
-
- /// <summary>
- /// Delete the specified column from the worksheet.
- /// </summary>
- /// <param name="column">The column to be deleted</param>
- public void DeleteColumn(int column) {
- DeleteColumn(column, 1);
- }
-
- /// <summary>
- /// Delete the specified column from the worksheet.
- /// </summary>
- /// <param name="columnFrom">The start column</param>
- /// <param name="columns">Number of columns to delete</param>
- public void DeleteColumn(int columnFrom, int columns) {
- if (columnFrom < 1 || columnFrom + columns > ExcelPackage.MaxColumns) {
- throw (new ArgumentException(
- "Column out of range. Spans from 1 to "
- + ExcelPackage.MaxColumns.ToString(CultureInfo.InvariantCulture)));
- }
- var col = _values.GetValue(0, columnFrom) as ExcelColumn;
- if (col == null) {
- var r = 0;
- var c = columnFrom;
- if (_values.PrevCell(ref r, ref c)) {
- col = _values.GetValue(0, c) as ExcelColumn;
- if (col._columnMax >= columnFrom) {
- col.ColumnMax = columnFrom - 1;
- }
- }
- }
-
- _values.Delete(0, columnFrom, ExcelPackage.MaxRows, columns);
- _types.Delete(0, columnFrom, ExcelPackage.MaxRows, columns);
- _formulas.Delete(0, columnFrom, ExcelPackage.MaxRows, columns);
- _styles.Delete(0, columnFrom, ExcelPackage.MaxRows, columns);
- _flags.Delete(0, columnFrom, ExcelPackage.MaxRows, columns);
- _commentsStore.Delete(0, columnFrom, ExcelPackage.MaxRows, columns);
- _hyperLinks.Delete(0, columnFrom, ExcelPackage.MaxRows, columns);
-
- AdjustFormulasColumn(columnFrom, columns);
- FixMergedCellsColumn(columnFrom, columns, true);
-
- var csec = new CellsStoreEnumerator<object>(_values, 0, columnFrom, 0, ExcelPackage.MaxColumns);
- foreach (var column in csec) {
- if (column is ExcelColumn excelColumn) {
- if (excelColumn._columnMin >= columnFrom) {
- excelColumn._columnMin -= columns;
- excelColumn._columnMax -= columns;
- }
- }
- }
-
- foreach (var tbl in Tables) {
- if (columnFrom >= tbl.Address.Start.Column && columnFrom <= tbl.Address.End.Column) {
- var node = tbl.Columns[0].TopNode.ParentNode;
- var ix = columnFrom - tbl.Address.Start.Column;
- for (int i = 0; i < columns; i++) {
- if (node.ChildNodes.Count > ix) {
- node.RemoveChild(node.ChildNodes[ix]);
- }
- }
- tbl._cols = new(tbl);
- }
-
- tbl.Address = tbl.Address.DeleteColumn(columnFrom, columns);
- }
- }
-
- internal void AdjustFormulasRow(int rowFrom, int rows) {
- var delSf = new List<int>();
- foreach (var sf in _sharedFormulas.Values) {
- var a = new ExcelAddress(sf.Address).DeleteRow(rowFrom, rows);
- if (a == null) {
- delSf.Add(sf.Index);
- } else {
- sf.Address = a.Address;
- if (sf.StartRow > rowFrom) {
- var r = Math.Min(sf.StartRow - rowFrom, rows);
- sf.Formula = ExcelCellBase.UpdateFormulaReferences(sf.Formula, -r, 0, rowFrom, 0);
- sf.StartRow -= r;
- }
- }
- }
- foreach (var ix in delSf) {
- _sharedFormulas.Remove(ix);
- }
- var cse = new CellsStoreEnumerator<object>(
- _formulas,
- 1,
- 1,
- ExcelPackage.MaxRows,
- ExcelPackage.MaxColumns);
- while (cse.Next()) {
- if (cse.Value is string) {
- cse.Value = ExcelCellBase.UpdateFormulaReferences(
- cse.Value.ToString(),
- -rows,
- 0,
- rowFrom,
- 0);
- }
- }
- }
-
- internal void AdjustFormulasColumn(int columnFrom, int columns) {
- var delSf = new List<int>();
- foreach (var sf in _sharedFormulas.Values) {
- var a = new ExcelAddress(sf.Address).DeleteColumn(columnFrom, columns);
- if (a == null) {
- delSf.Add(sf.Index);
- } else {
- sf.Address = a.Address;
- if (sf.StartCol > columnFrom) {
- var c = Math.Min(sf.StartCol - columnFrom, columns);
- sf.Formula = ExcelCellBase.UpdateFormulaReferences(sf.Formula, 0, -c, 0, 1);
- sf.StartCol -= c;
- }
- }
- }
- foreach (var ix in delSf) {
- _sharedFormulas.Remove(ix);
- }
- var cse = new CellsStoreEnumerator<object>(
- _formulas,
- 1,
- 1,
- ExcelPackage.MaxRows,
- ExcelPackage.MaxColumns);
- while (cse.Next()) {
- if (cse.Value is string) {
- cse.Value = ExcelCellBase.UpdateFormulaReferences(
- cse.Value.ToString(),
- 0,
- -columns,
- 0,
- columnFrom);
- }
- }
- }
-
- /// <summary>
- /// Deletes the specified row from the worksheet.
- /// </summary>
- /// <param name="rowFrom">The number of the start row to be deleted</param>
- /// <param name="rows">Number of rows to delete</param>
- /// <param name="shiftOtherRowsUp">Not used. Rows are always shifted</param>
- public void DeleteRow(int rowFrom, int rows, bool shiftOtherRowsUp) {
- DeleteRow(rowFrom, rows);
- }
-
- /// <summary>
- /// Get the cell value from thw worksheet
- /// </summary>
- /// <param name="row">The row number</param>
- /// <param name="column">The row number</param>
- /// <returns>The value</returns>
- public object GetValue(int row, int column) {
- CheckSheetType();
- var v = _values.GetValue(row, column);
- if (v != null) {
- if (_flags.GetFlagValue(row, column, CellFlags.RichText)) {
- return Cells[row, column].RichText.Text;
- }
- return v;
- }
- return null;
- }
-
- /// <summary>
- /// Get a strongly typed cell value from the worksheet
- /// </summary>
- /// <typeparam name="T">The type</typeparam>
- /// <param name="row">The row number</param>
- /// <param name="column">The row number</param>
- /// <returns>The value. If the value can't be converted to the specified type, the default value will be returned</returns>
- public T GetValue<T>(int row, int column) {
- CheckSheetType();
- //ulong cellID=ExcelCellBase.GetCellID(SheetID, Row, Column);
- var v = _values.GetValue(row, column);
- if (v == null) {
- return default(T);
- }
-
- //var cell=((ExcelCell)_cells[cellID]);
- if (_flags.GetFlagValue(row, column, CellFlags.RichText)) {
- return (T)(object)Cells[row, column].RichText.Text;
- }
- return GetTypedValue<T>(v);
- }
-
- //Thanks to Michael Tran for parts of this method
- internal T GetTypedValue<T>(object v) {
- if (v == null) {
- return default(T);
- }
- Type fromType = v.GetType();
- Type toType = typeof(T);
- if (fromType == toType) {
- return (T)v;
- }
- var cnv = TypeDescriptor.GetConverter(fromType);
- if (toType
- == typeof(DateTime)) //Handle dates
- {
- if (fromType == typeof(TimeSpan)) {
- return ((T)(object)(new DateTime(((TimeSpan)v).Ticks)));
- }
- if (fromType == typeof(string)) {
- if (DateTime.TryParse(v.ToString(), out var dt)) {
- return (T)(object)(dt);
- }
- return default(T);
- }
- if (cnv.CanConvertTo(typeof(double))) {
- return (T)(object)(DateTime.FromOADate((double)cnv.ConvertTo(v, typeof(double))));
- }
- return default(T);
- }
- if (toType
- == typeof(TimeSpan)) //Handle timespan
- {
- if (fromType == typeof(DateTime)) {
- return ((T)(object)(new TimeSpan(((DateTime)v).Ticks)));
- }
- if (fromType == typeof(string)) {
- if (TimeSpan.TryParse(v.ToString(), out var ts)) {
- return (T)(object)(ts);
- }
- return default(T);
- }
- if (cnv.CanConvertTo(typeof(double))) {
- return (T)
- (object)(new TimeSpan(
- DateTime.FromOADate((double)cnv.ConvertTo(v, typeof(double))).Ticks));
- }
- try {
- // Issue 14682 -- "GetValue<decimal>() won't convert strings"
- // As suggested, after all special cases, all .NET to do it's
- // preferred conversion rather than simply returning the default
- return (T)Convert.ChangeType(v, typeof(T));
- } catch (Exception) {
- // This was the previous behaviour -- no conversion is available.
- return default(T);
- }
- }
- if (cnv.CanConvertTo(toType)) {
- return (T)cnv.ConvertTo(v, typeof(T));
- }
- if (toType.IsGenericType && toType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
- toType = Nullable.GetUnderlyingType(toType);
- if (cnv.CanConvertTo(toType)) {
- return (T)cnv.ConvertTo(v, typeof(T));
- }
- }
-
- if (fromType == typeof(double) && toType == typeof(decimal)) {
- return (T)(object)Convert.ToDecimal(v);
- }
- if (fromType == typeof(decimal) && toType == typeof(double)) {
- return (T)(object)Convert.ToDouble(v);
- }
- return default(T);
- }
-
- /// <summary>
- /// Set the value of a cell
- /// </summary>
- /// <param name="row">The row number</param>
- /// <param name="column">The column number</param>
- /// <param name="value">The value</param>
- public void SetValue(int row, int column, object value) {
- CheckSheetType();
- if (row < 1 || column < 1 || row > ExcelPackage.MaxRows && column > ExcelPackage.MaxColumns) {
- throw new ArgumentOutOfRangeException("Row or Column out of range");
- }
- _values.SetValue(row, column, value);
- }
-
- /// <summary>
- /// Set the value of a cell
- /// </summary>
- /// <param name="address">The Excel address</param>
- /// <param name="value">The value</param>
- public void SetValue(string address, object value) {
- CheckSheetType();
- ExcelCellBase.GetRowCol(address, out var row, out var col, true);
- if (row < 1 || col < 1 || row > ExcelPackage.MaxRows && col > ExcelPackage.MaxColumns) {
- throw new ArgumentOutOfRangeException("Address is invalid or out of range");
- }
- _values.SetValue(row, col, value);
- }
-
- /// <summary>
- /// Get MergeCell Index No
- /// </summary>
- /// <param name="row"></param>
- /// <param name="column"></param>
- /// <returns></returns>
- public int GetMergeCellId(int row, int column) {
- for (int i = 0; i < _mergedCells.Count; i++) {
- if (!string.IsNullOrEmpty(_mergedCells[i])) {
- ExcelRange range = Cells[_mergedCells[i]];
-
- if (range.Start.Row <= row && row <= range.End.Row) {
- if (range.Start.Column <= column && column <= range.End.Column) {
- return i + 1;
- }
- }
- }
- }
- return 0;
- }
-
- internal void Save() {
- DeletePrinterSettings();
- if (!(this is ExcelChartsheet)) {
- var d = Dimension;
- if (d == null) {
- DeleteAllNode("d:dimension/@ref");
- } else {
- SetXmlNodeString("d:dimension/@ref", d.Address);
- }
- SaveTables();
- SavePivotTables();
- }
- }
-
- internal void SaveHandler(StreamWriter streamWriter) {
- //Create the nodes if they do not exist.
- if (this is ExcelChartsheet) {
- streamWriter.Write(WorksheetXml.OuterXml);
- } else {
- CreateNode("d:cols");
- CreateNode("d:sheetData");
- CreateNode("d:mergeCells");
- CreateNode("d:hyperlinks");
- CreateNode("d:rowBreaks");
- CreateNode("d:colBreaks");
-
- //StreamWriter sw=new StreamWriter(Part.GetStream(FileMode.Create, FileAccess.Write));
- var xml = WorksheetXml.OuterXml;
- int colStart = 0,
- colEnd = 0;
- GetBlockPos(xml, "cols", ref colStart, ref colEnd);
-
- streamWriter.Write(xml.Substring(0, colStart));
- UpdateColumnData(streamWriter);
-
- int cellStart = colEnd,
- cellEnd = colEnd;
- GetBlockPos(xml, "sheetData", ref cellStart, ref cellEnd);
-
- streamWriter.Write(xml.Substring(colEnd, cellStart - colEnd));
- UpdateRowCellData(streamWriter);
-
- int mergeStart = cellEnd,
- mergeEnd = cellEnd;
-
- GetBlockPos(xml, "mergeCells", ref mergeStart, ref mergeEnd);
- streamWriter.Write(xml.Substring(cellEnd, mergeStart - cellEnd));
-
- CleanupMergedCells(_mergedCells);
- if (_mergedCells.Count > 0) {
- UpdateMergedCells(streamWriter);
- }
-
- int hyperStart = mergeEnd,
- hyperEnd = mergeEnd;
- GetBlockPos(xml, "hyperlinks", ref hyperStart, ref hyperEnd);
- streamWriter.Write(xml.Substring(mergeEnd, hyperStart - mergeEnd));
- UpdateHyperLinks(streamWriter);
-
- int rowBreakStart = hyperEnd,
- rowBreakEnd = hyperEnd;
- GetBlockPos(xml, "rowBreaks", ref rowBreakStart, ref rowBreakEnd);
- streamWriter.Write(xml.Substring(hyperEnd, rowBreakStart - hyperEnd));
- UpdateRowBreaks(streamWriter);
-
- int colBreakStart = rowBreakEnd,
- colBreakEnd = rowBreakEnd;
- GetBlockPos(xml, "colBreaks", ref colBreakStart, ref colBreakEnd);
- streamWriter.Write(xml.Substring(rowBreakEnd, colBreakStart - rowBreakEnd));
- UpdateColBreaks(streamWriter);
- streamWriter.Write(xml.Substring(colBreakEnd, xml.Length - colBreakEnd));
- }
- }
-
- /// <summary>
- /// Delete the printersettings relationship and part.
- /// </summary>
- private void DeletePrinterSettings() {
- //Delete the relationship from the pageSetup tag
- XmlAttribute attr = (XmlAttribute)
- WorksheetXml.SelectSingleNode("//d:pageSetup/@r:id", NameSpaceManager);
- if (attr != null) {
- string relId = attr.Value;
- //First delete the attribute from the XML
- attr.OwnerElement.Attributes.Remove(attr);
- if (Part.RelationshipExists(relId)) {
- var rel = Part.GetRelationship(relId);
- Uri printerSettingsUri = UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri);
- Part.DeleteRelationship(rel.Id);
-
- //Delete the part from the package
- if (_package.Package.PartExists(printerSettingsUri)) {
- _package.Package.DeletePart(printerSettingsUri);
- }
- }
- }
- }
-
- /// <summary>
- /// Save all table data
- /// </summary>
- private void SaveTables() {
- foreach (var tbl in Tables) {
- if (tbl.ShowHeader || tbl.ShowTotal) {
- int colNum = tbl.Address._fromCol;
- var colVal = new HashSet<string>();
- foreach (var col in tbl.Columns) {
- string n = col.Name.ToLower(CultureInfo.InvariantCulture);
- if (tbl.ShowHeader) {
- n = tbl.WorkSheet.GetValue<string>(
- tbl.Address._fromRow,
- tbl.Address._fromCol + col.Position);
- if (string.IsNullOrEmpty(n)) {
- n = col.Name.ToLower(CultureInfo.InvariantCulture);
- } else {
- col.Name = n;
- }
- } else {
- n = col.Name.ToLower(CultureInfo.InvariantCulture);
- }
-
- if (colVal.Contains(n)) {
- throw (new InvalidDataException(
- string.Format(
- "Table {0} Column {1} does not have a unique name.",
- tbl.Name,
- col.Name)));
- }
- colVal.Add(n);
- col.Name = ConvertUtil.ExcelEncodeString(col.Name);
- if (tbl.ShowHeader) {
- _values.SetValue(tbl.Address._fromRow, colNum, col.Name);
- }
- if (tbl.ShowTotal) {
- SetTableTotalFunction(tbl, col, colNum);
- }
- if (!string.IsNullOrEmpty(col.CalculatedColumnFormula)) {
- int fromRow = tbl.ShowHeader ? tbl.Address._fromRow + 1 : tbl.Address._fromRow;
- int toRow = tbl.ShowTotal ? tbl.Address._toRow - 1 : tbl.Address._toRow;
- for (int row = fromRow; row <= toRow; row++) {
- //Cell(row, colNum).Formula = col.CalculatedColumnFormula;
- SetFormula(row, colNum, col.CalculatedColumnFormula);
- }
- }
- colNum++;
- }
- }
- }
- }
-
- internal void SetTableTotalFunction(ExcelTable tbl, ExcelTableColumn col, int colNum = -1) {
- if (tbl.ShowTotal == false) {
- return;
- }
- if (colNum == -1) {
- for (int i = 0; i < tbl.Columns.Count; i++) {
- if (tbl.Columns[i].Name == col.Name) {
- colNum = tbl.Address._fromCol + i;
- }
- }
- }
- if (col.TotalsRowFunction == RowFunctions.Custom) {
- SetFormula(tbl.Address._toRow, colNum, col.TotalsRowFormula);
- } else if (col.TotalsRowFunction != RowFunctions.None) {
- switch (col.TotalsRowFunction) {
- case RowFunctions.Average:
- SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "101"));
- break;
- case RowFunctions.Count:
- SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "102"));
- break;
- case RowFunctions.CountNums:
- SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "103"));
- break;
- case RowFunctions.Max:
- SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "104"));
- break;
- case RowFunctions.Min:
- SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "105"));
- break;
- case RowFunctions.StdDev:
- SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "107"));
- break;
- case RowFunctions.Var:
- SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "110"));
- break;
- case RowFunctions.Sum:
- SetFormula(tbl.Address._toRow, colNum, GetTotalFunction(col, "109"));
- break;
- default:
- throw (new("Unknown RowFunction enum"));
- }
- } else {
- _values.SetValue(tbl.Address._toRow, colNum, col.TotalsRowLabel);
- }
- }
-
- internal void SetFormula(int row, int col, object value) {
- _formulas.SetValue(row, col, value);
- if (!_values.Exists(row, col)) {
- _values.SetValue(row, col, null);
- }
- }
-
- internal void SetStyle(int row, int col, int value) {
- _styles.SetValue(row, col, value);
- if (!_values.Exists(row, col)) {
- _values.SetValue(row, col, null);
- }
- }
-
- private void SavePivotTables() {
- foreach (var pt in PivotTables) {
- if (pt.DataFields.Count > 1) {
- XmlElement parentNode;
- if (pt.DataOnRows) {
- parentNode =
- pt.PivotTableXml.SelectSingleNode("//d:rowFields", pt.NameSpaceManager) as XmlElement;
- if (parentNode == null) {
- pt.CreateNode("d:rowFields");
- parentNode =
- pt.PivotTableXml.SelectSingleNode("//d:rowFields", pt.NameSpaceManager)
- as XmlElement;
- }
- } else {
- parentNode =
- pt.PivotTableXml.SelectSingleNode("//d:colFields", pt.NameSpaceManager) as XmlElement;
- if (parentNode == null) {
- pt.CreateNode("d:colFields");
- parentNode =
- pt.PivotTableXml.SelectSingleNode("//d:colFields", pt.NameSpaceManager)
- as XmlElement;
- }
- }
-
- if (parentNode.SelectSingleNode("d:field[@ x= \"-2\"]", pt.NameSpaceManager) == null) {
- XmlElement fieldNode = pt.PivotTableXml.CreateElement("field", ExcelPackage._schemaMain);
- fieldNode.SetAttribute("x", "-2");
- parentNode.AppendChild(fieldNode);
- }
- }
- var ws = Workbook.Worksheets[pt.CacheDefinition.SourceRange.WorkSheet];
- var t = ws.Tables.GetFromRange(pt.CacheDefinition.SourceRange);
- var fields = pt.CacheDefinition.CacheDefinitionXml.SelectNodes(
- "d:pivotCacheDefinition/d:cacheFields/d:cacheField",
- NameSpaceManager);
- int ix = 0;
- if (fields != null) {
- var flds = new HashSet<string>();
- foreach (XmlElement node in fields) {
- if (ix >= pt.CacheDefinition.SourceRange.Columns) {
- break;
- }
- var fldName = node.GetAttribute("name"); //Fixes issue 15295 dup name error
- if (string.IsNullOrEmpty(fldName)) {
- fldName =
- (t == null
- ? pt.CacheDefinition.SourceRange.Offset(0, ix++, 1, 1).Value.ToString()
- : t.Columns[ix++].Name);
- }
- if (flds.Contains(fldName)) {
- fldName = GetNewName(flds, fldName);
- }
- flds.Add(fldName);
- node.SetAttribute("name", fldName);
- }
- foreach (var df in pt.DataFields) {
- if (string.IsNullOrEmpty(df.Name)) {
- string name;
- if (df.Function == DataFieldFunctions.None) {
- name = df.Field.Name; //Name must be set or Excel will crash on rename.
- } else {
- name = df.Function + " of " + df.Field.Name; //Name must be set or Excel will crash on rename.
- }
- //Make sure name is unique
- var newName = name;
- var i = 2;
- while (pt.DataFields.ExistsDfName(newName, df)) {
- newName = name + (i++).ToString(CultureInfo.InvariantCulture);
- }
- df.Name = newName;
- }
- }
- }
- }
- }
-
- private string GetNewName(HashSet<string> flds, string fldName) {
- int ix = 2;
- while (flds.Contains(fldName + ix.ToString(CultureInfo.InvariantCulture))) {
- ix++;
- }
- return fldName + ix.ToString(CultureInfo.InvariantCulture);
- }
-
- private static string GetTotalFunction(ExcelTableColumn col, string functionNum) {
- return string.Format("SUBTOTAL({0},{1}[{2}])", functionNum, col._tbl.Name, col.Name);
- }
-
- private void CleanupMergedCells(MergeCellsCollection mergedCells) {
- int i = 0;
- while (i < mergedCells.List.Count) {
- if (mergedCells[i] == null) {
- mergedCells.List.RemoveAt(i);
- } else {
- i++;
- }
- }
- }
-
- private void UpdateColBreaks(StreamWriter sw) {
- StringBuilder breaks = new StringBuilder();
- int count = 0;
- var cse = new CellsStoreEnumerator<object>(_values, 0, 0, 0, ExcelPackage.MaxColumns);
- while (cse.Next()) {
- var col = cse.Value as ExcelColumn;
- if (col != null && col.PageBreak) {
- breaks.AppendFormat("<brk id=\"{0}\" max=\"16383\" man=\"1\" />", cse.Column);
- count++;
- }
- }
- if (count > 0) {
- sw.Write("<colBreaks count=\"{0}\" manualBreakCount=\"{0}\">{1}</colBreaks>", count, breaks);
- }
- }
-
- private void UpdateRowBreaks(StreamWriter sw) {
- StringBuilder breaks = new StringBuilder();
- int count = 0;
- var cse = new CellsStoreEnumerator<object>(_values, 0, 0, ExcelPackage.MaxRows, 0);
- //foreach(ExcelRow row in _rows)
- while (cse.Next()) {
- var row = cse.Value as RowInternal;
- if (row != null && row.PageBreak) {
- breaks.AppendFormat("<brk id=\"{0}\" max=\"1048575\" man=\"1\" />", cse.Row);
- count++;
- }
- }
- if (count > 0) {
- sw.Write("<rowBreaks count=\"{0}\" manualBreakCount=\"{0}\">{1}</rowBreaks>", count, breaks);
- }
- }
-
- /// <summary>
- /// Inserts the cols collection into the XML document
- /// </summary>
- private void UpdateColumnData(StreamWriter sw) {
- var cse = new CellsStoreEnumerator<object>(_values, 0, 1, 0, ExcelPackage.MaxColumns);
- bool first = true;
- while (cse.Next()) {
- if (first) {
- sw.Write("<cols>");
- first = false;
- }
- var col = cse.Value as ExcelColumn;
- ExcelStyleCollection<ExcelXfs> cellXfs = _workbook.Styles.CellXfs;
-
- sw.Write("<col min=\"{0}\" max=\"{1}\"", col.ColumnMin, col.ColumnMax);
- if (col.Hidden) {
- //sbXml.Append(" width=\"0\" hidden=\"1\" customWidth=\"1\"");
- sw.Write(" hidden=\"1\"");
- } else if (col.BestFit) {
- sw.Write(" bestFit=\"1\"");
- }
- sw.Write(
- string.Format(
- CultureInfo.InvariantCulture,
- " width=\"{0}\" customWidth=\"1\"",
- col.Width));
- if (col.OutlineLevel > 0) {
- sw.Write(" outlineLevel=\"{0}\" ", col.OutlineLevel);
- if (col.Collapsed) {
- if (col.Hidden) {
- sw.Write(" collapsed=\"1\"");
- } else {
- sw.Write(" collapsed=\"1\" hidden=\"1\""); //Always hidden
- }
- }
- }
- if (col.Phonetic) {
- sw.Write(" phonetic=\"1\"");
- }
-
- var styleId = col.StyleID >= 0 ? cellXfs[col.StyleID].newID : col.StyleID;
- if (styleId > 0) {
- sw.Write(" style=\"{0}\"", styleId);
- }
- sw.Write(" />");
- }
- if (!first) {
- sw.Write("</cols>");
- }
- }
-
- /// <summary>
- /// Insert row and cells into the XML document
- /// </summary>
- private void UpdateRowCellData(StreamWriter sw) {
- ExcelStyleCollection<ExcelXfs> cellXfs = _workbook.Styles.CellXfs;
-
- int row = -1;
-
- var ss = _workbook._sharedStrings;
- var styles = _workbook.Styles;
- var cache = new StringBuilder();
- cache.Append("<sheetData>");
-
- //Set a value for cells with style and no value set.
- var cseStyle = new CellsStoreEnumerator<int>(
- _styles,
- 0,
- 0,
- ExcelPackage.MaxRows,
- ExcelPackage.MaxColumns);
- foreach (var s in cseStyle) {
- if (!_values.Exists(cseStyle.Row, cseStyle.Column)) {
- _values.SetValue(cseStyle.Row, cseStyle.Column, null);
- }
- }
-
- var cse = new CellsStoreEnumerator<object>(
- _values,
- 1,
- 0,
- ExcelPackage.MaxRows,
- ExcelPackage.MaxColumns);
- //foreach (IRangeID r in _cells)
- while (cse.Next()) {
- if (cse.Column > 0) {
- int styleId = cellXfs[styles.GetStyleId(this, cse.Row, cse.Column)].newID;
- //Add the row element if it's a new row
- if (cse.Row != row) {
- WriteRow(cache, cellXfs, row, cse.Row);
- row = cse.Row;
- }
- object v = cse.Value;
- object formula = _formulas.GetValue(cse.Row, cse.Column);
- if (formula is int sfId) {
- var f = _sharedFormulas[sfId];
- if (f.Address.IndexOf(':') > 0) {
- if (f.StartCol == cse.Column && f.StartRow == cse.Row) {
- if (f.IsArray) {
- cache.AppendFormat(
- "<c r=\"{0}\" s=\"{1}\"{5}><f ref=\"{2}\" t=\"array\">{3}</f>{4}</c>",
- cse.CellAddress,
- styleId < 0 ? 0 : styleId,
- f.Address,
- SecurityElement.Escape(f.Formula),
- GetFormulaValue(v),
- GetCellType(v, true));
- } else {
- cache.AppendFormat(
- "<c r=\"{0}\" s=\"{1}\"{6}><f ref=\"{2}\" t=\"shared\" si=\"{3}\">{4}</f>{5}</c>",
- cse.CellAddress,
- styleId < 0 ? 0 : styleId,
- f.Address,
- sfId,
- SecurityElement.Escape(f.Formula),
- GetFormulaValue(v),
- GetCellType(v, true));
- }
- } else if (f.IsArray) {
- cache.AppendFormat(
- "<c r=\"{0}\" s=\"{1}\" />",
- cse.CellAddress,
- styleId < 0 ? 0 : styleId);
- } else {
- cache.AppendFormat(
- "<c r=\"{0}\" s=\"{1}\"{4}><f t=\"shared\" si=\"{2}\" />{3}</c>",
- cse.CellAddress,
- styleId < 0 ? 0 : styleId,
- sfId,
- GetFormulaValue(v),
- GetCellType(v, true));
- }
- } else {
- // We can also have a single cell array formula
- if (f.IsArray) {
- cache.AppendFormat(
- "<c r=\"{0}\" s=\"{1}\"{5}><f ref=\"{2}\" t=\"array\">{3}</f>{4}</c>",
- cse.CellAddress,
- styleId < 0 ? 0 : styleId,
- string.Format("{0}:{1}", f.Address, f.Address),
- SecurityElement.Escape(f.Formula),
- GetFormulaValue(v),
- GetCellType(v, true));
- } else {
- cache.AppendFormat("<c r=\"{0}\" s=\"{1}\">", f.Address, styleId < 0 ? 0 : styleId);
- cache.AppendFormat(
- "<f>{0}</f>{1}</c>",
- SecurityElement.Escape(f.Formula),
- GetFormulaValue(v));
- }
- }
- } else if (formula != null && formula.ToString() != "") {
- cache.AppendFormat(
- "<c r=\"{0}\" s=\"{1}\"{2}>",
- cse.CellAddress,
- styleId < 0 ? 0 : styleId,
- GetCellType(v, true));
- cache.AppendFormat(
- "<f>{0}</f>{1}</c>",
- SecurityElement.Escape(formula.ToString()),
- GetFormulaValue(v));
- } else {
- if (v == null && styleId > 0) {
- cache.AppendFormat(
- "<c r=\"{0}\" s=\"{1}\" />",
- cse.CellAddress,
- styleId < 0 ? 0 : styleId);
- } else if (v != null) {
- if ((v.GetType().IsPrimitive
- || v is double
- || v is decimal
- || v is DateTime
- || v is TimeSpan)) {
- //string sv = GetValueForXml(v);
- cache.AppendFormat(
- "<c r=\"{0}\" s=\"{1}\" {2}>",
- cse.CellAddress,
- styleId < 0 ? 0 : styleId,
- GetCellType(v));
- cache.AppendFormat("{0}</c>", GetFormulaValue(v));
- } else {
- int ix;
- if (!ss.ContainsKey(v.ToString())) {
- ix = ss.Count;
- ss.Add(
- v.ToString(),
- new() {
- isRichText = _flags.GetFlagValue(cse.Row, cse.Column, CellFlags.RichText),
- pos = ix,
- });
- } else {
- ix = ss[v.ToString()].pos;
- }
- cache.AppendFormat(
- "<c r=\"{0}\" s=\"{1}\" t=\"s\">",
- cse.CellAddress,
- styleId < 0 ? 0 : styleId);
- cache.AppendFormat("<v>{0}</v></c>", ix);
- }
- }
- }
- } else //ExcelRow
- {
- WriteRow(cache, cellXfs, row, cse.Row);
- row = cse.Row;
- }
- if (cache.Length > 0x600000) {
- sw.Write(cache.ToString());
- cache = new();
- }
- }
-
- if (row != -1) {
- cache.Append("</row>");
- }
- cache.Append("</sheetData>");
- sw.Write(cache.ToString());
- sw.Flush();
- }
-
- private object GetFormulaValue(object v) {
- if (v != null && v.ToString() != "") {
- return "<v>" + SecurityElement.Escape(GetValueForXml(v)) + "</v>"; //Fixes issue 15071
- }
- return "";
- }
-
- private string GetCellType(object v, bool allowStr = false) {
- if (v is bool) {
- return " t=\"b\"";
- }
- if ((v is double d && double.IsInfinity(d)) || v is ExcelErrorValue) {
- return " t=\"e\"";
- }
- if (allowStr
- && v != null
- && !(v.GetType().IsPrimitive
- || v is double
- || v is decimal
- || v is DateTime
- || v is TimeSpan)) {
- return " t=\"str\"";
- }
- return "";
- }
-
- private string GetValueForXml(object v) {
- string s;
- try {
- if (v is DateTime time) {
- double sdv = time.ToOADate();
-
- if (Workbook.Date1904) {
- sdv -= ExcelWorkbook._date1904Offset;
- }
-
- s = sdv.ToString(CultureInfo.InvariantCulture);
- } else if (v is TimeSpan span) {
- s = new DateTime(span.Ticks).ToOADate().ToString(CultureInfo.InvariantCulture);
- ;
- } else if (v.GetType().IsPrimitive || v is double || v is decimal) {
- if (v is double d && double.IsNaN(d)) {
- s = "";
- } else if (v is double d1 && double.IsInfinity(d1)) {
- s = "#NUM!";
- } else {
- s = Convert
- .ToDouble(v, CultureInfo.InvariantCulture)
- .ToString("R15", CultureInfo.InvariantCulture);
- }
- } else {
- s = v.ToString();
- }
- } catch {
- s = "0";
- }
- return s;
- }
-
- private void WriteRow(
- StringBuilder cache,
- ExcelStyleCollection<ExcelXfs> cellXfs,
- int prevRow,
- int row) {
- if (prevRow != -1) {
- cache.Append("</row>");
- }
- //ulong rowID = ExcelRow.GetRowID(SheetID, row);
- cache.AppendFormat("<row r=\"{0}\" ", row);
- RowInternal currRow = _values.GetValue(row, 0) as RowInternal;
- if (currRow != null) {
- if (currRow.Hidden) {
- cache.Append("ht=\"0\" hidden=\"1\" ");
- } else if (currRow.Height != DefaultRowHeight && currRow.Height >= 0) {
- cache.AppendFormat(CultureInfo.InvariantCulture, "ht=\"{0}\" ", currRow.Height);
- if (currRow.CustomHeight) {
- cache.Append("customHeight=\"1\" ");
- }
- }
-
- if (currRow.OutlineLevel > 0) {
- cache.AppendFormat("outlineLevel =\"{0}\" ", currRow.OutlineLevel);
- if (currRow.Collapsed) {
- if (currRow.Hidden) {
- cache.Append(" collapsed=\"1\" ");
- } else {
- cache.Append(" collapsed=\"1\" hidden=\"1\" "); //Always hidden
- }
- }
- }
- if (currRow.Phonetic) {
- cache.Append("ph=\"1\" ");
- }
- }
- var s = _styles.GetValue(row, 0);
- if (s > 0) {
- cache.AppendFormat("s=\"{0}\" customFormat=\"1\"", cellXfs[s].newID);
- }
- cache.Append(">");
- }
-
- /// <summary>
- /// Update xml with hyperlinks
- /// </summary>
- /// <param name="sw">The stream</param>
- private void UpdateHyperLinks(StreamWriter sw) {
- Dictionary<string, string> hyps = new Dictionary<string, string>();
- var cse = new CellsStoreEnumerator<Uri>(_hyperLinks);
- bool first = true;
- //foreach (ulong cell in _hyperLinks)
- while (cse.Next()) {
- if (first) {
- sw.Write("<hyperlinks>");
- first = false;
- }
- //int row, col;
- var uri = _hyperLinks.GetValue(cse.Row, cse.Column);
- //ExcelCell cell = _cells[cellId] as ExcelCell;
- if (uri is ExcelHyperLink link && !string.IsNullOrEmpty(link.ReferenceAddress)) {
- sw.Write(
- "<hyperlink ref=\"{0}\" location=\"{1}\" {2}{3}/>",
- Cells[cse.Row, cse.Column, cse.Row + link.RowSpann, cse.Column + link.ColSpann].Address,
- ExcelCellBase.GetFullAddress(
- SecurityElement.Escape(Name),
- SecurityElement.Escape(link.ReferenceAddress)),
- string.IsNullOrEmpty(link.Display)
- ? ""
- : "display=\"" + SecurityElement.Escape(link.Display) + "\" ",
- string.IsNullOrEmpty(link.ToolTip)
- ? ""
- : "tooltip=\"" + SecurityElement.Escape(link.ToolTip) + "\" ");
- } else if (uri != null) {
- Uri hyp;
- if (uri is ExcelHyperLink hyperLink) {
- hyp = hyperLink.OriginalUri;
- } else {
- hyp = uri;
- }
- if (!hyps.ContainsKey(hyp.OriginalString)) {
- var relationship = Part.CreateRelationship(
- hyp,
- TargetMode.External,
- ExcelPackage._schemaHyperlink);
- if (uri is ExcelHyperLink hl) {
- sw.Write(
- "<hyperlink ref=\"{0}\" {2}{3}r:id=\"{1}\" />",
- ExcelCellBase.GetAddress(cse.Row, cse.Column),
- relationship.Id,
- string.IsNullOrEmpty(hl.Display)
- ? ""
- : "display=\"" + SecurityElement.Escape(hl.Display) + "\" ",
- string.IsNullOrEmpty(hl.ToolTip)
- ? ""
- : "tooltip=\"" + SecurityElement.Escape(hl.ToolTip) + "\" ");
- } else {
- sw.Write(
- "<hyperlink ref=\"{0}\" r:id=\"{1}\" />",
- ExcelCellBase.GetAddress(cse.Row, cse.Column),
- relationship.Id);
- }
- }
- }
- }
- if (!first) {
- sw.Write("</hyperlinks>");
- }
- }
-
- /// <summary>
- /// Dimension address for the worksheet.
- /// Top left cell to Bottom right.
- /// If the worksheet has no cells, null is returned
- /// </summary>
- public ExcelAddressBase Dimension {
- get {
- CheckSheetType();
- if (_values.GetDimension(out var fromRow, out var fromCol, out var toRow, out var toCol)) {
- var addr = new ExcelAddressBase(fromRow, fromCol, toRow, toCol);
- addr._ws = Name;
- return addr;
- }
- return null;
- }
- }
-
- private ExcelSheetProtection _protection;
-
- /// <summary>
- /// Access to sheet protection properties
- /// </summary>
- public ExcelSheetProtection Protection {
- get {
- if (_protection == null) {
- _protection = new(NameSpaceManager, TopNode);
- }
- return _protection;
- }
- }
-
- private ExcelProtectedRangeCollection _protectedRanges;
-
- public ExcelProtectedRangeCollection ProtectedRanges {
- get {
- if (_protectedRanges == null) {
- _protectedRanges = new(NameSpaceManager, TopNode);
- }
- return _protectedRanges;
- }
- }
-
- private ExcelTableCollection _tables;
-
- /// <summary>
- /// Tables defined in the worksheet.
- /// </summary>
- public ExcelTableCollection Tables {
- get {
- CheckSheetType();
- if (Workbook._nextTableID == int.MinValue) {
- Workbook.ReadAllTables();
- }
- if (_tables == null) {
- _tables = new(this);
- }
- return _tables;
- }
- }
-
- private ExcelPivotTableCollection _pivotTables;
-
- /// <summary>
- /// Pivottables defined in the worksheet.
- /// </summary>
- public ExcelPivotTableCollection PivotTables {
- get {
- CheckSheetType();
- if (_pivotTables == null) {
- if (Workbook._nextPivotTableID == int.MinValue) {
- Workbook.ReadAllTables();
- }
- _pivotTables = new(this);
- }
- return _pivotTables;
- }
- }
-
- private ExcelConditionalFormattingCollection _conditionalFormatting;
-
- /// <summary>
- /// ConditionalFormatting defined in the worksheet. Use the Add methods to create ConditionalFormatting and add them to the worksheet. Then
- /// set the properties on the instance returned.
- /// </summary>
- /// <seealso cref="ExcelConditionalFormattingCollection"/>
- public ExcelConditionalFormattingCollection ConditionalFormatting {
- get {
- CheckSheetType();
- if (_conditionalFormatting == null) {
- _conditionalFormatting = new(this);
- }
- return _conditionalFormatting;
- }
- }
-
- private ExcelDataValidationCollection _dataValidation;
-
- /// <summary>
- /// DataValidation defined in the worksheet. Use the Add methods to create DataValidations and add them to the worksheet. Then
- /// set the properties on the instance returned.
- /// </summary>
- /// <seealso cref="ExcelDataValidationCollection"/>
- public ExcelDataValidationCollection DataValidations {
- get {
- CheckSheetType();
- if (_dataValidation == null) {
- _dataValidation = new(this);
- }
- return _dataValidation;
- }
- }
-
- /// <summary>
- /// Returns the style ID given a style name.
- /// The style ID will be created if not found, but only if the style name exists!
- /// </summary>
- /// <param name="styleName"></param>
- /// <returns></returns>
- internal int GetStyleId(string styleName) {
- ExcelNamedStyleXml namedStyle = null;
- Workbook.Styles.NamedStyles.FindById(styleName, ref namedStyle);
- if (namedStyle.XfId == int.MinValue) {
- namedStyle.XfId = Workbook.Styles.CellXfs.FindIndexById(namedStyle.Style.Id);
- }
- return namedStyle.XfId;
- }
-
- /// <summary>
- /// The workbook object
- /// </summary>
- public ExcelWorkbook Workbook => _workbook;
-
- /// <summary>
- /// Get the next ID from a shared formula or an Array formula
- /// Sharedforumlas will have an id from 0-x. Array formula ids start from 0x4000001-.
- /// </summary>
- /// <param name="isArray">If the formula is an array formula</param>
- /// <returns></returns>
- internal int GetMaxShareFunctionIndex(bool isArray) {
- int i = _sharedFormulas.Count + 1;
- if (isArray) {
- i |= 0x40000000;
- }
-
- while (_sharedFormulas.ContainsKey(i)) {
- i++;
- }
- return i;
- }
-
- internal void UpdateCellsWithDate1904Setting() {
- var cse = new CellsStoreEnumerator<object>(_values);
- var offset = Workbook.Date1904 ? -ExcelWorkbook._date1904Offset : ExcelWorkbook._date1904Offset;
- while (cse.MoveNext()) {
- if (cse.Value is DateTime time) {
- try {
- double sdv = time.ToOADate();
- sdv += offset;
-
- cse.Value = DateTime.FromOADate(sdv);
- } catch {}
- }
- }
- }
-
- public string GetFormula(int row, int col) {
- var v = _formulas.GetValue(row, col);
- if (v is int i) {
- return _sharedFormulas[i].GetFormula(row, col, Name);
- }
- if (v != null) {
- return v.ToString();
- }
- return "";
- }
-
- public string GetFormulaR1C1(int row, int col) {
- var v = _formulas.GetValue(row, col);
- if (v is int i) {
- var sf = _sharedFormulas[i];
- return ExcelCellBase.TranslateToR1C1(
- Formulas.RemoveDummyFunction(sf.Formula),
- sf.StartRow,
- sf.StartCol);
- }
- if (v != null) {
- return ExcelCellBase.TranslateToR1C1(Formulas.RemoveDummyFunction(v.ToString()), row, col);
- }
- return "";
- }
-
- public string GetFormulaR1C1_V1(int row, int col) {
- var v = _formulas.GetValue(row, col);
- if (v is int i) {
- var sf = _sharedFormulas[i];
- return ExcelCellBase.TranslateToR1C1_V1(
- Formulas.RemoveDummyFunction(sf.Formula),
- sf.StartRow,
- sf.StartCol);
- }
- if (v != null) {
- return ExcelCellBase.TranslateToR1C1_V1(Formulas.RemoveDummyFunction(v.ToString()), row, col);
- }
- return "";
- }
-
- public bool IsArrayFormula(int row, int col) =>
- _flags.GetFlagValue(row, col, CellFlags.ArrayFormula);
-
- public string GetArrayFormulaAddress(int row, int col) {
- var v = _formulas.GetValue(row, col);
- if ((v is int i) && (_sharedFormulas[i].IsArray)) {
- return _sharedFormulas[i].Address;
- }
- return "";
- }
-
- public int GetStyleId(int row, int col) {
- int styleId = 0;
- if (!_styles.Exists(row, col, ref styleId) && !_styles.Exists(row, 0, ref styleId)) {
- styleId = _styles.GetValue(0, col);
- }
- return styleId;
- }
-
- /// <summary>
- /// Get the ExcelColumn for column (span ColumnMin and ColumnMax)
- /// </summary>
- /// <param name="column"></param>
- /// <returns></returns>
- internal ExcelColumn GetColumn(int column) {
- var c = _values.GetValue(0, column) as ExcelColumn;
- if (c == null) {
- int row = 0,
- col = column;
- if (_values.PrevCell(ref row, ref col)) {
- c = _values.GetValue(0, col) as ExcelColumn;
- if (c != null && c.ColumnMax >= column) {
- return c;
- }
- return null;
- }
- }
- return c;
- }
-
- public bool Equals(ExcelWorksheet x, ExcelWorksheet y) {
- return x.Name == y.Name
- && x.SheetID == y.SheetID
- && x.WorksheetXml.OuterXml == y.WorksheetXml.OuterXml;
- }
-
- public int GetHashCode(ExcelWorksheet obj) {
- return obj.WorksheetXml.OuterXml.GetHashCode();
- }
-}
diff --git a/EPPlus/ExcelWorksheetView.cs b/EPPlus/ExcelWorksheetView.cs
deleted file mode 100644
index 758ec6e..0000000
--- a/EPPlus/ExcelWorksheetView.cs
+++ /dev/null
@@ -1,396 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan K�llman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Collections.Immutable;
-using System.Xml;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Represents the different view states of the worksheet
-/// </summary>
-public class ExcelWorksheetView : XmlHelper {
- /// <summary>
- /// The worksheet panes after a freeze or split.
- /// </summary>
- public class ExcelWorksheetPanes : XmlHelper {
- private XmlElement _selectionNode;
-
- internal ExcelWorksheetPanes(XmlNamespaceManager ns, XmlNode topNode)
- : base(ns, topNode) {
- if (topNode.Name == "selection") {
- _selectionNode = topNode as XmlElement;
- }
- }
-
- private const string _activeCellPath = "@activeCell";
-
- /// <summary>
- /// Set the active cell. Must be set within the SelectedRange.
- /// </summary>
- public string ActiveCell {
- get {
- string address = GetXmlNodeString(_activeCellPath);
- if (address == "") {
- return "A1";
- }
- return address;
- }
- set {
- int toCol,
- toRow;
- if (_selectionNode == null) {
- CreateSelectionElement();
- }
- ExcelCellBase.GetRowColFromAddress(
- value,
- out var fromRow,
- out var fromCol,
- out toRow,
- out toCol);
- SetXmlNodeString(_activeCellPath, value);
- if (((XmlElement)TopNode).GetAttribute("sqref") == "") {
- SelectedRange = ExcelCellBase.GetAddress(fromRow, fromCol);
- }
- //TODO:Add fix for out of range here
- }
- }
-
- private void CreateSelectionElement() {
- _selectionNode = TopNode.OwnerDocument.CreateElement("selection", ExcelPackage._schemaMain);
- TopNode.AppendChild(_selectionNode);
- TopNode = _selectionNode;
- }
-
- private const string _selectionRangePath = "@sqref";
-
- /// <summary>
- /// Selected Cells.Used in combination with ActiveCell
- /// </summary>
- public string SelectedRange {
- get {
- string address = GetXmlNodeString(_selectionRangePath);
- if (address == "") {
- return "A1";
- }
- return address;
- }
- set {
- int toCol,
- toRow;
- if (_selectionNode == null) {
- CreateSelectionElement();
- }
- ExcelCellBase.GetRowColFromAddress(
- value,
- out var fromRow,
- out var fromCol,
- out toRow,
- out toCol);
- SetXmlNodeString(_selectionRangePath, value);
- if (((XmlElement)TopNode).GetAttribute("activeCell") == "") {
- ActiveCell = ExcelCellBase.GetAddress(fromRow, fromCol);
- }
- //TODO:Add fix for out of range here
- }
- }
- }
-
- private readonly ExcelWorksheet _worksheet;
-
- protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
- "sheetViews",
- "sheetView",
- "pane",
- "selection",
- ];
-
- /// <summary>
- /// Creates a new ExcelWorksheetView which provides access to all the view states of the worksheet.
- /// </summary>
- /// <param name="ns"></param>
- /// <param name="node"></param>
- /// <param name="xlWorksheet"></param>
- internal ExcelWorksheetView(XmlNamespaceManager ns, XmlNode node, ExcelWorksheet xlWorksheet)
- : base(ns, node) {
- _worksheet = xlWorksheet;
- Panes = LoadPanes();
- }
-
- private ExcelWorksheetPanes[] LoadPanes() {
- XmlNodeList nodes = TopNode.SelectNodes("//d:selection", NameSpaceManager);
- if (nodes.Count == 0) {
- return new[] { new ExcelWorksheetPanes(NameSpaceManager, TopNode) };
- }
- ExcelWorksheetPanes[] panes = new ExcelWorksheetPanes[nodes.Count];
- int i = 0;
- foreach (XmlElement elem in nodes) {
- panes[i++] = new(NameSpaceManager, elem);
- }
- return panes;
- }
-
- /// <summary>
- /// Returns a reference to the sheetView element
- /// </summary>
- protected internal XmlElement SheetViewElement => (XmlElement)TopNode;
-
- /// <summary>
- /// The active cell.
- /// </summary>
- public string ActiveCell {
- get => Panes[Panes.GetUpperBound(0)].ActiveCell;
- set => Panes[Panes.GetUpperBound(0)].ActiveCell = value;
- }
-
- /// <summary>
- /// Selected Cells in the worksheet.Used in combination with ActiveCell
- /// </summary>
- public string SelectedRange {
- get => Panes[Panes.GetUpperBound(0)].SelectedRange;
- set => Panes[Panes.GetUpperBound(0)].SelectedRange = value;
- }
-
- /// <summary>
- /// Indicates if the worksheet is selected within the workbook
- /// </summary>
- public bool TabSelected {
- get => GetXmlNodeBool("@tabSelected");
- set {
- if (value) {
- // // ensure no other worksheet has its tabSelected attribute set to 1
- foreach (ExcelWorksheet sheet in _worksheet.Workbook.Worksheets) {
- sheet.View.TabSelected = false;
- }
-
- SheetViewElement.SetAttribute("tabSelected", "1");
- XmlElement bookView =
- _worksheet.Workbook.WorkbookXml.SelectSingleNode(
- "//d:workbookView",
- _worksheet.NameSpaceManager) as XmlElement;
- if (bookView != null) {
- bookView.SetAttribute("activeTab", (_worksheet.PositionID - 1).ToString());
- }
- } else {
- SetXmlNodeString("@tabSelected", "0");
- }
- }
- }
-
- /// <summary>
- /// Sets the view mode of the worksheet to pagelayout
- /// </summary>
- public bool PageLayoutView {
- get => GetXmlNodeString("@view") == "pageLayout";
- set {
- if (value) {
- SetXmlNodeString("@view", "pageLayout");
- } else {
- SheetViewElement.RemoveAttribute("view");
- }
- }
- }
-
- /// <summary>
- /// Sets the view mode of the worksheet to pagebreak
- /// </summary>
- public bool PageBreakView {
- get => GetXmlNodeString("@view") == "pageBreakPreview";
- set {
- if (value) {
- SetXmlNodeString("@view", "pageBreakPreview");
- } else {
- SheetViewElement.RemoveAttribute("view");
- }
- }
- }
-
- /// <summary>
- /// Show gridlines in the worksheet
- /// </summary>
- public bool ShowGridLines {
- get => GetXmlNodeBool("@showGridLines");
- set => SetXmlNodeString("@showGridLines", value ? "1" : "0");
- }
-
- /// <summary>
- /// Show the Column/Row headers (containg column letters and row numbers)
- /// </summary>
- public bool ShowHeaders {
- get => GetXmlNodeBool("@showRowColHeaders");
- set => SetXmlNodeString("@showRowColHeaders", value ? "1" : "0");
- }
-
- /// <summary>
- /// Window zoom magnification for current view representing percent values.
- /// </summary>
- public int ZoomScale {
- get => GetXmlNodeInt("@zoomScale");
- set {
- if (value < 10 || value > 400) {
- throw new ArgumentOutOfRangeException("Zoome scale out of range (10-400)");
- }
- SetXmlNodeString("@zoomScale", value.ToString());
- }
- }
-
- /// <summary>
- /// Flag indicating whether the sheet is in 'right to left' display mode. When in this mode,Column A is on the far right, Column B ;is one column left of Column A, and so on. Also,information in cells is displayed in the Right to Left format.
- /// </summary>
- public bool RightToLeft {
- get => GetXmlNodeBool("@rightToLeft");
- set => SetXmlNodeString("@rightToLeft", value ? "1" : "0");
- }
-
- internal bool WindowProtection {
- get => GetXmlNodeBool("@windowProtection", false);
- set => SetXmlNodeBool("@windowProtection", value, false);
- }
-
- /// <summary>
- /// Reference to the panes
- /// </summary>
- public ExcelWorksheetPanes[] Panes { get; internal set; }
-
- private readonly string _paneNodePath = "d:pane";
- private readonly string _selectionNodePath = "d:selection";
-
- /// <summary>
- /// Freeze the columns/rows to left and above the cell
- /// </summary>
- /// <param name="row"></param>
- /// <param name="column"></param>
- public void FreezePanes(int row, int column) {
- //TODO:fix this method to handle splits as well.
- if (row == 1 && column == 1) {
- UnFreezePanes();
- }
- string sqRef = SelectedRange,
- activeCell = ActiveCell;
-
- XmlElement paneNode = TopNode.SelectSingleNode(_paneNodePath, NameSpaceManager) as XmlElement;
- if (paneNode == null) {
- CreateNode(_paneNodePath);
- paneNode = TopNode.SelectSingleNode(_paneNodePath, NameSpaceManager) as XmlElement;
- }
- paneNode.RemoveAll(); //Clear all attributes
- if (column > 1) {
- paneNode.SetAttribute("xSplit", (column - 1).ToString());
- }
- if (row > 1) {
- paneNode.SetAttribute("ySplit", (row - 1).ToString());
- }
- paneNode.SetAttribute("topLeftCell", ExcelCellBase.GetAddress(row, column));
- paneNode.SetAttribute("state", "frozen");
-
- RemoveSelection();
-
- if (row > 1 && column == 1) {
- paneNode.SetAttribute("activePane", "bottomLeft");
- XmlElement sel = TopNode.OwnerDocument.CreateElement("selection", ExcelPackage._schemaMain);
- sel.SetAttribute("pane", "bottomLeft");
- if (activeCell != "") {
- sel.SetAttribute("activeCell", activeCell);
- }
- if (sqRef != "") {
- sel.SetAttribute("sqref", sqRef);
- }
- sel.SetAttribute("sqref", sqRef);
- TopNode.InsertAfter(sel, paneNode);
- } else if (column > 1 && row == 1) {
- paneNode.SetAttribute("activePane", "topRight");
- XmlElement sel = TopNode.OwnerDocument.CreateElement("selection", ExcelPackage._schemaMain);
- sel.SetAttribute("pane", "topRight");
- if (activeCell != "") {
- sel.SetAttribute("activeCell", activeCell);
- }
- if (sqRef != "") {
- sel.SetAttribute("sqref", sqRef);
- }
- TopNode.InsertAfter(sel, paneNode);
- } else {
- paneNode.SetAttribute("activePane", "bottomRight");
- XmlElement sel1 = TopNode.OwnerDocument.CreateElement("selection", ExcelPackage._schemaMain);
- sel1.SetAttribute("pane", "topRight");
- string cell = ExcelCellBase.GetAddress(1, column);
- sel1.SetAttribute("activeCell", cell);
- sel1.SetAttribute("sqref", cell);
- paneNode.ParentNode.InsertAfter(sel1, paneNode);
-
- XmlElement sel2 = TopNode.OwnerDocument.CreateElement("selection", ExcelPackage._schemaMain);
- cell = ExcelCellBase.GetAddress(row, 1);
- sel2.SetAttribute("pane", "bottomLeft");
- sel2.SetAttribute("activeCell", cell);
- sel2.SetAttribute("sqref", cell);
- sel1.ParentNode.InsertAfter(sel2, sel1);
-
- XmlElement sel3 = TopNode.OwnerDocument.CreateElement("selection", ExcelPackage._schemaMain);
- sel3.SetAttribute("pane", "bottomRight");
- if (activeCell != "") {
- sel3.SetAttribute("activeCell", activeCell);
- }
- if (sqRef != "") {
- sel3.SetAttribute("sqref", sqRef);
- }
- sel2.ParentNode.InsertAfter(sel3, sel2);
- }
- Panes = LoadPanes();
- }
-
- private void RemoveSelection() {
- //Find selection nodes and remove them
- XmlNodeList selections = TopNode.SelectNodes(_selectionNodePath, NameSpaceManager);
- foreach (XmlNode sel in selections) {
- sel.ParentNode.RemoveChild(sel);
- }
- }
-
- /// <summary>
- /// Unlock all rows and columns to scroll freely
- /// /// </summary>
- public void UnFreezePanes() {
- string sqRef = SelectedRange,
- activeCell = ActiveCell;
-
- XmlElement paneNode = TopNode.SelectSingleNode(_paneNodePath, NameSpaceManager) as XmlElement;
- if (paneNode != null) {
- paneNode.ParentNode.RemoveChild(paneNode);
- }
- RemoveSelection();
-
- Panes = LoadPanes();
-
- SelectedRange = sqRef;
- ActiveCell = activeCell;
- }
-}
diff --git a/EPPlus/ExcelWorksheets.cs b/EPPlus/ExcelWorksheets.cs
deleted file mode 100644
index a0e4ebb..0000000
--- a/EPPlus/ExcelWorksheets.cs
+++ /dev/null
@@ -1,336 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Text.RegularExpressions;
-using System.Xml;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// The collection of worksheets for the workbook
-/// </summary>
-public class ExcelWorksheets : XmlHelper, IEnumerable<ExcelWorksheet> {
- private readonly ExcelPackage _pck;
- private readonly ExcelWorkbook _workbook;
- private Dictionary<int, ExcelWorksheet> _worksheets = new();
- private readonly XmlNamespaceManager _namespaceManager;
-
- internal ExcelWorksheets(
- ExcelPackage pck,
- ExcelWorkbook workbook,
- XmlNamespaceManager nsm,
- XmlNode topNode)
- : base(nsm, topNode) {
- _pck = pck;
- _workbook = workbook;
- _namespaceManager = nsm;
- int positionId = 1;
-
- foreach (XmlNode sheetNode in topNode.ChildNodes) {
- if (sheetNode.NodeType == XmlNodeType.Element) {
- string name = sheetNode.Attributes["name"].Value;
- //Get the relationship id
- string relId = sheetNode.Attributes["r:id"].Value;
- int sheetId = Convert.ToInt32(sheetNode.Attributes["sheetId"].Value);
-
- //Hidden property
- eWorkSheetHidden hidden = eWorkSheetHidden.Visible;
- XmlNode attr = sheetNode.Attributes["state"];
- if (attr != null) {
- hidden = TranslateHidden(attr.Value);
- }
-
- var sheetRelation = _workbook.Part.GetRelationship(relId);
- Uri uriWorksheet = UriHelper.ResolvePartUri(
- ExcelWorkbook.WorkbookUri,
- sheetRelation.TargetUri);
-
- //add the worksheet
- if (sheetRelation.RelationshipType.EndsWith("chartsheet")) {
- _worksheets.Add(
- positionId,
- new ExcelChartsheet(
- _namespaceManager,
- pck,
- _workbook,
- uriWorksheet,
- name,
- sheetId,
- positionId,
- hidden));
- } else {
- _worksheets.Add(
- positionId,
- new(
- _namespaceManager,
- pck,
- _workbook,
- uriWorksheet,
- name,
- sheetId,
- positionId,
- hidden));
- }
- positionId++;
- }
- }
- }
-
- private eWorkSheetHidden TranslateHidden(string value) {
- switch (value) {
- case "hidden":
- return eWorkSheetHidden.Hidden;
- case "veryHidden":
- return eWorkSheetHidden.VeryHidden;
- default:
- return eWorkSheetHidden.Visible;
- }
- }
-
- /// <summary>
- /// Returns the number of worksheets in the workbook
- /// </summary>
- public int Count => (_worksheets.Count);
-
- private const string _errDupWorksheet =
- "A worksheet with this name already exists in the workbook";
- internal const string _worksheetContentType =
- "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml";
-
- /// <summary>
- /// Foreach support
- /// </summary>
- /// <returns>An enumerator</returns>
- public IEnumerator<ExcelWorksheet> GetEnumerator() {
- return (_worksheets.Values.GetEnumerator());
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- return (_worksheets.Values.GetEnumerator());
- }
-
- /// <summary>
- /// Adds a new blank worksheet.
- /// </summary>
- /// <param name="name">The name of the workbook</param>
- public ExcelWorksheet Add(string name) {
- name = ValidateFixSheetName(name);
- if (GetByName(name) != null) {
- throw (new InvalidOperationException(_errDupWorksheet + " : " + name));
- }
- GetSheetUri(ref name, out var sheetId, out var uriWorksheet, false);
-
- // Create the new worksheet
- var rel = _pck.CreateXmlDocument(
- uriWorksheet,
- _worksheetContentType,
- ExcelPackage._schemaRelationships + "/worksheet",
- CreateNewWorksheet(false));
-
- // Add worksheet to the workbook
- XmlElement worksheetNode = _workbook.WorkbookXml.CreateElement(
- "sheet",
- ExcelPackage._schemaMain);
- worksheetNode.SetAttribute("name", name);
- worksheetNode.SetAttribute("sheetId", sheetId.ToString());
- worksheetNode.SetAttribute("id", ExcelPackage._schemaRelationships, rel.Id);
- TopNode.AppendChild(worksheetNode);
-
- int positionId = _worksheets.Count + 1;
-
- ExcelWorksheet worksheet = new(
- _namespaceManager,
- _pck,
- _workbook,
- uriWorksheet,
- name,
- sheetId,
- positionId,
- eWorkSheetHidden.Visible);
-
- _worksheets.Add(positionId, worksheet);
- return worksheet;
- }
-
- private void GetSheetUri(ref string name, out int sheetId, out Uri uriWorksheet, bool isChart) {
- name = ValidateFixSheetName(name);
-
- //First find maximum existing sheetID
- sheetId = 0;
- foreach (var ws in this) {
- if (ws.SheetID > sheetId) {
- sheetId = ws.SheetID;
- }
- }
- // we now have the max existing values, so add one
- sheetId++;
-
- // add the new worksheet to the package
- if (isChart) {
- uriWorksheet = new("/xl/chartsheets/chartsheet" + sheetId + ".xml", UriKind.Relative);
- } else {
- uriWorksheet = new("/xl/worksheets/sheet" + sheetId + ".xml", UriKind.Relative);
- }
- }
-
- internal string ValidateFixSheetName(string name) {
- //remove invalid characters
- if (ValidateName(name)) {
- if (name.IndexOf(':') > -1) {
- name = name.Replace(":", " ");
- }
- if (name.IndexOf('/') > -1) {
- name = name.Replace("/", " ");
- }
- if (name.IndexOf('\\') > -1) {
- name = name.Replace("\\", " ");
- }
- if (name.IndexOf('?') > -1) {
- name = name.Replace("?", " ");
- }
- if (name.IndexOf('[') > -1) {
- name = name.Replace("[", " ");
- }
- if (name.IndexOf(']') > -1) {
- name = name.Replace("]", " ");
- }
- }
-
- if (name.Trim() == "") {
- throw new ArgumentException("The worksheet can not have an empty name");
- }
- if (name.Length > 31) {
- name = name.Substring(0, 31); //A sheet can have max 31 char's
- }
- return name;
- }
-
- /// <summary>
- /// Validate the sheetname
- /// </summary>
- /// <param name="name">The Name</param>
- /// <returns>True if valid</returns>
- private bool ValidateName(string name) {
- return Regex.IsMatch(name, @":|\?|/|\\|\[|\]");
- }
-
- /// <summary>
- /// Creates the XML document representing a new empty worksheet
- /// </summary>
- /// <returns></returns>
- internal XmlDocument CreateNewWorksheet(bool isChart) {
- XmlDocument xmlDoc = new XmlDocument();
- XmlElement elemWs = xmlDoc.CreateElement(
- isChart ? "chartsheet" : "worksheet",
- ExcelPackage._schemaMain);
- elemWs.SetAttribute("xmlns:r", ExcelPackage._schemaRelationships);
- xmlDoc.AppendChild(elemWs);
-
- if (isChart) {
- XmlElement elemSheetPr = xmlDoc.CreateElement("sheetPr", ExcelPackage._schemaMain);
- elemWs.AppendChild(elemSheetPr);
-
- XmlElement elemSheetViews = xmlDoc.CreateElement("sheetViews", ExcelPackage._schemaMain);
- elemWs.AppendChild(elemSheetViews);
-
- XmlElement elemSheetView = xmlDoc.CreateElement("sheetView", ExcelPackage._schemaMain);
- elemSheetView.SetAttribute("workbookViewId", "0");
- elemSheetView.SetAttribute("zoomToFit", "1");
-
- elemSheetViews.AppendChild(elemSheetView);
- } else {
- XmlElement elemSheetViews = xmlDoc.CreateElement("sheetViews", ExcelPackage._schemaMain);
- elemWs.AppendChild(elemSheetViews);
-
- XmlElement elemSheetView = xmlDoc.CreateElement("sheetView", ExcelPackage._schemaMain);
- elemSheetView.SetAttribute("workbookViewId", "0");
- elemSheetViews.AppendChild(elemSheetView);
-
- XmlElement elemSheetFormatPr = xmlDoc.CreateElement(
- "sheetFormatPr",
- ExcelPackage._schemaMain);
- elemSheetFormatPr.SetAttribute("defaultRowHeight", "15");
- elemWs.AppendChild(elemSheetFormatPr);
-
- XmlElement elemSheetData = xmlDoc.CreateElement("sheetData", ExcelPackage._schemaMain);
- elemWs.AppendChild(elemSheetData);
- }
- return xmlDoc;
- }
-
- /// <summary>
- /// Returns the worksheet at the specified position.
- /// </summary>
- /// <param name="positionId">The position of the worksheet. 1-base</param>
- /// <returns></returns>
- public ExcelWorksheet this[int positionId] {
- get {
- if (_worksheets.ContainsKey(positionId)) {
- return _worksheets[positionId];
- }
- throw (new IndexOutOfRangeException("Worksheet position out of range."));
- }
- }
-
- /// <summary>
- /// Returns the worksheet matching the specified name
- /// </summary>
- /// <param name="name">The name of the worksheet</param>
- /// <returns></returns>
- public ExcelWorksheet this[string name] => GetByName(name);
-
- internal ExcelWorksheet GetBySheetId(int localSheetId) {
- foreach (ExcelWorksheet ws in this) {
- if (ws.SheetID == localSheetId) {
- return ws;
- }
- }
- return null;
- }
-
- private ExcelWorksheet GetByName(string name) {
- if (string.IsNullOrEmpty(name)) {
- return null;
- }
- ExcelWorksheet xlWorksheet = null;
- foreach (ExcelWorksheet worksheet in _worksheets.Values) {
- if (worksheet.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)) {
- xlWorksheet = worksheet;
- }
- }
- return (xlWorksheet);
- }
-} // end class Worksheets
diff --git a/EPPlus/FormulaParsing/CalculateExtentions.cs b/EPPlus/FormulaParsing/CalculateExtentions.cs
deleted file mode 100644
index afeb3ff..0000000
--- a/EPPlus/FormulaParsing/CalculateExtentions.cs
+++ /dev/null
@@ -1,159 +0,0 @@
-/*******************************************************************************
- * 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 2012-03-04
- *******************************************************************************/
-
-using System;
-using OfficeOpenXml.FormulaParsing;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-
-namespace OfficeOpenXml;
-
-public static class CalculationExtension {
- public static void Calculate(this ExcelWorkbook workbook) {
- Calculate(
- workbook,
- new() {
- AllowCirculareReferences = false,
- });
- }
-
- public static void Calculate(this ExcelWorkbook workbook, ExcelCalculationOption options) {
- Init(workbook);
-
- var dc = DependencyChainFactory.Create(workbook, options);
- workbook.FormulaParser.InitNewCalc();
- CalcChain(workbook, workbook.FormulaParser, dc);
- }
-
- public static void Calculate(this ExcelWorksheet worksheet) {
- Calculate(worksheet, new ExcelCalculationOption());
- }
-
- public static void Calculate(this ExcelWorksheet worksheet, ExcelCalculationOption options) {
- Init(worksheet.Workbook);
- //worksheet.Workbook._formulaParser = null; TODO:Cant reset. Don't work with userdefined or overrided worksheet functions
- var dc = DependencyChainFactory.Create(worksheet, options);
-
- // Display Calc Chain to determine why formula calculation is taking so long.
- // Uncomment the following line to display the Calc Chain.
- // DisplayCalcChain(worksheet, dc);
-
- var parser = worksheet.Workbook.FormulaParser;
- parser.InitNewCalc();
- CalcChain(worksheet.Workbook, parser, dc);
- }
-
- public static void Calculate(this ExcelRangeBase range) {
- Calculate(range, new());
- }
-
- public static void Calculate(this ExcelRangeBase range, ExcelCalculationOption options) {
- Init(range._workbook);
- var parser = range._workbook.FormulaParser;
- parser.InitNewCalc();
- var dc = DependencyChainFactory.Create(range, options);
- CalcChain(range._workbook, parser, dc);
- }
-
- public static object Calculate(this ExcelWorksheet worksheet, string formula) {
- return Calculate(worksheet, formula, new());
- }
-
- public static object Calculate(
- this ExcelWorksheet worksheet,
- string formula,
- ExcelCalculationOption options) {
- try {
- worksheet.CheckSheetType();
- if (string.IsNullOrEmpty(formula.Trim())) {
- return null;
- }
- Init(worksheet.Workbook);
- var parser = worksheet.Workbook.FormulaParser;
- parser.InitNewCalc();
- if (formula[0] == '=') {
- formula = formula.Substring(1); //Remove any starting equal sign
- }
- var dc = DependencyChainFactory.Create(worksheet, formula, options);
- var f = dc.list[0];
- dc.CalcOrder.RemoveAt(dc.CalcOrder.Count - 1);
-
- CalcChain(worksheet.Workbook, parser, dc);
-
- return parser.ParseCell(f.Tokens, worksheet.Name, -1, -1);
- } catch (Exception ex) {
- return new ExcelErrorValueException(ex.Message, ExcelErrorValue.Create(eErrorType.Value));
- }
- }
-
- private static void CalcChain(ExcelWorkbook wb, FormulaParser parser, DependencyChain dc) {
- foreach (var ix in dc.CalcOrder) {
- var item = dc.list[ix];
- try {
- var ws = wb.Worksheets.GetBySheetId(item.SheetID);
- var v = parser.ParseCell(item.Tokens, ws == null ? "" : ws.Name, item.Row, item.Column);
- SetValue(wb, item, v);
- } catch (FunctionException) {
- // Excel function is not supported by EPPlus
- throw;
- } catch (FormatException) {
- throw;
- } catch (Exception) {
- var error = ExcelErrorValue.Parse(ExcelErrorValue.Values.Value);
- SetValue(wb, item, error);
- }
- }
- }
-
- private static void Init(ExcelWorkbook workbook) {
- workbook._formulaTokens = new();
- ;
- foreach (var ws in workbook.Worksheets) {
- if (!(ws is ExcelChartsheet)) {
- ws._formulaTokens = new();
- }
- }
- }
-
- private static void SetValue(ExcelWorkbook workbook, FormulaCell item, object v) {
- if (item.Column == 0) {
- if (item.SheetID <= 0) {
- workbook.Names[item.Row].NameValue = v;
- } else {
- var sh = workbook.Worksheets.GetBySheetId(item.SheetID);
- sh.Names[item.Row].NameValue = v;
- }
- } else {
- var sheet = workbook.Worksheets.GetBySheetId(item.SheetID);
- sheet._values.SetValue(item.Row, item.Column, v);
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/DependencyChain/DependencyChain.cs b/EPPlus/FormulaParsing/DependencyChain/DependencyChain.cs
deleted file mode 100644
index 74a0a7e..0000000
--- a/EPPlus/FormulaParsing/DependencyChain/DependencyChain.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing;
-
-internal class DependencyChain {
- internal List<FormulaCell> list = new();
- internal Dictionary<ulong, int> index = new();
- internal List<int> CalcOrder = new();
-
- internal void Add(FormulaCell f) {
- list.Add(f);
- f.Index = list.Count - 1;
- index.Add(ExcelCellBase.GetCellId(f.SheetID, f.Row, f.Column), f.Index);
- }
-}
diff --git a/EPPlus/FormulaParsing/DependencyChain/DependenyChainFactory.cs b/EPPlus/FormulaParsing/DependencyChain/DependenyChainFactory.cs
deleted file mode 100644
index f198123..0000000
--- a/EPPlus/FormulaParsing/DependencyChain/DependenyChainFactory.cs
+++ /dev/null
@@ -1,373 +0,0 @@
-/*******************************************************************************
- * 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 2012-03-04
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-namespace OfficeOpenXml.FormulaParsing;
-
-internal static class DependencyChainFactory {
- internal static DependencyChain Create(ExcelWorkbook wb, ExcelCalculationOption options) {
- var depChain = new DependencyChain();
- foreach (var ws in wb.Worksheets) {
- if (!(ws is ExcelChartsheet)) {
- GetChain(depChain, wb.FormulaParser.Lexer, ws.Cells, options);
- GetWorksheetNames(ws, depChain, options);
- }
- }
- foreach (var name in wb.Names) {
- if (name.NameValue == null) {
- GetChain(depChain, wb.FormulaParser.Lexer, name, options);
- }
- }
- return depChain;
- }
-
- internal static DependencyChain Create(ExcelWorksheet ws, ExcelCalculationOption options) {
- ws.CheckSheetType();
- var depChain = new DependencyChain();
-
- GetChain(depChain, ws.Workbook.FormulaParser.Lexer, ws.Cells, options);
-
- GetWorksheetNames(ws, depChain, options);
-
- return depChain;
- }
-
- internal static DependencyChain Create(
- ExcelWorksheet ws,
- string formula,
- ExcelCalculationOption options) {
- ws.CheckSheetType();
- var depChain = new DependencyChain();
-
- GetChain(depChain, ws.Workbook.FormulaParser.Lexer, ws, formula, options);
-
- return depChain;
- }
-
- private static void GetWorksheetNames(
- ExcelWorksheet ws,
- DependencyChain depChain,
- ExcelCalculationOption options) {
- foreach (var name in ws.Names) {
- if (!string.IsNullOrEmpty(name.NameFormula)) {
- GetChain(depChain, ws.Workbook.FormulaParser.Lexer, name, options);
- }
- }
- }
-
- internal static DependencyChain Create(ExcelRangeBase range, ExcelCalculationOption options) {
- var depChain = new DependencyChain();
-
- GetChain(depChain, range.Worksheet.Workbook.FormulaParser.Lexer, range, options);
-
- return depChain;
- }
-
- private static void GetChain(
- DependencyChain depChain,
- ILexer lexer,
- ExcelNamedRange name,
- ExcelCalculationOption options) {
- var ws = name.Worksheet;
- var id = ExcelCellBase.GetCellId(ws?.SheetID ?? 0, name.Index, 0);
- if (!depChain.index.ContainsKey(id)) {
- var f = new FormulaCell {
- SheetID = ws?.SheetID ?? 0,
- Row = name.Index,
- Column = 0,
- Formula = name.NameFormula,
- };
- if (!string.IsNullOrEmpty(f.Formula)) {
- f.Tokens = lexer.Tokenize(f.Formula, ws?.Name).ToList();
- if (ws == null) {
- name._workbook._formulaTokens.SetValue(name.Index, 0, f.Tokens);
- } else {
- ws._formulaTokens.SetValue(name.Index, 0, f.Tokens);
- }
- depChain.Add(f);
- FollowChain(depChain, lexer, name._workbook, ws, f, options);
- }
- }
- }
-
- private static void GetChain(
- DependencyChain depChain,
- ILexer lexer,
- ExcelWorksheet ws,
- string formula,
- ExcelCalculationOption options) {
- var f = new FormulaCell {
- SheetID = ws.SheetID,
- Row = -1,
- Column = -1,
- };
- f.Formula = formula;
- if (!string.IsNullOrEmpty(f.Formula)) {
- f.Tokens = lexer.Tokenize(f.Formula, ws.Name).ToList();
- depChain.Add(f);
- FollowChain(depChain, lexer, ws.Workbook, ws, f, options);
- }
- }
-
- private static void GetChain(
- DependencyChain depChain,
- ILexer lexer,
- ExcelRangeBase range,
- ExcelCalculationOption options) {
- var ws = range.Worksheet;
- var fs = new CellsStoreEnumerator<object>(
- ws._formulas,
- range.Start.Row,
- range.Start.Column,
- range.End.Row,
- range.End.Column);
- while (fs.Next()) {
- if (fs.Value == null || fs.Value.ToString().Trim() == "") {
- continue;
- }
- var id = ExcelCellBase.GetCellId(ws.SheetID, fs.Row, fs.Column);
- if (!depChain.index.ContainsKey(id)) {
- var f = new FormulaCell {
- SheetID = ws.SheetID,
- Row = fs.Row,
- Column = fs.Column,
- };
- if (fs.Value is int value) {
- f.Formula = ws._sharedFormulas[value].GetFormula(fs.Row, fs.Column, ws.Name);
- } else {
- f.Formula = fs.Value.ToString();
- }
- if (!string.IsNullOrEmpty(f.Formula)) {
- f.Tokens = lexer.Tokenize(f.Formula, range.Worksheet.Name).ToList();
- ws._formulaTokens.SetValue(fs.Row, fs.Column, f.Tokens);
- depChain.Add(f);
- FollowChain(depChain, lexer, ws.Workbook, ws, f, options);
- }
- }
- }
- }
-
- /// <summary>
- /// This method follows the calculation chain to get the order of the calculation
- /// Goto (!) is used internally to prevent stackoverflow on extremly larget dependency trees (that is, many recursive formulas).
- /// </summary>
- /// <param name="depChain">The dependency chain object</param>
- /// <param name="lexer">The formula tokenizer</param>
- /// <param name="wb">The workbook where the formula comes from</param>
- /// <param name="ws">The worksheet where the formula comes from</param>
- /// <param name="f">The cell function object</param>
- /// <param name="options">Calcultaiton options</param>
- private static void FollowChain(
- DependencyChain depChain,
- ILexer lexer,
- ExcelWorkbook wb,
- ExcelWorksheet ws,
- FormulaCell f,
- ExcelCalculationOption options) {
- Stack<FormulaCell> stack = new Stack<FormulaCell>();
- iterateToken:
- while (f.tokenIx < f.Tokens.Count) {
- var t = f.Tokens[f.tokenIx];
- if (t.TokenType == TokenType.ExcelAddress) {
- var adr = new ExcelFormulaAddress(t.Value);
- if (adr.Table != null) {
- adr.SetRcFromTable(ws.Workbook, new(f.Row, f.Column, f.Row, f.Column));
- }
-
- if (adr.WorkSheet == null
- && adr.Collide(new(f.Row, f.Column, f.Row, f.Column))
- != ExcelAddressBase.eAddressCollition.No) {
- throw (new CircularReferenceException(
- string.Format(
- "Circular Reference in cell {0}",
- ExcelCellBase.GetAddress(f.Row, f.Column))));
- }
-
- if (adr._fromRow > 0 && adr._fromCol > 0) {
- if (string.IsNullOrEmpty(adr.WorkSheet)) {
- if (f.ws == null) {
- f.ws = ws;
- } else if (f.ws.SheetID != f.SheetID) {
- f.ws = wb.Worksheets.GetBySheetId(f.SheetID);
- }
- } else {
- f.ws = wb.Worksheets[adr.WorkSheet];
- }
-
- if (f.ws != null) {
- f.iterator = new(
- f.ws._formulas,
- adr.Start.Row,
- adr.Start.Column,
- adr.End.Row,
- adr.End.Column);
- goto iterateCells;
- }
- }
- } else if (t.TokenType == TokenType.NameValue) {
- string adrWb;
- ExcelNamedRange name;
- ExcelAddressBase.SplitAddress(
- t.Value,
- out adrWb,
- out var adrWs,
- out var adrName,
- f.ws == null ? "" : f.ws.Name);
- if (!string.IsNullOrEmpty(adrWs)) {
- if (f.ws == null) {
- f.ws = wb.Worksheets[adrWs];
- }
- if (f.ws.Names.ContainsKey(t.Value)) {
- name = f.ws.Names[adrName];
- } else if (wb.Names.ContainsKey(adrName)) {
- name = wb.Names[adrName];
- } else {
- name = null;
- }
- if (name != null) {
- f.ws = name.Worksheet;
- }
- } else if (wb.Names.ContainsKey(adrName)) {
- name = wb.Names[t.Value];
- if (string.IsNullOrEmpty(adrWs)) {
- f.ws = name.Worksheet;
- }
- } else {
- name = null;
- }
-
- if (name != null) {
- if (string.IsNullOrEmpty(name.NameFormula)) {
- if (name.NameValue == null) {
- f.iterator = new(
- f.ws._formulas,
- name.Start.Row,
- name.Start.Column,
- name.End.Row,
- name.End.Column);
- goto iterateCells;
- }
- } else {
- var id = ExcelCellBase.GetCellId(name.LocalSheetId, name.Index, 0);
-
- if (!depChain.index.ContainsKey(id)) {
- var rf = new FormulaCell {
- SheetID = name.LocalSheetId,
- Row = name.Index,
- Column = 0,
- };
- rf.Formula = name.NameFormula;
- rf.Tokens =
- name.LocalSheetId == -1
- ? lexer.Tokenize(rf.Formula).ToList()
- : lexer
- .Tokenize(rf.Formula, wb.Worksheets.GetBySheetId(name.LocalSheetId).Name)
- .ToList();
-
- depChain.Add(rf);
- stack.Push(f);
- f = rf;
- goto iterateToken;
- }
- if (stack.Count > 0) {
- //Check for circular references
- foreach (var par in stack) {
- if (ExcelCellBase.GetCellId(par.SheetID, par.Row, par.Column) == id) {
- throw (new CircularReferenceException(
- string.Format("Circular Reference in name {0}", name.Name)));
- }
- }
- }
- }
- }
- }
- f.tokenIx++;
- }
- depChain.CalcOrder.Add(f.Index);
- if (stack.Count > 0) {
- f = stack.Pop();
- goto iterateCells;
- }
- return;
- iterateCells:
-
- while (f.iterator != null && f.iterator.Next()) {
- var v = f.iterator.Value;
- if (v == null || v.ToString().Trim() == "") {
- continue;
- }
- var id = ExcelCellBase.GetCellId(f.ws.SheetID, f.iterator.Row, f.iterator.Column);
- if (!depChain.index.ContainsKey(id)) {
- var rf = new FormulaCell {
- SheetID = f.ws.SheetID,
- Row = f.iterator.Row,
- Column = f.iterator.Column,
- };
- if (f.iterator.Value is int) {
- rf.Formula = f.ws._sharedFormulas[(int)v]
- .GetFormula(f.iterator.Row, f.iterator.Column, ws.Name);
- } else {
- rf.Formula = v.ToString();
- }
- rf.ws = f.ws;
- rf.Tokens = lexer.Tokenize(rf.Formula, f.ws.Name).ToList();
- ws._formulaTokens.SetValue(rf.Row, rf.Column, rf.Tokens);
- depChain.Add(rf);
- stack.Push(f);
- f = rf;
- goto iterateToken;
- }
- if (stack.Count > 0) {
- //Check for circular references
- foreach (var par in stack) {
- if (ExcelCellBase.GetCellId(par.ws.SheetID, par.iterator.Row, par.iterator.Column)
- == id) {
- if (options.AllowCirculareReferences == false) {
- throw (new CircularReferenceException(
- string.Format(
- "Circular Reference in cell {0}!{1}",
- par.ws.Name,
- ExcelCellBase.GetAddress(f.Row, f.Column))));
- }
- f = stack.Pop();
- goto iterateCells;
- }
- }
- }
- }
- f.tokenIx++;
- goto iterateToken;
- }
-}
diff --git a/EPPlus/FormulaParsing/DependencyChain/FormulaCell.cs b/EPPlus/FormulaParsing/DependencyChain/FormulaCell.cs
deleted file mode 100644
index 2b96a7d..0000000
--- a/EPPlus/FormulaParsing/DependencyChain/FormulaCell.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-namespace OfficeOpenXml.FormulaParsing;
-
-internal class FormulaCell {
- internal int Index { get; set; }
-
- internal int SheetID { get; set; }
-
- internal int Row { get; set; }
-
- internal int Column { get; set; }
-
- internal string Formula { get; set; }
-
- internal List<Token> Tokens { get; set; }
-
- internal int tokenIx = 0;
- internal int addressIx = 0;
- internal CellsStoreEnumerator<object> iterator;
- internal ExcelWorksheet ws;
-}
diff --git a/EPPlus/FormulaParsing/EpplusExcelDataProvider.cs b/EPPlus/FormulaParsing/EpplusExcelDataProvider.cs
deleted file mode 100644
index 8dfe6d1..0000000
--- a/EPPlus/FormulaParsing/EpplusExcelDataProvider.cs
+++ /dev/null
@@ -1,359 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-using OfficeOpenXml.Style.XmlAccess;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing;
-
-public class EpplusExcelDataProvider : ExcelDataProvider {
- public class RangeInfo : IRangeInfo {
- internal ExcelWorksheet _ws;
- private readonly CellsStoreEnumerator<object> _values;
- private readonly int _fromRow;
- private readonly int _toRow;
- private readonly int _fromCol;
- private readonly int _toCol;
- private int _cellCount;
- private readonly ExcelAddressBase _address;
- private readonly ICellInfo _cell;
-
- public RangeInfo(ExcelWorksheet ws, int fromRow, int fromCol, int toRow, int toCol) {
- _ws = ws;
- _fromRow = fromRow;
- _fromCol = fromCol;
- _toRow = toRow;
- _toCol = toCol;
- _address = new(_fromRow, _fromCol, _toRow, _toCol);
- _address._ws = ws.Name;
- _values = new(ws._values, _fromRow, _fromCol, _toRow, _toCol);
- _cell = new CellInfo(_ws, _values);
- }
-
- public int GetNCells() {
- return ((_toRow - _fromRow) + 1) * ((_toCol - _fromCol) + 1);
- }
-
- public bool IsEmpty {
- get {
- if (_cellCount > 0) {
- return false;
- }
- if (_values.Next()) {
- _values.Reset();
- return false;
- }
- return true;
- }
- }
-
- public bool IsMulti {
- get {
- if (_cellCount == 0) {
- if (_values.Next() && _values.Next()) {
- _values.Reset();
- return true;
- }
- _values.Reset();
- return false;
- }
- if (_cellCount > 1) {
- return true;
- }
- return false;
- }
- }
-
- public ICellInfo Current => _cell;
-
- public ExcelWorksheet Worksheet => _ws;
-
- public void Dispose() {}
-
- object IEnumerator.Current => this;
-
- public bool MoveNext() {
- _cellCount++;
- return _values.MoveNext();
- }
-
- public void Reset() {
- _values.Init();
- }
-
- public bool NextCell() {
- _cellCount++;
- return _values.MoveNext();
- }
-
- public IEnumerator<ICellInfo> GetEnumerator() {
- Reset();
- return this;
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- return this;
- }
-
- public ExcelAddressBase Address => _address;
-
- public object GetValue(int row, int col) {
- return _ws.GetValue(row, col);
- }
-
- public object GetOffset(int rowOffset, int colOffset) {
- if (_values.Row < _fromRow || _values.Column < _fromCol) {
- return _ws.GetValue(_fromRow + rowOffset, _fromCol + colOffset);
- }
- return _ws.GetValue(_values.Row + rowOffset, _values.Column + colOffset);
- }
- }
-
- public class CellInfo : ICellInfo {
- private readonly ExcelWorksheet _ws;
- private readonly CellsStoreEnumerator<object> _values;
-
- internal CellInfo(ExcelWorksheet ws, CellsStoreEnumerator<object> values) {
- _ws = ws;
- _values = values;
- }
-
- public string Address => _values.CellAddress;
-
- public int Row => _values.Row;
-
- public int Column => _values.Column;
-
- public string Formula => _ws.GetFormula(_values.Row, _values.Column);
-
- public object Value => _values.Value;
-
- public double ValueDouble => ConvertUtil.GetValueDouble(_values.Value, true);
-
- public double ValueDoubleLogical => ConvertUtil.GetValueDouble(_values.Value);
-
- public bool IsHiddenRow {
- get {
- var row = _ws._values.GetValue(_values.Row, 0) as RowInternal;
- if (row != null) {
- return row.Hidden || row.Height == 0;
- }
- return false;
- }
- }
-
- public bool IsExcelError => ExcelErrorValue.Values.IsErrorValue(_values.Value);
-
- public IList<Token> Tokens => _ws._formulaTokens.GetValue(_values.Row, _values.Column);
- }
-
- public class NameInfo : INameInfo {
- public ulong Id { get; set; }
-
- public string Worksheet { get; set; }
-
- public string Name { get; set; }
-
- public string Formula { get; set; }
-
- public IList<Token> Tokens { get; internal set; }
-
- public object Value { get; set; }
- }
-
- private readonly ExcelWorkbook _workbook;
- private ExcelWorksheet _currentWorksheet;
- private Dictionary<ulong, INameInfo> _names = new();
-
- public EpplusExcelDataProvider(ExcelWorkbook workbook) {
- _workbook = workbook;
- }
-
- public override ExcelNamedRangeCollection GetWorksheetNames(string worksheet) {
- var ws = _workbook.Worksheets[worksheet];
- if (ws != null) {
- return ws.Names;
- }
- return null;
- }
-
- public override ExcelNamedRangeCollection GetWorkbookNameValues() {
- return _workbook.Names;
- }
-
- public override IRangeInfo GetRange(
- string worksheet,
- int fromRow,
- int fromCol,
- int toRow,
- int toCol) {
- SetCurrentWorksheet(worksheet);
- var wsName = string.IsNullOrEmpty(worksheet) ? _currentWorksheet.Name : worksheet;
- var ws = _workbook.Worksheets[wsName];
- return new RangeInfo(ws, fromRow, fromCol, toRow, toCol);
- }
-
- public override IRangeInfo GetRange(string worksheet, int row, int column, string address) {
- var addr = new ExcelAddress(worksheet, address);
- if (addr.Table != null) {
- addr.SetRcFromTable(_workbook, new(row, column, row, column));
- }
- //SetCurrentWorksheet(addr.WorkSheet);
- var wsName = string.IsNullOrEmpty(addr.WorkSheet) ? _currentWorksheet.Name : addr.WorkSheet;
- var ws = _workbook.Worksheets[wsName];
- //return new CellsStoreEnumerator<object>(ws._values, addr._fromRow, addr._fromCol, addr._toRow, addr._toCol);
- return new RangeInfo(ws, addr._fromRow, addr._fromCol, addr._toRow, addr._toCol);
- }
-
- public override INameInfo GetName(string worksheet, string name) {
- ExcelNamedRange nameItem;
- ulong id;
- ExcelWorksheet ws;
- if (string.IsNullOrEmpty(worksheet)) {
- if (_workbook.Names.ContainsKey(name)) {
- nameItem = _workbook.Names[name];
- } else {
- return null;
- }
- ws = null;
- } else {
- ws = _workbook.Worksheets[worksheet];
- if (ws != null && ws.Names.ContainsKey(name)) {
- nameItem = ws.Names[name];
- } else if (_workbook.Names.ContainsKey(name)) {
- nameItem = _workbook.Names[name];
- } else {
- return null;
- }
- }
- id = ExcelCellBase.GetCellId(nameItem.LocalSheetId, nameItem.Index, 0);
-
- if (_names.ContainsKey(id)) {
- return _names[id];
- }
- var ni = new NameInfo {
- Id = id,
- Name = name,
- Worksheet = nameItem.Worksheet == null ? nameItem._ws : nameItem.Worksheet.Name,
- Formula = nameItem.Formula,
- };
- if (nameItem._fromRow > 0) {
- ni.Value = new RangeInfo(
- nameItem.Worksheet ?? ws,
- nameItem._fromRow,
- nameItem._fromCol,
- nameItem._toRow,
- nameItem._toCol);
- } else {
- ni.Value = nameItem.Value;
- }
- _names.Add(id, ni);
- return ni;
- }
-
- public override IEnumerable<object> GetRangeValues(string address) {
- SetCurrentWorksheet(ExcelAddressInfo.Parse(address));
- var addr = new ExcelAddress(address);
- var wsName = string.IsNullOrEmpty(addr.WorkSheet) ? _currentWorksheet.Name : addr.WorkSheet;
- var ws = _workbook.Worksheets[wsName];
- return (new CellsStoreEnumerator<object>(
- ws._values,
- addr._fromRow,
- addr._fromCol,
- addr._toRow,
- addr._toCol));
- }
-
- public object GetValue(int row, int column) {
- return _currentWorksheet._values.GetValue(row, column);
- }
-
- public bool IsMerged(int row, int column) {
- //return _currentWorksheet._flags.GetFlagValue(row, column, CellFlags.Merged);
- return _currentWorksheet.MergedCells[row, column] != null;
- }
-
- public bool IsHidden(int row, int column) {
- return _currentWorksheet.Column(column).Hidden
- || _currentWorksheet.Column(column).Width == 0
- || _currentWorksheet.Row(row).Hidden
- || _currentWorksheet.Row(column).Height == 0;
- }
-
- public override object GetCellValue(string sheetName, int row, int col) {
- SetCurrentWorksheet(sheetName);
- return _currentWorksheet._values.GetValue(row, col);
- }
-
- public override ExcelCellAddress GetDimensionEnd(string worksheet) {
- ExcelCellAddress address = null;
- try {
- address = _workbook.Worksheets[worksheet].Dimension.End;
- } catch {}
-
- return address;
- }
-
- private void SetCurrentWorksheet(ExcelAddressInfo addressInfo) {
- if (addressInfo.WorksheetIsSpecified) {
- _currentWorksheet = _workbook.Worksheets[addressInfo.Worksheet];
- } else if (_currentWorksheet == null) {
- _currentWorksheet = _workbook.Worksheets.First();
- }
- }
-
- private void SetCurrentWorksheet(string worksheetName) {
- if (!string.IsNullOrEmpty(worksheetName)) {
- _currentWorksheet = _workbook.Worksheets[worksheetName];
- } else {
- _currentWorksheet = _workbook.Worksheets.First();
- }
- }
-
- public override int ExcelMaxColumns => ExcelPackage.MaxColumns;
-
- public override int ExcelMaxRows => ExcelPackage.MaxRows;
-
- public override string GetRangeFormula(string worksheetName, int row, int column) {
- SetCurrentWorksheet(worksheetName);
- return _currentWorksheet.GetFormula(row, column);
- }
-
- public override object GetRangeValue(string worksheetName, int row, int column) {
- SetCurrentWorksheet(worksheetName);
- return _currentWorksheet.GetValue(row, column);
- }
-
- public override string GetFormat(object value, string format) {
- var styles = _workbook.Styles;
- ExcelNumberFormatXml.ExcelFormatTranslator ft = null;
- foreach (var f in styles.NumberFormats) {
- if (f.Format == format) {
- ft = f.FormatTranslator;
- break;
- }
- }
- if (ft == null) {
- ft = new(format, -1);
- }
- return ExcelRangeBase.FormatValue(value, ft, format, ft.NetFormat);
- }
-
- public override List<Token> GetRangeFormulaTokens(string worksheetName, int row, int column) {
- return _workbook.Worksheets[worksheetName]._formulaTokens.GetValue(row, column);
- }
-
- public override bool IsRowHidden(string worksheetName, int row) {
- var b =
- _workbook.Worksheets[worksheetName].Row(row).Height == 0
- || _workbook.Worksheets[worksheetName].Row(row).Hidden;
-
- return b;
- }
-
- public override void Reset() {
- _names = new(); //Reset name cache.
- }
-}
diff --git a/EPPlus/FormulaParsing/EpplusNameValueProvider.cs b/EPPlus/FormulaParsing/EpplusNameValueProvider.cs
deleted file mode 100644
index 65b9db3..0000000
--- a/EPPlus/FormulaParsing/EpplusNameValueProvider.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-namespace OfficeOpenXml.FormulaParsing;
-
-public class EpplusNameValueProvider : INameValueProvider {
- private readonly ExcelDataProvider _excelDataProvider;
- private ExcelNamedRangeCollection _values;
-
- public EpplusNameValueProvider(ExcelDataProvider excelDataProvider) {
- _excelDataProvider = excelDataProvider;
- _values = _excelDataProvider.GetWorkbookNameValues();
- }
-
- public virtual bool IsNamedValue(string key, string ws) {
- if (ws != null) {
- var wsNames = _excelDataProvider.GetWorksheetNames(ws);
- if (wsNames != null && wsNames.ContainsKey(key)) {
- return true;
- }
- }
- return _values != null && _values.ContainsKey(key);
- }
-
- public virtual object GetNamedValue(string key) {
- return _values[key];
- }
-
- public virtual void Reload() {
- _values = _excelDataProvider.GetWorkbookNameValues();
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/ExcelCellState.cs b/EPPlus/FormulaParsing/Excel/ExcelCellState.cs
deleted file mode 100644
index 3551b8a..0000000
--- a/EPPlus/FormulaParsing/Excel/ExcelCellState.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml.FormulaParsing.Excel;
-
-[Flags]
-public enum ExcelCellState {
- HiddenCell = 1,
- ContainsError = 2,
- IsResultOfSubtotal = 4,
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/ArgumentCollectionUtil.cs b/EPPlus/FormulaParsing/Excel/Functions/ArgumentCollectionUtil.cs
deleted file mode 100644
index 9f04f77..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/ArgumentCollectionUtil.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-/*******************************************************************************
- * 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public class ArgumentCollectionUtil {
- private readonly DoubleEnumerableArgConverter _doubleEnumerableArgConverter;
- private readonly ObjectEnumerableArgConverter _objectEnumerableArgConverter;
-
- public ArgumentCollectionUtil()
- : this(new(), new()) {}
-
- public ArgumentCollectionUtil(
- DoubleEnumerableArgConverter doubleEnumerableArgConverter,
- ObjectEnumerableArgConverter objectEnumerableArgConverter) {
- _doubleEnumerableArgConverter = doubleEnumerableArgConverter;
- _objectEnumerableArgConverter = objectEnumerableArgConverter;
- }
-
- public virtual IEnumerable<double> ArgsToDoubleEnumerable(
- bool ignoreHidden,
- bool ignoreErrors,
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- return _doubleEnumerableArgConverter.ConvertArgs(
- ignoreHidden,
- ignoreErrors,
- arguments,
- context);
- }
-
- public virtual IEnumerable<object> ArgsToObjectEnumerable(
- bool ignoreHidden,
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- return _objectEnumerableArgConverter.ConvertArgs(ignoreHidden, arguments, context);
- }
-
- public virtual double CalculateCollection(
- IEnumerable<FunctionArgument> collection,
- double result,
- Func<FunctionArgument, double, double> action) {
- foreach (var item in collection) {
- if (item.Value is IEnumerable<FunctionArgument> value) {
- result = CalculateCollection(value, result, action);
- } else {
- result = action(item, result);
- }
- }
- return result;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/ArgumentParser.cs b/EPPlus/FormulaParsing/Excel/Functions/ArgumentParser.cs
deleted file mode 100644
index d198dea..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/ArgumentParser.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-/* 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
-*******************************************************************************
-* Mats Alm Added 2013-12-03
-*******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public abstract class ArgumentParser {
- public abstract object Parse(object obj);
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/ArgumentParserFactory.cs b/EPPlus/FormulaParsing/Excel/Functions/ArgumentParserFactory.cs
deleted file mode 100644
index 817f85a..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/ArgumentParserFactory.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public class ArgumentParserFactory {
- public virtual ArgumentParser CreateArgumentParser(DataType dataType) {
- switch (dataType) {
- case DataType.Integer:
- return new IntArgumentParser();
- case DataType.Boolean:
- return new BoolArgumentParser();
- case DataType.Decimal:
- return new DoubleArgumentParser();
- default:
- throw new InvalidOperationException("non supported argument parser type " + dataType);
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/ArgumentParsers.cs b/EPPlus/FormulaParsing/Excel/Functions/ArgumentParsers.cs
deleted file mode 100644
index 0a518f9..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/ArgumentParsers.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public class ArgumentParsers {
- private readonly Dictionary<DataType, ArgumentParser> _parsers = new();
- private readonly ArgumentParserFactory _parserFactory;
-
- public ArgumentParsers()
- : this(new()) {}
-
- public ArgumentParsers(ArgumentParserFactory factory) {
- Require.That(factory).Named("argumentParserfactory").IsNotNull();
- _parserFactory = factory;
- }
-
- public ArgumentParser GetParser(DataType dataType) {
- if (!_parsers.ContainsKey(dataType)) {
- if (!_parsers.ContainsKey(dataType)) {
- _parsers.Add(dataType, _parserFactory.CreateArgumentParser(dataType));
- }
- }
- return _parsers[dataType];
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/BoolArgumentParser.cs b/EPPlus/FormulaParsing/Excel/Functions/BoolArgumentParser.cs
deleted file mode 100644
index 3f24d9c..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/BoolArgumentParser.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public class BoolArgumentParser : ArgumentParser {
- public override object Parse(object obj) {
- if (obj is ExcelDataProvider.IRangeInfo info) {
- var r = info.FirstOrDefault();
- obj = r?.Value;
- }
- if (obj == null) {
- return false;
- }
- if (obj is bool b) {
- return b;
- }
- if (obj.IsNumeric()) {
- return Convert.ToBoolean(obj);
- }
- if (bool.TryParse(obj.ToString(), out var result)) {
- return result;
- }
- return result;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/BuiltInFunctions.cs b/EPPlus/FormulaParsing/Excel/Functions/BuiltInFunctions.cs
deleted file mode 100644
index c7d56b2..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/BuiltInFunctions.cs
+++ /dev/null
@@ -1,202 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Numeric;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public class BuiltInFunctions : FunctionsModule {
- public BuiltInFunctions() {
- // Text
- Functions["len"] = new Len();
- Functions["lower"] = new Lower();
- Functions["upper"] = new Upper();
- Functions["left"] = new Left();
- Functions["right"] = new Right();
- Functions["mid"] = new Mid();
- Functions["replace"] = new Replace();
- Functions["rept"] = new Rept();
- Functions["substitute"] = new Substitute();
- Functions["concatenate"] = new Concatenate();
- Functions["char"] = new CharFunction();
- Functions["exact"] = new Exact();
- Functions["find"] = new Find();
- Functions["fixed"] = new Fixed();
- Functions["proper"] = new Proper();
- Functions["text"] = new Text.Text();
- Functions["t"] = new T();
- Functions["hyperlink"] = new Hyperlink();
- // Numbers
- Functions["int"] = new CInt();
- // Math
- Functions["abs"] = new Abs();
- Functions["asin"] = new Asin();
- Functions["asinh"] = new Asinh();
- Functions["cos"] = new Cos();
- Functions["cosh"] = new Cosh();
- Functions["power"] = new Power();
- Functions["sign"] = new Sign();
- Functions["sqrt"] = new Sqrt();
- Functions["sqrtpi"] = new SqrtPi();
- Functions["pi"] = new Pi();
- Functions["product"] = new Product();
- Functions["ceiling"] = new Ceiling();
- Functions["count"] = new Count();
- Functions["counta"] = new CountA();
- Functions["countblank"] = new CountBlank();
- Functions["countif"] = new CountIf();
- Functions["countifs"] = new CountIfs();
- Functions["fact"] = new Fact();
- Functions["floor"] = new Floor();
- Functions["sin"] = new Sin();
- Functions["sinh"] = new Sinh();
- Functions["sum"] = new Sum();
- Functions["sumif"] = new SumIf();
- Functions["sumifs"] = new SumIfs();
- Functions["sumproduct"] = new SumProduct();
- Functions["sumsq"] = new Sumsq();
- Functions["stdev"] = new Stdev();
- Functions["stdevp"] = new StdevP();
- Functions["stdev.s"] = new Stdev();
- Functions["stdev.p"] = new StdevP();
- Functions["subtotal"] = new Subtotal();
- Functions["exp"] = new Exp();
- Functions["log"] = new Log();
- Functions["log10"] = new Log10();
- Functions["ln"] = new Ln();
- Functions["max"] = new Max();
- Functions["maxa"] = new Maxa();
- Functions["median"] = new Median();
- Functions["min"] = new Min();
- Functions["mina"] = new Mina();
- Functions["mod"] = new Mod();
- Functions["average"] = new Average();
- Functions["averagea"] = new AverageA();
- Functions["averageif"] = new AverageIf();
- Functions["averageifs"] = new AverageIfs();
- Functions["round"] = new Round();
- Functions["rounddown"] = new Rounddown();
- Functions["roundup"] = new Roundup();
- Functions["rand"] = new Rand();
- Functions["randbetween"] = new RandBetween();
- Functions["quotient"] = new Quotient();
- Functions["trunc"] = new Trunc();
- Functions["tan"] = new Tan();
- Functions["tanh"] = new Tanh();
- Functions["atan"] = new Atan();
- Functions["atan2"] = new Atan2();
- Functions["atanh"] = new Atanh();
- Functions["acos"] = new Acos();
- Functions["acosh"] = new Acosh();
- Functions["var"] = new Var();
- Functions["varp"] = new VarP();
- Functions["large"] = new Large();
- Functions["small"] = new Small();
- Functions["degrees"] = new Degrees();
- // Information
- Functions["isblank"] = new IsBlank();
- Functions["isnumber"] = new IsNumber();
- Functions["istext"] = new IsText();
- Functions["isnontext"] = new IsNonText();
- Functions["iserror"] = new IsError();
- Functions["iserr"] = new IsErr();
- Functions["error.type"] = new ErrorType();
- Functions["iseven"] = new IsEven();
- Functions["isodd"] = new IsOdd();
- Functions["islogical"] = new IsLogical();
- Functions["isna"] = new IsNa();
- Functions["na"] = new Na();
- Functions["n"] = new N();
- // Logical
- Functions["if"] = new If();
- Functions["iferror"] = new IfError();
- Functions["ifna"] = new IfNa();
- Functions["not"] = new Not();
- Functions["and"] = new And();
- Functions["or"] = new Or();
- Functions["true"] = new True();
- Functions["false"] = new False();
- // Reference and lookup
- Functions["address"] = new Address();
- Functions["hlookup"] = new HLookup();
- Functions["vlookup"] = new VLookup();
- Functions["lookup"] = new Lookup();
- Functions["match"] = new Match();
- Functions["row"] = new Row {
- SkipArgumentEvaluation = true,
- };
- Functions["rows"] = new Rows {
- SkipArgumentEvaluation = true,
- };
- Functions["column"] = new Column {
- SkipArgumentEvaluation = true,
- };
- Functions["columns"] = new Columns {
- SkipArgumentEvaluation = true,
- };
- Functions["choose"] = new Choose();
- Functions["index"] = new Index();
- Functions["indirect"] = new Indirect();
- Functions["offset"] = new Offset {
- SkipArgumentEvaluation = true,
- };
- // Date
- Functions["date"] = new Date();
- Functions["today"] = new Today();
- Functions["now"] = new Now();
- Functions["day"] = new Day();
- Functions["month"] = new Month();
- Functions["year"] = new Year();
- Functions["time"] = new Time();
- Functions["hour"] = new Hour();
- Functions["minute"] = new Minute();
- Functions["second"] = new Second();
- Functions["weeknum"] = new Weeknum();
- Functions["weekday"] = new Weekday();
- Functions["days360"] = new Days360();
- Functions["yearfrac"] = new Yearfrac();
- Functions["edate"] = new Edate();
- Functions["eomonth"] = new Eomonth();
- Functions["isoweeknum"] = new IsoWeekNum();
- Functions["workday"] = new Workday();
- // Database
- Functions["dget"] = new Dget();
- Functions["dcount"] = new Dcount();
- Functions["dcounta"] = new DcountA();
- Functions["dmax"] = new Dmax();
- Functions["dmin"] = new Dmin();
- Functions["dsum"] = new Dsum();
- Functions["daverage"] = new Daverage();
- Functions["dvar"] = new Dvar();
- Functions["dvarp"] = new Dvarp();
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/CellStateHelper.cs b/EPPlus/FormulaParsing/Excel/Functions/CellStateHelper.cs
deleted file mode 100644
index e461919..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/CellStateHelper.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-internal static class CellStateHelper {
- private static bool IsSubTotal(ExcelDataProvider.ICellInfo c) {
- var tokens = c.Tokens;
- if (tokens == null) {
- return false;
- }
- return c.Tokens.Any(token =>
- token.TokenType == TokenType.Function
- && token.Value.Equals("SUBTOTAL", StringComparison.InvariantCultureIgnoreCase));
- }
-
- internal static bool ShouldIgnore(
- bool ignoreHiddenValues,
- ExcelDataProvider.ICellInfo c,
- ParsingContext context) {
- return (ignoreHiddenValues && c.IsHiddenRow)
- || (context.Scopes.Current.IsSubtotal && IsSubTotal(c));
- }
-
- internal static bool ShouldIgnore(
- bool ignoreHiddenValues,
- FunctionArgument arg,
- ParsingContext context) {
- return (ignoreHiddenValues && arg.ExcelStateFlagIsSet(ExcelCellState.HiddenCell));
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/CollectionFlattener.cs b/EPPlus/FormulaParsing/Excel/Functions/CollectionFlattener.cs
deleted file mode 100644
index dfcf5d9..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/CollectionFlattener.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public abstract class CollectionFlattener<T> {
- public virtual IEnumerable<T> FuncArgsToFlatEnumerable(
- IEnumerable<FunctionArgument> arguments,
- Action<FunctionArgument, IList<T>> convertFunc) {
- var argList = new List<T>();
- FuncArgsToFlatEnumerable(arguments, argList, convertFunc);
- return argList;
- }
-
- private void FuncArgsToFlatEnumerable(
- IEnumerable<FunctionArgument> arguments,
- List<T> argList,
- Action<FunctionArgument, IList<T>> convertFunc) {
- foreach (var arg in arguments) {
- if (arg.Value is IEnumerable<FunctionArgument> value) {
- FuncArgsToFlatEnumerable(value, argList, convertFunc);
- } else {
- convertFunc(arg, argList);
- }
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/CompileResultValidator.cs b/EPPlus/FormulaParsing/Excel/Functions/CompileResultValidator.cs
deleted file mode 100644
index e936798..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/CompileResultValidator.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-26
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public abstract class CompileResultValidator {
- public abstract void Validate(object obj);
-
- private static CompileResultValidator _empty;
-
- public static CompileResultValidator Empty =>
- _empty ?? (_empty = new EmptyCompileResultValidator());
-}
-
-internal class EmptyCompileResultValidator : CompileResultValidator {
- public override void Validate(object obj) {
- // empty validator - do nothing
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/CompileResultValidators.cs b/EPPlus/FormulaParsing/Excel/Functions/CompileResultValidators.cs
deleted file mode 100644
index 40f74c5..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/CompileResultValidators.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-26
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public class CompileResultValidators {
- private readonly Dictionary<DataType, CompileResultValidator> _validators = new();
-
- private CompileResultValidator CreateOrGet(DataType dataType) {
- if (_validators.ContainsKey(dataType)) {
- return _validators[dataType];
- }
- if (dataType == DataType.Decimal) {
- return _validators[DataType.Decimal] = new DecimalCompileResultValidator();
- }
- return CompileResultValidator.Empty;
- }
-
- public CompileResultValidator GetValidator(DataType dataType) {
- return CreateOrGet(dataType);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/DSum.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/DSum.cs
deleted file mode 100644
index 5522539..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/DSum.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-19
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public class Dsum : DatabaseFunction {
- public Dsum()
- : this(new()) {}
-
- public Dsum(RowMatcher rowMatcher)
- : base(rowMatcher) {}
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 3);
- var values = GetMatchingValues(arguments, context);
- if (!values.Any()) {
- return CreateResult(0d, DataType.Integer);
- }
- return CreateResult(values.Sum(), DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/DatabaseFunction.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/DatabaseFunction.cs
deleted file mode 100644
index f686f8e..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/DatabaseFunction.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-19
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public abstract class DatabaseFunction : ExcelFunction {
- protected RowMatcher RowMatcher { get; private set; }
-
- public DatabaseFunction()
- : this(new()) {}
-
- public DatabaseFunction(RowMatcher rowMatcher) {
- RowMatcher = rowMatcher;
- }
-
- protected IEnumerable<double> GetMatchingValues(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var dbAddress = arguments.ElementAt(0).ValueAsRangeInfo.Address.Address;
- //var field = ArgToString(arguments, 1).ToLower(CultureInfo.InvariantCulture);
- var field = arguments.ElementAt(1).Value;
- var criteriaRange = arguments.ElementAt(2).ValueAsRangeInfo.Address.Address;
-
- var db = new ExcelDatabase(context.ExcelDataProvider, dbAddress);
- var criteria = new ExcelDatabaseCriteria(context.ExcelDataProvider, criteriaRange);
- var values = new List<double>();
-
- while (db.HasMoreRows) {
- var dataRow = db.Read();
- if (!RowMatcher.IsMatch(dataRow, criteria)) {
- continue;
- }
- var candidate = ConvertUtil.IsNumeric(field)
- ? dataRow[(int)ConvertUtil.GetValueDouble(field)]
- : dataRow[field.ToString().ToLower(CultureInfo.InvariantCulture)];
- if (ConvertUtil.IsNumeric(candidate)) {
- values.Add(ConvertUtil.GetValueDouble(candidate));
- }
- }
- return values;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/Daverage.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/Daverage.cs
deleted file mode 100644
index 21a890a..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/Daverage.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-19
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public class Daverage : DatabaseFunction {
- public Daverage()
- : this(new()) {}
-
- public Daverage(RowMatcher rowMatcher)
- : base(rowMatcher) {}
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 3);
- var values = GetMatchingValues(arguments, context);
- if (!values.Any()) {
- return CreateResult(0d, DataType.Integer);
- }
- return CreateResult(values.Average(), DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/Dcount.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/Dcount.cs
deleted file mode 100644
index 2ad31fa..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/Dcount.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-06
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public class Dcount : ExcelFunction {
- private readonly RowMatcher _rowMatcher;
-
- public Dcount()
- : this(new()) {}
-
- public Dcount(RowMatcher rowMatcher) {
- _rowMatcher = rowMatcher;
- }
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var dbAddress = arguments.ElementAt(0).ValueAsRangeInfo.Address.Address;
- string field = null;
- string criteriaRange = null;
- if (arguments.Count() == 2) {
- criteriaRange = arguments.ElementAt(1).ValueAsRangeInfo.Address.Address;
- } else {
- field = ArgToString(arguments, 1).ToLower(CultureInfo.InvariantCulture);
- criteriaRange = arguments.ElementAt(2).ValueAsRangeInfo.Address.Address;
- }
- var db = new ExcelDatabase(context.ExcelDataProvider, dbAddress);
- var criteria = new ExcelDatabaseCriteria(context.ExcelDataProvider, criteriaRange);
-
- var nHits = 0;
- while (db.HasMoreRows) {
- var dataRow = db.Read();
- if (_rowMatcher.IsMatch(dataRow, criteria)) {
- // if a fieldname is supplied, count only this row if the value
- // of the supplied field is numeric.
- if (!string.IsNullOrEmpty(field)) {
- var candidate = dataRow[field];
- if (ConvertUtil.IsNumeric(candidate)) {
- nHits++;
- }
- } else {
- // no fieldname was supplied, always count matching row.
- nHits++;
- }
- }
- }
- return CreateResult(nHits, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/DcountA.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/DcountA.cs
deleted file mode 100644
index 3af4c77..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/DcountA.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-06
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public class DcountA : DatabaseFunction {
- public DcountA()
- : this(new()) {}
-
- public DcountA(RowMatcher rowMatcher)
- : base(rowMatcher) {}
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var dbAddress = arguments.ElementAt(0).ValueAsRangeInfo.Address.Address;
- string field = null;
- string criteriaRange;
- if (arguments.Count() == 2) {
- criteriaRange = arguments.ElementAt(1).ValueAsRangeInfo.Address.Address;
- } else {
- field = ArgToString(arguments, 1).ToLower(CultureInfo.InvariantCulture);
- criteriaRange = arguments.ElementAt(2).ValueAsRangeInfo.Address.Address;
- }
- var db = new ExcelDatabase(context.ExcelDataProvider, dbAddress);
- var criteria = new ExcelDatabaseCriteria(context.ExcelDataProvider, criteriaRange);
-
- var nHits = 0;
- while (db.HasMoreRows) {
- var dataRow = db.Read();
- if (RowMatcher.IsMatch(dataRow, criteria)) {
- // if a fieldname is supplied, count only this row if the value
- // of the supplied field is not blank.
- if (!string.IsNullOrEmpty(field)) {
- var candidate = dataRow[field];
- if (ShouldCount(candidate)) {
- nHits++;
- }
- } else {
- // no fieldname was supplied, always count matching row.
- nHits++;
- }
- }
- }
- return CreateResult(nHits, DataType.Integer);
- }
-
- private bool ShouldCount(object value) {
- if (value == null) {
- return false;
- }
- return (!string.IsNullOrEmpty(value.ToString()));
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/Dget.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/Dget.cs
deleted file mode 100644
index e8aa790..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/Dget.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-06
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public class Dget : DatabaseFunction {
- public Dget()
- : this(new()) {}
-
- public Dget(RowMatcher rowMatcher)
- : base(rowMatcher) {}
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 3);
- var dbAddress = arguments.ElementAt(0).ValueAsRangeInfo.Address.Address;
- var field = ArgToString(arguments, 1).ToLower(CultureInfo.InvariantCulture);
- var criteriaRange = arguments.ElementAt(2).ValueAsRangeInfo.Address.Address;
-
- var db = new ExcelDatabase(context.ExcelDataProvider, dbAddress);
- var criteria = new ExcelDatabaseCriteria(context.ExcelDataProvider, criteriaRange);
-
- var nHits = 0;
- object retVal = null;
- while (db.HasMoreRows) {
- var dataRow = db.Read();
- if (!RowMatcher.IsMatch(dataRow, criteria)) {
- continue;
- }
- if (++nHits > 1) {
- return CreateResult(ExcelErrorValue.Values.Num, DataType.ExcelError);
- }
- retVal = dataRow[field];
- }
- return new CompileResultFactory().Create(retVal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/Dmax.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/Dmax.cs
deleted file mode 100644
index 62f7d1c..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/Dmax.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-19
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public class Dmax : DatabaseFunction {
- public Dmax()
- : this(new()) {}
-
- public Dmax(RowMatcher rowMatcher)
- : base(rowMatcher) {}
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 3);
- var values = GetMatchingValues(arguments, context);
- if (!values.Any()) {
- return CreateResult(0d, DataType.Integer);
- }
- return CreateResult(values.Max(), DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/Dmin.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/Dmin.cs
deleted file mode 100644
index 8203884..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/Dmin.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-19
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public class Dmin : DatabaseFunction {
- public Dmin()
- : this(new()) {}
-
- public Dmin(RowMatcher rowMatcher)
- : base(rowMatcher) {}
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 3);
- var values = GetMatchingValues(arguments, context);
- if (!values.Any()) {
- return CreateResult(0d, DataType.Integer);
- }
- return CreateResult(values.Min(), DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/Dvar.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/Dvar.cs
deleted file mode 100644
index d961b82..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/Dvar.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-19
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public class Dvar : DatabaseFunction {
- public Dvar()
- : this(new()) {}
-
- public Dvar(RowMatcher rowMatcher)
- : base(rowMatcher) {}
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 3);
- var values = GetMatchingValues(arguments, context);
- if (!values.Any()) {
- return CreateResult(0d, DataType.Integer);
- }
- return CreateResult(VarMethods.Var(values), DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/Dvarp.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/Dvarp.cs
deleted file mode 100644
index 7c43e88..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/Dvarp.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-19
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public class Dvarp : DatabaseFunction {
- public Dvarp()
- : this(new()) {}
-
- public Dvarp(RowMatcher rowMatcher)
- : base(rowMatcher) {}
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 3);
- var values = GetMatchingValues(arguments, context);
- if (!values.Any()) {
- return CreateResult(0d, DataType.Integer);
- }
- return CreateResult(VarMethods.VarP(values), DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabase.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabase.cs
deleted file mode 100644
index 90e3f97..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabase.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-06
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Globalization;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public class ExcelDatabase {
- private readonly ExcelDataProvider _dataProvider;
- private readonly int _fromCol;
- private readonly int _toCol;
- private readonly int _fieldRow;
- private readonly int _endRow;
- private readonly string _worksheet;
- private int _rowIndex;
- private readonly List<ExcelDatabaseField> _fields = new();
-
- public IEnumerable<ExcelDatabaseField> Fields => _fields;
-
- public ExcelDatabase(ExcelDataProvider dataProvider, string range) {
- _dataProvider = dataProvider;
- var address = new ExcelAddressBase(range);
- _fromCol = address._fromCol;
- _toCol = address._toCol;
- _fieldRow = address._fromRow;
- _endRow = address._toRow;
- _worksheet = address.WorkSheet;
- _rowIndex = _fieldRow;
- Initialize();
- }
-
- private void Initialize() {
- var fieldIx = 0;
- for (var colIndex = _fromCol; colIndex <= _toCol; colIndex++) {
- var nameObj = GetCellValue(_fieldRow, colIndex);
- var name =
- nameObj != null ? nameObj.ToString().ToLower(CultureInfo.InvariantCulture) : string.Empty;
- _fields.Add(new(name, fieldIx++));
- }
- }
-
- private object GetCellValue(int row, int col) {
- return _dataProvider.GetRangeValue(_worksheet, row, col);
- }
-
- public bool HasMoreRows => _rowIndex < _endRow;
-
- public ExcelDatabaseRow Read() {
- var retVal = new ExcelDatabaseRow();
- _rowIndex++;
- foreach (var field in Fields) {
- var colIndex = _fromCol + field.ColIndex;
- var val = GetCellValue(_rowIndex, colIndex);
- retVal[field.FieldName] = val;
- }
- return retVal;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteria.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteria.cs
deleted file mode 100644
index f8b8846..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteria.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-06
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Globalization;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public class ExcelDatabaseCriteria {
- private readonly ExcelDataProvider _dataProvider;
- private readonly int _fromCol;
- private readonly int _toCol;
- private readonly string _worksheet;
- private readonly int _fieldRow;
- private readonly Dictionary<ExcelDatabaseCriteriaField, object> _criterias = new();
-
- public ExcelDatabaseCriteria(ExcelDataProvider dataProvider, string range) {
- _dataProvider = dataProvider;
- var address = new ExcelAddressBase(range);
- _fromCol = address._fromCol;
- _toCol = address._toCol;
- _worksheet = address.WorkSheet;
- _fieldRow = address._fromRow;
- Initialize();
- }
-
- private void Initialize() {
- for (var x = _fromCol; x <= _toCol; x++) {
- var fieldObj = _dataProvider.GetCellValue(_worksheet, _fieldRow, x);
- var val = _dataProvider.GetCellValue(_worksheet, _fieldRow + 1, x);
- if (fieldObj != null && val != null) {
- if (fieldObj is string) {
- var field = new ExcelDatabaseCriteriaField(
- fieldObj.ToString().ToLower(CultureInfo.InvariantCulture));
- _criterias.Add(field, val);
- } else if (ConvertUtil.IsNumeric(fieldObj)) {
- var field = new ExcelDatabaseCriteriaField((int)fieldObj);
- _criterias.Add(field, val);
- }
- }
- }
- }
-
- public virtual IDictionary<ExcelDatabaseCriteriaField, object> Items => _criterias;
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteriaField.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteriaField.cs
deleted file mode 100644
index eec151c..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteriaField.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-19
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public class ExcelDatabaseCriteriaField {
- public ExcelDatabaseCriteriaField(string fieldName) {
- FieldName = fieldName;
- }
-
- public ExcelDatabaseCriteriaField(int fieldIndex) {
- FieldIndex = fieldIndex;
- }
-
- public override string ToString() {
- if (!string.IsNullOrEmpty(FieldName)) {
- return FieldName;
- }
- return base.ToString();
- }
-
- public string FieldName { get; private set; }
-
- public int? FieldIndex { get; private set; }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseField.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseField.cs
deleted file mode 100644
index 9578486..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseField.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-06
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public class ExcelDatabaseField {
- public string FieldName { get; private set; }
-
- public int ColIndex { get; private set; }
-
- public ExcelDatabaseField(string fieldName, int colIndex) {
- FieldName = fieldName;
- ColIndex = colIndex;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseRow.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseRow.cs
deleted file mode 100644
index e3c9a12..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseRow.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-19
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public class ExcelDatabaseRow {
- private readonly Dictionary<int, string> _fieldIndexes = new();
- private readonly Dictionary<string, object> _items = new();
- private int _colIndex = 1;
-
- public object this[string field] {
- get => _items[field];
- set {
- _items[field] = value;
- _fieldIndexes[_colIndex++] = field;
- }
- }
-
- public object this[int index] {
- get {
- var field = _fieldIndexes[index];
- return _items[field];
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Database/RowMatcher.cs b/EPPlus/FormulaParsing/Excel/Functions/Database/RowMatcher.cs
deleted file mode 100644
index 3493872..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/RowMatcher.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-06
- *******************************************************************************/
-
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.Utilities;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
-
-public class RowMatcher {
- private readonly WildCardValueMatcher _wildCardValueMatcher;
- private readonly NumericExpressionEvaluator _numericExpressionEvaluator;
-
- public RowMatcher()
- : this(new(), new()) {}
-
- public RowMatcher(
- WildCardValueMatcher wildCardValueMatcher,
- NumericExpressionEvaluator numericExpressionEvaluator) {
- _wildCardValueMatcher = wildCardValueMatcher;
- _numericExpressionEvaluator = numericExpressionEvaluator;
- }
-
- public bool IsMatch(ExcelDatabaseRow row, ExcelDatabaseCriteria criteria) {
- var retVal = true;
- foreach (var c in criteria.Items) {
- var candidate = c.Key.FieldIndex.HasValue
- ? row[c.Key.FieldIndex.Value]
- : row[c.Key.FieldName];
- var crit = c.Value;
- if (candidate.IsNumeric() && crit.IsNumeric()) {
- if (System.Math.Abs(
- ConvertUtil.GetValueDouble(candidate) - ConvertUtil.GetValueDouble(crit))
- > double.Epsilon) {
- return false;
- }
- } else {
- var criteriaString = crit.ToString();
- if (!Evaluate(candidate, criteriaString)) {
- return false;
- }
- }
- }
- return retVal;
- }
-
- private bool Evaluate(object obj, string expression) {
- if (obj == null) {
- return false;
- }
- double? candidate = default(double?);
- if (ConvertUtil.IsNumeric(obj)) {
- candidate = ConvertUtil.GetValueDouble(obj);
- }
- if (candidate.HasValue) {
- return _numericExpressionEvaluator.Evaluate(candidate.Value, expression);
- }
- return _wildCardValueMatcher.IsMatch(expression, obj.ToString()) == 0;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Date.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Date.cs
deleted file mode 100644
index e2e8ad9..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Date.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Date : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 3);
- var year = ArgToInt(arguments, 0);
- var month = ArgToInt(arguments, 1);
- var day = ArgToInt(arguments, 2);
- var date = new System.DateTime(year, 1, 1);
- month -= 1;
- date = date.AddMonths(month);
- date = date.AddDays(day - 1);
- return CreateResult(date.ToOADate(), DataType.Date);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/DateParsingFunction.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/DateParsingFunction.cs
deleted file mode 100644
index 47143ef..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/DateParsingFunction.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System.Collections.Generic;
-using System.Globalization;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public abstract class DateParsingFunction : ExcelFunction {
- protected System.DateTime ParseDate(IEnumerable<FunctionArgument> arguments, object dateObj) {
- System.DateTime date;
- if (dateObj is string) {
- date = System.DateTime.Parse(dateObj.ToString(), CultureInfo.InvariantCulture);
- } else {
- var d = ArgToDecimal(arguments, 0);
- date = System.DateTime.FromOADate(d);
- }
- return date;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/DateStringParser.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/DateStringParser.cs
deleted file mode 100644
index 74860bf..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/DateStringParser.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class DateStringParser {}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/DateValue.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/DateValue.cs
deleted file mode 100644
index a474018..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/DateValue.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-/// <summary>
-/// Simple implementation of DateValue function, just using .NET built-in
-/// function System.DateTime.TryParse, based on current culture
-/// </summary>
-public class DateValue : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var dateString = ArgToString(arguments, 0);
- return Execute(dateString);
- }
-
- internal CompileResult Execute(string dateString) {
- System.DateTime.TryParse(dateString, out var result);
- return result != System.DateTime.MinValue
- ? CreateResult(result.ToOADate(), DataType.Date)
- : CreateResult(ExcelErrorValue.Create(eErrorType.Value), DataType.ExcelError);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Day.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Day.cs
deleted file mode 100644
index dc4d39c..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Day.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Day : DateParsingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var dateObj = GetFirstValue(arguments);
- var date = ParseDate(arguments, dateObj);
-
- return CreateResult(date.Day, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Days360.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Days360.cs
deleted file mode 100644
index 797053e..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Days360.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Days360 : ExcelFunction {
- private enum Days360Calctype {
- European,
- Us,
- }
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var numDate1 = ArgToDecimal(arguments, 0);
- var numDate2 = ArgToDecimal(arguments, 1);
- var dt1 = System.DateTime.FromOADate(numDate1);
- var dt2 = System.DateTime.FromOADate(numDate2);
-
- var calcType = Days360Calctype.Us;
- if (arguments.Count() > 2) {
- var european = ArgToBool(arguments, 2);
- if (european) {
- calcType = Days360Calctype.European;
- }
- }
-
- var startYear = dt1.Year;
- var startMonth = dt1.Month;
- var startDay = dt1.Day;
- var endYear = dt2.Year;
- var endMonth = dt2.Month;
- var endDay = dt2.Day;
-
- if (calcType == Days360Calctype.European) {
- if (startDay == 31) {
- startDay = 30;
- }
- if (endDay == 31) {
- endDay = 30;
- }
- } else {
- var calendar = new GregorianCalendar();
- var nDaysInFeb = calendar.IsLeapYear(dt1.Year) ? 29 : 28;
-
- // If the investment is EOM and (Date1 is the last day of February) and (Date2 is the last day of February), then change D2 to 30.
- if (startMonth == 2 && startDay == nDaysInFeb && endMonth == 2 && endDay == nDaysInFeb) {
- endDay = 30;
- }
- // If the investment is EOM and (Date1 is the last day of February), then change D1 to 30.
- if (startMonth == 2 && startDay == nDaysInFeb) {
- startDay = 30;
- }
- // If D2 is 31 and D1 is 30 or 31, then change D2 to 30.
- if (endDay == 31 && (startDay == 30 || startDay == 31)) {
- endDay = 30;
- }
- // If D1 is 31, then change D1 to 30.
- if (startDay == 31) {
- startDay = 30;
- }
- }
- var result =
- (endYear * 12 * 30 + endMonth * 30 + endDay)
- - (startYear * 12 * 30 + startMonth * 30 + startDay);
- return CreateResult(result, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Edate.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Edate.cs
deleted file mode 100644
index 7a1af10..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Edate.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Edate : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2, eErrorType.Value);
- var dateSerial = ArgToDecimal(arguments, 0);
- var date = System.DateTime.FromOADate(dateSerial);
- var nMonthsToAdd = ArgToInt(arguments, 1);
- var resultDate = date.AddMonths(nMonthsToAdd);
- return CreateResult(resultDate.ToOADate(), DataType.Date);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Eomonth.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Eomonth.cs
deleted file mode 100644
index 33454da..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Eomonth.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Eomonth : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var date = System.DateTime.FromOADate(ArgToDecimal(arguments, 0));
- var monthsToAdd = ArgToInt(arguments, 1);
- var resultDate = new System.DateTime(date.Year, date.Month, 1)
- .AddMonths(monthsToAdd + 1)
- .AddDays(-1);
- return CreateResult(resultDate.ToOADate(), DataType.Date);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Hour.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Hour.cs
deleted file mode 100644
index 5509889..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Hour.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Hour : DateParsingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var dateObj = arguments.ElementAt(0).Value;
- var date = ParseDate(arguments, dateObj);
- return CreateResult(date.Hour, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/IsoWeekNum.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/IsoWeekNum.cs
deleted file mode 100644
index 45b838b..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/IsoWeekNum.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using System;
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class IsoWeekNum : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var dateInt = ArgToInt(arguments, 0);
- var date = System.DateTime.FromOADate(dateInt);
- return CreateResult(WeekNumber(date), DataType.Integer);
- }
-
- /// <summary>
- /// This implementation was found on http://stackoverflow.com/questions/1285191/get-week-of-date-from-linq-query
- /// </summary>
- /// <param name="fromDate"></param>
- /// <returns></returns>
- private int WeekNumber(System.DateTime fromDate) {
- // Get jan 1st of the year
- var startOfYear = fromDate.AddDays(-fromDate.Day + 1).AddMonths(-fromDate.Month + 1);
- // Get dec 31st of the year
- var endOfYear = startOfYear.AddYears(1).AddDays(-1);
- // ISO 8601 weeks start with Monday
- // The first week of a year includes the first Thursday
- // DayOfWeek returns 0 for sunday up to 6 for saterday
- int[] iso8601Correction = { 6, 7, 8, 9, 10, 4, 5 };
- int nds = fromDate.Subtract(startOfYear).Days + iso8601Correction[(int)startOfYear.DayOfWeek];
- int wk = nds / 7;
- switch (wk) {
- case 0:
- // Return weeknumber of dec 31st of the previous year
- return WeekNumber(startOfYear.AddDays(-1));
- case 53:
- // If dec 31st falls before thursday it is week 01 of next year
- if (endOfYear.DayOfWeek < DayOfWeek.Thursday) {
- return 1;
- }
- return wk;
- default:
- return wk;
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Minute.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Minute.cs
deleted file mode 100644
index a93b354..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Minute.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Minute : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var dateObj = arguments.ElementAt(0).Value;
- System.DateTime date;
- if (dateObj is string) {
- date = System.DateTime.Parse(dateObj.ToString());
- } else {
- var d = ArgToDecimal(arguments, 0);
- date = System.DateTime.FromOADate(d);
- }
- return CreateResult(date.Minute, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Month.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Month.cs
deleted file mode 100644
index c6aaba4..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Month.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Month : DateParsingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var dateObj = arguments.ElementAt(0).Value;
- var date = ParseDate(arguments, dateObj);
- return CreateResult(date.Month, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Networkdays.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Networkdays.cs
deleted file mode 100644
index 93e419e..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Networkdays.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Networkdays : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
- ValidateArguments(functionArguments, 2);
- var startDate = System.DateTime.FromOADate(ArgToInt(functionArguments, 0));
- var endDate = System.DateTime.FromOADate(ArgToInt(functionArguments, 1));
- var calculator = new WorkdayCalculator();
- var result = calculator.CalculateNumberOfWorkdays(startDate, endDate);
- if (functionArguments.Length > 2) {
- result = calculator.ReduceWorkdaysWithHolidays(result, functionArguments[2]);
- }
-
- return new(result.NumberOfWorkdays, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/NetworkdaysIntl.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/NetworkdaysIntl.cs
deleted file mode 100644
index e3e1891..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/NetworkdaysIntl.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class NetworkdaysIntl : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
- ValidateArguments(functionArguments, 2);
- var startDate = System.DateTime.FromOADate(ArgToInt(functionArguments, 0));
- var endDate = System.DateTime.FromOADate(ArgToInt(functionArguments, 1));
- WorkdayCalculator calculator = new WorkdayCalculator();
- var weekdayFactory = new HolidayWeekdaysFactory();
- if (functionArguments.Length > 2) {
- var holidayArg = functionArguments[2].Value;
- if (Regex.IsMatch(holidayArg.ToString(), "^[01]{7}")) {
- calculator = new(weekdayFactory.Create(holidayArg.ToString()));
- } else if (IsNumeric(holidayArg)) {
- var holidayCode = Convert.ToInt32(holidayArg);
- calculator = new(weekdayFactory.Create(holidayCode));
- } else {
- return new(eErrorType.Value);
- }
- }
- var result = calculator.CalculateNumberOfWorkdays(startDate, endDate);
- if (functionArguments.Length > 3) {
- result = calculator.ReduceWorkdaysWithHolidays(result, functionArguments[3]);
- }
- return new(result.NumberOfWorkdays, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Now.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Now.cs
deleted file mode 100644
index b4bd17d..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Now.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Now : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- return CreateResult(System.DateTime.Now.ToOADate(), DataType.Date);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Second.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Second.cs
deleted file mode 100644
index 443e913..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Second.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Second : DateParsingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var dateObj = arguments.ElementAt(0).Value;
- System.DateTime date = ParseDate(arguments, dateObj);
- return CreateResult(date.Second, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Time.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Time.cs
deleted file mode 100644
index fb1144e..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Time.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Time : TimeBaseFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var firstArg = arguments.ElementAt(0).Value.ToString();
- if (arguments.Count() == 1 && TimeStringParser.CanParse(firstArg)) {
- var result = TimeStringParser.Parse(firstArg);
- return new(result, DataType.Time);
- }
- ValidateArguments(arguments, 3);
- var hour = ArgToInt(arguments, 0);
- var min = ArgToInt(arguments, 1);
- var sec = ArgToInt(arguments, 2);
-
- ThrowArgumentExceptionIf(() => sec < 0 || sec > 59, "Invalid second: " + sec);
- ThrowArgumentExceptionIf(() => min < 0 || min > 59, "Invalid minute: " + min);
- ThrowArgumentExceptionIf(() => min < 0 || hour > 23, "Invalid hour: " + hour);
-
- var secondsOfThisTime = (double)(hour * 60 * 60 + min * 60 + sec);
- return CreateResult(GetTimeSerialNumber(secondsOfThisTime), DataType.Time);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/TimeBaseFunction.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/TimeBaseFunction.cs
deleted file mode 100644
index 4b2ef4a..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/TimeBaseFunction.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public abstract class TimeBaseFunction : ExcelFunction {
- protected TimeStringParser TimeStringParser { get; private set; } = new();
-
- protected double SerialNumber { get; private set; }
-
- public void ValidateAndInitSerialNumber(IEnumerable<FunctionArgument> arguments) {
- ValidateArguments(arguments, 1);
- SerialNumber = ArgToDecimal(arguments, 0);
- }
-
- protected double SecondsInADay => 24 * 60 * 60;
-
- protected double GetTimeSerialNumber(double seconds) {
- return seconds / SecondsInADay;
- }
-
- protected double GetSeconds(double serialNumber) {
- return serialNumber * SecondsInADay;
- }
-
- protected double GetHour(double serialNumber) {
- var seconds = GetSeconds(serialNumber);
- return (int)seconds / (60 * 60);
- }
-
- protected double GetMinute(double serialNumber) {
- var seconds = GetSeconds(serialNumber);
- seconds -= GetHour(serialNumber) * 60 * 60;
- return (seconds - (seconds % 60)) / 60;
- }
-
- protected double GetSecond(double serialNumber) {
- return GetSeconds(serialNumber) % 60;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/TimeStringParser.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/TimeStringParser.cs
deleted file mode 100644
index 0c403b6..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/TimeStringParser.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Text.RegularExpressions;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class TimeStringParser {
- private const string _regEx24 = @"^[0-9]{1,2}(\:[0-9]{1,2}){0,2}$";
- private const string _regEx12 = @"^[0-9]{1,2}(\:[0-9]{1,2}){0,2}( PM| AM)$";
-
- private double GetSerialNumber(int hour, int minute, int second) {
- var secondsInADay = 24d * 60d * 60d;
- return ((double)hour * 60 * 60 + (double)minute * 60 + second) / secondsInADay;
- }
-
- private void ValidateValues(int hour, int minute, int second) {
- if (second < 0 || second > 59) {
- throw new FormatException("Illegal value for second: " + second);
- }
- if (minute < 0 || minute > 59) {
- throw new FormatException("Illegal value for minute: " + minute);
- }
- }
-
- public virtual double Parse(string input) {
- return InternalParse(input);
- }
-
- public virtual bool CanParse(string input) {
- System.DateTime dt;
- return Regex.IsMatch(input, _regEx24)
- || Regex.IsMatch(input, _regEx12)
- || System.DateTime.TryParse(input, out dt);
- }
-
- private double InternalParse(string input) {
- if (Regex.IsMatch(input, _regEx24)) {
- return Parse24HourTimeString(input);
- }
- if (Regex.IsMatch(input, _regEx12)) {
- return Parse12HourTimeString(input);
- }
- if (System.DateTime.TryParse(input, out var dateTime)) {
- return GetSerialNumber(dateTime.Hour, dateTime.Minute, dateTime.Second);
- }
- return -1;
- }
-
- private double Parse12HourTimeString(string input) {
- var dayPart = input.Substring(input.Length - 2, 2);
- GetValuesFromString(input, out var hour, out var minute, out var second);
- if (dayPart == "PM") {
- hour += 12;
- }
- ValidateValues(hour, minute, second);
- return GetSerialNumber(hour, minute, second);
- }
-
- private double Parse24HourTimeString(string input) {
- GetValuesFromString(input, out var hour, out var minute, out var second);
- ValidateValues(hour, minute, second);
- return GetSerialNumber(hour, minute, second);
- }
-
- private static void GetValuesFromString(
- string input,
- out int hour,
- out int minute,
- out int second) {
- hour = 0;
- minute = 0;
- second = 0;
-
- var items = input.Split(':');
- hour = int.Parse(items[0]);
- if (items.Length > 1) {
- minute = int.Parse(items[1]);
- }
- if (items.Length > 2) {
- var val = items[2];
- val = Regex.Replace(val, "[^0-9]+$", string.Empty);
- second = int.Parse(val);
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/TimeValue.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/TimeValue.cs
deleted file mode 100644
index c2de2e0..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/TimeValue.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-/// <summary>
-/// Simple implementation of TimeValue function, just using .NET built-in
-/// function System.DateTime.TryParse, based on current culture
-/// </summary>
-public class TimeValue : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var dateString = ArgToString(arguments, 0);
- return Execute(dateString);
- }
-
- internal CompileResult Execute(string dateString) {
- System.DateTime.TryParse(dateString, out var result);
- return result != System.DateTime.MinValue
- ? CreateResult(GetTimeValue(result), DataType.Date)
- : CreateResult(ExcelErrorValue.Create(eErrorType.Value), DataType.ExcelError);
- }
-
- private double GetTimeValue(System.DateTime result) {
- return (int)result.TimeOfDay.TotalSeconds == 0
- ? 0d
- : result.TimeOfDay.TotalSeconds / (3600 * 24);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Today.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Today.cs
deleted file mode 100644
index e6ff48f..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Today.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Today : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- return CreateResult(System.DateTime.Today.ToOADate(), DataType.Date);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Weekday.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Weekday.cs
deleted file mode 100644
index cf1af33..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Weekday.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Weekday : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var serialNumber = ArgToDecimal(arguments, 0);
- var returnType = arguments.Count() > 1 ? ArgToInt(arguments, 1) : 1;
- return CreateResult(
- CalculateDayOfWeek(System.DateTime.FromOADate(serialNumber), returnType),
- DataType.Integer);
- }
-
- private static readonly List<int> _oneBasedStartOnSunday = new() { 1, 2, 3, 4, 5, 6, 7 };
- private static readonly List<int> _oneBasedStartOnMonday = new() { 7, 1, 2, 3, 4, 5, 6 };
- private static readonly List<int> _zeroBasedStartOnSunday = new() { 6, 0, 1, 2, 3, 4, 5 };
-
- private int CalculateDayOfWeek(System.DateTime dateTime, int returnType) {
- var dayIx = (int)dateTime.DayOfWeek;
- switch (returnType) {
- case 1:
- return _oneBasedStartOnSunday[dayIx];
- case 2:
- return _oneBasedStartOnMonday[dayIx];
- case 3:
- return _zeroBasedStartOnSunday[dayIx];
- default:
- throw new ExcelErrorValueException(eErrorType.Num);
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Weeknum.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Weeknum.cs
deleted file mode 100644
index f5c1b05..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Weeknum.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Weeknum : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1, eErrorType.Value);
- var dateSerial = ArgToDecimal(arguments, 0);
- var date = System.DateTime.FromOADate(dateSerial);
- var startDay = DayOfWeek.Sunday;
- if (arguments.Count() > 1) {
- var argStartDay = ArgToInt(arguments, 1);
- switch (argStartDay) {
- case 1:
- startDay = DayOfWeek.Sunday;
- break;
- case 2:
- case 11:
- startDay = DayOfWeek.Monday;
- break;
- case 12:
- startDay = DayOfWeek.Tuesday;
- break;
- case 13:
- startDay = DayOfWeek.Wednesday;
- break;
- case 14:
- startDay = DayOfWeek.Thursday;
- break;
- case 15:
- startDay = DayOfWeek.Friday;
- break;
- case 16:
- startDay = DayOfWeek.Saturday;
- break;
- default:
- // Not supported
- ThrowExcelErrorValueException(eErrorType.Num);
- break;
- }
- }
- if (DateTimeFormatInfo.CurrentInfo == null) {
- throw new InvalidOperationException(
- "Could not execute Weeknum function because DateTimeFormatInfo.CurrentInfo was null");
- }
- var week = DateTimeFormatInfo.CurrentInfo.Calendar.GetWeekOfYear(
- date,
- CalendarWeekRule.FirstDay,
- startDay);
- return CreateResult(week, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workday.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workday.cs
deleted file mode 100644
index 947bc3e..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workday.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Workday : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var startDate = System.DateTime.FromOADate(ArgToInt(arguments, 0));
- var nWorkDays = ArgToInt(arguments, 1);
- var resultDate = System.DateTime.MinValue;
- var workdaysCounted = 0;
- var tmpDate = startDate;
- // first move forward to the first monday
- while (tmpDate.DayOfWeek != DayOfWeek.Monday && (nWorkDays - workdaysCounted) > 0) {
- if (!IsHoliday(tmpDate)) {
- workdaysCounted++;
- }
- tmpDate = tmpDate.AddDays(1);
- }
- // then calculate whole weeks
- var nWholeWeeks = (nWorkDays - workdaysCounted) / 5;
- tmpDate = tmpDate.AddDays(nWholeWeeks * 7);
- workdaysCounted += nWholeWeeks * 5;
-
- // calculate the rest
- while (workdaysCounted < nWorkDays) {
- tmpDate = tmpDate.AddDays(1);
- if (!IsHoliday(tmpDate)) {
- workdaysCounted++;
- }
- }
- resultDate = AdjustResultWithHolidays(tmpDate, arguments);
- return CreateResult(resultDate.ToOADate(), DataType.Date);
- }
-
- private System.DateTime AdjustResultWithHolidays(
- System.DateTime resultDate,
- IEnumerable<FunctionArgument> arguments) {
- if (arguments.Count() == 2) {
- return resultDate;
- }
- var holidays = arguments.ElementAt(2).Value as IEnumerable<FunctionArgument>;
- if (holidays != null) {
- foreach (var arg in holidays) {
- if (ConvertUtil.IsNumeric(arg.Value)) {
- var dateSerial = ConvertUtil.GetValueDouble(arg.Value);
- var holidayDate = System.DateTime.FromOADate(dateSerial);
- if (!IsHoliday(holidayDate)) {
- resultDate = resultDate.AddDays(1);
- }
- }
- }
- } else {
- var range = arguments.ElementAt(2).Value as ExcelDataProvider.IRangeInfo;
- if (range != null) {
- foreach (var cell in range) {
- if (ConvertUtil.IsNumeric(cell.Value)) {
- var dateSerial = ConvertUtil.GetValueDouble(cell.Value);
- var holidayDate = System.DateTime.FromOADate(dateSerial);
- if (!IsHoliday(holidayDate)) {
- resultDate = resultDate.AddDays(1);
- }
- }
- }
- }
- }
- return resultDate;
- }
-
- private bool IsHoliday(System.DateTime date) {
- return date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/AdditionalHolidayDays.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/AdditionalHolidayDays.cs
deleted file mode 100644
index 38bd021..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/AdditionalHolidayDays.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays;
-
-public class AdditionalHolidayDays {
- private readonly FunctionArgument _holidayArg;
- private readonly List<System.DateTime> _holidayDates = new();
-
- public AdditionalHolidayDays(FunctionArgument holidayArg) {
- _holidayArg = holidayArg;
- Initialize();
- }
-
- public IEnumerable<System.DateTime> AdditionalDates => _holidayDates;
-
- private void Initialize() {
- var holidays = _holidayArg.Value as IEnumerable<FunctionArgument>;
- if (holidays != null) {
- foreach (var holidayDate in from arg in holidays
- where ConvertUtil.IsNumeric(arg.Value)
- select ConvertUtil.GetValueDouble(arg.Value) into dateSerial
- select System.DateTime.FromOADate(dateSerial)) {
- _holidayDates.Add(holidayDate);
- }
- }
- var range = _holidayArg.Value as ExcelDataProvider.IRangeInfo;
- if (range != null) {
- foreach (var holidayDate in from cell in range
- where ConvertUtil.IsNumeric(cell.Value)
- select ConvertUtil.GetValueDouble(cell.Value) into dateSerial
- select System.DateTime.FromOADate(dateSerial)) {
- _holidayDates.Add(holidayDate);
- }
- }
- if (ConvertUtil.IsNumeric(_holidayArg.Value)) {
- _holidayDates.Add(System.DateTime.FromOADate(ConvertUtil.GetValueDouble(_holidayArg.Value)));
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdays.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdays.cs
deleted file mode 100644
index 3e866b0..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdays.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays;
-
-public class HolidayWeekdays {
- private readonly List<DayOfWeek> _holidayDays = new();
-
- public HolidayWeekdays()
- : this(DayOfWeek.Saturday, DayOfWeek.Sunday) {}
-
- public int NumberOfWorkdaysPerWeek => 7 - _holidayDays.Count;
-
- public HolidayWeekdays(params DayOfWeek[] holidayDays) {
- foreach (var dayOfWeek in holidayDays) {
- _holidayDays.Add(dayOfWeek);
- }
- }
-
- public bool IsHolidayWeekday(System.DateTime dateTime) {
- return _holidayDays.Contains(dateTime.DayOfWeek);
- }
-
- public System.DateTime AdjustResultWithHolidays(
- System.DateTime resultDate,
- IEnumerable<FunctionArgument> arguments) {
- if (arguments.Count() == 2) {
- return resultDate;
- }
- var holidays = arguments.ElementAt(2).Value as IEnumerable<FunctionArgument>;
- if (holidays != null) {
- foreach (var arg in holidays) {
- if (ConvertUtil.IsNumeric(arg.Value)) {
- var dateSerial = ConvertUtil.GetValueDouble(arg.Value);
- var holidayDate = System.DateTime.FromOADate(dateSerial);
- if (!IsHolidayWeekday(holidayDate)) {
- resultDate = resultDate.AddDays(1);
- }
- }
- }
- } else {
- var range = arguments.ElementAt(2).Value as ExcelDataProvider.IRangeInfo;
- if (range != null) {
- foreach (var cell in range) {
- if (ConvertUtil.IsNumeric(cell.Value)) {
- var dateSerial = ConvertUtil.GetValueDouble(cell.Value);
- var holidayDate = System.DateTime.FromOADate(dateSerial);
- if (!IsHolidayWeekday(holidayDate)) {
- resultDate = resultDate.AddDays(1);
- }
- }
- }
- }
- }
- return resultDate;
- }
-
- public System.DateTime GetNextWorkday(
- System.DateTime date,
- WorkdayCalculationDirection direction = WorkdayCalculationDirection.Forward) {
- var changeParam = (int)direction;
- var tmpDate = date.AddDays(changeParam);
- while (IsHolidayWeekday(tmpDate)) {
- tmpDate = tmpDate.AddDays(changeParam);
- }
- return tmpDate;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdaysFactory.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdaysFactory.cs
deleted file mode 100644
index cf17962..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdaysFactory.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays;
-
-public class HolidayWeekdaysFactory {
- private readonly DayOfWeek[] _dayOfWeekArray = {
- DayOfWeek.Monday,
- DayOfWeek.Tuesday,
- DayOfWeek.Wednesday,
- DayOfWeek.Thursday,
- DayOfWeek.Friday,
- DayOfWeek.Saturday,
- DayOfWeek.Sunday,
- };
-
- public HolidayWeekdays Create(string weekdays) {
- if (string.IsNullOrEmpty(weekdays) || weekdays.Length != 7) {
- throw new ArgumentException("Illegal weekday string", nameof(Weekday));
- }
-
- var retVal = new List<DayOfWeek>();
- var arr = weekdays.ToCharArray();
- for (var i = 0; i < arr.Length; i++) {
- var ch = arr[i];
- if (ch == '1') {
- retVal.Add(_dayOfWeekArray[i]);
- }
- }
- return new(retVal.ToArray());
- }
-
- public HolidayWeekdays Create(int code) {
- switch (code) {
- case 1:
- return new(DayOfWeek.Saturday, DayOfWeek.Sunday);
- case 2:
- return new(DayOfWeek.Sunday, DayOfWeek.Monday);
- case 3:
- return new(DayOfWeek.Monday, DayOfWeek.Tuesday);
- case 4:
- return new(DayOfWeek.Tuesday, DayOfWeek.Wednesday);
- case 5:
- return new(DayOfWeek.Wednesday, DayOfWeek.Thursday);
- case 6:
- return new(DayOfWeek.Thursday, DayOfWeek.Friday);
- case 7:
- return new(DayOfWeek.Friday, DayOfWeek.Saturday);
- case 11:
- return new(DayOfWeek.Sunday);
- case 12:
- return new(DayOfWeek.Monday);
- case 13:
- return new(DayOfWeek.Tuesday);
- case 14:
- return new(DayOfWeek.Wednesday);
- case 15:
- return new(DayOfWeek.Thursday);
- case 16:
- return new(DayOfWeek.Friday);
- case 17:
- return new(DayOfWeek.Saturday);
- default:
- throw new ArgumentException("Invalid code supplied to HolidayWeekdaysFactory: " + code);
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculationDirection.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculationDirection.cs
deleted file mode 100644
index c0f56b4..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculationDirection.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays;
-
-public enum WorkdayCalculationDirection {
- Forward = 1,
- Backward = -1,
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculator.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculator.cs
deleted file mode 100644
index e09e7ba..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculator.cs
+++ /dev/null
@@ -1,123 +0,0 @@
-using System.Linq;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays;
-
-public class WorkdayCalculator {
- private readonly HolidayWeekdays _holidayWeekdays;
-
- public WorkdayCalculator()
- : this(new()) {}
-
- public WorkdayCalculator(HolidayWeekdays holidayWeekdays) {
- _holidayWeekdays = holidayWeekdays;
- }
-
- public WorkdayCalculatorResult CalculateNumberOfWorkdays(
- System.DateTime startDate,
- System.DateTime endDate) {
- var calcDirection =
- startDate < endDate
- ? WorkdayCalculationDirection.Forward
- : WorkdayCalculationDirection.Backward;
- System.DateTime calcStartDate;
- System.DateTime calcEndDate;
- if (calcDirection == WorkdayCalculationDirection.Forward) {
- calcStartDate = startDate.Date;
- calcEndDate = endDate.Date;
- } else {
- calcStartDate = endDate.Date;
- calcEndDate = startDate.Date;
- }
- var nWholeWeeks = (int)calcEndDate.Subtract(calcStartDate).TotalDays / 7;
- var workdaysCounted = nWholeWeeks * _holidayWeekdays.NumberOfWorkdaysPerWeek;
- if (!_holidayWeekdays.IsHolidayWeekday(calcStartDate)) {
- workdaysCounted++;
- }
- var tmpDate = calcStartDate.AddDays(nWholeWeeks * 7);
- while (tmpDate < calcEndDate) {
- tmpDate = tmpDate.AddDays(1);
- if (!_holidayWeekdays.IsHolidayWeekday(tmpDate)) {
- workdaysCounted++;
- }
- }
- return new(workdaysCounted, startDate, endDate, calcDirection);
- }
-
- public WorkdayCalculatorResult CalculateWorkday(System.DateTime startDate, int nWorkDays) {
- var calcDirection =
- nWorkDays > 0 ? WorkdayCalculationDirection.Forward : WorkdayCalculationDirection.Backward;
- var direction = (int)calcDirection;
- nWorkDays *= direction;
- var workdaysCounted = 0;
- var tmpDate = startDate;
-
- // calculate whole weeks
- var nWholeWeeks = nWorkDays / _holidayWeekdays.NumberOfWorkdaysPerWeek;
- tmpDate = tmpDate.AddDays(nWholeWeeks * 7 * direction);
- workdaysCounted += nWholeWeeks * _holidayWeekdays.NumberOfWorkdaysPerWeek;
-
- // calculate the rest
- while (workdaysCounted < nWorkDays) {
- tmpDate = tmpDate.AddDays(direction);
- if (!_holidayWeekdays.IsHolidayWeekday(tmpDate)) {
- workdaysCounted++;
- }
- }
- return new(workdaysCounted, startDate, tmpDate, calcDirection);
- }
-
- public WorkdayCalculatorResult ReduceWorkdaysWithHolidays(
- WorkdayCalculatorResult calculatedResult,
- FunctionArgument holidayArgument) {
- var startDate = calculatedResult.StartDate;
- var endDate = calculatedResult.EndDate;
- var additionalDays = new AdditionalHolidayDays(holidayArgument);
- System.DateTime calcStartDate;
- System.DateTime calcEndDate;
- if (startDate < endDate) {
- calcStartDate = startDate;
- calcEndDate = endDate;
- } else {
- calcStartDate = endDate;
- calcEndDate = startDate;
- }
- var nAdditionalHolidayDays = additionalDays.AdditionalDates.Count(x =>
- x >= calcStartDate && x <= calcEndDate && !_holidayWeekdays.IsHolidayWeekday(x));
- return new(
- calculatedResult.NumberOfWorkdays - nAdditionalHolidayDays,
- startDate,
- endDate,
- calculatedResult.Direction);
- }
-
- public WorkdayCalculatorResult AdjustResultWithHolidays(
- WorkdayCalculatorResult calculatedResult,
- FunctionArgument holidayArgument) {
- var startDate = calculatedResult.StartDate;
- var endDate = calculatedResult.EndDate;
- var direction = calculatedResult.Direction;
- var workdaysCounted = calculatedResult.NumberOfWorkdays;
- var additionalDays = new AdditionalHolidayDays(holidayArgument);
- foreach (var date in additionalDays.AdditionalDates) {
- if (direction == WorkdayCalculationDirection.Forward
- && (date < startDate || date > endDate)) {
- continue;
- }
- if (direction == WorkdayCalculationDirection.Backward
- && (date > startDate || date < endDate)) {
- continue;
- }
- if (_holidayWeekdays.IsHolidayWeekday(date)) {
- continue;
- }
- var tmpDate = _holidayWeekdays.GetNextWorkday(endDate, direction);
- while (additionalDays.AdditionalDates.Contains(tmpDate)) {
- tmpDate = _holidayWeekdays.GetNextWorkday(tmpDate, direction);
- }
- workdaysCounted++;
- endDate = tmpDate;
- }
-
- return new(workdaysCounted, calculatedResult.StartDate, endDate, direction);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculatorResult.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculatorResult.cs
deleted file mode 100644
index a61a05e..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculatorResult.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays;
-
-public class WorkdayCalculatorResult {
- public WorkdayCalculatorResult(
- int numberOfWorkdays,
- System.DateTime startDate,
- System.DateTime endDate,
- WorkdayCalculationDirection direction) {
- NumberOfWorkdays = numberOfWorkdays;
- StartDate = startDate;
- EndDate = endDate;
- Direction = direction;
- }
-
- public int NumberOfWorkdays { get; }
-
- public System.DateTime StartDate { get; }
-
- public System.DateTime EndDate { get; }
-
- public WorkdayCalculationDirection Direction { get; set; }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Year.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Year.cs
deleted file mode 100644
index 103c487..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Year.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Year : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var dateObj = arguments.ElementAt(0).Value;
- System.DateTime date = System.DateTime.MinValue;
- if (dateObj is string) {
- date = System.DateTime.Parse(dateObj.ToString());
- } else {
- var d = ArgToDecimal(arguments, 0);
- date = System.DateTime.FromOADate(d);
- }
- return CreateResult(date.Year, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Yearfrac.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Yearfrac.cs
deleted file mode 100644
index 440c46a..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Yearfrac.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-
-public class Yearfrac : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
- ValidateArguments(functionArguments, 2);
- var date1Num = ArgToDecimal(functionArguments, 0);
- var date2Num = ArgToDecimal(functionArguments, 1);
- if (date1Num
- > date2Num) //Switch to make date1 the lowest date
- {
- var t = date1Num;
- date1Num = date2Num;
- date2Num = t;
- var fa = functionArguments[1];
- functionArguments[1] = functionArguments[0];
- functionArguments[0] = fa;
- }
- var date1 = System.DateTime.FromOADate(date1Num);
- var date2 = System.DateTime.FromOADate(date2Num);
-
- var basis = 0;
- if (functionArguments.Count() > 2) {
- basis = ArgToInt(functionArguments, 2);
- ThrowExcelErrorValueExceptionIf(() => basis < 0 || basis > 4, eErrorType.Num);
- }
- var func = context.Configuration.FunctionRepository.GetFunction("days360");
- var calendar = new GregorianCalendar();
- switch (basis) {
- case 0:
- var d360Result = System.Math.Abs(func.Execute(functionArguments, context).ResultNumeric);
- // reproducing excels behaviour
- if (date1.Month == 2 && date2.Day == 31) {
- var daysInFeb = calendar.IsLeapYear(date1.Year) ? 29 : 28;
- if (date1.Day == daysInFeb) {
- d360Result++;
- }
- }
- return CreateResult(d360Result / 360d, DataType.Decimal);
- case 1:
- return CreateResult(
- System.Math.Abs((date2 - date1).TotalDays / CalculateAcutalYear(date1, date2)),
- DataType.Decimal);
- case 2:
- return CreateResult(System.Math.Abs((date2 - date1).TotalDays / 360d), DataType.Decimal);
- case 3:
- return CreateResult(System.Math.Abs((date2 - date1).TotalDays / 365d), DataType.Decimal);
- case 4:
- var args = functionArguments.ToList();
- args.Add(new(true));
- double? result = System.Math.Abs(func.Execute(args, context).ResultNumeric / 360d);
- return CreateResult(result.Value, DataType.Decimal);
- default:
- return null;
- }
- }
-
- private double CalculateAcutalYear(System.DateTime dt1, System.DateTime dt2) {
- var calendar = new GregorianCalendar();
- var perYear = 0d;
- var nYears = dt2.Year - dt1.Year + 1;
- for (var y = dt1.Year; y <= dt2.Year; ++y) {
- perYear += calendar.IsLeapYear(y) ? 366 : 365;
- }
- if (new System.DateTime(dt1.Year + 1, dt1.Month, dt1.Day) >= dt2) {
- nYears = 1;
- perYear = 365;
- if (calendar.IsLeapYear(dt1.Year) && dt1.Month <= 2) {
- perYear = 366;
- } else if (calendar.IsLeapYear(dt2.Year) && dt2.Month > 2) {
- perYear = 366;
- } else if (dt2.Month == 2 && dt2.Day == 29) {
- perYear = 366;
- }
- }
- return perYear / nYears;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DecimalCompileResultValidator.cs b/EPPlus/FormulaParsing/Excel/Functions/DecimalCompileResultValidator.cs
deleted file mode 100644
index 208cfa2..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DecimalCompileResultValidator.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-26
- *******************************************************************************/
-
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public class DecimalCompileResultValidator : CompileResultValidator {
- public override void Validate(object obj) {
- var num = ConvertUtil.GetValueDouble(obj);
- if (double.IsNaN(num) || double.IsInfinity(num)) {
- throw new ExcelErrorValueException(eErrorType.Num);
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DoubleArgumentParser.cs b/EPPlus/FormulaParsing/Excel/Functions/DoubleArgumentParser.cs
deleted file mode 100644
index ed0cec4..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DoubleArgumentParser.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Globalization;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.Utilities;
-using ConvertUtil = OfficeOpenXml.Utils.ConvertUtil;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public class DoubleArgumentParser : ArgumentParser {
- public override object Parse(object obj) {
- Require.That(obj).Named("argument").IsNotNull();
- if (obj is ExcelDataProvider.IRangeInfo info) {
- var r = info.FirstOrDefault();
- return r?.ValueDouble ?? 0;
- }
- if (obj is double) {
- return obj;
- }
- if (obj.IsNumeric()) {
- return ConvertUtil.GetValueDouble(obj);
- }
- var str = obj != null ? obj.ToString() : string.Empty;
- try {
- return double.Parse(str, CultureInfo.InvariantCulture);
- } catch // (Exception e)
- {
- throw new ExcelErrorValueException(ExcelErrorValue.Create(eErrorType.Value));
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DoubleEnumerableArgConverter.cs b/EPPlus/FormulaParsing/Excel/Functions/DoubleEnumerableArgConverter.cs
deleted file mode 100644
index 1895872..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/DoubleEnumerableArgConverter.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public class DoubleEnumerableArgConverter : CollectionFlattener<double> {
- public virtual IEnumerable<double> ConvertArgs(
- bool ignoreHidden,
- bool ignoreErrors,
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- return base.FuncArgsToFlatEnumerable(
- arguments,
- (arg, argList) => {
- if (arg.IsExcelRange) {
- foreach (var cell in arg.ValueAsRangeInfo) {
- if (!ignoreErrors && cell.IsExcelError) {
- throw new ExcelErrorValueException(ExcelErrorValue.Parse(cell.Value.ToString()));
- }
- if (!CellStateHelper.ShouldIgnore(ignoreHidden, cell, context)
- && ConvertUtil.IsNumeric(cell.Value)) {
- argList.Add(cell.ValueDouble);
- }
- }
- } else {
- if (!ignoreErrors && arg.ValueIsExcelError) {
- throw new ExcelErrorValueException(arg.ValueAsExcelErrorValue);
- }
- if (ConvertUtil.IsNumeric(arg.Value)
- && !CellStateHelper.ShouldIgnore(ignoreHidden, arg, context)) {
- argList.Add(ConvertUtil.GetValueDouble(arg.Value));
- }
- }
- });
- }
-
- public virtual IEnumerable<double> ConvertArgsIncludingOtherTypes(
- IEnumerable<FunctionArgument> arguments) {
- return base.FuncArgsToFlatEnumerable(
- arguments,
- (arg, argList) => {
- //var cellInfo = arg.Value as EpplusExcelDataProvider.CellInfo;
- //var value = cellInfo != null ? cellInfo.Value : arg.Value;
- if (arg.Value is ExcelDataProvider.IRangeInfo info) {
- foreach (var cell in info) {
- argList.Add(cell.ValueDoubleLogical);
- }
- } else {
- if (arg.Value is double || arg.Value is int || arg.Value is bool) {
- argList.Add(Convert.ToDouble(arg.Value));
- } else if (arg.Value is string) {
- argList.Add(0d);
- }
- }
- });
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/ErrorHandlingFunction.cs b/EPPlus/FormulaParsing/Excel/Functions/ErrorHandlingFunction.cs
deleted file mode 100644
index fb950a8..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/ErrorHandlingFunction.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-/// <summary>
-/// Base class for functions that handles an error that occurs during the
-/// normal execution of the function.
-/// If an exception occurs during the Execute-call that exception will be
-/// caught by the compiler, then the HandleError-method will be called.
-/// </summary>
-public abstract class ErrorHandlingFunction : ExcelFunction {
- /// <summary>
- /// Indicates that the function is an ErrorHandlingFunction.
- /// </summary>
- public override bool IsErrorHandlingFunction => true;
-
- /// <summary>
- /// Method that should be implemented to handle the error.
- /// </summary>
- /// <param name="errorCode"></param>
- /// <returns></returns>
- public abstract CompileResult HandleError(string errorCode);
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/ExcelFunction.cs b/EPPlus/FormulaParsing/Excel/Functions/ExcelFunction.cs
deleted file mode 100644
index a1ae44c..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/ExcelFunction.cs
+++ /dev/null
@@ -1,439 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-/// <summary>
-/// Base class for Excel function implementations.
-/// </summary>
-public abstract class ExcelFunction {
- public ExcelFunction()
- : this(new(), new(), new()) {}
-
- public ExcelFunction(
- ArgumentCollectionUtil argumentCollectionUtil,
- ArgumentParsers argumentParsers,
- CompileResultValidators compileResultValidators) {
- _argumentCollectionUtil = argumentCollectionUtil;
- _argumentParsers = argumentParsers;
- _compileResultValidators = compileResultValidators;
- }
-
- private readonly ArgumentCollectionUtil _argumentCollectionUtil;
- private readonly ArgumentParsers _argumentParsers;
- private readonly CompileResultValidators _compileResultValidators;
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="arguments">Arguments to the function, each argument can contain primitive types, lists or <see cref="ExcelDataProvider.IRangeInfo">Excel ranges</see></param>
- /// <param name="context">The <see cref="ParsingContext"/> contains various data that can be useful in functions.</param>
- /// <returns>A <see cref="CompileResult"/> containing the calculated value</returns>
- public abstract CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context);
-
- /// <summary>
- /// If overridden, this method is called before Execute is called.
- /// </summary>
- /// <param name="context"></param>
- public virtual void BeforeInvoke(ParsingContext context) {}
-
- public virtual bool IsLookupFuction => false;
-
- public virtual bool IsErrorHandlingFunction => false;
-
- /// <summary>
- /// Used for some Lookupfunctions to indicate that function arguments should
- /// not be compiled before the function is called.
- /// </summary>
- public bool SkipArgumentEvaluation { get; set; }
-
- protected object GetFirstValue(IEnumerable<FunctionArgument> val) {
- var arg = val.FirstOrDefault();
- if (arg.Value is ExcelDataProvider.IRangeInfo) {
- //var r=((ExcelDataProvider.IRangeInfo)arg);
- var r = arg.ValueAsRangeInfo;
- return r.GetValue(r.Address._fromRow, r.Address._fromCol);
- }
- return arg?.Value;
- }
-
- /// <summary>
- /// This functions validates that the supplied <paramref name="arguments"/> contains at least
- /// (the value of) <paramref name="minLength"/> elements. If one of the arguments is an
- /// <see cref="ExcelDataProvider.IRangeInfo">Excel range</see> the number of cells in
- /// that range will be counted as well.
- /// </summary>
- /// <param name="arguments"></param>
- /// <param name="minLength"></param>
- /// <param name="errorTypeToThrow">The <see cref="eErrorType"/> of the <see cref="ExcelErrorValueException"/> that will be thrown if <paramref name="minLength"/> is not met.</param>
- protected void ValidateArguments(
- IEnumerable<FunctionArgument> arguments,
- int minLength,
- eErrorType errorTypeToThrow) {
- Require.That(arguments).Named("arguments").IsNotNull();
- ThrowExcelErrorValueExceptionIf(
- () => {
- var nArgs = 0;
- if (arguments.Any()) {
- foreach (var arg in arguments) {
- nArgs++;
- if (nArgs >= minLength) {
- return false;
- }
- if (arg.IsExcelRange) {
- nArgs += arg.ValueAsRangeInfo.GetNCells();
- if (nArgs >= minLength) {
- return false;
- }
- }
- }
- }
- return true;
- },
- errorTypeToThrow);
- }
-
- /// <summary>
- /// This functions validates that the supplied <paramref name="arguments"/> contains at least
- /// (the value of) <paramref name="minLength"/> elements. If one of the arguments is an
- /// <see cref="ExcelDataProvider.IRangeInfo">Excel range</see> the number of cells in
- /// that range will be counted as well.
- /// </summary>
- /// <param name="arguments"></param>
- /// <param name="minLength"></param>
- /// <exception cref="ArgumentException"></exception>
- protected void ValidateArguments(IEnumerable<FunctionArgument> arguments, int minLength) {
- Require.That(arguments).Named("arguments").IsNotNull();
- ThrowArgumentExceptionIf(
- () => {
- var nArgs = 0;
- if (arguments.Any()) {
- foreach (var arg in arguments) {
- nArgs++;
- if (nArgs >= minLength) {
- return false;
- }
- if (arg.IsExcelRange) {
- nArgs += arg.ValueAsRangeInfo.GetNCells();
- if (nArgs >= minLength) {
- return false;
- }
- }
- }
- }
- return true;
- },
- "Expecting at least {0} arguments",
- minLength.ToString());
- }
-
- /// <summary>
- /// Returns the value of the argument att the position of the 0-based
- /// <paramref name="index"/> as an integer.
- /// </summary>
- /// <param name="arguments"></param>
- /// <param name="index"></param>
- /// <returns>Value of the argument as an integer.</returns>
- /// <exception cref="ExcelErrorValueException"></exception>
- protected int ArgToInt(IEnumerable<FunctionArgument> arguments, int index) {
- var val = arguments.ElementAt(index).ValueFirst;
- return (int)_argumentParsers.GetParser(DataType.Integer).Parse(val);
- }
-
- /// <summary>
- /// Returns the value of the argument att the position of the 0-based
- /// <paramref name="index"/> as a string.
- /// </summary>
- /// <param name="arguments"></param>
- /// <param name="index"></param>
- /// <returns>Value of the argument as a string.</returns>
- protected string ArgToString(IEnumerable<FunctionArgument> arguments, int index) {
- var obj = arguments.ElementAt(index).ValueFirst;
- return obj != null ? obj.ToString() : string.Empty;
- }
-
- /// <summary>
- /// Returns the value of the argument att the position of the 0-based
- /// </summary>
- /// <param name="obj"></param>
- /// <returns>Value of the argument as a double.</returns>
- /// <exception cref="ExcelErrorValueException"></exception>
- protected double ArgToDecimal(object obj) {
- return (double)_argumentParsers.GetParser(DataType.Decimal).Parse(obj);
- }
-
- /// <summary>
- /// Returns the value of the argument att the position of the 0-based
- /// <paramref name="index"/> as a <see cref="System.Double"/>.
- /// </summary>
- /// <param name="arguments"></param>
- /// <param name="index"></param>
- /// <returns>Value of the argument as an integer.</returns>
- /// <exception cref="ExcelErrorValueException"></exception>
- protected double ArgToDecimal(IEnumerable<FunctionArgument> arguments, int index) {
- return ArgToDecimal(arguments.ElementAt(index).Value);
- }
-
- protected double Divide(double left, double right) {
- if (System.Math.Abs(right - 0d) < double.Epsilon) {
- throw new ExcelErrorValueException(eErrorType.Div0);
- }
- return left / right;
- }
-
- protected bool IsNumericString(object value) {
- if (value == null || string.IsNullOrEmpty(value.ToString())) {
- return false;
- }
- return Regex.IsMatch(value.ToString(), @"^[\d]+(\,[\d])?");
- }
-
- /// <summary>
- /// If the argument is a boolean value its value will be returned.
- /// If the argument is an integer value, true will be returned if its
- /// value is not 0, otherwise false.
- /// </summary>
- /// <param name="arguments"></param>
- /// <param name="index"></param>
- /// <returns></returns>
- protected bool ArgToBool(IEnumerable<FunctionArgument> arguments, int index) {
- var obj = arguments.ElementAt(index).Value ?? string.Empty;
- return (bool)_argumentParsers.GetParser(DataType.Boolean).Parse(obj);
- }
-
- /// <summary>
- /// Throws an <see cref="ArgumentException"/> if <paramref name="condition"/> evaluates to true.
- /// </summary>
- /// <param name="condition"></param>
- /// <param name="message"></param>
- /// <exception cref="ArgumentException"></exception>
- protected void ThrowArgumentExceptionIf(Func<bool> condition, string message) {
- if (condition()) {
- throw new ArgumentException(message);
- }
- }
-
- /// <summary>
- /// Throws an <see cref="ArgumentException"/> if <paramref name="condition"/> evaluates to true.
- /// </summary>
- /// <param name="condition"></param>
- /// <param name="message"></param>
- /// <param name="formats">Formats to the message string.</param>
- protected void ThrowArgumentExceptionIf(
- Func<bool> condition,
- string message,
- params object[] formats) {
- message = string.Format(message, formats);
- ThrowArgumentExceptionIf(condition, message);
- }
-
- /// <summary>
- /// Throws an <see cref="ExcelErrorValueException"/> with the given <paramref name="errorType"/> set.
- /// </summary>
- /// <param name="errorType"></param>
- protected void ThrowExcelErrorValueException(eErrorType errorType) {
- throw new ExcelErrorValueException(
- "An excel function error occurred",
- ExcelErrorValue.Create(errorType));
- }
-
- /// <summary>
- /// Throws an <see cref="ArgumentException"/> if <paramref name="condition"/> evaluates to true.
- /// </summary>
- /// <param name="condition"></param>
- /// <param name="errorType"></param>
- /// <exception cref="ExcelErrorValueException"></exception>
- protected void ThrowExcelErrorValueExceptionIf(Func<bool> condition, eErrorType errorType) {
- if (condition()) {
- throw new ExcelErrorValueException(
- "An excel function error occurred",
- ExcelErrorValue.Create(errorType));
- }
- }
-
- protected bool IsNumeric(object val) {
- if (val == null) {
- return false;
- }
- return (val.GetType().IsPrimitive
- || val is double
- || val is decimal
- || val is System.DateTime
- || val is TimeSpan);
- }
-
- //protected virtual bool IsNumber(object obj)
- //{
- // if (obj == null) return false;
- // return (obj is int || obj is double || obj is short || obj is decimal || obj is long);
- //}
-
- /// <summary>
- /// Helper method for comparison of two doubles.
- /// </summary>
- /// <param name="d1"></param>
- /// <param name="d2"></param>
- /// <returns></returns>
- protected bool AreEqual(double d1, double d2) {
- return System.Math.Abs(d1 - d2) < double.Epsilon;
- }
-
- /// <summary>
- /// Will return the arguments as an enumerable of doubles.
- /// </summary>
- /// <param name="arguments"></param>
- /// <param name="context"></param>
- /// <returns></returns>
- protected virtual IEnumerable<double> ArgsToDoubleEnumerable(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- return ArgsToDoubleEnumerable(false, arguments, context);
- }
-
- /// <summary>
- /// Will return the arguments as an enumerable of doubles.
- /// </summary>
- /// <param name="ignoreHiddenCells">If a cell is hidden and this value is true the value of that cell will be ignored</param>
- /// <param name="ignoreErrors">If a cell contains an error, that error will be ignored if this method is set to true</param>
- /// <param name="arguments"></param>
- /// <param name="context"></param>
- /// <returns></returns>
- protected virtual IEnumerable<double> ArgsToDoubleEnumerable(
- bool ignoreHiddenCells,
- bool ignoreErrors,
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- return _argumentCollectionUtil.ArgsToDoubleEnumerable(
- ignoreHiddenCells,
- ignoreErrors,
- arguments,
- context);
- }
-
- /// <summary>
- /// Will return the arguments as an enumerable of doubles.
- /// </summary>
- /// <param name="ignoreHiddenCells">If a cell is hidden and this value is true the value of that cell will be ignored</param>
- /// <param name="arguments"></param>
- /// <param name="context"></param>
- /// <returns></returns>
- protected virtual IEnumerable<double> ArgsToDoubleEnumerable(
- bool ignoreHiddenCells,
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- return ArgsToDoubleEnumerable(ignoreHiddenCells, true, arguments, context);
- }
-
- /// <summary>
- /// Will return the arguments as an enumerable of objects.
- /// </summary>
- /// <param name="ignoreHiddenCells">If a cell is hidden and this value is true the value of that cell will be ignored</param>
- /// <param name="arguments"></param>
- /// <param name="context"></param>
- /// <returns></returns>
- protected virtual IEnumerable<object> ArgsToObjectEnumerable(
- bool ignoreHiddenCells,
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- return _argumentCollectionUtil.ArgsToObjectEnumerable(ignoreHiddenCells, arguments, context);
- }
-
- /// <summary>
- /// Use this method to create a result to return from Excel functions.
- /// </summary>
- /// <param name="result"></param>
- /// <param name="dataType"></param>
- /// <returns></returns>
- protected CompileResult CreateResult(object result, DataType dataType) {
- var validator = _compileResultValidators.GetValidator(dataType);
- validator.Validate(result);
- return new(result, dataType);
- }
-
- /// <summary>
- /// Use this method to apply a function on a collection of arguments. The <paramref name="result"/>
- /// should be modifyed in the supplied <paramref name="action"/> and will contain the result
- /// after this operation has been performed.
- /// </summary>
- /// <param name="collection"></param>
- /// <param name="result"></param>
- /// <param name="action"></param>
- /// <returns></returns>
- protected virtual double CalculateCollection(
- IEnumerable<FunctionArgument> collection,
- double result,
- Func<FunctionArgument, double, double> action) {
- return _argumentCollectionUtil.CalculateCollection(collection, result, action);
- }
-
- /// <summary>
- /// if the supplied <paramref name="arg">argument</paramref> contains an Excel error
- /// an <see cref="ExcelErrorValueException"/> with that errorcode will be thrown
- /// </summary>
- /// <param name="arg"></param>
- /// <exception cref="ExcelErrorValueException"></exception>
- protected void CheckForAndHandleExcelError(FunctionArgument arg) {
- if (arg.ValueIsExcelError) {
- throw (new ExcelErrorValueException(arg.ValueAsExcelErrorValue));
- }
- }
-
- /// <summary>
- /// If the supplied <paramref name="cell"/> contains an Excel error
- /// an <see cref="ExcelErrorValueException"/> with that errorcode will be thrown
- /// </summary>
- /// <param name="cell"></param>
- protected void CheckForAndHandleExcelError(ExcelDataProvider.ICellInfo cell) {
- if (cell.IsExcelError) {
- throw (new ExcelErrorValueException(ExcelErrorValue.Parse(cell.Value.ToString())));
- }
- }
-
- protected CompileResult GetResultByObject(object result) {
- if (IsNumeric(result)) {
- return CreateResult(result, DataType.Decimal);
- }
- if (result is string) {
- return CreateResult(result, DataType.String);
- }
- if (ExcelErrorValue.Values.IsErrorValue(result)) {
- return CreateResult(result, DataType.ExcelAddress);
- }
- if (result == null) {
- return CompileResult.Empty;
- }
- return CreateResult(result, DataType.Enumerable);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/FunctionArgument.cs b/EPPlus/FormulaParsing/Excel/Functions/FunctionArgument.cs
deleted file mode 100644
index baa9da7..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/FunctionArgument.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public class FunctionArgument {
- public FunctionArgument(object val) {
- Value = val;
- }
-
- private ExcelCellState _excelCellState;
-
- public void SetExcelStateFlag(ExcelCellState state) {
- _excelCellState |= state;
- }
-
- public bool ExcelStateFlagIsSet(ExcelCellState state) {
- return (_excelCellState & state) != 0;
- }
-
- public object Value { get; private set; }
-
- public Type Type => Value?.GetType();
-
- public bool IsExcelRange => Value != null && Value is ExcelDataProvider.IRangeInfo;
-
- public bool ValueIsExcelError => ExcelErrorValue.Values.IsErrorValue(Value);
-
- public ExcelErrorValue ValueAsExcelErrorValue => ExcelErrorValue.Parse(Value.ToString());
-
- public ExcelDataProvider.IRangeInfo ValueAsRangeInfo => Value as ExcelDataProvider.IRangeInfo;
-
- public object ValueFirst {
- get {
- if (Value is ExcelDataProvider.INameInfo info) {
- Value = info.Value;
- }
- var v = Value as ExcelDataProvider.IRangeInfo;
- if (v == null) {
- return Value;
- }
- return v.GetValue(v.Address._fromRow, v.Address._fromCol);
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/FunctionNameProvider.cs b/EPPlus/FormulaParsing/Excel/Functions/FunctionNameProvider.cs
deleted file mode 100644
index 012a7c7..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/FunctionNameProvider.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public class FunctionNameProvider : IFunctionNameProvider {
- private FunctionNameProvider() {}
-
- public static FunctionNameProvider Empty => new();
-
- public virtual bool IsFunctionName(string name) {
- return false;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/FunctionRepository.cs b/EPPlus/FormulaParsing/Excel/Functions/FunctionRepository.cs
deleted file mode 100644
index fe09617..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/FunctionRepository.cs
+++ /dev/null
@@ -1,121 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-// Used to report the names of Excel functions that are not supported by EPPlus
-public class FunctionException : SystemException {
- // Summary:
- // Initializes a new instance of the System.FunctionException class.
- public FunctionException() {}
-
- //
- // Summary:
- // Initializes a new instance of the System.FunctionException class with a specified
- // error message.
- //
- // Parameters:
- // message:
- // The message that describes the error.
- public FunctionException(string message)
- : base(message) {}
-}
-
-/// <summary>
-/// This class provides methods for accessing/modifying VBA Functions.
-/// </summary>
-public class FunctionRepository : IFunctionNameProvider {
- private readonly Dictionary<string, ExcelFunction> _functions = new(
- StringComparer.InvariantCulture);
-
- private FunctionRepository() {}
-
- public static FunctionRepository Create() {
- var repo = new FunctionRepository();
- repo.LoadModule(new BuiltInFunctions());
- return repo;
- }
-
- /// <summary>
- /// Loads a module of <see cref="ExcelFunction"/>s to the function repository.
- /// </summary>
- /// <param name="module">A <see cref="IFunctionModule"/> that can be used for adding functions</param>
- public virtual void LoadModule(IFunctionModule module) {
- foreach (var key in module.Functions.Keys) {
- var lowerKey = key.ToLower(CultureInfo.InvariantCulture);
- _functions[lowerKey] = module.Functions[key];
- }
- }
-
- public virtual ExcelFunction GetFunction(string name) {
- if (!_functions.ContainsKey(name.ToLower(CultureInfo.InvariantCulture))) {
- // Report that Excel function is not supported by EPPlus
- throw new FunctionException(
- string.Format("Excel function '{0}' is not supported in formulas.", name));
- }
- return _functions[name.ToLower(CultureInfo.InvariantCulture)];
- }
-
- /// <summary>
- /// Removes all functions from the repository
- /// </summary>
- public virtual void Clear() {
- _functions.Clear();
- }
-
- /// <summary>
- /// Returns true if the the supplied <paramref name="name"/> exists in the repository.
- /// </summary>
- /// <param name="name"></param>
- /// <returns></returns>
- public bool IsFunctionName(string name) {
- return _functions.ContainsKey(name.ToLower(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// Returns the names of all implemented functions.
- /// </summary>
- public IEnumerable<string> FunctionNames => _functions.Keys;
-
- /// <summary>
- /// Adds or replaces a function.
- /// </summary>
- /// <param name="functionName"> Case-insensitive name of the function that should be added or replaced.</param>
- /// <param name="functionImpl">An implementation of an <see cref="ExcelFunction"/>.</param>
- public void AddOrReplaceFunction(string functionName, ExcelFunction functionImpl) {
- Require.That(functionName).Named("functionName").IsNotNullOrEmpty();
- Require.That(functionImpl).Named("functionImpl").IsNotNull();
- var fName = functionName.ToLower(CultureInfo.InvariantCulture);
- if (_functions.ContainsKey(fName)) {
- _functions.Remove(fName);
- }
- _functions[fName] = functionImpl;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/FunctionsModule.cs b/EPPlus/FormulaParsing/Excel/Functions/FunctionsModule.cs
deleted file mode 100644
index 522451a..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/FunctionsModule.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-/// <summary>
-/// Base class
-/// </summary>
-public abstract class FunctionsModule : IFunctionModule {
- private readonly Dictionary<string, ExcelFunction> _functions = new();
-
- public IDictionary<string, ExcelFunction> Functions => _functions;
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/HiddenValuesHandlingFunction.cs b/EPPlus/FormulaParsing/Excel/Functions/HiddenValuesHandlingFunction.cs
deleted file mode 100644
index 81b3cc8..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/HiddenValuesHandlingFunction.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-/// <summary>
-/// Base class for functions that needs to handle cells that is not visible.
-/// </summary>
-public abstract class HiddenValuesHandlingFunction : ExcelFunction {
- /// <summary>
- /// Set to true or false to indicate whether the function should ignore hidden values.
- /// </summary>
- public bool IgnoreHiddenValues { get; set; }
-
- protected override IEnumerable<double> ArgsToDoubleEnumerable(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- return ArgsToDoubleEnumerable(arguments, context, true);
- }
-
- protected IEnumerable<double> ArgsToDoubleEnumerable(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context,
- bool ignoreErrors) {
- if (!arguments.Any()) {
- return Enumerable.Empty<double>();
- }
- if (IgnoreHiddenValues) {
- var nonHidden = arguments.Where(x => !x.ExcelStateFlagIsSet(ExcelCellState.HiddenCell));
- return base.ArgsToDoubleEnumerable(IgnoreHiddenValues, nonHidden, context);
- }
- return base.ArgsToDoubleEnumerable(IgnoreHiddenValues, ignoreErrors, arguments, context);
- }
-
- protected bool ShouldIgnore(ExcelDataProvider.ICellInfo c, ParsingContext context) {
- return CellStateHelper.ShouldIgnore(IgnoreHiddenValues, c, context);
- }
-
- protected bool ShouldIgnore(FunctionArgument arg) {
- if (IgnoreHiddenValues && arg.ExcelStateFlagIsSet(ExcelCellState.HiddenCell)) {
- return true;
- }
- return false;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/IFunctionModule.cs b/EPPlus/FormulaParsing/Excel/Functions/IFunctionModule.cs
deleted file mode 100644
index 6ab248f..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/IFunctionModule.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public interface IFunctionModule {
- IDictionary<string, ExcelFunction> Functions { get; }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/IFunctionNameProvider.cs b/EPPlus/FormulaParsing/Excel/Functions/IFunctionNameProvider.cs
deleted file mode 100644
index 5722862..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/IFunctionNameProvider.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public interface IFunctionNameProvider {
- bool IsFunctionName(string name);
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Information/ErrorType.cs b/EPPlus/FormulaParsing/Excel/Functions/Information/ErrorType.cs
deleted file mode 100644
index f68f0f9..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/ErrorType.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-15
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
-
-public class ErrorType : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var error = arguments.ElementAt(0);
- var isErrorFunc = context.Configuration.FunctionRepository.GetFunction("iserror");
- var isErrorResult = isErrorFunc.Execute(arguments, context);
- if (!(bool)isErrorResult.Result) {
- return CreateResult(ExcelErrorValue.Create(eErrorType.Na), DataType.ExcelError);
- }
- var errorType = error.ValueAsExcelErrorValue;
- switch (errorType.Type) {
- case eErrorType.Null:
- return CreateResult(1, DataType.Integer);
- case eErrorType.Div0:
- return CreateResult(2, DataType.Integer);
- case eErrorType.Value:
- return CreateResult(3, DataType.Integer);
- case eErrorType.Ref:
- return CreateResult(4, DataType.Integer);
- case eErrorType.Name:
- return CreateResult(5, DataType.Integer);
- case eErrorType.Num:
- return CreateResult(6, DataType.Integer);
- case eErrorType.Na:
- return CreateResult(7, DataType.Integer);
- // Bug G0004
- case eErrorType.Error:
- return CreateResult(8, DataType.Integer);
- }
- return CreateResult(ExcelErrorValue.Create(eErrorType.Na), DataType.ExcelError);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Information/IsBlank.cs b/EPPlus/FormulaParsing/Excel/Functions/Information/IsBlank.cs
deleted file mode 100644
index 8923a4c..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsBlank.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
-
-public class IsBlank : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- if (arguments == null || arguments.Count() == 0) {
- return CreateResult(true, DataType.Boolean);
- }
- var result = true;
- foreach (var arg in arguments) {
- if (arg.Value is ExcelDataProvider.IRangeInfo info) {
- if (info.GetValue(info.Address._fromRow, info.Address._fromCol) != null) {
- result = false;
- }
- } else {
- if (arg.Value != null && (arg.Value.ToString() != string.Empty)) {
- result = false;
- break;
- }
- }
- }
- return CreateResult(result, DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Information/IsErr.cs b/EPPlus/FormulaParsing/Excel/Functions/Information/IsErr.cs
deleted file mode 100644
index d857231..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsErr.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
-
-public class IsErr : ErrorHandlingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var isError = new IsError();
- var result = isError.Execute(arguments, context);
- if ((bool)result.Result) {
- var arg = GetFirstValue(arguments);
- if (arg is ExcelDataProvider.IRangeInfo info) {
- var e = info.GetValue(info.Address._fromRow, info.Address._fromCol) as ExcelErrorValue;
- if (e != null && e.Type == eErrorType.Na) {
- return CreateResult(false, DataType.Boolean);
- }
- } else {
- if (arg is ExcelErrorValue value && value.Type == eErrorType.Na) {
- return CreateResult(false, DataType.Boolean);
- }
- }
- }
- return result;
- }
-
- public override CompileResult HandleError(string errorCode) {
- return CreateResult(true, DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Information/IsError.cs b/EPPlus/FormulaParsing/Excel/Functions/Information/IsError.cs
deleted file mode 100644
index 11aaf0b..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsError.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
-
-public class IsError : ErrorHandlingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- if (arguments == null || arguments.Count() == 0) {
- return CreateResult(false, DataType.Boolean);
- }
- foreach (var argument in arguments) {
- if (argument.Value is ExcelDataProvider.IRangeInfo info) {
- if (ExcelErrorValue.Values.IsErrorValue(
- info.GetValue(info.Address._fromRow, info.Address._fromCol))) {
- return CreateResult(true, DataType.Boolean);
- }
- } else {
- if (ExcelErrorValue.Values.IsErrorValue(argument.Value)) {
- return CreateResult(true, DataType.Boolean);
- }
- }
- }
- return CreateResult(false, DataType.Boolean);
- }
-
- public override CompileResult HandleError(string errorCode) {
- return CreateResult(true, DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Information/IsEven.cs b/EPPlus/FormulaParsing/Excel/Functions/Information/IsEven.cs
deleted file mode 100644
index af8bf4e..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsEven.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
-
-public class IsEven : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg1 = GetFirstValue(arguments); //arguments.ElementAt(0);
- if (!ConvertUtil.IsNumeric(arg1)) {
- ThrowExcelErrorValueException(eErrorType.Value);
- }
- var number = (int)System.Math.Floor(ConvertUtil.GetValueDouble(arg1));
- return CreateResult(number % 2 == 0, DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Information/IsLogical.cs b/EPPlus/FormulaParsing/Excel/Functions/Information/IsLogical.cs
deleted file mode 100644
index fbda5d6..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsLogical.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
-
-public class IsLogical : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
- ValidateArguments(functionArguments, 1);
- var v = GetFirstValue(arguments);
- return CreateResult(v is bool, DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Information/IsNa.cs b/EPPlus/FormulaParsing/Excel/Functions/Information/IsNa.cs
deleted file mode 100644
index 641ea01..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsNa.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-15
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
-
-public class IsNa : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- if (arguments == null || arguments.Count() == 0) {
- return CreateResult(false, DataType.Boolean);
- }
-
- var v = GetFirstValue(arguments);
-
- if (v is ExcelErrorValue value && value.Type == eErrorType.Na) {
- return CreateResult(true, DataType.Boolean);
- }
- return CreateResult(false, DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Information/IsNonText.cs b/EPPlus/FormulaParsing/Excel/Functions/Information/IsNonText.cs
deleted file mode 100644
index c84008d..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsNonText.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-15
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
-
-public class IsNonText : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var firstArg = arguments.ElementAt(0);
- if (firstArg.Value == null || firstArg.ValueIsExcelError) {
- return CreateResult(false, DataType.Boolean);
- }
- return CreateResult(!(firstArg.Value is string), DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Information/IsNumber.cs b/EPPlus/FormulaParsing/Excel/Functions/Information/IsNumber.cs
deleted file mode 100644
index eac8fdd..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsNumber.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
-
-public class IsNumber : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = GetFirstValue(arguments);
- return CreateResult(IsNumeric(arg), DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Information/IsOdd.cs b/EPPlus/FormulaParsing/Excel/Functions/Information/IsOdd.cs
deleted file mode 100644
index 1e1af7f..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsOdd.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-15
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
-
-public class IsOdd : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg1 = GetFirstValue(arguments); //arguments.ElementAt(0);
- if (!ConvertUtil.IsNumeric(arg1)) {
- ThrowExcelErrorValueException(eErrorType.Value);
- }
- var number = (int)System.Math.Floor(ConvertUtil.GetValueDouble(arg1));
- return CreateResult(number % 2 == 1, DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Information/IsText.cs b/EPPlus/FormulaParsing/Excel/Functions/Information/IsText.cs
deleted file mode 100644
index b2d288b..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsText.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
-
-public class IsText : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- if (arguments.Count() == 1 && arguments.ElementAt(0).Value != null) {
- return CreateResult((GetFirstValue(arguments) is string), DataType.Boolean);
- }
- return CreateResult(false, DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Information/N.cs b/EPPlus/FormulaParsing/Excel/Functions/Information/N.cs
deleted file mode 100644
index cf3d171..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/N.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
-
-public class N : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = GetFirstValue(arguments);
-
- if (arg is bool b) {
- var val = b ? 1d : 0d;
- return CreateResult(val, DataType.Decimal);
- }
- if (IsNumeric(arg)) {
- var val = ConvertUtil.GetValueDouble(arg);
- return CreateResult(val, DataType.Decimal);
- }
- if (arg is string) {
- return CreateResult(0d, DataType.Decimal);
- }
- if (arg is ExcelErrorValue) {
- return CreateResult(arg, DataType.ExcelError);
- }
- throw new ExcelErrorValueException(eErrorType.Value);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Information/Na.cs b/EPPlus/FormulaParsing/Excel/Functions/Information/Na.cs
deleted file mode 100644
index 93bfba2..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/Na.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
-
-public class Na : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- return CreateResult(ExcelErrorValue.Create(eErrorType.Na), DataType.ExcelError);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/IntArgumentParser.cs b/EPPlus/FormulaParsing/Excel/Functions/IntArgumentParser.cs
deleted file mode 100644
index 40a5d21..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/IntArgumentParser.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public class IntArgumentParser : ArgumentParser {
- public override object Parse(object obj) {
- Require.That(obj).Named("argument").IsNotNull();
- if (obj is ExcelDataProvider.IRangeInfo info) {
- var r = info.FirstOrDefault();
- return r == null ? 0 : Convert.ToInt32(r.ValueDouble);
- }
- var objType = obj.GetType();
- if (objType == typeof(int)) {
- return (int)obj;
- }
- if (objType == typeof(double) || objType == typeof(decimal)) {
- return Convert.ToInt32(obj);
- }
- if (!int.TryParse(obj.ToString(), out var result)) {
- throw new ExcelErrorValueException(ExcelErrorValue.Create(eErrorType.Value));
- }
- return result;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Logical/And.cs b/EPPlus/FormulaParsing/Excel/Functions/Logical/And.cs
deleted file mode 100644
index c483af5..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/And.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
-
-public class And : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- for (var x = 0; x < arguments.Count(); x++) {
- if (!ArgToBool(arguments, x)) {
- return new(false, DataType.Boolean);
- }
- }
- return new(true, DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Logical/False.cs b/EPPlus/FormulaParsing/Excel/Functions/Logical/False.cs
deleted file mode 100644
index 176d31a..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/False.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
-
-public class False : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- return CreateResult(false, DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Logical/If.cs b/EPPlus/FormulaParsing/Excel/Functions/Logical/If.cs
deleted file mode 100644
index bc55272..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/If.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
-
-public class If : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 3);
- var condition = ArgToBool(arguments, 0);
- var firstStatement = arguments.ElementAt(1).Value;
- var secondStatement = arguments.ElementAt(2).Value;
- var factory = new CompileResultFactory();
- return condition ? factory.Create(firstStatement) : factory.Create(secondStatement);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Logical/IfError.cs b/EPPlus/FormulaParsing/Excel/Functions/Logical/IfError.cs
deleted file mode 100644
index 8fe9993..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/IfError.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
-
-public class IfError : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var firstArg = arguments.First();
- return GetResultByObject(firstArg.Value);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Logical/IfNa.cs b/EPPlus/FormulaParsing/Excel/Functions/Logical/IfNa.cs
deleted file mode 100644
index ec74404..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/IfNa.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
-
-public class IfNa : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var firstArg = arguments.First();
- return GetResultByObject(firstArg.Value);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Logical/Not.cs b/EPPlus/FormulaParsing/Excel/Functions/Logical/Not.cs
deleted file mode 100644
index aec7f74..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/Not.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
-
-public class Not : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var result = !ArgToBool(arguments, 0);
- return new(result, DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Logical/Or.cs b/EPPlus/FormulaParsing/Excel/Functions/Logical/Or.cs
deleted file mode 100644
index bcf6e31..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/Or.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
-
-public class Or : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- for (var x = 0; x < arguments.Count(); x++) {
- if (ArgToBool(arguments, x)) {
- return new(true, DataType.Boolean);
- }
- }
- return new(false, DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Logical/True.cs b/EPPlus/FormulaParsing/Excel/Functions/Logical/True.cs
deleted file mode 100644
index bb23a62..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/True.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
-
-public class True : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- return CreateResult(true, DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Abs.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Abs.cs
deleted file mode 100644
index ad29a14..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Abs.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Abs : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var val = ArgToDecimal(arguments, 0);
- if (val < 0) {
- val *= -1;
- }
- return CreateResult(val, DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Acos.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Acos.cs
deleted file mode 100644
index 077a02e..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Acos.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-11
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Acos : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = ArgToDecimal(arguments, 0);
- return CreateResult(MathHelper.Arccos(arg), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Acosh.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Acosh.cs
deleted file mode 100644
index cf07e1b..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Acosh.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-11
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Acosh : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = ArgToDecimal(arguments, 0);
- return CreateResult(MathHelper.HArccos(arg), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Asin.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Asin.cs
deleted file mode 100644
index 288763c..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Asin.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-11
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Asin : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = ArgToDecimal(arguments, 0);
- return CreateResult(System.Math.Asin(arg), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Asinh.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Asinh.cs
deleted file mode 100644
index 80ebdfa..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Asinh.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-11
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Asinh : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = ArgToDecimal(arguments, 0);
- return CreateResult(MathHelper.HArcsin(arg), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Atan.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Atan.cs
deleted file mode 100644
index 9cc60b0..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Atan.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Atan : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = ArgToDecimal(arguments, 0);
- return CreateResult(System.Math.Atan(arg), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Atan2.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Atan2.cs
deleted file mode 100644
index a490c1d..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Atan2.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Atan2 : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var arg1 = ArgToDecimal(arguments, 0);
- var arg2 = ArgToDecimal(arguments, 1);
- // Had to switch order of the arguments to get the same result as in excel /MA
- return CreateResult(System.Math.Atan2(arg2, arg1), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Atanh.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Atanh.cs
deleted file mode 100644
index 302c97f..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Atanh.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-11
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Atanh : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = ArgToDecimal(arguments, 0);
- return CreateResult(MathHelper.HArctan(arg), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Average.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Average.cs
deleted file mode 100644
index b154d24..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Average.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Globalization;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Average : HiddenValuesHandlingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1, eErrorType.Div0);
- double nValues = 0d,
- result = 0d;
- foreach (var arg in arguments) {
- Calculate(arg, context, ref result, ref nValues);
- }
- return CreateResult(Divide(result, nValues), DataType.Decimal);
- }
-
- private void Calculate(
- FunctionArgument arg,
- ParsingContext context,
- ref double retVal,
- ref double nValues,
- bool isInArray = false) {
- if (ShouldIgnore(arg)) {
- return;
- }
- if (arg.Value is IEnumerable<FunctionArgument> value) {
- foreach (var item in value) {
- Calculate(item, context, ref retVal, ref nValues, true);
- }
- } else if (arg.IsExcelRange) {
- foreach (var c in arg.ValueAsRangeInfo) {
- if (ShouldIgnore(c, context)) {
- continue;
- }
- CheckForAndHandleExcelError(c);
- if (!IsNumeric(c.Value)) {
- continue;
- }
- nValues++;
- retVal += c.ValueDouble;
- }
- } else {
- var numericValue = GetNumericValue(arg.Value, isInArray);
- if (numericValue.HasValue) {
- nValues++;
- retVal += numericValue.Value;
- } else if ((arg.Value is string) && !ConvertUtil.IsNumericString(arg.Value)) {
- if (!isInArray) {
- ThrowExcelErrorValueException(eErrorType.Value);
- }
- }
- }
- CheckForAndHandleExcelError(arg);
- }
-
- private double? GetNumericValue(object obj, bool isInArray) {
- if (IsNumeric(obj)) {
- return ConvertUtil.GetValueDouble(obj);
- }
- if ((obj is bool) && !isInArray) {
- return ConvertUtil.GetValueDouble(obj);
- }
- if (ConvertUtil.IsNumericString(obj)) {
- return double.Parse(obj.ToString(), CultureInfo.InvariantCulture);
- }
- return default(double?);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/AverageA.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/AverageA.cs
deleted file mode 100644
index 5cbcdb0..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/AverageA.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2014-01-06
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Globalization;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class AverageA : HiddenValuesHandlingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1, eErrorType.Div0);
- double nValues = 0d,
- result = 0d;
- foreach (var arg in arguments) {
- Calculate(arg, context, ref result, ref nValues);
- }
- return CreateResult(Divide(result, nValues), DataType.Decimal);
- }
-
- private void Calculate(
- FunctionArgument arg,
- ParsingContext context,
- ref double retVal,
- ref double nValues,
- bool isInArray = false) {
- if (ShouldIgnore(arg)) {
- return;
- }
- if (arg.Value is IEnumerable<FunctionArgument> value) {
- foreach (var item in value) {
- Calculate(item, context, ref retVal, ref nValues, true);
- }
- } else if (arg.IsExcelRange) {
- foreach (var c in arg.ValueAsRangeInfo) {
- if (ShouldIgnore(c, context)) {
- continue;
- }
- CheckForAndHandleExcelError(c);
- if (IsNumeric(c.Value)) {
- nValues++;
- retVal += c.ValueDouble;
- } else if (c.Value is bool cValue) {
- nValues++;
- retVal += cValue ? 1 : 0;
- } else if (c.Value is string) {
- nValues++;
- }
- }
- } else {
- var numericValue = GetNumericValue(arg.Value, isInArray);
- if (numericValue.HasValue) {
- nValues++;
- retVal += numericValue.Value;
- } else if ((arg.Value is string) && !ConvertUtil.IsNumericString(arg.Value)) {
- if (isInArray) {
- nValues++;
- } else {
- ThrowExcelErrorValueException(eErrorType.Value);
- }
- }
- }
- CheckForAndHandleExcelError(arg);
- }
-
- private double? GetNumericValue(object obj, bool isInArray) {
- if (IsNumeric(obj)) {
- return ConvertUtil.GetValueDouble(obj);
- }
- if (obj is bool) {
- if (isInArray) {
- return default(double?);
- }
- return ConvertUtil.GetValueDouble(obj);
- }
- if (ConvertUtil.IsNumericString(obj)) {
- return double.Parse(obj.ToString(), CultureInfo.InvariantCulture);
- }
- return default(double?);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/AverageIf.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/AverageIf.cs
deleted file mode 100644
index 5568a25..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/AverageIf.cs
+++ /dev/null
@@ -1,128 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.Utilities;
-using OfficeOpenXml.Utils;
-using Require = OfficeOpenXml.FormulaParsing.Utilities.Require;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class AverageIf : HiddenValuesHandlingFunction {
- private readonly NumericExpressionEvaluator _numericExpressionEvaluator;
- private readonly WildCardValueMatcher _wildCardValueMatcher;
-
- public AverageIf()
- : this(new(), new()) {}
-
- public AverageIf(
- NumericExpressionEvaluator evaluator,
- WildCardValueMatcher wildCardValueMatcher) {
- Require.That(evaluator).Named("evaluator").IsNotNull();
- Require.That(evaluator).Named("wildCardValueMatcher").IsNotNull();
- _numericExpressionEvaluator = evaluator;
- _wildCardValueMatcher = wildCardValueMatcher;
- }
-
- private bool Evaluate(object obj, string expression) {
- double? candidate = default(double?);
- if (IsNumeric(obj)) {
- candidate = ConvertUtil.GetValueDouble(obj);
- }
- if (candidate.HasValue) {
- return _numericExpressionEvaluator.Evaluate(candidate.Value, expression);
- }
- if (obj == null) {
- return false;
- }
- return _wildCardValueMatcher.IsMatch(expression, obj.ToString()) == 0;
- }
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var firstArg = arguments.ElementAt(0);
- var args = firstArg.Value as IEnumerable<FunctionArgument>;
- if (args == null && firstArg.IsExcelRange) {
- args = new List<FunctionArgument> { firstArg };
- }
- var criteria = arguments.ElementAt(1).Value;
- ThrowExcelErrorValueExceptionIf(
- () => criteria == null || criteria.ToString().Length > 255,
- eErrorType.Value);
- double retVal;
- if (arguments.Count() > 2) {
- var secondArg = arguments.ElementAt(2);
- var lookupRange = secondArg.Value as IEnumerable<FunctionArgument>;
- if (lookupRange == null && secondArg.IsExcelRange) {
- lookupRange = new List<FunctionArgument> { secondArg };
- }
- retVal = CalculateWithLookupRange(args, criteria.ToString(), lookupRange, context);
- } else {
- retVal = CalculateSingleRange(args, criteria.ToString(), context);
- }
- return CreateResult(retVal, DataType.Decimal);
- }
-
- private double CalculateWithLookupRange(
- IEnumerable<FunctionArgument> range,
- string criteria,
- IEnumerable<FunctionArgument> sumRange,
- ParsingContext context) {
- var retVal = 0d;
- var nMatches = 0;
- var flattenedRange = ArgsToObjectEnumerable(false, range, context);
- var flattenedSumRange = ArgsToDoubleEnumerable(sumRange, context);
- for (var x = 0; x < flattenedRange.Count(); x++) {
- var candidate = flattenedSumRange.ElementAt(x);
- if (Evaluate(flattenedRange.ElementAt(x), criteria)) {
- nMatches++;
- retVal += candidate;
- }
- }
- return Divide(retVal, nMatches);
- }
-
- private double CalculateSingleRange(
- IEnumerable<FunctionArgument> args,
- string expression,
- ParsingContext context) {
- var retVal = 0d;
- var nMatches = 0;
- var flattendedRange = ArgsToDoubleEnumerable(args, context);
- var candidates = flattendedRange as double[] ?? flattendedRange.ToArray();
- foreach (var candidate in candidates) {
- if (Evaluate(candidate, expression)) {
- retVal += candidate;
- nMatches++;
- }
- }
- return Divide(retVal, nMatches);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/AverageIfs.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/AverageIfs.cs
deleted file mode 100644
index a24266c..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/AverageIfs.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-02-01
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class AverageIfs : MultipleRangeCriteriasFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
- ValidateArguments(functionArguments, 3);
- var sumRange = ArgsToDoubleEnumerable(
- true,
- new List<FunctionArgument> { functionArguments[0] },
- context)
- .ToList();
- var argRanges = new List<ExcelDataProvider.IRangeInfo>();
- var criterias = new List<object>();
- for (var ix = 1; ix < 31; ix += 2) {
- if (functionArguments.Length <= ix) {
- break;
- }
- var rangeInfo = functionArguments[ix].ValueAsRangeInfo;
- argRanges.Add(rangeInfo);
- if (ix > 1) {
- ThrowExcelErrorValueExceptionIf(
- () => rangeInfo.GetNCells() != argRanges[0].GetNCells(),
- eErrorType.Value);
- }
- criterias.Add(functionArguments[ix + 1].Value);
- }
- IEnumerable<int> matchIndexes = GetMatchIndexes(argRanges[0], criterias[0]);
- var enumerable = matchIndexes as IList<int> ?? matchIndexes.ToList();
- for (var ix = 1; ix < argRanges.Count && enumerable.Any(); ix++) {
- var indexes = GetMatchIndexes(argRanges[ix], criterias[ix]);
- matchIndexes = enumerable.Intersect(indexes);
- }
-
- var result = matchIndexes.Average(index => sumRange[index]);
-
- return CreateResult(result, DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Ceiling.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Ceiling.cs
deleted file mode 100644
index 2140891..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Ceiling.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Ceiling : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var number = ArgToDecimal(arguments, 0);
- var significance = ArgToDecimal(arguments, 1);
- ValidateNumberAndSign(number, significance);
- if (significance < 1 && significance > 0) {
- var floor = System.Math.Floor(number);
- var rest = number - floor;
- var nSign = (int)(rest / significance) + 1;
- return CreateResult(floor + (nSign * significance), DataType.Decimal);
- }
- if (significance == 1) {
- return CreateResult(System.Math.Ceiling(number), DataType.Decimal);
- }
- var result = number - (number % significance) + significance;
- return CreateResult(result, DataType.Decimal);
- }
-
- private void ValidateNumberAndSign(double number, double sign) {
- if (number > 0d && sign < 0) {
- var values = string.Format("num: {0}, sign: {1}", number, sign);
- throw new InvalidOperationException(
- "Ceiling cannot handle a negative significance when the number is positive" + values);
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Cos.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Cos.cs
deleted file mode 100644
index a605707..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Cos.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Cos : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = ArgToDecimal(arguments, 0);
- return CreateResult(System.Math.Cos(arg), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Cosh.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Cosh.cs
deleted file mode 100644
index bb15381..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Cosh.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Cosh : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = ArgToDecimal(arguments, 0);
- return CreateResult(System.Math.Cosh(arg), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Count.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Count.cs
deleted file mode 100644
index c5c42da..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Count.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Count : HiddenValuesHandlingFunction {
- private enum ItemContext {
- InRange,
- InArray,
- SingleArg,
- }
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var nItems = 0d;
- Calculate(arguments, ref nItems, context, ItemContext.SingleArg);
- return CreateResult(nItems, DataType.Integer);
- }
-
- private void Calculate(
- IEnumerable<FunctionArgument> items,
- ref double nItems,
- ParsingContext context,
- ItemContext itemContext) {
- foreach (var item in items) {
- var cs = item.Value as ExcelDataProvider.IRangeInfo;
- if (cs != null) {
- foreach (var c in cs) {
- _CheckForAndHandleExcelError(c, context);
- if (ShouldIgnore(c, context) == false && ShouldCount(c.Value, ItemContext.InRange)) {
- nItems++;
- }
- }
- } else {
- var value = item.Value as IEnumerable<FunctionArgument>;
- if (value != null) {
- Calculate(value, ref nItems, context, ItemContext.InArray);
- } else {
- _CheckForAndHandleExcelError(item, context);
- if (ShouldIgnore(item) == false && ShouldCount(item.Value, itemContext)) {
- nItems++;
- }
- }
- }
- }
- }
-
- private void _CheckForAndHandleExcelError(FunctionArgument arg, ParsingContext context) {
- //if (context.Scopes.Current.IsSubtotal)
- //{
- // CheckForAndHandleExcelError(arg);
- //}
- }
-
- private void _CheckForAndHandleExcelError(
- ExcelDataProvider.ICellInfo cell,
- ParsingContext context) {
- //if (context.Scopes.Current.IsSubtotal)
- //{
- // CheckForAndHandleExcelError(cell);
- //}
- }
-
- private bool ShouldCount(object value, ItemContext context) {
- switch (context) {
- case ItemContext.SingleArg:
- return IsNumeric(value) || IsNumericString(value);
- case ItemContext.InRange:
- return IsNumeric(value);
- case ItemContext.InArray:
- return IsNumeric(value) || IsNumericString(value);
- default:
- throw new ArgumentException("Unknown ItemContext:" + context);
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/CountA.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/CountA.cs
deleted file mode 100644
index a9e3b52..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/CountA.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class CountA : HiddenValuesHandlingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var nItems = 0d;
- Calculate(arguments, context, ref nItems);
- return CreateResult(nItems, DataType.Integer);
- }
-
- private void Calculate(
- IEnumerable<FunctionArgument> items,
- ParsingContext context,
- ref double nItems) {
- foreach (var item in items) {
- var cs = item.Value as ExcelDataProvider.IRangeInfo;
- if (cs != null) {
- foreach (var c in cs) {
- _CheckForAndHandleExcelError(c, context);
- if (!ShouldIgnore(c, context) && ShouldCount(c.Value)) {
- nItems++;
- }
- }
- } else if (item.Value is IEnumerable<FunctionArgument> value) {
- Calculate(value, context, ref nItems);
- } else {
- _CheckForAndHandleExcelError(item, context);
- if (!ShouldIgnore(item) && ShouldCount(item.Value)) {
- nItems++;
- }
- }
- }
- }
-
- private void _CheckForAndHandleExcelError(FunctionArgument arg, ParsingContext context) {
- if (context.Scopes.Current.IsSubtotal) {
- CheckForAndHandleExcelError(arg);
- }
- }
-
- private void _CheckForAndHandleExcelError(
- ExcelDataProvider.ICellInfo cell,
- ParsingContext context) {
- if (context.Scopes.Current.IsSubtotal) {
- CheckForAndHandleExcelError(cell);
- }
- }
-
- private bool ShouldCount(object value) {
- if (value == null) {
- return false;
- }
- return (!string.IsNullOrEmpty(value.ToString()));
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/CountBlank.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/CountBlank.cs
deleted file mode 100644
index 23176ae..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/CountBlank.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class CountBlank : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = arguments.First();
- if (!arg.IsExcelRange) {
- throw new InvalidOperationException("CountBlank only support ranges as arguments");
- }
- var result = arg.ValueAsRangeInfo.GetNCells();
- foreach (var cell in arg.ValueAsRangeInfo) {
- if (!(cell.Value == null || cell.Value == string.Empty)) {
- result--;
- }
- }
- return CreateResult(result, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/CountIf.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/CountIf.cs
deleted file mode 100644
index 277058c..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/CountIf.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.Utilities;
-using OfficeOpenXml.Utils;
-using Require = OfficeOpenXml.FormulaParsing.Utilities.Require;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class CountIf : ExcelFunction {
- private readonly NumericExpressionEvaluator _numericExpressionEvaluator;
- private readonly WildCardValueMatcher _wildCardValueMatcher;
-
- public CountIf()
- : this(new(), new()) {}
-
- public CountIf(NumericExpressionEvaluator evaluator, WildCardValueMatcher wildCardValueMatcher) {
- Require.That(evaluator).Named("evaluator").IsNotNull();
- Require.That(wildCardValueMatcher).Named("wildCardValueMatcher").IsNotNull();
- _numericExpressionEvaluator = evaluator;
- _wildCardValueMatcher = wildCardValueMatcher;
- }
-
- private bool Evaluate(object obj, string expression) {
- double? candidate = default(double?);
- if (IsNumeric(obj)) {
- candidate = ConvertUtil.GetValueDouble(obj);
- }
- if (candidate.HasValue) {
- return _numericExpressionEvaluator.Evaluate(candidate.Value, expression);
- }
- if (obj == null) {
- return false;
- }
- return _wildCardValueMatcher.IsMatch(expression, obj.ToString()) == 0;
- }
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
- ValidateArguments(functionArguments, 2);
- var range = functionArguments.ElementAt(0);
- var criteria = ArgToString(functionArguments, 1);
- double result = 0d;
- if (range.IsExcelRange) {
- foreach (var cell in range.ValueAsRangeInfo) {
- if (Evaluate(cell.Value, criteria)) {
- result++;
- }
- }
- } else if (range.Value is IEnumerable<FunctionArgument> value) {
- foreach (var arg in value) {
- if (Evaluate(arg.Value, criteria)) {
- result++;
- }
- }
- } else {
- if (Evaluate(range.Value, criteria)) {
- result++;
- }
- }
- return CreateResult(result, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/CountIfs.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/CountIfs.cs
deleted file mode 100644
index e4b7418..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/CountIfs.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-11
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class CountIfs : MultipleRangeCriteriasFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
- ValidateArguments(functionArguments, 2);
- var argRanges = new List<ExcelDataProvider.IRangeInfo>();
- var criterias = new List<object>();
- for (var ix = 0; ix < 30; ix += 2) {
- if (functionArguments.Length <= ix) {
- break;
- }
- var rangeInfo = functionArguments[ix].ValueAsRangeInfo;
- argRanges.Add(rangeInfo);
- if (ix > 0) {
- ThrowExcelErrorValueExceptionIf(
- () => rangeInfo.GetNCells() != argRanges[0].GetNCells(),
- eErrorType.Value);
- }
- criterias.Add(functionArguments[ix + 1].Value);
- }
- IEnumerable<int> matchIndexes = GetMatchIndexes(argRanges[0], criterias[0]);
- var enumerable = matchIndexes as IList<int> ?? matchIndexes.ToList();
- for (var ix = 1; ix < argRanges.Count && enumerable.Any(); ix++) {
- var indexes = GetMatchIndexes(argRanges[ix], criterias[ix]);
- matchIndexes = enumerable.Intersect(indexes);
- }
-
- return CreateResult((double)matchIndexes.Count(), DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Degrees.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Degrees.cs
deleted file mode 100644
index 7faae97..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Degrees.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Degrees : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var angle = ArgToDecimal(arguments, 0);
- var result = (angle * 180) / System.Math.PI;
- return CreateResult(result, DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Exp.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Exp.cs
deleted file mode 100644
index de88305..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Exp.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Exp : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var number = ArgToDecimal(arguments, 0);
- return CreateResult(System.Math.Exp(number), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Fact.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Fact.cs
deleted file mode 100644
index 2bb24f5..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Fact.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Fact : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var number = ArgToDecimal(arguments, 0);
- ThrowExcelErrorValueExceptionIf(() => number < 0, eErrorType.Na);
- var result = 1d;
- for (var x = 1; x < number; x++) {
- result *= x;
- }
- return CreateResult(result, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Floor.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Floor.cs
deleted file mode 100644
index caa43c5..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Floor.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Floor : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var number = ArgToDecimal(arguments, 0);
- var significance = ArgToDecimal(arguments, 1);
- ValidateNumberAndSign(number, significance);
- if (significance < 1 && significance > 0) {
- var floor = System.Math.Floor(number);
- var rest = number - floor;
- var nSign = (int)(rest / significance);
- return CreateResult(floor + (nSign * significance), DataType.Decimal);
- }
- if (significance == 1) {
- return CreateResult(System.Math.Floor(number), DataType.Decimal);
- }
- double result;
- if (number > 1) {
- result = number - (number % significance) + significance;
- } else {
- result = number - (number % significance);
- }
- return CreateResult(result, DataType.Decimal);
- }
-
- private void ValidateNumberAndSign(double number, double sign) {
- if (number > 0d && sign < 0) {
- var values = string.Format("num: {0}, sign: {1}", number, sign);
- throw new InvalidOperationException(
- "Floor cannot handle a negative significance when the number is positive" + values);
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Large.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Large.cs
deleted file mode 100644
index 025c47f..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Large.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Large : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var args = arguments.ElementAt(0);
- var index = ArgToInt(arguments, 1) - 1;
- var values = ArgsToDoubleEnumerable(new List<FunctionArgument> { args }, context);
- ThrowExcelErrorValueExceptionIf(() => index < 0 || index >= values.Count(), eErrorType.Num);
- var result = values.OrderByDescending(x => x).ElementAt(index);
- return CreateResult(result, DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Ln.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Ln.cs
deleted file mode 100644
index e93147f..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Ln.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Ln : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = ArgToDecimal(arguments, 0);
- return CreateResult(System.Math.Log(arg, System.Math.E), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Log.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Log.cs
deleted file mode 100644
index c348ecf..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Log.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Log : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var number = ArgToDecimal(arguments, 0);
- if (arguments.Count() == 1) {
- return CreateResult(System.Math.Log(number, 10d), DataType.Decimal);
- }
- var newBase = ArgToDecimal(arguments, 1);
- return CreateResult(System.Math.Log(number, newBase), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Log10.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Log10.cs
deleted file mode 100644
index c9f9431..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Log10.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Log10 : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var number = ArgToDecimal(arguments, 0);
- return CreateResult(System.Math.Log10(number), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/MathHelper.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/MathHelper.cs
deleted file mode 100644
index 6b9163a..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/MathHelper.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-11
- *******************************************************************************/
-
-using MathObj = System.Math;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-/// <summary>
-/// Thanks to the guys in this thread: http://stackoverflow.com/questions/2840798/c-sharp-math-class-question
-/// </summary>
-public static class MathHelper {
- // Secant
- public static double Sec(double x) {
- return 1 / MathObj.Cos(x);
- }
-
- // Cosecant
- public static double Cosec(double x) {
- return 1 / MathObj.Sin(x);
- }
-
- // Cotangent
- public static double Cotan(double x) {
- return 1 / MathObj.Tan(x);
- }
-
- // Inverse Sine
- public static double Arcsin(double x) {
- return MathObj.Atan(x / MathObj.Sqrt(-x * x + 1));
- }
-
- // Inverse Cosine
- public static double Arccos(double x) {
- return MathObj.Atan(-x / MathObj.Sqrt(-x * x + 1)) + 2 * MathObj.Atan(1);
- }
-
- // Inverse Secant
- public static double Arcsec(double x) {
- return 2 * MathObj.Atan(1) - MathObj.Atan(MathObj.Sign(x) / MathObj.Sqrt(x * x - 1));
- }
-
- // Inverse Cosecant
- public static double Arccosec(double x) {
- return MathObj.Atan(MathObj.Sign(x) / MathObj.Sqrt(x * x - 1));
- }
-
- // Inverse Cotangent
- public static double Arccotan(double x) {
- return 2 * MathObj.Atan(1) - MathObj.Atan(x);
- }
-
- // Hyperbolic Sine
- public static double HSin(double x) {
- return (MathObj.Exp(x) - MathObj.Exp(-x)) / 2;
- }
-
- // Hyperbolic Cosine
- public static double HCos(double x) {
- return (MathObj.Exp(x) + MathObj.Exp(-x)) / 2;
- }
-
- // Hyperbolic Tangent
- public static double HTan(double x) {
- return (MathObj.Exp(x) - MathObj.Exp(-x)) / (MathObj.Exp(x) + MathObj.Exp(-x));
- }
-
- // Hyperbolic Secant
- public static double HSec(double x) {
- return 2 / (MathObj.Exp(x) + MathObj.Exp(-x));
- }
-
- // Hyperbolic Cosecant
- public static double HCosec(double x) {
- return 2 / (MathObj.Exp(x) - MathObj.Exp(-x));
- }
-
- // Hyperbolic Cotangent
- public static double HCotan(double x) {
- return (MathObj.Exp(x) + MathObj.Exp(-x)) / (MathObj.Exp(x) - MathObj.Exp(-x));
- }
-
- // Inverse Hyperbolic Sine
- public static double HArcsin(double x) {
- return MathObj.Log(x + MathObj.Sqrt(x * x + 1));
- }
-
- // Inverse Hyperbolic Cosine
- public static double HArccos(double x) {
- return MathObj.Log(x + MathObj.Sqrt(x * x - 1));
- }
-
- // Inverse Hyperbolic Tangent
- public static double HArctan(double x) {
- return MathObj.Log((1 + x) / (1 - x)) / 2;
- }
-
- // Inverse Hyperbolic Secant
- public static double HArcsec(double x) {
- return MathObj.Log((MathObj.Sqrt(-x * x + 1) + 1) / x);
- }
-
- // Inverse Hyperbolic Cosecant
- public static double HArccosec(double x) {
- return MathObj.Log((MathObj.Sign(x) * MathObj.Sqrt(x * x + 1) + 1) / x);
- }
-
- // Inverse Hyperbolic Cotangent
- public static double HArccotan(double x) {
- return MathObj.Log((x + 1) / (x - 1)) / 2;
- }
-
- // Logarithm to base N
- public static double LogN(double x, double n) {
- return MathObj.Log(x) / MathObj.Log(n);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Max.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Max.cs
deleted file mode 100644
index c6ddf8f..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Max.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Max : HiddenValuesHandlingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var values = ArgsToDoubleEnumerable(IgnoreHiddenValues, false, arguments, context);
- return CreateResult(values.Max(), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Maxa.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Maxa.cs
deleted file mode 100644
index 1ef491a..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Maxa.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Maxa : ExcelFunction {
- private readonly DoubleEnumerableArgConverter _argConverter;
-
- public Maxa()
- : this(new()) {}
-
- public Maxa(DoubleEnumerableArgConverter argConverter) {
- Require.That(argConverter).Named("argConverter").IsNotNull();
- _argConverter = argConverter;
- }
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var values = _argConverter.ConvertArgsIncludingOtherTypes(arguments);
- return CreateResult(values.Max(), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Median.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Median.cs
deleted file mode 100644
index 6edc020..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Median.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-10
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Median : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var nums = ArgsToDoubleEnumerable(arguments, context);
- var arr = nums.ToArray();
- Array.Sort(arr);
- ThrowExcelErrorValueExceptionIf(() => arr.Length == 0, eErrorType.Num);
- double result;
- if (arr.Length % 2 == 1) {
- result = arr[arr.Length / 2];
- } else {
- var startIndex = arr.Length / 2 - 1;
- result = (arr[startIndex] + arr[startIndex + 1]) / 2d;
- }
- return CreateResult(result, DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Min.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Min.cs
deleted file mode 100644
index f2b5fdf..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Min.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Min : HiddenValuesHandlingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var values = ArgsToDoubleEnumerable(IgnoreHiddenValues, false, arguments, context);
- return CreateResult(values.Min(), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Mina.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Mina.cs
deleted file mode 100644
index a93424f..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Mina.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Mina : ExcelFunction {
- private readonly DoubleEnumerableArgConverter _argConverter;
-
- public Mina()
- : this(new()) {}
-
- public Mina(DoubleEnumerableArgConverter argConverter) {
- Require.That(argConverter).Named("argConverter").IsNotNull();
- _argConverter = argConverter;
- }
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var values = _argConverter.ConvertArgsIncludingOtherTypes(arguments);
- return CreateResult(values.Min(), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Mod.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Mod.cs
deleted file mode 100644
index 968e1c8..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Mod.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Mod : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var n1 = ArgToDecimal(arguments, 0);
- var n2 = ArgToDecimal(arguments, 1);
- return new(n1 % n2, DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/MultipleRangeCriteriasFunction.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/MultipleRangeCriteriasFunction.cs
deleted file mode 100644
index 5efe6f0..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/MultipleRangeCriteriasFunction.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-15
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.Utilities;
-using OfficeOpenXml.Utils;
-using Require = OfficeOpenXml.FormulaParsing.Utilities.Require;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public abstract class MultipleRangeCriteriasFunction : ExcelFunction {
- private readonly NumericExpressionEvaluator _numericExpressionEvaluator;
- private readonly WildCardValueMatcher _wildCardValueMatcher;
-
- protected MultipleRangeCriteriasFunction()
- : this(new(), new()) {}
-
- protected MultipleRangeCriteriasFunction(
- NumericExpressionEvaluator evaluator,
- WildCardValueMatcher wildCardValueMatcher) {
- Require.That(evaluator).Named("evaluator").IsNotNull();
- Require.That(wildCardValueMatcher).Named("wildCardValueMatcher").IsNotNull();
- _numericExpressionEvaluator = evaluator;
- _wildCardValueMatcher = wildCardValueMatcher;
- }
-
- protected bool Evaluate(object obj, object expression) {
- double? candidate = default(double?);
- if (IsNumeric(obj)) {
- candidate = ConvertUtil.GetValueDouble(obj);
- }
- if (candidate.HasValue && expression is string) {
- return _numericExpressionEvaluator.Evaluate(candidate.Value, expression.ToString());
- }
- if (obj == null) {
- return false;
- }
- return _wildCardValueMatcher.IsMatch(expression, obj.ToString()) == 0;
- }
-
- protected List<int> GetMatchIndexes(ExcelDataProvider.IRangeInfo rangeInfo, object searched) {
- var result = new List<int>();
- var internalIndex = 0;
- for (var row = rangeInfo.Address._fromRow; row <= rangeInfo.Address._toRow; row++) {
- for (var col = rangeInfo.Address._fromCol; col <= rangeInfo.Address._toCol; col++) {
- var candidate = rangeInfo.GetValue(row, col);
- if (Evaluate(candidate, searched)) {
- result.Add(internalIndex);
- }
- internalIndex++;
- }
- }
- return result;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Pi.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Pi.cs
deleted file mode 100644
index c606b48..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Pi.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Pi : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var result = System.Math.Round(System.Math.PI, 14);
- return CreateResult(result, DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Power.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Power.cs
deleted file mode 100644
index f0fd0a6..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Power.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Power : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var number = ArgToDecimal(arguments, 0);
- var power = ArgToDecimal(arguments, 1);
- var result = System.Math.Pow(number, power);
- return CreateResult(result, DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Product.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Product.cs
deleted file mode 100644
index 5414558..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Product.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Product : HiddenValuesHandlingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var result = 0d;
- var index = 0;
- while (AreEqual(result, 0d) && index < arguments.Count()) {
- result = CalculateFirstItem(arguments, index++, context);
- }
- result = CalculateCollection(
- arguments.Skip(index),
- result,
- (arg, current) => {
- if (ShouldIgnore(arg)) {
- return current;
- }
- if (arg.ValueIsExcelError) {
- ThrowExcelErrorValueException(arg.ValueAsExcelErrorValue.Type);
- }
- if (arg.IsExcelRange) {
- foreach (var cell in arg.ValueAsRangeInfo) {
- if (ShouldIgnore(cell, context)) {
- return current;
- }
- current *= cell.ValueDouble;
- }
- return current;
- }
- var obj = arg.Value;
- if (obj != null && IsNumeric(obj)) {
- var val = Convert.ToDouble(obj);
- current *= val;
- }
- return current;
- });
- return CreateResult(result, DataType.Decimal);
- }
-
- private double CalculateFirstItem(
- IEnumerable<FunctionArgument> arguments,
- int index,
- ParsingContext context) {
- var element = arguments.ElementAt(index);
- var argList = new List<FunctionArgument> { element };
- var valueList = ArgsToDoubleEnumerable(false, false, argList, context);
- var result = 0d;
- foreach (var value in valueList) {
- if (result == 0d && value > 0d) {
- result = value;
- } else {
- result *= value;
- }
- }
- return result;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Quotient.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Quotient.cs
deleted file mode 100644
index 866ddd9..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Quotient.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Quotient : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var num = ArgToDecimal(arguments, 0);
- var denom = ArgToDecimal(arguments, 1);
- ThrowExcelErrorValueExceptionIf(() => (int)denom == 0, eErrorType.Div0);
- var result = (int)(num / denom);
- return CreateResult(result, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Rand.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Rand.cs
deleted file mode 100644
index 9beb787..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Rand.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Rand : ExcelFunction {
- private static int Seed { get; set; }
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- Seed = Seed > 50 ? 0 : Seed + 5;
- var val = new Random(System.DateTime.Now.Millisecond + Seed).NextDouble();
- return CreateResult(val, DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/RandBetween.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/RandBetween.cs
deleted file mode 100644
index 5bb9e8a..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/RandBetween.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class RandBetween : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var low = ArgToDecimal(arguments, 0);
- var high = ArgToDecimal(arguments, 1);
- var rand = new Rand().Execute(new FunctionArgument[0], context).Result;
- var randPart = (CalulateDiff(high, low) * (double)rand) + 1;
- randPart = System.Math.Floor(randPart);
- return CreateResult(low + randPart, DataType.Integer);
- }
-
- private double CalulateDiff(double high, double low) {
- if (high > 0 && low < 0) {
- return high + low * -1;
- }
- if (high < 0 && low < 0) {
- return high * -1 - low * -1;
- }
- return high - low;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Round.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Round.cs
deleted file mode 100644
index 1bda92d..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Round.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Round : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var number = ArgToDecimal(arguments, 0);
- var nDigits = ArgToInt(arguments, 1);
- if (nDigits < 0) {
- nDigits *= -1;
- return CreateResult(number - (number % (System.Math.Pow(10, nDigits))), DataType.Integer);
- }
- return CreateResult(System.Math.Round(number, nDigits), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Rounddown.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Rounddown.cs
deleted file mode 100644
index 396c355..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Rounddown.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2014-01-06
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Rounddown : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var number = ArgToDecimal(arguments, 0);
- var nDecimals = ArgToInt(arguments, 1);
-
- var nFactor = number < 0 ? -1 : 1;
- number *= nFactor;
-
- double result;
- if (nDecimals > 0) {
- result = RoundDownDecimalNumber(number, nDecimals);
- } else {
- result = (int)System.Math.Floor(number);
- result = result - (result % System.Math.Pow(10, (nDecimals * -1)));
- }
- return CreateResult(result * nFactor, DataType.Decimal);
- }
-
- private static double RoundDownDecimalNumber(double number, int nDecimals) {
- var integerPart = System.Math.Floor(number);
- var decimalPart = number - integerPart;
- decimalPart = System.Math.Pow(10d, nDecimals) * decimalPart;
- decimalPart = System.Math.Truncate(decimalPart) / System.Math.Pow(10d, nDecimals);
- var result = integerPart + decimalPart;
- return result;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Roundup.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Roundup.cs
deleted file mode 100644
index d411ce6..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Roundup.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2014-01-06
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Roundup : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var number = ArgToDecimal(arguments, 0);
- var nDigits = ArgToInt(arguments, 1);
- double result =
- (number >= 0)
- ? System.Math.Ceiling(number * System.Math.Pow(10, nDigits))
- / System.Math.Pow(10, nDigits)
- : System.Math.Floor(number * System.Math.Pow(10, nDigits))
- / System.Math.Pow(10, nDigits);
- return CreateResult(result, DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Sign.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Sign.cs
deleted file mode 100644
index e09a919..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Sign.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Sign : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var result = 0d;
- var val = ArgToDecimal(arguments, 0);
- if (val < 0) {
- result = -1;
- } else if (val > 0) {
- result = 1;
- }
- return CreateResult(result, DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Sin.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Sin.cs
deleted file mode 100644
index 5b55efa..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Sin.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Sin : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = ArgToDecimal(arguments, 0);
- return CreateResult(System.Math.Sin(arg), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Sinh.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Sinh.cs
deleted file mode 100644
index 5cf3d88..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Sinh.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Sinh : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = ArgToDecimal(arguments, 0);
- return CreateResult(System.Math.Sinh(arg), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Small.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Small.cs
deleted file mode 100644
index f22e9fa..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Small.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Small : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var args = arguments.ElementAt(0);
- var index = ArgToInt(arguments, 1) - 1;
- var values = ArgsToDoubleEnumerable(new List<FunctionArgument> { args }, context);
- ThrowExcelErrorValueExceptionIf(() => index < 0 || index >= values.Count(), eErrorType.Num);
- var result = values.OrderBy(x => x).ElementAt(index);
- return CreateResult(result, DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Sqrt.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Sqrt.cs
deleted file mode 100644
index 61dff82..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Sqrt.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Sqrt : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = ArgToDecimal(arguments, 0);
- var result = System.Math.Sqrt(arg);
- return CreateResult(result, DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/SqrtPi.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/SqrtPi.cs
deleted file mode 100644
index cea3e32..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/SqrtPi.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class SqrtPi : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var number = ArgToDecimal(arguments, 0);
- return CreateResult(System.Math.Sqrt(number * System.Math.PI), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Stdev.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Stdev.cs
deleted file mode 100644
index 62831fb..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Stdev.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using MathObj = System.Math;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Stdev : HiddenValuesHandlingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var values = ArgsToDoubleEnumerable(arguments, context, false);
- return CreateResult(StandardDeviation(values), DataType.Decimal);
- }
-
- private double StandardDeviation(IEnumerable<double> values) {
- double ret = 0;
- if (values.Any()) {
- var nValues = values.Count();
- if (nValues == 1) {
- throw new ExcelErrorValueException(eErrorType.Div0);
- }
- //Compute the Average
- double avg = values.Average();
- //Perform the Sum of (value-avg)_2_2
- double sum = values.Sum(d => MathObj.Pow(d - avg, 2));
- //Put it all together
- ret = MathObj.Sqrt(Divide(sum, (values.Count() - 1)));
- }
- return ret;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/StdevP.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/StdevP.cs
deleted file mode 100644
index 16e7b7a..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/StdevP.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using MathObj = System.Math;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class StdevP : HiddenValuesHandlingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var args = ArgsToDoubleEnumerable(IgnoreHiddenValues, false, arguments, context);
- return CreateResult(StandardDeviation(args), DataType.Decimal);
- }
-
- private static double StandardDeviation(IEnumerable<double> values) {
- double avg = values.Average();
- return MathObj.Sqrt(values.Average(v => MathObj.Pow(v - avg, 2)));
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Subtotal.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Subtotal.cs
deleted file mode 100644
index 17d8586..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Subtotal.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Subtotal : ExcelFunction {
- private readonly Dictionary<int, HiddenValuesHandlingFunction> _functions = new();
-
- public Subtotal() {
- Initialize();
- }
-
- private void Initialize() {
- _functions[1] = new Average();
- _functions[2] = new Count();
- _functions[3] = new CountA();
- _functions[4] = new Max();
- _functions[5] = new Min();
- _functions[6] = new Product();
- _functions[7] = new Stdev();
- _functions[8] = new StdevP();
- _functions[9] = new Sum();
- _functions[10] = new Var();
- _functions[11] = new VarP();
-
- AddHiddenValueHandlingFunction(new Average(), 101);
- AddHiddenValueHandlingFunction(new Count(), 102);
- AddHiddenValueHandlingFunction(new CountA(), 103);
- AddHiddenValueHandlingFunction(new Max(), 104);
- AddHiddenValueHandlingFunction(new Min(), 105);
- AddHiddenValueHandlingFunction(new Product(), 106);
- AddHiddenValueHandlingFunction(new Stdev(), 107);
- AddHiddenValueHandlingFunction(new StdevP(), 108);
- AddHiddenValueHandlingFunction(new Sum(), 109);
- AddHiddenValueHandlingFunction(new Var(), 110);
- AddHiddenValueHandlingFunction(new VarP(), 111);
- }
-
- private void AddHiddenValueHandlingFunction(HiddenValuesHandlingFunction func, int funcNum) {
- func.IgnoreHiddenValues = true;
- _functions[funcNum] = func;
- }
-
- public override void BeforeInvoke(ParsingContext context) {
- base.BeforeInvoke(context);
- context.Scopes.Current.IsSubtotal = true;
- }
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var funcNum = ArgToInt(arguments, 0);
- if (context.Scopes.Current.Parent != null && context.Scopes.Current.Parent.IsSubtotal) {
- return CreateResult(0d, DataType.Decimal);
- }
- var actualArgs = arguments.Skip(1);
- var function = GetFunctionByCalcType(funcNum);
- var compileResult = function.Execute(actualArgs, context);
- compileResult.IsResultOfSubtotal = true;
- return compileResult;
- }
-
- private ExcelFunction GetFunctionByCalcType(int funcNum) {
- if (!_functions.ContainsKey(funcNum)) {
- ThrowExcelErrorValueException(eErrorType.Value);
- //throw new ArgumentException("Invalid funcNum " + funcNum + ", valid ranges are 1-11 and 101-111");
- }
- return _functions[funcNum];
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Sum.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Sum.cs
deleted file mode 100644
index b9b6850..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Sum.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Sum : HiddenValuesHandlingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var retVal = 0d;
- if (arguments != null) {
- foreach (var arg in arguments) {
- retVal += Calculate(arg, context);
- }
- }
- return CreateResult(retVal, DataType.Decimal);
- }
-
- private double Calculate(FunctionArgument arg, ParsingContext context) {
- var retVal = 0d;
- if (ShouldIgnore(arg)) {
- return retVal;
- }
- if (arg.Value is IEnumerable<FunctionArgument> value) {
- foreach (var item in value) {
- retVal += Calculate(item, context);
- }
- } else if (arg.Value is ExcelDataProvider.IRangeInfo info) {
- foreach (var c in info) {
- if (ShouldIgnore(c, context) == false) {
- CheckForAndHandleExcelError(c);
- retVal += c.ValueDouble;
- }
- }
- } else {
- CheckForAndHandleExcelError(arg);
- retVal += ConvertUtil.GetValueDouble(arg.Value, true);
- }
- return retVal;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/SumIf.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/SumIf.cs
deleted file mode 100644
index 8d8d61b..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/SumIf.cs
+++ /dev/null
@@ -1,150 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.Utilities;
-using Util = OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class SumIf : HiddenValuesHandlingFunction {
- private readonly NumericExpressionEvaluator _evaluator;
-
- public SumIf()
- : this(new()) {}
-
- public SumIf(NumericExpressionEvaluator evaluator) {
- Require.That(evaluator).Named("evaluator").IsNotNull();
- _evaluator = evaluator;
- }
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var args = arguments.ElementAt(0).Value as ExcelDataProvider.IRangeInfo; //IEnumerable<FunctionArgument>;
- var criteria = arguments.ElementAt(1).Value;
- ThrowExcelErrorValueExceptionIf(
- () => criteria == null || criteria.ToString().Length > 255,
- eErrorType.Value);
- double retVal;
- if (arguments.Count() > 2) {
- var sumRange = arguments.ElementAt(2).Value as ExcelDataProvider.IRangeInfo; //IEnumerable<FunctionArgument>;
- retVal = CalculateWithSumRange(args, criteria.ToString(), sumRange, context);
- } else {
- if (args != null) {
- retVal = CalculateSingleRange(args, criteria.ToString(), context);
- } else {
- retVal = CalculateSingleRange(
- (arguments.ElementAt(0).Value as IEnumerable<FunctionArgument>),
- criteria.ToString(),
- context);
- }
- }
- return CreateResult(retVal, DataType.Decimal);
- }
-
- private double CalculateWithSumRange(
- ExcelDataProvider.IRangeInfo range,
- string criteria,
- ExcelDataProvider.IRangeInfo sumRange,
- ParsingContext context) {
- var retVal = 0d;
- foreach (var cell in range) {
- if (_evaluator.Evaluate(cell.Value, criteria)) {
- var or = cell.Row - range.Address._fromRow;
- var oc = cell.Column - range.Address._fromCol;
- if (sumRange.Address._fromRow + or <= sumRange.Address._toRow
- && sumRange.Address._fromCol + oc <= sumRange.Address._toCol) {
- var v = sumRange.GetOffset(or, oc);
- if (v is ExcelErrorValue value) {
- throw (new ExcelErrorValueException(value));
- }
- retVal += Util.ConvertUtil.GetValueDouble(v, true);
- }
- }
- }
- return retVal;
- }
-
- private double CalculateSingleRange(
- IEnumerable<FunctionArgument> args,
- string expression,
- ParsingContext context) {
- var retVal = 0d;
- var flattendedRange = ArgsToDoubleEnumerable(args, context);
- foreach (var candidate in flattendedRange) {
- if (_evaluator.Evaluate(candidate, expression)) {
- retVal += candidate;
- }
- }
- return retVal;
- }
-
- private double CalculateSingleRange(
- ExcelDataProvider.IRangeInfo range,
- string expression,
- ParsingContext context) {
- var retVal = 0d;
- foreach (var candidate in range) {
- if (_evaluator.Evaluate(candidate.Value, expression)) {
- if (candidate.IsExcelError) {
- throw (new ExcelErrorValueException((ExcelErrorValue)candidate.Value));
- }
- retVal += candidate.ValueDouble;
- }
- }
- return retVal;
- }
-
- //private double Calculate(FunctionArgument arg, string expression)
- //{
- // var retVal = 0d;
- // if (ShouldIgnore(arg) || !_evaluator.Evaluate(arg.Value, expression))
- // {
- // return retVal;
- // }
- // if (arg.Value is double || arg.Value is int)
- // {
- // retVal += Convert.ToDouble(arg.Value);
- // }
- // else if (arg.Value is System.DateTime)
- // {
- // retVal += Convert.ToDateTime(arg.Value).ToOADate();
- // }
- // else if (arg.Value is IEnumerable<FunctionArgument>)
- // {
- // foreach (var item in (IEnumerable<FunctionArgument>)arg.Value)
- // {
- // retVal += Calculate(item, expression);
- // }
- // }
- // return retVal;
- //}
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/SumIfs.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/SumIfs.cs
deleted file mode 100644
index 72ed696..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/SumIfs.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-15
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class SumIfs : MultipleRangeCriteriasFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
- ValidateArguments(functionArguments, 3);
- var sumRange = ArgsToDoubleEnumerable(
- true,
- new List<FunctionArgument> { functionArguments[0] },
- context)
- .ToList();
- var argRanges = new List<ExcelDataProvider.IRangeInfo>();
- var criterias = new List<object>();
- for (var ix = 1; ix < 31; ix += 2) {
- if (functionArguments.Length <= ix) {
- break;
- }
- var rangeInfo = functionArguments[ix].ValueAsRangeInfo;
- argRanges.Add(rangeInfo);
- if (ix > 1) {
- ThrowExcelErrorValueExceptionIf(
- () => rangeInfo.GetNCells() != argRanges[0].GetNCells(),
- eErrorType.Value);
- }
- criterias.Add(functionArguments[ix + 1].Value);
- }
- IEnumerable<int> matchIndexes = GetMatchIndexes(argRanges[0], criterias[0]);
- var enumerable = matchIndexes as IList<int> ?? matchIndexes.ToList();
- for (var ix = 1; ix < argRanges.Count && enumerable.Any(); ix++) {
- var indexes = GetMatchIndexes(argRanges[ix], criterias[ix]);
- matchIndexes = enumerable.Intersect(indexes);
- }
-
- var result = matchIndexes.Sum(index => sumRange[index]);
-
- return CreateResult(result, DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/SumProduct.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/SumProduct.cs
deleted file mode 100644
index 0ee2d19..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/SumProduct.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class SumProduct : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- double result = 0d;
- List<List<double>> results = new List<List<double>>();
- foreach (var arg in arguments) {
- results.Add(new());
- var currentResult = results.Last();
- if (arg.Value is IEnumerable<FunctionArgument> value) {
- foreach (var val in value) {
- AddValue(val.Value, currentResult);
- }
- } else if (arg.Value is FunctionArgument) {
- AddValue(arg.Value, currentResult);
- } else if (arg.IsExcelRange) {
- var r = arg.ValueAsRangeInfo;
- for (int col = r.Address._fromCol; col <= r.Address._toCol; col++) {
- for (int row = r.Address._fromRow; row <= r.Address._toRow; row++) {
- AddValue(r.GetValue(row, col), currentResult);
- }
- }
- }
- }
- // Validate that all supplied lists have the same length
- var arrayLength = results.First().Count;
- foreach (var list in results) {
- if (list.Count != arrayLength) {
- throw new ExcelErrorValueException(ExcelErrorValue.Create(eErrorType.Value));
- //throw new ExcelFunctionException("All supplied arrays must have the same length", ExcelErrorCodes.Value);
- }
- }
- for (var rowIndex = 0; rowIndex < arrayLength; rowIndex++) {
- double rowResult = 1;
- for (var colIndex = 0; colIndex < results.Count; colIndex++) {
- rowResult *= results[colIndex][rowIndex];
- }
- result += rowResult;
- }
- return CreateResult(result, DataType.Decimal);
- }
-
- private void AddValue(object convertVal, List<double> currentResult) {
- if (IsNumeric(convertVal)) {
- currentResult.Add(Convert.ToDouble(convertVal));
- } else if (convertVal is ExcelErrorValue val) {
- throw (new ExcelErrorValueException(val));
- } else {
- currentResult.Add(0d);
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Sumsq.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Sumsq.cs
deleted file mode 100644
index cb18398..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Sumsq.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Sumsq : HiddenValuesHandlingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var retVal = 0d;
- if (arguments != null) {
- foreach (var arg in arguments) {
- retVal += Calculate(arg, context);
- }
- }
- return CreateResult(retVal, DataType.Decimal);
- }
-
- private double Calculate(FunctionArgument arg, ParsingContext context, bool isInArray = false) {
- var retVal = 0d;
- if (ShouldIgnore(arg)) {
- return retVal;
- }
- if (arg.Value is IEnumerable<FunctionArgument> arguments) {
- foreach (var item in arguments) {
- retVal += Calculate(item, context, true);
- }
- } else {
- var cs = arg.Value as ExcelDataProvider.IRangeInfo;
- if (cs != null) {
- foreach (var c in cs) {
- if (ShouldIgnore(c, context) == false) {
- CheckForAndHandleExcelError(c);
- retVal += System.Math.Pow(c.ValueDouble, 2);
- }
- }
- } else {
- CheckForAndHandleExcelError(arg);
- if (IsNumericString(arg.Value) && !isInArray) {
- var value = ConvertUtil.GetValueDouble(arg.Value);
- return System.Math.Pow(value, 2);
- }
- var ignoreBool = isInArray;
- retVal += System.Math.Pow(ConvertUtil.GetValueDouble(arg.Value, ignoreBool), 2);
- }
- }
- return retVal;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Tan.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Tan.cs
deleted file mode 100644
index dd85652..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Tan.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Tan : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = ArgToDecimal(arguments, 0);
- return CreateResult(System.Math.Tan(arg), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Tanh.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Tanh.cs
deleted file mode 100644
index e2e4f14..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Tanh.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Tanh : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var arg = ArgToDecimal(arguments, 0);
- return CreateResult(System.Math.Tanh(arg), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Trunc.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Trunc.cs
deleted file mode 100644
index 3730382..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Trunc.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2014-01-06
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Trunc : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var number = ArgToDecimal(arguments, 0);
- if (arguments.Count() == 1) {
- return CreateResult(System.Math.Truncate(number), DataType.Decimal);
- }
- var nDigits = ArgToInt(arguments, 1);
- var func = context.Configuration.FunctionRepository.GetFunction("rounddown");
- return func.Execute(arguments, context);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Var.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Var.cs
deleted file mode 100644
index b32b165..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Var.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class Var : HiddenValuesHandlingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var args = ArgsToDoubleEnumerable(IgnoreHiddenValues, false, arguments, context);
- return new(VarMethods.Var(args), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/VarMethods.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/VarMethods.cs
deleted file mode 100644
index 6061b74..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/VarMethods.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-04-19
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-internal static class VarMethods {
- private static double Divide(double left, double right) {
- if (System.Math.Abs(right - 0d) < double.Epsilon) {
- throw new ExcelErrorValueException(eErrorType.Div0);
- }
- return left / right;
- }
-
- public static double Var(IEnumerable<double> args) {
- double avg = args.Average();
- double d = args.Aggregate(0.0, (total, next) => total + System.Math.Pow(next - avg, 2));
- return Divide(d, (args.Count() - 1));
- }
-
- public static double VarP(IEnumerable<double> args) {
- double avg = args.Average();
- double d = args.Aggregate(0.0, (total, next) => total + System.Math.Pow(next - avg, 2));
- return Divide(d, args.Count());
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/VarP.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/VarP.cs
deleted file mode 100644
index 1afab92..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/VarP.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
-public class VarP : HiddenValuesHandlingFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var args = ArgsToDoubleEnumerable(IgnoreHiddenValues, false, arguments, context);
- return new(VarMethods.VarP(args), DataType.Decimal);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Numeric/CInt.cs b/EPPlus/FormulaParsing/Excel/Functions/Numeric/CInt.cs
deleted file mode 100644
index 0482de8..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Numeric/CInt.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Numeric;
-
-public class CInt : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var num = ArgToDecimal(arguments, 0);
- return CreateResult((int)System.Math.Floor(num), DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/ObjectEnumerableArgConverter.cs b/EPPlus/FormulaParsing/Excel/Functions/ObjectEnumerableArgConverter.cs
deleted file mode 100644
index 6e56c59..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/ObjectEnumerableArgConverter.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-public class ObjectEnumerableArgConverter : CollectionFlattener<object> {
- public virtual IEnumerable<object> ConvertArgs(
- bool ignoreHidden,
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- return base.FuncArgsToFlatEnumerable(
- arguments,
- (arg, argList) => {
- if (arg.Value is ExcelDataProvider.IRangeInfo info) {
- foreach (var cell in info) {
- if (!CellStateHelper.ShouldIgnore(ignoreHidden, cell, context)) {
- argList.Add(cell.Value);
- }
- }
- } else {
- argList.Add(arg.Value);
- }
- });
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Address.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Address.cs
deleted file mode 100644
index b0ce169..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Address.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class Address : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var row = ArgToInt(arguments, 0);
- var col = ArgToInt(arguments, 1);
- ThrowExcelErrorValueExceptionIf(() => row < 0 && col < 0, eErrorType.Value);
- var referenceType = ExcelReferenceType.AbsoluteRowAndColumn;
- var worksheetSpec = string.Empty;
- if (arguments.Count() > 2) {
- var arg3 = ArgToInt(arguments, 2);
- ThrowExcelErrorValueExceptionIf(() => arg3 < 1 || arg3 > 4, eErrorType.Value);
- referenceType = (ExcelReferenceType)ArgToInt(arguments, 2);
- }
- if (arguments.Count() > 3) {
- var fourthArg = arguments.ElementAt(3).Value;
- if (fourthArg is bool arg && !arg) {
- throw new InvalidOperationException("Excelformulaparser does not support the R1C1 format!");
- }
- }
- if (arguments.Count() > 4) {
- var fifthArg = arguments.ElementAt(4).Value;
- if (fifthArg is string && !string.IsNullOrEmpty(fifthArg.ToString())) {
- worksheetSpec = fifthArg + "!";
- }
- }
- var translator = new IndexToAddressTranslator(context.ExcelDataProvider, referenceType);
- return CreateResult(worksheetSpec + translator.ToAddress(col, row), DataType.ExcelAddress);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/ArrayLookupNavigator.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/ArrayLookupNavigator.cs
deleted file mode 100644
index e558462..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/ArrayLookupNavigator.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class ArrayLookupNavigator : LookupNavigator {
- private readonly FunctionArgument[] _arrayData;
- private int _index;
- private object _currentValue;
-
- public ArrayLookupNavigator(
- LookupDirection direction,
- LookupArguments arguments,
- ParsingContext parsingContext)
- : base(direction, arguments, parsingContext) {
- Require.That(arguments).Named("arguments").IsNotNull();
- Require.That(arguments.DataArray).Named("arguments.DataArray").IsNotNull();
- _arrayData = arguments.DataArray.ToArray();
- Initialize();
- }
-
- private void Initialize() {
- if (Arguments.LookupIndex >= _arrayData.Length) {
- throw new ExcelErrorValueException(eErrorType.Ref);
- }
- SetCurrentValue();
- }
-
- public override int Index => _index;
-
- private void SetCurrentValue() {
- _currentValue = _arrayData[_index];
- }
-
- private bool HasNext() {
- if (Direction == LookupDirection.Vertical) {
- return _index < (_arrayData.Length - 1);
- }
- return false;
- }
-
- public override bool MoveNext() {
- if (!HasNext()) {
- return false;
- }
- if (Direction == LookupDirection.Vertical) {
- _index++;
- }
- SetCurrentValue();
- return true;
- }
-
- public override object CurrentValue => _arrayData[_index].Value;
-
- public override object GetLookupValue() {
- return _arrayData[_index].Value;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Choose.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Choose.cs
deleted file mode 100644
index 599467b..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Choose.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class Choose : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var index = ArgToInt(arguments, 0);
- var items = new List<string>();
- for (int x = 0; x < arguments.Count(); x++) {
- items.Add(arguments.ElementAt(x).ValueFirst.ToString());
- }
- return CreateResult(items[index], DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Column.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Column.cs
deleted file mode 100644
index c2b4366..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Column.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class Column : LookupFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- if (arguments == null || arguments.Count() == 0) {
- return CreateResult(context.Scopes.Current.Address.FromCol, DataType.Integer);
- }
- var rangeAddress = ArgToString(arguments, 0);
- if (!ExcelAddressUtil.IsValidAddress(rangeAddress)) {
- throw new ArgumentException("An invalid argument was supplied");
- }
- var factory = new RangeAddressFactory(context.ExcelDataProvider);
- var address = factory.Create(rangeAddress);
- return CreateResult(address.FromCol, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Columns.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Columns.cs
deleted file mode 100644
index 27864bb..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Columns.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class Columns : LookupFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var r = arguments.ElementAt(0).ValueAsRangeInfo;
- if (r != null) {
- return CreateResult(r.Address._toCol - r.Address._fromCol + 1, DataType.Integer);
- }
- var range = ArgToString(arguments, 0);
- if (ExcelAddressUtil.IsValidAddress(range)) {
- var factory = new RangeAddressFactory(context.ExcelDataProvider);
- var address = factory.Create(range);
- return CreateResult(address.ToCol - address.FromCol + 1, DataType.Integer);
- }
- throw new ArgumentException("Invalid range supplied");
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/ExcelLookupNavigator.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/ExcelLookupNavigator.cs
deleted file mode 100644
index 124fb3e..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/ExcelLookupNavigator.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class ExcelLookupNavigator : LookupNavigator {
- private int _currentRow;
- private int _currentCol;
- private object _currentValue;
- private RangeAddress _rangeAddress;
- private int _index;
-
- public ExcelLookupNavigator(
- LookupDirection direction,
- LookupArguments arguments,
- ParsingContext parsingContext)
- : base(direction, arguments, parsingContext) {
- Initialize();
- }
-
- private void Initialize() {
- _index = 0;
- var factory = new RangeAddressFactory(ParsingContext.ExcelDataProvider);
- if (Arguments.RangeInfo == null) {
- _rangeAddress = factory.Create(
- ParsingContext.Scopes.Current.Address.Worksheet,
- Arguments.RangeAddress);
- } else {
- _rangeAddress = factory.Create(
- Arguments.RangeInfo.Address.WorkSheet,
- Arguments.RangeInfo.Address.Address);
- }
- _currentCol = _rangeAddress.FromCol;
- _currentRow = _rangeAddress.FromRow;
- SetCurrentValue();
- }
-
- private void SetCurrentValue() {
- _currentValue = ParsingContext.ExcelDataProvider.GetCellValue(
- _rangeAddress.Worksheet,
- _currentRow,
- _currentCol);
- }
-
- private bool HasNext() {
- if (Direction == LookupDirection.Vertical) {
- return _currentRow < _rangeAddress.ToRow;
- }
- return _currentCol < _rangeAddress.ToCol;
- }
-
- public override int Index => _index;
-
- public override bool MoveNext() {
- if (!HasNext()) {
- return false;
- }
- if (Direction == LookupDirection.Vertical) {
- _currentRow++;
- } else {
- _currentCol++;
- }
- _index++;
- SetCurrentValue();
- return true;
- }
-
- public override object CurrentValue => _currentValue;
-
- public override object GetLookupValue() {
- var row = _currentRow;
- var col = _currentCol;
- if (Direction == LookupDirection.Vertical) {
- col += Arguments.LookupIndex - 1;
- row += Arguments.LookupOffset;
- } else {
- row += Arguments.LookupIndex - 1;
- col += Arguments.LookupOffset;
- }
- return ParsingContext.ExcelDataProvider.GetCellValue(_rangeAddress.Worksheet, row, col);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/HLookup.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/HLookup.cs
deleted file mode 100644
index a2ec6a3..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/HLookup.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class HLookup : LookupFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 3);
- var lookupArgs = new LookupArguments(arguments);
- ThrowExcelErrorValueExceptionIf(() => lookupArgs.LookupIndex < 1, eErrorType.Value);
- var navigator = LookupNavigatorFactory.Create(LookupDirection.Horizontal, lookupArgs, context);
- return Lookup(navigator, lookupArgs);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Index.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Index.cs
deleted file mode 100644
index 7c8431d..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Index.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class Index : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var arg1 = arguments.ElementAt(0);
- var args = arg1.Value as IEnumerable<FunctionArgument>;
- var crf = new CompileResultFactory();
- if (args != null) {
- var index = ArgToInt(arguments, 1);
- if (index > args.Count()) {
- throw new ExcelErrorValueException(eErrorType.Ref);
- }
- var candidate = args.ElementAt(index - 1);
- //Commented JK-Can be any data type
- //if (!IsNumber(candidate.Value))
- //{
- // throw new ExcelErrorValueException(eErrorType.Value);
- //}
- //return CreateResult(ConvertUtil.GetValueDouble(candidate.Value), DataType.Decimal);
- return crf.Create(candidate.Value);
- }
- if (arg1.IsExcelRange) {
- var row = ArgToInt(arguments, 1);
- var col = arguments.Count() > 2 ? ArgToInt(arguments, 2) : 1;
- var ri = arg1.ValueAsRangeInfo;
- if (row > ri.Address._toRow - ri.Address._fromRow + 1
- || col > ri.Address._toCol - ri.Address._fromCol + 1) {
- ThrowExcelErrorValueException(eErrorType.Ref);
- }
- var candidate = ri.GetOffset(row - 1, col - 1);
- //Commented JK-Can be any data type
- //if (!IsNumber(candidate.Value))
- //{
- // throw new ExcelErrorValueException(eErrorType.Value);
- //}
- return crf.Create(candidate);
- }
- throw new NotImplementedException();
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Indirect.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Indirect.cs
deleted file mode 100644
index ae80178..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Indirect.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2014-04-13
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class Indirect : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var address = ArgToString(arguments, 0);
- var adr = new ExcelAddress(address);
- var ws = adr.WorkSheet;
- if (string.IsNullOrEmpty(ws)) {
- ws = context.Scopes.Current.Address.Worksheet;
- }
- var result = context.ExcelDataProvider.GetRange(ws, adr._fromRow, adr._fromCol, address);
- if (result.IsEmpty) {
- // Bug 15290
- var namedValueExpr = new NamedValueExpression(address, context);
- return namedValueExpr.Compile();
- }
- return new(result, DataType.Enumerable);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Lookup.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Lookup.cs
deleted file mode 100644
index 8fee752..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Lookup.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class Lookup : LookupFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- if (HaveTwoRanges(arguments)) {
- return HandleTwoRanges(arguments, context);
- }
- return HandleSingleRange(arguments, context);
- }
-
- private bool HaveTwoRanges(IEnumerable<FunctionArgument> arguments) {
- if (arguments.Count() == 2) {
- return false;
- }
- return (ExcelAddressUtil.IsValidAddress(arguments.ElementAt(2).Value.ToString()));
- }
-
- private CompileResult HandleSingleRange(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var searchedValue = arguments.ElementAt(0).Value;
- Require.That(arguments.ElementAt(1).Value).Named("firstAddress").IsNotNull();
- var firstAddress = ArgToString(arguments, 1);
- var rangeAddressFactory = new RangeAddressFactory(context.ExcelDataProvider);
- var address = rangeAddressFactory.Create(firstAddress);
- var nRows = address.ToRow - address.FromRow;
- var nCols = address.ToCol - address.FromCol;
- var lookupIndex = nCols + 1;
- var lookupDirection = LookupDirection.Vertical;
- if (nCols > nRows) {
- lookupIndex = nRows + 1;
- lookupDirection = LookupDirection.Horizontal;
- }
- var lookupArgs = new LookupArguments(searchedValue, firstAddress, lookupIndex, 0, true);
- var navigator = LookupNavigatorFactory.Create(lookupDirection, lookupArgs, context);
- return Lookup(navigator, lookupArgs);
- }
-
- private CompileResult HandleTwoRanges(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var searchedValue = arguments.ElementAt(0).Value;
- Require.That(arguments.ElementAt(1).Value).Named("firstAddress").IsNotNull();
- Require.That(arguments.ElementAt(2).Value).Named("secondAddress").IsNotNull();
- var firstAddress = ArgToString(arguments, 1);
- var secondAddress = ArgToString(arguments, 2);
- var rangeAddressFactory = new RangeAddressFactory(context.ExcelDataProvider);
- var address1 = rangeAddressFactory.Create(firstAddress);
- var address2 = rangeAddressFactory.Create(secondAddress);
- var lookupIndex = (address2.FromCol - address1.FromCol) + 1;
- var lookupOffset = address2.FromRow - address1.FromRow;
- var lookupDirection = GetLookupDirection(address1);
- if (lookupDirection == LookupDirection.Horizontal) {
- lookupIndex = (address2.FromRow - address1.FromRow) + 1;
- lookupOffset = address2.FromCol - address1.FromCol;
- }
- var lookupArgs = new LookupArguments(
- searchedValue,
- firstAddress,
- lookupIndex,
- lookupOffset,
- true);
- var navigator = LookupNavigatorFactory.Create(lookupDirection, lookupArgs, context);
- return Lookup(navigator, lookupArgs);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupArguments.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupArguments.cs
deleted file mode 100644
index 8bed82d..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupArguments.cs
+++ /dev/null
@@ -1,103 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class LookupArguments {
- public enum LookupArgumentDataType {
- ExcelRange,
- DataArray,
- }
-
- public LookupArguments(IEnumerable<FunctionArgument> arguments)
- : this(arguments, new()) {}
-
- public LookupArguments(IEnumerable<FunctionArgument> arguments, ArgumentParsers argumentParsers) {
- _argumentParsers = argumentParsers;
- SearchedValue = arguments.ElementAt(0).Value;
- var arg1 = arguments.ElementAt(1).Value;
- var dataArray = arg1 as IEnumerable<FunctionArgument>;
- if (dataArray != null) {
- DataArray = dataArray;
- ArgumentDataType = LookupArgumentDataType.DataArray;
- } else {
- //if (arg1 is ExcelDataProvider.INameInfo) arg1 = ((ExcelDataProvider.INameInfo) arg1).Value;
- var rangeInfo = arg1 as ExcelDataProvider.IRangeInfo;
- if (rangeInfo != null) {
- RangeAddress = string.IsNullOrEmpty(rangeInfo.Address.WorkSheet)
- ? rangeInfo.Address.Address
- : "'" + rangeInfo.Address.WorkSheet + "'!" + rangeInfo.Address.Address;
- RangeInfo = rangeInfo;
- ArgumentDataType = LookupArgumentDataType.ExcelRange;
- } else {
- RangeAddress = arg1.ToString();
- ArgumentDataType = LookupArgumentDataType.ExcelRange;
- }
- }
- LookupIndex = (int)
- _argumentParsers.GetParser(DataType.Integer).Parse(arguments.ElementAt(2).Value);
- if (arguments.Count() > 3) {
- RangeLookup = (bool)
- _argumentParsers.GetParser(DataType.Boolean).Parse(arguments.ElementAt(3).Value);
- } else {
- RangeLookup = true;
- }
- }
-
- public LookupArguments(
- object searchedValue,
- string rangeAddress,
- int lookupIndex,
- int lookupOffset,
- bool rangeLookup) {
- SearchedValue = searchedValue;
- RangeAddress = rangeAddress;
- LookupIndex = lookupIndex;
- LookupOffset = lookupOffset;
- RangeLookup = rangeLookup;
- }
-
- private readonly ArgumentParsers _argumentParsers;
-
- public object SearchedValue { get; private set; }
-
- public string RangeAddress { get; private set; }
-
- public int LookupIndex { get; private set; }
-
- public int LookupOffset { get; private set; }
-
- public bool RangeLookup { get; private set; }
-
- public IEnumerable<FunctionArgument> DataArray { get; private set; }
-
- public ExcelDataProvider.IRangeInfo RangeInfo { get; private set; }
-
- public LookupArgumentDataType ArgumentDataType { get; private set; }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupDirection.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupDirection.cs
deleted file mode 100644
index abb564c..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupDirection.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public enum LookupDirection {
- Vertical,
- Horizontal,
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupFunction.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupFunction.cs
deleted file mode 100644
index 84f20d8..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupFunction.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public abstract class LookupFunction : ExcelFunction {
- private readonly ValueMatcher _valueMatcher;
- private readonly CompileResultFactory _compileResultFactory;
-
- public LookupFunction()
- : this(new LookupValueMatcher(), new()) {}
-
- public LookupFunction(ValueMatcher valueMatcher, CompileResultFactory compileResultFactory) {
- _valueMatcher = valueMatcher;
- _compileResultFactory = compileResultFactory;
- }
-
- public override bool IsLookupFuction => true;
-
- protected int IsMatch(object o1, object o2) {
- return _valueMatcher.IsMatch(o1, o2);
- }
-
- protected LookupDirection GetLookupDirection(RangeAddress rangeAddress) {
- var nRows = rangeAddress.ToRow - rangeAddress.FromRow;
- var nCols = rangeAddress.ToCol - rangeAddress.FromCol;
- return nCols > nRows ? LookupDirection.Horizontal : LookupDirection.Vertical;
- }
-
- protected CompileResult Lookup(LookupNavigator navigator, LookupArguments lookupArgs) {
- object lastValue = null;
- object lastLookupValue = null;
- int? lastMatchResult = null;
- if (lookupArgs.SearchedValue == null) {
- return new(ExcelErrorValue.Create(eErrorType.Na), DataType.ExcelError);
- }
- do {
- var matchResult = IsMatch(navigator.CurrentValue, lookupArgs.SearchedValue);
- if (matchResult != 0) {
- if (lastValue != null && navigator.CurrentValue == null) {
- break;
- }
-
- if (lookupArgs.RangeLookup) {
- if (lastValue == null && matchResult > 0) {
- ThrowExcelErrorValueException(eErrorType.Na);
- }
- if (lastValue != null && matchResult > 0 && lastMatchResult < 0) {
- return _compileResultFactory.Create(lastLookupValue);
- }
- lastMatchResult = matchResult;
- lastValue = navigator.CurrentValue;
- lastLookupValue = navigator.GetLookupValue();
- }
- } else {
- return _compileResultFactory.Create(navigator.GetLookupValue());
- }
- } while (navigator.MoveNext());
-
- if (lookupArgs.RangeLookup) {
- return _compileResultFactory.Create(lastLookupValue);
- }
- return new(ExcelErrorValue.Create(eErrorType.Na), DataType.ExcelError);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigator.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigator.cs
deleted file mode 100644
index f93cfbe..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigator.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public abstract class LookupNavigator {
- protected readonly LookupDirection Direction;
- protected readonly LookupArguments Arguments;
- protected readonly ParsingContext ParsingContext;
-
- public LookupNavigator(
- LookupDirection direction,
- LookupArguments arguments,
- ParsingContext parsingContext) {
- Require.That(arguments).Named("arguments").IsNotNull();
- Require.That(parsingContext).Named("parsingContext").IsNotNull();
- Require
- .That(parsingContext.ExcelDataProvider)
- .Named("parsingContext.ExcelDataProvider")
- .IsNotNull();
- Direction = direction;
- Arguments = arguments;
- ParsingContext = parsingContext;
- }
-
- public abstract int Index { get; }
-
- public abstract bool MoveNext();
-
- public abstract object CurrentValue { get; }
-
- public abstract object GetLookupValue();
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigatorFactory.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigatorFactory.cs
deleted file mode 100644
index d444525..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigatorFactory.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public static class LookupNavigatorFactory {
- public static LookupNavigator Create(
- LookupDirection direction,
- LookupArguments args,
- ParsingContext parsingContext) {
- if (args.ArgumentDataType == LookupArguments.LookupArgumentDataType.ExcelRange) {
- return new ExcelLookupNavigator(direction, args, parsingContext);
- }
- if (args.ArgumentDataType == LookupArguments.LookupArgumentDataType.DataArray) {
- return new ArrayLookupNavigator(direction, args, parsingContext);
- }
- throw new NotSupportedException("Invalid argument datatype");
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Match.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Match.cs
deleted file mode 100644
index 36f24fc..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Match.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class Match : LookupFunction {
- private enum MatchType {
- ClosestAbove = -1,
- ExactMatch = 0,
- ClosestBelow = 1,
- }
-
- public Match()
- : base(new WildCardValueMatcher(), new()) {}
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
-
- var searchedValue = arguments.ElementAt(0).Value;
- var address = ArgToString(arguments, 1);
- var rangeAddressFactory = new RangeAddressFactory(context.ExcelDataProvider);
- var rangeAddress = rangeAddressFactory.Create(address);
- var matchType = GetMatchType(arguments);
- var args = new LookupArguments(searchedValue, address, 0, 0, false);
- var lookupDirection = GetLookupDirection(rangeAddress);
- var navigator = LookupNavigatorFactory.Create(lookupDirection, args, context);
- int? lastMatchResult = default(int?);
- do {
- var matchResult = IsMatch(navigator.CurrentValue, searchedValue);
- if (matchType == MatchType.ClosestBelow && matchResult >= 0) {
- if (!lastMatchResult.HasValue && matchResult > 0) {
- // TODO: error handling. This happens only if the first item is
- // below the searched value.
- }
- var index = matchResult == 0 ? navigator.Index + 1 : navigator.Index;
- return CreateResult(index, DataType.Integer);
- }
- if (matchType == MatchType.ClosestAbove && matchResult <= 0) {
- if (!lastMatchResult.HasValue && matchResult < 0) {
- // TODO: error handling. This happens only if the first item is
- // above the searched value
- }
- var index = matchResult == 0 ? navigator.Index + 1 : navigator.Index;
- return CreateResult(index, DataType.Integer);
- }
- if (matchType == MatchType.ExactMatch && matchResult == 0) {
- return CreateResult(navigator.Index + 1, DataType.Integer);
- }
- lastMatchResult = matchResult;
- } while (navigator.MoveNext());
- return CreateResult(null, DataType.Integer);
- }
-
- private MatchType GetMatchType(IEnumerable<FunctionArgument> arguments) {
- var matchType = MatchType.ClosestBelow;
- if (arguments.Count() > 2) {
- matchType = (MatchType)ArgToInt(arguments, 2);
- }
- return matchType;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Offset.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Offset.cs
deleted file mode 100644
index 8a16080..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Offset.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-11
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class Offset : LookupFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
- ValidateArguments(functionArguments, 3);
- var startRange = ArgToString(functionArguments, 0);
- var rowOffset = ArgToInt(functionArguments, 1);
- var colOffset = ArgToInt(functionArguments, 2);
- int width = 0,
- height = 0;
- if (functionArguments.Length > 3) {
- height = ArgToInt(functionArguments, 3);
- ThrowExcelErrorValueExceptionIf(() => height == 0, eErrorType.Ref);
- }
- if (functionArguments.Length > 4) {
- width = ArgToInt(functionArguments, 4);
- ThrowExcelErrorValueExceptionIf(() => width == 0, eErrorType.Ref);
- }
-
- var adr = new ExcelAddress(startRange);
- var ws = adr.WorkSheet;
-
- var fromRow = adr._fromRow + rowOffset;
- var fromCol = adr._fromCol + colOffset;
- var toRow = (height != 0 ? height : adr._toRow) + rowOffset;
- var toCol = (width != 0 ? width : adr._toCol) + colOffset;
-
- var newRange = context.ExcelDataProvider.GetRange(ws, fromRow, fromCol, toRow, toCol);
- if (!newRange.IsMulti) {
- if (newRange.IsEmpty) {
- return CompileResult.Empty;
- }
- var val = newRange.GetValue(fromRow, fromCol);
- if (IsNumeric(val)) {
- return CreateResult(val, DataType.Decimal);
- }
- if (val is ExcelErrorValue) {
- return CreateResult(val, DataType.ExcelError);
- }
- return CreateResult(val, DataType.String);
- }
- return CreateResult(newRange, DataType.Enumerable);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Row.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Row.cs
deleted file mode 100644
index 5b20a5b..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Row.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class Row : LookupFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- if (arguments == null || arguments.Count() == 0) {
- return CreateResult(context.Scopes.Current.Address.FromRow, DataType.Integer);
- }
- var rangeAddress = ArgToString(arguments, 0);
- if (!ExcelAddressUtil.IsValidAddress(rangeAddress)) {
- throw new ArgumentException("An invalid argument was supplied");
- }
- var factory = new RangeAddressFactory(context.ExcelDataProvider);
- var address = factory.Create(rangeAddress);
- return CreateResult(address.FromRow, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Rows.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Rows.cs
deleted file mode 100644
index 94f5203..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Rows.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class Rows : LookupFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var r = arguments.ElementAt(0).ValueAsRangeInfo;
- if (r != null) {
- return CreateResult(r.Address._toRow - r.Address._fromRow + 1, DataType.Integer);
- }
- var range = ArgToString(arguments, 0);
- if (ExcelAddressUtil.IsValidAddress(range)) {
- var factory = new RangeAddressFactory(context.ExcelDataProvider);
- var address = factory.Create(range);
- return CreateResult(address.ToRow - address.FromRow + 1, DataType.Integer);
- }
- throw new ArgumentException("Invalid range supplied");
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/VLookup.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/VLookup.cs
deleted file mode 100644
index 559715a..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/VLookup.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Diagnostics;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-
-public class VLookup : LookupFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- Stopwatch sw = null;
- if (context.Debug) {
- sw = new();
- sw.Start();
- }
- ValidateArguments(arguments, 3);
- var lookupArgs = new LookupArguments(arguments);
- var navigator = LookupNavigatorFactory.Create(LookupDirection.Vertical, lookupArgs, context);
- var result = Lookup(navigator, lookupArgs);
- if (context.Debug) {
- sw.Stop();
- context.Configuration.Logger.LogFunction("VLOOKUP", sw.ElapsedMilliseconds);
- }
- return result;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/CStr.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/CStr.cs
deleted file mode 100644
index 2350c6c..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/CStr.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class CStr : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- return CreateResult(ArgToString(arguments, 0), DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/CharFunction.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/CharFunction.cs
deleted file mode 100644
index 231479a..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/CharFunction.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class CharFunction : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var number = ArgToInt(arguments, 0);
- ThrowExcelErrorValueExceptionIf(() => number < 1 || number > 255, eErrorType.Value);
- return CreateResult(((char)number).ToString(), DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Concatenate.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Concatenate.cs
deleted file mode 100644
index 9a22422..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Concatenate.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Text;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Concatenate : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- if (arguments == null) {
- return CreateResult(string.Empty, DataType.String);
- }
- var sb = new StringBuilder();
- foreach (var arg in arguments) {
- var v = arg.ValueFirst;
- if (v != null) {
- sb.Append(v);
- }
- }
- return CreateResult(sb.ToString(), DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Exact.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Exact.cs
deleted file mode 100644
index 41d6a3e..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Exact.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Exact : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var val1 = arguments.ElementAt(0).ValueFirst;
- var val2 = arguments.ElementAt(1).ValueFirst;
-
- if (val1 == null && val2 == null) {
- return CreateResult(true, DataType.Boolean);
- }
- if ((val1 == null && val2 != null) || (val1 != null && val2 == null)) {
- return CreateResult(false, DataType.Boolean);
- }
-
- var result = string.Compare(
- val1.ToString(),
- val2.ToString(),
- StringComparison.InvariantCulture);
- return CreateResult(result == 0, DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Find.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Find.cs
deleted file mode 100644
index 1a8c255..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Find.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Find : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
- ValidateArguments(functionArguments, 2);
- var search = ArgToString(functionArguments, 0);
- var searchIn = ArgToString(functionArguments, 1);
- var startIndex = 0;
- if (functionArguments.Count() > 2) {
- startIndex = ArgToInt(functionArguments, 2);
- }
- var result = searchIn.IndexOf(search, startIndex, StringComparison.Ordinal);
- if (result == -1) {
- throw new ExcelErrorValueException(ExcelErrorValue.Create(eErrorType.Value));
- }
- // Adding 1 because Excel uses 1-based index
- return CreateResult(result + 1, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Fixed.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Fixed.cs
deleted file mode 100644
index 4eab700..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Fixed.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Fixed : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var number = ArgToDecimal(arguments, 0);
- var nDecimals = 2;
- var noCommas = false;
- if (arguments.Count() > 1) {
- nDecimals = ArgToInt(arguments, 1);
- }
- if (arguments.Count() > 2) {
- noCommas = ArgToBool(arguments, 2);
- }
- var format = (noCommas ? "F" : "N") + nDecimals.ToString(CultureInfo.InvariantCulture);
- if (nDecimals < 0) {
- number = number - (number % (System.Math.Pow(10, nDecimals * -1)));
- number = System.Math.Floor(number);
- format = noCommas ? "F0" : "N0";
- }
- var retVal = number.ToString(format);
- return CreateResult(retVal, DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Hyperlink.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Hyperlink.cs
deleted file mode 100644
index 1635f43..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Hyperlink.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-10
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Hyperlink : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- if (arguments.Count() > 1) {
- return CreateResult(ArgToString(arguments, 1), DataType.String);
- }
- return CreateResult(ArgToString(arguments, 0), DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Left.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Left.cs
deleted file mode 100644
index bdbbc74..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Left.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Left : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var str = ArgToString(arguments, 0);
- var length = ArgToInt(arguments, 1);
- return CreateResult(str.Substring(0, length), DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Len.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Len.cs
deleted file mode 100644
index d5ce785..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Len.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Len : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var length = arguments.First().ValueFirst.ToString().Length;
- return CreateResult(Convert.ToDouble(length), DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Lower.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Lower.cs
deleted file mode 100644
index b9e51e2..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Lower.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Lower : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- return CreateResult(arguments.First().ValueFirst.ToString().ToLower(), DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Mid.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Mid.cs
deleted file mode 100644
index 8bbd0e6..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Mid.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Mid : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 3);
- var text = ArgToString(arguments, 0);
- var startIx = ArgToInt(arguments, 1);
- var length = ArgToInt(arguments, 2);
- if (startIx <= 0) {
- throw (new ArgumentException("Argument start can't be less than 1"));
- }
- //Allow overflowing start and length
- if (startIx > text.Length) {
- return CreateResult("", DataType.String);
- }
- var result = text.Substring(
- startIx - 1,
- startIx - 1 + length < text.Length ? length : text.Length - startIx + 1);
- return CreateResult(result, DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Proper.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Proper.cs
deleted file mode 100644
index a336746..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Proper.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Globalization;
-using System.Text;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Proper : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var text = ArgToString(arguments, 0).ToLower(CultureInfo.InvariantCulture);
- var sb = new StringBuilder();
- var previousChar = '.';
- foreach (var ch in text) {
- if (!char.IsLetter(previousChar)) {
- sb.Append(ch.ToString(CultureInfo.InvariantCulture).ToUpperInvariant());
- } else {
- sb.Append(ch);
- }
- previousChar = ch;
- }
- return CreateResult(sb.ToString(), DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Replace.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Replace.cs
deleted file mode 100644
index 37ccc2c..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Replace.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Replace : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 4);
- var oldText = ArgToString(arguments, 0);
- var startPos = ArgToInt(arguments, 1);
- var nCharsToReplace = ArgToInt(arguments, 2);
- var newText = ArgToString(arguments, 3);
- var firstPart = GetFirstPart(oldText, startPos);
- var lastPart = GetLastPart(oldText, startPos, nCharsToReplace);
- var result = string.Concat(firstPart, newText, lastPart);
- return CreateResult(result, DataType.String);
- }
-
- private string GetFirstPart(string text, int startPos) {
- return text.Substring(0, startPos - 1);
- }
-
- private string GetLastPart(string text, int startPos, int nCharactersToReplace) {
- int startIx = startPos - 1;
- startIx += nCharactersToReplace;
- return text.Substring(startIx, text.Length - startIx);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Rept.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Rept.cs
deleted file mode 100644
index 1f7cc5c..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Rept.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2015-01-10
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Text;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Rept : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var str = ArgToString(arguments, 0);
- var n = ArgToInt(arguments, 1);
- var sb = new StringBuilder();
- for (var x = 0; x < n; x++) {
- sb.Append(str);
- }
- return CreateResult(sb.ToString(), DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Right.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Right.cs
deleted file mode 100644
index f78efd9..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Right.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Right : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var str = ArgToString(arguments, 0);
- var length = ArgToInt(arguments, 1);
- var startIx = str.Length - length;
- return CreateResult(str.Substring(startIx, str.Length - startIx), DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Search.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Search.cs
deleted file mode 100644
index a6d38ba..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Search.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2016-03-28
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Search : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- var functionArguments = arguments as FunctionArgument[] ?? arguments.ToArray();
- ValidateArguments(functionArguments, 2);
- var search = ArgToString(functionArguments, 0);
- var searchIn = ArgToString(functionArguments, 1);
- var startIndex = 0;
- if (functionArguments.Count() > 2) {
- startIndex = ArgToInt(functionArguments, 2);
- }
- var result = searchIn.IndexOf(search, startIndex, StringComparison.OrdinalIgnoreCase);
- if (result == -1) {
- return CreateResult(ExcelErrorValue.Create(eErrorType.Value), DataType.ExcelError);
- }
- // Adding 1 because Excel uses 1-based index
- return CreateResult(result + 1, DataType.Integer);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Substitute.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Substitute.cs
deleted file mode 100644
index 22d887e..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Substitute.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Substitute : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 3);
- var text = ArgToString(arguments, 0);
- var find = ArgToString(arguments, 1);
- var replaceWith = ArgToString(arguments, 2);
- var result = text.Replace(find, replaceWith);
- return CreateResult(result, DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/T.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/T.cs
deleted file mode 100644
index 646b90b..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/T.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class T : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var val = arguments.ElementAt(0).ValueFirst;
- if (val is string) {
- return CreateResult(val, DataType.String);
- }
- return CreateResult(string.Empty, DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Text.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Text.cs
deleted file mode 100644
index 00ae7fc..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Text.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-/* 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 2014-01-17
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Text : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 2);
- var value = arguments.First().ValueFirst;
- var format = ArgToString(arguments, 1);
- format = format.Replace(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, ".");
- format = format.Replace(
- CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator.Replace((char)160, ' '),
- ","); //Special handling for No-Break Space
-
- var result = context.ExcelDataProvider.GetFormat(value, format);
-
- return CreateResult(result, DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Upper.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Upper.cs
deleted file mode 100644
index c40e6f4..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Upper.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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
- *******************************************************************************
- * Mats Alm Added 2013-12-03
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Upper : ExcelFunction {
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- return CreateResult(arguments.First().ValueFirst.ToString().ToUpper(), DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Text/Value.cs b/EPPlus/FormulaParsing/Excel/Functions/Text/Value.cs
deleted file mode 100644
index e5ee106..0000000
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Value.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using System.Collections.Generic;
-using System.Globalization;
-using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-
-public class Value : ExcelFunction {
- private readonly string _groupSeparator = CultureInfo
- .CurrentCulture
- .NumberFormat
- .NumberGroupSeparator;
- private readonly string _decimalSeparator = CultureInfo
- .CurrentCulture
- .NumberFormat
- .NumberDecimalSeparator;
- private readonly string _timeSeparator = CultureInfo.CurrentCulture.DateTimeFormat.TimeSeparator;
- private readonly DateValue _dateValueFunc = new();
- private readonly TimeValue _timeValueFunc = new();
-
- public override CompileResult Execute(
- IEnumerable<FunctionArgument> arguments,
- ParsingContext context) {
- ValidateArguments(arguments, 1);
- var val = ArgToString(arguments, 0).TrimEnd(' ');
- double result;
- if (Regex.IsMatch(
- val,
- $"^[\\d]*({Regex.Escape(_groupSeparator)}?[\\d]*)?({Regex.Escape(_decimalSeparator)
- }[\\d]*)?[ ?% ?]?$")) {
- if (val.EndsWith("%")) {
- val = val.TrimEnd('%');
- result = double.Parse(val) / 100;
- } else {
- result = double.Parse(val);
- }
- return CreateResult(result, DataType.Decimal);
- }
- if (double.TryParse(val, NumberStyles.Float, CultureInfo.CurrentCulture, out result)) {
- return CreateResult(result, DataType.Decimal);
- }
- var timeSeparator = Regex.Escape(_timeSeparator);
- if (Regex.IsMatch(
- val,
- @"^[\d]{1,2}" + timeSeparator + @"[\d]{2}(" + timeSeparator + @"[\d]{2})?$")) {
- var timeResult = _timeValueFunc.Execute(val);
- if (timeResult.DataType == DataType.Date) {
- return timeResult;
- }
- }
- var dateResult = _dateValueFunc.Execute(val);
- if (dateResult.DataType == DataType.Date) {
- return dateResult;
- }
- return CreateResult(ExcelErrorValue.Create(eErrorType.Value), DataType.ExcelError);
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Operators/IOperator.cs b/EPPlus/FormulaParsing/Excel/Operators/IOperator.cs
deleted file mode 100644
index 7975cc1..0000000
--- a/EPPlus/FormulaParsing/Excel/Operators/IOperator.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Operators;
-
-public interface IOperator {
- Operators Operator { get; }
-
- CompileResult Apply(CompileResult left, CompileResult right);
-
- int Precedence { get; }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Operators/Operator.cs b/EPPlus/FormulaParsing/Excel/Operators/Operator.cs
deleted file mode 100644
index e6d25e2..0000000
--- a/EPPlus/FormulaParsing/Excel/Operators/Operator.cs
+++ /dev/null
@@ -1,390 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Operators;
-
-public class Operator : IOperator {
- private const int _precedencePercent = 2;
- private const int _precedenceExp = 4;
- private const int _precedenceMultiplyDevide = 6;
- private const int _precedenceAddSubtract = 12;
- private const int _precedenceConcat = 15;
- private const int _precedenceComparison = 25;
-
- private Operator(
- Operators @operator,
- int precedence,
- Func<CompileResult, CompileResult, CompileResult> implementation) {
- _implementation = implementation;
- _precedence = precedence;
- _operator = @operator;
- }
-
- private readonly Func<CompileResult, CompileResult, CompileResult> _implementation;
- private readonly int _precedence;
- private readonly Operators _operator;
-
- int IOperator.Precedence => _precedence;
-
- Operators IOperator.Operator => _operator;
-
- public CompileResult Apply(CompileResult left, CompileResult right) {
- if (left.Result is ExcelErrorValue) {
- return new(left.Result, DataType.ExcelError);
- //throw(new ExcelErrorValueException((ExcelErrorValue)left.Result));
- }
- if (right.Result is ExcelErrorValue) {
- return new(right.Result, DataType.ExcelError);
- //throw(new ExcelErrorValueException((ExcelErrorValue)right.Result));
- }
- return _implementation(left, right);
- }
-
- public override string ToString() {
- return "Operator: " + _operator;
- }
-
- private static IOperator _plus;
-
- public static IOperator Plus {
- get {
- return _plus
- ?? (_plus = new Operator(
- Operators.Plus,
- _precedenceAddSubtract,
- (l, r) => {
- l = l == null || l.Result == null ? new(0, DataType.Integer) : l;
- r = r == null || r.Result == null ? new(0, DataType.Integer) : r;
- if (EitherIsError(l, r, out var errorVal)) {
- return new(errorVal);
- }
- if (l.DataType == DataType.Integer && r.DataType == DataType.Integer) {
- return new(l.ResultNumeric + r.ResultNumeric, DataType.Integer);
- }
- if ((l.IsNumeric
- || l.IsNumericString
- || l.Result is ExcelDataProvider.IRangeInfo)
- && (r.IsNumeric
- || r.IsNumericString
- || r.Result is ExcelDataProvider.IRangeInfo)) {
- return new(l.ResultNumeric + r.ResultNumeric, DataType.Decimal);
- }
- return new(eErrorType.Value);
- }));
- }
- }
-
- private static IOperator _minus;
-
- public static IOperator Minus {
- get {
- return _minus
- ?? (_minus = new Operator(
- Operators.Minus,
- _precedenceAddSubtract,
- (l, r) => {
- l = l == null || l.Result == null ? new(0, DataType.Integer) : l;
- r = r == null || r.Result == null ? new(0, DataType.Integer) : r;
- if (l.DataType == DataType.Integer && r.DataType == DataType.Integer) {
- return new(l.ResultNumeric - r.ResultNumeric, DataType.Integer);
- }
- if ((l.IsNumeric
- || l.IsNumericString
- || l.Result is ExcelDataProvider.IRangeInfo)
- && (r.IsNumeric
- || r.IsNumericString
- || r.Result is ExcelDataProvider.IRangeInfo)) {
- return new(l.ResultNumeric - r.ResultNumeric, DataType.Decimal);
- }
-
- return new(eErrorType.Value);
- }));
- }
- }
-
- private static IOperator _multiply;
-
- public static IOperator Multiply {
- get {
- return _multiply
- ?? (_multiply = new Operator(
- Operators.Multiply,
- _precedenceMultiplyDevide,
- (l, r) => {
- l = l ?? new CompileResult(0, DataType.Integer);
- r = r ?? new CompileResult(0, DataType.Integer);
- if (l.DataType == DataType.Integer && r.DataType == DataType.Integer) {
- return new(l.ResultNumeric * r.ResultNumeric, DataType.Integer);
- }
- if ((l.IsNumeric
- || l.IsNumericString
- || l.Result is ExcelDataProvider.IRangeInfo)
- && (r.IsNumeric
- || r.IsNumericString
- || r.Result is ExcelDataProvider.IRangeInfo)) {
- return new(l.ResultNumeric * r.ResultNumeric, DataType.Decimal);
- }
- return new(eErrorType.Value);
- }));
- }
- }
-
- private static IOperator _divide;
-
- public static IOperator Divide {
- get {
- return _divide
- ?? (_divide = new Operator(
- Operators.Divide,
- _precedenceMultiplyDevide,
- (l, r) => {
- if (!(l.IsNumeric
- || l.IsNumericString
- || l.Result is ExcelDataProvider.IRangeInfo)
- || !(r.IsNumeric
- || r.IsNumericString
- || r.Result is ExcelDataProvider.IRangeInfo)) {
- return new(eErrorType.Value);
- }
- var left = l.ResultNumeric;
- var right = r.ResultNumeric;
- if (Math.Abs(right - 0d) < double.Epsilon) {
- return new(eErrorType.Div0);
- }
- if ((l.IsNumeric
- || l.IsNumericString
- || l.Result is ExcelDataProvider.IRangeInfo)
- && (r.IsNumeric
- || r.IsNumericString
- || r.Result is ExcelDataProvider.IRangeInfo)) {
- return new(left / right, DataType.Decimal);
- }
- return new(eErrorType.Value);
- }));
- }
- }
-
- public static IOperator Exp {
- get {
- return new Operator(
- Operators.Exponentiation,
- _precedenceExp,
- (l, r) => {
- if (l == null && r == null) {
- return new(eErrorType.Value);
- }
- l = l ?? new CompileResult(0, DataType.Integer);
- r = r ?? new CompileResult(0, DataType.Integer);
- if ((l.IsNumeric || l.Result is ExcelDataProvider.IRangeInfo)
- && (r.IsNumeric || r.Result is ExcelDataProvider.IRangeInfo)) {
- return new(Math.Pow(l.ResultNumeric, r.ResultNumeric), DataType.Decimal);
- }
- return new(0d, DataType.Decimal);
- });
- }
- }
-
- public static IOperator Concat {
- get {
- return new Operator(
- Operators.Concat,
- _precedenceConcat,
- (l, r) => {
- l = l ?? new CompileResult(string.Empty, DataType.String);
- r = r ?? new CompileResult(string.Empty, DataType.String);
- var lStr = l.Result != null ? l.ResultValue.ToString() : string.Empty;
- var rStr = r.Result != null ? r.ResultValue.ToString() : string.Empty;
- return new(string.Concat(lStr, rStr), DataType.String);
- });
- }
- }
-
- private static IOperator _greaterThan;
-
- public static IOperator GreaterThan {
- get {
- //return new Operator(Operators.GreaterThan, PrecedenceComparison, (l, r) => new CompileResult(Compare(l, r) > 0, DataType.Boolean));
- return _greaterThan
- ?? (_greaterThan = new Operator(
- Operators.LessThanOrEqual,
- _precedenceComparison,
- (l, r) => Compare(l, r, compRes => compRes > 0)));
- }
- }
-
- private static IOperator _eq;
-
- public static IOperator Eq {
- get {
- //return new Operator(Operators.Equals, PrecedenceComparison, (l, r) => new CompileResult(Compare(l, r) == 0, DataType.Boolean));
- return _eq
- ?? (_eq = new Operator(
- Operators.LessThanOrEqual,
- _precedenceComparison,
- (l, r) => Compare(l, r, compRes => compRes == 0)));
- }
- }
-
- private static IOperator _notEqualsTo;
-
- public static IOperator NotEqualsTo {
- get {
- //return new Operator(Operators.NotEqualTo, PrecedenceComparison, (l, r) => new CompileResult(Compare(l, r) != 0, DataType.Boolean));
- return _notEqualsTo
- ?? (_notEqualsTo = new Operator(
- Operators.LessThanOrEqual,
- _precedenceComparison,
- (l, r) => Compare(l, r, compRes => compRes != 0)));
- }
- }
-
- private static IOperator _greaterThanOrEqual;
-
- public static IOperator GreaterThanOrEqual {
- get {
- //return new Operator(Operators.GreaterThanOrEqual, PrecedenceComparison, (l, r) => new CompileResult(Compare(l, r) >= 0, DataType.Boolean));
- return _greaterThanOrEqual
- ?? (_greaterThanOrEqual = new Operator(
- Operators.LessThanOrEqual,
- _precedenceComparison,
- (l, r) => Compare(l, r, compRes => compRes >= 0)));
- }
- }
-
- private static IOperator _lessThan;
-
- public static IOperator LessThan {
- get {
- //return new Operator(Operators.LessThan, PrecedenceComparison, (l, r) => new CompileResult(Compare(l, r) < 0, DataType.Boolean));
- return _lessThan
- ?? (_lessThan = new Operator(
- Operators.LessThanOrEqual,
- _precedenceComparison,
- (l, r) => Compare(l, r, compRes => compRes < 0)));
- }
- }
-
- public static IOperator LessThanOrEqual {
- get {
- //return new Operator(Operators.LessThanOrEqual, PrecedenceComparison, (l, r) => new CompileResult(Compare(l, r) <= 0, DataType.Boolean));
- return new Operator(
- Operators.LessThanOrEqual,
- _precedenceComparison,
- (l, r) => Compare(l, r, compRes => compRes <= 0));
- }
- }
-
- private static IOperator _percent;
-
- public static IOperator Percent {
- get {
- if (_percent == null) {
- _percent = new Operator(
- Operators.Percent,
- _precedencePercent,
- (l, r) => {
- l = l ?? new CompileResult(0, DataType.Integer);
- r = r ?? new CompileResult(0, DataType.Integer);
- if (l.DataType == DataType.Integer && r.DataType == DataType.Integer) {
- return new(l.ResultNumeric * r.ResultNumeric, DataType.Integer);
- }
- if ((l.IsNumeric || l.Result is ExcelDataProvider.IRangeInfo)
- && (r.IsNumeric || r.Result is ExcelDataProvider.IRangeInfo)) {
- return new(l.ResultNumeric * r.ResultNumeric, DataType.Decimal);
- }
- return new(eErrorType.Value);
- });
- }
- return _percent;
- }
- }
-
- private static object GetObjFromOther(CompileResult obj, CompileResult other) {
- if (obj.Result == null) {
- if (other.DataType == DataType.String) {
- return string.Empty;
- }
- return 0d;
- }
- return obj.ResultValue;
- }
-
- private static CompileResult Compare(
- CompileResult l,
- CompileResult r,
- Func<int, bool> comparison) {
- if (EitherIsError(l, r, out var errorVal)) {
- return new(errorVal);
- }
- object left,
- right;
- left = GetObjFromOther(l, r);
- right = GetObjFromOther(r, l);
- if (ConvertUtil.IsNumeric(left) && ConvertUtil.IsNumeric(right)) {
- var lnum = ConvertUtil.GetValueDouble(left);
- var rnum = ConvertUtil.GetValueDouble(right);
- if (Math.Abs(lnum - rnum) < double.Epsilon) {
- return new(comparison(0), DataType.Boolean);
- }
- var comparisonResult = lnum.CompareTo(rnum);
- return new(comparison(comparisonResult), DataType.Boolean);
- } else {
- var comparisonResult = CompareString(left, right);
- return new(comparison(comparisonResult), DataType.Boolean);
- }
- }
-
- private static int CompareString(object l, object r) {
- var sl = (l ?? "").ToString();
- var sr = (r ?? "").ToString();
- return String.Compare(sl, sr, StringComparison.Ordinal);
- }
-
- private static bool EitherIsError(
- CompileResult l,
- CompileResult r,
- out ExcelErrorValue errorVal) {
- if (l.DataType == DataType.ExcelError) {
- errorVal = (ExcelErrorValue)l.Result;
- return true;
- }
- if (r.DataType == DataType.ExcelError) {
- errorVal = (ExcelErrorValue)r.Result;
- return true;
- }
- errorVal = null;
- return false;
- }
-}
diff --git a/EPPlus/FormulaParsing/Excel/Operators/Operators.cs b/EPPlus/FormulaParsing/Excel/Operators/Operators.cs
deleted file mode 100644
index 04c07e5..0000000
--- a/EPPlus/FormulaParsing/Excel/Operators/Operators.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Operators;
-
-public enum Operators {
- Undefined,
- Concat,
- Plus,
- Minus,
- Multiply,
- Divide,
- Modulus,
- Percent,
- Equals,
- GreaterThan,
- GreaterThanOrEqual,
- LessThan,
- LessThanOrEqual,
- NotEqualTo,
- IntegerDivision,
- Exponentiation,
-}
diff --git a/EPPlus/FormulaParsing/Excel/Operators/OperatorsDict.cs b/EPPlus/FormulaParsing/Excel/Operators/OperatorsDict.cs
deleted file mode 100644
index 2f1cf99..0000000
--- a/EPPlus/FormulaParsing/Excel/Operators/OperatorsDict.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.Excel.Operators;
-
-public class OperatorsDict : Dictionary<string, IOperator> {
- public OperatorsDict() {
- Add("+", Operator.Plus);
- Add("-", Operator.Minus);
- Add("*", Operator.Multiply);
- Add("/", Operator.Divide);
- Add("^", Operator.Exp);
- Add("=", Operator.Eq);
- Add(">", Operator.GreaterThan);
- Add(">=", Operator.GreaterThanOrEqual);
- Add("<", Operator.LessThan);
- Add("<=", Operator.LessThanOrEqual);
- Add("<>", Operator.NotEqualsTo);
- Add("&", Operator.Concat);
- }
-
- private static IDictionary<string, IOperator> _instance;
-
- public static IDictionary<string, IOperator> Instance {
- get {
- if (_instance == null) {
- _instance = new OperatorsDict();
- }
- return _instance;
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/ExcelCalculationOption.cs b/EPPlus/FormulaParsing/ExcelCalculationOption.cs
deleted file mode 100644
index 79d03bc..0000000
--- a/EPPlus/FormulaParsing/ExcelCalculationOption.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-namespace OfficeOpenXml.FormulaParsing;
-
-public class ExcelCalculationOption {
- public bool AllowCirculareReferences { get; set; } = false;
-}
diff --git a/EPPlus/FormulaParsing/ExcelDataProvider.cs b/EPPlus/FormulaParsing/ExcelDataProvider.cs
deleted file mode 100644
index 2c33ece..0000000
--- a/EPPlus/FormulaParsing/ExcelDataProvider.cs
+++ /dev/null
@@ -1,153 +0,0 @@
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-namespace OfficeOpenXml.FormulaParsing;
-
-/// <summary>
-/// This class should be implemented to be able to deliver excel data
-/// to the formula parser.
-/// </summary>
-public abstract class ExcelDataProvider {
- /// <summary>
- /// A range of cells in a worksheet.
- /// </summary>
- public interface IRangeInfo : IEnumerator<ICellInfo>, IEnumerable<ICellInfo> {
- bool IsEmpty { get; }
-
- bool IsMulti { get; }
-
- int GetNCells();
-
- ExcelAddressBase Address { get; }
-
- object GetValue(int row, int col);
-
- object GetOffset(int rowOffset, int colOffset);
-
- ExcelWorksheet Worksheet { get; }
- }
-
- /// <summary>
- /// Information and help methods about a cell
- /// </summary>
- public interface ICellInfo {
- string Address { get; }
-
- int Row { get; }
-
- int Column { get; }
-
- string Formula { get; }
-
- object Value { get; }
-
- double ValueDouble { get; }
-
- double ValueDoubleLogical { get; }
-
- bool IsHiddenRow { get; }
-
- bool IsExcelError { get; }
-
- IList<Token> Tokens { get; }
- }
-
- public interface INameInfo {
- ulong Id { get; set; }
-
- string Worksheet { get; set; }
-
- string Name { get; set; }
-
- string Formula { get; set; }
-
- IList<Token> Tokens { get; }
-
- object Value { get; set; }
- }
-
- /// <summary>
- /// Returns the names of all worksheet names
- /// </summary>
- /// <returns></returns>
- public abstract ExcelNamedRangeCollection GetWorksheetNames(string worksheet);
-
- /// <summary>
- /// Returns all defined names in a workbook
- /// </summary>
- /// <returns></returns>
- public abstract ExcelNamedRangeCollection GetWorkbookNameValues();
-
- /// <summary>
- /// Returns values from the required range.
- /// </summary>
- /// <param name="worksheetName">The name of the worksheet</param>
- /// <param name="row">Row</param>
- /// <param name="column">Column</param>
- /// <param name="address">The reference address</param>
- /// <returns></returns>
- public abstract IRangeInfo GetRange(string worksheetName, int row, int column, string address);
-
- public abstract INameInfo GetName(string worksheet, string name);
-
- public abstract IEnumerable<object> GetRangeValues(string address);
-
- public abstract string GetRangeFormula(string worksheetName, int row, int column);
-
- public abstract List<Token> GetRangeFormulaTokens(string worksheetName, int row, int column);
-
- public abstract bool IsRowHidden(string worksheetName, int row);
-
- ///// <summary>
- ///// Returns a single cell value
- ///// </summary>
- ///// <param name="address"></param>
- ///// <returns></returns>
- //public abstract object GetCellValue(int sheetID, string address);
-
- /// <summary>
- /// Returns a single cell value
- /// </summary>
- /// <param name="sheetName"></param>
- /// <param name="row"></param>
- /// <param name="col"></param>
- /// <returns></returns>
- public abstract object GetCellValue(string sheetName, int row, int col);
-
- ///// <summary>
- ///// Sets the value on the cell
- ///// </summary>
- ///// <param name="address"></param>
- ///// <param name="value"></param>
- //public abstract void SetCellValue(string address, object value);
-
- /// <summary>
- /// Returns the address of the lowest rightmost cell on the worksheet.
- /// </summary>
- /// <param name="worksheet"></param>
- /// <returns></returns>
- public abstract ExcelCellAddress GetDimensionEnd(string worksheet);
-
- /// <summary>
- /// Max number of columns in a worksheet that the Excel data provider can handle.
- /// </summary>
- public abstract int ExcelMaxColumns { get; }
-
- /// <summary>
- /// Max number of rows in a worksheet that the Excel data provider can handle
- /// </summary>
- public abstract int ExcelMaxRows { get; }
-
- public abstract object GetRangeValue(string worksheetName, int row, int column);
-
- public abstract string GetFormat(object value, string format);
-
- public abstract void Reset();
-
- public abstract IRangeInfo GetRange(
- string worksheet,
- int fromRow,
- int fromCol,
- int toRow,
- int toCol);
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/AddressTranslator.cs b/EPPlus/FormulaParsing/ExcelUtilities/AddressTranslator.cs
deleted file mode 100644
index 7816854..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/AddressTranslator.cs
+++ /dev/null
@@ -1,116 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Globalization;
-using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-/// <summary>
-/// Handles translations from Spreadsheet addresses to 0-based numeric index.
-/// </summary>
-public class AddressTranslator {
- public enum RangeCalculationBehaviour {
- FirstPart,
- LastPart,
- }
-
- private readonly ExcelDataProvider _excelDataProvider;
-
- public AddressTranslator(ExcelDataProvider excelDataProvider) {
- Require.That(excelDataProvider).Named("excelDataProvider").IsNotNull();
- _excelDataProvider = excelDataProvider;
- }
-
- /// <summary>
- /// Translates an address in format "A1" to col- and rowindex.
- ///
- /// If the supplied address is a range, the address of the first part will be calculated.
- /// </summary>
- /// <param name="address"></param>
- /// <param name="col"></param>
- /// <param name="row"></param>
- public virtual void ToColAndRow(string address, out int col, out int row) {
- ToColAndRow(address, out col, out row, RangeCalculationBehaviour.FirstPart);
- }
-
- /// <summary>
- /// Translates an address in format "A1" to col- and rowindex.
- /// </summary>
- /// <param name="address"></param>
- /// <param name="col"></param>
- /// <param name="row"></param>
- /// <param name="behaviour"></param>
- public virtual void ToColAndRow(
- string address,
- out int col,
- out int row,
- RangeCalculationBehaviour behaviour) {
- address = address.ToUpper(CultureInfo.InvariantCulture);
- var alphaPart = GetAlphaPart(address);
- col = 0;
- var nLettersInAlphabet = 26;
- for (int x = 0; x < alphaPart.Length; x++) {
- var pos = alphaPart.Length - x - 1;
- var currentNumericValue = GetNumericAlphaValue(alphaPart[x]);
- col += (nLettersInAlphabet * pos * currentNumericValue);
- if (pos == 0) {
- col += currentNumericValue;
- }
- }
- //col--;
- //row = GetIntPart(address) - 1 ?? GetRowIndexByBehaviour(behaviour);
- row = GetIntPart(address) ?? GetRowIndexByBehaviour(behaviour);
- }
-
- private int GetRowIndexByBehaviour(RangeCalculationBehaviour behaviour) {
- if (behaviour == RangeCalculationBehaviour.FirstPart) {
- return 1;
- }
- return _excelDataProvider.ExcelMaxRows;
- }
-
- private int GetNumericAlphaValue(char c) {
- return c - 64;
- }
-
- private string GetAlphaPart(string address) {
- return Regex.Match(address, "[A-Z]+").Value;
- }
-
- private int? GetIntPart(string address) {
- if (Regex.IsMatch(address, "[0-9]+")) {
- return int.Parse(Regex.Match(address, "[0-9]+").Value);
- }
- return null;
- }
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/CellReferenceProvider.cs b/EPPlus/FormulaParsing/ExcelUtilities/CellReferenceProvider.cs
deleted file mode 100644
index 590d3e0..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/CellReferenceProvider.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-public class CellReferenceProvider {
- public virtual IEnumerable<string> GetReferencedAddresses(
- string cellFormula,
- ParsingContext context) {
- var resultCells = new List<string>();
- var r = context.Configuration.Lexer.Tokenize(
- cellFormula,
- context.Scopes.Current.Address.Worksheet);
- var toAddresses = r.Where(x => x.TokenType == TokenType.ExcelAddress);
- foreach (var toAddress in toAddresses) {
- var rangeAddress = context.RangeAddressFactory.Create(toAddress.Value);
- var rangeCells = new List<string>();
- if (rangeAddress.FromRow < rangeAddress.ToRow || rangeAddress.FromCol < rangeAddress.ToCol) {
- for (var col = rangeAddress.FromCol; col <= rangeAddress.ToCol; col++) {
- for (var row = rangeAddress.FromRow; row <= rangeAddress.ToRow; row++) {
- resultCells.Add(context.RangeAddressFactory.Create(col, row).Address);
- }
- }
- } else {
- rangeCells.Add(toAddress.Value);
- }
- resultCells.AddRange(rangeCells);
- }
- return resultCells;
- }
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/ExcelAddressInfo.cs b/EPPlus/FormulaParsing/ExcelUtilities/ExcelAddressInfo.cs
deleted file mode 100644
index c7dd453..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/ExcelAddressInfo.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-public class ExcelAddressInfo {
- private ExcelAddressInfo(string address) {
- var addressOnSheet = address;
- if (address.Contains("!")) {
- var worksheetArr = address.Split('!');
- Worksheet = worksheetArr[0];
- addressOnSheet = worksheetArr[1];
- }
- if (addressOnSheet.Contains(":")) {
- var rangeArr = addressOnSheet.Split(':');
- StartCell = rangeArr[0];
- EndCell = rangeArr[1];
- } else {
- StartCell = addressOnSheet;
- }
- AddressOnSheet = addressOnSheet;
- }
-
- public static ExcelAddressInfo Parse(string address) {
- Require.That(address).Named("address").IsNotNullOrEmpty();
- return new(address);
- }
-
- public string Worksheet { get; private set; } = string.Empty;
-
- public bool WorksheetIsSpecified => !string.IsNullOrEmpty(Worksheet);
-
- public bool IsMultipleCells => !string.IsNullOrEmpty(EndCell);
-
- public string StartCell { get; private set; }
-
- public string EndCell { get; private set; }
-
- public string AddressOnSheet { get; private set; }
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/ExcelAddressUtil.cs b/EPPlus/FormulaParsing/ExcelUtilities/ExcelAddressUtil.cs
deleted file mode 100644
index 03373ce..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/ExcelAddressUtil.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-public static class ExcelAddressUtil {
- private static readonly char[] SheetNameInvalidChars = { '?', ':', '*', '/', '\\' };
-
- public static bool IsValidAddress(string token) {
- int ix;
- if (token[0] == '\'') {
- ix = token.LastIndexOf('\'');
- if (ix > 0 && ix < token.Length - 1 && token[ix + 1] == '!') {
- if (token.IndexOfAny(SheetNameInvalidChars, 1, ix - 1) > 0) {
- return false;
- }
- token = token.Substring(ix + 2);
- } else {
- return false;
- }
- } else if ((ix = token.IndexOf('!')) > 1) {
- if (token.IndexOfAny(SheetNameInvalidChars, 0, token.IndexOf('!')) > 0) {
- return false;
- }
- token = token.Substring(token.IndexOf('!') + 1);
- }
- return ExcelCellBase.IsValidAddress(token);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/ExcelReferenceType.cs b/EPPlus/FormulaParsing/ExcelUtilities/ExcelReferenceType.cs
deleted file mode 100644
index 9651a35..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/ExcelReferenceType.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-public enum ExcelReferenceType {
- AbsoluteRowAndColumn = 1,
- AbsoluteRowRelativeColumn = 2,
- RelativeRowAbsolutColumn = 3,
- RelativeRowAndColumn = 4,
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/ExpressionEvaluator.cs b/EPPlus/FormulaParsing/ExcelUtilities/ExpressionEvaluator.cs
deleted file mode 100644
index df05bb4..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/ExpressionEvaluator.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.Excel.Operators;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-public class ExpressionEvaluator {
- private readonly WildCardValueMatcher _wildCardValueMatcher;
- private readonly CompileResultFactory _compileResultFactory;
-
- public ExpressionEvaluator()
- : this(new(), new()) {}
-
- public ExpressionEvaluator(
- WildCardValueMatcher wildCardValueMatcher,
- CompileResultFactory compileResultFactory) {
- _wildCardValueMatcher = wildCardValueMatcher;
- _compileResultFactory = compileResultFactory;
- }
-
- private string GetNonAlphanumericStartChars(string expression) {
- if (!string.IsNullOrEmpty(expression)) {
- if (Regex.IsMatch(expression, "^([^a-zA-Z0-9]{2})")) {
- return expression.Substring(0, 2);
- }
- if (Regex.IsMatch(expression, "^([^a-zA-Z0-9]{1})")) {
- return expression.Substring(0, 1);
- }
- }
- return null;
- }
-
- private bool EvaluateOperator(object left, object right, IOperator op) {
- var leftResult = _compileResultFactory.Create(left);
- var rightResult = _compileResultFactory.Create(right);
- var result = op.Apply(leftResult, rightResult);
- if (result.DataType != DataType.Boolean) {
- throw new ArgumentException("Illegal operator in expression");
- }
- return (bool)result.Result;
- }
-
- public bool TryConvertToDouble(object op, out double d) {
- if (op is double || op is int) {
- d = Convert.ToDouble(op);
- return true;
- }
- if (op is DateTime time) {
- d = time.ToOADate();
- return true;
- }
- if (op != null) {
- if (double.TryParse(op.ToString(), out d)) {
- return true;
- }
- }
- d = 0;
- return false;
- }
-
- public bool Evaluate(object left, string expression) {
- if (expression == string.Empty) {
- return left == null;
- }
- var operatorCandidate = GetNonAlphanumericStartChars(expression);
- if (!string.IsNullOrEmpty(operatorCandidate) && operatorCandidate != "-") {
- if (OperatorsDict.Instance.TryGetValue(operatorCandidate, out var op)) {
- var right = expression.Replace(operatorCandidate, string.Empty);
- if (left == null && right == string.Empty) {
- return op.Operator == Operators.Equals;
- }
- if (left == null ^ right == string.Empty) {
- return op.Operator == Operators.NotEqualTo;
- }
- bool leftIsNumeric = TryConvertToDouble(left, out var leftNum);
- bool rightIsNumeric = double.TryParse(right, out var rightNum);
- bool rightIsDate = DateTime.TryParse(right, out var date);
- if (leftIsNumeric && rightIsNumeric) {
- return EvaluateOperator(leftNum, rightNum, op);
- }
- if (leftIsNumeric && rightIsDate) {
- return EvaluateOperator(leftNum, date.ToOADate(), op);
- }
- if (leftIsNumeric != rightIsNumeric) {
- return op.Operator == Operators.NotEqualTo;
- }
- return EvaluateOperator(left, right, op);
- }
- }
- return _wildCardValueMatcher.IsMatch(expression, left) == 0;
- }
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependencies.cs b/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependencies.cs
deleted file mode 100644
index b5bc0cf..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependencies.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-public class FormulaDependencies {
- public FormulaDependencies()
- : this(new()) {}
-
- public FormulaDependencies(FormulaDependencyFactory formulaDependencyFactory) {
- _formulaDependencyFactory = formulaDependencyFactory;
- }
-
- private readonly FormulaDependencyFactory _formulaDependencyFactory;
- private readonly Dictionary<string, FormulaDependency> _dependencies = new();
-
- public IEnumerable<KeyValuePair<string, FormulaDependency>> Dependencies => _dependencies;
-
- public void AddFormulaScope(ParsingScope parsingScope) {
- //var dependency = _formulaDependencyFactory.Create(parsingScope);
- //var address = parsingScope.Address.ToString();
- //if (!_dependencies.ContainsKey(address))
- //{
- // _dependencies.Add(address, dependency);
- //}
- //if (parsingScope.Parent != null)
- //{
- // var parentAddress = parsingScope.Parent.Address.ToString();
- // if (_dependencies.ContainsKey(parentAddress))
- // {
- // var parent = _dependencies[parentAddress];
- // parent.AddReferenceTo(parsingScope.Address);
- // dependency.AddReferenceFrom(parent.Address);
- // }
- //}
- }
-
- public void Clear() {
- _dependencies.Clear();
- }
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependency.cs b/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependency.cs
deleted file mode 100644
index d46fca9..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependency.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-public class FormulaDependency {
- public FormulaDependency(ParsingScope scope) {
- ScopeId = scope.ScopeId;
- Address = scope.Address;
- }
-
- public Guid ScopeId { get; private set; }
-
- public RangeAddress Address { get; private set; }
-
- private readonly List<RangeAddress> _referencedBy = new();
-
- private readonly List<RangeAddress> _references = new();
-
- public virtual void AddReferenceFrom(RangeAddress rangeAddress) {
- if (Address.CollidesWith(rangeAddress)
- || _references.Exists(x => x.CollidesWith(rangeAddress))) {
- throw new CircularReferenceException("Circular reference detected at " + rangeAddress);
- }
- _referencedBy.Add(rangeAddress);
- }
-
- public virtual void AddReferenceTo(RangeAddress rangeAddress) {
- if (Address.CollidesWith(rangeAddress)
- || _referencedBy.Exists(x => x.CollidesWith(rangeAddress))) {
- throw new CircularReferenceException("Circular reference detected at " + rangeAddress);
- }
- _references.Add(rangeAddress);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependencyFactory.cs b/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependencyFactory.cs
deleted file mode 100644
index 9eb1f6d..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependencyFactory.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-public class FormulaDependencyFactory {
- public virtual FormulaDependency Create(ParsingScope scope) {
- return new(scope);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/IndexToAddressTranslator.cs b/EPPlus/FormulaParsing/ExcelUtilities/IndexToAddressTranslator.cs
deleted file mode 100644
index 238743a..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/IndexToAddressTranslator.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-public class IndexToAddressTranslator {
- public IndexToAddressTranslator(ExcelDataProvider excelDataProvider)
- : this(excelDataProvider, ExcelReferenceType.AbsoluteRowAndColumn) {}
-
- public IndexToAddressTranslator(
- ExcelDataProvider excelDataProvider,
- ExcelReferenceType referenceType) {
- Require.That(excelDataProvider).Named("excelDataProvider").IsNotNull();
- _excelDataProvider = excelDataProvider;
- _excelReferenceType = referenceType;
- }
-
- private readonly ExcelDataProvider _excelDataProvider;
- private readonly ExcelReferenceType _excelReferenceType;
-
- protected internal static string GetColumnLetter(int iColumnNumber, bool fixedCol) {
- if (iColumnNumber < 1) {
- //throw new Exception("Column number is out of range");
- return "#REF!";
- }
-
- string sCol = "";
- do {
- sCol = ((char)('A' + ((iColumnNumber - 1) % 26))) + sCol;
- iColumnNumber = (iColumnNumber - ((iColumnNumber - 1) % 26)) / 26;
- } while (iColumnNumber > 0);
- return fixedCol ? "$" + sCol : sCol;
- }
-
- public string ToAddress(int col, int row) {
- var fixedCol =
- _excelReferenceType == ExcelReferenceType.AbsoluteRowAndColumn
- || _excelReferenceType == ExcelReferenceType.RelativeRowAbsolutColumn;
- var colString = GetColumnLetter(col, fixedCol);
- return colString + GetRowNumber(row);
- }
-
- private string GetRowNumber(int rowNo) {
- var retVal = rowNo < (_excelDataProvider.ExcelMaxRows) ? rowNo.ToString() : string.Empty;
- if (!string.IsNullOrEmpty(retVal)) {
- switch (_excelReferenceType) {
- case ExcelReferenceType.AbsoluteRowAndColumn:
- case ExcelReferenceType.AbsoluteRowRelativeColumn:
- return "$" + retVal;
- default:
- return retVal;
- }
- }
- return retVal;
- }
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/LookupValueMatcher.cs b/EPPlus/FormulaParsing/ExcelUtilities/LookupValueMatcher.cs
deleted file mode 100644
index d2e0f3e..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/LookupValueMatcher.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-public class LookupValueMatcher : ValueMatcher {
- protected override int CompareObjectToString(object o1, string o2) {
- return IncompatibleOperands;
- }
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/NumericExpressionEvaluator.cs b/EPPlus/FormulaParsing/ExcelUtilities/NumericExpressionEvaluator.cs
deleted file mode 100644
index 174d595..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/NumericExpressionEvaluator.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.Excel.Operators;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-public class NumericExpressionEvaluator {
- private readonly ValueMatcher _valueMatcher;
- private readonly CompileResultFactory _compileResultFactory;
-
- public NumericExpressionEvaluator()
- : this(new(), new()) {}
-
- public NumericExpressionEvaluator(
- ValueMatcher valueMatcher,
- CompileResultFactory compileResultFactory) {
- _valueMatcher = valueMatcher;
- _compileResultFactory = compileResultFactory;
- }
-
- private string GetNonNumericStartChars(string expression) {
- if (!string.IsNullOrEmpty(expression)) {
- if (Regex.IsMatch(expression, @"^([^\d]{2})")) {
- return expression.Substring(0, 2);
- }
- if (Regex.IsMatch(expression, @"^([^\d]{1})")) {
- return expression.Substring(0, 1);
- }
- }
- return null;
- }
-
- public double? OperandAsDouble(object op) {
- if (op is double || op is int) {
- return Convert.ToDouble(op);
- }
- if (op != null) {
- if (double.TryParse(op.ToString(), out var output)) {
- return output;
- }
- }
- return null;
- }
-
- public bool Evaluate(object left, string expression) {
- var operatorCandidate = GetNonNumericStartChars(expression);
- var leftNum = OperandAsDouble(left);
- if (!string.IsNullOrEmpty(operatorCandidate) && leftNum != null) {
- if (OperatorsDict.Instance.TryGetValue(operatorCandidate, out var op)) {
- var numericCandidate = expression.Replace(operatorCandidate, string.Empty);
- if (double.TryParse(numericCandidate, out var d)) {
- var leftResult = _compileResultFactory.Create(leftNum);
- var rightResult = _compileResultFactory.Create(d);
- var result = op.Apply(leftResult, rightResult);
- if (result.DataType != DataType.Boolean) {
- throw new ArgumentException("Illegal operator in expression");
- }
- return (bool)result.Result;
- }
- }
- }
- return _valueMatcher.IsMatch(left, expression) == 0;
- }
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/RangeAddress.cs b/EPPlus/FormulaParsing/ExcelUtilities/RangeAddress.cs
deleted file mode 100644
index b46145c..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/RangeAddress.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-public class RangeAddress {
- internal string Address { get; set; } = string.Empty;
-
- public string Worksheet { get; internal set; }
-
- public int FromCol { get; internal set; }
-
- public int ToCol { get; internal set; }
-
- public int FromRow { get; internal set; }
-
- public int ToRow { get; internal set; }
-
- public override string ToString() {
- return Address;
- }
-
- private static readonly RangeAddress _empty = new();
-
- public static RangeAddress Empty => _empty;
-
- /// <summary>
- /// Returns true if this range collides (full or partly) with the supplied range
- /// </summary>
- /// <param name="other">The range to check</param>
- /// <returns></returns>
- public bool CollidesWith(RangeAddress other) {
- if (other.Worksheet != Worksheet) {
- return false;
- }
- if (other.FromRow > ToRow
- || other.FromCol > ToCol
- || FromRow > other.ToRow
- || FromCol > other.ToCol) {
- return false;
- }
- return true;
- }
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/RangeAddressFactory.cs b/EPPlus/FormulaParsing/ExcelUtilities/RangeAddressFactory.cs
deleted file mode 100644
index 2ff911b..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/RangeAddressFactory.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-public class RangeAddressFactory {
- private readonly ExcelDataProvider _excelDataProvider;
- private readonly IndexToAddressTranslator _indexToAddressTranslator;
-
- public RangeAddressFactory(ExcelDataProvider excelDataProvider)
- : this(
- excelDataProvider,
- new(excelDataProvider),
- new(excelDataProvider, ExcelReferenceType.RelativeRowAndColumn)) {}
-
- public RangeAddressFactory(
- ExcelDataProvider excelDataProvider,
- AddressTranslator addressTranslator,
- IndexToAddressTranslator indexToAddressTranslator) {
- Require.That(excelDataProvider).Named("excelDataProvider").IsNotNull();
- Require.That(addressTranslator).Named("addressTranslator").IsNotNull();
- Require.That(indexToAddressTranslator).Named("indexToAddressTranslator").IsNotNull();
- _excelDataProvider = excelDataProvider;
- _indexToAddressTranslator = indexToAddressTranslator;
- }
-
- public RangeAddress Create(int col, int row) {
- return Create(string.Empty, col, row);
- }
-
- public RangeAddress Create(string worksheetName, int col, int row) {
- return new() {
- Address = _indexToAddressTranslator.ToAddress(col, row),
- Worksheet = worksheetName,
- FromCol = col,
- ToCol = col,
- FromRow = row,
- ToRow = row,
- };
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="worksheetName">will be used if no worksheet name is specified in <paramref name="address"/></param>
- /// <param name="address">address of a range</param>
- /// <returns></returns>
- public RangeAddress Create(string worksheetName, string address) {
- Require.That(address).Named("range").IsNotNullOrEmpty();
- //var addressInfo = ExcelAddressInfo.Parse(address);
- var adr = new ExcelAddressBase(address);
- var sheet = string.IsNullOrEmpty(adr.WorkSheet) ? worksheetName : adr.WorkSheet;
- var dim = _excelDataProvider.GetDimensionEnd(adr.WorkSheet);
- var rangeAddress = new RangeAddress {
- Address = adr.Address,
- Worksheet = sheet,
- FromRow = adr._fromRow,
- FromCol = adr._fromCol,
- ToRow = (dim != null && adr._toRow > dim.Row) ? dim.Row : adr._toRow,
- ToCol = adr._toCol,
- };
- return rangeAddress;
- }
-
- public RangeAddress Create(string range) {
- Require.That(range).Named("range").IsNotNullOrEmpty();
- //var addressInfo = ExcelAddressInfo.Parse(range);
- var adr = new ExcelAddressBase(range);
- var rangeAddress = new RangeAddress {
- Address = adr.Address,
- Worksheet = adr.WorkSheet ?? "",
- FromRow = adr._fromRow,
- FromCol = adr._fromCol,
- ToRow = adr._toRow,
- ToCol = adr._toCol,
- };
- return rangeAddress;
- }
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/ValueMatcher.cs b/EPPlus/FormulaParsing/ExcelUtilities/ValueMatcher.cs
deleted file mode 100644
index 0fb50ba..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/ValueMatcher.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-public class ValueMatcher {
- public const int IncompatibleOperands = -2;
-
- public virtual int IsMatch(object o1, object o2) {
- if (o1 != null && o2 == null) {
- return 1;
- }
- if (o1 == null && o2 != null) {
- return -1;
- }
- if (o1 == null && o2 == null) {
- return 0;
- }
- //Handle ranges and defined names
- o1 = CheckGetRange(o1);
- o2 = CheckGetRange(o2);
-
- if (o1 is string && o2 is string) {
- return CompareStringToString(o1.ToString().ToLower(), o2.ToString().ToLower());
- }
- if (o1.GetType() == typeof(string)) {
- return CompareStringToObject(o1.ToString(), o2);
- }
- if (o2.GetType() == typeof(string)) {
- return CompareObjectToString(o1, o2.ToString());
- }
- return Convert.ToDouble(o1).CompareTo(Convert.ToDouble(o2));
- }
-
- private static object CheckGetRange(object v) {
- if (v is ExcelDataProvider.IRangeInfo info) {
- if (info.GetNCells() > 1) {
- v = ExcelErrorValue.Create(eErrorType.Na);
- }
- v = info.GetOffset(0, 0);
- } else if (v is ExcelDataProvider.INameInfo nameInfo) {
- v = CheckGetRange(nameInfo);
- }
- return v;
- }
-
- protected virtual int CompareStringToString(string s1, string s2) {
- return s1.CompareTo(s2);
- }
-
- protected virtual int CompareStringToObject(string o1, object o2) {
- if (double.TryParse(o1, out var d1)) {
- return d1.CompareTo(Convert.ToDouble(o2));
- }
- return IncompatibleOperands;
- }
-
- protected virtual int CompareObjectToString(object o1, string o2) {
- if (double.TryParse(o2, out var d2)) {
- return Convert.ToDouble(o1).CompareTo(d2);
- }
- return IncompatibleOperands;
- }
-}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/WildCardValueMatcher.cs b/EPPlus/FormulaParsing/ExcelUtilities/WildCardValueMatcher.cs
deleted file mode 100644
index 15a1754..0000000
--- a/EPPlus/FormulaParsing/ExcelUtilities/WildCardValueMatcher.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Text.RegularExpressions;
-
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-public class WildCardValueMatcher : ValueMatcher {
- protected override int CompareStringToString(string s1, string s2) {
- if (s1.Contains("*") || s1.Contains("?")) {
- var regexPattern = Regex.Escape(s1);
- regexPattern = string.Format("^{0}$", regexPattern);
- regexPattern = regexPattern.Replace(@"\*", ".*");
- regexPattern = regexPattern.Replace(@"\?", ".");
- if (Regex.IsMatch(s2, regexPattern)) {
- return 0;
- }
- }
- return base.CompareStringToString(s1, s2);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExcelValues.cs b/EPPlus/FormulaParsing/ExcelValues.cs
deleted file mode 100644
index c15c606..0000000
--- a/EPPlus/FormulaParsing/ExcelValues.cs
+++ /dev/null
@@ -1,206 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Represents the errortypes in excel
-/// </summary>
-public enum eErrorType {
- /// <summary>
- /// Division by zero
- /// </summary>
- Div0,
-
- /// <summary>
- /// Not applicable
- /// </summary>
- Na,
-
- /// <summary>
- /// Name error
- /// </summary>
- Name,
-
- /// <summary>
- /// Null error
- /// </summary>
- Null,
-
- /// <summary>
- /// Num error
- /// </summary>
- Num,
-
- /// <summary>
- /// Reference error
- /// </summary>
- Ref,
-
- /// <summary>
- /// Value error
- /// </summary>
- Value,
-
- // Bug G0004
- /// <summary>
- /// Error error // Google Bug G0004
- /// </summary>
- Error,
-
- // Bug G0005
- /// <summary>
- /// ErrorValueIsNullOrEmpty error // Google Bug G0005
- /// </summary>
- ErrorValueIsNullOrEmpty,
-}
-
-/// <summary>
-/// Represents an Excel error.
-/// </summary>
-/// <seealso cref="eErrorType"/>
-public class ExcelErrorValue {
- /// <summary>
- /// Handles the convertion between <see cref="eErrorType"/> and the string values
- /// used by Excel.
- /// </summary>
- public static class Values {
- public const string Div0 = "#DIV/0!";
- public const string Na = "#N/A";
- public const string Name = "#NAME?";
- public const string Null = "#NULL!";
- public const string Num = "#NUM!";
- public const string Ref = "#REF!";
- public const string Value = "#VALUE!";
- public const string Error = "#ERROR!"; // Bug G0004
- public const string ErrorValueIsNullOrEmpty = "#ERRORVALUEISNULLOREMPTY!"; // Bug G0005
-
- private static readonly Dictionary<string, eErrorType> _values = new() {
- { Div0, eErrorType.Div0 },
- { Na, eErrorType.Na },
- { Name, eErrorType.Name },
- { Null, eErrorType.Null },
- { Num, eErrorType.Num },
- { Ref, eErrorType.Ref },
- { Value, eErrorType.Value },
- { Error, eErrorType.Error }, // Bug G0004
- {
- ErrorValueIsNullOrEmpty,
- eErrorType.ErrorValueIsNullOrEmpty
- } // Bug G0005
- ,
- };
-
- /// <summary>
- /// Returns true if the supplied <paramref name="candidate"/> is an excel error.
- /// </summary>
- /// <param name="candidate"></param>
- /// <returns></returns>
- public static bool IsErrorValue(object candidate) {
- if (candidate == null || !(candidate is ExcelErrorValue)) {
- return false;
- }
- var candidateString = candidate.ToString();
- return (!string.IsNullOrEmpty(candidateString) && _values.ContainsKey(candidateString));
- }
-
- /// <summary>
- /// Returns true if the supplied <paramref name="candidate"/> is an excel error.
- /// </summary>
- /// <param name="candidate"></param>
- /// <returns></returns>
- public static bool StringIsErrorValue(string candidate) {
- return (!string.IsNullOrEmpty(candidate) && _values.ContainsKey(candidate));
- }
-
- /// <summary>
- /// Converts a string to an <see cref="eErrorType"/>
- /// </summary>
- /// <param name="val"></param>
- /// <returns></returns>
- /// <exception cref="ArgumentException">Thrown if the supplied value is not an Excel error</exception>
- public static eErrorType ToErrorType(string val) {
- if (string.IsNullOrEmpty(val) || !_values.ContainsKey(val)) {
- throw new ArgumentException("Invalid error code " + (val ?? "<empty>"));
- }
- return _values[val];
- }
- }
-
- internal static ExcelErrorValue Create(eErrorType errorType) {
- return new(errorType);
- }
-
- internal static ExcelErrorValue Parse(string val) {
- if (string.IsNullOrEmpty(
- val)) // Google Bug G0005
- {
- val = Values.ErrorValueIsNullOrEmpty;
- }
-
- if (Values.StringIsErrorValue(val)) {
- return new(Values.ToErrorType(val));
- }
- if (string.IsNullOrEmpty(val)) {
- throw new ArgumentNullException("val");
- }
- throw new ArgumentException("Not a valid error value: " + val);
- }
-
- private ExcelErrorValue(eErrorType type) {
- Type = type;
- }
-
- /// <summary>
- /// The error type
- /// </summary>
- public eErrorType Type { get; private set; }
-
- /// <summary>
- /// Returns the string representation of the error type
- /// </summary>
- /// <returns></returns>
- public override string ToString() {
- switch (Type) {
- case eErrorType.Div0:
- return Values.Div0;
- case eErrorType.Na:
- return Values.Na;
- case eErrorType.Name:
- return Values.Name;
- case eErrorType.Null:
- return Values.Null;
- case eErrorType.Num:
- return Values.Num;
- case eErrorType.Ref:
- return Values.Ref;
- case eErrorType.Value:
- return Values.Value;
- case eErrorType.Error: // Bug G0004
- return Values.Error;
- case eErrorType.ErrorValueIsNullOrEmpty: // Bug G0005
- return Values.ErrorValueIsNullOrEmpty;
- default:
- throw (new ArgumentException("Invalid errortype"));
- }
- }
-
- public static ExcelErrorValue operator +(object v1, ExcelErrorValue v2) {
- return v2;
- }
-
- public static ExcelErrorValue operator +(ExcelErrorValue v1, ExcelErrorValue v2) {
- return v1;
- }
-
- public override int GetHashCode() {
- return base.GetHashCode();
- }
-
- public override bool Equals(object obj) {
- if (!(obj is ExcelErrorValue value)) {
- return false;
- }
- return value.ToString() == ToString();
- }
-}
diff --git a/EPPlus/FormulaParsing/Exceptions/CircularReferenceException.cs b/EPPlus/FormulaParsing/Exceptions/CircularReferenceException.cs
deleted file mode 100644
index 90dad5b..0000000
--- a/EPPlus/FormulaParsing/Exceptions/CircularReferenceException.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml.FormulaParsing.Exceptions;
-
-public class CircularReferenceException : Exception {
- public CircularReferenceException(string message)
- : base(message) {}
-}
diff --git a/EPPlus/FormulaParsing/Exceptions/ExcelErrorCodes.cs b/EPPlus/FormulaParsing/Exceptions/ExcelErrorCodes.cs
deleted file mode 100644
index 9dc8ea4..0000000
--- a/EPPlus/FormulaParsing/Exceptions/ExcelErrorCodes.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-
-namespace OfficeOpenXml.FormulaParsing.Exceptions;
-
-public class ExcelErrorCodes {
- private ExcelErrorCodes(string code) {
- Code = code;
- }
-
- public string Code { get; private set; }
-
- public override int GetHashCode() {
- return Code.GetHashCode();
- }
-
- public override bool Equals(object obj) {
- if (obj is ExcelErrorCodes codes) {
- return codes.Code.Equals(Code);
- }
- return false;
- }
-
- public static bool operator ==(ExcelErrorCodes c1, ExcelErrorCodes c2) {
- return c1.Code.Equals(c2.Code);
- }
-
- public static bool operator !=(ExcelErrorCodes c1, ExcelErrorCodes c2) {
- return !c1.Code.Equals(c2.Code);
- }
-
- private static readonly IEnumerable<string> Codes = new List<string> {
- Value.Code,
- Name.Code,
- NoValueAvaliable.Code,
- };
-
- public static bool IsErrorCode(object valueToTest) {
- if (valueToTest == null) {
- return false;
- }
- var candidate = valueToTest.ToString();
- if (Codes.FirstOrDefault(x => x == candidate) != null) {
- return true;
- }
- return false;
- }
-
- public static ExcelErrorCodes Value => new("#VALUE!");
-
- public static ExcelErrorCodes Name => new("#NAME?");
-
- public static ExcelErrorCodes NoValueAvaliable => new("#N/A");
-}
diff --git a/EPPlus/FormulaParsing/Exceptions/ExcelErrorValueException.cs b/EPPlus/FormulaParsing/Exceptions/ExcelErrorValueException.cs
deleted file mode 100644
index 4341ed0..0000000
--- a/EPPlus/FormulaParsing/Exceptions/ExcelErrorValueException.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-
-namespace OfficeOpenXml.FormulaParsing.Exceptions;
-
-/// <summary>
-/// This Exception represents an Excel error. When this exception is thrown
-/// from an Excel function, the ErrorValue code will be set as the value of the
-/// parsed cell.
-/// </summary>
-/// <seealso cref="ExcelErrorValue"/>
-public class ExcelErrorValueException : Exception {
- public ExcelErrorValueException(ExcelErrorValue error)
- : this(error.ToString(), error) {}
-
- public ExcelErrorValueException(string message, ExcelErrorValue error)
- : base(message) {
- ErrorValue = error;
- }
-
- public ExcelErrorValueException(eErrorType errorType)
- : this(ExcelErrorValue.Create(errorType)) {}
-
- /// <summary>
- /// The error value
- /// </summary>
- public ExcelErrorValue ErrorValue { get; private set; }
-}
diff --git a/EPPlus/FormulaParsing/Exceptions/UnrecognizedTokenException.cs b/EPPlus/FormulaParsing/Exceptions/UnrecognizedTokenException.cs
deleted file mode 100644
index f4852c0..0000000
--- a/EPPlus/FormulaParsing/Exceptions/UnrecognizedTokenException.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-namespace OfficeOpenXml.FormulaParsing.Exceptions;
-
-public class UnrecognizedTokenException : Exception {
- public UnrecognizedTokenException(Token token)
- : base("Unrecognized token: " + token.Value) {}
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/AtomicExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/AtomicExpression.cs
deleted file mode 100644
index 0ad249e..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/AtomicExpression.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public abstract class AtomicExpression : Expression {
- public AtomicExpression(string expression)
- : base(expression) {}
-
- public override bool IsGroupedExpression => false;
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/BooleanExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/BooleanExpression.cs
deleted file mode 100644
index e61bdf6..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/BooleanExpression.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class BooleanExpression : AtomicExpression {
- private readonly bool? _precompiledValue;
-
- public BooleanExpression(string expression)
- : base(expression) {}
-
- public BooleanExpression(bool value)
- : base(value ? "true" : "false") {
- _precompiledValue = value;
- }
-
- public override CompileResult Compile() {
- var result = _precompiledValue ?? bool.Parse(ExpressionString);
- return new(result, DataType.Boolean);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/CompileResult.cs b/EPPlus/FormulaParsing/ExpressionGraph/CompileResult.cs
deleted file mode 100644
index 90693ee..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/CompileResult.cs
+++ /dev/null
@@ -1,115 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-using System.Globalization;
-using System.Linq;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class CompileResult {
- private static readonly CompileResult _empty = new(null, DataType.Empty);
-
- public static CompileResult Empty => _empty;
-
- public CompileResult(object result, DataType dataType) {
- Result = result;
- DataType = dataType;
- }
-
- public CompileResult(eErrorType errorType) {
- Result = ExcelErrorValue.Create(errorType);
- DataType = DataType.ExcelError;
- }
-
- public CompileResult(ExcelErrorValue errorValue) {
- Require.Argument(errorValue).IsNotNull("errorValue");
- Result = errorValue;
- DataType = DataType.ExcelError;
- }
-
- public object Result { get; private set; }
-
- public object ResultValue {
- get {
- var r = Result as ExcelDataProvider.IRangeInfo;
- if (r == null) {
- return Result;
- }
- return r.GetValue(r.Address._fromRow, r.Address._fromCol);
- }
- }
-
- public double ResultNumeric {
- get {
- if (IsNumeric) {
- return Result == null ? 0 : Convert.ToDouble(Result);
- }
- if (Result is DateTime time) {
- return time.ToOADate();
- }
- if (Result is TimeSpan span) {
- return new DateTime(span.Ticks).ToOADate();
- }
- if (IsNumericString) {
- try {
- return double.Parse(Result.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture);
- } catch (Exception) {
- return 0;
- }
- }
- if (Result is ExcelDataProvider.IRangeInfo info) {
- var c = info.FirstOrDefault();
- if (c == null) {
- return 0;
- }
- return c.ValueDoubleLogical;
- }
- return 0;
- }
- }
-
- public DataType DataType { get; private set; }
-
- public bool IsNumeric =>
- DataType == DataType.Decimal
- || DataType == DataType.Integer
- || DataType == DataType.Empty
- || DataType == DataType.Boolean
- || DataType == DataType.Date;
-
- public bool IsNumericString => DataType == DataType.String && ConvertUtil.IsNumericString(Result);
-
- public bool IsResultOfSubtotal { get; set; }
-
- public bool IsHiddenCell { get; set; }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/CompileResultFactory.cs b/EPPlus/FormulaParsing/ExpressionGraph/CompileResultFactory.cs
deleted file mode 100644
index 4434031..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/CompileResultFactory.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class CompileResultFactory {
- public virtual CompileResult Create(object obj) {
- if ((obj is ExcelDataProvider.INameInfo info)) {
- obj = info.Value;
- }
- if (obj is ExcelDataProvider.IRangeInfo rangeInfo) {
- obj = rangeInfo.GetOffset(0, 0);
- }
- if (obj == null) {
- return new(null, DataType.Empty);
- }
- if (obj.GetType().Equals(typeof(string))) {
- return new(obj, DataType.String);
- }
- if (obj.GetType().Equals(typeof(double)) || obj is decimal) {
- return new(obj, DataType.Decimal);
- }
- if (obj.GetType().Equals(typeof(int)) || obj is long || obj is short) {
- return new(obj, DataType.Integer);
- }
- if (obj.GetType().Equals(typeof(bool))) {
- return new(obj, DataType.Boolean);
- }
- if (obj.GetType().Equals(typeof(ExcelErrorValue))) {
- return new(obj, DataType.ExcelError);
- }
- if (obj.GetType().Equals(typeof(DateTime))) {
- return new(((DateTime)obj).ToOADate(), DataType.Date);
- }
- throw new ArgumentException("Non supported type " + obj.GetType().FullName);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategy.cs b/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategy.cs
deleted file mode 100644
index 0eab4ab..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategy.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.CompileStrategy;
-
-public abstract class CompileStrategy {
- protected readonly Expression _expression;
-
- public CompileStrategy(Expression expression) {
- _expression = expression;
- }
-
- public abstract Expression Compile();
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategyFactory.cs b/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategyFactory.cs
deleted file mode 100644
index 944a3bf..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategyFactory.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using OfficeOpenXml.FormulaParsing.Excel.Operators;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.CompileStrategy;
-
-public class CompileStrategyFactory : ICompileStrategyFactory {
- public CompileStrategy Create(Expression expression) {
- if (expression.Operator.Operator == Operators.Concat) {
- return new StringConcatStrategy(expression);
- }
- return new DefaultCompileStrategy(expression);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/DefaultCompileStrategy.cs b/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/DefaultCompileStrategy.cs
deleted file mode 100644
index 27475d1..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/DefaultCompileStrategy.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.CompileStrategy;
-
-public class DefaultCompileStrategy : CompileStrategy {
- public DefaultCompileStrategy(Expression expression)
- : base(expression) {}
-
- public override Expression Compile() {
- return _expression.MergeWithNext();
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/ICompileStrategyFactory.cs b/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/ICompileStrategyFactory.cs
deleted file mode 100644
index 16a53a4..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/ICompileStrategyFactory.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.CompileStrategy;
-
-public interface ICompileStrategyFactory {
- CompileStrategy Create(Expression expression);
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/StringConcatStrategy.cs b/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/StringConcatStrategy.cs
deleted file mode 100644
index 4403ab8..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/StringConcatStrategy.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.CompileStrategy;
-
-public class StringConcatStrategy : CompileStrategy {
- public StringConcatStrategy(Expression expression)
- : base(expression) {}
-
- public override Expression Compile() {
- var newExp =
- _expression is ExcelAddressExpression
- ? _expression
- : ExpressionConverter.Instance.ToStringExpression(_expression);
- newExp.Prev = _expression.Prev;
- newExp.Next = _expression.Next;
- if (_expression.Prev != null) {
- _expression.Prev.Next = newExp;
- }
- if (_expression.Next != null) {
- _expression.Next.Prev = newExp;
- }
- return newExp.MergeWithNext();
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/ConstantExpressions.cs b/EPPlus/FormulaParsing/ExpressionGraph/ConstantExpressions.cs
deleted file mode 100644
index 00fe9c6..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/ConstantExpressions.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public static class ConstantExpressions {
- public static Expression Percent {
- get { return new ConstantExpression("Percent", () => new(0.01, DataType.Decimal)); }
- }
-}
-
-public class ConstantExpression : AtomicExpression {
- private readonly Func<CompileResult> _factoryMethod;
-
- public ConstantExpression(string title, Func<CompileResult> factoryMethod)
- : base(title) {
- _factoryMethod = factoryMethod;
- }
-
- public override CompileResult Compile() {
- return _factoryMethod();
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/DataType.cs b/EPPlus/FormulaParsing/ExpressionGraph/DataType.cs
deleted file mode 100644
index 4751df3..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/DataType.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public enum DataType {
- Integer,
- Decimal,
- String,
- Boolean,
- Date,
- Time,
- Enumerable,
- LookupArray,
- ExcelAddress,
- ExcelError,
- Empty,
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/DateExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/DateExpression.cs
deleted file mode 100644
index 12e9342..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/DateExpression.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-using System.Globalization;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class DateExpression : AtomicExpression {
- public DateExpression(string expression)
- : base(expression) {}
-
- public override CompileResult Compile() {
- var date = double.Parse(ExpressionString, CultureInfo.InvariantCulture);
- return new(DateTime.FromOADate(date), DataType.Date);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/DecimalExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/DecimalExpression.cs
deleted file mode 100644
index 9d82c5a..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/DecimalExpression.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using System.Globalization;
-
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class DecimalExpression : AtomicExpression {
- private readonly double? _compiledValue;
- private readonly bool _negate;
-
- public DecimalExpression(string expression)
- : this(expression, false) {}
-
- public DecimalExpression(string expression, bool negate)
- : base(expression) {
- _negate = negate;
- }
-
- public DecimalExpression(double compiledValue)
- : base(compiledValue.ToString(CultureInfo.InvariantCulture)) {
- _compiledValue = compiledValue;
- }
-
- public override CompileResult Compile() {
- double result = _compiledValue ?? double.Parse(ExpressionString, CultureInfo.InvariantCulture);
- result = _negate ? result * -1 : result;
- return new(result, DataType.Decimal);
- }
-
- public bool IsNegated => _negate;
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/EnumerableExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/EnumerableExpression.cs
deleted file mode 100644
index 56b0fa8..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/EnumerableExpression.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class EnumerableExpression : Expression {
- public EnumerableExpression()
- : this(new ExpressionCompiler()) {}
-
- public EnumerableExpression(IExpressionCompiler expressionCompiler) {
- _expressionCompiler = expressionCompiler;
- }
-
- private readonly IExpressionCompiler _expressionCompiler;
-
- public override bool IsGroupedExpression => false;
-
- public override Expression PrepareForNextChild() {
- return this;
- }
-
- public override CompileResult Compile() {
- var result = new List<object>();
- foreach (var childExpression in Children) {
- result.Add(_expressionCompiler.Compile(new List<Expression> { childExpression }).Result);
- }
- return new(result, DataType.Enumerable);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/ExcelAddressExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/ExcelAddressExpression.cs
deleted file mode 100644
index 8e409b7..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/ExcelAddressExpression.cs
+++ /dev/null
@@ -1,111 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class ExcelAddressExpression : AtomicExpression {
- private readonly ExcelDataProvider _excelDataProvider;
- private readonly ParsingContext _parsingContext;
- private readonly RangeAddressFactory _rangeAddressFactory;
- private readonly bool _negate;
-
- public ExcelAddressExpression(
- string expression,
- ExcelDataProvider excelDataProvider,
- ParsingContext parsingContext)
- : this(expression, excelDataProvider, parsingContext, new(excelDataProvider), false) {}
-
- public ExcelAddressExpression(
- string expression,
- ExcelDataProvider excelDataProvider,
- ParsingContext parsingContext,
- bool negate)
- : this(expression, excelDataProvider, parsingContext, new(excelDataProvider), negate) {}
-
- public ExcelAddressExpression(
- string expression,
- ExcelDataProvider excelDataProvider,
- ParsingContext parsingContext,
- RangeAddressFactory rangeAddressFactory,
- bool negate)
- : base(expression) {
- Require.That(excelDataProvider).Named("excelDataProvider").IsNotNull();
- Require.That(parsingContext).Named("parsingContext").IsNotNull();
- Require.That(rangeAddressFactory).Named("rangeAddressFactory").IsNotNull();
- _excelDataProvider = excelDataProvider;
- _parsingContext = parsingContext;
- _rangeAddressFactory = rangeAddressFactory;
- _negate = negate;
- }
-
- public override bool IsGroupedExpression => false;
-
- public override CompileResult Compile() {
- if (ParentIsLookupFunction) {
- return new(ExpressionString, DataType.ExcelAddress);
- }
- return CompileRangeValues();
- }
-
- private CompileResult CompileRangeValues() {
- var c = _parsingContext.Scopes.Current;
- var result = _excelDataProvider.GetRange(
- c.Address.Worksheet,
- c.Address.FromRow,
- c.Address.FromCol,
- ExpressionString);
-
- if (result == null || result.IsEmpty) {
- return CompileResult.Empty;
- }
- if (result.Address.Rows > 1 || result.Address.Columns > 1) {
- return new(result, DataType.Enumerable);
- }
- return CompileSingleCell(result);
- }
-
- private CompileResult CompileSingleCell(ExcelDataProvider.IRangeInfo result) {
- var cell = result.First();
- var factory = new CompileResultFactory();
- var compileResult = factory.Create(cell.Value);
- if (_negate && compileResult.IsNumeric) {
- compileResult = new(compileResult.ResultNumeric * -1, compileResult.DataType);
- }
- compileResult.IsHiddenCell = cell.IsHiddenRow;
- return compileResult;
- }
-
- public bool IsNegated => _negate;
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/ExcelErrorExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/ExcelErrorExpression.cs
deleted file mode 100644
index 44770f8..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/ExcelErrorExpression.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class ExcelErrorExpression : Expression {
- private readonly ExcelErrorValue _error;
-
- public ExcelErrorExpression(string expression, ExcelErrorValue error)
- : base(expression) {
- _error = error;
- }
-
- public ExcelErrorExpression(ExcelErrorValue error)
- : this(error.ToString(), error) {}
-
- public override bool IsGroupedExpression => false;
-
- public override CompileResult Compile() {
- return new(_error, DataType.ExcelError);
- //if (ParentIsLookupFunction)
- //{
- // return new CompileResult(ExpressionString, DataType.ExcelError);
- //}
- //else
- //{
- // return CompileRangeValues();
- //}
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/Expression.cs b/EPPlus/FormulaParsing/ExpressionGraph/Expression.cs
deleted file mode 100644
index bdab90a..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/Expression.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Excel.Operators;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public abstract class Expression {
- public string ExpressionString { get; private set; }
-
- private readonly List<Expression> _children = new();
-
- public IEnumerable<Expression> Children => _children;
-
- public Expression Next { get; set; }
-
- public Expression Prev { get; set; }
-
- public IOperator Operator { get; set; }
-
- public abstract bool IsGroupedExpression { get; }
-
- public Expression() {}
-
- public Expression(string expression) {
- ExpressionString = expression;
- Operator = null;
- }
-
- public virtual bool ParentIsLookupFunction { get; set; }
-
- public virtual bool HasChildren => _children.Any();
-
- public virtual Expression PrepareForNextChild() {
- return this;
- }
-
- public virtual Expression AddChild(Expression child) {
- if (_children.Any()) {
- var last = _children.Last();
- child.Prev = last;
- last.Next = child;
- }
- _children.Add(child);
- return child;
- }
-
- public virtual Expression MergeWithNext() {
- Expression expression;
- if (Next != null && Operator != null) {
- var result = Operator.Apply(Compile(), Next.Compile());
- expression = ExpressionConverter.Instance.FromCompileResult(result);
- if (expression is ExcelErrorExpression) {
- expression.Next = null;
- expression.Prev = null;
- return expression;
- }
- if (Next != null) {
- expression.Operator = Next.Operator;
- } else {
- expression.Operator = null;
- }
- expression.Next = Next.Next;
- if (expression.Next != null) {
- expression.Next.Prev = expression;
- }
- expression.Prev = Prev;
- } else {
- throw (new FormatException("Invalid formula syntax. Operator missing expression."));
- }
- if (Prev != null) {
- Prev.Next = expression;
- }
- return expression;
- }
-
- public abstract CompileResult Compile();
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/ExpressionCompiler.cs b/EPPlus/FormulaParsing/ExpressionGraph/ExpressionCompiler.cs
deleted file mode 100644
index e29c4f2..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/ExpressionCompiler.cs
+++ /dev/null
@@ -1,145 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph.CompileStrategy;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class ExpressionCompiler : IExpressionCompiler {
- private IEnumerable<Expression> _expressions;
- private readonly IExpressionConverter _expressionConverter;
- private readonly ICompileStrategyFactory _compileStrategyFactory;
-
- public ExpressionCompiler()
- : this(new ExpressionConverter(), new CompileStrategyFactory()) {}
-
- public ExpressionCompiler(
- IExpressionConverter expressionConverter,
- ICompileStrategyFactory compileStrategyFactory) {
- _expressionConverter = expressionConverter;
- _compileStrategyFactory = compileStrategyFactory;
- }
-
- public CompileResult Compile(IEnumerable<Expression> expressions) {
- _expressions = expressions;
- return PerformCompilation();
- }
-
- public CompileResult Compile(
- string worksheet,
- int row,
- int column,
- IEnumerable<Expression> expressions) {
- _expressions = expressions;
- return PerformCompilation(worksheet, row, column);
- }
-
- private CompileResult PerformCompilation(string worksheet = "", int row = -1, int column = -1) {
- var compiledExpressions = HandleGroupedExpressions();
- while (compiledExpressions.Any(x => x.Operator != null)) {
- var prec = FindLowestPrecedence();
- compiledExpressions = HandlePrecedenceLevel(prec);
- }
- if (_expressions.Any()) {
- return compiledExpressions.First().Compile();
- }
- return CompileResult.Empty;
- }
-
- private IEnumerable<Expression> HandleGroupedExpressions() {
- if (!_expressions.Any()) {
- return Enumerable.Empty<Expression>();
- }
- var first = _expressions.First();
- var groupedExpressions = _expressions.Where(x => x.IsGroupedExpression);
- foreach (var groupedExpression in groupedExpressions) {
- var result = groupedExpression.Compile();
- if (result == CompileResult.Empty) {
- continue;
- }
- var newExp = _expressionConverter.FromCompileResult(result);
- newExp.Operator = groupedExpression.Operator;
- newExp.Prev = groupedExpression.Prev;
- newExp.Next = groupedExpression.Next;
- if (groupedExpression.Prev != null) {
- groupedExpression.Prev.Next = newExp;
- }
- if (groupedExpression.Next != null) {
- groupedExpression.Next.Prev = newExp;
- }
- if (groupedExpression == first) {
- first = newExp;
- }
- }
- return RefreshList(first);
- }
-
- private IEnumerable<Expression> HandlePrecedenceLevel(int precedence) {
- var first = _expressions.First();
- var expressionsToHandle = _expressions.Where(x =>
- x.Operator != null && x.Operator.Precedence == precedence);
- var last = expressionsToHandle.Last();
- var expression = expressionsToHandle.First();
- do {
- var strategy = _compileStrategyFactory.Create(expression);
- var compiledExpression = strategy.Compile();
- if (compiledExpression is ExcelErrorExpression) {
- return RefreshList(compiledExpression);
- }
- if (expression == first) {
- first = compiledExpression;
- }
-
- expression = compiledExpression;
- } while (expression != null
- && expression.Operator != null
- && expression.Operator.Precedence == precedence);
- return RefreshList(first);
- }
-
- private int FindLowestPrecedence() {
- return _expressions.Where(x => x.Operator != null).Min(x => x.Operator.Precedence);
- }
-
- private IEnumerable<Expression> RefreshList(Expression first) {
- var resultList = new List<Expression>();
- var exp = first;
- resultList.Add(exp);
- while (exp.Next != null) {
- resultList.Add(exp.Next);
- exp = exp.Next;
- }
- _expressions = resultList;
- return resultList;
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/ExpressionConverter.cs b/EPPlus/FormulaParsing/ExpressionGraph/ExpressionConverter.cs
deleted file mode 100644
index 339b757..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/ExpressionConverter.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class ExpressionConverter : IExpressionConverter {
- public StringExpression ToStringExpression(Expression expression) {
- var result = expression.Compile();
- var newExp = new StringExpression(result.Result.ToString());
- newExp.Operator = expression.Operator;
- return newExp;
- }
-
- public Expression FromCompileResult(CompileResult compileResult) {
- switch (compileResult.DataType) {
- case DataType.Integer:
- return compileResult.Result is string
- ? new(compileResult.Result.ToString())
- : new IntegerExpression(Convert.ToDouble(compileResult.Result));
- case DataType.String:
- return new StringExpression(compileResult.Result.ToString());
- case DataType.Decimal:
- return compileResult.Result is string
- ? new(compileResult.Result.ToString())
- : new DecimalExpression(((double)compileResult.Result));
- case DataType.Boolean:
- return compileResult.Result is string
- ? new(compileResult.Result.ToString())
- : new BooleanExpression((bool)compileResult.Result);
- //case DataType.Enumerable:
- // return
- case DataType.ExcelError:
- //throw (new OfficeOpenXml.FormulaParsing.Exceptions.ExcelErrorValueException((ExcelErrorValue)compileResult.Result)); //Added JK
- return compileResult.Result is string
- ? new(
- compileResult.Result.ToString(),
- ExcelErrorValue.Parse(compileResult.Result.ToString()))
- : new ExcelErrorExpression((ExcelErrorValue)compileResult.Result);
- case DataType.Empty:
- return new IntegerExpression(0); //Added JK
- }
- return null;
- }
-
- private static IExpressionConverter _instance;
-
- public static IExpressionConverter Instance {
- get {
- if (_instance == null) {
- _instance = new ExpressionConverter();
- }
- return _instance;
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/ExpressionFactory.cs b/EPPlus/FormulaParsing/ExpressionGraph/ExpressionFactory.cs
deleted file mode 100644
index 742d50c..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/ExpressionFactory.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class ExpressionFactory : IExpressionFactory {
- private readonly ExcelDataProvider _excelDataProvider;
- private readonly ParsingContext _parsingContext;
-
- public ExpressionFactory(ExcelDataProvider excelDataProvider, ParsingContext context) {
- _excelDataProvider = excelDataProvider;
- _parsingContext = context;
- }
-
- public Expression Create(Token token) {
- switch (token.TokenType) {
- case TokenType.Integer:
- return new IntegerExpression(token.Value, token.IsNegated);
- case TokenType.String:
- return new StringExpression(token.Value);
- case TokenType.Decimal:
- return new DecimalExpression(token.Value, token.IsNegated);
- case TokenType.Boolean:
- return new BooleanExpression(token.Value);
- case TokenType.ExcelAddress:
- return new ExcelAddressExpression(
- token.Value,
- _excelDataProvider,
- _parsingContext,
- token.IsNegated);
- case TokenType.InvalidReference:
- return new ExcelErrorExpression(token.Value, ExcelErrorValue.Create(eErrorType.Ref));
- case TokenType.NumericError:
- return new ExcelErrorExpression(token.Value, ExcelErrorValue.Create(eErrorType.Num));
- case TokenType.ValueDataTypeError:
- return new ExcelErrorExpression(token.Value, ExcelErrorValue.Create(eErrorType.Value));
- case TokenType.Null:
- return new ExcelErrorExpression(token.Value, ExcelErrorValue.Create(eErrorType.Null));
- case TokenType.NameValue:
- return new NamedValueExpression(token.Value, _parsingContext);
- default:
- return new StringExpression(token.Value);
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/ExpressionGraph.cs b/EPPlus/FormulaParsing/ExpressionGraph/ExpressionGraph.cs
deleted file mode 100644
index 98fe430..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/ExpressionGraph.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class ExpressionGraph {
- private readonly List<Expression> _expressions = new();
-
- public IEnumerable<Expression> Expressions => _expressions;
-
- public Expression Current { get; private set; }
-
- public Expression Add(Expression expression) {
- _expressions.Add(expression);
- if (Current != null) {
- Current.Next = expression;
- expression.Prev = Current;
- }
- Current = expression;
- return expression;
- }
-
- public void Reset() {
- _expressions.Clear();
- Current = null;
- }
-
- public void Remove(Expression item) {
- if (item == Current) {
- Current = item.Prev ?? item.Next;
- }
- _expressions.Remove(item);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/ExpressionGraphBuilder.cs b/EPPlus/FormulaParsing/ExpressionGraph/ExpressionGraphBuilder.cs
deleted file mode 100644
index 156b425..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/ExpressionGraphBuilder.cs
+++ /dev/null
@@ -1,196 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Excel.Operators;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class ExpressionGraphBuilder : IExpressionGraphBuilder {
- private readonly ExpressionGraph _graph = new();
- private readonly IExpressionFactory _expressionFactory;
- private readonly ParsingContext _parsingContext;
- private int _tokenIndex;
- private bool _negateNextExpression;
-
- public ExpressionGraphBuilder(ExcelDataProvider excelDataProvider, ParsingContext parsingContext)
- : this(new ExpressionFactory(excelDataProvider, parsingContext), parsingContext) {}
-
- public ExpressionGraphBuilder(
- IExpressionFactory expressionFactory,
- ParsingContext parsingContext) {
- _expressionFactory = expressionFactory;
- _parsingContext = parsingContext;
- }
-
- public ExpressionGraph Build(IEnumerable<Token> tokens) {
- _tokenIndex = 0;
- _graph.Reset();
- var tokensArr = tokens != null ? tokens.ToArray() : new Token[0];
- BuildUp(tokensArr, null);
- return _graph;
- }
-
- private void BuildUp(Token[] tokens, Expression parent) {
- while (_tokenIndex < tokens.Length) {
- var token = tokens[_tokenIndex];
- if (token.TokenType == TokenType.Operator
- && OperatorsDict.Instance.TryGetValue(token.Value, out var op)) {
- SetOperatorOnExpression(parent, op);
- } else if (token.TokenType == TokenType.Function) {
- BuildFunctionExpression(tokens, parent, token.Value);
- } else if (token.TokenType == TokenType.OpeningEnumerable) {
- _tokenIndex++;
- BuildEnumerableExpression(tokens, parent);
- } else if (token.TokenType == TokenType.OpeningParenthesis) {
- _tokenIndex++;
- BuildGroupExpression(tokens, parent);
- //if (parent is FunctionExpression)
- //{
- // return;
- //}
- } else if (token.TokenType == TokenType.ClosingParenthesis
- || token.TokenType == TokenType.ClosingEnumerable) {
- break;
- } else if (token.TokenType == TokenType.Negator) {
- _negateNextExpression = true;
- } else if (token.TokenType == TokenType.Percent) {
- SetOperatorOnExpression(parent, Operator.Percent);
- if (parent == null) {
- _graph.Add(ConstantExpressions.Percent);
- } else {
- parent.AddChild(ConstantExpressions.Percent);
- }
- } else {
- CreateAndAppendExpression(ref parent, token);
- }
- _tokenIndex++;
- }
- }
-
- private void BuildEnumerableExpression(Token[] tokens, Expression parent) {
- if (parent == null) {
- _graph.Add(new EnumerableExpression());
- BuildUp(tokens, _graph.Current);
- } else {
- var enumerableExpression = new EnumerableExpression();
- parent.AddChild(enumerableExpression);
- BuildUp(tokens, enumerableExpression);
- }
- }
-
- private void CreateAndAppendExpression(ref Expression parent, Token token) {
- if (IsWaste(token)) {
- return;
- }
- if (parent != null
- && (token.TokenType == TokenType.Comma || token.TokenType == TokenType.SemiColon)) {
- parent = parent.PrepareForNextChild();
- return;
- }
- if (_negateNextExpression) {
- token.Negate();
- _negateNextExpression = false;
- }
- var expression = _expressionFactory.Create(token);
- if (parent == null) {
- _graph.Add(expression);
- } else {
- parent.AddChild(expression);
- }
- }
-
- private bool IsWaste(Token token) {
- if (token.TokenType == TokenType.String) {
- return true;
- }
- return false;
- }
-
- private void BuildFunctionExpression(Token[] tokens, Expression parent, string funcName) {
- if (parent == null) {
- _graph.Add(new FunctionExpression(funcName, _parsingContext, _negateNextExpression));
- _negateNextExpression = false;
- HandleFunctionArguments(tokens, _graph.Current);
- } else {
- var func = new FunctionExpression(funcName, _parsingContext, _negateNextExpression);
- _negateNextExpression = false;
- parent.AddChild(func);
- HandleFunctionArguments(tokens, func);
- }
- }
-
- private void HandleFunctionArguments(Token[] tokens, Expression function) {
- _tokenIndex++;
- var token = tokens.ElementAt(_tokenIndex);
- if (token.TokenType != TokenType.OpeningParenthesis) {
- throw new ExcelErrorValueException(eErrorType.Value);
- }
- _tokenIndex++;
- BuildUp(tokens, function.Children.First());
- }
-
- private void BuildGroupExpression(Token[] tokens, Expression parent) {
- if (parent == null) {
- _graph.Add(new GroupExpression(_negateNextExpression));
- _negateNextExpression = false;
- BuildUp(tokens, _graph.Current);
- } else {
- if (parent.IsGroupedExpression || parent is FunctionArgumentExpression) {
- var newGroupExpression = new GroupExpression(_negateNextExpression);
- _negateNextExpression = false;
- parent.AddChild(newGroupExpression);
- BuildUp(tokens, newGroupExpression);
- }
- BuildUp(tokens, parent);
- }
- }
-
- private void SetOperatorOnExpression(Expression parent, IOperator op) {
- if (parent == null) {
- _graph.Current.Operator = op;
- } else {
- Expression candidate;
- if (parent is FunctionArgumentExpression) {
- candidate = parent.Children.Last();
- } else {
- candidate = parent.Children.Last();
- if (candidate is FunctionArgumentExpression) {
- candidate = candidate.Children.Last();
- }
- }
- candidate.Operator = op;
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/FunctionArgumentExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/FunctionArgumentExpression.cs
deleted file mode 100644
index 0123e1d..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionArgumentExpression.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class FunctionArgumentExpression : GroupExpression {
- private readonly Expression _function;
-
- public FunctionArgumentExpression(Expression function)
- : base(false) {
- _function = function;
- }
-
- public override bool ParentIsLookupFunction {
- get => base.ParentIsLookupFunction;
- set {
- base.ParentIsLookupFunction = value;
- foreach (var child in Children) {
- child.ParentIsLookupFunction = value;
- }
- }
- }
-
- public override bool IsGroupedExpression => false;
-
- public override Expression PrepareForNextChild() {
- return _function.PrepareForNextChild();
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/DefaultCompiler.cs b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/DefaultCompiler.cs
deleted file mode 100644
index ebc2918..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/DefaultCompiler.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.Excel;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
-
-public class DefaultCompiler : FunctionCompiler {
- public DefaultCompiler(ExcelFunction function)
- : base(function) {}
-
- public override CompileResult Compile(IEnumerable<Expression> children, ParsingContext context) {
- var args = new List<FunctionArgument>();
- Function.BeforeInvoke(context);
- foreach (var child in children) {
- var compileResult = child.Compile();
- if (compileResult.IsResultOfSubtotal) {
- var arg = new FunctionArgument(compileResult.Result);
- arg.SetExcelStateFlag(ExcelCellState.IsResultOfSubtotal);
- args.Add(arg);
- } else {
- BuildFunctionArguments(compileResult.Result, args);
- }
- }
- return Function.Execute(args, context);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/ErrorHandlingFunctionCompiler.cs b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/ErrorHandlingFunctionCompiler.cs
deleted file mode 100644
index f93b6ce..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/ErrorHandlingFunctionCompiler.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
-
-public class ErrorHandlingFunctionCompiler : FunctionCompiler {
- public ErrorHandlingFunctionCompiler(ExcelFunction function)
- : base(function) {}
-
- public override CompileResult Compile(IEnumerable<Expression> children, ParsingContext context) {
- var args = new List<FunctionArgument>();
- Function.BeforeInvoke(context);
- foreach (var child in children) {
- try {
- var arg = child.Compile();
- BuildFunctionArguments(arg?.Result, args);
- } catch (ExcelErrorValueException efe) {
- return ((ErrorHandlingFunction)Function).HandleError(efe.ErrorValue.ToString());
- } catch // (Exception e)
- {
- return ((ErrorHandlingFunction)Function).HandleError(ExcelErrorValue.Values.Value);
- }
- }
- return Function.Execute(args, context);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompiler.cs b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompiler.cs
deleted file mode 100644
index 8be6020..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompiler.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
-
-public abstract class FunctionCompiler {
- protected ExcelFunction Function { get; private set; }
-
- public FunctionCompiler(ExcelFunction function) {
- Require.That(function).Named("function").IsNotNull();
- Function = function;
- }
-
- protected void BuildFunctionArguments(object result, List<FunctionArgument> args) {
- if (result is IEnumerable<object> objects && !(objects is ExcelDataProvider.IRangeInfo)) {
- var argList = new List<FunctionArgument>();
- foreach (var arg in objects) {
- BuildFunctionArguments(arg, argList);
- }
- args.Add(new(argList));
- } else {
- args.Add(new(result));
- }
- }
-
- public abstract CompileResult Compile(IEnumerable<Expression> children, ParsingContext context);
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompilerFactory.cs b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompilerFactory.cs
deleted file mode 100644
index 0f54dcc..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompilerFactory.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
-
-public class FunctionCompilerFactory {
- private readonly Dictionary<Type, FunctionCompiler> _specialCompilers = new();
-
- public FunctionCompilerFactory(FunctionRepository repository) {
- _specialCompilers.Add(typeof(If), new IfFunctionCompiler(repository.GetFunction("if")));
- _specialCompilers.Add(
- typeof(IfError),
- new IfErrorFunctionCompiler(repository.GetFunction("iferror")));
- _specialCompilers.Add(typeof(IfNa), new IfNaFunctionCompiler(repository.GetFunction("ifna")));
- }
-
- private FunctionCompiler GetCompilerByType(ExcelFunction function) {
- var funcType = function.GetType();
- if (_specialCompilers.ContainsKey(funcType)) {
- return _specialCompilers[funcType];
- }
- return new DefaultCompiler(function);
- }
-
- public virtual FunctionCompiler Create(ExcelFunction function) {
- if (function.IsLookupFuction) {
- return new LookupFunctionCompiler(function);
- }
- if (function.IsErrorHandlingFunction) {
- return new ErrorHandlingFunctionCompiler(function);
- }
- return GetCompilerByType(function);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfErrorFunctionCompiler.cs b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfErrorFunctionCompiler.cs
deleted file mode 100644
index e809ea5..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfErrorFunctionCompiler.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
-
-public class IfErrorFunctionCompiler : FunctionCompiler {
- public IfErrorFunctionCompiler(ExcelFunction function)
- : base(function) {
- Require.That(function).Named("function").IsNotNull();
- }
-
- public override CompileResult Compile(IEnumerable<Expression> children, ParsingContext context) {
- if (children.Count() != 2) {
- throw new ExcelErrorValueException(eErrorType.Value);
- }
- var args = new List<FunctionArgument>();
- Function.BeforeInvoke(context);
- var firstChild = children.First();
- var lastChild = children.ElementAt(1);
- try {
- var result = firstChild.Compile();
- if (result.DataType == DataType.ExcelError) {
- args.Add(new(lastChild.Compile().Result));
- } else {
- args.Add(new(result.Result));
- }
- } catch (ExcelErrorValueException) {
- args.Add(new(lastChild.Compile().Result));
- }
- return Function.Execute(args, context);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfFunctionCompiler.cs b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfFunctionCompiler.cs
deleted file mode 100644
index 15d262b..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfFunctionCompiler.cs
+++ /dev/null
@@ -1,103 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2014-01-27
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.Utilities;
-using OfficeOpenXml.Utils;
-using Require = OfficeOpenXml.FormulaParsing.Utilities.Require;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
-
-/// <summary>
-/// Why do the If function require a compiler of its own you might ask;)
-///
-/// It is because it only needs to evaluate one of the two last expressions. This
-/// compiler handles this - it ignores the irrelevant expression.
-/// </summary>
-public class IfFunctionCompiler : FunctionCompiler {
- public IfFunctionCompiler(ExcelFunction function)
- : base(function) {
- Require.That(function).Named("function").IsNotNull();
- if (!(function is If)) {
- throw new ArgumentException("function must be of type If");
- }
- }
-
- public override CompileResult Compile(IEnumerable<Expression> children, ParsingContext context) {
- if (children.Count() < 3) {
- throw new ExcelErrorValueException(eErrorType.Value);
- }
- var args = new List<FunctionArgument>();
- Function.BeforeInvoke(context);
- var firstChild = children.ElementAt(0);
- var v = firstChild.Compile().Result;
-
- /**** Handle names and ranges ****/
- if (v is ExcelDataProvider.INameInfo info) {
- v = info.Value;
- }
-
- if (v is ExcelDataProvider.IRangeInfo rangeInfo) {
- if (rangeInfo.GetNCells() > 1) {
- throw (new ArgumentException("Logical can't be more than one cell"));
- }
- v = rangeInfo.GetOffset(0, 0);
- }
- bool boolVal;
- if (v is bool b) {
- boolVal = b;
- } else {
- if (ConvertUtil.IsNumeric(v)) {
- boolVal = ConvertUtil.GetValueDouble(v) != 0;
- } else {
- throw (new ArgumentException("Invalid logical test"));
- }
- }
- /**** End Handle names and ranges ****/
-
- args.Add(new(boolVal));
- if (boolVal) {
- var val = children.ElementAt(1).Compile().Result;
- args.Add(new(val));
- args.Add(new(null));
- } else {
- var val = children.ElementAt(2).Compile().Result;
- args.Add(new(null));
- args.Add(new(val));
- }
- return Function.Execute(args, context);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfNaFunctionCompiler.cs b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfNaFunctionCompiler.cs
deleted file mode 100644
index 55f15b2..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfNaFunctionCompiler.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
-
-public class IfNaFunctionCompiler : FunctionCompiler {
- public IfNaFunctionCompiler(ExcelFunction function)
- : base(function) {}
-
- public override CompileResult Compile(IEnumerable<Expression> children, ParsingContext context) {
- if (children.Count() != 2) {
- throw new ExcelErrorValueException(eErrorType.Value);
- }
- var args = new List<FunctionArgument>();
- Function.BeforeInvoke(context);
- var firstChild = children.First();
- var lastChild = children.ElementAt(1);
- try {
- var result = firstChild.Compile();
- if (result.DataType == DataType.ExcelError
- && (Equals(result.Result, ExcelErrorValue.Create(eErrorType.Na)))) {
- args.Add(new(lastChild.Compile().Result));
- } else {
- args.Add(new(result.Result));
- }
- } catch (ExcelErrorValueException) {
- args.Add(new(lastChild.Compile().Result));
- }
- return Function.Execute(args, context);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/LookupFunctionCompiler.cs b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/LookupFunctionCompiler.cs
deleted file mode 100644
index de672c1..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/LookupFunctionCompiler.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
-
-public class LookupFunctionCompiler : FunctionCompiler {
- public LookupFunctionCompiler(ExcelFunction function)
- : base(function) {}
-
- public override CompileResult Compile(IEnumerable<Expression> children, ParsingContext context) {
- var args = new List<FunctionArgument>();
- Function.BeforeInvoke(context);
- var firstChild = true;
- foreach (var child in children) {
- if (!firstChild || Function.SkipArgumentEvaluation) {
- child.ParentIsLookupFunction = Function.IsLookupFuction;
- } else {
- firstChild = false;
- }
- var arg = child.Compile();
- BuildFunctionArguments(arg?.Result, args);
- }
- return Function.Execute(args, context);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/FunctionExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/FunctionExpression.cs
deleted file mode 100644
index 0f39bd5..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionExpression.cs
+++ /dev/null
@@ -1,110 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-/// <summary>
-/// Expression that handles execution of a function.
-/// </summary>
-public class FunctionExpression : AtomicExpression {
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="expression">should be the of the function</param>
- /// <param name="parsingContext"></param>
- /// <param name="isNegated">True if the numeric result of the function should be negated.</param>
- public FunctionExpression(string expression, ParsingContext parsingContext, bool isNegated)
- : base(expression) {
- _parsingContext = parsingContext;
- _functionCompilerFactory = new(parsingContext.Configuration.FunctionRepository);
- _isNegated = isNegated;
- base.AddChild(new FunctionArgumentExpression(this));
- }
-
- private readonly ParsingContext _parsingContext;
- private readonly FunctionCompilerFactory _functionCompilerFactory;
- private readonly bool _isNegated;
-
- public override CompileResult Compile() {
- try {
- var function = _parsingContext.Configuration.FunctionRepository.GetFunction(ExpressionString);
- if (function == null) {
- if (_parsingContext.Debug) {
- _parsingContext.Configuration.Logger.Log(
- _parsingContext,
- string.Format("'{0}' is not a supported function", ExpressionString));
- }
- return new(ExcelErrorValue.Create(eErrorType.Name), DataType.ExcelError);
- }
- if (_parsingContext.Debug) {
- _parsingContext.Configuration.Logger.LogFunction(ExpressionString);
- }
- var compiler = _functionCompilerFactory.Create(function);
- var result = compiler.Compile(
- HasChildren ? Children : Enumerable.Empty<Expression>(),
- _parsingContext);
- if (_isNegated) {
- if (!result.IsNumeric) {
- if (_parsingContext.Debug) {
- var msg = string.Format(
- "Trying to negate a non-numeric value ({0}) in function '{1}'",
- result.Result,
- ExpressionString);
- _parsingContext.Configuration.Logger.Log(_parsingContext, msg);
- }
- return new(ExcelErrorValue.Create(eErrorType.Value), DataType.ExcelError);
- }
- return new(result.ResultNumeric * -1, result.DataType);
- }
- return result;
- } catch (ExcelErrorValueException e) {
- if (_parsingContext.Debug) {
- _parsingContext.Configuration.Logger.Log(_parsingContext, e);
- }
- return new(e.ErrorValue, DataType.ExcelError);
- }
- }
-
- public override Expression PrepareForNextChild() {
- return base.AddChild(new FunctionArgumentExpression(this));
- }
-
- public override bool HasChildren => (Children.Any() && Children.First().Children.Any());
-
- public override Expression AddChild(Expression child) {
- Children.Last().AddChild(child);
- return child;
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/GroupExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/GroupExpression.cs
deleted file mode 100644
index 54df131..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/GroupExpression.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class GroupExpression : Expression {
- public GroupExpression(bool isNegated)
- : this(isNegated, new ExpressionCompiler()) {}
-
- public GroupExpression(bool isNegated, IExpressionCompiler expressionCompiler) {
- _expressionCompiler = expressionCompiler;
- _isNegated = isNegated;
- }
-
- private readonly IExpressionCompiler _expressionCompiler;
- private readonly bool _isNegated;
-
- public override CompileResult Compile() {
- var result = _expressionCompiler.Compile(Children);
- if (result.IsNumeric && _isNegated) {
- return new(result.ResultNumeric * -1, result.DataType);
- }
- return result;
- }
-
- public override bool IsGroupedExpression => true;
-
- public bool IsNegated => _isNegated;
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/IExpressionCompiler.cs b/EPPlus/FormulaParsing/ExpressionGraph/IExpressionCompiler.cs
deleted file mode 100644
index c7ef8dd..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/IExpressionCompiler.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public interface IExpressionCompiler {
- CompileResult Compile(IEnumerable<Expression> expressions);
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/IExpressionConverter.cs b/EPPlus/FormulaParsing/ExpressionGraph/IExpressionConverter.cs
deleted file mode 100644
index 0a1b901..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/IExpressionConverter.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public interface IExpressionConverter {
- StringExpression ToStringExpression(Expression expression);
-
- Expression FromCompileResult(CompileResult compileResult);
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/IExpressionFactory.cs b/EPPlus/FormulaParsing/ExpressionGraph/IExpressionFactory.cs
deleted file mode 100644
index 2e89b2a..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/IExpressionFactory.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public interface IExpressionFactory {
- Expression Create(Token token);
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/IExpressionGraphBuilder.cs b/EPPlus/FormulaParsing/ExpressionGraph/IExpressionGraphBuilder.cs
deleted file mode 100644
index 2fad667..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/IExpressionGraphBuilder.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public interface IExpressionGraphBuilder {
- ExpressionGraph Build(IEnumerable<Token> tokens);
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/IntegerExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/IntegerExpression.cs
deleted file mode 100644
index f24afa0..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/IntegerExpression.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-using System.Globalization;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class IntegerExpression : AtomicExpression {
- private readonly double? _compiledValue;
- private readonly bool _negate;
-
- public IntegerExpression(string expression)
- : this(expression, false) {}
-
- public IntegerExpression(string expression, bool negate)
- : base(expression) {
- _negate = negate;
- }
-
- public IntegerExpression(double val)
- : base(val.ToString(CultureInfo.InvariantCulture)) {
- _compiledValue = Math.Floor(val);
- }
-
- public override CompileResult Compile() {
- double result = _compiledValue ?? double.Parse(ExpressionString, CultureInfo.InvariantCulture);
- result = _negate ? result * -1 : result;
- return new(result, DataType.Integer);
- }
-
- public bool IsNegated => _negate;
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/NamedValueExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/NamedValueExpression.cs
deleted file mode 100644
index cdf7582..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/NamedValueExpression.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class NamedValueExpression : AtomicExpression {
- public NamedValueExpression(string expression, ParsingContext parsingContext)
- : base(expression) {
- _parsingContext = parsingContext;
- }
-
- private readonly ParsingContext _parsingContext;
-
- public override CompileResult Compile() {
- var c = _parsingContext.Scopes.Current;
- var name = _parsingContext.ExcelDataProvider.GetName(c.Address.Worksheet, ExpressionString);
- //var result = _parsingContext.Parser.Parse(value.ToString());
-
- if (name == null) {
- throw (new ExcelErrorValueException(ExcelErrorValue.Create(eErrorType.Name)));
- }
- if (name.Value == null) {
- return null;
- }
- if (name.Value is ExcelDataProvider.IRangeInfo range) {
- if (range.IsMulti) {
- return new(range, DataType.Enumerable);
- }
- if (range.IsEmpty) {
- return null;
- }
- var factory = new CompileResultFactory();
- return factory.Create(range.First().Value);
- }
- {
- var factory = new CompileResultFactory();
- return factory.Create(name.Value);
- }
-
- //return new CompileResultFactory().Create(result);
- }
-}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/StringExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/StringExpression.cs
deleted file mode 100644
index f3b29de..0000000
--- a/EPPlus/FormulaParsing/ExpressionGraph/StringExpression.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
-
-public class StringExpression : AtomicExpression {
- public StringExpression(string expression)
- : base(expression) {}
-
- public override CompileResult Compile() {
- return new(ExpressionString, DataType.String);
- }
-}
diff --git a/EPPlus/FormulaParsing/FormulaParser.cs b/EPPlus/FormulaParsing/FormulaParser.cs
deleted file mode 100644
index 06bd4a6..0000000
--- a/EPPlus/FormulaParsing/FormulaParser.cs
+++ /dev/null
@@ -1,197 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing;
-
-public class FormulaParser {
- private readonly ParsingContext _parsingContext;
- private readonly ExcelDataProvider _excelDataProvider;
-
- public FormulaParser(ExcelDataProvider excelDataProvider)
- : this(excelDataProvider, ParsingContext.Create()) {}
-
- public FormulaParser(ExcelDataProvider excelDataProvider, ParsingContext parsingContext) {
- parsingContext.Parser = this;
- parsingContext.ExcelDataProvider = excelDataProvider;
- parsingContext.NameValueProvider = new EpplusNameValueProvider(excelDataProvider);
- parsingContext.RangeAddressFactory = new(excelDataProvider);
- _parsingContext = parsingContext;
- _excelDataProvider = excelDataProvider;
- Configure(configuration => {
- configuration
- .SetLexer(
- new Lexer(
- _parsingContext.Configuration.FunctionRepository,
- _parsingContext.NameValueProvider))
- .SetGraphBuilder(new ExpressionGraphBuilder(excelDataProvider, _parsingContext))
- .SetExpresionCompiler(new ExpressionCompiler())
- .FunctionRepository.LoadModule(new BuiltInFunctions());
- });
- }
-
- public void Configure(Action<ParsingConfiguration> configMethod) {
- configMethod.Invoke(_parsingContext.Configuration);
- _lexer = _parsingContext.Configuration.Lexer ?? _lexer;
- _graphBuilder = _parsingContext.Configuration.GraphBuilder ?? _graphBuilder;
- _compiler = _parsingContext.Configuration.ExpressionCompiler ?? _compiler;
- }
-
- private ILexer _lexer;
- private IExpressionGraphBuilder _graphBuilder;
- private IExpressionCompiler _compiler;
-
- public ILexer Lexer => _lexer;
-
- public IEnumerable<string> FunctionNames =>
- _parsingContext.Configuration.FunctionRepository.FunctionNames;
-
- internal virtual object Parse(string formula, RangeAddress rangeAddress) {
- using (var scope = _parsingContext.Scopes.NewScope(rangeAddress)) {
- var tokens = _lexer.Tokenize(formula);
- var graph = _graphBuilder.Build(tokens);
- if (graph.Expressions.Count() == 0) {
- return null;
- }
- return _compiler.Compile(graph.Expressions).Result;
- }
- }
-
- internal virtual object Parse(IEnumerable<Token> tokens, string worksheet, string address) {
- var rangeAddress = _parsingContext.RangeAddressFactory.Create(address);
- using (var scope = _parsingContext.Scopes.NewScope(rangeAddress)) {
- var graph = _graphBuilder.Build(tokens);
- if (graph.Expressions.Count() == 0) {
- return null;
- }
- return _compiler.Compile(graph.Expressions).Result;
- }
- }
-
- internal virtual object ParseCell(
- IEnumerable<Token> tokens,
- string worksheet,
- int row,
- int column) {
- var rangeAddress = _parsingContext.RangeAddressFactory.Create(worksheet, column, row);
- using (var scope = _parsingContext.Scopes.NewScope(rangeAddress)) {
- // _parsingContext.Dependencies.AddFormulaScope(scope);
- var graph = _graphBuilder.Build(tokens);
- if (graph.Expressions.Count() == 0) {
- return 0d;
- }
- try {
- var compileResult = _compiler.Compile(graph.Expressions);
- // quick solution for the fact that an excelrange can be returned.
- var rangeInfo = compileResult.Result as ExcelDataProvider.IRangeInfo;
- if (rangeInfo == null) {
- return compileResult.Result ?? 0d;
- }
- if (rangeInfo.IsEmpty) {
- return 0d;
- }
- if (!rangeInfo.IsMulti) {
- return rangeInfo.First().Value ?? 0d;
- }
- // ok to return multicell if it is a workbook scoped name.
- if (string.IsNullOrEmpty(worksheet)) {
- return rangeInfo;
- }
- if (_parsingContext.Debug) {
- var msg = string.Format(
- "A range with multiple cell was returned at row {0}, column {1}",
- row,
- column);
- _parsingContext.Configuration.Logger.Log(_parsingContext, msg);
- }
- return ExcelErrorValue.Create(eErrorType.Value);
- } catch (ExcelErrorValueException ex) {
- if (_parsingContext.Debug) {
- _parsingContext.Configuration.Logger.Log(_parsingContext, ex);
- }
- return ex.ErrorValue;
- }
- }
- }
-
- public virtual object Parse(string formula, string address) {
- return Parse(formula, _parsingContext.RangeAddressFactory.Create(address));
- }
-
- public virtual object Parse(string formula) {
- return Parse(formula, RangeAddress.Empty);
- }
-
- public virtual object ParseAt(string address) {
- Require.That(address).Named("address").IsNotNullOrEmpty();
- var rangeAddress = _parsingContext.RangeAddressFactory.Create(address);
- return ParseAt(rangeAddress.Worksheet, rangeAddress.FromRow, rangeAddress.FromCol);
- }
-
- public virtual object ParseAt(string worksheetName, int row, int col) {
- var f = _excelDataProvider.GetRangeFormula(worksheetName, row, col);
- if (string.IsNullOrEmpty(f)) {
- return _excelDataProvider.GetRangeValue(worksheetName, row, col);
- }
- return Parse(f, _parsingContext.RangeAddressFactory.Create(worksheetName, col, row));
- //var dataItem = _excelDataProvider.GetRangeValues(address).FirstOrDefault();
- //if (dataItem == null /*|| (dataItem.Value == null && dataItem.Formula == null)*/) return null;
- //if (!string.IsNullOrEmpty(dataItem.Formula))
- //{
- // return Parse(dataItem.Formula, _parsingContext.RangeAddressFactory.Create(address));
- //}
- //return Parse(dataItem.Value.ToString(), _parsingContext.RangeAddressFactory.Create(address));
- }
-
- internal void InitNewCalc() {
- if (_excelDataProvider != null) {
- _excelDataProvider.Reset();
- }
- }
-
- // Praveen's Formula Parser
- public ExpressionGraph.ExpressionGraph ParseToGraph(string formula) {
- using (var scope = _parsingContext.Scopes.NewScope(RangeAddress.Empty)) {
- var tokens = _lexer.Tokenize(formula);
- var graph = _graphBuilder.Build(tokens);
- return graph;
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/FormulaParserManager.cs b/EPPlus/FormulaParsing/FormulaParserManager.cs
deleted file mode 100644
index 9d7dc65..0000000
--- a/EPPlus/FormulaParsing/FormulaParserManager.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing;
-
-/// <summary>
-/// Provides access to various functionality regarding
-/// excel formula evaluation.
-/// </summary>
-public class FormulaParserManager {
- private readonly FormulaParser _parser;
-
- internal FormulaParserManager(FormulaParser parser) {
- Require.That(parser).Named("parser").IsNotNull();
- _parser = parser;
- }
-
- /// <summary>
- /// Loads a module containing custom functions to the formula parser. By using
- /// this method you can add your own implementations of Excel functions, by
- /// implementing a <see cref="IFunctionModule"/>.
- /// </summary>
- /// <param name="module">A <see cref="IFunctionModule"/> containing <see cref="ExcelFunction"/>s.</param>
- public void LoadFunctionModule(IFunctionModule module) {
- _parser.Configure(x => x.FunctionRepository.LoadModule(module));
- }
-
- /// <summary>
- /// If the supplied <paramref name="functionName"/> does not exist, the supplied
- /// <paramref name="functionImpl"/> implementation will be added to the formula parser.
- /// If it exists, the existing function will be replaced by the supplied <paramref name="functionImpl">function implementation</paramref>
- /// </summary>
- /// <param name="functionName"></param>
- /// <param name="functionImpl"></param>
- public void AddOrReplaceFunction(string functionName, ExcelFunction functionImpl) {
- _parser.Configure(x => x.FunctionRepository.AddOrReplaceFunction(functionName, functionImpl));
- }
-
- /// <summary>
- /// Returns an enumeration of all functions implemented, both the built in functions
- /// and functions added using the LoadFunctionModule method of this class.
- /// </summary>
- /// <returns>Function names in lower case</returns>
- public IEnumerable<string> GetImplementedFunctionNames() {
- var fnList = _parser.FunctionNames.ToList();
- fnList.Sort((x, y) => String.Compare(x, y, StringComparison.Ordinal));
- return fnList;
- }
-
- /// <summary>
- /// Parses the supplied <paramref name="formula"/> and returns the result.
- /// </summary>
- /// <param name="formula"></param>
- /// <returns></returns>
- public object Parse(string formula) {
- return _parser.Parse(formula);
- }
-
- // Praveen's Parser Support
- public ExpressionGraph.ExpressionGraph ParseToGraph(string formula) {
- return _parser.ParseToGraph(formula);
- }
-}
diff --git a/EPPlus/FormulaParsing/INameValueProvider.cs b/EPPlus/FormulaParsing/INameValueProvider.cs
deleted file mode 100644
index 0a227ae..0000000
--- a/EPPlus/FormulaParsing/INameValueProvider.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace OfficeOpenXml.FormulaParsing;
-
-public interface INameValueProvider {
- bool IsNamedValue(string key, string worksheet);
-
- object GetNamedValue(string key);
-
- void Reload();
-}
diff --git a/EPPlus/FormulaParsing/IParsingLifetimeEventHandler.cs b/EPPlus/FormulaParsing/IParsingLifetimeEventHandler.cs
deleted file mode 100644
index 52fc794..0000000
--- a/EPPlus/FormulaParsing/IParsingLifetimeEventHandler.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-namespace OfficeOpenXml.FormulaParsing;
-
-public interface IParsingLifetimeEventHandler {
- void ParsingCompleted();
-}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/ILexer.cs b/EPPlus/FormulaParsing/LexicalAnalysis/ILexer.cs
deleted file mode 100644
index ec3aef5..0000000
--- a/EPPlus/FormulaParsing/LexicalAnalysis/ILexer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-public interface ILexer {
- IEnumerable<Token> Tokenize(string input);
-
- IEnumerable<Token> Tokenize(string input, string worksheet);
-}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/ISourceCodeTokenizer.cs b/EPPlus/FormulaParsing/LexicalAnalysis/ISourceCodeTokenizer.cs
deleted file mode 100644
index 488d4aa..0000000
--- a/EPPlus/FormulaParsing/LexicalAnalysis/ISourceCodeTokenizer.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-public interface ISourceCodeTokenizer {
- IEnumerable<Token> Tokenize(string input, string worksheet);
-}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/ISyntacticAnalyzer.cs b/EPPlus/FormulaParsing/LexicalAnalysis/ISyntacticAnalyzer.cs
deleted file mode 100644
index 9f73dba..0000000
--- a/EPPlus/FormulaParsing/LexicalAnalysis/ISyntacticAnalyzer.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-public interface ISyntacticAnalyzer {
- void Analyze(IEnumerable<Token> tokens);
-}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/ITokenFactory.cs b/EPPlus/FormulaParsing/LexicalAnalysis/ITokenFactory.cs
deleted file mode 100644
index ab5b170..0000000
--- a/EPPlus/FormulaParsing/LexicalAnalysis/ITokenFactory.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-public interface ITokenFactory {
- Token Create(IEnumerable<Token> tokens, string token);
-
- Token Create(IEnumerable<Token> tokens, string token, string worksheet);
-
- Token Create(string token, TokenType explicitTokenType);
-}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/ITokenIndexProvider.cs b/EPPlus/FormulaParsing/LexicalAnalysis/ITokenIndexProvider.cs
deleted file mode 100644
index 1028a1c..0000000
--- a/EPPlus/FormulaParsing/LexicalAnalysis/ITokenIndexProvider.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-public interface ITokenIndexProvider {
- int Index { get; }
-
- void MoveIndexPointerForward();
-}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/ITokenSeparatorProvider.cs b/EPPlus/FormulaParsing/LexicalAnalysis/ITokenSeparatorProvider.cs
deleted file mode 100644
index 91fb6b9..0000000
--- a/EPPlus/FormulaParsing/LexicalAnalysis/ITokenSeparatorProvider.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-public interface ITokenSeparatorProvider {
- IDictionary<string, Token> Tokens { get; }
-
- bool IsOperator(string item);
-
- bool IsPossibleLastPartOfMultipleCharOperator(string part);
-}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/Lexer.cs b/EPPlus/FormulaParsing/LexicalAnalysis/Lexer.cs
deleted file mode 100644
index 35f4e8f..0000000
--- a/EPPlus/FormulaParsing/LexicalAnalysis/Lexer.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-//using OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-public class Lexer : ILexer {
- public Lexer(FunctionRepository functionRepository, INameValueProvider nameValueProvider)
- : this(
- new SourceCodeTokenizer(functionRepository, nameValueProvider),
- new SyntacticAnalyzer()) {}
-
- public Lexer(ISourceCodeTokenizer tokenizer, ISyntacticAnalyzer analyzer) {
- _tokenizer = tokenizer;
- _analyzer = analyzer;
- }
-
- private readonly ISourceCodeTokenizer _tokenizer;
- private readonly ISyntacticAnalyzer _analyzer;
-
- public IEnumerable<Token> Tokenize(string input) {
- return Tokenize(input, null);
- }
-
- public IEnumerable<Token> Tokenize(string input, string worksheet) {
- var tokens = _tokenizer.Tokenize(input, worksheet);
- _analyzer.Analyze(tokens);
- return tokens;
- }
-}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/SourceCodeTokenizer.cs b/EPPlus/FormulaParsing/LexicalAnalysis/SourceCodeTokenizer.cs
deleted file mode 100644
index 51f6f4b..0000000
--- a/EPPlus/FormulaParsing/LexicalAnalysis/SourceCodeTokenizer.cs
+++ /dev/null
@@ -1,297 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-public class SourceCodeTokenizer : ISourceCodeTokenizer {
- public static ISourceCodeTokenizer Default =>
- new SourceCodeTokenizer(FunctionNameProvider.Empty, NameValueProvider.Empty);
-
- public SourceCodeTokenizer(
- IFunctionNameProvider functionRepository,
- INameValueProvider nameValueProvider)
- : this(
- new TokenFactory(functionRepository, nameValueProvider),
- new TokenSeparatorProvider()) {}
-
- public SourceCodeTokenizer(ITokenFactory tokenFactory, ITokenSeparatorProvider tokenProvider) {
- _tokenFactory = tokenFactory;
- _tokenProvider = tokenProvider;
- }
-
- private readonly ITokenSeparatorProvider _tokenProvider;
- private readonly ITokenFactory _tokenFactory;
-
- public IEnumerable<Token> Tokenize(string input) {
- return Tokenize(input, null);
- }
-
- public IEnumerable<Token> Tokenize(string input, string worksheet) {
- if (string.IsNullOrEmpty(input)) {
- return Enumerable.Empty<Token>();
- }
- // MA 1401: Ignore leading plus in formula.
- input = input.TrimStart('+');
- var context = new TokenizerContext(input);
-
- bool isSingleQuoteString = false;
- for (int i = 0; i < context.FormulaChars.Length; i++) {
- var c = context.FormulaChars[i];
- if (CharIsTokenSeparator(c, out var tokenSeparator)) {
- if (context.IsInString) {
- if (IsDoubleQuote(tokenSeparator, i, context)) {
- i++;
- context.AppendToCurrentToken(c);
- continue;
- }
- if (tokenSeparator.TokenType != TokenType.String) {
- context.AppendToCurrentToken(c);
- continue;
- }
- // CHANGE 2
- if ((isSingleQuoteString && c != '\'') || (!isSingleQuoteString && c != '"')) {
- context.AppendToCurrentToken(c);
- continue;
- }
- }
- if (tokenSeparator.TokenType == TokenType.OpeningBracket) {
- context.AppendToCurrentToken(c);
- context.BracketCount++;
- continue;
- }
- if (tokenSeparator.TokenType == TokenType.ClosingBracket) {
- context.AppendToCurrentToken(c);
- context.BracketCount--;
- continue;
- }
- if (context.BracketCount > 0) {
- context.AppendToCurrentToken(c);
- continue;
- }
- // two operators in sequence could be "<=" or ">="
- if (IsPartOfMultipleCharSeparator(context, c)) {
- var sOp = context.LastToken.Value + c.ToString(CultureInfo.InvariantCulture);
- var op = _tokenProvider.Tokens[sOp];
- context.ReplaceLastToken(op);
- context.NewToken();
- continue;
- }
- if (tokenSeparator.TokenType == TokenType.String) {
- // CHANGE3 :
- isSingleQuoteString = (c == '\'');
- if (context.LastToken != null
- && context.LastToken.TokenType == TokenType.OpeningEnumerable) {
- // context.AppendToCurrentToken(c); // Praveen's change of 10/28/2015
- context.ToggleIsInString();
- continue;
- }
- if (context.LastToken != null && context.LastToken.TokenType == TokenType.String) {
- context.AddToken(
- !context.CurrentTokenHasValue
- ? new(string.Empty, TokenType.StringContent)
- : new Token(context.CurrentToken, TokenType.StringContent));
- }
- context.AddToken(new("\"", TokenType.String));
- context.ToggleIsInString();
- context.NewToken();
- continue;
- }
- if (context.CurrentTokenHasValue) {
- if (Regex.IsMatch(context.CurrentToken, "^\"*$")) {
- context.AddToken(_tokenFactory.Create(context.CurrentToken, TokenType.StringContent));
- } else {
- context.AddToken(CreateToken(context, worksheet));
- }
-
- //If the a next token is an opening parantheses and the previous token is interpeted as an address or name, then the currenct token is a function
- if (tokenSeparator.TokenType == TokenType.OpeningParenthesis
- && (context.LastToken.TokenType == TokenType.ExcelAddress
- || context.LastToken.TokenType == TokenType.NameValue)) {
- context.LastToken.TokenType = TokenType.Function;
- }
- }
- if (tokenSeparator.Value == "-") {
- if (TokenIsNegator(context)) {
- context.AddToken(new("-", TokenType.Negator));
- continue;
- }
- }
- context.AddToken(tokenSeparator);
- context.NewToken();
- continue;
- }
- context.AppendToCurrentToken(c);
- }
- if (context.CurrentTokenHasValue) {
- context.AddToken(CreateToken(context, worksheet));
- }
-
- CleanupTokens(context, _tokenProvider.Tokens);
-
- return context.Result;
- }
-
- private static bool IsDoubleQuote(
- Token tokenSeparator,
- int formulaCharIndex,
- TokenizerContext context) {
- return tokenSeparator.TokenType == TokenType.String
- && formulaCharIndex + 1 < context.FormulaChars.Length
- && context.FormulaChars[formulaCharIndex + 1] == '\"';
- }
-
- private static void CleanupTokens(TokenizerContext context, IDictionary<string, Token> tokens) {
- for (int i = 0; i < context.Result.Count; i++) {
- var token = context.Result[i];
- if (token.TokenType == TokenType.Unrecognized) {
- if (i < context.Result.Count - 1) {
- if (context.Result[i + 1].TokenType == TokenType.OpeningParenthesis) {
- token.TokenType = TokenType.Function;
- } else {
- token.TokenType = TokenType.NameValue;
- }
- } else {
- token.TokenType = TokenType.NameValue;
- }
- } else if (token.TokenType == TokenType.Function) {
- if (i < context.Result.Count - 1) {
- if (context.Result[i + 1].TokenType == TokenType.OpeningParenthesis) {
- token.TokenType = TokenType.Function;
- } else {
- token.TokenType = TokenType.Unrecognized;
- }
- } else {
- token.TokenType = TokenType.Unrecognized;
- }
- } else if ((token.TokenType == TokenType.Operator || token.TokenType == TokenType.Negator)
- && i < context.Result.Count - 1
- && (token.Value == "+" || token.Value == "-")) {
- if (i > 0
- && token.Value
- == "+") //Remove any + with an opening parenthesis before.
- {
- if (context.Result[i - 1].TokenType == TokenType.OpeningParenthesis) {
- context.Result.RemoveAt(i);
- SetNegatorOperator(context, i, tokens);
- i--;
- continue;
- }
- }
-
- var nextToken = context.Result[i + 1];
- if (nextToken.TokenType == TokenType.Operator || nextToken.TokenType == TokenType.Negator) {
- if (token.Value == "+" && (nextToken.Value == "+" || nextToken.Value == "-")) {
- //Remove first
- context.Result.RemoveAt(i);
- SetNegatorOperator(context, i, tokens);
- i--;
- } else if (token.Value == "-" && nextToken.Value == "+") {
- //Remove second
- context.Result.RemoveAt(i + 1);
- SetNegatorOperator(context, i, tokens);
- i--;
- } else if (token.Value == "-" && nextToken.Value == "-") {
- //Remove first and set operator to +
- context.Result.RemoveAt(i);
- if (i == 0) {
- context.Result.RemoveAt(i + 1);
- i += 2;
- } else {
- //context.Result[i].TokenType = TokenType.Operator;
- //context.Result[i].Value = "+";
- context.Result[i] = tokens["+"];
- SetNegatorOperator(context, i, tokens);
- i--;
- }
- }
- }
- }
- }
- }
-
- private static void SetNegatorOperator(
- TokenizerContext context,
- int i,
- IDictionary<string, Token> tokens) {
- if (context.Result[i].Value == "-"
- && i > 0
- && (context.Result[i].TokenType == TokenType.Operator
- || context.Result[i].TokenType == TokenType.Negator)) {
- if (TokenIsNegator(context.Result[i - 1])) {
- context.Result[i] = new("-", TokenType.Negator);
- } else {
- context.Result[i] = tokens["-"];
- }
- }
- }
-
- private static bool TokenIsNegator(TokenizerContext context) {
- return TokenIsNegator(context.LastToken);
- }
-
- private static bool TokenIsNegator(Token t) {
- return t == null
- || t.TokenType == TokenType.Operator
- || t.TokenType == TokenType.OpeningParenthesis
- || t.TokenType == TokenType.Comma
- || t.TokenType == TokenType.SemiColon
- || t.TokenType == TokenType.OpeningEnumerable;
- }
-
- private bool IsPartOfMultipleCharSeparator(TokenizerContext context, char c) {
- var lastToken = context.LastToken != null ? context.LastToken.Value : string.Empty;
- return _tokenProvider.IsOperator(lastToken)
- && _tokenProvider.IsPossibleLastPartOfMultipleCharOperator(
- c.ToString(CultureInfo.InvariantCulture))
- && !context.CurrentTokenHasValue;
- }
-
- private Token CreateToken(TokenizerContext context, string worksheet) {
- if (context.CurrentToken == "-") {
- if (context.LastToken == null && context.LastToken.TokenType == TokenType.Operator) {
- return new("-", TokenType.Negator);
- }
- }
- return _tokenFactory.Create(context.Result, context.CurrentToken, worksheet);
- }
-
- private bool CharIsTokenSeparator(char c, out Token token) {
- var result = _tokenProvider.Tokens.ContainsKey(c.ToString());
- token = result ? token = _tokenProvider.Tokens[c.ToString()] : null;
- return result;
- }
-}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/SyntacticAnalyzer.cs b/EPPlus/FormulaParsing/LexicalAnalysis/SyntacticAnalyzer.cs
deleted file mode 100644
index e771aaf..0000000
--- a/EPPlus/FormulaParsing/LexicalAnalysis/SyntacticAnalyzer.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-public class SyntacticAnalyzer : ISyntacticAnalyzer {
- private class AnalyzingContext {
- public int NumberOfOpenedParentheses { get; set; }
-
- public int NumberOfClosedParentheses { get; set; }
-
- public int OpenedStrings { get; set; }
-
- public int ClosedStrings { get; set; }
-
- public bool IsInString { get; set; }
- }
-
- public void Analyze(IEnumerable<Token> tokens) {
- var context = new AnalyzingContext();
- foreach (var token in tokens) {
- if (token.TokenType == TokenType.Unrecognized) {
- throw new UnrecognizedTokenException(token);
- }
- EnsureParenthesesAreWellFormed(token, context);
- EnsureStringsAreWellFormed(token, context);
- }
- Validate(context);
- }
-
- private static void Validate(AnalyzingContext context) {
- if (context.NumberOfOpenedParentheses != context.NumberOfClosedParentheses) {
- throw new FormatException("Number of opened and closed parentheses does not match");
- }
- if (context.OpenedStrings != context.ClosedStrings) {
- throw new FormatException("Unterminated string");
- }
- }
-
- private void EnsureParenthesesAreWellFormed(Token token, AnalyzingContext context) {
- if (token.TokenType == TokenType.OpeningParenthesis) {
- context.NumberOfOpenedParentheses++;
- } else if (token.TokenType == TokenType.ClosingParenthesis) {
- context.NumberOfClosedParentheses++;
- }
- }
-
- private void EnsureStringsAreWellFormed(Token token, AnalyzingContext context) {
- if (!context.IsInString && token.TokenType == TokenType.String) {
- context.IsInString = true;
- context.OpenedStrings++;
- } else if (context.IsInString && token.TokenType == TokenType.String) {
- context.IsInString = false;
- context.ClosedStrings++;
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/Token.cs b/EPPlus/FormulaParsing/LexicalAnalysis/Token.cs
deleted file mode 100644
index f3faa0c..0000000
--- a/EPPlus/FormulaParsing/LexicalAnalysis/Token.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-public class Token {
- public Token(string token, TokenType tokenType) {
- Value = token;
- TokenType = tokenType;
- }
-
- public string Value { get; internal set; }
-
- public TokenType TokenType { get; internal set; }
-
- public void Append(string stringToAppend) {
- Value += stringToAppend;
- }
-
- public bool IsNegated { get; private set; }
-
- public void Negate() {
- if (TokenType == TokenType.Decimal
- || TokenType == TokenType.Integer
- || TokenType == TokenType.ExcelAddress) {
- IsNegated = true;
- }
- }
-
- public override string ToString() {
- return TokenType + ", " + Value;
- }
-}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/TokenFactory.cs b/EPPlus/FormulaParsing/LexicalAnalysis/TokenFactory.cs
deleted file mode 100644
index 4639753..0000000
--- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenFactory.cs
+++ /dev/null
@@ -1,140 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- * Jan Källman Replaced Adress validate 2013-03-01
- * *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-public class TokenFactory : ITokenFactory {
- public TokenFactory(
- IFunctionNameProvider functionRepository,
- INameValueProvider nameValueProvider)
- : this(new TokenSeparatorProvider(), nameValueProvider, functionRepository) {}
-
- public TokenFactory(
- ITokenSeparatorProvider tokenSeparatorProvider,
- INameValueProvider nameValueProvider,
- IFunctionNameProvider functionNameProvider) {
- _tokenSeparatorProvider = tokenSeparatorProvider;
- _functionNameProvider = functionNameProvider;
- _nameValueProvider = nameValueProvider;
- }
-
- private readonly ITokenSeparatorProvider _tokenSeparatorProvider;
- private readonly IFunctionNameProvider _functionNameProvider;
- private readonly INameValueProvider _nameValueProvider;
-
- public Token Create(IEnumerable<Token> tokens, string token) {
- return Create(tokens, token, null);
- }
-
- public Token Create(IEnumerable<Token> tokens, string token, string worksheet) {
- if (_tokenSeparatorProvider.Tokens.TryGetValue(token, out var tokenSeparator)) {
- return tokenSeparator;
- }
- var tokenList = (IList<Token>)tokens;
- //Address with worksheet-string before /JK
- if (token.StartsWith("!") && tokenList[tokenList.Count - 1].TokenType == TokenType.String) {
- var i = tokenList.Count - 2;
- if (i > 0) {
- string addr;
- if (tokenList[i].TokenType == TokenType.StringContent) {
- addr = "'" + tokenList[i].Value.Replace("'", "''") + "'";
- } else {
- throw (new ArgumentException(
- string.Format("Invalid formula token sequence near {0}", token)));
- }
- //Remove the string tokens and content
- tokenList.RemoveAt(tokenList.Count - 1);
- tokenList.RemoveAt(tokenList.Count - 1);
- tokenList.RemoveAt(tokenList.Count - 1);
-
- return new(addr + token, TokenType.ExcelAddress);
- }
- throw (new ArgumentException(
- string.Format("Invalid formula token sequence near {0}", token)));
- }
-
- if (tokens.Any() && tokens.Last().TokenType == TokenType.String) {
- return new(token, TokenType.StringContent);
- }
- if (!string.IsNullOrEmpty(token)) {
- token = token.Trim();
- }
- if (Regex.IsMatch(token, RegexConstants.Decimal)) {
- return new(token, TokenType.Decimal);
- }
- if (Regex.IsMatch(token, RegexConstants.Integer)) {
- return new(token, TokenType.Integer);
- }
- if (Regex.IsMatch(token, RegexConstants.Boolean, RegexOptions.IgnoreCase)) {
- return new(token, TokenType.Boolean);
- }
- if (token.ToUpper(CultureInfo.InvariantCulture).Contains("#REF!")) {
- return new(token, TokenType.InvalidReference);
- }
- if (token.ToUpper(CultureInfo.InvariantCulture) == "#NUM!") {
- return new(token, TokenType.NumericError);
- }
- if (token.ToUpper(CultureInfo.InvariantCulture) == "#VALUE!") {
- return new(token, TokenType.ValueDataTypeError);
- }
- if (token.ToUpper(CultureInfo.InvariantCulture) == "#NULL!") {
- return new(token, TokenType.Null);
- }
- if (_nameValueProvider != null && _nameValueProvider.IsNamedValue(token, worksheet)) {
- return new(token, TokenType.NameValue);
- }
- if (_functionNameProvider.IsFunctionName(token)) {
- return new(token, TokenType.Function);
- }
- if (tokenList.Count > 0
- && tokenList[tokenList.Count - 1].TokenType == TokenType.OpeningEnumerable) {
- return new(token, TokenType.Enumerable);
- }
- var at = ExcelAddressBase.IsValid(token);
- if (at == ExcelAddressBase.AddressType.InternalAddress) {
- return new(token.ToUpper(CultureInfo.InvariantCulture), TokenType.ExcelAddress);
- }
- return new(token, TokenType.Unrecognized);
- }
-
- public Token Create(string token, TokenType explicitTokenType) {
- return new(token, explicitTokenType);
- }
-}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorProvider.cs b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorProvider.cs
deleted file mode 100644
index d56dc18..0000000
--- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorProvider.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-public class TokenSeparatorProvider : ITokenSeparatorProvider {
- private static readonly Dictionary<string, Token> _tokens = new();
-
- static TokenSeparatorProvider() {
- _tokens.Add("+", new("+", TokenType.Operator));
- _tokens.Add("-", new("-", TokenType.Operator));
- _tokens.Add("*", new("*", TokenType.Operator));
- _tokens.Add("/", new("/", TokenType.Operator));
- _tokens.Add("^", new("^", TokenType.Operator));
- _tokens.Add("&", new("&", TokenType.Operator));
- _tokens.Add(">", new(">", TokenType.Operator));
- _tokens.Add("<", new("<", TokenType.Operator));
- _tokens.Add("=", new("=", TokenType.Operator));
- _tokens.Add("<=", new("<=", TokenType.Operator));
- _tokens.Add(">=", new(">=", TokenType.Operator));
- _tokens.Add("<>", new("<>", TokenType.Operator));
- _tokens.Add("(", new("(", TokenType.OpeningParenthesis));
- _tokens.Add(")", new(")", TokenType.ClosingParenthesis));
- _tokens.Add("{", new("{", TokenType.OpeningEnumerable));
- _tokens.Add("}", new("}", TokenType.ClosingEnumerable));
- _tokens.Add("'", new("'", TokenType.String));
- _tokens.Add("\"", new("\"", TokenType.String));
- _tokens.Add(",", new(",", TokenType.Comma));
- _tokens.Add(";", new(";", TokenType.SemiColon));
- _tokens.Add("[", new("[", TokenType.OpeningBracket));
- _tokens.Add("]", new("]", TokenType.ClosingBracket));
- _tokens.Add("%", new("%", TokenType.Percent));
- }
-
- IDictionary<string, Token> ITokenSeparatorProvider.Tokens => _tokens;
-
- public bool IsOperator(string item) {
- if (_tokens.TryGetValue(item, out var token)) {
- if (token.TokenType == TokenType.Operator) {
- return true;
- }
- }
- return false;
- }
-
- public bool IsPossibleLastPartOfMultipleCharOperator(string part) {
- return part == "=" || part == ">";
- }
-}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/TokenType.cs b/EPPlus/FormulaParsing/LexicalAnalysis/TokenType.cs
deleted file mode 100644
index a698470..0000000
--- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenType.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-public enum TokenType {
- Operator,
- Negator,
- OpeningParenthesis,
- ClosingParenthesis,
- OpeningEnumerable,
- ClosingEnumerable,
- OpeningBracket,
- ClosingBracket,
- Enumerable,
- Comma,
- SemiColon,
- String,
- StringContent,
- Integer,
- Boolean,
- Decimal,
- Percent,
- Function,
- ExcelAddress,
- NameValue,
- InvalidReference,
- NumericError,
- ValueDataTypeError,
- Null,
- Unrecognized,
-}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/TokenizerContext.cs b/EPPlus/FormulaParsing/LexicalAnalysis/TokenizerContext.cs
deleted file mode 100644
index 130324d..0000000
--- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenizerContext.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-public class TokenizerContext {
- public TokenizerContext(string formula) {
- if (!string.IsNullOrEmpty(formula)) {
- _chars = formula.ToArray();
- }
- }
-
- private readonly char[] _chars;
- private readonly List<Token> _result = new();
- private StringBuilder _currentToken = new();
-
- public char[] FormulaChars => _chars;
-
- public IList<Token> Result => _result;
-
- public bool IsInString { get; private set; }
-
- public void ToggleIsInString() {
- IsInString = !IsInString;
- }
-
- internal int BracketCount { get; set; }
-
- public string CurrentToken => _currentToken.ToString();
-
- public bool CurrentTokenHasValue =>
- !string.IsNullOrEmpty(IsInString ? CurrentToken : CurrentToken.Trim());
-
- public void NewToken() {
- _currentToken = new();
- }
-
- public void AddToken(Token token) {
- _result.Add(token);
- }
-
- public void AppendToCurrentToken(char c) {
- _currentToken.Append(c.ToString());
- }
-
- public void AppendToLastToken(string stringToAppend) {
- _result.Last().Append(stringToAppend);
- }
-
- public void SetLastTokenType(TokenType type) {
- _result.Last().TokenType = type;
- }
-
- public void ReplaceLastToken(Token newToken) {
- var count = _result.Count;
- if (count > 0) {
- _result.RemoveAt(count - 1);
- }
- _result.Add(newToken);
- }
-
- public Token LastToken => _result.Count > 0 ? _result.Last() : null;
-}
diff --git a/EPPlus/FormulaParsing/Logging/IFormulaParserLogger.cs b/EPPlus/FormulaParsing/Logging/IFormulaParserLogger.cs
deleted file mode 100644
index dc38d9d..0000000
--- a/EPPlus/FormulaParsing/Logging/IFormulaParserLogger.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using System;
-
-namespace OfficeOpenXml.FormulaParsing.Logging;
-
-/// <summary>
-/// Used for logging during FormulaParsing
-/// </summary>
-public interface IFormulaParserLogger : IDisposable {
- /// <summary>
- /// Called each time an exception occurs during formula parsing.
- /// </summary>
- /// <param name="context"></param>
- /// <param name="ex"></param>
- void Log(ParsingContext context, Exception ex);
-
- /// <summary>
- /// Called each time information should be logged during formula parsing.
- /// </summary>
- /// <param name="context"></param>
- /// <param name="message"></param>
- void Log(ParsingContext context, string message);
-
- /// <summary>
- /// Called to log a message outside the parsing context.
- /// </summary>
- /// <param name="message"></param>
- void Log(string message);
-
- /// <summary>
- /// Called each time a cell within the calc chain is accessed during formula parsing.
- /// </summary>
- void LogCellCounted();
-
- /// <summary>
- /// Called each time a function is called during formula parsing.
- /// </summary>
- /// <param name="func"></param>
- void LogFunction(string func);
-
- /// <summary>
- /// Some functions measure performance, if so this function will be called.
- /// </summary>
- /// <param name="func"></param>
- /// <param name="milliseconds"></param>
- void LogFunction(string func, long milliseconds);
-}
diff --git a/EPPlus/FormulaParsing/NameValueProvider.cs b/EPPlus/FormulaParsing/NameValueProvider.cs
deleted file mode 100644
index f7b0a8d..0000000
--- a/EPPlus/FormulaParsing/NameValueProvider.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace OfficeOpenXml.FormulaParsing;
-
-public class NameValueProvider : INameValueProvider {
- private NameValueProvider() {}
-
- public static INameValueProvider Empty => new NameValueProvider();
-
- public bool IsNamedValue(string key, string worksheet) {
- return false;
- }
-
- public object GetNamedValue(string key) {
- return null;
- }
-
- public void Reload() {}
-}
diff --git a/EPPlus/FormulaParsing/ParsedValue.cs b/EPPlus/FormulaParsing/ParsedValue.cs
deleted file mode 100644
index 43112b7..0000000
--- a/EPPlus/FormulaParsing/ParsedValue.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace OfficeOpenXml.FormulaParsing;
-
-public class ParsedValue {
- public ParsedValue(object val, int rowIndex, int colIndex) {
- Value = val;
- RowIndex = rowIndex;
- ColIndex = colIndex;
- }
-
- public object Value { get; private set; }
-
- public int RowIndex { get; private set; }
-
- public int ColIndex { get; private set; }
-}
diff --git a/EPPlus/FormulaParsing/ParsingConfiguration.cs b/EPPlus/FormulaParsing/ParsingConfiguration.cs
deleted file mode 100644
index 90792b4..0000000
--- a/EPPlus/FormulaParsing/ParsingConfiguration.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-using OfficeOpenXml.FormulaParsing.Logging;
-using OfficeOpenXml.FormulaParsing.Utilities;
-
-namespace OfficeOpenXml.FormulaParsing;
-
-public class ParsingConfiguration {
- public virtual ILexer Lexer { get; private set; }
-
- public IFormulaParserLogger Logger { get; private set; }
-
- public IExpressionGraphBuilder GraphBuilder { get; private set; }
-
- public IExpressionCompiler ExpressionCompiler { get; private set; }
-
- public FunctionRepository FunctionRepository { get; private set; } = FunctionRepository.Create();
-
- private ParsingConfiguration() {}
-
- internal static ParsingConfiguration Create() {
- return new();
- }
-
- public ParsingConfiguration SetLexer(ILexer lexer) {
- Lexer = lexer;
- return this;
- }
-
- public ParsingConfiguration SetGraphBuilder(IExpressionGraphBuilder graphBuilder) {
- GraphBuilder = graphBuilder;
- return this;
- }
-
- public ParsingConfiguration SetExpresionCompiler(IExpressionCompiler expressionCompiler) {
- ExpressionCompiler = expressionCompiler;
- return this;
- }
-
- /// <summary>
- /// Attaches a logger, errors and log entries will be written to the logger during the parsing process.
- /// </summary>
- /// <param name="logger"></param>
- /// <returns></returns>
- public ParsingConfiguration AttachLogger(IFormulaParserLogger logger) {
- Require.That(logger).Named("logger").IsNotNull();
- Logger = logger;
- return this;
- }
-
- /// <summary>
- /// if a logger is attached it will be removed.
- /// </summary>
- /// <returns></returns>
- public ParsingConfiguration DetachLogger() {
- Logger = null;
- return this;
- }
-}
diff --git a/EPPlus/FormulaParsing/ParsingContext.cs b/EPPlus/FormulaParsing/ParsingContext.cs
deleted file mode 100644
index 8eee889..0000000
--- a/EPPlus/FormulaParsing/ParsingContext.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.Logging;
-
-namespace OfficeOpenXml.FormulaParsing;
-
-/// <summary>
-/// Parsing context
-/// </summary>
-public class ParsingContext : IParsingLifetimeEventHandler {
- private ParsingContext() {}
-
- /// <summary>
- /// The <see cref="FormulaParser"/> of the current context.
- /// </summary>
- public FormulaParser Parser { get; set; }
-
- /// <summary>
- /// The <see cref="ExcelDataProvider"/> is an abstraction on top of
- /// Excel, in this case EPPlus.
- /// </summary>
- public ExcelDataProvider ExcelDataProvider { get; set; }
-
- /// <summary>
- /// Utility for handling addresses
- /// </summary>
- public RangeAddressFactory RangeAddressFactory { get; set; }
-
- /// <summary>
- /// <see cref="INameValueProvider"/> of the current context
- /// </summary>
- public INameValueProvider NameValueProvider { get; set; }
-
- /// <summary>
- /// Configuration
- /// </summary>
- public ParsingConfiguration Configuration { get; set; }
-
- /// <summary>
- /// Scopes, a scope represents the parsing of a cell or a value.
- /// </summary>
- public ParsingScopes Scopes { get; private set; }
-
- /// <summary>
- /// Returns true if a <see cref="IFormulaParserLogger"/> is attached to the parser.
- /// </summary>
- public bool Debug => Configuration.Logger != null;
-
- /// <summary>
- /// Factory method.
- /// </summary>
- /// <returns></returns>
- public static ParsingContext Create() {
- var context = new ParsingContext();
- context.Configuration = ParsingConfiguration.Create();
- context.Scopes = new(context);
- return context;
- }
-
- void IParsingLifetimeEventHandler.ParsingCompleted() {}
-}
diff --git a/EPPlus/FormulaParsing/ParsingScope.cs b/EPPlus/FormulaParsing/ParsingScope.cs
deleted file mode 100644
index f901f1e..0000000
--- a/EPPlus/FormulaParsing/ParsingScope.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using System;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-namespace OfficeOpenXml.FormulaParsing;
-
-/// <summary>
-/// Represents a parsing of a single input or workbook addrses.
-/// </summary>
-public class ParsingScope : IDisposable {
- private readonly ParsingScopes _parsingScopes;
-
- public ParsingScope(ParsingScopes parsingScopes, RangeAddress address)
- : this(parsingScopes, null, address) {}
-
- public ParsingScope(ParsingScopes parsingScopes, ParsingScope parent, RangeAddress address) {
- _parsingScopes = parsingScopes;
- Parent = parent;
- Address = address;
- }
-
- /// <summary>
- /// Id of the scope.
- /// </summary>
- public Guid ScopeId { get; private set; } = Guid.NewGuid();
-
- /// <summary>
- /// The calling scope.
- /// </summary>
- public ParsingScope Parent { get; private set; }
-
- /// <summary>
- /// The address of the cell currently beeing parsed.
- /// </summary>
- public RangeAddress Address { get; private set; }
-
- /// <summary>
- /// True if the current scope is a Subtotal function beeing executed.
- /// </summary>
- public bool IsSubtotal { get; set; }
-
- public void Dispose() {
- _parsingScopes.KillScope(this);
- }
-}
diff --git a/EPPlus/FormulaParsing/ParsingScopes.cs b/EPPlus/FormulaParsing/ParsingScopes.cs
deleted file mode 100644
index 66ef836..0000000
--- a/EPPlus/FormulaParsing/ParsingScopes.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-
-namespace OfficeOpenXml.FormulaParsing;
-
-/// <summary>
-/// This class implements a stack on which instances of <see cref="ParsingScope"/>
-/// are put. Each ParsingScope represents the parsing of an address in the workbook.
-/// </summary>
-public class ParsingScopes {
- private readonly IParsingLifetimeEventHandler _lifetimeEventHandler;
-
- public ParsingScopes(IParsingLifetimeEventHandler lifetimeEventHandler) {
- _lifetimeEventHandler = lifetimeEventHandler;
- }
-
- private readonly Stack<ParsingScope> _scopes = new();
-
- /// <summary>
- /// Creates a new <see cref="ParsingScope"/> and puts it on top of the stack.
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public virtual ParsingScope NewScope(RangeAddress address) {
- ParsingScope scope;
- if (_scopes.Count() > 0) {
- scope = new(this, _scopes.Peek(), address);
- } else {
- scope = new(this, address);
- }
- _scopes.Push(scope);
- return scope;
- }
-
- /// <summary>
- /// The current parsing scope.
- /// </summary>
- public virtual ParsingScope Current => _scopes.Count() > 0 ? _scopes.Peek() : null;
-
- /// <summary>
- /// Removes the current scope, setting the calling scope to current.
- /// </summary>
- /// <param name="parsingScope"></param>
- public virtual void KillScope(ParsingScope parsingScope) {
- _scopes.Pop();
- if (_scopes.Count() == 0) {
- _lifetimeEventHandler.ParsingCompleted();
- }
- }
-}
diff --git a/EPPlus/FormulaParsing/Utilities/ArgumentInfo.cs b/EPPlus/FormulaParsing/Utilities/ArgumentInfo.cs
deleted file mode 100644
index a0a826f..0000000
--- a/EPPlus/FormulaParsing/Utilities/ArgumentInfo.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace OfficeOpenXml.FormulaParsing.Utilities;
-
-public class ArgumentInfo<T> {
- public ArgumentInfo(T val) {
- Value = val;
- }
-
- public T Value { get; private set; }
-
- public string Name { get; private set; }
-
- public ArgumentInfo<T> Named(string argName) {
- Name = argName;
- return this;
- }
-}
diff --git a/EPPlus/FormulaParsing/Utilities/ExtensionMethods.cs b/EPPlus/FormulaParsing/Utilities/ExtensionMethods.cs
deleted file mode 100644
index 786ec4f..0000000
--- a/EPPlus/FormulaParsing/Utilities/ExtensionMethods.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System;
-
-namespace OfficeOpenXml.FormulaParsing.Utilities;
-
-public static class ExtensionMethods {
- public static void IsNotNullOrEmpty(this ArgumentInfo<string> val) {
- if (string.IsNullOrEmpty(val.Value)) {
- throw new ArgumentException(val.Name + " cannot be null or empty");
- }
- }
-
- public static void IsNotNull<T>(this ArgumentInfo<T> val)
- where T : class {
- if (val.Value == null) {
- throw new ArgumentNullException(val.Name);
- }
- }
-
- public static bool IsNumeric(this object obj) {
- if (obj == null) {
- return false;
- }
- return (obj.GetType().IsPrimitive
- || obj is double
- || obj is decimal
- || obj is DateTime
- || obj is TimeSpan);
- }
-}
diff --git a/EPPlus/FormulaParsing/Utilities/IdProvider.cs b/EPPlus/FormulaParsing/Utilities/IdProvider.cs
deleted file mode 100644
index 15e02b3..0000000
--- a/EPPlus/FormulaParsing/Utilities/IdProvider.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-namespace OfficeOpenXml.FormulaParsing.Utilities;
-
-public abstract class IdProvider {
- public abstract object NewId();
-}
diff --git a/EPPlus/FormulaParsing/Utilities/IntegerIdProvider.cs b/EPPlus/FormulaParsing/Utilities/IntegerIdProvider.cs
deleted file mode 100644
index d1a39f4..0000000
--- a/EPPlus/FormulaParsing/Utilities/IntegerIdProvider.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-
-namespace OfficeOpenXml.FormulaParsing.Utilities;
-
-public class IntegerIdProvider : IdProvider {
- private int _lastId = int.MinValue;
-
- public override object NewId() {
- if (_lastId >= int.MaxValue) {
- throw new InvalidOperationException("IdProvider run out of id:s");
- }
- return _lastId++;
- }
-}
diff --git a/EPPlus/FormulaParsing/Utilities/RegexConstants.cs b/EPPlus/FormulaParsing/Utilities/RegexConstants.cs
deleted file mode 100644
index deba058..0000000
--- a/EPPlus/FormulaParsing/Utilities/RegexConstants.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
- *******************************************************************************/
-
-namespace OfficeOpenXml.FormulaParsing.Utilities;
-
-public static class RegexConstants {
- public const string SingleCellAddress =
- @"^(('[^/\\?*\[\]]{1,31}'|[A-Za-z_]{1,31})!)?[A-Z]{1,3}[1-9]{1}[0-9]{0,7}$";
-
- //Changed JK 26/2-2013
- public const string ExcelAddress =
- @"^(('[^/\\?*\[\]]{1,31}'|[A-Za-z_]{1,31})!)?[\$]{0,1}([A-Z]|[A-Z]{1,3}[\$]{0,1}[1-9]{1}[0-9]{0,7})(\:({0,1}[A-Z]|[A-Z]{1,3}[\$]{0,1}[1-9]{1}[0-9]{0,7})){0,1}$";
-
- //public const string ExcelAddress = @"^([\$]{0,1}([A-Z]{1,3}[\$]{0,1}[0-9]{1,7})(\:([\$]{0,1}[A-Z]{1,3}[\$]{0,1}[0-9]{1,7}){0,1})|([\$]{0,1}[A-Z]{1,3}\:[\$]{0,1}[A-Z]{1,3})|([\$]{0,1}[0-9]{1,7}\:[\$]{0,1}[0-9]{1,7}))$";
- public const string Boolean = "^(true|false)$";
- public const string Decimal = @"^[0-9]+\.[0-9]+$";
- public const string Integer = "^[0-9]+$";
-}
diff --git a/EPPlus/FormulaParsing/Utilities/Require.cs b/EPPlus/FormulaParsing/Utilities/Require.cs
deleted file mode 100644
index 35d53cd..0000000
--- a/EPPlus/FormulaParsing/Utilities/Require.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace OfficeOpenXml.FormulaParsing.Utilities;
-
-public static class Require {
- public static ArgumentInfo<T> That<T>(T arg) {
- return new(arg);
- }
-}
diff --git a/EPPlus/IRangeID.cs b/EPPlus/IRangeID.cs
deleted file mode 100644
index 8ead21d..0000000
--- a/EPPlus/IRangeID.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * 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 2010-02-04
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Id from a cell, column or row.
-/// </summary>
-internal interface IRangeId {
- /// <summary>
- /// This is the id for a cell, row or column.
- /// The id is a composit of the SheetID, the row number and the column number.
- /// Bit 1-14 SheetID, Bit 15-28 Column number (0 if entire column), Bit 29- Row number (0 if entire row).
- /// </summary>
- ulong RangeID { get; set; }
-}
diff --git a/EPPlus/OfficeProperties.cs b/EPPlus/OfficeProperties.cs
deleted file mode 100644
index e41d226..0000000
--- a/EPPlus/OfficeProperties.cs
+++ /dev/null
@@ -1,265 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan K�llman Total rewrite 2010-03-01
- * Jan K�llman License changed GPL-->LGPL 2011-12-27
- * Raziq York Added Created & Modified 2014-08-20
- *******************************************************************************/
-
-using System;
-using System.Globalization;
-using System.Xml;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Provides access to the properties bag of the package
-/// </summary>
-public sealed class OfficeProperties : XmlHelper {
- private readonly XmlDocument _xmlPropertiesCore;
- private readonly XmlDocument _xmlPropertiesExtended;
-
- private readonly Uri _uriPropertiesCore = new("/docProps/core.xml", UriKind.Relative);
- private readonly Uri _uriPropertiesExtended = new("/docProps/app.xml", UriKind.Relative);
-
- private readonly XmlHelper _coreHelper;
- private readonly XmlHelper _extendedHelper;
-
- /// <summary>
- /// Provides access to all the office document properties.
- /// </summary>
- /// <param name="package"></param>
- /// <param name="ns"></param>
- internal OfficeProperties(ExcelPackage package, XmlNamespaceManager ns)
- : base(ns) {
- const string coreBaseXml =
- $"""<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><cp:coreProperties xmlns:cp="{ExcelPackage._schemaCore}" xmlns:dc="{ExcelPackage._schemaDc}" xmlns:dcterms="{ExcelPackage._schemaDcTerms}" xmlns:dcmitype="{ExcelPackage._schemaDcmiType}" xmlns:xsi="{ExcelPackage._schemaXsi}"></cp:coreProperties>""";
- _xmlPropertiesCore = package.GetOrCreateXmlDocument(
- _uriPropertiesCore,
- "application/vnd.openxmlformats-package.core-properties+xml",
- "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
- coreBaseXml);
- _coreHelper = XmlHelperFactory.Create(
- ns,
- _xmlPropertiesCore.SelectSingleNode("cp:coreProperties", NameSpaceManager));
-
- const string extendedBaseXml =
- $"""<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><Properties xmlns:vt="{ExcelPackage._schemaVt}" xmlns="{ExcelPackage._schemaExtended}"></Properties>""";
- _xmlPropertiesExtended = package.GetOrCreateXmlDocument(
- _uriPropertiesExtended,
- "application/vnd.openxmlformats-officedocument.extended-properties+xml",
- "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
- extendedBaseXml);
- _extendedHelper = XmlHelperFactory.Create(ns, _xmlPropertiesExtended);
- }
-
- private const string _titlePath = "dc:title";
-
- /// <summary>
- /// Gets/sets the title property of the document (core property)
- /// </summary>
- public string Title {
- get => _coreHelper.GetXmlNodeString(_titlePath);
- set => _coreHelper.SetXmlNodeString(_titlePath, value);
- }
-
- private const string _subjectPath = "dc:subject";
-
- /// <summary>
- /// Gets/sets the subject property of the document (core property)
- /// </summary>
- public string Subject {
- get => _coreHelper.GetXmlNodeString(_subjectPath);
- set => _coreHelper.SetXmlNodeString(_subjectPath, value);
- }
-
- private const string _authorPath = "dc:creator";
-
- /// <summary>
- /// Gets/sets the author property of the document (core property)
- /// </summary>
- public string Author {
- get => _coreHelper.GetXmlNodeString(_authorPath);
- set => _coreHelper.SetXmlNodeString(_authorPath, value);
- }
-
- private const string _commentsPath = "dc:description";
-
- /// <summary>
- /// Gets/sets the comments property of the document (core property)
- /// </summary>
- public string Comments {
- get => _coreHelper.GetXmlNodeString(_commentsPath);
- set => _coreHelper.SetXmlNodeString(_commentsPath, value);
- }
-
- private const string _keywordsPath = "cp:keywords";
-
- /// <summary>
- /// Gets/sets the keywords property of the document (core property)
- /// </summary>
- public string Keywords {
- get => _coreHelper.GetXmlNodeString(_keywordsPath);
- set => _coreHelper.SetXmlNodeString(_keywordsPath, value);
- }
-
- private const string _lastModifiedByPath = "cp:lastModifiedBy";
-
- /// <summary>
- /// Gets/sets the lastModifiedBy property of the document (core property)
- /// </summary>
- public string LastModifiedBy {
- get => _coreHelper.GetXmlNodeString(_lastModifiedByPath);
- set => _coreHelper.SetXmlNodeString(_lastModifiedByPath, value);
- }
-
- private const string _lastPrintedPath = "cp:lastPrinted";
-
- /// <summary>
- /// Gets/sets the lastPrinted property of the document (core property)
- /// </summary>
- public string LastPrinted {
- get => _coreHelper.GetXmlNodeString(_lastPrintedPath);
- set => _coreHelper.SetXmlNodeString(_lastPrintedPath, value);
- }
-
- private const string _createdPath = "dcterms:created";
-
- /// <summary>
- /// Gets/sets the created property of the document (core property)
- /// </summary>
- public DateTime Created {
- get =>
- DateTime.TryParse(_coreHelper.GetXmlNodeString(_createdPath), out var date)
- ? date
- : DateTime.MinValue;
- set {
- var dateString = value.ToUniversalTime().ToString("s", CultureInfo.InvariantCulture) + "Z";
- _coreHelper.SetXmlNodeString(_createdPath, dateString);
- _coreHelper.SetXmlNodeString(_createdPath + "/@xsi:type", "dcterms:W3CDTF");
- }
- }
-
- private const string _categoryPath = "cp:category";
-
- /// <summary>
- /// Gets/sets the category property of the document (core property)
- /// </summary>
- public string Category {
- get => _coreHelper.GetXmlNodeString(_categoryPath);
- set => _coreHelper.SetXmlNodeString(_categoryPath, value);
- }
-
- private const string _contentStatusPath = "cp:contentStatus";
-
- /// <summary>
- /// Gets/sets the status property of the document (core property)
- /// </summary>
- public string Status {
- get => _coreHelper.GetXmlNodeString(_contentStatusPath);
- set => _coreHelper.SetXmlNodeString(_contentStatusPath, value);
- }
-
- /// <summary>
- /// Provides access to the XML document that holds the extended properties of the document (app.xml)
- /// </summary>
- public XmlDocument ExtendedPropertiesXml {
- get {
- if (_xmlPropertiesExtended == null) {}
- return (_xmlPropertiesExtended);
- }
- }
-
- private const string _applicationPath = "xp:Properties/xp:Application";
-
- /// <summary>
- /// Gets/Set the Application property of the document (extended property)
- /// </summary>
- public string Application {
- get => _extendedHelper.GetXmlNodeString(_applicationPath);
- set => _extendedHelper.SetXmlNodeString(_applicationPath, value);
- }
-
- private const string _hyperlinkBasePath = "xp:Properties/xp:HyperlinkBase";
-
- /// <summary>
- /// Gets/sets the HyperlinkBase property of the document (extended property)
- /// </summary>
- public Uri HyperlinkBase {
- get => new(_extendedHelper.GetXmlNodeString(_hyperlinkBasePath), UriKind.Absolute);
- set => _extendedHelper.SetXmlNodeString(_hyperlinkBasePath, value.AbsoluteUri);
- }
-
- private const string _appVersionPath = "xp:Properties/xp:AppVersion";
-
- /// <summary>
- /// Gets/Set the AppVersion property of the document (extended property)
- /// </summary>
- public string AppVersion {
- get => _extendedHelper.GetXmlNodeString(_appVersionPath);
- set => _extendedHelper.SetXmlNodeString(_appVersionPath, value);
- }
-
- private const string _companyPath = "xp:Properties/xp:Company";
-
- /// <summary>
- /// Gets/sets the Company property of the document (extended property)
- /// </summary>
- public string Company {
- get => _extendedHelper.GetXmlNodeString(_companyPath);
- set => _extendedHelper.SetXmlNodeString(_companyPath, value);
- }
-
- private const string _managerPath = "xp:Properties/xp:Manager";
-
- /// <summary>
- /// Gets/sets the Manager property of the document (extended property)
- /// </summary>
- public string Manager {
- get => _extendedHelper.GetXmlNodeString(_managerPath);
- set => _extendedHelper.SetXmlNodeString(_managerPath, value);
- }
-
- private const string _modifiedPath = "dcterms:modified";
-
- /// <summary>
- /// Gets/sets the modified property of the document (core property)
- /// </summary>
- public DateTime Modified {
- get =>
- DateTime.TryParse(_coreHelper.GetXmlNodeString(_modifiedPath), out var date)
- ? date
- : DateTime.MinValue;
- set {
- var dateString = value.ToUniversalTime().ToString("s", CultureInfo.InvariantCulture) + "Z";
- _coreHelper.SetXmlNodeString(_modifiedPath, dateString);
- _coreHelper.SetXmlNodeString(_modifiedPath + "/@xsi:type", "dcterms:W3CDTF");
- }
- }
-}
diff --git a/EPPlus/Packaging/ZipPackage.cs b/EPPlus/Packaging/ZipPackage.cs
deleted file mode 100644
index 921c744..0000000
--- a/EPPlus/Packaging/ZipPackage.cs
+++ /dev/null
@@ -1,263 +0,0 @@
-/*******************************************************************************
- * 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 25-Oct-2012
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.IO.Compression;
-using System.Linq;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Xml;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.Packaging;
-
-/// <summary>
-/// Specifies whether the target is inside or outside the System.IO.Packaging.Package.
-/// </summary>
-public enum TargetMode {
- /// <summary>
- /// The relationship references a part that is inside the package.
- /// </summary>
- Internal = 0,
-
- /// <summary>
- /// The relationship references a resource that is external to the package.
- /// </summary>
- External = 1,
-}
-
-/// <summary>
-/// Represent an OOXML Zip package.
-/// </summary>
-internal class ZipPackage : ZipPackageRelationshipBase {
- internal class ContentType {
- internal string Name;
- internal bool IsExtension;
- internal string Match;
-
- public ContentType(string name, bool isExtension, string match) {
- Name = name;
- IsExtension = isExtension;
- Match = match;
- }
- }
-
- private readonly Dictionary<string, ZipPackagePart> Parts = new(
- StringComparer.InvariantCultureIgnoreCase);
- internal Dictionary<string, ContentType> _contentTypes = new(
- StringComparer.InvariantCultureIgnoreCase);
-
- internal ZipPackage() {
- AddNew();
- }
-
- private void AddNew() {
- _contentTypes.Add("xml", new(ExcelPackage._schemaXmlExtension, true, "xml"));
- _contentTypes.Add("rels", new(ExcelPackage._schemaRelsExtension, true, "rels"));
- }
-
- internal ZipPackage(Stream stream) {
- bool hasContentTypeXml = false;
- if (stream == null || stream.Length == 0) {
- AddNew();
- } else {
- var rels = new Dictionary<string, ZipArchiveEntry>();
- stream.Seek(0, SeekOrigin.Begin);
- using var zip = new ZipArchive(stream, ZipArchiveMode.Read, leaveOpen: true);
- foreach (var e in zip.Entries) {
- if (e.Length > 0) {
- if (e.FullName.Equals(
- "[content_types].xml",
- StringComparison.InvariantCultureIgnoreCase)) {
- using var inputStream = e.Open();
- AddContentTypes(inputStream);
- hasContentTypeXml = true;
- } else if (e.FullName.Equals(
- "_rels/.rels",
- StringComparison.InvariantCultureIgnoreCase)) {
- using var inputStream = e.Open();
- ReadRelation(inputStream, "");
- } else {
- if (e.FullName.EndsWith(".rels", StringComparison.InvariantCultureIgnoreCase)) {
- rels.Add(GetUriKey(e.FullName), e);
- } else {
- var data = new byte[e.Length];
- using var inputStream = e.Open();
- inputStream.ReadExactly(data);
- var part = new ZipPackagePart(
- this,
- e,
- ImmutableCollectionsMarshal.AsImmutableArray(data));
- Parts.Add(GetUriKey(e.FullName), part);
- }
- }
- }
- }
- foreach (var p in Parts) {
- string name = Path.GetFileName(p.Key);
- string extension = Path.GetExtension(p.Key);
- string relFile = string.Format(
- "{0}_rels/{1}.rels",
- p.Key.Substring(0, p.Key.Length - name.Length),
- name);
- if (rels.TryGetValue(relFile, out var zipArchiveEntry)) {
- using var inputStream = zipArchiveEntry.Open();
- p.Value.ReadRelation(inputStream, p.Value.Uri.OriginalString);
- }
- if (_contentTypes.TryGetValue(p.Key, out var type)) {
- p.Value.ContentType = type.Name;
- } else if (extension.Length > 1 && _contentTypes.ContainsKey(extension.Substring(1))) {
- p.Value.ContentType = _contentTypes[extension.Substring(1)].Name;
- }
- }
- if (!hasContentTypeXml) {
- throw new InvalidDataException("The file is not an valid Package file.");
- }
- }
- }
-
- private void AddContentTypes(Stream inputStream) {
- var doc = new XmlDocument();
- XmlHelper.LoadXmlSafe(doc, inputStream);
-
- foreach (XmlElement c in doc.DocumentElement.ChildNodes) {
- ContentType ct;
- if (string.IsNullOrEmpty(c.GetAttribute("Extension"))) {
- ct = new(c.GetAttribute("ContentType"), false, c.GetAttribute("PartName"));
- } else {
- ct = new(c.GetAttribute("ContentType"), true, c.GetAttribute("Extension"));
- }
- _contentTypes.Add(GetUriKey(ct.Match), ct);
- }
- }
-
- internal void CreatePart(Uri partUri, string contentType, Action<StreamWriter> saveHandler) {
- if (PartExists(partUri)) {
- throw (new InvalidOperationException("Part already exist"));
- }
-
- var part = new ZipPackagePart(this, partUri, contentType, saveHandler);
- _contentTypes.Add(
- GetUriKey(part.Uri.OriginalString),
- new(contentType, false, part.Uri.OriginalString));
- Parts.Add(GetUriKey(part.Uri.OriginalString), part);
- }
-
- internal ZipPackagePart GetPart(Uri partUri) {
- if (PartExists(partUri)) {
- return Parts
- .Single(x =>
- x.Key.Equals(
- GetUriKey(partUri.OriginalString),
- StringComparison.InvariantCultureIgnoreCase))
- .Value;
- }
- throw (new InvalidOperationException("Part does not exist."));
- }
-
- internal string GetUriKey(string uri) {
- string ret = uri;
- if (ret[0] != '/') {
- ret = "/" + ret;
- }
- return ret;
- }
-
- internal bool PartExists(Uri partUri) {
- var uriKey = GetUriKey(partUri.OriginalString.ToLower(CultureInfo.InvariantCulture));
- return Parts.Keys.Any(x => x.Equals(uriKey, StringComparison.InvariantCultureIgnoreCase));
- }
-
- internal void DeletePart(Uri uri) {
- var delList = new List<object[]>();
- foreach (var p in Parts.Values) {
- foreach (var r in p.GetRelationships()) {
- if (UriHelper
- .ResolvePartUri(p.Uri, r.TargetUri)
- .OriginalString.Equals(
- uri.OriginalString,
- StringComparison.InvariantCultureIgnoreCase)) {
- delList.Add(new object[] { r.Id, p });
- }
- }
- }
- foreach (var o in delList) {
- ((ZipPackagePart)o[1]).DeleteRelationship(o[0].ToString());
- }
- var rels = GetPart(uri).GetRelationships();
- while (rels.Count > 0) {
- rels.Remove(rels.First().Id);
- }
- _contentTypes.Remove(GetUriKey(uri.OriginalString));
- //remove all relations
- Parts.Remove(GetUriKey(uri.OriginalString));
- }
-
- internal void Save(Stream stream) {
- using var zipArchive = new ZipArchive(stream, ZipArchiveMode.Create, leaveOpen: true);
- // Content types
- var contentTypesEntry = zipArchive.CreateEntry("[Content_Types].xml");
- using (var contentTypesWriter = new StreamWriter(contentTypesEntry.Open())) {
- contentTypesWriter.Write(GetContentTypeXml());
- }
- // Top Rels
- _rels.WriteZip(zipArchive, "_rels/.rels");
- ZipPackagePart ssPart = null;
- foreach (var part in Parts.Values) {
- if (part.ContentType != ExcelPackage._contentTypeSharedString) {
- part.WriteZip(zipArchive);
- } else {
- ssPart = part;
- }
- }
- //Shared strings must be saved after all worksheets. The ss dictionary is populated when that workheets are saved (to get the best performance).
- if (ssPart != null) {
- ssPart.WriteZip(zipArchive);
- }
- }
-
- private string GetContentTypeXml() {
- StringBuilder xml = new StringBuilder(
- "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">");
- foreach (ContentType ct in _contentTypes.Values) {
- if (ct.IsExtension) {
- xml.Append($"<Default ContentType=\"{ct.Name}\" Extension=\"{ct.Match}\"/>");
- } else {
- xml.Append($"<Override ContentType=\"{ct.Name}\" PartName=\"{GetUriKey(ct.Match)}\" />");
- }
- }
- xml.Append("</Types>");
- return xml.ToString();
- }
-}
diff --git a/EPPlus/Packaging/ZipPackagePart.cs b/EPPlus/Packaging/ZipPackagePart.cs
deleted file mode 100644
index 47d20fb..0000000
--- a/EPPlus/Packaging/ZipPackagePart.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-/*******************************************************************************
- * 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 25-Oct-2012
- *******************************************************************************/
-
-using System;
-using System.Collections.Immutable;
-using System.IO;
-using System.IO.Compression;
-using System.Runtime.InteropServices;
-
-namespace OfficeOpenXml.Packaging;
-
-internal class ZipPackagePart : ZipPackageRelationshipBase, IDisposable {
- internal ZipPackagePart(ZipPackage package, ZipArchiveEntry entry, ImmutableArray<byte> data) {
- Package = package;
- SaveHandler = null;
- Uri = new(package.GetUriKey(entry.FullName), UriKind.Relative);
- _data = data;
- }
-
- private readonly ImmutableArray<byte> _data;
-
- internal ZipPackagePart(
- ZipPackage package,
- Uri partUri,
- string contentType,
- Action<StreamWriter> saveHandler) {
- Package = package;
- Uri = partUri;
- ContentType = contentType;
- SaveHandler = saveHandler;
- }
-
- private ZipPackage Package { get; }
-
- internal override ZipPackageRelationship CreateRelationship(
- Uri targetUri,
- TargetMode targetMode,
- string relationshipType) {
- var rel = base.CreateRelationship(targetUri, targetMode, relationshipType);
- rel.SourceUri = Uri;
- return rel;
- }
-
- internal MemoryStream GetStream() {
- return new(ImmutableCollectionsMarshal.AsArray(_data) ?? [], false);
- }
-
- private string _contentType = "";
-
- public string ContentType {
- get => _contentType;
- internal set {
- if (!string.IsNullOrEmpty(_contentType)) {
- if (Package._contentTypes.ContainsKey(Package.GetUriKey(Uri.OriginalString))) {
- Package._contentTypes.Remove(Package.GetUriKey(Uri.OriginalString));
- Package._contentTypes.Add(
- Package.GetUriKey(Uri.OriginalString),
- new(value, false, Uri.OriginalString));
- }
- }
- _contentType = value;
- }
- }
-
- public Uri Uri { get; }
-
- internal Action<StreamWriter> SaveHandler { get; set; }
-
- internal void WriteZip(ZipArchive zipArchive) {
- if (SaveHandler == null) {
- if (_data.Length == 0) {
- return;
- }
- var zipEntry = zipArchive.CreateEntry(Uri.OriginalString);
- using var os = zipEntry.Open();
- os.Write(_data.AsSpan());
- } else {
- var zipEntry = zipArchive.CreateEntry(Uri.OriginalString);
- using var streamWriter = new StreamWriter(zipEntry.Open());
- SaveHandler(streamWriter);
- }
-
- if (_rels.Count > 0) {
- string f = Uri.OriginalString;
- var name = Path.GetFileName(f);
- _rels.WriteZip(zipArchive, $"{f.Substring(0, f.Length - name.Length)}_rels/{name}.rels");
- }
- }
-
- public void Dispose() {}
-}
diff --git a/EPPlus/Packaging/ZipPackageRelationship.cs b/EPPlus/Packaging/ZipPackageRelationship.cs
deleted file mode 100644
index 1d76501..0000000
--- a/EPPlus/Packaging/ZipPackageRelationship.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
- * 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 25-Oct-2012
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml.Packaging;
-
-internal class ZipPackageRelationship {
- public Uri TargetUri { get; internal set; }
-
- public Uri SourceUri { get; internal set; }
-
- public string RelationshipType { get; internal set; }
-
- public TargetMode TargetMode { get; internal set; }
-
- public string Id { get; internal set; }
-}
diff --git a/EPPlus/Packaging/ZipPackageRelationshipBase.cs b/EPPlus/Packaging/ZipPackageRelationshipBase.cs
deleted file mode 100644
index ff9bf8f..0000000
--- a/EPPlus/Packaging/ZipPackageRelationshipBase.cs
+++ /dev/null
@@ -1,123 +0,0 @@
-/*******************************************************************************
- * 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 25-Oct-2012
- *******************************************************************************/
-
-using System;
-using System.IO;
-using System.Xml;
-
-namespace OfficeOpenXml.Packaging;
-
-internal abstract class ZipPackageRelationshipBase {
- protected ZipPackageRelationshipCollection _rels = new();
- protected internal int maxRId = 1;
-
- internal void DeleteRelationship(string id) {
- _rels.Remove(id);
- UpdateMaxRId(id, ref maxRId);
- }
-
- protected void UpdateMaxRId(string id, ref int maxRId) {
- if (id.StartsWith("rId")) {
- if (int.TryParse(id.Substring(3), out var num)) {
- if (num == maxRId - 1) {
- maxRId--;
- }
- }
- }
- }
-
- internal virtual ZipPackageRelationship CreateRelationship(
- Uri targetUri,
- TargetMode targetMode,
- string relationshipType) {
- var rel = new ZipPackageRelationship();
- rel.TargetUri = targetUri;
- rel.TargetMode = targetMode;
- rel.RelationshipType = relationshipType;
- rel.Id = "rId" + (maxRId++);
- _rels.Add(rel);
- return rel;
- }
-
- internal bool RelationshipExists(string id) {
- return _rels.ContainsKey(id);
- }
-
- internal ZipPackageRelationshipCollection GetRelationshipsByType(string schema) {
- return _rels.GetRelationshipsByType(schema);
- }
-
- internal ZipPackageRelationshipCollection GetRelationships() {
- return _rels;
- }
-
- internal ZipPackageRelationship GetRelationship(string id) {
- return _rels[id];
- }
-
- internal void ReadRelation(Stream inputStream, string source) {
- var doc = new XmlDocument();
- XmlHelper.LoadXmlSafe(doc, inputStream);
-
- foreach (XmlElement c in doc.DocumentElement.ChildNodes) {
- var rel = new ZipPackageRelationship();
- rel.Id = c.GetAttribute("Id");
- rel.RelationshipType = c.GetAttribute("Type");
- rel.TargetMode = c.GetAttribute("TargetMode")
- .Equals("external", StringComparison.InvariantCultureIgnoreCase)
- ? TargetMode.External
- : TargetMode.Internal;
- try {
- rel.TargetUri = new(c.GetAttribute("Target"), UriKind.RelativeOrAbsolute);
- } catch {
- //The URI is not a valid URI. Encode it to make i valid.
- rel.TargetUri = new(
- Uri.EscapeUriString("Invalid:URI " + c.GetAttribute("Target")),
- UriKind.RelativeOrAbsolute);
- }
- if (!string.IsNullOrEmpty(source)) {
- rel.SourceUri = new(source, UriKind.Relative);
- }
- if (rel.Id.StartsWith("rid", StringComparison.InvariantCultureIgnoreCase)) {
- if (int.TryParse(rel.Id.Substring(3), out var id)) {
- if (id >= maxRId
- && id
- < int.MaxValue
- - 10000) //Not likly to have this high id's but make sure we have space to avoid overflow.
- {
- maxRId = id + 1;
- }
- }
- }
- _rels.Add(rel);
- }
- }
-}
diff --git a/EPPlus/Packaging/ZipPackageRelationshipCollection.cs b/EPPlus/Packaging/ZipPackageRelationshipCollection.cs
deleted file mode 100644
index 7890ad6..0000000
--- a/EPPlus/Packaging/ZipPackageRelationshipCollection.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-/*******************************************************************************
- * 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 25-Oct-2012
- *******************************************************************************/
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using System.IO.Compression;
-using System.Security;
-
-namespace OfficeOpenXml.Packaging;
-
-internal class ZipPackageRelationshipCollection : IEnumerable<ZipPackageRelationship> {
- protected internal Dictionary<string, ZipPackageRelationship> _rels = new(
- StringComparer.InvariantCultureIgnoreCase);
-
- internal void Add(ZipPackageRelationship item) {
- _rels.Add(item.Id, item);
- }
-
- public IEnumerator<ZipPackageRelationship> GetEnumerator() {
- return _rels.Values.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- return _rels.Values.GetEnumerator();
- }
-
- internal void Remove(string id) {
- _rels.Remove(id);
- }
-
- internal bool ContainsKey(string id) {
- return _rels.ContainsKey(id);
- }
-
- internal ZipPackageRelationship this[string id] => _rels[id];
-
- internal ZipPackageRelationshipCollection GetRelationshipsByType(string relationshipType) {
- var ret = new ZipPackageRelationshipCollection();
- foreach (var rel in _rels.Values) {
- if (rel.RelationshipType == relationshipType) {
- ret.Add(rel);
- }
- }
- return ret;
- }
-
- internal void WriteZip(ZipArchive zipArchive, string filename) {
- var entry = zipArchive.CreateEntry(filename);
- using var writer = new StreamWriter(entry.Open());
-
- writer.Write(
- "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">");
- foreach (var rel in _rels.Values) {
- writer.Write(
- "<Relationship Id=\"{0}\" Type=\"{1}\" Target=\"{2}\"{3}/>",
- SecurityElement.Escape(rel.Id),
- rel.RelationshipType,
- SecurityElement.Escape(rel.TargetUri.OriginalString),
- rel.TargetMode == TargetMode.External ? " TargetMode=\"External\"" : "");
- }
- writer.Write("</Relationships>");
- }
-
- public int Count => _rels.Count;
-}
diff --git a/EPPlus/RangeCollection.cs b/EPPlus/RangeCollection.cs
deleted file mode 100644
index c7f8218..0000000
--- a/EPPlus/RangeCollection.cs
+++ /dev/null
@@ -1,277 +0,0 @@
-/*******************************************************************************
- * 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 2010-02-04
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// This is the store for all Rows, Columns and Cells.
-/// It is a Dictionary implementation that allows you to change the Key (the RowID, ColumnID or CellID )
-/// </summary>
-internal class RangeCollection : IEnumerator<IRangeId>, IEnumerable, IDisposable {
- private class IndexItem {
- internal IndexItem(ulong cellId) {
- RangeID = cellId;
- }
-
- internal IndexItem(ulong cellId, int listPointer) {
- RangeID = cellId;
- ListPointer = listPointer;
- }
-
- internal ulong RangeID;
- internal int ListPointer;
- }
-
- /// <summary>
- /// Compares an IndexItem
- /// </summary>
- internal class Compare : IComparer<IndexItem> {
- int IComparer<IndexItem>.Compare(IndexItem x, IndexItem y) {
- return x.RangeID < y.RangeID
- ? -1
- : x.RangeID > y.RangeID
- ? 1
- : 0;
- }
- }
-
- private IndexItem[] _cellIndex;
- private List<IRangeId> _cells;
- private static readonly Compare _comparer = new();
-
- /// <summary>
- /// Creates a new collection
- /// </summary>
- /// <param name="cells">The Cells. This list must be sorted</param>
- internal RangeCollection(List<IRangeId> cells) {
- _cells = cells;
- InitSize(_cells);
- for (int i = 0; i < _cells.Count; i++) {
- _cellIndex[i] = new(cells[i].RangeID, i);
- }
- }
-
- ~RangeCollection() {
- _cells = null;
- _cellIndex = null;
- }
-
- /// <summary>
- /// Return the item with the RangeID
- /// </summary>
- /// <param name="rangeId"></param>
- /// <returns></returns>
- internal IRangeId this[ulong rangeId] => _cells[_cellIndex[IndexOf(rangeId)].ListPointer];
-
- /// <summary>
- /// Return specified index from the sorted list
- /// </summary>
- /// <param name="index"></param>
- /// <returns></returns>
- internal IRangeId this[int index] => _cells[_cellIndex[index].ListPointer];
-
- internal int Count => _cells.Count;
-
- internal void Add(IRangeId cell) {
- var ix = IndexOf(cell.RangeID);
- if (ix >= 0) {
- throw (new("Item already exists"));
- }
- Insert(~ix, cell);
- }
-
- internal void Delete(ulong key) {
- var ix = IndexOf(key);
- if (ix < 0) {
- throw (new("Key does not exists"));
- }
- int listPointer = _cellIndex[ix].ListPointer;
- Array.Copy(_cellIndex, ix + 1, _cellIndex, ix, _cells.Count - ix - 1);
- _cells.RemoveAt(listPointer);
-
- //Item is removed subtract one from all items with greater ListPointer
- for (int i = 0; i < _cells.Count; i++) {
- if (_cellIndex[i].ListPointer >= listPointer) {
- _cellIndex[i].ListPointer--;
- }
- }
- }
-
- internal int IndexOf(ulong key) {
- return Array.BinarySearch(_cellIndex, 0, _cells.Count, new(key), _comparer);
- }
-
- internal bool ContainsKey(ulong key) {
- return IndexOf(key) < 0 ? false : true;
- }
-
- private int _size { get; set; }
-
- /// <summary>
- /// Insert a number of rows in the collecion but dont update the cell only the index
- /// </summary>
- /// <param name="rowId"></param>
- /// <param name="rows"></param>
- /// <returns>Index of first rangeItem</returns>
- internal int InsertRowsUpdateIndex(ulong rowId, int rows) {
- int index = IndexOf(rowId);
- if (index < 0) {
- index = ~index; //No match found invert to get start cell
- }
- ulong rowAdd = (((ulong)rows) << 29);
- for (int i = index; i < _cells.Count; i++) {
- _cellIndex[i].RangeID += rowAdd;
- }
- return index;
- }
-
- /// <summary>
- /// Insert a number of rows in the collecion
- /// </summary>
- /// <param name="rowId"></param>
- /// <param name="rows"></param>
- /// <returns>Index of first rangeItem</returns>
- internal int InsertRows(ulong rowId, int rows) {
- int index = IndexOf(rowId);
- if (index < 0) {
- index = ~index; //No match found invert to get start cell
- }
- ulong rowAdd = (((ulong)rows) << 29);
- for (int i = index; i < _cells.Count; i++) {
- _cellIndex[i].RangeID += rowAdd;
- _cells[_cellIndex[i].ListPointer].RangeID += rowAdd;
- }
- return index;
- }
-
- /// <summary>
- /// Delete rows from the collecion
- /// </summary>
- /// <param name="rowId"></param>
- /// <param name="rows"></param>
- /// <param name="updateCells">Update range id's on cells</param>
- internal int DeleteRows(ulong rowId, int rows, bool updateCells) {
- ulong rowAdd = (((ulong)rows) << 29);
- var index = IndexOf(rowId);
- if (index < 0) {
- index = ~index; //No match found invert to get start cell
- }
-
- if (index >= _cells.Count || _cellIndex[index] == null) {
- return -1; //No row above this row
- }
- while (index < _cells.Count && _cellIndex[index].RangeID < rowId + rowAdd) {
- Delete(_cellIndex[index].RangeID);
- }
-
- int updIndex = IndexOf(rowId + rowAdd);
- if (updIndex < 0) {
- updIndex = ~updIndex; //No match found invert to get start cell
- }
-
- for (int i = updIndex; i < _cells.Count; i++) {
- _cellIndex[i].RangeID -= rowAdd; //Change the index
- if (updateCells) {
- _cells[_cellIndex[i].ListPointer].RangeID -= rowAdd; //Change the cell/row or column object
- }
- }
- return index;
- }
-
- internal void InsertColumn(ulong columnId, int columns) {
- throw (new("Working on it..."));
- }
-
- internal void DeleteColumn(ulong columnId, int columns) {
- throw (new("Working on it..."));
- }
-
- /// <summary>
- /// Init the size starting from 128 items. Double the size until the list fits.
- /// </summary>
- /// <param name="_cells"></param>
- private void InitSize(List<IRangeId> cells) {
- _size = 128;
- while (cells.Count > _size) {
- _size <<= 1;
- }
- _cellIndex = new IndexItem[_size];
- }
-
- /// <summary>
- /// Check the size and double the size if out of bound
- /// </summary>
- private void CheckSize() {
- if (_cells.Count >= _size) {
- _size <<= 1;
- Array.Resize(ref _cellIndex, _size);
- }
- }
-
- private void Insert(int ix, IRangeId cell) {
- CheckSize();
- Array.Copy(_cellIndex, ix, _cellIndex, ix + 1, _cells.Count - ix);
- _cellIndex[ix] = new(cell.RangeID, _cells.Count);
- _cells.Add(cell);
- }
-
- IRangeId IEnumerator<IRangeId>.Current {
- get { throw new NotImplementedException(); }
- }
-
- void IDisposable.Dispose() {
- _ix = -1;
- }
-
- private int _ix = -1;
-
- object IEnumerator.Current {
- get { return _cells[_cellIndex[_ix].ListPointer]; }
- }
-
- bool IEnumerator.MoveNext() {
- _ix++;
- return _ix < _cells.Count;
- }
-
- void IEnumerator.Reset() {
- _ix = -1;
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- return MemberwiseClone() as IEnumerator;
- }
-}
diff --git a/EPPlus/Style/Dxf/DxfStyleBase.cs b/EPPlus/Style/Dxf/DxfStyleBase.cs
deleted file mode 100644
index b81e07a..0000000
--- a/EPPlus/Style/Dxf/DxfStyleBase.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-using System;
-using System.Globalization;
-
-namespace OfficeOpenXml.Style.Dxf;
-
-public abstract class DxfStyleBase<T> {
- protected ExcelStyles _styles;
-
- internal DxfStyleBase(ExcelStyles styles) {
- _styles = styles;
- }
-
- protected internal abstract string Id { get; }
-
- protected internal abstract bool HasValue { get; }
-
- protected internal abstract void CreateNodes(XmlHelper helper, string path);
-
- protected internal abstract T Clone();
-
- protected void SetValueColor(XmlHelper helper, string path, ExcelDxfColor color) {
- if (color != null && color.HasValue) {
- if (color.Rgb != null) {
- SetValue(helper, path + "/@rgb", color.Rgb);
- } else if (color.Auto != null) {
- SetValueBool(helper, path + "/@auto", color.Auto);
- } else if (color.Theme != null) {
- SetValue(helper, path + "/@theme", color.Theme);
- } else if (color.Index != null) {
- SetValue(helper, path + "/@indexed", color.Index);
- }
- if (color.Tint != null) {
- SetValue(helper, path + "/@tint", color.Tint);
- }
- }
- }
-
- /// <summary>
- /// Same as SetValue but will set first char to lower case.
- /// </summary>
- /// <param name="helper"></param>
- /// <param name="path"></param>
- /// <param name="v"></param>
- protected void SetValueEnum(XmlHelper helper, string path, Enum v) {
- if (v == null) {
- helper.DeleteNode(path);
- } else {
- var s = v.ToString();
- s = s.Substring(0, 1).ToLower(CultureInfo.InvariantCulture) + s.Substring(1);
- helper.SetXmlNodeString(path, s);
- }
- }
-
- protected void SetValue(XmlHelper helper, string path, object v) {
- if (v == null) {
- helper.DeleteNode(path);
- } else {
- helper.SetXmlNodeString(path, v.ToString());
- }
- }
-
- protected void SetValueBool(XmlHelper helper, string path, bool? v) {
- if (v == null) {
- helper.DeleteNode(path);
- } else {
- helper.SetXmlNodeBool(path, (bool)v);
- }
- }
-
- protected string GetAsString(object v) {
- return (v ?? "").ToString();
- }
-
- /// <summary>
- /// Is this value allowed to be changed?
- /// </summary>
- protected internal bool AllowChange { get; set; } = false;
-}
diff --git a/EPPlus/Style/Dxf/ExcelDxfBorder.cs b/EPPlus/Style/Dxf/ExcelDxfBorder.cs
deleted file mode 100644
index 12bcc84..0000000
--- a/EPPlus/Style/Dxf/ExcelDxfBorder.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-namespace OfficeOpenXml.Style.Dxf;
-
-public class ExcelDxfBorderBase : DxfStyleBase<ExcelDxfBorderBase> {
- internal ExcelDxfBorderBase(ExcelStyles styles)
- : base(styles) {
- Left = new(_styles);
- Right = new(_styles);
- Top = new(_styles);
- Bottom = new(_styles);
- }
-
- /// <summary>
- /// Left border style
- /// </summary>
- public ExcelDxfBorderItem Left { get; internal set; }
-
- /// <summary>
- /// Right border style
- /// </summary>
- public ExcelDxfBorderItem Right { get; internal set; }
-
- /// <summary>
- /// Top border style
- /// </summary>
- public ExcelDxfBorderItem Top { get; internal set; }
-
- /// <summary>
- /// Bottom border style
- /// </summary>
- public ExcelDxfBorderItem Bottom { get; internal set; }
-
- ///// <summary>
- ///// Diagonal border style
- ///// </summary>
- //public ExcelDxfBorderItem Diagonal
- //{
- // get;
- // private set;
- //}
- ///// <summary>
- ///// A diagonal from the bottom left to top right of the cell
- ///// </summary>
- //public bool DiagonalUp
- //{
- // get;
- // set;
- //}
- ///// <summary>
- ///// A diagonal from the top left to bottom right of the cell
- ///// </summary>
- //public bool DiagonalDown
- //{
- // get;
- // set;
- //}
-
- protected internal override string Id =>
- Top.Id
- + Bottom.Id
- + Left.Id
- + Right.Id /* + Diagonal.Id + GetAsString(DiagonalUp) + GetAsString(DiagonalDown)*/;
-
- protected internal override void CreateNodes(XmlHelper helper, string path) {
- Left.CreateNodes(helper, path + "/d:left");
- Right.CreateNodes(helper, path + "/d:right");
- Top.CreateNodes(helper, path + "/d:top");
- Bottom.CreateNodes(helper, path + "/d:bottom");
- }
-
- protected internal override bool HasValue =>
- Left.HasValue || Right.HasValue || Top.HasValue || Bottom.HasValue;
-
- protected internal override ExcelDxfBorderBase Clone() {
- return new(_styles) {
- Bottom = Bottom.Clone(),
- Top = Top.Clone(),
- Left = Left.Clone(),
- Right = Right.Clone(),
- };
- }
-}
diff --git a/EPPlus/Style/Dxf/ExcelDxfBorderItem.cs b/EPPlus/Style/Dxf/ExcelDxfBorderItem.cs
deleted file mode 100644
index f068605..0000000
--- a/EPPlus/Style/Dxf/ExcelDxfBorderItem.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-namespace OfficeOpenXml.Style.Dxf;
-
-public class ExcelDxfBorderItem : DxfStyleBase<ExcelDxfBorderItem> {
- internal ExcelDxfBorderItem(ExcelStyles styles)
- : base(styles) {
- Color = new(styles);
- }
-
- public ExcelBorderStyle? Style { get; set; }
-
- public ExcelDxfColor Color { get; internal set; }
-
- protected internal override string Id =>
- GetAsString(Style) + "|" + (Color == null ? "" : Color.Id);
-
- protected internal override void CreateNodes(XmlHelper helper, string path) {
- SetValueEnum(helper, path + "/@style", Style);
- SetValueColor(helper, path + "/d:color", Color);
- }
-
- protected internal override bool HasValue => Style != null || Color.HasValue;
-
- protected internal override ExcelDxfBorderItem Clone() {
- return new(_styles) {
- Style = Style,
- Color = Color,
- };
- }
-}
diff --git a/EPPlus/Style/Dxf/ExcelDxfColor.cs b/EPPlus/Style/Dxf/ExcelDxfColor.cs
deleted file mode 100644
index d22a7f9..0000000
--- a/EPPlus/Style/Dxf/ExcelDxfColor.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using System;
-
-namespace OfficeOpenXml.Style.Dxf;
-
-public class ExcelDxfColor : DxfStyleBase<ExcelDxfColor> {
- public ExcelDxfColor(ExcelStyles styles)
- : base(styles) {}
-
- public int? Theme { get; set; }
-
- public int? Index { get; set; }
-
- public bool? Auto { get; set; }
-
- public double? Tint { get; set; }
-
- public string Rgb { get; set; }
-
- protected internal override string Id =>
- GetAsString(Theme)
- + "|"
- + GetAsString(Index)
- + "|"
- + GetAsString(Auto)
- + "|"
- + GetAsString(Tint)
- + "|"
- + GetAsString(Rgb);
-
- protected internal override ExcelDxfColor Clone() {
- return new(_styles) {
- Theme = Theme,
- Index = Index,
- Rgb = Rgb,
- Auto = Auto,
- Tint = Tint,
- };
- }
-
- protected internal override bool HasValue =>
- Theme != null || Index != null || Auto != null || Tint != null || Rgb != null;
-
- protected internal override void CreateNodes(XmlHelper helper, string path) {
- throw new NotImplementedException();
- }
-}
diff --git a/EPPlus/Style/Dxf/ExcelDxfFill.cs b/EPPlus/Style/Dxf/ExcelDxfFill.cs
deleted file mode 100644
index f4bf1d3..0000000
--- a/EPPlus/Style/Dxf/ExcelDxfFill.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-namespace OfficeOpenXml.Style.Dxf;
-
-public class ExcelDxfFill : DxfStyleBase<ExcelDxfFill> {
- public ExcelDxfFill(ExcelStyles styles)
- : base(styles) {
- PatternColor = new(styles);
- BackgroundColor = new(styles);
- }
-
- public ExcelFillStyle? PatternType { get; set; }
-
- /// <summary>
- /// The color of the pattern
- /// </summary>
- public ExcelDxfColor PatternColor { get; internal set; }
-
- /// <summary>
- /// The background color
- /// </summary>
- public ExcelDxfColor BackgroundColor { get; internal set; }
-
- protected internal override string Id =>
- GetAsString(PatternType)
- + "|"
- + (PatternColor == null ? "" : PatternColor.Id)
- + "|"
- + (BackgroundColor == null ? "" : BackgroundColor.Id);
-
- protected internal override void CreateNodes(XmlHelper helper, string path) {
- helper.CreateNode(path);
- SetValueEnum(helper, path + "/d:patternFill/@patternType", PatternType);
- SetValueColor(helper, path + "/d:patternFill/d:fgColor", PatternColor);
- SetValueColor(helper, path + "/d:patternFill/d:bgColor", BackgroundColor);
- }
-
- protected internal override bool HasValue =>
- PatternType != null || PatternColor.HasValue || BackgroundColor.HasValue;
-
- protected internal override ExcelDxfFill Clone() {
- return new(_styles) {
- PatternType = PatternType,
- PatternColor = PatternColor.Clone(),
- BackgroundColor = BackgroundColor.Clone(),
- };
- }
-}
diff --git a/EPPlus/Style/Dxf/ExcelDxfFontBase.cs b/EPPlus/Style/Dxf/ExcelDxfFontBase.cs
deleted file mode 100644
index aae7d61..0000000
--- a/EPPlus/Style/Dxf/ExcelDxfFontBase.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-namespace OfficeOpenXml.Style.Dxf;
-
-public class ExcelDxfFontBase : DxfStyleBase<ExcelDxfFontBase> {
- public ExcelDxfFontBase(ExcelStyles styles)
- : base(styles) {
- Color = new(styles);
- }
-
- /// <summary>
- /// Font bold
- /// </summary>
- public bool? Bold { get; set; }
-
- /// <summary>
- /// Font Italic
- /// </summary>
- public bool? Italic { get; set; }
-
- /// <summary>
- /// Font-Strikeout
- /// </summary>
- public bool? Strike { get; set; }
-
- //public float? Size { get; set; }
- public ExcelDxfColor Color { get; set; }
-
- //public string Name { get; set; }
- //public int? Family { get; set; }
- ///// <summary>
- ///// Font-Vertical Align
- ///// </summary>
- //public ExcelVerticalAlignmentFont? VerticalAlign
- //{
- // get;
- // set;
- //}
-
- public ExcelUnderLineType? Underline { get; set; }
-
- protected internal override string Id =>
- GetAsString(Bold)
- + "|"
- + GetAsString(Italic)
- + "|"
- + GetAsString(Strike)
- + "|"
- + (Color == null ? "" : Color.Id)
- + "|" /*+ GetAsString(VerticalAlign) + "|"*/
- + GetAsString(Underline);
-
- protected internal override void CreateNodes(XmlHelper helper, string path) {
- helper.CreateNode(path);
- SetValueBool(helper, path + "/d:b/@val", Bold);
- SetValueBool(helper, path + "/d:i/@val", Italic);
- SetValueBool(helper, path + "/d:strike", Strike);
- SetValue(helper, path + "/d:u/@val", Underline);
- SetValueColor(helper, path + "/d:color", Color);
- }
-
- protected internal override bool HasValue =>
- Bold != null || Italic != null || Strike != null || Underline != null || Color.HasValue;
-
- protected internal override ExcelDxfFontBase Clone() {
- return new(_styles) {
- Bold = Bold,
- Color = Color.Clone(),
- Italic = Italic,
- Strike = Strike,
- Underline = Underline,
- };
- }
-}
diff --git a/EPPlus/Style/Dxf/ExcelDxfNumberFormat.cs b/EPPlus/Style/Dxf/ExcelDxfNumberFormat.cs
deleted file mode 100644
index e00114c..0000000
--- a/EPPlus/Style/Dxf/ExcelDxfNumberFormat.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-namespace OfficeOpenXml.Style.Dxf;
-
-public class ExcelDxfNumberFormat : DxfStyleBase<ExcelDxfNumberFormat> {
- public ExcelDxfNumberFormat(ExcelStyles styles)
- : base(styles) {}
-
- private int _numFmtID = int.MinValue;
-
- /// <summary>
- /// Id for number format
- ///
- /// Build in ID's
- ///
- /// 0 General
- /// 1 0
- /// 2 0.00
- /// 3 #,##0
- /// 4 #,##0.00
- /// 9 0%
- /// 10 0.00%
- /// 11 0.00E+00
- /// 12 # ?/?
- /// 13 # ??/??
- /// 14 mm-dd-yy
- /// 15 d-mmm-yy
- /// 16 d-mmm
- /// 17 mmm-yy
- /// 18 h:mm AM/PM
- /// 19 h:mm:ss AM/PM
- /// 20 h:mm
- /// 21 h:mm:ss
- /// 22 m/d/yy h:mm
- /// 37 #,##0 ;(#,##0)
- /// 38 #,##0 ;[Red](#,##0)
- /// 39 #,##0.00;(#,##0.00)
- /// 40 #,##0.00;[Red](#,##0.00)
- /// 45 mm:ss
- /// 46 [h]:mm:ss
- /// 47 mmss.0
- /// 48 ##0.0E+0
- /// 49 @
- /// </summary>
- public int NumFmtID {
- get => _numFmtID;
- internal set => _numFmtID = value;
- }
-
- private string _format = "";
-
- public string Format {
- get => _format;
- set {
- _format = value;
- NumFmtID = ExcelNumberFormat.GetFromBuildIdFromFormat(value);
- }
- }
-
- protected internal override string Id => Format;
-
- protected internal override void CreateNodes(XmlHelper helper, string path) {
- if (NumFmtID < 0 && !string.IsNullOrEmpty(Format)) {
- NumFmtID = _styles._nextDfxNumFmtID++;
- }
- helper.CreateNode(path);
- SetValue(helper, path + "/@numFmtId", NumFmtID);
- SetValue(helper, path + "/@formatCode", Format);
- }
-
- protected internal override bool HasValue => !string.IsNullOrEmpty(Format);
-
- protected internal override ExcelDxfNumberFormat Clone() {
- return new(_styles) {
- NumFmtID = NumFmtID,
- Format = Format,
- };
- }
-}
diff --git a/EPPlus/Style/Dxf/ExcelDxfStyle.cs b/EPPlus/Style/Dxf/ExcelDxfStyle.cs
deleted file mode 100644
index 4784a1e..0000000
--- a/EPPlus/Style/Dxf/ExcelDxfStyle.cs
+++ /dev/null
@@ -1,135 +0,0 @@
-using System;
-using System.Collections.Immutable;
-using System.Globalization;
-using System.Xml;
-
-namespace OfficeOpenXml.Style.Dxf;
-
-public class ExcelDxfStyleConditionalFormatting : DxfStyleBase<ExcelDxfStyleConditionalFormatting> {
- private readonly DxfStyleXmlHelper _helper;
-
- private class DxfStyleXmlHelper(XmlNamespaceManager nameSpaceManager, XmlNode topNode)
- : XmlHelper(nameSpaceManager, topNode) {
- protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
- "font",
- "numFmt",
- "fill",
- "border",
- ];
- }
-
- internal ExcelDxfStyleConditionalFormatting(
- XmlNamespaceManager nameSpaceManager,
- XmlNode topNode,
- ExcelStyles styles)
- : base(styles) {
- NumberFormat = new(_styles);
- Font = new(_styles);
- Border = new(_styles);
- Fill = new(_styles);
- if (topNode != null) {
- _helper = new(nameSpaceManager, topNode);
- NumberFormat.NumFmtID = _helper.GetXmlNodeInt("d:numFmt/@numFmtId");
- NumberFormat.Format = _helper.GetXmlNodeString("d:numFmt/@formatCode");
- if (NumberFormat.NumFmtID < 164 && string.IsNullOrEmpty(NumberFormat.Format)) {
- NumberFormat.Format = ExcelNumberFormat.GetFromBuildInFromId(NumberFormat.NumFmtID);
- }
-
- Font.Bold = _helper.GetXmlNodeBoolNullable("d:font/d:b/@val");
- Font.Italic = _helper.GetXmlNodeBoolNullable("d:font/d:i/@val");
- Font.Strike = _helper.GetXmlNodeBoolNullable("d:font/d:strike");
- Font.Underline = GetUnderLineEnum(_helper.GetXmlNodeString("d:font/d:u/@val"));
- Font.Color = GetColor(_helper, "d:font/d:color");
-
- Border.Left = GetBorderItem(_helper, "d:border/d:left");
- Border.Right = GetBorderItem(_helper, "d:border/d:right");
- Border.Bottom = GetBorderItem(_helper, "d:border/d:bottom");
- Border.Top = GetBorderItem(_helper, "d:border/d:top");
-
- Fill.PatternType = GetPatternTypeEnum(
- _helper.GetXmlNodeString("d:fill/d:patternFill/@patternType"));
- Fill.BackgroundColor = GetColor(_helper, "d:fill/d:patternFill/d:bgColor/");
- Fill.PatternColor = GetColor(_helper, "d:fill/d:patternFill/d:fgColor/");
- } else {
- _helper = new(nameSpaceManager, null);
- }
- }
-
- private ExcelDxfBorderItem GetBorderItem(XmlHelper helper, string path) {
- ExcelDxfBorderItem bi = new ExcelDxfBorderItem(_styles);
- bi.Style = GetBorderStyleEnum(helper.GetXmlNodeString(path + "/@style"));
- bi.Color = GetColor(helper, path + "/d:color");
- return bi;
- }
-
- private ExcelBorderStyle GetBorderStyleEnum(string style) =>
- Enum.TryParse<ExcelBorderStyle>(style, true, out var result) ? result : ExcelBorderStyle.None;
-
- private ExcelFillStyle GetPatternTypeEnum(string patternType) =>
- Enum.TryParse<ExcelFillStyle>(patternType, true, out var result) ? result : ExcelFillStyle.None;
-
- private ExcelDxfColor GetColor(XmlHelper helper, string path) {
- ExcelDxfColor ret = new ExcelDxfColor(_styles);
- ret.Theme = helper.GetXmlNodeIntNull(path + "/@theme");
- ret.Index = helper.GetXmlNodeIntNull(path + "/@indexed");
- ret.Rgb = helper.GetXmlNodeString(path + "/@rgb");
- ret.Auto = helper.GetXmlNodeBoolNullable(path + "/@auto");
- ret.Tint = helper.GetXmlNodeDoubleNull(path + "/@tint");
- return ret;
- }
-
- private ExcelUnderLineType? GetUnderLineEnum(string value) {
- switch (value.ToLower(CultureInfo.InvariantCulture)) {
- case "single":
- return ExcelUnderLineType.Single;
- case "double":
- return ExcelUnderLineType.Double;
- case "singleaccounting":
- return ExcelUnderLineType.SingleAccounting;
- case "doubleaccounting":
- return ExcelUnderLineType.DoubleAccounting;
- default:
- return null;
- }
- }
-
- internal int DxfId { get; set; }
-
- public ExcelDxfFontBase Font { get; set; }
-
- public ExcelDxfNumberFormat NumberFormat { get; set; }
-
- public ExcelDxfFill Fill { get; set; }
-
- public ExcelDxfBorderBase Border { get; set; }
-
- protected internal override string Id =>
- NumberFormat.Id + Font.Id + Border.Id + Fill.Id + (AllowChange ? "" : DxfId.ToString()); //If allowchange is false we add the dxfID to ensure it's not used when conditional formatting is updated);
-
- protected internal override ExcelDxfStyleConditionalFormatting Clone() {
- var s = new ExcelDxfStyleConditionalFormatting(_helper.NameSpaceManager, null, _styles);
- s.Font = Font.Clone();
- s.NumberFormat = NumberFormat.Clone();
- s.Fill = Fill.Clone();
- s.Border = Border.Clone();
- return s;
- }
-
- protected internal override void CreateNodes(XmlHelper helper, string path) {
- if (Font.HasValue) {
- Font.CreateNodes(helper, "d:font");
- }
- if (NumberFormat.HasValue) {
- NumberFormat.CreateNodes(helper, "d:numFmt");
- }
- if (Fill.HasValue) {
- Fill.CreateNodes(helper, "d:fill");
- }
- if (Border.HasValue) {
- Border.CreateNodes(helper, "d:border");
- }
- }
-
- protected internal override bool HasValue =>
- Font.HasValue || NumberFormat.HasValue || Fill.HasValue || Border.HasValue;
-}
diff --git a/EPPlus/Style/ExcelBorder.cs b/EPPlus/Style/ExcelBorder.cs
deleted file mode 100644
index 55889fb..0000000
--- a/EPPlus/Style/ExcelBorder.cs
+++ /dev/null
@@ -1,105 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-namespace OfficeOpenXml.Style;
-
-/// <summary>
-/// Cell Border style
-/// </summary>
-public sealed class Border : StyleBase {
- internal Border(
- ExcelStyles styles,
- XmlHelper.ChangedEventHandler changedEvent,
- int positionId,
- string address,
- int index)
- : base(styles, changedEvent, positionId, address) {
- Index = index;
- }
-
- /// <summary>
- /// Left border style
- /// </summary>
- public ExcelBorderItem Left =>
- new(_styles, _ChangedEvent, _positionID, _address, eStyleClass.BorderLeft, this);
-
- /// <summary>
- /// Right border style
- /// </summary>
- public ExcelBorderItem Right =>
- new(_styles, _ChangedEvent, _positionID, _address, eStyleClass.BorderRight, this);
-
- /// <summary>
- /// Top border style
- /// </summary>
- public ExcelBorderItem Top =>
- new(_styles, _ChangedEvent, _positionID, _address, eStyleClass.BorderTop, this);
-
- /// <summary>
- /// Bottom border style
- /// </summary>
- public ExcelBorderItem Bottom =>
- new(_styles, _ChangedEvent, _positionID, _address, eStyleClass.BorderBottom, this);
-
- /// <summary>
- /// 0Diagonal border style
- /// </summary>
- public ExcelBorderItem Diagonal =>
- new(_styles, _ChangedEvent, _positionID, _address, eStyleClass.BorderDiagonal, this);
-
- /// <summary>
- /// A diagonal from the bottom left to top right of the cell
- /// </summary>
- public bool DiagonalUp {
- get {
- if (Index >= 0) {
- return _styles.Borders[Index].DiagonalUp;
- }
- return false;
- }
- }
-
- /// <summary>
- /// A diagonal from the top left to bottom right of the cell
- /// </summary>
- public bool DiagonalDown {
- get {
- if (Index >= 0) {
- return _styles.Borders[Index].DiagonalDown;
- }
- return false;
- }
- }
-
- internal override string Id =>
- Top.Id + Bottom.Id + Left.Id + Right.Id + Diagonal.Id + DiagonalUp + DiagonalDown;
-}
diff --git a/EPPlus/Style/ExcelBorderItem.cs b/EPPlus/Style/ExcelBorderItem.cs
deleted file mode 100644
index 89dc283..0000000
--- a/EPPlus/Style/ExcelBorderItem.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using OfficeOpenXml.Style.XmlAccess;
-
-namespace OfficeOpenXml.Style;
-
-/// <summary>
-/// Cell border style
-/// </summary>
-public sealed class ExcelBorderItem : StyleBase {
- private readonly eStyleClass _cls;
- private readonly StyleBase _parent;
-
- internal ExcelBorderItem(
- ExcelStyles styles,
- XmlHelper.ChangedEventHandler changedEvent,
- int worksheetId,
- string address,
- eStyleClass cls,
- StyleBase parent)
- : base(styles, changedEvent, worksheetId, address) {
- _cls = cls;
- _parent = parent;
- }
-
- /// <summary>
- /// The line style of the border
- /// </summary>
- public ExcelBorderStyle Style => GetSource().Style;
-
- private ExcelColor _color;
-
- /// <summary>
- /// The color of the border
- /// </summary>
- public ExcelColor Color {
- get {
- if (_color == null) {
- _color = new(_styles, _ChangedEvent, _positionID, _address, _cls, _parent);
- }
- return _color;
- }
- }
-
- internal override string Id => Style + Color.Id;
-
- internal override void SetIndex(int index) {
- _parent.Index = index;
- }
-
- private ExcelBorderItemXml GetSource() {
- int ix = _parent.Index < 0 ? 0 : _parent.Index;
-
- switch (_cls) {
- case eStyleClass.BorderTop:
- return _styles.Borders[ix].Top;
- case eStyleClass.BorderBottom:
- return _styles.Borders[ix].Bottom;
- case eStyleClass.BorderLeft:
- return _styles.Borders[ix].Left;
- case eStyleClass.BorderRight:
- return _styles.Borders[ix].Right;
- case eStyleClass.BorderDiagonal:
- return _styles.Borders[ix].Diagonal;
- default:
- throw new("Invalid class for Borderitem");
- }
- }
-}
diff --git a/EPPlus/Style/ExcelColor.cs b/EPPlus/Style/ExcelColor.cs
deleted file mode 100644
index e02de45..0000000
--- a/EPPlus/Style/ExcelColor.cs
+++ /dev/null
@@ -1,105 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using OfficeOpenXml.Style.XmlAccess;
-
-namespace OfficeOpenXml.Style;
-
-/// <summary>
-/// Color for cellstyling
-/// </summary>
-public sealed class ExcelColor : StyleBase {
- private readonly eStyleClass _cls;
- private readonly StyleBase _parent;
-
- internal ExcelColor(
- ExcelStyles styles,
- XmlHelper.ChangedEventHandler changedEvent,
- int worksheetId,
- string address,
- eStyleClass cls,
- StyleBase parent)
- : base(styles, changedEvent, worksheetId, address) {
- _parent = parent;
- _cls = cls;
- }
-
- /// <summary>
- /// The theme color
- /// </summary>
- public string Theme => GetSource().Theme;
-
- /// <summary>
- /// The tint value
- /// </summary>
- public decimal Tint => GetSource().Tint;
-
- /// <summary>
- /// The RGB value
- /// </summary>
- public string Rgb => GetSource().Rgb;
-
- /// <summary>
- /// The indexed color number.
- /// </summary>
- public int Indexed => GetSource().Indexed;
-
- internal override string Id => Theme + Tint + Rgb + Indexed;
-
- private ExcelColorXml GetSource() {
- Index = _parent.Index < 0 ? 0 : _parent.Index;
- switch (_cls) {
- case eStyleClass.FillBackgroundColor:
- return _styles.Fills[Index].BackgroundColor;
- case eStyleClass.FillPatternColor:
- return _styles.Fills[Index].PatternColor;
- case eStyleClass.Font:
- return _styles.Fonts[Index].Color;
- case eStyleClass.BorderLeft:
- return _styles.Borders[Index].Left.Color;
- case eStyleClass.BorderTop:
- return _styles.Borders[Index].Top.Color;
- case eStyleClass.BorderRight:
- return _styles.Borders[Index].Right.Color;
- case eStyleClass.BorderBottom:
- return _styles.Borders[Index].Bottom.Color;
- case eStyleClass.BorderDiagonal:
- return _styles.Borders[Index].Diagonal.Color;
- default:
- throw (new("Invalid style-class for Color"));
- }
- }
-
- internal override void SetIndex(int index) {
- _parent.Index = index;
- }
-}
diff --git a/EPPlus/Style/ExcelFill.cs b/EPPlus/Style/ExcelFill.cs
deleted file mode 100644
index 09193d7..0000000
--- a/EPPlus/Style/ExcelFill.cs
+++ /dev/null
@@ -1,131 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-namespace OfficeOpenXml.Style;
-
-/// <summary>
-/// The background fill of a cell
-/// </summary>
-public class ExcelFill : StyleBase {
- internal ExcelFill(
- ExcelStyles styles,
- XmlHelper.ChangedEventHandler changedEvent,
- int positionId,
- string address,
- int index)
- : base(styles, changedEvent, positionId, address) {
- Index = index;
- }
-
- /// <summary>
- /// The pattern for solid fills.
- /// </summary>
- public ExcelFillStyle PatternType {
- get {
- if (Index == int.MinValue) {
- return ExcelFillStyle.None;
- }
- return _styles.Fills[Index].PatternType;
- }
- }
-
- private ExcelColor _patternColor;
-
- /// <summary>
- /// The color of the pattern
- /// </summary>
- public ExcelColor PatternColor {
- get {
- if (_patternColor == null) {
- _patternColor = new(
- _styles,
- _ChangedEvent,
- _positionID,
- _address,
- eStyleClass.FillPatternColor,
- this);
- if (_gradient != null) {
- _gradient = null;
- }
- }
- return _patternColor;
- }
- }
-
- private ExcelColor _backgroundColor;
-
- /// <summary>
- /// The background color
- /// </summary>
- public ExcelColor BackgroundColor {
- get {
- if (_backgroundColor == null) {
- _backgroundColor = new(
- _styles,
- _ChangedEvent,
- _positionID,
- _address,
- eStyleClass.FillBackgroundColor,
- this);
- if (_gradient != null) {
- _gradient = null;
- }
- }
- return _backgroundColor;
- }
- }
-
- private ExcelGradientFill _gradient;
-
- /// <summary>
- /// Access to properties for gradient fill.
- /// </summary>
- public ExcelGradientFill Gradient {
- get {
- if (_gradient == null) {
- _gradient = new(_styles, _ChangedEvent, _positionID, _address, Index);
- _backgroundColor = null;
- _patternColor = null;
- }
- return _gradient;
- }
- }
-
- internal override string Id {
- get {
- if (_gradient == null) {
- return PatternType + PatternColor.Id + BackgroundColor.Id;
- }
- return _gradient.Id;
- }
- }
-}
diff --git a/EPPlus/Style/ExcelFont.cs b/EPPlus/Style/ExcelFont.cs
deleted file mode 100644
index 528c3c6..0000000
--- a/EPPlus/Style/ExcelFont.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml.Style;
-
-/// <summary>
-/// Cell style Font
-/// </summary>
-public sealed class ExcelFont : StyleBase {
- internal ExcelFont(
- ExcelStyles styles,
- XmlHelper.ChangedEventHandler changedEvent,
- int positionId,
- string address,
- int index)
- : base(styles, changedEvent, positionId, address) {
- Index = index;
- }
-
- /// <summary>
- /// The name of the font
- /// </summary>
- public string Name => _styles.Fonts[Index].Name;
-
- /// <summary>
- /// The Size of the font
- /// </summary>
- public float Size => _styles.Fonts[Index].Size;
-
- /// <summary>
- /// Font family
- /// </summary>
- public int Family => _styles.Fonts[Index].Family;
-
- /// <summary>
- /// Cell color
- /// </summary>
- public ExcelColor Color =>
- new(_styles, _ChangedEvent, _positionID, _address, eStyleClass.Font, this);
-
- /// <summary>
- /// Scheme
- /// </summary>
- public string Scheme => _styles.Fonts[Index].Scheme;
-
- /// <summary>
- /// Font-bold
- /// </summary>
- public bool Bold {
- get => _styles.Fonts[Index].Bold;
- set =>
- _ChangedEvent(this, new(eStyleClass.Font, eStyleProperty.Bold, value, _positionID, _address));
- }
-
- /// <summary>
- /// Font-italic
- /// </summary>
- public bool Italic => _styles.Fonts[Index].Italic;
-
- /// <summary>
- /// Font-Strikeout
- /// </summary>
- public bool Strike => _styles.Fonts[Index].Strike;
-
- /// <summary>
- /// Font-Underline
- /// </summary>
- public bool UnderLine => _styles.Fonts[Index].UnderLine;
-
- public ExcelUnderLineType UnderLineType => _styles.Fonts[Index].UnderLineType;
-
- /// <summary>
- /// Font-Vertical Align
- /// </summary>
- public ExcelVerticalAlignmentFont VerticalAlign =>
- Enum.TryParse<ExcelVerticalAlignmentFont>(
- _styles.Fonts[Index].VerticalAlign,
- true,
- out var result)
- ? result
- : ExcelVerticalAlignmentFont.None;
-
- internal override string Id =>
- Name
- + Size
- + Family
- + Scheme
- + Bold.ToString()[0]
- + Italic.ToString()[0]
- + Strike.ToString()[0]
- + UnderLine.ToString()[0]
- + VerticalAlign;
-}
diff --git a/EPPlus/Style/ExcelGradientFill.cs b/EPPlus/Style/ExcelGradientFill.cs
deleted file mode 100644
index 4ab355e..0000000
--- a/EPPlus/Style/ExcelGradientFill.cs
+++ /dev/null
@@ -1,123 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using OfficeOpenXml.Style.XmlAccess;
-
-namespace OfficeOpenXml.Style;
-
-/// <summary>
-/// The background fill of a cell
-/// </summary>
-public class ExcelGradientFill : StyleBase {
- internal ExcelGradientFill(
- ExcelStyles styles,
- XmlHelper.ChangedEventHandler changedEvent,
- int positionId,
- string address,
- int index)
- : base(styles, changedEvent, positionId, address) {
- Index = index;
- }
-
- /// <summary>
- /// Angle of the linear gradient
- /// </summary>
- public double Degree => ((ExcelGradientFillXml)_styles.Fills[Index]).Degree;
-
- /// <summary>
- /// Linear or Path gradient
- /// </summary>
- public ExcelFillGradientType Type => ((ExcelGradientFillXml)_styles.Fills[Index]).Type;
-
- /// <summary>
- /// Specifies in percentage format(from the top to the bottom) the position of the top edge of the inner rectangle (color 1). For top, 0 means the top edge of the inner rectangle is on the top edge of the cell, and 1 means it is on the bottom edge of the cell. (applies to From Corner and From Center gradients).
- /// </summary>
- public double Top => ((ExcelGradientFillXml)_styles.Fills[Index]).Top;
-
- /// <summary>
- /// Specifies in percentage format (from the top to the bottom) the position of the bottom edge of the inner rectangle (color 1). For bottom, 0 means the bottom edge of the inner rectangle is on the top edge of the cell, and 1 means it is on the bottom edge of the cell.
- /// </summary>
- public double Bottom => ((ExcelGradientFillXml)_styles.Fills[Index]).Bottom;
-
- /// <summary>
- /// Specifies in percentage format (from the left to the right) the position of the left edge of the inner rectangle (color 1). For left, 0 means the left edge of the inner rectangle is on the left edge of the cell, and 1 means it is on the right edge of the cell. (applies to From Corner and From Center gradients).
- /// </summary>
- public double Left => ((ExcelGradientFillXml)_styles.Fills[Index]).Left;
-
- /// <summary>
- /// Specifies in percentage format (from the left to the right) the position of the right edge of the inner rectangle (color 1). For right, 0 means the right edge of the inner rectangle is on the left edge of the cell, and 1 means it is on the right edge of the cell. (applies to From Corner and From Center gradients).
- /// </summary>
- public double Right => ((ExcelGradientFillXml)_styles.Fills[Index]).Right;
-
- private ExcelColor _gradientColor1;
-
- /// <summary>
- /// Gradient Color 1
- /// </summary>
- public ExcelColor Color1 {
- get {
- if (_gradientColor1 == null) {
- _gradientColor1 = new(
- _styles,
- _ChangedEvent,
- _positionID,
- _address,
- eStyleClass.FillGradientColor1,
- this);
- }
- return _gradientColor1;
- }
- }
-
- private ExcelColor _gradientColor2;
-
- /// <summary>
- /// Gradient Color 2
- /// </summary>
- public ExcelColor Color2 {
- get {
- if (_gradientColor2 == null) {
- _gradientColor2 = new(
- _styles,
- _ChangedEvent,
- _positionID,
- _address,
- eStyleClass.FillGradientColor2,
- this);
- }
- return _gradientColor2;
- }
- }
-
- internal override string Id =>
- Degree.ToString() + Type + Color1.Id + Color2.Id + Top + Bottom + Left + Right;
-}
diff --git a/EPPlus/Style/ExcelNumberFormat.cs b/EPPlus/Style/ExcelNumberFormat.cs
deleted file mode 100644
index 32d88ac..0000000
--- a/EPPlus/Style/ExcelNumberFormat.cs
+++ /dev/null
@@ -1,210 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-namespace OfficeOpenXml.Style;
-
-/// <summary>
-/// The numberformat of the cell
-/// </summary>
-public sealed class ExcelNumberFormat : StyleBase {
- internal ExcelNumberFormat(
- ExcelStyles styles,
- XmlHelper.ChangedEventHandler changedEvent,
- int positionId,
- string address,
- int index)
- : base(styles, changedEvent, positionId, address) {
- Index = index;
- }
-
- /// <summary>
- /// The numeric index fror the format
- /// </summary>
- public int NumFmtID => Index;
-
- /// <summary>
- /// The numberformat
- /// </summary>
- public string Format {
- get {
- for (int i = 0; i < _styles.NumberFormats.Count; i++) {
- if (Index == _styles.NumberFormats[i].NumFmtId) {
- return _styles.NumberFormats[i].Format;
- }
- }
- return "general";
- }
- set =>
- _ChangedEvent(
- this,
- new(
- eStyleClass.Numberformat,
- eStyleProperty.Format,
- (string.IsNullOrEmpty(value) ? "General" : value),
- _positionID,
- _address));
- }
-
- internal override string Id => Format;
-
- /// <summary>
- /// If the numeric format is a build-in from.
- /// </summary>
- public bool BuildIn { get; private set; }
-
- internal static string GetFromBuildInFromId(int numFmtId) {
- switch (numFmtId) {
- case 0:
- return "General";
- case 1:
- return "0";
- case 2:
- return "0.00";
- case 3:
- return "#,##0";
- case 4:
- return "#,##0.00";
- case 9:
- return "0%";
- case 10:
- return "0.00%";
- case 11:
- return "0.00E+00";
- case 12:
- return "# ?/?";
- case 13:
- return "# ??/??";
- case 14:
- return "mm-dd-yy";
- case 15:
- return "d-mmm-yy";
- case 16:
- return "d-mmm";
- case 17:
- return "mmm-yy";
- case 18:
- return "h:mm AM/PM";
- case 19:
- return "h:mm:ss AM/PM";
- case 20:
- return "h:mm";
- case 21:
- return "h:mm:ss";
- case 22:
- return "m/d/yy h:mm";
- case 37:
- return "#,##0 ;(#,##0)";
- case 38:
- return "#,##0 ;[Red](#,##0)";
- case 39:
- return "#,##0.00;(#,##0.00)";
- case 40:
- return "#,##0.00;[Red](#,##0.00)";
- case 45:
- return "mm:ss";
- case 46:
- return "[h]:mm:ss";
- case 47:
- return "mmss.0";
- case 48:
- return "##0.0";
- case 49:
- return "@";
- default:
- return string.Empty;
- }
- }
-
- internal static int GetFromBuildIdFromFormat(string format) {
- switch (format) {
- case "General":
- case "":
- return 0;
- case "0":
- return 1;
- case "0.00":
- return 2;
- case "#,##0":
- return 3;
- case "#,##0.00":
- return 4;
- case "0%":
- return 9;
- case "0.00%":
- return 10;
- case "0.00E+00":
- return 11;
- case "# ?/?":
- return 12;
- case "# ??/??":
- return 13;
- case "mm-dd-yy":
- return 14;
- case "d-mmm-yy":
- return 15;
- case "d-mmm":
- return 16;
- case "mmm-yy":
- return 17;
- case "h:mm AM/PM":
- return 18;
- case "h:mm:ss AM/PM":
- return 19;
- case "h:mm":
- return 20;
- case "h:mm:ss":
- return 21;
- case "m/d/yy h:mm":
- return 22;
- case "#,##0 ;(#,##0)":
- return 37;
- case "#,##0 ;[Red](#,##0)":
- return 38;
- case "#,##0.00;(#,##0.00)":
- return 39;
- case "#,##0.00;[Red](#,##0.00)":
- return 40;
- case "mm:ss":
- return 45;
- case "[h]:mm:ss":
- return 46;
- case "mmss.0":
- return 47;
- case "##0.0":
- return 48;
- case "@":
- return 49;
- default:
- return int.MinValue;
- }
- }
-}
diff --git a/EPPlus/Style/ExcelRichText.cs b/EPPlus/Style/ExcelRichText.cs
deleted file mode 100644
index 3e9994e..0000000
--- a/EPPlus/Style/ExcelRichText.cs
+++ /dev/null
@@ -1,277 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- * Richard Tallent Fix inadvertent removal of XML node 2012-10-31
- * Richard Tallent Remove VertAlign node if no alignment specified 2012-10-31
- *******************************************************************************/
-
-using System;
-using System.Collections.Immutable;
-using System.Globalization;
-using System.Xml;
-
-namespace OfficeOpenXml.Style;
-
-/// <summary>
-/// A richtext part
-/// </summary>
-public class ExcelRichText : XmlHelper {
- protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
- "rPr",
- "t",
- "b",
- "i",
- "strike",
- "u",
- "vertAlign",
- "sz",
- "color",
- "rFont",
- "family",
- "scheme",
- "charset",
- ];
-
- internal ExcelRichText(
- XmlNamespaceManager ns,
- XmlNode topNode,
- ExcelRichTextCollection collection)
- : base(ns, topNode) {
- _collection = collection;
- }
-
- internal delegate void CallbackDelegate();
-
- private CallbackDelegate _callback;
-
- internal void SetCallback(CallbackDelegate callback) {
- _callback = callback;
- }
-
- private const string _textPath = "d:t";
-
- /// <summary>
- /// The text
- /// </summary>
- public string Text {
- get {
- // Bug 15151
- if (TopNode.Name == "t") {
- return TopNode.InnerText;
- }
- return GetXmlNodeString(_textPath);
- }
- set {
- _collection.ConvertRichtext();
- // Don't remove if blank -- setting a blank rich text value on a node is common,
- // for example when applying both bold and italic to text.
- SetXmlNodeString(_textPath, value, false);
- if (PreserveSpace) {
- XmlElement elem = TopNode.SelectSingleNode(_textPath, NameSpaceManager) as XmlElement;
- elem.SetAttribute("xml:space", "preserve");
- }
- if (_callback != null) {
- _callback();
- }
- }
- }
-
- /// <summary>
- /// Preserves whitespace. Default true
- /// </summary>
- public bool PreserveSpace {
- get {
- XmlElement elem = TopNode.SelectSingleNode(_textPath, NameSpaceManager) as XmlElement;
- if (elem != null) {
- return elem.GetAttribute("xml:space") == "preserve";
- }
- return false;
- }
- set {
- _collection.ConvertRichtext();
- XmlElement elem = TopNode.SelectSingleNode(_textPath, NameSpaceManager) as XmlElement;
- if (elem != null) {
- if (value) {
- elem.SetAttribute("xml:space", "preserve");
- } else {
- elem.RemoveAttribute("xml:space");
- }
- }
- if (_callback != null) {
- _callback();
- }
- }
- }
-
- private const string _boldPath = "d:rPr/d:b";
-
- /// <summary>
- /// Bold text
- /// </summary>
- public bool Bold {
- get => ExistNode(_boldPath);
- set {
- _collection.ConvertRichtext();
- if (value) {
- CreateNode(_boldPath);
- } else {
- DeleteNode(_boldPath);
- }
- if (_callback != null) {
- _callback();
- }
- }
- }
-
- private const string _italicPath = "d:rPr/d:i";
-
- /// <summary>
- /// Italic text
- /// </summary>
- public bool Italic {
- get =>
- //return GetXmlNodeBool(ITALIC_PATH, false);
- ExistNode(_italicPath);
- set {
- _collection.ConvertRichtext();
- if (value) {
- CreateNode(_italicPath);
- } else {
- DeleteNode(_italicPath);
- }
- if (_callback != null) {
- _callback();
- }
- }
- }
-
- private const string _strikePath = "d:rPr/d:strike";
-
- /// <summary>
- /// Strike-out text
- /// </summary>
- public bool Strike {
- get => ExistNode(_strikePath);
- set {
- _collection.ConvertRichtext();
- if (value) {
- CreateNode(_strikePath);
- } else {
- DeleteNode(_strikePath);
- }
- if (_callback != null) {
- _callback();
- }
- }
- }
-
- private const string _underlinePath = "d:rPr/d:u";
-
- /// <summary>
- /// Underlined text
- /// </summary>
- public bool UnderLine {
- get => ExistNode(_underlinePath);
- set {
- _collection.ConvertRichtext();
- if (value) {
- CreateNode(_underlinePath);
- } else {
- DeleteNode(_underlinePath);
- }
- if (_callback != null) {
- _callback();
- }
- }
- }
-
- private const string _vertAlignPath = "d:rPr/d:vertAlign/@val";
-
- /// <summary>
- /// Vertical Alignment
- /// </summary>
- public ExcelVerticalAlignmentFont VerticalAlign =>
- Enum.TryParse<ExcelVerticalAlignmentFont>(
- GetXmlNodeString(TopNode, _vertAlignPath),
- true,
- out var result)
- ? result
- : ExcelVerticalAlignmentFont.None;
-
- private const string _sizePath = "d:rPr/d:sz/@val";
-
- /// <summary>
- /// Font size
- /// </summary>
- public float Size {
- get => Convert.ToSingle(GetXmlNodeDecimal(_sizePath));
- set {
- _collection.ConvertRichtext();
- SetXmlNodeString(_sizePath, value.ToString(CultureInfo.InvariantCulture));
- if (_callback != null) {
- _callback();
- }
- }
- }
-
- private const string _fontPath = "d:rPr/d:rFont/@val";
-
- /// <summary>
- /// Name of the font
- /// </summary>
- public string FontName {
- get => GetXmlNodeString(_fontPath);
- set {
- _collection.ConvertRichtext();
- SetXmlNodeString(_fontPath, value);
- if (_callback != null) {
- _callback();
- }
- }
- }
-
- private const string _colorPath = "d:rPr/d:color/@rgb";
-
- /// <summary>
- /// Text color
- /// </summary>
- public string Color {
- get => GetXmlNodeString(_colorPath);
- set {
- _collection.ConvertRichtext();
- SetXmlNodeString(_colorPath, value);
- if (_callback != null) {
- _callback();
- }
- }
- }
-
- public ExcelRichTextCollection _collection { get; set; }
-}
diff --git a/EPPlus/Style/ExcelRichTextCollection.cs b/EPPlus/Style/ExcelRichTextCollection.cs
deleted file mode 100644
index 21f4803..0000000
--- a/EPPlus/Style/ExcelRichTextCollection.cs
+++ /dev/null
@@ -1,233 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml;
-
-namespace OfficeOpenXml.Style;
-
-/// <summary>
-/// Collection of Richtext objects
-/// </summary>
-public class ExcelRichTextCollection : XmlHelper, IEnumerable<ExcelRichText> {
- private readonly List<ExcelRichText> _list = new();
- private readonly ExcelRangeBase _cells;
-
- internal ExcelRichTextCollection(XmlNamespaceManager ns, XmlNode topNode)
- : base(ns, topNode) {
- var nl = topNode.SelectNodes("d:r|d:t", NameSpaceManager); // Bug 15151
- if (nl != null) {
- foreach (XmlNode n in nl) {
- _list.Add(new(ns, n, this));
- }
- }
- }
-
- internal ExcelRichTextCollection(XmlNamespaceManager ns, XmlNode topNode, ExcelRangeBase cells)
- : this(ns, topNode) {
- _cells = cells;
- }
-
- /// <summary>
- /// Collection containing the richtext objects
- /// </summary>
- /// <param name="index"></param>
- /// <returns></returns>
- public ExcelRichText this[int index] {
- get {
- var item = _list[index];
- if (_cells != null) {
- item.SetCallback(UpdateCells);
- }
- return item;
- }
- }
-
- /// <summary>
- /// Items in the list
- /// </summary>
- public int Count => _list.Count;
-
- /// <summary>
- /// Add a rich text string
- /// </summary>
- /// <param name="text">The text to add</param>
- /// <returns></returns>
- public ExcelRichText Add(string text) {
- ConvertRichtext();
- XmlDocument doc;
- if (TopNode is XmlDocument document) {
- doc = document;
- } else {
- doc = TopNode.OwnerDocument;
- }
- var node = doc.CreateElement("d", "r", ExcelPackage._schemaMain);
- TopNode.AppendChild(node);
- var rt = new ExcelRichText(NameSpaceManager, node, this);
- if (_list.Count > 0) {
- ExcelRichText prevItem = _list[_list.Count - 1];
- rt.FontName = prevItem.FontName;
- rt.Size = prevItem.Size;
- rt.Color = prevItem.Color == "" ? "FF00000" : prevItem.Color;
- rt.PreserveSpace = rt.PreserveSpace;
- rt.Bold = prevItem.Bold;
- rt.Italic = prevItem.Italic;
- rt.UnderLine = prevItem.UnderLine;
- } else if (_cells == null) {
- rt.FontName = "Calibri";
- rt.Size = 11;
- } else {
- var style = _cells.Offset(0, 0).Style;
- rt.FontName = style.Font.Name;
- rt.Size = style.Font.Size;
- rt.Bold = style.Font.Bold;
- rt.Italic = style.Font.Italic;
- _cells.IsRichText = true;
- }
- rt.Text = text;
- rt.PreserveSpace = true;
- if (_cells != null) {
- rt.SetCallback(UpdateCells);
- UpdateCells();
- }
- _list.Add(rt);
- return rt;
- }
-
- internal void ConvertRichtext() {
- if (_cells == null) {
- return;
- }
- var isRt = _cells.Worksheet._flags.GetFlagValue(
- _cells._fromRow,
- _cells._fromCol,
- CellFlags.RichText);
- if (Count == 1 && isRt == false) {
- _cells.Worksheet._flags.SetFlagValue(
- _cells._fromRow,
- _cells._fromCol,
- true,
- CellFlags.RichText);
- var s = _cells.Worksheet._styles.GetValue(_cells._fromRow, _cells._fromCol);
- //var fnt = cell.Style.Font;
- var fnt = _cells.Worksheet.Workbook.Styles
- .GetStyleObject(
- s,
- _cells.Worksheet.PositionID,
- ExcelCellBase.GetAddress(_cells._fromRow, _cells._fromCol))
- .Font;
- this[0].PreserveSpace = true;
- this[0].Bold = fnt.Bold;
- this[0].FontName = fnt.Name;
- this[0].Italic = fnt.Italic;
- this[0].Size = fnt.Size;
- this[0].UnderLine = fnt.UnderLine;
- }
- }
-
- internal void UpdateCells() {
- _cells.SetValueRichText(TopNode.InnerXml);
- }
-
- /// <summary>
- /// Removes an item at the specific index
- /// </summary>
- /// <param name="index"></param>
- public void RemoveAt(int index) {
- TopNode.RemoveChild(_list[index].TopNode);
- _list.RemoveAt(index);
- if (_cells != null && _list.Count == 0) {
- _cells.IsRichText = false;
- }
- }
-
- /// <summary>
- /// Removes an item
- /// </summary>
- /// <param name="item"></param>
- public void Remove(ExcelRichText item) {
- TopNode.RemoveChild(item.TopNode);
- _list.Remove(item);
- if (_cells != null && _list.Count == 0) {
- _cells.IsRichText = false;
- }
- }
-
- //public void Insert(int index, string Text)
- //{
- // _list.Insert(index, item);
- //}
-
- /// <summary>
- /// The text
- /// </summary>
- public string Text {
- get {
- StringBuilder sb = new StringBuilder();
- foreach (var item in _list) {
- sb.Append(item.Text);
- }
- return sb.ToString();
- }
- set {
- if (Count == 0) {
- Add(value);
- } else {
- this[0].Text = value;
- for (int ix = 1; ix < Count; ix++) {
- RemoveAt(ix);
- }
- }
- }
- }
-
- IEnumerator<ExcelRichText> IEnumerable<ExcelRichText>.GetEnumerator() {
- return _list
- .Select(x => {
- x.SetCallback(UpdateCells);
- return x;
- })
- .GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- return _list
- .Select(x => {
- x.SetCallback(UpdateCells);
- return x;
- })
- .GetEnumerator();
- }
-}
diff --git a/EPPlus/Style/ExcelStyle.cs b/EPPlus/Style/ExcelStyle.cs
deleted file mode 100644
index 088b8c3..0000000
--- a/EPPlus/Style/ExcelStyle.cs
+++ /dev/null
@@ -1,163 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using OfficeOpenXml.Style.XmlAccess;
-
-namespace OfficeOpenXml.Style;
-
-/// <summary>
-/// Toplevel class for cell styling
-/// </summary>
-public sealed class ExcelStyle : StyleBase {
- internal ExcelStyle(
- ExcelStyles styles,
- XmlHelper.ChangedEventHandler changedEvent,
- int positionId,
- string address,
- int xfsId)
- : base(styles, changedEvent, positionId, address) {
- Index = xfsId;
- ExcelXfs xfs;
- if (positionId > -1) {
- xfs = _styles.CellXfs[xfsId];
- } else {
- xfs = _styles.CellStyleXfs[xfsId];
- }
- Styles = styles;
- PositionID = positionId;
- Numberformat = new(styles, changedEvent, PositionID, address, xfs.NumberFormatId);
- Font = new(styles, changedEvent, PositionID, address, xfs.FontId);
- Fill = new(styles, changedEvent, PositionID, address, xfs.FillId);
- Border = new(styles, changedEvent, PositionID, address, xfs.BorderId);
- }
-
- /// <summary>
- /// Numberformat
- /// </summary>
- public ExcelNumberFormat Numberformat { get; set; }
-
- /// <summary>
- /// Font styling
- /// </summary>
- public ExcelFont Font { get; set; }
-
- /// <summary>
- /// Fill Styling
- /// </summary>
- public ExcelFill Fill { get; set; }
-
- /// <summary>
- /// Border
- /// </summary>
- public Border Border { get; set; }
-
- /// <summary>
- /// The horizontal alignment in the cell
- /// </summary>
- public ExcelHorizontalAlignment HorizontalAlignment => _styles.CellXfs[Index].HorizontalAlignment;
-
- /// <summary>
- /// The vertical alignment in the cell
- /// </summary>
- public ExcelVerticalAlignment VerticalAlignment => _styles.CellXfs[Index].VerticalAlignment;
-
- /// <summary>
- /// Wrap the text
- /// </summary>
- public bool WrapText {
- get => _styles.CellXfs[Index].WrapText;
- set =>
- _ChangedEvent(
- this,
- new(eStyleClass.Style, eStyleProperty.WrapText, value, _positionID, _address));
- }
-
- /// <summary>
- /// Readingorder
- /// </summary>
- public ExcelReadingOrder ReadingOrder => _styles.CellXfs[Index].ReadingOrder;
-
- /// <summary>
- /// Shrink the text to fit
- /// </summary>
- public bool ShrinkToFit => _styles.CellXfs[Index].ShrinkToFit;
-
- /// <summary>
- /// The margin between the border and the text
- /// </summary>
- public int Indent => _styles.CellXfs[Index].Indent;
-
- /// <summary>
- /// Text orientation in degrees. Values range from 0 to 180.
- /// </summary>
- public int TextRotation => _styles.CellXfs[Index].TextRotation;
-
- /// <summary>
- /// If true the cell is locked for editing when the sheet is protected
- /// <seealso cref="ExcelWorksheet.Protection"/>
- /// </summary>
- public bool Locked => _styles.CellXfs[Index].Locked;
-
- /// <summary>
- /// If true the formula is hidden when the sheet is protected.
- /// <seealso cref="ExcelWorksheet.Protection"/>
- /// </summary>
- public bool Hidden => _styles.CellXfs[Index].Hidden;
-
- /// <summary>
- /// The index in the style collection
- /// </summary>
- public int XfId => _styles.CellXfs[Index].XfId;
-
- internal int PositionID { get; set; }
-
- internal ExcelStyles Styles { get; set; }
-
- internal override string Id =>
- Numberformat.Id
- + "|"
- + Font.Id
- + "|"
- + Fill.Id
- + "|"
- + Border.Id
- + "|"
- + VerticalAlignment
- + "|"
- + HorizontalAlignment
- + "|"
- + WrapText
- + "|"
- + ReadingOrder
- + "|"
- + XfId;
-}
diff --git a/EPPlus/Style/IStyle.cs b/EPPlus/Style/IStyle.cs
deleted file mode 100644
index f1f492e..0000000
--- a/EPPlus/Style/IStyle.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-namespace OfficeOpenXml.Style;
-
-internal interface IStyle {
- void SetNewStyleId(string value);
-
- ulong Id { get; }
-
- ExcelStyle ExcelStyle { get; }
-}
diff --git a/EPPlus/Style/StyleBase.cs b/EPPlus/Style/StyleBase.cs
deleted file mode 100644
index edc6650..0000000
--- a/EPPlus/Style/StyleBase.cs
+++ /dev/null
@@ -1,188 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-namespace OfficeOpenXml.Style;
-
-/// <summary>
-/// Border line style
-/// </summary>
-public enum ExcelBorderStyle {
- None,
- Hair,
- Dotted,
- DashDot,
- Thin,
- DashDotDot,
- Dashed,
- MediumDashDotDot,
- MediumDashed,
- MediumDashDot,
- Thick,
- Medium,
- Double,
-}
-
-/// <summary>
-/// Horizontal text alignment
-/// </summary>
-public enum ExcelHorizontalAlignment {
- General,
- Left,
- Center,
- CenterContinuous,
- Right,
- Fill,
- Distributed,
- Justify,
-}
-
-/// <summary>
-/// Vertical text alignment
-/// </summary>
-public enum ExcelVerticalAlignment {
- Top,
- Center,
- Bottom,
- Distributed,
- Justify,
-}
-
-/// <summary>
-/// Font-Vertical Align
-/// </summary>
-public enum ExcelVerticalAlignmentFont {
- None,
- Subscript,
- Superscript,
-}
-
-/// <summary>
-/// Font-Underlinestyle for
-/// </summary>
-public enum ExcelUnderLineType {
- None,
- Single,
- Double,
- SingleAccounting,
- DoubleAccounting,
-}
-
-/// <summary>
-/// Fill pattern
-/// </summary>
-public enum ExcelFillStyle {
- None,
- Solid,
- DarkGray,
- MediumGray,
- LightGray,
- Gray125,
- Gray0625,
- DarkVertical,
- DarkHorizontal,
- DarkDown,
- DarkUp,
- DarkGrid,
- DarkTrellis,
- LightVertical,
- LightHorizontal,
- LightDown,
- LightUp,
- LightGrid,
- LightTrellis,
-}
-
-/// <summary>
-/// Type of gradient fill
-/// </summary>
-public enum ExcelFillGradientType {
- /// <summary>
- /// No gradient fill.
- /// </summary>
- None,
-
- /// <summary>
- /// This gradient fill is of linear gradient type. Linear gradient type means that the transition from one color to the next is along a line (e.g., horizontal, vertical,diagonal, etc.)
- /// </summary>
- Linear,
-
- /// <summary>
- /// This gradient fill is of path gradient type. Path gradient type means the that the boundary of transition from one color to the next is a rectangle, defined by top,bottom, left, and right attributes on the gradientFill element.
- /// </summary>
- Path,
-}
-
-/// <summary>
-/// The reading order
-/// </summary>
-public enum ExcelReadingOrder {
- /// <summary>
- /// Reading order is determined by scanning the text for the first non-whitespace character: if it is a strong right-to-left character, the reading order is right-to-left; otherwise, the reading order left-to-right.
- /// </summary>
- ContextDependent = 0,
-
- /// <summary>
- /// Left to Right
- /// </summary>
- LeftToRight = 1,
-
- /// <summary>
- /// Right to Left
- /// </summary>
- RightToLeft = 2,
-}
-
-public abstract class StyleBase {
- protected ExcelStyles _styles;
- internal XmlHelper.ChangedEventHandler _ChangedEvent;
- protected int _positionID;
- protected string _address;
-
- internal StyleBase(
- ExcelStyles styles,
- XmlHelper.ChangedEventHandler changedEvent,
- int positionId,
- string address) {
- _styles = styles;
- _ChangedEvent = changedEvent;
- _address = address;
- _positionID = positionId;
- }
-
- internal int Index { get; set; }
-
- internal abstract string Id { get; }
-
- internal virtual void SetIndex(int index) {
- Index = index;
- }
-}
diff --git a/EPPlus/Style/StyleChangeEventArgs.cs b/EPPlus/Style/StyleChangeEventArgs.cs
deleted file mode 100644
index 352dc51..0000000
--- a/EPPlus/Style/StyleChangeEventArgs.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml.Style;
-
-internal enum eStyleClass {
- Numberformat,
- Font,
- Border,
- BorderTop,
- BorderLeft,
- BorderBottom,
- BorderRight,
- BorderDiagonal,
- Fill,
- GradientFill,
- FillBackgroundColor,
- FillPatternColor,
- FillGradientColor1,
- FillGradientColor2,
- NamedStyle,
- Style,
-}
-
-internal enum eStyleProperty {
- Format,
- Name,
- Size,
- Bold,
- Italic,
- Strike,
- Color,
- Tint,
- IndexedColor,
- AutoColor,
- GradientColor,
- Family,
- Scheme,
- UnderlineType,
- HorizontalAlign,
- VerticalAlign,
- Border,
- NamedStyle,
- Style,
- PatternType,
- ReadingOrder,
- WrapText,
- TextRotation,
- Locked,
- Hidden,
- ShrinkToFit,
- BorderDiagonalUp,
- BorderDiagonalDown,
- GradientDegree,
- GradientType,
- GradientTop,
- GradientBottom,
- GradientLeft,
- GradientRight,
- XfId,
- Indent,
-}
-
-internal class StyleChangeEventArgs : EventArgs {
- internal StyleChangeEventArgs(
- eStyleClass styleclass,
- eStyleProperty styleProperty,
- object value,
- int positionId,
- string address) {
- StyleClass = styleclass;
- StyleProperty = styleProperty;
- Value = value;
- Address = address;
- PositionID = positionId;
- }
-
- internal eStyleClass StyleClass;
- internal eStyleProperty StyleProperty;
-
- //internal string PropertyName;
- internal object Value;
-
- internal int PositionID { get; set; }
-
- //internal string Address;
- internal string Address;
-}
diff --git a/EPPlus/Style/XmlAccess/ExcelBorderItemXml.cs b/EPPlus/Style/XmlAccess/ExcelBorderItemXml.cs
deleted file mode 100644
index 9c0de5e..0000000
--- a/EPPlus/Style/XmlAccess/ExcelBorderItemXml.cs
+++ /dev/null
@@ -1,130 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System;
-using System.Globalization;
-using System.Xml;
-
-namespace OfficeOpenXml.Style.XmlAccess;
-
-/// <summary>
-/// Xml access class for border items
-/// </summary>
-public sealed class ExcelBorderItemXml : StyleXmlHelper {
- internal ExcelBorderItemXml(XmlNamespaceManager nameSpaceManager)
- : base(nameSpaceManager) {
- _borderStyle = ExcelBorderStyle.None;
- _color = new(NameSpaceManager);
- }
-
- internal ExcelBorderItemXml(XmlNamespaceManager nsm, XmlNode topNode)
- : base(nsm, topNode) {
- if (topNode != null) {
- _borderStyle = GetBorderStyle(GetXmlNodeString("@style"));
- _color = new(nsm, topNode.SelectSingleNode(_colorPath, nsm));
- Exists = true;
- } else {
- Exists = false;
- }
- }
-
- private ExcelBorderStyle GetBorderStyle(string style) {
- if (style == "") {
- return ExcelBorderStyle.None;
- }
- return Enum.TryParse<ExcelBorderStyle>(style, true, out var result)
- ? result
- : ExcelBorderStyle.None;
- }
-
- private ExcelBorderStyle _borderStyle = ExcelBorderStyle.None;
-
- /// <summary>
- /// Cell Border style
- /// </summary>
- public ExcelBorderStyle Style {
- get => _borderStyle;
- set {
- _borderStyle = value;
- Exists = true;
- }
- }
-
- private ExcelColorXml _color;
- private const string _colorPath = "d:color";
-
- /// <summary>
- /// Border style
- /// </summary>
- public ExcelColorXml Color {
- get => _color;
- internal set => _color = value;
- }
-
- internal override string Id {
- get {
- if (Exists) {
- return Style + Color.Id;
- }
- return "None";
- }
- }
-
- internal ExcelBorderItemXml Copy() {
- ExcelBorderItemXml borderItem = new ExcelBorderItemXml(NameSpaceManager);
- borderItem.Style = _borderStyle;
- borderItem.Color = _color.Copy();
- return borderItem;
- }
-
- internal override XmlNode CreateXmlNode(XmlNode topNode) {
- TopNode = topNode;
-
- if (Style != ExcelBorderStyle.None) {
- SetXmlNodeString("@style", SetBorderString(Style));
- if (Color.Exists) {
- CreateNode(_colorPath);
- topNode.AppendChild(
- Color.CreateXmlNode(TopNode.SelectSingleNode(_colorPath, NameSpaceManager)));
- }
- }
- return TopNode;
- }
-
- private string SetBorderString(ExcelBorderStyle style) {
- string newName = Enum.GetName(typeof(ExcelBorderStyle), style);
- return newName.Substring(0, 1).ToLower(CultureInfo.InvariantCulture)
- + newName.Substring(1, newName.Length - 1);
- }
-
- public bool Exists { get; private set; }
-}
diff --git a/EPPlus/Style/XmlAccess/ExcelBorderXml.cs b/EPPlus/Style/XmlAccess/ExcelBorderXml.cs
deleted file mode 100644
index 9d19974..0000000
--- a/EPPlus/Style/XmlAccess/ExcelBorderXml.cs
+++ /dev/null
@@ -1,171 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.Style.XmlAccess;
-
-/// <summary>
-/// Xml access class for border top level
-/// </summary>
-public sealed class ExcelBorderXml : StyleXmlHelper {
- internal ExcelBorderXml(XmlNamespaceManager nameSpaceManager)
- : base(nameSpaceManager) {}
-
- internal ExcelBorderXml(XmlNamespaceManager nsm, XmlNode topNode)
- : base(nsm, topNode) {
- _left = new(nsm, topNode.SelectSingleNode(_leftPath, nsm));
- _right = new(nsm, topNode.SelectSingleNode(_rightPath, nsm));
- _top = new(nsm, topNode.SelectSingleNode(_topPath, nsm));
- _bottom = new(nsm, topNode.SelectSingleNode(_bottomPath, nsm));
- _diagonal = new(nsm, topNode.SelectSingleNode(_diagonalPath, nsm));
- _diagonalUp = GetBoolValue(topNode, _diagonalUpPath);
- _diagonalDown = GetBoolValue(topNode, _diagonalDownPath);
- }
-
- internal override string Id =>
- Left.Id + Right.Id + Top.Id + Bottom.Id + Diagonal.Id + DiagonalUp + DiagonalDown;
-
- private const string _leftPath = "d:left";
- private ExcelBorderItemXml _left;
-
- /// <summary>
- /// Left border style properties
- /// </summary>
- public ExcelBorderItemXml Left {
- get => _left;
- internal set => _left = value;
- }
-
- private const string _rightPath = "d:right";
- private ExcelBorderItemXml _right;
-
- /// <summary>
- /// Right border style properties
- /// </summary>
- public ExcelBorderItemXml Right {
- get => _right;
- internal set => _right = value;
- }
-
- private const string _topPath = "d:top";
- private ExcelBorderItemXml _top;
-
- /// <summary>
- /// Top border style properties
- /// </summary>
- public ExcelBorderItemXml Top {
- get => _top;
- internal set => _top = value;
- }
-
- private const string _bottomPath = "d:bottom";
- private ExcelBorderItemXml _bottom;
-
- /// <summary>
- /// Bottom border style properties
- /// </summary>
- public ExcelBorderItemXml Bottom {
- get => _bottom;
- internal set => _bottom = value;
- }
-
- private const string _diagonalPath = "d:diagonal";
- private ExcelBorderItemXml _diagonal;
-
- /// <summary>
- /// Diagonal border style properties
- /// </summary>
- public ExcelBorderItemXml Diagonal {
- get => _diagonal;
- internal set => _diagonal = value;
- }
-
- private const string _diagonalUpPath = "@diagonalUp";
- private bool _diagonalUp;
-
- /// <summary>
- /// Diagonal up border
- /// </summary>
- public bool DiagonalUp {
- get => _diagonalUp;
- internal set => _diagonalUp = value;
- }
-
- private const string _diagonalDownPath = "@diagonalDown";
- private bool _diagonalDown;
-
- /// <summary>
- /// Diagonal down border
- /// </summary>
- public bool DiagonalDown {
- get => _diagonalDown;
- internal set => _diagonalDown = value;
- }
-
- internal ExcelBorderXml Copy() {
- ExcelBorderXml newBorder = new ExcelBorderXml(NameSpaceManager);
- newBorder.Bottom = _bottom.Copy();
- newBorder.Diagonal = _diagonal.Copy();
- newBorder.Left = _left.Copy();
- newBorder.Right = _right.Copy();
- newBorder.Top = _top.Copy();
- newBorder.DiagonalUp = _diagonalUp;
- newBorder.DiagonalDown = _diagonalDown;
-
- return newBorder;
- }
-
- internal override XmlNode CreateXmlNode(XmlNode topNode) {
- TopNode = topNode;
- CreateNode(_leftPath);
- topNode.AppendChild(_left.CreateXmlNode(TopNode.SelectSingleNode(_leftPath, NameSpaceManager)));
- CreateNode(_rightPath);
- topNode.AppendChild(
- _right.CreateXmlNode(TopNode.SelectSingleNode(_rightPath, NameSpaceManager)));
- CreateNode(_topPath);
- topNode.AppendChild(_top.CreateXmlNode(TopNode.SelectSingleNode(_topPath, NameSpaceManager)));
- CreateNode(_bottomPath);
- topNode.AppendChild(
- _bottom.CreateXmlNode(TopNode.SelectSingleNode(_bottomPath, NameSpaceManager)));
- CreateNode(_diagonalPath);
- topNode.AppendChild(
- _diagonal.CreateXmlNode(TopNode.SelectSingleNode(_diagonalPath, NameSpaceManager)));
- if (_diagonalUp) {
- SetXmlNodeString(_diagonalUpPath, "1");
- }
- if (_diagonalDown) {
- SetXmlNodeString(_diagonalDownPath, "1");
- }
- return topNode;
- }
-}
diff --git a/EPPlus/Style/XmlAccess/ExcelColorXml.cs b/EPPlus/Style/XmlAccess/ExcelColorXml.cs
deleted file mode 100644
index 7a6d024..0000000
--- a/EPPlus/Style/XmlAccess/ExcelColorXml.cs
+++ /dev/null
@@ -1,175 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System;
-using System.Globalization;
-using System.Xml;
-
-namespace OfficeOpenXml.Style.XmlAccess;
-
-/// <summary>
-/// Xml access class for color
-/// </summary>
-public sealed class ExcelColorXml : StyleXmlHelper {
- internal ExcelColorXml(XmlNamespaceManager nameSpaceManager)
- : base(nameSpaceManager) {
- _auto = false;
- _theme = "";
- _tint = 0;
- _rgb = "";
- _indexed = int.MinValue;
- }
-
- internal ExcelColorXml(XmlNamespaceManager nsm, XmlNode topNode)
- : base(nsm, topNode) {
- if (topNode == null) {
- _exists = false;
- } else {
- _exists = true;
- _auto = GetXmlNodeBool("@auto");
- _theme = GetXmlNodeString("@theme");
- _tint = GetXmlNodeDecimalNull("@tint") ?? decimal.MinValue;
- _rgb = GetXmlNodeString("@rgb");
- _indexed = GetXmlNodeIntNull("@indexed") ?? int.MinValue;
- }
- }
-
- internal override string Id => _auto + "|" + _theme + "|" + _tint + "|" + _rgb + "|" + _indexed;
-
- private bool _auto;
-
- public bool Auto {
- get => _auto;
- set {
- _auto = value;
- _exists = true;
- Clear();
- }
- }
-
- private string _theme;
-
- /// <summary>
- /// Theme color value
- /// </summary>
- public string Theme => _theme;
-
- private decimal _tint;
-
- /// <summary>
- /// Tint
- /// </summary>
- public decimal Tint {
- get {
- if (_tint == decimal.MinValue) {
- return 0;
- }
- return _tint;
- }
- set {
- _tint = value;
- _exists = true;
- }
- }
-
- private string _rgb;
-
- /// <summary>
- /// RGB value
- /// </summary>
- public string Rgb {
- get => _rgb;
- set {
- _rgb = value;
- _exists = true;
- _indexed = int.MinValue;
- _auto = false;
- }
- }
-
- private int _indexed;
-
- /// <summary>
- /// Indexed color value
- /// </summary>
- public int Indexed {
- get => (_indexed == int.MinValue ? 0 : _indexed);
- set {
- if (value < 0 || value > 65) {
- throw (new ArgumentOutOfRangeException("Index out of range"));
- }
- Clear();
- _indexed = value;
- _exists = true;
- }
- }
-
- internal void Clear() {
- _theme = "";
- _tint = decimal.MinValue;
- _indexed = int.MinValue;
- _rgb = "";
- _auto = false;
- }
-
- internal ExcelColorXml Copy() {
- return new(NameSpaceManager) {
- _indexed = _indexed,
- _tint = _tint,
- _rgb = _rgb,
- _theme = _theme,
- _auto = _auto,
- _exists = _exists,
- };
- }
-
- internal override XmlNode CreateXmlNode(XmlNode topNode) {
- TopNode = topNode;
- if (_rgb != "") {
- SetXmlNodeString("@rgb", _rgb);
- } else if (_indexed >= 0) {
- SetXmlNodeString("@indexed", _indexed.ToString());
- } else if (_auto) {
- SetXmlNodeBool("@auto", _auto);
- } else {
- SetXmlNodeString("@theme", _theme);
- }
- if (_tint != decimal.MinValue) {
- SetXmlNodeString("@tint", _tint.ToString(CultureInfo.InvariantCulture));
- }
- return TopNode;
- }
-
- private bool _exists;
-
- internal bool Exists => _exists;
-}
diff --git a/EPPlus/Style/XmlAccess/ExcelFillXml.cs b/EPPlus/Style/XmlAccess/ExcelFillXml.cs
deleted file mode 100644
index cf43d0e..0000000
--- a/EPPlus/Style/XmlAccess/ExcelFillXml.cs
+++ /dev/null
@@ -1,130 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System;
-using System.Globalization;
-using System.Xml;
-
-namespace OfficeOpenXml.Style.XmlAccess;
-
-/// <summary>
-/// Xml access class for fills
-/// </summary>
-public class ExcelFillXml : StyleXmlHelper {
- internal ExcelFillXml(XmlNamespaceManager nameSpaceManager)
- : base(nameSpaceManager) {
- _fillPatternType = ExcelFillStyle.None;
- _backgroundColor = new(NameSpaceManager);
- _patternColor = new(NameSpaceManager);
- }
-
- internal ExcelFillXml(XmlNamespaceManager nsm, XmlNode topNode)
- : base(nsm, topNode) {
- PatternType = GetPatternType(GetXmlNodeString(_fillPatternTypePath));
- _backgroundColor = new(nsm, topNode.SelectSingleNode(_backgroundColorPath, nsm));
- _patternColor = new(nsm, topNode.SelectSingleNode(_patternColorPath, nsm));
- }
-
- private ExcelFillStyle GetPatternType(string patternType) {
- return Enum.TryParse<ExcelFillStyle>(patternType, true, out var result)
- ? result
- : ExcelFillStyle.None;
- }
-
- internal override string Id => PatternType + PatternColor.Id + BackgroundColor.Id;
-
- private const string _fillPatternTypePath = "d:patternFill/@patternType";
- protected ExcelFillStyle _fillPatternType;
-
- /// <summary>
- /// Cell fill pattern style
- /// </summary>
- public ExcelFillStyle PatternType {
- get => _fillPatternType;
- set => _fillPatternType = value;
- }
-
- protected ExcelColorXml _patternColor;
- private const string _patternColorPath = "d:patternFill/d:bgColor";
-
- /// <summary>
- /// Pattern color
- /// </summary>
- public ExcelColorXml PatternColor {
- get => _patternColor;
- internal set => _patternColor = value;
- }
-
- protected ExcelColorXml _backgroundColor;
- private const string _backgroundColorPath = "d:patternFill/d:fgColor";
-
- /// <summary>
- /// Cell background color
- /// </summary>
- public ExcelColorXml BackgroundColor {
- get => _backgroundColor;
- internal set => _backgroundColor = value;
- }
-
- internal virtual ExcelFillXml Copy() {
- ExcelFillXml newFill = new ExcelFillXml(NameSpaceManager);
- newFill.PatternType = _fillPatternType;
- newFill.BackgroundColor = _backgroundColor.Copy();
- newFill.PatternColor = _patternColor.Copy();
- return newFill;
- }
-
- internal override XmlNode CreateXmlNode(XmlNode topNode) {
- TopNode = topNode;
- SetXmlNodeString(_fillPatternTypePath, SetPatternString(_fillPatternType));
- if (PatternType != ExcelFillStyle.None) {
- XmlNode pattern = topNode.SelectSingleNode(_fillPatternTypePath, NameSpaceManager);
- if (BackgroundColor.Exists) {
- CreateNode(_backgroundColorPath);
- BackgroundColor.CreateXmlNode(
- topNode.SelectSingleNode(_backgroundColorPath, NameSpaceManager));
- if (PatternColor.Exists) {
- CreateNode(_patternColorPath);
- //topNode.AppendChild(PatternColor.CreateXmlNode(topNode.SelectSingleNode(_patternColorPath, NameSpaceManager)));
- PatternColor.CreateXmlNode(topNode.SelectSingleNode(_patternColorPath, NameSpaceManager));
- }
- }
- }
- return topNode;
- }
-
- private string SetPatternString(ExcelFillStyle pattern) {
- string newName = Enum.GetName(typeof(ExcelFillStyle), pattern);
- return newName.Substring(0, 1).ToLower(CultureInfo.InvariantCulture)
- + newName.Substring(1, newName.Length - 1);
- }
-}
diff --git a/EPPlus/Style/XmlAccess/ExcelFontXml.cs b/EPPlus/Style/XmlAccess/ExcelFontXml.cs
deleted file mode 100644
index 2d90c95..0000000
--- a/EPPlus/Style/XmlAccess/ExcelFontXml.cs
+++ /dev/null
@@ -1,294 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System;
-using System.Globalization;
-using System.Xml;
-
-namespace OfficeOpenXml.Style.XmlAccess;
-
-/// <summary>
-/// Xml access class for fonts
-/// </summary>
-public sealed class ExcelFontXml : StyleXmlHelper {
- internal ExcelFontXml(XmlNamespaceManager nameSpaceManager)
- : base(nameSpaceManager) {
- _name = "";
- _size = 0;
- _family = int.MinValue;
- _scheme = "";
- _color = _color = new(NameSpaceManager);
- _bold = false;
- _italic = false;
- _strike = false;
- _underlineType = ExcelUnderLineType.None;
- _verticalAlign = "";
- }
-
- internal ExcelFontXml(XmlNamespaceManager nsm, XmlNode topNode)
- : base(nsm, topNode) {
- _name = GetXmlNodeString(_namePath);
- _size = (float)GetXmlNodeDecimal(_sizePath);
- _family = GetXmlNodeIntNull(_familyPath) ?? int.MinValue;
- _scheme = GetXmlNodeString(_schemePath);
- _color = new(nsm, topNode.SelectSingleNode(_colorPath, nsm));
- _bold = GetBoolValue(topNode, _boldPath);
- _italic = GetBoolValue(topNode, _italicPath);
- _strike = GetBoolValue(topNode, _strikePath);
- _verticalAlign = GetXmlNodeString(_verticalAlignPath);
- if (topNode.SelectSingleNode(_underLinedPath, NameSpaceManager) != null) {
- string ut = GetXmlNodeString(_underLinedPath + "/@val");
- if (ut == "") {
- _underlineType = ExcelUnderLineType.Single;
- } else {
- if (!Enum.TryParse(ut, true, out _underlineType)) {
- _underlineType = ExcelUnderLineType.Single;
- }
- }
- } else {
- _underlineType = ExcelUnderLineType.None;
- }
- }
-
- internal override string Id =>
- Name
- + "|"
- + Size
- + "|"
- + Family
- + "|"
- + Color.Id
- + "|"
- + Scheme
- + "|"
- + Bold
- + "|"
- + Italic
- + "|"
- + Strike
- + "|"
- + VerticalAlign
- + "|"
- + UnderLineType;
-
- private const string _namePath = "d:name/@val";
- private string _name;
-
- /// <summary>
- /// The name of the font
- /// </summary>
- public string Name {
- get => _name;
- set {
- Scheme = ""; //Reset schema to avoid corrupt file if unsupported font is selected.
- _name = value;
- }
- }
-
- private const string _sizePath = "d:sz/@val";
- private float _size;
-
- /// <summary>
- /// Font size
- /// </summary>
- public float Size {
- get => _size;
- set => _size = value;
- }
-
- private const string _familyPath = "d:family/@val";
- private int _family;
-
- /// <summary>
- /// Font family
- /// </summary>
- public int Family {
- get => (_family == int.MinValue ? 0 : _family);
- set => _family = value;
- }
-
- private ExcelColorXml _color;
- private const string _colorPath = "d:color";
-
- /// <summary>
- /// Text color
- /// </summary>
- public ExcelColorXml Color {
- get => _color;
- internal set => _color = value;
- }
-
- private const string _schemePath = "d:scheme/@val";
- private string _scheme = "";
-
- /// <summary>
- /// Font Scheme
- /// </summary>
- public string Scheme {
- get => _scheme;
- private set => _scheme = value;
- }
-
- private const string _boldPath = "d:b";
- private bool _bold;
-
- /// <summary>
- /// If the font is bold
- /// </summary>
- public bool Bold {
- get => _bold;
- set => _bold = value;
- }
-
- private const string _italicPath = "d:i";
- private bool _italic;
-
- /// <summary>
- /// If the font is italic
- /// </summary>
- public bool Italic {
- get => _italic;
- set => _italic = value;
- }
-
- private const string _strikePath = "d:strike";
- private bool _strike;
-
- /// <summary>
- /// If the font is striked out
- /// </summary>
- public bool Strike {
- get => _strike;
- set => _strike = value;
- }
-
- private const string _underLinedPath = "d:u";
-
- /// <summary>
- /// If the font is underlined.
- /// When set to true a the text is underlined with a single line
- /// </summary>
- public bool UnderLine {
- get => UnderLineType != ExcelUnderLineType.None;
- set => _underlineType = value ? ExcelUnderLineType.Single : ExcelUnderLineType.None;
- }
-
- private ExcelUnderLineType _underlineType;
-
- /// <summary>
- /// If the font is underlined
- /// </summary>
- public ExcelUnderLineType UnderLineType {
- get => _underlineType;
- set => _underlineType = value;
- }
-
- private const string _verticalAlignPath = "d:vertAlign/@val";
- private string _verticalAlign;
-
- /// <summary>
- /// Vertical aligned
- /// </summary>
- public string VerticalAlign {
- get => _verticalAlign;
- set => _verticalAlign = value;
- }
-
- internal ExcelFontXml Copy() {
- ExcelFontXml newFont = new ExcelFontXml(NameSpaceManager);
- newFont.Name = _name;
- newFont.Size = _size;
- newFont.Family = _family;
- newFont.Scheme = _scheme;
- newFont.Bold = _bold;
- newFont.Italic = _italic;
- newFont.UnderLineType = _underlineType;
- newFont.Strike = _strike;
- newFont.VerticalAlign = _verticalAlign;
- newFont.Color = Color.Copy();
- return newFont;
- }
-
- internal override XmlNode CreateXmlNode(XmlNode topElement) {
- TopNode = topElement;
-
- if (_bold) {
- CreateNode(_boldPath);
- } else {
- DeleteAllNode(_boldPath);
- }
- if (_italic) {
- CreateNode(_italicPath);
- } else {
- DeleteAllNode(_italicPath);
- }
- if (_strike) {
- CreateNode(_strikePath);
- } else {
- DeleteAllNode(_strikePath);
- }
-
- if (_underlineType == ExcelUnderLineType.None) {
- DeleteAllNode(_underLinedPath);
- } else if (_underlineType == ExcelUnderLineType.Single) {
- CreateNode(_underLinedPath);
- } else {
- var v = _underlineType.ToString();
- SetXmlNodeString(
- _underLinedPath + "/@val",
- v.Substring(0, 1).ToLower(CultureInfo.InvariantCulture) + v.Substring(1));
- }
-
- if (_verticalAlign != "") {
- SetXmlNodeString(_verticalAlignPath, _verticalAlign);
- }
- if (_size > 0) {
- SetXmlNodeString(_sizePath, _size.ToString(CultureInfo.InvariantCulture));
- }
- if (_color.Exists) {
- CreateNode(_colorPath);
- TopNode.AppendChild(
- _color.CreateXmlNode(TopNode.SelectSingleNode(_colorPath, NameSpaceManager)));
- }
- if (!string.IsNullOrEmpty(_name)) {
- SetXmlNodeString(_namePath, _name);
- }
- if (_family > int.MinValue) {
- SetXmlNodeString(_familyPath, _family.ToString());
- }
- if (_scheme != "") {
- SetXmlNodeString(_schemePath, _scheme);
- }
-
- return TopNode;
- }
-}
diff --git a/EPPlus/Style/XmlAccess/ExcelGradientFillXml.cs b/EPPlus/Style/XmlAccess/ExcelGradientFillXml.cs
deleted file mode 100644
index 00adf5e..0000000
--- a/EPPlus/Style/XmlAccess/ExcelGradientFillXml.cs
+++ /dev/null
@@ -1,184 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System.Globalization;
-using System.Xml;
-
-namespace OfficeOpenXml.Style.XmlAccess;
-
-/// <summary>
-/// Xml access class for gradient fillsde
-/// </summary>
-public sealed class ExcelGradientFillXml : ExcelFillXml {
- internal ExcelGradientFillXml(XmlNamespaceManager nameSpaceManager)
- : base(nameSpaceManager) {
- GradientColor1 = new(nameSpaceManager);
- GradientColor2 = new(nameSpaceManager);
- }
-
- internal ExcelGradientFillXml(XmlNamespaceManager nsm, XmlNode topNode)
- : base(nsm, topNode) {
- Degree = GetXmlNodeDouble(_degreePath);
- Type =
- GetXmlNodeString(_typePath) == "path"
- ? ExcelFillGradientType.Path
- : ExcelFillGradientType.Linear;
- GradientColor1 = new(nsm, topNode.SelectSingleNode(_gradientColor1Path, nsm));
- GradientColor2 = new(nsm, topNode.SelectSingleNode(_gradientColor2Path, nsm));
-
- Top = GetXmlNodeDouble(_topPath);
- Bottom = GetXmlNodeDouble(_bottomPath);
- Left = GetXmlNodeDouble(_leftPath);
- Right = GetXmlNodeDouble(_rightPath);
- }
-
- private const string _typePath = "d:gradientFill/@type";
-
- /// <summary>
- /// Type of gradient fill.
- /// </summary>
- public ExcelFillGradientType Type { get; internal set; }
-
- private const string _degreePath = "d:gradientFill/@degree";
-
- /// <summary>
- /// Angle of the linear gradient
- /// </summary>
- public double Degree { get; internal set; }
-
- private const string _gradientColor1Path = "d:gradientFill/d:stop[@position=\"0\"]/d:color";
-
- /// <summary>
- /// Gradient color 1
- /// </summary>
- public ExcelColorXml GradientColor1 { get; private set; }
-
- private const string _gradientColor2Path = "d:gradientFill/d:stop[@position=\"1\"]/d:color";
-
- /// <summary>
- /// Gradient color 2
- /// </summary>
- public ExcelColorXml GradientColor2 { get; private set; }
-
- private const string _bottomPath = "d:gradientFill/@bottom";
-
- /// <summary>
- /// Percentage format bottom
- /// </summary>
- public double Bottom { get; internal set; }
-
- private const string _topPath = "d:gradientFill/@top";
-
- /// <summary>
- /// Percentage format top
- /// </summary>
- public double Top { get; internal set; }
-
- private const string _leftPath = "d:gradientFill/@left";
-
- /// <summary>
- /// Percentage format left
- /// </summary>
- public double Left { get; internal set; }
-
- private const string _rightPath = "d:gradientFill/@right";
-
- /// <summary>
- /// Percentage format right
- /// </summary>
- public double Right { get; internal set; }
-
- internal override string Id =>
- base.Id + Degree + GradientColor1.Id + GradientColor2.Id + Type + Left + Right + Bottom + Top;
-
- internal override ExcelFillXml Copy() {
- ExcelGradientFillXml newFill = new ExcelGradientFillXml(NameSpaceManager);
- newFill.PatternType = _fillPatternType;
- newFill.BackgroundColor = _backgroundColor.Copy();
- newFill.PatternColor = _patternColor.Copy();
-
- newFill.GradientColor1 = GradientColor1.Copy();
- newFill.GradientColor2 = GradientColor2.Copy();
- newFill.Type = Type;
- newFill.Degree = Degree;
- newFill.Top = Top;
- newFill.Bottom = Bottom;
- newFill.Left = Left;
- newFill.Right = Right;
-
- return newFill;
- }
-
- internal override XmlNode CreateXmlNode(XmlNode topNode) {
- TopNode = topNode;
- CreateNode("d:gradientFill");
- if (Type == ExcelFillGradientType.Path) {
- SetXmlNodeString(_typePath, "path");
- }
- if (!double.IsNaN(Degree)) {
- SetXmlNodeString(_degreePath, Degree.ToString(CultureInfo.InvariantCulture));
- }
- if (GradientColor1 != null) {
- /*** Gradient color node 1***/
- var node = TopNode.SelectSingleNode("d:gradientFill", NameSpaceManager);
- var stopNode = node.OwnerDocument.CreateElement("stop", ExcelPackage._schemaMain);
- stopNode.SetAttribute("position", "0");
- node.AppendChild(stopNode);
- var colorNode = node.OwnerDocument.CreateElement("color", ExcelPackage._schemaMain);
- stopNode.AppendChild(colorNode);
- GradientColor1.CreateXmlNode(colorNode);
-
- /*** Gradient color node 2***/
- stopNode = node.OwnerDocument.CreateElement("stop", ExcelPackage._schemaMain);
- stopNode.SetAttribute("position", "1");
- node.AppendChild(stopNode);
- colorNode = node.OwnerDocument.CreateElement("color", ExcelPackage._schemaMain);
- stopNode.AppendChild(colorNode);
-
- GradientColor2.CreateXmlNode(colorNode);
- }
- if (!double.IsNaN(Top)) {
- SetXmlNodeString(_topPath, Top.ToString("F5", CultureInfo.InvariantCulture));
- }
- if (!double.IsNaN(Bottom)) {
- SetXmlNodeString(_bottomPath, Bottom.ToString("F5", CultureInfo.InvariantCulture));
- }
- if (!double.IsNaN(Left)) {
- SetXmlNodeString(_leftPath, Left.ToString("F5", CultureInfo.InvariantCulture));
- }
- if (!double.IsNaN(Right)) {
- SetXmlNodeString(_rightPath, Right.ToString("F5", CultureInfo.InvariantCulture));
- }
-
- return topNode;
- }
-}
diff --git a/EPPlus/Style/XmlAccess/ExcelNamedStyleXml.cs b/EPPlus/Style/XmlAccess/ExcelNamedStyleXml.cs
deleted file mode 100644
index 8004056..0000000
--- a/EPPlus/Style/XmlAccess/ExcelNamedStyleXml.cs
+++ /dev/null
@@ -1,127 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.Style.XmlAccess;
-
-/// <summary>
-/// Xml access class for named styles
-/// </summary>
-public sealed class ExcelNamedStyleXml : StyleXmlHelper {
- private readonly ExcelStyles _styles;
-
- internal ExcelNamedStyleXml(XmlNamespaceManager nameSpaceManager, ExcelStyles styles)
- : base(nameSpaceManager) {
- _styles = styles;
- BuildInId = int.MinValue;
- }
-
- internal ExcelNamedStyleXml(
- XmlNamespaceManager nameSpaceManager,
- XmlNode topNode,
- ExcelStyles styles)
- : base(nameSpaceManager, topNode) {
- StyleXfId = GetXmlNodeInt(_idPath);
- Name = GetXmlNodeString(_namePath);
- BuildInId = GetXmlNodeInt(_buildInIdPath);
- CustomBuildin = GetXmlNodeBool(_customBuiltinPath);
-
- _styles = styles;
- _style = new(styles, styles.NamedStylePropertyChange, -1, Name, _styleXfId);
- }
-
- internal override string Id => Name;
-
- private int _styleXfId;
- private const string _idPath = "@xfId";
-
- /// <summary>
- /// Named style index
- /// </summary>
- public int StyleXfId {
- get => _styleXfId;
- set => _styleXfId = value;
- }
-
- private int _xfId = int.MinValue;
-
- /// <summary>
- /// Style index
- /// </summary>
- internal int XfId {
- get => _xfId;
- set => _xfId = value;
- }
-
- private const string _buildInIdPath = "@builtinId";
-
- public int BuildInId { get; set; }
-
- private const string _customBuiltinPath = "@customBuiltin";
-
- public bool CustomBuildin { get; set; }
-
- private const string _namePath = "@name";
- private string _name;
-
- /// <summary>
- /// Name of the style
- /// </summary>
- public string Name {
- get => _name;
- internal set => _name = value;
- }
-
- private ExcelStyle _style;
-
- /// <summary>
- /// The style object
- /// </summary>
- public ExcelStyle Style {
- get => _style;
- internal set => _style = value;
- }
-
- internal override XmlNode CreateXmlNode(XmlNode topNode) {
- TopNode = topNode;
- SetXmlNodeString(_namePath, _name);
- SetXmlNodeString("@xfId", _styles.CellStyleXfs[StyleXfId].newID.ToString());
- if (BuildInId >= 0) {
- SetXmlNodeString("@builtinId", BuildInId.ToString());
- }
- if (CustomBuildin) {
- SetXmlNodeBool(_customBuiltinPath, true);
- }
- return TopNode;
- }
-}
diff --git a/EPPlus/Style/XmlAccess/ExcelNumberFormatXml.cs b/EPPlus/Style/XmlAccess/ExcelNumberFormatXml.cs
deleted file mode 100644
index c67aed9..0000000
--- a/EPPlus/Style/XmlAccess/ExcelNumberFormatXml.cs
+++ /dev/null
@@ -1,696 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Xml;
-
-namespace OfficeOpenXml.Style.XmlAccess;
-
-/// <summary>
-/// Xml access class for number formats
-/// </summary>
-public sealed class ExcelNumberFormatXml : StyleXmlHelper {
- internal ExcelNumberFormatXml(XmlNamespaceManager nameSpaceManager)
- : base(nameSpaceManager) {}
-
- internal ExcelNumberFormatXml(XmlNamespaceManager nameSpaceManager, bool buildIn)
- : base(nameSpaceManager) {
- BuildIn = buildIn;
- }
-
- internal ExcelNumberFormatXml(XmlNamespaceManager nsm, XmlNode topNode)
- : base(nsm, topNode) {
- _numFmtId = GetXmlNodeInt("@numFmtId");
- _format = GetXmlNodeString("@formatCode");
- }
-
- public bool BuildIn { get; private set; }
-
- private int _numFmtId;
-
- // const string idPath = "@numFmtId";
- /// <summary>
- /// Id for number format
- ///
- /// Build in ID's
- ///
- /// 0 General
- /// 1 0
- /// 2 0.00
- /// 3 #,##0
- /// 4 #,##0.00
- /// 9 0%
- /// 10 0.00%
- /// 11 0.00E+00
- /// 12 # ?/?
- /// 13 # ??/??
- /// 14 mm-dd-yy
- /// 15 d-mmm-yy
- /// 16 d-mmm
- /// 17 mmm-yy
- /// 18 h:mm AM/PM
- /// 19 h:mm:ss AM/PM
- /// 20 h:mm
- /// 21 h:mm:ss
- /// 22 m/d/yy h:mm
- /// 37 #,##0 ;(#,##0)
- /// 38 #,##0 ;[Red](#,##0)
- /// 39 #,##0.00;(#,##0.00)
- /// 40 #,##0.00;[Red](#,##0.00)
- /// 45 mm:ss
- /// 46 [h]:mm:ss
- /// 47 mmss.0
- /// 48 ##0.0E+0
- /// 49 @
- /// </summary>
- public int NumFmtId {
- get => _numFmtId;
- set => _numFmtId = value;
- }
-
- internal override string Id => _format;
-
- private string _format = string.Empty;
-
- public string Format {
- get => _format;
- set {
- _numFmtId = ExcelNumberFormat.GetFromBuildIdFromFormat(value);
- _format = value;
- }
- }
-
- internal string GetNewId(int numFmtId, string format) {
- if (numFmtId < 0) {
- numFmtId = ExcelNumberFormat.GetFromBuildIdFromFormat(format);
- }
- return numFmtId.ToString();
- }
-
- internal static void AddBuildIn(
- XmlNamespaceManager nameSpaceManager,
- ExcelStyleCollection<ExcelNumberFormatXml> numberFormats) {
- numberFormats.Add(
- "General",
- new(nameSpaceManager, true) {
- NumFmtId = 0,
- Format = "General",
- });
- numberFormats.Add(
- "0",
- new(nameSpaceManager, true) {
- NumFmtId = 1,
- Format = "0",
- });
- numberFormats.Add(
- "0.00",
- new(nameSpaceManager, true) {
- NumFmtId = 2,
- Format = "0.00",
- });
- numberFormats.Add(
- "#,##0",
- new(nameSpaceManager, true) {
- NumFmtId = 3,
- Format = "#,##0",
- });
- numberFormats.Add(
- "#,##0.00",
- new(nameSpaceManager, true) {
- NumFmtId = 4,
- Format = "#,##0.00",
- });
- numberFormats.Add(
- "0%",
- new(nameSpaceManager, true) {
- NumFmtId = 9,
- Format = "0%",
- });
- numberFormats.Add(
- "0.00%",
- new(nameSpaceManager, true) {
- NumFmtId = 10,
- Format = "0.00%",
- });
- numberFormats.Add(
- "0.00E+00",
- new(nameSpaceManager, true) {
- NumFmtId = 11,
- Format = "0.00E+00",
- });
- numberFormats.Add(
- "# ?/?",
- new(nameSpaceManager, true) {
- NumFmtId = 12,
- Format = "# ?/?",
- });
- numberFormats.Add(
- "# ??/??",
- new(nameSpaceManager, true) {
- NumFmtId = 13,
- Format = "# ??/??",
- });
- numberFormats.Add(
- "mm-dd-yy",
- new(nameSpaceManager, true) {
- NumFmtId = 14,
- Format = "mm-dd-yy",
- });
- numberFormats.Add(
- "d-mmm-yy",
- new(nameSpaceManager, true) {
- NumFmtId = 15,
- Format = "d-mmm-yy",
- });
- numberFormats.Add(
- "d-mmm",
- new(nameSpaceManager, true) {
- NumFmtId = 16,
- Format = "d-mmm",
- });
- numberFormats.Add(
- "mmm-yy",
- new(nameSpaceManager, true) {
- NumFmtId = 17,
- Format = "mmm-yy",
- });
- numberFormats.Add(
- "h:mm AM/PM",
- new(nameSpaceManager, true) {
- NumFmtId = 18,
- Format = "h:mm AM/PM",
- });
- numberFormats.Add(
- "h:mm:ss AM/PM",
- new(nameSpaceManager, true) {
- NumFmtId = 19,
- Format = "h:mm:ss AM/PM",
- });
- numberFormats.Add(
- "h:mm",
- new(nameSpaceManager, true) {
- NumFmtId = 20,
- Format = "h:mm",
- });
- numberFormats.Add(
- "h:mm:ss",
- new(nameSpaceManager, true) {
- NumFmtId = 21,
- Format = "h:mm:ss",
- });
- numberFormats.Add(
- "m/d/yy h:mm",
- new(nameSpaceManager, true) {
- NumFmtId = 22,
- Format = "m/d/yy h:mm",
- });
- numberFormats.Add(
- "#,##0 ;(#,##0)",
- new(nameSpaceManager, true) {
- NumFmtId = 37,
- Format = "#,##0 ;(#,##0)",
- });
- numberFormats.Add(
- "#,##0 ;[Red](#,##0)",
- new(nameSpaceManager, true) {
- NumFmtId = 38,
- Format = "#,##0 ;[Red](#,##0)",
- });
- numberFormats.Add(
- "#,##0.00;(#,##0.00)",
- new(nameSpaceManager, true) {
- NumFmtId = 39,
- Format = "#,##0.00;(#,##0.00)",
- });
- numberFormats.Add(
- "#,##0.00;[Red](#,##0.00)",
- new(nameSpaceManager, true) {
- NumFmtId = 40,
- Format = "#,##0.00;[Red](#,#)",
- });
- numberFormats.Add(
- "mm:ss",
- new(nameSpaceManager, true) {
- NumFmtId = 45,
- Format = "mm:ss",
- });
- numberFormats.Add(
- "[h]:mm:ss",
- new(nameSpaceManager, true) {
- NumFmtId = 46,
- Format = "[h]:mm:ss",
- });
- numberFormats.Add(
- "mmss.0",
- new(nameSpaceManager, true) {
- NumFmtId = 47,
- Format = "mmss.0",
- });
- numberFormats.Add(
- "##0.0",
- new(nameSpaceManager, true) {
- NumFmtId = 48,
- Format = "##0.0",
- });
- numberFormats.Add(
- "@",
- new(nameSpaceManager, true) {
- NumFmtId = 49,
- Format = "@",
- });
-
- numberFormats.NextId = 164; //Start for custom formats.
- }
-
- internal override XmlNode CreateXmlNode(XmlNode topNode) {
- TopNode = topNode;
- SetXmlNodeString("@numFmtId", NumFmtId.ToString());
- SetXmlNodeString("@formatCode", Format);
- return TopNode;
- }
-
- internal enum eFormatType {
- Unknown = 0,
- Number = 1,
- DateTime = 2,
- }
-
- private ExcelFormatTranslator _translator;
-
- internal ExcelFormatTranslator FormatTranslator {
- get {
- if (_translator == null) {
- _translator = new(Format, NumFmtId);
- }
- return _translator;
- }
- }
-
- internal class ExcelFormatTranslator {
- internal ExcelFormatTranslator(string format, int numFmtId) {
- if (numFmtId == 14) {
- NetFormat = NetFormatForWidth = "d";
- NetTextFormat = NetTextFormatForWidth = "";
- DataType = eFormatType.DateTime;
- } else if (format.Equals("general", StringComparison.InvariantCultureIgnoreCase)) {
- NetFormat = NetFormatForWidth = "0.#####";
- NetTextFormat = NetTextFormatForWidth = "";
- DataType = eFormatType.Number;
- } else {
- ToNetFormat(format, false);
- ToNetFormat(format, true);
- }
- }
-
- internal string NetTextFormat { get; private set; }
-
- internal string NetFormat { get; private set; }
-
- private CultureInfo _ci;
-
- internal CultureInfo Culture {
- get {
- if (_ci == null) {
- return CultureInfo.CurrentCulture;
- }
- return _ci;
- }
- private set => _ci = value;
- }
-
- internal eFormatType DataType { get; private set; }
-
- internal string NetTextFormatForWidth { get; private set; }
-
- internal string NetFormatForWidth { get; private set; }
-
- internal string FractionFormat { get; private set; }
-
- private void ToNetFormat(string excelFormat, bool forColWidth) {
- DataType = eFormatType.Unknown;
- int secCount = 0;
- bool isText = false;
- bool isBracket = false;
- string bracketText = "";
- bool prevBslsh = false;
- bool useMinute = false;
- bool prevUnderScore = false;
- bool ignoreNext = false;
- string specialDateFormat = "";
- bool containsAmPm = excelFormat.Contains("AM/PM");
- List<int> lstDec = new List<int>();
- StringBuilder sb = new StringBuilder();
- Culture = null;
- var format = "";
- var text = "";
- char clc;
-
- if (containsAmPm) {
- excelFormat = Regex.Replace(excelFormat, "AM/PM", "");
- DataType = eFormatType.DateTime;
- }
-
- for (int pos = 0; pos < excelFormat.Length; pos++) {
- char c = excelFormat[pos];
- if (c == '"') {
- isText = !isText;
- } else {
- if (ignoreNext) {
- ignoreNext = false;
- continue;
- }
- if (isText && !isBracket) {
- sb.Append(c);
- } else if (isBracket) {
- if (c == ']') {
- isBracket = false;
- if (bracketText[0]
- == '$') //Local Info
- {
- string[] li = Regex.Split(bracketText, "-");
- if (li[0].Length > 1) {
- sb.Append("\"" + li[0].Substring(1, li[0].Length - 1) + "\""); //Currency symbol
- }
- if (li.Length > 1) {
- if (li[1].Equals("f800", StringComparison.InvariantCultureIgnoreCase)) {
- specialDateFormat = "D";
- } else if (li[1].Equals("f400", StringComparison.InvariantCultureIgnoreCase)) {
- specialDateFormat = "T";
- } else {
- var num = int.Parse(li[1], NumberStyles.HexNumber);
- try {
- Culture = CultureInfo.GetCultureInfo(num & 0xFFFF);
- } catch {
- Culture = null;
- }
- }
- }
- } else if (bracketText[0] == 't') {
- sb.Append("hh"); //TODO:This will not be correct for dates over 24H.
- } else if (bracketText[0] == 'h') {
- specialDateFormat = "hh"; //TODO:This will not be correct for dates over 24H.
- }
- } else {
- bracketText += c;
- }
- } else if (prevUnderScore) {
- if (forColWidth) {
- sb.AppendFormat("\"{0}\"", c);
- }
- prevUnderScore = false;
- } else {
- if (c
- == ';') //We use first part (for positive only at this stage)
- {
- secCount++;
- if (DataType == eFormatType.DateTime || secCount == 3) {
- //Add qoutes
- if (DataType == eFormatType.DateTime) {
- SetDecimal(lstDec, sb); //Remove?
- }
- lstDec = new();
- format = sb.ToString();
- sb = new();
- } else {
- sb.Append(c);
- }
- } else {
- clc = c.ToString().ToLower(CultureInfo.InvariantCulture)[0]; //Lowercase character
- //Set the datetype
- if (DataType == eFormatType.Unknown) {
- if (c == '0' || c == '#' || c == '.') {
- DataType = eFormatType.Number;
- } else if (clc == 'y'
- || clc == 'm'
- || clc == 'd'
- || clc == 'h'
- || clc == 'm'
- || clc == 's') {
- DataType = eFormatType.DateTime;
- }
- }
-
- if (prevBslsh) {
- if (c == '.' || c == ',') {
- sb.Append('\\');
- }
- sb.Append(c);
- prevBslsh = false;
- } else if (c == '[') {
- bracketText = "";
- isBracket = true;
- } else if (c == '\\') {
- prevBslsh = true;
- } else if (c == '0'
- || c == '#'
- || c == '.'
- || c == ','
- || c == '%'
- || clc == 'd'
- || clc == 's') {
- sb.Append(c);
- if (c == '.') {
- lstDec.Add(sb.Length - 1);
- }
- } else if (clc == 'h') {
- if (containsAmPm) {
- sb.Append('h');
- ;
- } else {
- sb.Append('H');
- }
- useMinute = true;
- } else if (clc == 'm') {
- if (useMinute) {
- sb.Append('m');
- } else {
- sb.Append('M');
- }
- } else if (c
- == '_') //Skip next but use for alignment
- {
- prevUnderScore = true;
- } else if (c == '?') {
- sb.Append(' ');
- } else if (c == '/') {
- if (DataType == eFormatType.Number) {
- int startPos = pos - 1;
- while (startPos >= 0
- && (excelFormat[startPos] == '?'
- || excelFormat[startPos] == '#'
- || excelFormat[startPos] == '0')) {
- startPos--;
- }
-
- if (startPos
- > 0) //RemovePart
- {
- sb.Remove(sb.Length - (pos - startPos - 1), (pos - startPos - 1));
- }
-
- int endPos = pos + 1;
- while (endPos < excelFormat.Length
- && (excelFormat[endPos] == '?'
- || excelFormat[endPos] == '#'
- || (excelFormat[endPos] >= '0' && excelFormat[endPos] <= '9'))) {
- endPos++;
- }
- pos = endPos;
- if (FractionFormat != "") {
- FractionFormat = excelFormat.Substring(startPos + 1, endPos - startPos - 1);
- }
- sb.Append('?'); //Will be replaced later on by the fraction
- } else {
- sb.Append('/');
- }
- } else if (c == '*') {
- //repeat char--> ignore
- ignoreNext = true;
- } else if (c == '@') {
- sb.Append("{0}");
- } else {
- sb.Append(c);
- }
- }
- }
- }
- }
-
- //Add qoutes
- if (DataType == eFormatType.DateTime) {
- SetDecimal(lstDec, sb); //Remove?
- }
-
- // AM/PM format
- if (containsAmPm) {
- format += "tt";
- }
-
- if (format == "") {
- format = sb.ToString();
- } else {
- text = sb.ToString();
- }
- if (specialDateFormat != "") {
- format = specialDateFormat;
- }
-
- if (forColWidth) {
- NetFormatForWidth = format;
- NetTextFormatForWidth = text;
- } else {
- NetFormat = format;
- NetTextFormat = text;
- }
- if (Culture == null) {
- Culture = CultureInfo.CurrentCulture;
- }
- }
-
- private static void SetDecimal(List<int> lstDec, StringBuilder sb) {
- if (lstDec.Count > 1) {
- for (int i = lstDec.Count - 1; i >= 0; i--) {
- sb.Insert(lstDec[i] + 1, '\'');
- sb.Insert(lstDec[i], '\'');
- }
- }
- }
-
- internal string FormatFraction(double d) {
- int numerator,
- denomerator;
-
- int intPart = (int)d;
-
- string[] fmt = FractionFormat.Split('/');
-
- if (!int.TryParse(fmt[1], out var fixedDenominator)) {
- fixedDenominator = 0;
- }
-
- if (d == 0 || double.IsNaN(d)) {
- if (fmt[0].Trim() == "" && fmt[1].Trim() == "") {
- return new(' ', FractionFormat.Length);
- }
- return 0.ToString(fmt[0]) + "/" + 1.ToString(fmt[0]);
- }
-
- int maxDigits = fmt[1].Length;
- string sign = d < 0 ? "-" : "";
- if (fixedDenominator == 0) {
- List<double> numerators = new List<double> { 1, 0 };
- List<double> denominators = new List<double> { 0, 1 };
-
- if (maxDigits < 1 && maxDigits > 12) {
- throw (new ArgumentException("Number of digits out of range (1-12)"));
- }
-
- int maxNum = 0;
- for (int i = 0; i < maxDigits; i++) {
- maxNum += 9 * (int)(Math.Pow(10, i));
- }
-
- double divRes = 1 / (Math.Abs(d) - intPart);
- double result,
- prevResult = double.NaN;
- int listPos = 2,
- index = 1;
- while (true) {
- index++;
- double intDivRes = Math.Floor(divRes);
- numerators.Add((intDivRes * numerators[index - 1] + numerators[index - 2]));
- if (numerators[index] > maxNum) {
- break;
- }
-
- denominators.Add((intDivRes * denominators[index - 1] + denominators[index - 2]));
-
- result = numerators[index] / denominators[index];
- if (denominators[index] > maxNum) {
- break;
- }
- listPos = index;
-
- if (result == prevResult) {
- break;
- }
-
- if (result == d) {
- break;
- }
-
- prevResult = result;
-
- divRes = 1 / (divRes - intDivRes); //Rest
- }
-
- numerator = (int)numerators[listPos];
- denomerator = (int)denominators[listPos];
- } else {
- numerator = (int)Math.Round((d - intPart) / (1D / fixedDenominator), 0);
- denomerator = fixedDenominator;
- }
- if (numerator == denomerator || numerator == 0) {
- if (numerator == denomerator) {
- intPart++;
- }
- return sign + intPart.ToString(NetFormat).Replace("?", new(' ', FractionFormat.Length));
- }
- if (intPart == 0) {
- return sign + FmtInt(numerator, fmt[0]) + "/" + FmtInt(denomerator, fmt[1]);
- }
- return sign
- + intPart
- .ToString(NetFormat)
- .Replace("?", FmtInt(numerator, fmt[0]) + "/" + FmtInt(denomerator, fmt[1]));
- }
-
- private string FmtInt(double value, string format) {
- string v = value.ToString("#");
- string pad = "";
- if (v.Length < format.Length) {
- for (int i = format.Length - v.Length - 1; i >= 0; i--) {
- if (format[i] == '?') {
- pad += " ";
- } else if (format[i] == ' ') {
- pad += "0";
- }
- }
- }
- return pad + v;
- }
- }
-}
diff --git a/EPPlus/Style/XmlAccess/ExcelXfsXml.cs b/EPPlus/Style/XmlAccess/ExcelXfsXml.cs
deleted file mode 100644
index 45acdda..0000000
--- a/EPPlus/Style/XmlAccess/ExcelXfsXml.cs
+++ /dev/null
@@ -1,717 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System;
-using System.Globalization;
-using System.Xml;
-
-namespace OfficeOpenXml.Style.XmlAccess;
-
-/// <summary>
-/// Xml access class xfs records. This is the top level style object.
-/// </summary>
-public sealed class ExcelXfs : StyleXmlHelper {
- private readonly ExcelStyles _styles;
-
- internal ExcelXfs(XmlNamespaceManager nameSpaceManager, ExcelStyles styles)
- : base(nameSpaceManager) {
- _styles = styles;
- isBuildIn = false;
- }
-
- internal ExcelXfs(XmlNamespaceManager nsm, XmlNode topNode, ExcelStyles styles)
- : base(nsm, topNode) {
- _styles = styles;
- _xfID = GetXmlNodeInt("@xfId");
- if (_xfID == 0) {
- isBuildIn = true; //Normal taggen
- }
- _numFmtId = GetXmlNodeInt("@numFmtId");
- _fontId = GetXmlNodeInt("@fontId");
- _fillId = GetXmlNodeInt("@fillId");
- _borderId = GetXmlNodeInt("@borderId");
- _readingOrder = GetReadingOrder(GetXmlNodeString(_readingOrderPath));
- _indent = GetXmlNodeInt(_indentPath);
- _shrinkToFit = GetXmlNodeString(_shrinkToFitPath) == "1" ? true : false;
- _verticalAlignment = GetVerticalAlign(GetXmlNodeString(_verticalAlignPath));
- _horizontalAlignment = GetHorizontalAlign(GetXmlNodeString(_horizontalAlignPath));
- _wrapText = GetXmlNodeBool(_wrapTextPath);
- _textRotation = GetXmlNodeInt(textRotationPath);
- _hidden = GetXmlNodeBool(_hiddenPath);
- _locked = GetXmlNodeBool(_lockedPath, true);
- }
-
- private ExcelReadingOrder GetReadingOrder(string value) {
- switch (value) {
- case "1":
- return ExcelReadingOrder.LeftToRight;
- case "2":
- return ExcelReadingOrder.RightToLeft;
- default:
- return ExcelReadingOrder.ContextDependent;
- }
- }
-
- private ExcelHorizontalAlignment GetHorizontalAlign(string align) =>
- Enum.TryParse<ExcelHorizontalAlignment>(align, true, out var result)
- ? result
- : ExcelHorizontalAlignment.General;
-
- private ExcelVerticalAlignment GetVerticalAlign(string align) =>
- Enum.TryParse<ExcelVerticalAlignment>(align, true, out var result)
- ? result
- : ExcelVerticalAlignment.Bottom;
-
- private int _xfID;
-
- /// <summary>
- /// Style index
- /// </summary>
- public int XfId {
- get => _xfID;
- set => _xfID = value;
- }
-
- private int _numFmtId;
-
- internal int NumberFormatId {
- get => _numFmtId;
- set {
- _numFmtId = value;
- ApplyNumberFormat = (value > 0);
- }
- }
-
- private int _fontId;
-
- internal int FontId {
- get => _fontId;
- set => _fontId = value;
- }
-
- private int _fillId;
-
- internal int FillId {
- get => _fillId;
- set => _fillId = value;
- }
-
- private int _borderId;
-
- internal int BorderId {
- get => _borderId;
- set => _borderId = value;
- }
-
- private bool isBuildIn { get; set; }
-
- internal bool ApplyNumberFormat { get; set; }
-
- internal bool ApplyFont { get; set; }
-
- internal bool ApplyFill { get; set; }
-
- internal bool ApplyBorder { get; set; }
-
- internal bool ApplyAlignment { get; set; }
-
- internal bool ApplyProtection { get; set; }
-
- public ExcelStyles Styles { get; private set; }
-
- /// <summary>
- /// Numberformat properties
- /// </summary>
- public ExcelNumberFormatXml Numberformat => _styles.NumberFormats[_numFmtId < 0 ? 0 : _numFmtId];
-
- /// <summary>
- /// Font properties
- /// </summary>
- public ExcelFontXml Font => _styles.Fonts[_fontId < 0 ? 0 : _fontId];
-
- /// <summary>
- /// Fill properties
- /// </summary>
- public ExcelFillXml Fill => _styles.Fills[_fillId < 0 ? 0 : _fillId];
-
- /// <summary>
- /// Border style properties
- /// </summary>
- public ExcelBorderXml Border => _styles.Borders[_borderId < 0 ? 0 : _borderId];
-
- private const string _horizontalAlignPath = "d:alignment/@horizontal";
- private ExcelHorizontalAlignment _horizontalAlignment = ExcelHorizontalAlignment.General;
-
- /// <summary>
- /// Horizontal alignment
- /// </summary>
- public ExcelHorizontalAlignment HorizontalAlignment {
- get => _horizontalAlignment;
- set => _horizontalAlignment = value;
- }
-
- private const string _verticalAlignPath = "d:alignment/@vertical";
- private ExcelVerticalAlignment _verticalAlignment = ExcelVerticalAlignment.Bottom;
-
- /// <summary>
- /// Vertical alignment
- /// </summary>
- public ExcelVerticalAlignment VerticalAlignment {
- get => _verticalAlignment;
- set => _verticalAlignment = value;
- }
-
- private const string _wrapTextPath = "d:alignment/@wrapText";
- private bool _wrapText;
-
- /// <summary>
- /// Wraped text
- /// </summary>
- public bool WrapText {
- get => _wrapText;
- set => _wrapText = value;
- }
-
- private readonly string textRotationPath = "d:alignment/@textRotation";
- private int _textRotation;
-
- /// <summary>
- /// Text rotation angle
- /// </summary>
- public int TextRotation {
- get => (_textRotation == int.MinValue ? 0 : _textRotation);
- set => _textRotation = value;
- }
-
- private const string _lockedPath = "d:protection/@locked";
- private bool _locked = true;
-
- /// <summary>
- /// Locked when sheet is protected
- /// </summary>
- public bool Locked {
- get => _locked;
- set => _locked = value;
- }
-
- private const string _hiddenPath = "d:protection/@hidden";
- private bool _hidden;
-
- /// <summary>
- /// Hide formulas when sheet is protected
- /// </summary>
- public bool Hidden {
- get => _hidden;
- set => _hidden = value;
- }
-
- private const string _readingOrderPath = "d:alignment/@readingOrder";
- private ExcelReadingOrder _readingOrder = ExcelReadingOrder.ContextDependent;
-
- /// <summary>
- /// Readingorder
- /// </summary>
- public ExcelReadingOrder ReadingOrder {
- get => _readingOrder;
- set => _readingOrder = value;
- }
-
- private const string _shrinkToFitPath = "d:alignment/@shrinkToFit";
- private bool _shrinkToFit;
-
- /// <summary>
- /// Shrink to fit
- /// </summary>
- public bool ShrinkToFit {
- get => _shrinkToFit;
- set => _shrinkToFit = value;
- }
-
- private const string _indentPath = "d:alignment/@indent";
- private int _indent;
-
- /// <summary>
- /// Indentation
- /// </summary>
- public int Indent {
- get => (_indent == int.MinValue ? 0 : _indent);
- set => _indent = value;
- }
-
- internal void RegisterEvent(ExcelXfs xf) {
- // RegisterEvent(xf, xf.Xf_ChangedEvent);
- }
-
- internal override string Id =>
- XfId
- + "|"
- + NumberFormatId
- + "|"
- + FontId
- + "|"
- + FillId
- + "|"
- + BorderId
- + VerticalAlignment
- + "|"
- + HorizontalAlignment
- + "|"
- + WrapText
- + "|"
- + ReadingOrder
- + "|"
- + isBuildIn
- + TextRotation
- + Locked
- + Hidden
- + ShrinkToFit
- + Indent;
-
- //return Numberformat.Id + "|" + Font.Id + "|" + Fill.Id + "|" + Border.Id + VerticalAlignment.ToString() + "|" + HorizontalAlignment.ToString() + "|" + WrapText.ToString() + "|" + ReadingOrder.ToString();
- internal ExcelXfs Copy() {
- return Copy(_styles);
- }
-
- internal ExcelXfs Copy(ExcelStyles styles) {
- ExcelXfs newXf = new ExcelXfs(NameSpaceManager, styles);
- newXf.NumberFormatId = _numFmtId;
- newXf.FontId = _fontId;
- newXf.FillId = _fillId;
- newXf.BorderId = _borderId;
- newXf.XfId = _xfID;
- newXf.ReadingOrder = _readingOrder;
- newXf.HorizontalAlignment = _horizontalAlignment;
- newXf.VerticalAlignment = _verticalAlignment;
- newXf.WrapText = _wrapText;
- newXf.ShrinkToFit = _shrinkToFit;
- newXf.Indent = _indent;
- newXf.TextRotation = _textRotation;
- newXf.Locked = _locked;
- newXf.Hidden = _hidden;
- return newXf;
- }
-
- internal int GetNewId(
- ExcelStyleCollection<ExcelXfs> xfsCol,
- StyleBase styleObject,
- eStyleClass styleClass,
- eStyleProperty styleProperty,
- object value) {
- ExcelXfs newXfs = Copy();
- switch (styleClass) {
- case eStyleClass.Numberformat:
- newXfs.NumberFormatId = GetIdNumberFormat(styleProperty, value);
- styleObject.SetIndex(newXfs.NumberFormatId);
- break;
- case eStyleClass.Font: {
- newXfs.FontId = GetIdFont(styleProperty, value);
- styleObject.SetIndex(newXfs.FontId);
- break;
- }
- case eStyleClass.Fill:
- case eStyleClass.FillBackgroundColor:
- case eStyleClass.FillPatternColor:
- newXfs.FillId = GetIdFill(styleClass, styleProperty, value);
- styleObject.SetIndex(newXfs.FillId);
- break;
- case eStyleClass.GradientFill:
- case eStyleClass.FillGradientColor1:
- case eStyleClass.FillGradientColor2:
- newXfs.FillId = GetIdGradientFill(styleClass, styleProperty, value);
- styleObject.SetIndex(newXfs.FillId);
- break;
- case eStyleClass.Border:
- case eStyleClass.BorderBottom:
- case eStyleClass.BorderDiagonal:
- case eStyleClass.BorderLeft:
- case eStyleClass.BorderRight:
- case eStyleClass.BorderTop:
- newXfs.BorderId = GetIdBorder(styleClass, styleProperty, value);
- styleObject.SetIndex(newXfs.BorderId);
- break;
- case eStyleClass.Style:
- switch (styleProperty) {
- case eStyleProperty.XfId:
- newXfs.XfId = (int)value;
- break;
- case eStyleProperty.HorizontalAlign:
- newXfs.HorizontalAlignment = (ExcelHorizontalAlignment)value;
- break;
- case eStyleProperty.VerticalAlign:
- newXfs.VerticalAlignment = (ExcelVerticalAlignment)value;
- break;
- case eStyleProperty.WrapText:
- newXfs.WrapText = (bool)value;
- break;
- case eStyleProperty.ReadingOrder:
- newXfs.ReadingOrder = (ExcelReadingOrder)value;
- break;
- case eStyleProperty.ShrinkToFit:
- newXfs.ShrinkToFit = (bool)value;
- break;
- case eStyleProperty.Indent:
- newXfs.Indent = (int)value;
- break;
- case eStyleProperty.TextRotation:
- newXfs.TextRotation = (int)value;
- break;
- case eStyleProperty.Locked:
- newXfs.Locked = (bool)value;
- break;
- case eStyleProperty.Hidden:
- newXfs.Hidden = (bool)value;
- break;
- default:
- throw (new("Invalid property for class style."));
- }
- break;
- }
- int id = xfsCol.FindIndexById(newXfs.Id);
- if (id < 0) {
- return xfsCol.Add(newXfs.Id, newXfs);
- }
- return id;
- }
-
- private int GetIdBorder(eStyleClass styleClass, eStyleProperty styleProperty, object value) {
- ExcelBorderXml border = Border.Copy();
-
- switch (styleClass) {
- case eStyleClass.BorderBottom:
- SetBorderItem(border.Bottom, styleProperty, value);
- break;
- case eStyleClass.BorderDiagonal:
- SetBorderItem(border.Diagonal, styleProperty, value);
- break;
- case eStyleClass.BorderLeft:
- SetBorderItem(border.Left, styleProperty, value);
- break;
- case eStyleClass.BorderRight:
- SetBorderItem(border.Right, styleProperty, value);
- break;
- case eStyleClass.BorderTop:
- SetBorderItem(border.Top, styleProperty, value);
- break;
- case eStyleClass.Border:
- if (styleProperty == eStyleProperty.BorderDiagonalUp) {
- border.DiagonalUp = (bool)value;
- } else if (styleProperty == eStyleProperty.BorderDiagonalDown) {
- border.DiagonalDown = (bool)value;
- } else {
- throw (new("Invalid property for class Border."));
- }
- break;
- default:
- throw (new("Invalid class/property for class Border."));
- }
- int subId;
- string id = border.Id;
- subId = _styles.Borders.FindIndexById(id);
- if (subId == int.MinValue) {
- return _styles.Borders.Add(id, border);
- }
- return subId;
- }
-
- private void SetBorderItem(
- ExcelBorderItemXml excelBorderItem,
- eStyleProperty styleProperty,
- object value) {
- if (styleProperty == eStyleProperty.Style) {
- excelBorderItem.Style = (ExcelBorderStyle)value;
- } else if (styleProperty == eStyleProperty.Color
- || styleProperty == eStyleProperty.Tint
- || styleProperty == eStyleProperty.IndexedColor) {
- if (excelBorderItem.Style == ExcelBorderStyle.None) {
- throw (new("Can't set bordercolor when style is not set."));
- }
- excelBorderItem.Color.Rgb = value.ToString();
- }
- }
-
- private int GetIdFill(eStyleClass styleClass, eStyleProperty styleProperty, object value) {
- ExcelFillXml fill = Fill.Copy();
-
- switch (styleProperty) {
- case eStyleProperty.PatternType:
- if (fill is ExcelGradientFillXml) {
- fill = new(NameSpaceManager);
- }
- fill.PatternType = (ExcelFillStyle)value;
- break;
- case eStyleProperty.Color:
- case eStyleProperty.Tint:
- case eStyleProperty.IndexedColor:
- case eStyleProperty.AutoColor:
- if (fill is ExcelGradientFillXml) {
- fill = new(NameSpaceManager);
- }
- if (fill.PatternType == ExcelFillStyle.None) {
- throw (new ArgumentException("Can't set color when patterntype is not set."));
- }
- ExcelColorXml destColor;
- if (styleClass == eStyleClass.FillPatternColor) {
- destColor = fill.PatternColor;
- } else {
- destColor = fill.BackgroundColor;
- }
-
- if (styleProperty == eStyleProperty.Color) {
- destColor.Rgb = value.ToString();
- } else if (styleProperty == eStyleProperty.Tint) {
- destColor.Tint = (decimal)value;
- } else if (styleProperty == eStyleProperty.IndexedColor) {
- destColor.Indexed = (int)value;
- } else {
- destColor.Auto = (bool)value;
- }
-
- break;
- default:
- throw (new ArgumentException("Invalid class/property for class Fill."));
- }
- int subId;
- string id = fill.Id;
- subId = _styles.Fills.FindIndexById(id);
- if (subId == int.MinValue) {
- return _styles.Fills.Add(id, fill);
- }
- return subId;
- }
-
- private int GetIdGradientFill(
- eStyleClass styleClass,
- eStyleProperty styleProperty,
- object value) {
- ExcelGradientFillXml fill;
- if (Fill is ExcelGradientFillXml) {
- fill = (ExcelGradientFillXml)Fill.Copy();
- } else {
- fill = new(Fill.NameSpaceManager);
- fill.GradientColor1.Rgb = "FFFFFFFF";
- fill.GradientColor2.Rgb = "FF4F81BD";
- fill.Type = ExcelFillGradientType.Linear;
- fill.Degree = 90;
- fill.Top = double.NaN;
- fill.Bottom = double.NaN;
- fill.Left = double.NaN;
- fill.Right = double.NaN;
- }
-
- switch (styleProperty) {
- case eStyleProperty.GradientType:
- fill.Type = (ExcelFillGradientType)value;
- break;
- case eStyleProperty.GradientDegree:
- fill.Degree = (double)value;
- break;
- case eStyleProperty.GradientTop:
- fill.Top = (double)value;
- break;
- case eStyleProperty.GradientBottom:
- fill.Bottom = (double)value;
- break;
- case eStyleProperty.GradientLeft:
- fill.Left = (double)value;
- break;
- case eStyleProperty.GradientRight:
- fill.Right = (double)value;
- break;
- case eStyleProperty.Color:
- case eStyleProperty.Tint:
- case eStyleProperty.IndexedColor:
- case eStyleProperty.AutoColor:
- ExcelColorXml destColor;
-
- if (styleClass == eStyleClass.FillGradientColor1) {
- destColor = fill.GradientColor1;
- } else {
- destColor = fill.GradientColor2;
- }
-
- if (styleProperty == eStyleProperty.Color) {
- destColor.Rgb = value.ToString();
- } else if (styleProperty == eStyleProperty.Tint) {
- destColor.Tint = (decimal)value;
- } else if (styleProperty == eStyleProperty.IndexedColor) {
- destColor.Indexed = (int)value;
- } else {
- destColor.Auto = (bool)value;
- }
- break;
- default:
- throw (new ArgumentException("Invalid class/property for class Fill."));
- }
- int subId;
- string id = fill.Id;
- subId = _styles.Fills.FindIndexById(id);
- if (subId == int.MinValue) {
- return _styles.Fills.Add(id, fill);
- }
- return subId;
- }
-
- private int GetIdNumberFormat(eStyleProperty styleProperty, object value) {
- if (styleProperty == eStyleProperty.Format) {
- ExcelNumberFormatXml item = null;
- if (!_styles.NumberFormats.FindById(value.ToString(), ref item)) {
- item = new(NameSpaceManager) {
- Format = value.ToString(),
- NumFmtId = _styles.NumberFormats.NextId++,
- };
- _styles.NumberFormats.Add(value.ToString(), item);
- }
- return item.NumFmtId;
- }
- throw (new("Invalid property for class Numberformat"));
- }
-
- private int GetIdFont(eStyleProperty styleProperty, object value) {
- ExcelFontXml fnt = Font.Copy();
-
- switch (styleProperty) {
- case eStyleProperty.Name:
- fnt.Name = value.ToString();
- break;
- case eStyleProperty.Size:
- fnt.Size = (float)value;
- break;
- case eStyleProperty.Family:
- fnt.Family = (int)value;
- break;
- case eStyleProperty.Bold:
- fnt.Bold = (bool)value;
- break;
- case eStyleProperty.Italic:
- fnt.Italic = (bool)value;
- break;
- case eStyleProperty.Strike:
- fnt.Strike = (bool)value;
- break;
- case eStyleProperty.UnderlineType:
- fnt.UnderLineType = (ExcelUnderLineType)value;
- break;
- case eStyleProperty.Color:
- fnt.Color.Rgb = value.ToString();
- break;
- case eStyleProperty.VerticalAlign:
- fnt.VerticalAlign =
- ((ExcelVerticalAlignmentFont)value) == ExcelVerticalAlignmentFont.None
- ? ""
- : value.ToString().ToLower(CultureInfo.InvariantCulture);
- break;
- default:
- throw (new("Invalid property for class Font"));
- }
- int subId;
- string id = fnt.Id;
- subId = _styles.Fonts.FindIndexById(id);
- if (subId == int.MinValue) {
- return _styles.Fonts.Add(id, fnt);
- }
- return subId;
- }
-
- internal override XmlNode CreateXmlNode(XmlNode topNode) {
- return CreateXmlNode(topNode, false);
- }
-
- internal XmlNode CreateXmlNode(XmlNode topNode, bool isCellStyleXsf) {
- TopNode = topNode;
- var doSetXfId =
- (!isCellStyleXsf
- && _xfID > int.MinValue
- && _styles.CellStyleXfs.Count > 0
- && _styles.CellStyleXfs[_xfID].newID > int.MinValue);
- if (_numFmtId > 0) {
- SetXmlNodeString("@numFmtId", _numFmtId.ToString());
- if (doSetXfId) {
- SetXmlNodeString("@applyNumberFormat", "1");
- }
- }
- if (_fontId >= 0) {
- SetXmlNodeString("@fontId", _styles.Fonts[_fontId].newID.ToString());
- if (doSetXfId) {
- SetXmlNodeString("@applyFont", "1");
- }
- }
- if (_fillId >= 0) {
- SetXmlNodeString("@fillId", _styles.Fills[_fillId].newID.ToString());
- if (doSetXfId) {
- SetXmlNodeString("@applyFill", "1");
- }
- }
- if (_borderId >= 0) {
- SetXmlNodeString("@borderId", _styles.Borders[_borderId].newID.ToString());
- if (doSetXfId) {
- SetXmlNodeString("@applyBorder", "1");
- }
- }
- if (_horizontalAlignment != ExcelHorizontalAlignment.General) {
- SetXmlNodeString(_horizontalAlignPath, SetAlignString(_horizontalAlignment));
- }
- if (doSetXfId) {
- SetXmlNodeString("@xfId", _styles.CellStyleXfs[_xfID].newID.ToString());
- }
- if (_verticalAlignment != ExcelVerticalAlignment.Bottom) {
- SetXmlNodeString(_verticalAlignPath, SetAlignString(_verticalAlignment));
- }
- if (_wrapText) {
- SetXmlNodeString(_wrapTextPath, "1");
- }
- if (_readingOrder != ExcelReadingOrder.ContextDependent) {
- SetXmlNodeString(_readingOrderPath, ((int)_readingOrder).ToString());
- }
- if (_shrinkToFit) {
- SetXmlNodeString(_shrinkToFitPath, "1");
- }
- if (_indent > 0) {
- SetXmlNodeString(_indentPath, _indent.ToString());
- }
- if (_textRotation > 0) {
- SetXmlNodeString(textRotationPath, _textRotation.ToString());
- }
- if (!_locked) {
- SetXmlNodeString(_lockedPath, "0");
- }
- if (_hidden) {
- SetXmlNodeString(_hiddenPath, "1");
- }
- return TopNode;
- }
-
- private string SetAlignString(Enum align) {
- string newName = Enum.GetName(align.GetType(), align);
- return newName.Substring(0, 1).ToLower(CultureInfo.InvariantCulture)
- + newName.Substring(1, newName.Length - 1);
- }
-}
diff --git a/EPPlus/Style/XmlAccess/StyleXmlHelper.cs b/EPPlus/Style/XmlAccess/StyleXmlHelper.cs
deleted file mode 100644
index f735ef3..0000000
--- a/EPPlus/Style/XmlAccess/StyleXmlHelper.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml.Style.XmlAccess;
-
-/// <summary>
-/// Xml helper class for cell style classes
-/// </summary>
-public abstract class StyleXmlHelper : XmlHelper {
- internal StyleXmlHelper(XmlNamespaceManager nameSpaceManager)
- : base(nameSpaceManager) {}
-
- internal StyleXmlHelper(XmlNamespaceManager nameSpaceManager, XmlNode topNode)
- : base(nameSpaceManager, topNode) {}
-
- internal abstract XmlNode CreateXmlNode(XmlNode top);
-
- internal abstract string Id { get; }
-
- internal long useCnt = 0;
- internal int newID = int.MinValue;
-
- protected bool GetBoolValue(XmlNode topNode, string path) {
- var node = topNode.SelectSingleNode(path, NameSpaceManager);
- if (node is XmlAttribute) {
- return node.Value != "0";
- }
- if (node != null
- && ((node.Attributes["val"] != null && node.Attributes["val"].Value != "0")
- || node.Attributes["val"] == null)) {
- return true;
- }
- return false;
- }
-}
diff --git a/EPPlus/Table/ExcelTable.cs b/EPPlus/Table/ExcelTable.cs
deleted file mode 100644
index 674bb73..0000000
--- a/EPPlus/Table/ExcelTable.cs
+++ /dev/null
@@ -1,350 +0,0 @@
-/*******************************************************************************
- * 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();
- }
-}
diff --git a/EPPlus/Table/ExcelTableCollection.cs b/EPPlus/Table/ExcelTableCollection.cs
deleted file mode 100644
index 5a7941c..0000000
--- a/EPPlus/Table/ExcelTableCollection.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-/*******************************************************************************
- * 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;
-using System.Collections.Generic;
-using System.Xml;
-
-namespace OfficeOpenXml.Table;
-
-/// <summary>
-/// A collection of table objects
-/// </summary>
-public class ExcelTableCollection : IEnumerable<ExcelTable> {
- private readonly List<ExcelTable> _tables = new();
- internal Dictionary<string, int> _tableNames = new(StringComparer.InvariantCultureIgnoreCase);
- private readonly ExcelWorksheet _ws;
-
- internal ExcelTableCollection(ExcelWorksheet ws) {
- var pck = ws._package.Package;
- _ws = ws;
- foreach (XmlElement node in ws.WorksheetXml.SelectNodes(
- "//d:tableParts/d:tablePart",
- ws.NameSpaceManager)) {
- var rel = ws.Part.GetRelationship(node.GetAttribute("id", ExcelPackage._schemaRelationships));
- var tbl = new ExcelTable(rel, ws);
- _tableNames.Add(tbl.Name, _tables.Count);
- _tables.Add(tbl);
- }
- }
-
- internal string GetNewTableName() {
- string name = "Table1";
- int i = 2;
- while (_ws.Workbook.ExistsTableName(name)) {
- name = string.Format("Table{0}", i++);
- }
- return name;
- }
-
- /// <summary>
- /// Number of items in the collection
- /// </summary>
- public int Count => _tables.Count;
-
- /// <summary>
- /// Get the table object from a range.
- /// </summary>
- /// <param name="range">The range</param>
- /// <returns>The table. Null if no range matches</returns>
- public ExcelTable GetFromRange(ExcelRangeBase range) {
- foreach (var tbl in range.Worksheet.Tables) {
- if (tbl.Address._address == range._address) {
- return tbl;
- }
- }
- return null;
- }
-
- /// <summary>
- /// The table Index. Base 0.
- /// </summary>
- /// <param name="index"></param>
- /// <returns></returns>
- public ExcelTable this[int index] {
- get {
- if (index < 0 || index >= _tables.Count) {
- throw (new ArgumentOutOfRangeException("Table index out of range"));
- }
- return _tables[index];
- }
- }
-
- /// <summary>
- /// Indexer
- /// </summary>
- /// <param name="name">The name of the table</param>
- /// <returns>The table. Null if the table name is not found in the collection</returns>
- public ExcelTable this[string name] {
- get {
- if (_tableNames.ContainsKey(name)) {
- return _tables[_tableNames[name]];
- }
- return null;
- }
- }
-
- public IEnumerator<ExcelTable> GetEnumerator() {
- return _tables.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- return _tables.GetEnumerator();
- }
-}
diff --git a/EPPlus/Table/ExcelTableColumn.cs b/EPPlus/Table/ExcelTableColumn.cs
deleted file mode 100644
index 6680424..0000000
--- a/EPPlus/Table/ExcelTableColumn.cs
+++ /dev/null
@@ -1,203 +0,0 @@
-/*******************************************************************************
- * 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.Globalization;
-using System.Xml;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.Table;
-
-/// <summary>
-/// Build-in table row functions
-/// </summary>
-public enum RowFunctions {
- Average,
- Count,
- CountNums,
- Custom,
- Max,
- Min,
- None,
- StdDev,
- Sum,
- Var,
-}
-
-/// <summary>
-/// A table column
-/// </summary>
-public class ExcelTableColumn : XmlHelper {
- internal ExcelTable _tbl;
-
- internal ExcelTableColumn(XmlNamespaceManager ns, XmlNode topNode, ExcelTable tbl, int pos)
- : base(ns, topNode) {
- _tbl = tbl;
- Position = pos;
- }
-
- /// <summary>
- /// The column id
- /// </summary>
- public int Id {
- get => GetXmlNodeInt("@id");
- set => SetXmlNodeString("@id", value.ToString());
- }
-
- /// <summary>
- /// The position of the column
- /// </summary>
- public int Position { get; private set; }
-
- /// <summary>
- /// The name of the column
- /// </summary>
- public string Name {
- get {
- var n = GetXmlNodeString("@name");
- if (string.IsNullOrEmpty(n)) {
- if (_tbl.ShowHeader) {
- n = ConvertUtil.ExcelDecodeString(
- _tbl.WorkSheet.GetValue<string>(
- _tbl.Address._fromRow,
- _tbl.Address._fromCol + Position));
- } else {
- n = "Column" + (Position + 1);
- }
- }
- return n;
- }
- set {
- var v = ConvertUtil.ExcelEncodeString(value);
- SetXmlNodeString("@name", v);
- if (_tbl.ShowHeader) {
- _tbl.WorkSheet.SetValue(_tbl.Address._fromRow, _tbl.Address._fromCol + Position, value);
- }
- _tbl.WorkSheet.SetTableTotalFunction(_tbl, this);
- }
- }
-
- /// <summary>
- /// A string text in the total row
- /// </summary>
- public string TotalsRowLabel {
- get => GetXmlNodeString("@totalsRowLabel");
- set => SetXmlNodeString("@totalsRowLabel", value);
- }
-
- /// <summary>
- /// Build-in total row functions.
- /// To set a custom Total row formula use the TotalsRowFormula property
- /// <seealso cref="TotalsRowFormula"/>
- /// </summary>
- public RowFunctions TotalsRowFunction {
- get {
- if (GetXmlNodeString("@totalsRowFunction") == "") {
- return RowFunctions.None;
- }
- return (RowFunctions)
- Enum.Parse(typeof(RowFunctions), GetXmlNodeString("@totalsRowFunction"), true);
- }
- set {
- if (value == RowFunctions.Custom) {
- throw (new("Use the TotalsRowFormula-property to set a custom table formula"));
- }
- string s = value.ToString();
- s = s.Substring(0, 1).ToLower(CultureInfo.InvariantCulture) + s.Substring(1, s.Length - 1);
- SetXmlNodeString("@totalsRowFunction", s);
- _tbl.WorkSheet.SetTableTotalFunction(_tbl, this);
- }
- }
-
- private const string _totalsrowformulaPath = "d:totalsRowFormula";
-
- /// <summary>
- /// Sets a custom Totals row Formula.
- /// Be carefull with this property since it is not validated.
- /// <example>
- /// tbl.Columns[9].TotalsRowFormula = string.Format("SUM([{0}])",tbl.Columns[9].Name);
- /// </example>
- /// </summary>
- public string TotalsRowFormula {
- get => GetXmlNodeString(_totalsrowformulaPath);
- set {
- if (value.StartsWith("=")) {
- value = value.Substring(1, value.Length - 1);
- }
- SetXmlNodeString("@totalsRowFunction", "custom");
- SetXmlNodeString(_totalsrowformulaPath, value);
- _tbl.WorkSheet.SetTableTotalFunction(_tbl, this);
- }
- }
-
- private const string _datacellstylePath = "@dataCellStyle";
-
- /// <summary>
- /// The named style for datacells in the column
- /// </summary>
- public string DataCellStyleName {
- get => GetXmlNodeString(_datacellstylePath);
- set {
- if (_tbl.WorkSheet.Workbook.Styles.NamedStyles.FindIndexById(value) < 0) {
- throw (new(string.Format("Named style {0} does not exist.", value)));
- }
- SetXmlNodeString(TopNode, _datacellstylePath, value, true);
-
- int fromRow = _tbl.Address._fromRow + (_tbl.ShowHeader ? 1 : 0),
- toRow = _tbl.Address._toRow - (_tbl.ShowTotal ? 1 : 0),
- col = _tbl.Address._fromCol + Position;
-
- if (fromRow <= toRow) {
- _tbl.WorkSheet.Cells[fromRow, col, toRow, col].StyleName = value;
- }
- }
- }
-
- private const string _calculatedcolumnformulaPath = "d:calculatedColumnFormula";
-
- /// <summary>
- /// Sets a calculated column Formula.
- /// Be carefull with this property since it is not validated.
- /// <example>
- /// tbl.Columns[9].CalculatedColumnFormula = string.Format("SUM(MyDataTable[[#This Row],[{0}]])",tbl.Columns[9].Name);
- /// </example>
- /// </summary>
- public string CalculatedColumnFormula {
- get => GetXmlNodeString(_calculatedcolumnformulaPath);
- set {
- if (value.StartsWith("=")) {
- value = value.Substring(1, value.Length - 1);
- }
- SetXmlNodeString(_calculatedcolumnformulaPath, value);
- }
- }
-}
diff --git a/EPPlus/Table/ExcelTableColumnCollection.cs b/EPPlus/Table/ExcelTableColumnCollection.cs
deleted file mode 100644
index e74adbe..0000000
--- a/EPPlus/Table/ExcelTableColumnCollection.cs
+++ /dev/null
@@ -1,116 +0,0 @@
-/*******************************************************************************
- * 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;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Xml;
-
-namespace OfficeOpenXml.Table;
-
-/// <summary>
-/// A collection of table columns
-/// </summary>
-public class ExcelTableColumnCollection : IEnumerable<ExcelTableColumn> {
- private readonly List<ExcelTableColumn> _cols = new();
- private readonly Dictionary<string, int> _colNames = new(
- StringComparer.InvariantCultureIgnoreCase);
-
- public ExcelTableColumnCollection(ExcelTable table) {
- Table = table;
- foreach (XmlNode node in table.TableXml.SelectNodes(
- "//d:table/d:tableColumns/d:tableColumn",
- table.NameSpaceManager)) {
- _cols.Add(new(table.NameSpaceManager, node, table, _cols.Count));
- _colNames.Add(_cols[_cols.Count - 1].Name, _cols.Count - 1);
- }
- }
-
- /// <summary>
- /// A reference to the table object
- /// </summary>
- public ExcelTable Table { get; private set; }
-
- /// <summary>
- /// Number of items in the collection
- /// </summary>
- public int Count => _cols.Count;
-
- /// <summary>
- /// The column Index. Base 0.
- /// </summary>
- /// <param name="index"></param>
- /// <returns></returns>
- public ExcelTableColumn this[int index] {
- get {
- if (index < 0 || index >= _cols.Count) {
- throw (new ArgumentOutOfRangeException("Column index out of range"));
- }
- return _cols[index];
- }
- }
-
- /// <summary>
- /// Indexer
- /// </summary>
- /// <param name="name">The name of the table</param>
- /// <returns>The table column. Null if the table name is not found in the collection</returns>
- public ExcelTableColumn this[string name] {
- get {
- if (_colNames.ContainsKey(name)) {
- return _cols[_colNames[name]];
- }
- return null;
- }
- }
-
- IEnumerator<ExcelTableColumn> IEnumerable<ExcelTableColumn>.GetEnumerator() {
- return _cols.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- return _cols.GetEnumerator();
- }
-
- internal string GetUniqueName(string name) {
- if (_colNames.ContainsKey(name)) {
- string newName;
- var i = 2;
- do {
- newName = name + (i++).ToString(CultureInfo.InvariantCulture);
- } while (_colNames.ContainsKey(newName));
- return newName;
- }
- return name;
- }
-}
diff --git a/EPPlus/Table/PivotTable/ExcelPivotCacheDefinition.cs b/EPPlus/Table/PivotTable/ExcelPivotCacheDefinition.cs
deleted file mode 100644
index 44543ee..0000000
--- a/EPPlus/Table/PivotTable/ExcelPivotCacheDefinition.cs
+++ /dev/null
@@ -1,235 +0,0 @@
-/*******************************************************************************
- * 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.Linq;
-using System.Xml;
-using OfficeOpenXml.Packaging;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.Table.PivotTable;
-
-public enum eSourceType {
- /// <summary>
- /// Indicates that the cache contains data that consolidates ranges.
- /// </summary>
- Consolidation,
-
- /// <summary>
- /// Indicates that the cache contains data from an external data source.
- /// </summary>
- External,
-
- /// <summary>
- /// Indicates that the cache contains a scenario summary report
- /// </summary>
- Scenario,
-
- /// <summary>
- /// Indicates that the cache contains worksheet data
- /// </summary>
- Worksheet,
-}
-
-/// <summary>
-/// Cache definition. This class defines the source data. Note that one cache definition can be shared between many pivot tables.
-/// </summary>
-public class ExcelPivotCacheDefinition : XmlHelper {
- internal ExcelPivotCacheDefinition(XmlNamespaceManager ns, ExcelPivotTable pivotTable)
- : base(ns, null) {
- foreach (var r in pivotTable.Part.GetRelationshipsByType(
- ExcelPackage._schemaRelationships + "/pivotCacheDefinition")) {
- Relationship = r;
- }
- CacheDefinitionUri = UriHelper.ResolvePartUri(Relationship.SourceUri, Relationship.TargetUri);
-
- var pck = pivotTable.WorkSheet._package.Package;
- Part = pck.GetPart(CacheDefinitionUri);
- LoadXmlSafe(CacheDefinitionXml, Part.GetStream());
-
- TopNode = CacheDefinitionXml.DocumentElement;
- PivotTable = pivotTable;
- if (CacheSource == eSourceType.Worksheet) {
- var worksheetName = GetXmlNodeString(_sourceWorksheetPath);
- if (pivotTable.WorkSheet.Workbook.Worksheets.Any(t => t.Name == worksheetName)) {
- _sourceRange = pivotTable
- .WorkSheet
- .Workbook
- .Worksheets[worksheetName].Cells[GetXmlNodeString(_sourceAddressPath)];
- }
- }
- }
-
- /// <summary>
- /// Reference to the internal package part
- /// </summary>
- internal ZipPackagePart Part { get; set; }
-
- /// <summary>
- /// Provides access to the XML data representing the cache definition in the package.
- /// </summary>
- public XmlDocument CacheDefinitionXml { get; private set; } = new();
-
- /// <summary>
- /// The package internal URI to the pivottable cache definition Xml Document.
- /// </summary>
- public Uri CacheDefinitionUri { get; internal set; }
-
- internal Uri CacheRecordUri { get; set; }
-
- internal ZipPackageRelationship Relationship { get; set; }
-
- internal ZipPackageRelationship RecordRelationship { get; set; }
-
- internal string RecordRelationshipID {
- get => GetXmlNodeString("@r:id");
- set => SetXmlNodeString("@r:id", value);
- }
-
- /// <summary>
- /// Referece to the PivoTable object
- /// </summary>
- public ExcelPivotTable PivotTable { get; private set; }
-
- private const string _sourceWorksheetPath = "d:cacheSource/d:worksheetSource/@sheet";
- private const string _sourceNamePath = "d:cacheSource/d:worksheetSource/@name";
- private const string _sourceAddressPath = "d:cacheSource/d:worksheetSource/@ref";
- internal ExcelRangeBase _sourceRange;
-
- /// <summary>
- /// The source data range when the pivottable has a worksheet datasource.
- /// The number of columns in the range must be intact if this property is changed.
- /// The range must be in the same workbook as the pivottable.
- /// </summary>
- public ExcelRangeBase SourceRange {
- get {
- if (_sourceRange == null) {
- if (CacheSource == eSourceType.Worksheet) {
- var ws = PivotTable.WorkSheet.Workbook.Worksheets[GetXmlNodeString(_sourceWorksheetPath)];
- if (ws
- == null) //Not worksheet, check name or table name
- {
- var name = GetXmlNodeString(_sourceNamePath);
- foreach (var n in PivotTable.WorkSheet.Workbook.Names) {
- if (name.Equals(n.Name, StringComparison.InvariantCultureIgnoreCase)) {
- _sourceRange = n;
- return _sourceRange;
- }
- }
- foreach (var w in PivotTable.WorkSheet.Workbook.Worksheets) {
- if (w.Tables._tableNames.ContainsKey(name)) {
- _sourceRange = w.Cells[w.Tables[name].Address.Address];
- break;
- }
- foreach (var n in w.Names) {
- if (name.Equals(n.Name, StringComparison.InvariantCultureIgnoreCase)) {
- _sourceRange = n;
- break;
- }
- }
- }
- } else {
- _sourceRange = ws.Cells[GetXmlNodeString(_sourceAddressPath)];
- }
- } else {
- throw (new ArgumentException("The cachesource is not a worksheet"));
- }
- }
- return _sourceRange;
- }
- set {
- if (PivotTable.WorkSheet.Workbook != value.Worksheet.Workbook) {
- throw (new ArgumentException("Range must be in the same package as the pivottable"));
- }
-
- var sr = SourceRange;
- if (value.End.Column - value.Start.Column != sr.End.Column - sr.Start.Column) {
- throw (new ArgumentException(
- "Can not change the number of columns(fields) in the SourceRange"));
- }
-
- SetXmlNodeString(_sourceWorksheetPath, value.Worksheet.Name);
- SetXmlNodeString(_sourceAddressPath, value.FirstAddress);
- _sourceRange = value;
- }
- }
-
- /// <summary>
- /// Type of source data
- /// </summary>
- public eSourceType CacheSource {
- get {
- var s = GetXmlNodeString("d:cacheSource/@type");
- if (s == "") {
- return eSourceType.Worksheet;
- }
- return (eSourceType)Enum.Parse(typeof(eSourceType), s, true);
- }
- }
-
- private string GetStartXml(ExcelRangeBase sourceAddress) {
- string xml =
- "<pivotCacheDefinition xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" r:id=\"\" refreshOnLoad=\"1\" refreshedBy=\"SomeUser\" refreshedDate=\"40504.582403125001\" createdVersion=\"1\" refreshedVersion=\"3\" recordCount=\"5\" upgradeOnRefresh=\"1\">";
-
- xml += "<cacheSource type=\"worksheet\">";
- xml += string.Format(
- "<worksheetSource ref=\"{0}\" sheet=\"{1}\" /> ",
- sourceAddress.Address,
- sourceAddress.WorkSheet);
- xml += "</cacheSource>";
- xml += string.Format(
- "<cacheFields count=\"{0}\">",
- sourceAddress._toCol - sourceAddress._fromCol + 1);
- var sourceWorksheet = PivotTable.WorkSheet.Workbook.Worksheets[sourceAddress.WorkSheet];
- for (int col = sourceAddress._fromCol; col <= sourceAddress._toCol; col++) {
- if (sourceWorksheet == null
- || sourceWorksheet._values.GetValue(sourceAddress._fromRow, col) == null
- || sourceWorksheet._values.GetValue(sourceAddress._fromRow, col).ToString().Trim()
- == "") {
- xml += string.Format(
- "<cacheField name=\"Column{0}\" numFmtId=\"0\">",
- col - sourceAddress._fromCol + 1);
- } else {
- xml += string.Format(
- "<cacheField name=\"{0}\" numFmtId=\"0\">",
- sourceWorksheet._values.GetValue(sourceAddress._fromRow, col));
- }
- //xml += "<sharedItems containsNonDate=\"0\" containsString=\"0\" containsBlank=\"1\" /> ";
- xml += "<sharedItems containsBlank=\"1\" /> ";
- xml += "</cacheField>";
- }
- xml += "</cacheFields>";
- xml += "</pivotCacheDefinition>";
-
- return xml;
- }
-}
diff --git a/EPPlus/Table/PivotTable/ExcelPivotTable.cs b/EPPlus/Table/PivotTable/ExcelPivotTable.cs
deleted file mode 100644
index 47031ca..0000000
--- a/EPPlus/Table/PivotTable/ExcelPivotTable.cs
+++ /dev/null
@@ -1,645 +0,0 @@
-/*******************************************************************************
- * 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.Immutable;
-using System.Text.RegularExpressions;
-using System.Xml;
-using OfficeOpenXml.Packaging;
-using OfficeOpenXml.Utils;
-
-namespace OfficeOpenXml.Table.PivotTable;
-
-/// <summary>
-/// An Excel Pivottable
-/// </summary>
-public class ExcelPivotTable : XmlHelper {
- protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
- "location",
- "pivotFields",
- "rowFields",
- "rowItems",
- "colFields",
- "colItems",
- "pageFields",
- "pageItems",
- "dataFields",
- "dataItems",
- "formats",
- "pivotTableStyleInfo",
- ];
-
- internal ExcelPivotTable(ZipPackageRelationship rel, ExcelWorksheet sheet)
- : base(sheet.NameSpaceManager) {
- WorkSheet = sheet;
- PivotTableUri = UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri);
- Relationship = rel;
- var package = sheet._package;
- PivotTableXml = package.GetXmlDocument(PivotTableUri);
- TopNode = PivotTableXml.DocumentElement;
- Address = new(GetXmlNodeString("d:location/@ref"));
-
- CacheDefinition = new(sheet.NameSpaceManager, this);
- LoadFields();
-
- //Add row fields.
- foreach (XmlElement rowElem in TopNode.SelectNodes("d:rowFields/d:field", NameSpaceManager)) {
- if (int.TryParse(rowElem.GetAttribute("x"), out var x) && x >= 0) {
- RowFields.AddInternal(Fields[x]);
- } else {
- rowElem.ParentNode.RemoveChild(rowElem);
- }
- }
-
- ////Add column fields.
- foreach (XmlElement colElem in TopNode.SelectNodes("d:colFields/d:field", NameSpaceManager)) {
- if (int.TryParse(colElem.GetAttribute("x"), out var x) && x >= 0) {
- ColumnFields.AddInternal(Fields[x]);
- } else {
- colElem.ParentNode.RemoveChild(colElem);
- }
- }
-
- //Add Page elements
- //int index = 0;
- foreach (XmlElement pageElem in TopNode.SelectNodes(
- "d:pageFields/d:pageField",
- NameSpaceManager)) {
- if (int.TryParse(pageElem.GetAttribute("fld"), out var fld) && fld >= 0) {
- var field = Fields[fld];
- field._pageFieldSettings = new(NameSpaceManager, pageElem, field, fld);
- PageFields.AddInternal(field);
- }
- }
-
- //Add data elements
- //index = 0;
- foreach (XmlElement dataElem in TopNode.SelectNodes(
- "d:dataFields/d:dataField",
- NameSpaceManager)) {
- if (int.TryParse(dataElem.GetAttribute("fld"), out var fld) && fld >= 0) {
- var field = Fields[fld];
- var dataField = new ExcelPivotTableDataField(NameSpaceManager, dataElem, field);
- DataFields.AddInternal(dataField);
- }
- }
- }
-
- private void LoadFields() {
- //Fields.Clear();
- //int ix=0;
- //foreach(XmlElement fieldNode in PivotXml.SelectNodes("//d:pivotFields/d:pivotField",NameSpaceManager))
- //{
- // Fields.AddInternal(new ExcelPivotTableField(NameSpaceManager, fieldNode, this, ix++));
- //}
-
- int index = 0;
- //Add fields.
- foreach (XmlElement fieldElem in TopNode.SelectNodes(
- "d:pivotFields/d:pivotField",
- NameSpaceManager)) {
- var fld = new ExcelPivotTableField(NameSpaceManager, fieldElem, this, index, index++);
- Fields.AddInternal(fld);
- }
-
- //Add fields.
- index = 0;
- foreach (XmlElement fieldElem in CacheDefinition.TopNode.SelectNodes(
- "d:cacheFields/d:cacheField",
- NameSpaceManager)) {
- var fld = Fields[index++];
- fld.SetCacheFieldNode(fieldElem);
- }
- }
-
- private XmlDocument GetStartXml(
- string name,
- int id,
- ExcelAddressBase address,
- ExcelAddressBase sourceAddress) {
- string xml = $"""
- <pivotTableDefinition xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" name="
- {name}" cacheId="{id
- }" dataOnRows="1" applyNumberFormats="0" applyBorderFormats="0" applyFontFormats="0" applyPatternFormats="0" applyAlignmentFormats="0" applyWidthHeightFormats="1" dataCaption="Data" createdVersion="4" showMemberPropertyTips="0" useAutoFormatting="1" itemPrintTitles="1" indent="0" compact="0" compactData="0" gridDropZones="1">
-
- """;
- xml +=
- $"""<location ref="{address.FirstAddress
- }" firstHeaderRow="1" firstDataRow="1" firstDataCol="1" />""";
- xml += $"""<pivotFields count="{sourceAddress._toCol - sourceAddress._fromCol + 1}">""";
- for (int col = sourceAddress._fromCol; col <= sourceAddress._toCol; col++) {
- xml += """<pivotField showAll="0" />""";
- }
- xml += "</pivotFields>";
- xml +=
- """<pivotTableStyleInfo name="PivotStyleMedium9" showRowHeaders="1" showColHeaders="1" showRowStripes="0" showColStripes="0" showLastColumn="1" />""";
- xml += "</pivotTableDefinition>";
- var result = new XmlDocument();
- result.LoadXml(xml);
- return result;
- }
-
- internal ZipPackagePart Part { get; }
-
- /// <summary>
- /// Provides access to the XML data representing the pivottable in the package.
- /// </summary>
- public XmlDocument PivotTableXml { get; private set; }
-
- /// <summary>
- /// The package internal URI to the pivottable Xml Document.
- /// </summary>
- public Uri PivotTableUri { get; internal set; }
-
- internal ZipPackageRelationship Relationship { get; set; }
-
- //const string ID_PATH = "@id";
- //internal int Id
- //{
- // get
- // {
- // return GetXmlNodeInt(ID_PATH);
- // }
- // set
- // {
- // SetXmlNodeString(ID_PATH, value.ToString());
- // }
- //}
- private const string _namePath = "@name";
- private const string _displayNamePath = "@displayName";
-
- /// <summary>
- /// Name of the pivottable object in Excel
- /// </summary>
- public string Name {
- get => GetXmlNodeString(_namePath);
- set {
- if (WorkSheet.Workbook.ExistsTableName(value)) {
- throw (new ArgumentException("PivotTable name is not unique"));
- }
- string prevName = Name;
- if (WorkSheet.Tables._tableNames.ContainsKey(prevName)) {
- int ix = WorkSheet.Tables._tableNames[prevName];
- WorkSheet.Tables._tableNames.Remove(prevName);
- WorkSheet.Tables._tableNames.Add(value, ix);
- }
- SetXmlNodeString(_namePath, value);
- SetXmlNodeString(_displayNamePath, CleanDisplayName(value));
- }
- }
-
- /// <summary>
- /// Reference to the pivot table cache definition object
- /// </summary>
- public ExcelPivotCacheDefinition CacheDefinition { get; }
-
- private string CleanDisplayName(string name) {
- return Regex.Replace(name, @"[^\w\.-_]", "_");
- }
-
- /// <summary>
- /// The worksheet where the pivottable is located
- /// </summary>
- public ExcelWorksheet WorkSheet { get; set; }
-
- /// <summary>
- /// The location of the pivot table
- /// </summary>
- public ExcelAddressBase Address { get; internal set; }
-
- /// <summary>
- /// If multiple datafields are displayed in the row area or the column area
- /// </summary>
- public bool DataOnRows {
- get => GetXmlNodeBool("@dataOnRows");
- set => SetXmlNodeBool("@dataOnRows", value);
- }
-
- /// <summary>
- /// if true apply legacy table autoformat number format properties.
- /// </summary>
- public bool ApplyNumberFormats {
- get => GetXmlNodeBool("@applyNumberFormats");
- set => SetXmlNodeBool("@applyNumberFormats", value);
- }
-
- /// <summary>
- /// If true apply legacy table autoformat border properties
- /// </summary>
- public bool ApplyBorderFormats {
- get => GetXmlNodeBool("@applyBorderFormats");
- set => SetXmlNodeBool("@applyBorderFormats", value);
- }
-
- /// <summary>
- /// If true apply legacy table autoformat font properties
- /// </summary>
- public bool ApplyFontFormats {
- get => GetXmlNodeBool("@applyFontFormats");
- set => SetXmlNodeBool("@applyFontFormats", value);
- }
-
- /// <summary>
- /// If true apply legacy table autoformat pattern properties
- /// </summary>
- public bool ApplyPatternFormats {
- get => GetXmlNodeBool("@applyPatternFormats");
- set => SetXmlNodeBool("@applyPatternFormats", value);
- }
-
- /// <summary>
- /// If true apply legacy table autoformat width/height properties.
- /// </summary>
- public bool ApplyWidthHeightFormats {
- get => GetXmlNodeBool("@applyWidthHeightFormats");
- set => SetXmlNodeBool("@applyWidthHeightFormats", value);
- }
-
- /// <summary>
- /// Show member property information
- /// </summary>
- public bool ShowMemberPropertyTips {
- get => GetXmlNodeBool("@showMemberPropertyTips");
- set => SetXmlNodeBool("@showMemberPropertyTips", value);
- }
-
- /// <summary>
- /// Show the drill indicators
- /// </summary>
- public bool ShowCalcMember {
- get => GetXmlNodeBool("@showCalcMbrs");
- set => SetXmlNodeBool("@showCalcMbrs", value);
- }
-
- /// <summary>
- /// If the user is prevented from drilling down on a PivotItem or aggregate value
- /// </summary>
- public bool EnableDrill {
- get => GetXmlNodeBool("@enableDrill", true);
- set => SetXmlNodeBool("@enableDrill", value);
- }
-
- /// <summary>
- /// Show the drill down buttons
- /// </summary>
- public bool ShowDrill {
- get => GetXmlNodeBool("@showDrill", true);
- set => SetXmlNodeBool("@showDrill", value);
- }
-
- /// <summary>
- /// If the tooltips should be displayed for PivotTable data cells.
- /// </summary>
- public bool ShowDataTips {
- get => GetXmlNodeBool("@showDataTips", true);
- set => SetXmlNodeBool("@showDataTips", value, true);
- }
-
- /// <summary>
- /// If the row and column titles from the PivotTable should be printed.
- /// </summary>
- public bool FieldPrintTitles {
- get => GetXmlNodeBool("@fieldPrintTitles");
- set => SetXmlNodeBool("@fieldPrintTitles", value);
- }
-
- /// <summary>
- /// If the row and column titles from the PivotTable should be printed.
- /// </summary>
- public bool ItemPrintTitles {
- get => GetXmlNodeBool("@itemPrintTitles");
- set => SetXmlNodeBool("@itemPrintTitles", value);
- }
-
- /// <summary>
- /// If the grand totals should be displayed for the PivotTable columns
- /// </summary>
- public bool ColumGrandTotals {
- get => GetXmlNodeBool("@colGrandTotals");
- set => SetXmlNodeBool("@colGrandTotals", value);
- }
-
- /// <summary>
- /// If the grand totals should be displayed for the PivotTable rows
- /// </summary>
- public bool RowGrandTotals {
- get => GetXmlNodeBool("@rowGrandTotals");
- set => SetXmlNodeBool("@rowGrandTotals", value);
- }
-
- /// <summary>
- /// If the drill indicators expand collapse buttons should be printed.
- /// </summary>
- public bool PrintDrill {
- get => GetXmlNodeBool("@printDrill");
- set => SetXmlNodeBool("@printDrill", value);
- }
-
- /// <summary>
- /// Indicates whether to show error messages in cells.
- /// </summary>
- public bool ShowError {
- get => GetXmlNodeBool("@showError");
- set => SetXmlNodeBool("@showError", value);
- }
-
- /// <summary>
- /// The string to be displayed in cells that contain errors.
- /// </summary>
- public string ErrorCaption {
- get => GetXmlNodeString("@errorCaption");
- set => SetXmlNodeString("@errorCaption", value);
- }
-
- /// <summary>
- /// Specifies the name of the value area field header in the PivotTable.
- /// This caption is shown when the PivotTable when two or more fields are in the values area.
- /// </summary>
- public string DataCaption {
- get => GetXmlNodeString("@dataCaption");
- set => SetXmlNodeString("@dataCaption", value);
- }
-
- /// <summary>
- /// Show field headers
- /// </summary>
- public bool ShowHeaders {
- get => GetXmlNodeBool("@showHeaders");
- set => SetXmlNodeBool("@showHeaders", value);
- }
-
- /// <summary>
- /// The number of page fields to display before starting another row or column
- /// </summary>
- public int PageWrap {
- get => GetXmlNodeInt("@pageWrap");
- set {
- if (value < 0) {
- throw new("Value can't be negative");
- }
- SetXmlNodeString("@pageWrap", value.ToString());
- }
- }
-
- /// <summary>
- /// A boolean that indicates whether legacy auto formatting has been applied to the PivotTable view
- /// </summary>
- public bool UseAutoFormatting {
- get => GetXmlNodeBool("@useAutoFormatting");
- set => SetXmlNodeBool("@useAutoFormatting", value);
- }
-
- /// <summary>
- /// A boolean that indicates whether the in-grid drop zones should be displayed at runtime, and whether classic layout is applied
- /// </summary>
- public bool GridDropZones {
- get => GetXmlNodeBool("@gridDropZones");
- set => SetXmlNodeBool("@gridDropZones", value);
- }
-
- /// <summary>
- /// Specifies the indentation increment for compact axis and can be used to set the Report Layout to Compact Form
- /// </summary>
- public int Indent {
- get => GetXmlNodeInt("@indent");
- set => SetXmlNodeString("@indent", value.ToString());
- }
-
- /// <summary>
- /// A boolean that indicates whether data fields in the PivotTable should be displayed in outline form
- /// </summary>
- public bool OutlineData {
- get => GetXmlNodeBool("@outlineData");
- set => SetXmlNodeBool("@outlineData", value);
- }
-
- /// <summary>
- /// a boolean that indicates whether new fields should have their outline flag set to true
- /// </summary>
- public bool Outline {
- get => GetXmlNodeBool("@outline");
- set => SetXmlNodeBool("@outline", value);
- }
-
- /// <summary>
- /// A boolean that indicates whether the fields of a PivotTable can have multiple filters set on them
- /// </summary>
- public bool MultipleFieldFilters {
- get => GetXmlNodeBool("@multipleFieldFilters");
- set => SetXmlNodeBool("@multipleFieldFilters", value);
- }
-
- /// <summary>
- /// A boolean that indicates whether new fields should have their compact flag set to true
- /// </summary>
- public bool Compact {
- get => GetXmlNodeBool("@compact");
- set => SetXmlNodeBool("@compact", value);
- }
-
- /// <summary>
- /// A boolean that indicates whether the field next to the data field in the PivotTable should be displayed in the same column of the spreadsheet
- /// </summary>
- public bool CompactData {
- get => GetXmlNodeBool("@compactData");
- set => SetXmlNodeBool("@compactData", value);
- }
-
- /// <summary>
- /// Specifies the string to be displayed for grand totals.
- /// </summary>
- public string GrandTotalCaption {
- get => GetXmlNodeString("@grandTotalCaption");
- set => SetXmlNodeString("@grandTotalCaption", value);
- }
-
- /// <summary>
- /// Specifies the string to be displayed in row header in compact mode.
- /// </summary>
- public string RowHeaderCaption {
- get => GetXmlNodeString("@rowHeaderCaption");
- set => SetXmlNodeString("@rowHeaderCaption", value);
- }
-
- /// <summary>
- /// Specifies the string to be displayed in cells with no value
- /// </summary>
- public string MissingCaption {
- get => GetXmlNodeString("@missingCaption");
- set => SetXmlNodeString("@missingCaption", value);
- }
-
- private const string _firstheaderrowPath = "d:location/@firstHeaderRow";
-
- /// <summary>
- /// Specifies the first row of the PivotTable header, relative to the top left cell in the ref value
- /// </summary>
- public int FirstHeaderRow {
- get => GetXmlNodeInt(_firstheaderrowPath);
- set => SetXmlNodeString(_firstheaderrowPath, value.ToString());
- }
-
- private const string _firstdatarowPath = "d:location/@firstDataRow";
-
- /// <summary>
- /// Specifies the first column of the PivotTable data, relative to the top left cell in the ref value
- /// </summary>
- public int FirstDataRow {
- get => GetXmlNodeInt(_firstdatarowPath);
- set => SetXmlNodeString(_firstdatarowPath, value.ToString());
- }
-
- private const string _firstdatacolPath = "d:location/@firstDataCol";
-
- /// <summary>
- /// Specifies the first column of the PivotTable data, relative to the top left cell in the ref value
- /// </summary>
- public int FirstDataCol {
- get => GetXmlNodeInt(_firstdatacolPath);
- set => SetXmlNodeString(_firstdatacolPath, value.ToString());
- }
-
- private ExcelPivotTableFieldCollection _fields;
-
- /// <summary>
- /// The fields in the table
- /// </summary>
- public ExcelPivotTableFieldCollection Fields {
- get {
- if (_fields == null) {
- _fields = new(this, "");
- }
- return _fields;
- }
- }
-
- private ExcelPivotTableRowColumnFieldCollection _rowFields;
-
- /// <summary>
- /// Row label fields
- /// </summary>
- public ExcelPivotTableRowColumnFieldCollection RowFields {
- get {
- if (_rowFields == null) {
- _rowFields = new(this, "rowFields");
- }
- return _rowFields;
- }
- }
-
- private ExcelPivotTableRowColumnFieldCollection _columnFields;
-
- /// <summary>
- /// Column label fields
- /// </summary>
- public ExcelPivotTableRowColumnFieldCollection ColumnFields {
- get {
- if (_columnFields == null) {
- _columnFields = new(this, "colFields");
- }
- return _columnFields;
- }
- }
-
- private ExcelPivotTableDataFieldCollection _dataFields;
-
- /// <summary>
- /// Value fields
- /// </summary>
- public ExcelPivotTableDataFieldCollection DataFields {
- get {
- if (_dataFields == null) {
- _dataFields = new(this);
- }
- return _dataFields;
- }
- }
-
- private ExcelPivotTableRowColumnFieldCollection _pageFields;
-
- /// <summary>
- /// Report filter fields
- /// </summary>
- public ExcelPivotTableRowColumnFieldCollection PageFields {
- get {
- if (_pageFields == null) {
- _pageFields = new(this, "pageFields");
- }
- return _pageFields;
- }
- }
-
- private const string _stylenamePath = "d:pivotTableStyleInfo/@name";
-
- /// <summary>
- /// Pivot style name. Used for custom styles
- /// </summary>
- public string StyleName {
- get => GetXmlNodeString(_stylenamePath);
- set {
- if (value.StartsWith("PivotStyle")) {
- try {
- _tableStyle = (TableStyles)
- Enum.Parse(typeof(TableStyles), value.Substring(10, value.Length - 10), true);
- } catch {
- _tableStyle = TableStyles.Custom;
- }
- } else if (value == "None") {
- _tableStyle = TableStyles.None;
- value = "";
- } else {
- _tableStyle = TableStyles.Custom;
- }
- SetXmlNodeString(_stylenamePath, value, true);
- }
- }
-
- private TableStyles _tableStyle = TableStyles.Medium6;
-
- /// <summary>
- /// The table style. If this property is cusom the style from the StyleName propery is used.
- /// </summary>
- public TableStyles TableStyle {
- get => _tableStyle;
- set {
- _tableStyle = value;
- if (value != TableStyles.Custom) {
- SetXmlNodeString(_stylenamePath, "PivotStyle" + value);
- }
- }
- }
-
- internal int CacheID {
- get => GetXmlNodeInt("@cacheId");
- set => SetXmlNodeString("@cacheId", value.ToString());
- }
-}
diff --git a/EPPlus/Table/PivotTable/ExcelPivotTableCollection.cs b/EPPlus/Table/PivotTable/ExcelPivotTableCollection.cs
deleted file mode 100644
index fe9cc63..0000000
--- a/EPPlus/Table/PivotTable/ExcelPivotTableCollection.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-/*******************************************************************************
- * 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;
-using System.Collections.Generic;
-
-namespace OfficeOpenXml.Table.PivotTable;
-
-/// <summary>
-/// A collection of pivottable objects
-/// </summary>
-public class ExcelPivotTableCollection : IEnumerable<ExcelPivotTable> {
- private readonly List<ExcelPivotTable> _pivotTables = new();
- internal readonly Dictionary<string, int> _pivotTableNames = new();
-
- internal ExcelPivotTableCollection(ExcelWorksheet ws) {
- foreach (var rel in ws.Part.GetRelationships()) {
- if (rel.RelationshipType == ExcelPackage._schemaRelationships + "/pivotTable") {
- var tbl = new ExcelPivotTable(rel, ws);
- _pivotTableNames.Add(tbl.Name, _pivotTables.Count);
- _pivotTables.Add(tbl);
- }
- }
- }
-
- public int Count => _pivotTables.Count;
-
- /// <summary>
- /// The pivottable Index. Base 0.
- /// </summary>
- /// <param name="index"></param>
- /// <returns></returns>
- public ExcelPivotTable this[int index] {
- get {
- if (index < 0 || index >= _pivotTables.Count) {
- throw (new ArgumentOutOfRangeException("PivotTable index out of range"));
- }
- return _pivotTables[index];
- }
- }
-
- /// <summary>
- /// Pivottabes accesed by name
- /// </summary>
- /// <param name="name">The name of the pivottable</param>
- /// <returns>The Pivotable. Null if the no match is found</returns>
- public ExcelPivotTable this[string name] {
- get {
- if (_pivotTableNames.ContainsKey(name)) {
- return _pivotTables[_pivotTableNames[name]];
- }
- return null;
- }
- }
-
- public IEnumerator<ExcelPivotTable> GetEnumerator() {
- return _pivotTables.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- return _pivotTables.GetEnumerator();
- }
-}
diff --git a/EPPlus/Table/PivotTable/ExcelPivotTableDataField.cs b/EPPlus/Table/PivotTable/ExcelPivotTableDataField.cs
deleted file mode 100644
index bfe8c52..0000000
--- a/EPPlus/Table/PivotTable/ExcelPivotTableDataField.cs
+++ /dev/null
@@ -1,190 +0,0 @@
-/*******************************************************************************
- * 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.Globalization;
-using System.Xml;
-using OfficeOpenXml.Style.XmlAccess;
-
-namespace OfficeOpenXml.Table.PivotTable;
-
-/// <summary>
-/// A pivo table data field
-/// </summary>
-public class ExcelPivotTableDataField : XmlHelper {
- internal ExcelPivotTableDataField(
- XmlNamespaceManager ns,
- XmlNode topNode,
- ExcelPivotTableField field)
- : base(ns, topNode) {
- if (topNode.Attributes.Count == 0) {
- Index = field.Index;
- BaseField = 0;
- BaseItem = 0;
- }
-
- Field = field;
- }
-
- /// <summary>
- /// The field
- /// </summary>
- public ExcelPivotTableField Field { get; private set; }
-
- /// <summary>
- /// The index of the datafield
- /// </summary>
- public int Index {
- get => GetXmlNodeInt("@fld");
- internal set => SetXmlNodeString("@fld", value.ToString());
- }
-
- /// <summary>
- /// The name of the datafield
- /// </summary>
- public string Name {
- get => GetXmlNodeString("@name");
- set {
- if (Field._table.DataFields.ExistsDfName(value, this)) {
- throw (new InvalidOperationException("Duplicate datafield name"));
- }
- SetXmlNodeString("@name", value);
- }
- }
-
- /// <summary>
- /// Field index. Reference to the field collection
- /// </summary>
- public int BaseField {
- get => GetXmlNodeInt("@baseField");
- set => SetXmlNodeString("@baseField", value.ToString());
- }
-
- /// <summary>
- /// Specifies the index to the base item when the ShowDataAs calculation is in use
- /// </summary>
- public int BaseItem {
- get => GetXmlNodeInt("@baseItem");
- set => SetXmlNodeString("@baseItem", value.ToString());
- }
-
- /// <summary>
- /// Number format id.
- /// </summary>
- internal int NumFmtId {
- get => GetXmlNodeInt("@numFmtId");
- set => SetXmlNodeString("@numFmtId", value.ToString());
- }
-
- /// <summary>
- /// Number format for the data column
- /// </summary>
- public string Format {
- get {
- foreach (var nf in Field._table.WorkSheet.Workbook.Styles.NumberFormats) {
- if (nf.NumFmtId == NumFmtId) {
- return nf.Format;
- }
- }
- return Field._table.WorkSheet.Workbook.Styles.NumberFormats[0].Format;
- }
- set {
- var styles = Field._table.WorkSheet.Workbook.Styles;
-
- ExcelNumberFormatXml nf = null;
- if (!styles.NumberFormats.FindById(value, ref nf)) {
- nf = new(NameSpaceManager) {
- Format = value,
- NumFmtId = styles.NumberFormats.NextId++,
- };
- styles.NumberFormats.Add(value, nf);
- }
- NumFmtId = nf.NumFmtId;
- }
- }
-
- /// <summary>
- /// Type of aggregate function
- /// </summary>
- public DataFieldFunctions Function {
- get {
- string s = GetXmlNodeString("@subtotal");
- if (s == "") {
- return DataFieldFunctions.None;
- }
- return (DataFieldFunctions)Enum.Parse(typeof(DataFieldFunctions), s, true);
- }
- set {
- string v;
- switch (value) {
- case DataFieldFunctions.None:
- DeleteNode("@subtotal");
- return;
- case DataFieldFunctions.CountNums:
- v = "CountNums";
- break;
- case DataFieldFunctions.StdDev:
- v = "stdDev";
- break;
- case DataFieldFunctions.StdDevP:
- v = "stdDevP";
- break;
- default:
- v = value.ToString().ToLower(CultureInfo.InvariantCulture);
- break;
- }
- SetXmlNodeString("@subtotal", v);
- }
- }
- /////Since we have no items, Excel will crash when we use showDataAs options that require baseItem's
- //public eShowDataAs ShowDataAs
- //{
- // get
- // {
- // string s = GetXmlNodeString("@showDataAs");
- // if (s == "")
- // {
- // return eShowDataAs.Normal;
- // }
- // else
- // {
- // return (eShowDataAs)Enum.Parse(typeof(eShowDataAs), s, true);
- // }
- // }
- // set
- // {
- // string v = value.ToString();
- // v = v.Substring(0, 1).ToLower() + v.Substring(1);
- // SetXmlNodeString("@showDataAs", v);
- // }
- //}
-}
diff --git a/EPPlus/Table/PivotTable/ExcelPivotTableField.cs b/EPPlus/Table/PivotTable/ExcelPivotTableField.cs
deleted file mode 100644
index 05570f2..0000000
--- a/EPPlus/Table/PivotTable/ExcelPivotTableField.cs
+++ /dev/null
@@ -1,566 +0,0 @@
-/*******************************************************************************
- * 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.Globalization;
-using System.Xml;
-
-namespace OfficeOpenXml.Table.PivotTable;
-
-/// <summary>
-/// Defines the axis for a PivotTable
-/// </summary>
-public enum ePivotFieldAxis {
- /// <summary>
- /// None
- /// </summary>
- None = -1,
-
- /// <summary>
- /// Column axis
- /// </summary>
- Column,
-
- /// <summary>
- /// Page axis (Include Count Filter)
- ///
- /// </summary>
- Page,
-
- /// <summary>
- /// Row axis
- /// </summary>
- Row,
-
- /// <summary>
- /// Values axis
- /// </summary>
- Values,
-}
-
-/// <summary>
-/// Build-in table row functions
-/// </summary>
-public enum DataFieldFunctions {
- Average,
- Count,
- CountNums,
- Max,
- Min,
- Product,
- None,
- StdDev,
- StdDevP,
- Sum,
- Var,
- VarP,
-}
-
-/// <summary>
-/// Defines the data formats for a field in the PivotTable
-/// </summary>
-public enum eShowDataAs {
- /// <summary>
- /// Indicates the field is shown as the "difference from" a value.
- /// </summary>
- Difference,
-
- /// <summary>
- /// Indicates the field is shown as the "index.
- /// </summary>
- Index,
-
- /// <summary>
- /// Indicates that the field is shown as its normal datatype.
- /// </summary>
- Normal,
-
- /// <summary>
- /// /Indicates the field is show as the "percentage of" a value
- /// </summary>
- Percent,
-
- /// <summary>
- /// Indicates the field is shown as the "percentage difference from" a value.
- /// </summary>
- PercentDiff,
-
- /// <summary>
- /// Indicates the field is shown as the percentage of column.
- /// </summary>
- PercentOfCol,
-
- /// <summary>
- /// Indicates the field is shown as the percentage of row
- /// </summary>
- PercentOfRow,
-
- /// <summary>
- /// Indicates the field is shown as percentage of total.
- /// </summary>
- PercentOfTotal,
-
- /// <summary>
- /// Indicates the field is shown as running total in the table.
- /// </summary>
- RunTotal,
-}
-
-/// <summary>
-/// Built-in subtotal functions
-/// </summary>
-[Flags]
-public enum eSubTotalFunctions {
- None = 1,
- Count = 2,
- CountA = 4,
- Avg = 8,
- Default = 16,
- Min = 32,
- Max = 64,
- Product = 128,
- StdDev = 256,
- StdDevP = 512,
- Sum = 1024,
- Var = 2048,
- VarP = 4096,
-}
-
-/// <summary>
-/// Data grouping
-/// </summary>
-[Flags]
-public enum eDateGroupBy {
- Years = 1,
- Quarters = 2,
- Months = 4,
- Days = 8,
- Hours = 16,
- Minutes = 32,
- Seconds = 64,
-}
-
-/// <summary>
-/// Sorting
-/// </summary>
-public enum eSortType {
- None,
- Ascending,
- Descending,
-}
-
-/// <summary>
-/// A pivot table field.
-/// </summary>
-public class ExcelPivotTableField : XmlHelper {
- internal ExcelPivotTable _table;
-
- internal ExcelPivotTableField(
- XmlNamespaceManager ns,
- XmlNode topNode,
- ExcelPivotTable table,
- int index,
- int baseIndex)
- : base(ns, topNode) {
- Index = index;
- BaseIndex = baseIndex;
- _table = table;
- }
-
- public int Index { get; set; }
-
- internal int BaseIndex { get; set; }
-
- /// <summary>
- /// Name of the field
- /// </summary>
- public string Name {
- get {
- string v = GetXmlNodeString("@name");
- if (v == "") {
- return _cacheFieldHelper.GetXmlNodeString("@name");
- }
- return v;
- }
- set => SetXmlNodeString("@name", value);
- }
-
- /// <summary>
- /// Compact mode
- /// </summary>
- public bool Compact {
- get => GetXmlNodeBool("@compact");
- set => SetXmlNodeBool("@compact", value);
- }
-
- /// <summary>
- /// A boolean that indicates whether the items in this field should be shown in Outline form
- /// </summary>
- public bool Outline {
- get => GetXmlNodeBool("@outline");
- set => SetXmlNodeBool("@outline", value);
- }
-
- /// <summary>
- /// The custom text that is displayed for the subtotals label
- /// </summary>
- public bool SubtotalTop {
- get => GetXmlNodeBool("@subtotalTop");
- set => SetXmlNodeBool("@subtotalTop", value);
- }
-
- /// <summary>
- /// A boolean that indicates whether to show all items for this field
- /// </summary>
- public bool ShowAll {
- get => GetXmlNodeBool("@showAll");
- set => SetXmlNodeBool("@showAll", value);
- }
-
- /// <summary>
- /// The type of sort that is applied to this field
- /// </summary>
- public eSortType Sort {
- get {
- string v = GetXmlNodeString("@sortType");
- return v == "" ? eSortType.None : (eSortType)Enum.Parse(typeof(eSortType), v, true);
- }
- set {
- if (value == eSortType.None) {
- DeleteNode("@sortType");
- } else {
- SetXmlNodeString("@sortType", value.ToString().ToLower(CultureInfo.InvariantCulture));
- }
- }
- }
-
- /// <summary>
- /// A boolean that indicates whether manual filter is in inclusive mode
- /// </summary>
- public bool IncludeNewItemsInFilter {
- get => GetXmlNodeBool("@includeNewItemsInFilter");
- set => SetXmlNodeBool("@includeNewItemsInFilter", value);
- }
-
- /// <summary>
- /// Enumeration of the different subtotal operations that can be applied to page, row or column fields
- /// </summary>
- public eSubTotalFunctions SubTotalFunctions {
- get {
- eSubTotalFunctions ret = 0;
- XmlNodeList nl = TopNode.SelectNodes("d:items/d:item/@t", NameSpaceManager);
- if (nl.Count == 0) {
- return eSubTotalFunctions.None;
- }
- foreach (XmlAttribute item in nl) {
- try {
- ret |= (eSubTotalFunctions)Enum.Parse(typeof(eSubTotalFunctions), item.Value, true);
- } catch (ArgumentException ex) {
- throw new ArgumentException(
- "Unable to parse value of "
- + item.Value
- + " to a valid pivot table subtotal function",
- ex);
- }
- }
- return ret;
- }
- set {
- if ((value & eSubTotalFunctions.None) == eSubTotalFunctions.None
- && (value != eSubTotalFunctions.None)) {
- throw (new ArgumentException("Value None can not be combined with other values."));
- }
- if ((value & eSubTotalFunctions.Default) == eSubTotalFunctions.Default
- && (value != eSubTotalFunctions.Default)) {
- throw (new ArgumentException("Value Default can not be combined with other values."));
- }
-
- // remove old attribute
- XmlNodeList nl = TopNode.SelectNodes("d:items/d:item/@t", NameSpaceManager);
- if (nl.Count > 0) {
- foreach (XmlAttribute item in nl) {
- DeleteNode("@" + item.Value + "Subtotal");
- item.OwnerElement.ParentNode.RemoveChild(item.OwnerElement);
- }
- }
-
- if (value == eSubTotalFunctions.None) {
- // for no subtotals, set defaultSubtotal to off
- SetXmlNodeBool("@defaultSubtotal", false);
- TopNode.InnerXml = "";
- } else {
- string innerXml = "";
- int count = 0;
- foreach (eSubTotalFunctions e in Enum.GetValues(typeof(eSubTotalFunctions))) {
- if ((value & e) == e) {
- var newTotalType = e.ToString();
- var totalType =
- char.ToLower(newTotalType[0], CultureInfo.InvariantCulture)
- + newTotalType.Substring(1);
- // add new attribute
- SetXmlNodeBool("@" + totalType + "Subtotal", true);
- innerXml += "<item t=\"" + totalType + "\" />";
- count++;
- }
- }
- TopNode.InnerXml = string.Format("<items count=\"{0}\">{1}</items>", count, innerXml);
- }
- }
- }
-
- /// <summary>
- /// Type of axis
- /// </summary>
- public ePivotFieldAxis Axis {
- get {
- switch (GetXmlNodeString("@axis")) {
- case "axisRow":
- return ePivotFieldAxis.Row;
- case "axisCol":
- return ePivotFieldAxis.Column;
- case "axisPage":
- return ePivotFieldAxis.Page;
- case "axisValues":
- return ePivotFieldAxis.Values;
- default:
- return ePivotFieldAxis.None;
- }
- }
- internal set {
- switch (value) {
- case ePivotFieldAxis.Row:
- SetXmlNodeString("@axis", "axisRow");
- break;
- case ePivotFieldAxis.Column:
- SetXmlNodeString("@axis", "axisCol");
- break;
- case ePivotFieldAxis.Values:
- SetXmlNodeString("@axis", "axisValues");
- break;
- case ePivotFieldAxis.Page:
- SetXmlNodeString("@axis", "axisPage");
- break;
- default:
- DeleteNode("@axis");
- break;
- }
- }
- }
-
- /// <summary>
- /// If the field is a row field
- /// </summary>
- public bool IsRowField {
- get =>
- (TopNode.SelectSingleNode(
- string.Format("../../d:rowFields/d:field[@x={0}]", Index),
- NameSpaceManager) != null);
- internal set {
- if (value) {
- var rowsNode = TopNode.SelectSingleNode("../../d:rowFields", NameSpaceManager);
- if (rowsNode == null) {
- _table.CreateNode("d:rowFields");
- }
- rowsNode = TopNode.SelectSingleNode("../../d:rowFields", NameSpaceManager);
-
- AppendField(rowsNode, Index, "field", "x");
- if (BaseIndex == Index) {
- TopNode.InnerXml = "<items count=\"1\"><item t=\"default\" /></items>";
- } else {
- TopNode.InnerXml = "<items count=\"0\"></items>";
- }
- } else {
- XmlElement node =
- TopNode.SelectSingleNode(
- string.Format("../../d:rowFields/d:field[@x={0}]", Index),
- NameSpaceManager) as XmlElement;
- if (node != null) {
- node.ParentNode.RemoveChild(node);
- }
- }
- }
- }
-
- /// <summary>
- /// If the field is a column field
- /// </summary>
- public bool IsColumnField {
- get =>
- (TopNode.SelectSingleNode(
- string.Format("../../d:colFields/d:field[@x={0}]", Index),
- NameSpaceManager) != null);
- internal set {
- if (value) {
- var columnsNode = TopNode.SelectSingleNode("../../d:colFields", NameSpaceManager);
- if (columnsNode == null) {
- _table.CreateNode("d:colFields");
- }
- columnsNode = TopNode.SelectSingleNode("../../d:colFields", NameSpaceManager);
-
- AppendField(columnsNode, Index, "field", "x");
- if (BaseIndex == Index) {
- TopNode.InnerXml = "<items count=\"1\"><item t=\"default\" /></items>";
- } else {
- TopNode.InnerXml = "<items count=\"0\"></items>";
- }
- } else {
- XmlElement node =
- TopNode.SelectSingleNode(
- string.Format("../../d:colFields/d:field[@x={0}]", Index),
- NameSpaceManager) as XmlElement;
- if (node != null) {
- node.ParentNode.RemoveChild(node);
- }
- }
- }
- }
-
- /// <summary>
- /// If the field is a datafield
- /// </summary>
- public bool IsDataField => GetXmlNodeBool("@dataField", false);
-
- /// <summary>
- /// If the field is a page field.
- /// </summary>
- public bool IsPageField {
- get => (Axis == ePivotFieldAxis.Page);
- internal set {
- if (value) {
- var dataFieldsNode = TopNode.SelectSingleNode("../../d:pageFields", NameSpaceManager);
- if (dataFieldsNode == null) {
- _table.CreateNode("d:pageFields");
- dataFieldsNode = TopNode.SelectSingleNode("../../d:pageFields", NameSpaceManager);
- }
-
- TopNode.InnerXml = "<items count=\"1\"><item t=\"default\" /></items>";
-
- XmlElement node = AppendField(dataFieldsNode, Index, "pageField", "fld");
- _pageFieldSettings = new(NameSpaceManager, node, this, Index);
- } else {
- _pageFieldSettings = null;
- XmlElement node =
- TopNode.SelectSingleNode(
- string.Format("../../d:pageFields/d:pageField[@fld={0}]", Index),
- NameSpaceManager) as XmlElement;
- if (node != null) {
- node.ParentNode.RemoveChild(node);
- }
- }
- }
- }
-
- //public ExcelPivotGrouping DateGrouping
- //{
-
- //}
- internal ExcelPivotTablePageFieldSettings _pageFieldSettings;
-
- public ExcelPivotTablePageFieldSettings PageFieldSettings => _pageFieldSettings;
-
- internal eDateGroupBy DateGrouping { get; set; }
-
- private ExcelPivotTableFieldGroup _grouping;
-
- /// <summary>
- /// Grouping settings.
- /// Null if the field has no grouping otherwise ExcelPivotTableFieldNumericGroup or ExcelPivotTableFieldNumericGroup.
- /// </summary>
- public ExcelPivotTableFieldGroup Grouping => _grouping;
-
- internal XmlElement AppendField(
- XmlNode rowsNode,
- int index,
- string fieldNodeText,
- string indexAttrText) {
- XmlElement prevField = null,
- newElement;
- foreach (XmlElement field in rowsNode.ChildNodes) {
- string x = field.GetAttribute(indexAttrText);
- if (int.TryParse(x, out var fieldIndex)) {
- if (fieldIndex
- == index) //Row already exists
- {
- return field;
- }
- //else if (fieldIndex > index)
- //{
- // newElement = rowsNode.OwnerDocument.CreateElement(fieldNodeText, ExcelPackage.schemaMain);
- // newElement.SetAttribute(indexAttrText, index.ToString());
- // rowsNode.InsertAfter(newElement, field);
- //}
- }
- prevField = field;
- }
- newElement = rowsNode.OwnerDocument.CreateElement(fieldNodeText, ExcelPackage._schemaMain);
- newElement.SetAttribute(indexAttrText, index.ToString());
- rowsNode.InsertAfter(newElement, prevField);
-
- return newElement;
- }
-
- internal XmlHelperInstance _cacheFieldHelper;
-
- internal void SetCacheFieldNode(XmlNode cacheField) {
- _cacheFieldHelper = new(NameSpaceManager, cacheField);
- var groupNode = cacheField.SelectSingleNode("d:fieldGroup", NameSpaceManager);
- if (groupNode != null) {
- var groupBy = groupNode.SelectSingleNode("d:rangePr/@groupBy", NameSpaceManager);
- if (groupBy == null) {
- _grouping = new ExcelPivotTableFieldNumericGroup(NameSpaceManager, cacheField);
- } else {
- DateGrouping = (eDateGroupBy)Enum.Parse(typeof(eDateGroupBy), groupBy.Value, true);
- _grouping = new ExcelPivotTableFieldDateGroup(NameSpaceManager, groupNode);
- }
- }
- }
-
- internal ExcelPivotTableFieldCollectionBase<ExcelPivotTableFieldItem> _items;
-
- /// <summary>
- /// Pivottable field Items. Used for grouping.
- /// </summary>
- public ExcelPivotTableFieldCollectionBase<ExcelPivotTableFieldItem> Items {
- get {
- if (_items == null) {
- _items = new(_table);
- foreach (XmlNode node in TopNode.SelectNodes("d:items//d:item", NameSpaceManager)) {
- var item = new ExcelPivotTableFieldItem(NameSpaceManager, node, this);
- if (item.T == "") {
- _items.AddInternal(item);
- }
- }
- }
- return _items;
- }
- }
-}
diff --git a/EPPlus/Table/PivotTable/ExcelPivotTableFieldCollection.cs b/EPPlus/Table/PivotTable/ExcelPivotTableFieldCollection.cs
deleted file mode 100644
index 5f7053d..0000000
--- a/EPPlus/Table/PivotTable/ExcelPivotTableFieldCollection.cs
+++ /dev/null
@@ -1,302 +0,0 @@
-/*******************************************************************************
- * 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;
-using System.Collections.Generic;
-using System.Xml;
-
-namespace OfficeOpenXml.Table.PivotTable;
-
-/// <summary>
-/// Base collection class for pivottable fields
-/// </summary>
-/// <typeparam name="T"></typeparam>
-public class ExcelPivotTableFieldCollectionBase<T> : IEnumerable<T> {
- protected ExcelPivotTable _table;
- internal List<T> _list = new();
-
- internal ExcelPivotTableFieldCollectionBase(ExcelPivotTable table) {
- _table = table;
- }
-
- public IEnumerator<T> GetEnumerator() {
- return _list.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator() {
- return _list.GetEnumerator();
- }
-
- public int Count => _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<ExcelPivotTableField> {
- internal ExcelPivotTableFieldCollection(ExcelPivotTable table, string topNode)
- : base(table) {}
-
- /// <summary>
- /// Indexer by name
- /// </summary>
- /// <param name="name"></param>
- /// <returns></returns>
- public ExcelPivotTableField this[string name] {
- get {
- foreach (var field in _list) {
- if (field.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)) {
- return field;
- }
- }
- return null;
- }
- }
-
- /// <summary>
- /// Returns the date group field.
- /// </summary>
- /// <param name="groupBy">The type of grouping</param>
- /// <returns>The matching field. If none is found null is returned</returns>
- public ExcelPivotTableField GetDateGroupField(eDateGroupBy groupBy) {
- foreach (var fld in _list) {
- if (fld.Grouping is ExcelPivotTableFieldDateGroup group && (group.GroupBy) == groupBy) {
- return fld;
- }
- }
- return null;
- }
-
- /// <summary>
- /// Returns the numeric group field.
- /// </summary>
- /// <returns>The matching field. If none is found null is returned</returns>
- public ExcelPivotTableField GetNumericGroupField() {
- foreach (var fld in _list) {
- if (fld.Grouping is ExcelPivotTableFieldNumericGroup) {
- return fld;
- }
- }
- return null;
- }
-}
-
-/// <summary>
-/// Collection class for Row and column fields in a Pivottable
-/// </summary>
-public class ExcelPivotTableRowColumnFieldCollection
- : ExcelPivotTableFieldCollectionBase<ExcelPivotTableField> {
- internal string _topNode;
-
- internal ExcelPivotTableRowColumnFieldCollection(ExcelPivotTable table, string topNode)
- : base(table) {
- _topNode = topNode;
- }
-
- /// <summary>
- /// Add a new row/column field
- /// </summary>
- /// <param name="field">The field</param>
- /// <returns>The new field</returns>
- public ExcelPivotTableField Add(ExcelPivotTableField field) {
- SetFlag(field, true);
- _list.Add(field);
- return field;
- }
-
- /// <summary>
- /// Insert a new row/column field
- /// </summary>
- /// <param name="field">The field</param>
- /// <param name="index">The position to insert the field</param>
- /// <returns>The new field</returns>
- 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(
- "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(
- "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("Field is a column or row field. Can't add it to the PageFields collection"));
- }
- if (_table.Address._fromRow < 3) {
- throw (new(
- 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;
- }
- }
-
- /// <summary>
- /// Remove a field
- /// </summary>
- /// <param name="field"></param>
- public void Remove(ExcelPivotTableField field) {
- if (!_list.Contains(field)) {
- throw new ArgumentException("Field not in collection");
- }
- SetFlag(field, false);
- _list.Remove(field);
- }
-
- /// <summary>
- /// Remove a field at a specific position
- /// </summary>
- /// <param name="index"></param>
- public void RemoveAt(int index) {
- if (index > -1 && index < _list.Count) {
- throw (new IndexOutOfRangeException());
- }
- SetFlag(_list[index], false);
- _list.RemoveAt(index);
- }
-}
-
-/// <summary>
-/// Collection class for data fields in a Pivottable
-/// </summary>
-public class ExcelPivotTableDataFieldCollection
- : ExcelPivotTableFieldCollectionBase<ExcelPivotTableDataField> {
- internal ExcelPivotTableDataFieldCollection(ExcelPivotTable table)
- : base(table) {}
-
- /// <summary>
- /// Add a new datafield
- /// </summary>
- /// <param name="field">The field</param>
- /// <returns>The new datafield</returns>
- 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++;
- } 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;
- }
-
- /// <summary>
- /// Remove a datafield
- /// </summary>
- /// <param name="dataField"></param>
- 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);
- }
-}
diff --git a/EPPlus/Table/PivotTable/ExcelPivotTableFieldGroup.cs b/EPPlus/Table/PivotTable/ExcelPivotTableFieldGroup.cs
deleted file mode 100644
index 99fbd3c..0000000
--- a/EPPlus/Table/PivotTable/ExcelPivotTableFieldGroup.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-/*******************************************************************************
- * 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.Globalization;
-using System.Xml;
-
-namespace OfficeOpenXml.Table.PivotTable;
-
-/// <summary>
-/// Base class for pivot table field groups
-/// </summary>
-public class ExcelPivotTableFieldGroup : XmlHelper {
- internal ExcelPivotTableFieldGroup(XmlNamespaceManager ns, XmlNode topNode)
- : base(ns, topNode) {}
-}
-
-/// <summary>
-/// A date group
-/// </summary>
-public class ExcelPivotTableFieldDateGroup : ExcelPivotTableFieldGroup {
- internal ExcelPivotTableFieldDateGroup(XmlNamespaceManager ns, XmlNode topNode)
- : base(ns, topNode) {}
-
- private const string _groupByPath = "d:fieldGroup/d:rangePr/@groupBy";
-
- /// <summary>
- /// How to group the date field
- /// </summary>
- public eDateGroupBy GroupBy {
- get {
- string v = GetXmlNodeString(_groupByPath);
- if (v != "") {
- return (eDateGroupBy)Enum.Parse(typeof(eDateGroupBy), v, true);
- }
- throw (new("Invalid date Groupby"));
- }
- private set =>
- SetXmlNodeString(_groupByPath, value.ToString().ToLower(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// Auto detect start date
- /// </summary>
- public bool AutoStart => GetXmlNodeBool("@autoStart", false);
-
- /// <summary>
- /// Auto detect end date
- /// </summary>
- public bool AutoEnd => GetXmlNodeBool("@autoStart", false);
-}
-
-/// <summary>
-/// A pivot table field numeric grouping
-/// </summary>
-public class ExcelPivotTableFieldNumericGroup : ExcelPivotTableFieldGroup {
- internal ExcelPivotTableFieldNumericGroup(XmlNamespaceManager ns, XmlNode topNode)
- : base(ns, topNode) {}
-
- private const string _startPath = "d:fieldGroup/d:rangePr/@startNum";
-
- /// <summary>
- /// Start value
- /// </summary>
- public double Start => (double)GetXmlNodeDoubleNull(_startPath);
-
- private const string _endPath = "d:fieldGroup/d:rangePr/@endNum";
-
- /// <summary>
- /// End value
- /// </summary>
- public double End => (double)GetXmlNodeDoubleNull(_endPath);
-
- private const string _groupIntervalPath = "d:fieldGroup/d:rangePr/@groupInterval";
-
- /// <summary>
- /// Interval
- /// </summary>
- public double Interval => (double)GetXmlNodeDoubleNull(_groupIntervalPath);
-}
diff --git a/EPPlus/Table/PivotTable/ExcelPivotTableFieldItem.cs b/EPPlus/Table/PivotTable/ExcelPivotTableFieldItem.cs
deleted file mode 100644
index b300b73..0000000
--- a/EPPlus/Table/PivotTable/ExcelPivotTableFieldItem.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-/*******************************************************************************
- * 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.Xml;
-
-namespace OfficeOpenXml.Table.PivotTable;
-
-/// <summary>
-/// A field Item. Used for grouping
-/// </summary>
-public class ExcelPivotTableFieldItem : XmlHelper {
- private readonly ExcelPivotTableField _field;
-
- internal ExcelPivotTableFieldItem(
- XmlNamespaceManager ns,
- XmlNode topNode,
- ExcelPivotTableField field)
- : base(ns, topNode) {
- _field = field;
- }
-
- /// <summary>
- /// The text. Unique values only
- /// </summary>
- public string Text {
- get => GetXmlNodeString("@n");
- set {
- if (string.IsNullOrEmpty(value)) {
- DeleteNode("@n");
- return;
- }
- foreach (var item in _field.Items) {
- if (item.Text == value) {
- throw (new ArgumentException("Duplicate Text"));
- }
- }
- SetXmlNodeString("@n", value);
- }
- }
-
- internal int X => GetXmlNodeInt("@x");
-
- internal string T => GetXmlNodeString("@t");
-}
diff --git a/EPPlus/Table/PivotTable/ExcelPivotTablePageFieldSettings.cs b/EPPlus/Table/PivotTable/ExcelPivotTablePageFieldSettings.cs
deleted file mode 100644
index fe6f762..0000000
--- a/EPPlus/Table/PivotTable/ExcelPivotTablePageFieldSettings.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-/*******************************************************************************
- * 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.Xml;
-
-namespace OfficeOpenXml.Table.PivotTable;
-
-/// <summary>
-/// A page / report filter field
-/// </summary>
-public class ExcelPivotTablePageFieldSettings : XmlHelper {
- private ExcelPivotTableField _field;
-
- internal ExcelPivotTablePageFieldSettings(
- XmlNamespaceManager ns,
- XmlNode topNode,
- ExcelPivotTableField field,
- int index)
- : base(ns, topNode) {
- if (GetXmlNodeString("@hier") == "") {
- Hier = -1;
- }
- _field = field;
- }
-
- internal int Index {
- get => GetXmlNodeInt("@fld");
- set => SetXmlNodeString("@fld", value.ToString());
- }
-
- /// <summary>
- /// The Name of the field
- /// </summary>
- public string Name {
- get => GetXmlNodeString("@name");
- set => SetXmlNodeString("@name", value);
- }
-
- /***** Dont work. Need items to be populated. ****/
- ///// <summary>
- ///// The selected item
- ///// </summary>
- //public int SelectedItem
- //{
- // get
- // {
- // return GetXmlNodeInt("@item");
- // }
- // set
- // {
- // if (value < 0) throw new InvalidOperationException("Can't be negative");
- // SetXmlNodeString("@item", value.ToString());
- // }
- //}
- internal int NumFmtId {
- get => GetXmlNodeInt("@numFmtId");
- set => SetXmlNodeString("@numFmtId", value.ToString());
- }
-
- internal int Hier {
- get => GetXmlNodeInt("@hier");
- set => SetXmlNodeString("@hier", value.ToString());
- }
-}
diff --git a/EPPlus/Utils/AddressUtility.cs b/EPPlus/Utils/AddressUtility.cs
deleted file mode 100644
index 05fadd1..0000000
--- a/EPPlus/Utils/AddressUtility.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System.Text.RegularExpressions;
-
-namespace OfficeOpenXml.Utils;
-
-public static class AddressUtility {
- public static string ParseEntireColumnSelections(string address) {
- string parsedAddress = address;
- var matches = Regex.Matches(address, "[A-Z]+:[A-Z]+");
- foreach (Match match in matches) {
- AddRowNumbersToEntireColumnRange(ref parsedAddress, match.Value);
- }
- return parsedAddress;
- }
-
- private static void AddRowNumbersToEntireColumnRange(ref string address, string range) {
- var parsedRange = string.Format("{0}{1}", range, ExcelPackage.MaxRows);
- var splitArr = parsedRange.Split(new[] { ':' });
- address = address.Replace(range, string.Format("{0}1:{1}", splitArr[0], splitArr[1]));
- }
-}
diff --git a/EPPlus/Utils/Argument.cs b/EPPlus/Utils/Argument.cs
deleted file mode 100644
index 8519db1..0000000
--- a/EPPlus/Utils/Argument.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-namespace OfficeOpenXml.Utils;
-
-internal class Argument<T> : IArgument<T> {
- public Argument(T value) {
- _value = value;
- }
-
- private readonly T _value;
-
- T IArgument<T>.Value => _value;
-}
diff --git a/EPPlus/Utils/ArgumentExtensions.cs b/EPPlus/Utils/ArgumentExtensions.cs
deleted file mode 100644
index 6bba854..0000000
--- a/EPPlus/Utils/ArgumentExtensions.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml.Utils;
-
-/// <summary>
-/// Extension methods for guarding
-/// </summary>
-public static class ArgumentExtensions {
- /// <summary>
- /// Throws an ArgumentNullException if argument is null
- /// </summary>
- /// <typeparam name="T">Argument type</typeparam>
- /// <param name="argument">Argument to check</param>
- /// <param name="argumentName">parameter/argument name</param>
- /// <exception cref="ArgumentNullException"></exception>
- public static void IsNotNull<T>(this IArgument<T> argument, string argumentName)
- where T : class {
- argumentName = string.IsNullOrEmpty(argumentName) ? "value" : argumentName;
- if (argument.Value == null) {
- throw new ArgumentNullException(argumentName);
- }
- }
-
- /// <summary>
- /// Throws an <see cref="ArgumentNullException"/> if the string argument is null or empty
- /// </summary>
- /// <param name="argument">Argument to check</param>
- /// <param name="argumentName">parameter/argument name</param>
- /// <exception cref="ArgumentNullException"></exception>
- public static void IsNotNullOrEmpty(this IArgument<string> argument, string argumentName) {
- if (string.IsNullOrEmpty(argument.Value)) {
- throw new ArgumentNullException(argumentName);
- }
- }
-
- /// <summary>
- /// Throws an ArgumentOutOfRangeException if the value of the argument is out of the supplied range
- /// </summary>
- /// <typeparam name="T">Type implementing <see cref="IComparable"/></typeparam>
- /// <param name="argument">The argument to check</param>
- /// <param name="min">Min value of the supplied range</param>
- /// <param name="max">Max value of the supplied range</param>
- /// <param name="argumentName">parameter/argument name</param>
- /// <exception cref="ArgumentOutOfRangeException"></exception>
- public static void IsInRange<T>(this IArgument<T> argument, T min, T max, string argumentName)
- where T : IComparable {
- if (!(argument.Value.CompareTo(min) >= 0 && argument.Value.CompareTo(max) <= 0)) {
- throw new ArgumentOutOfRangeException(argumentName);
- }
- }
-}
diff --git a/EPPlus/Utils/ConvertUtil.cs b/EPPlus/Utils/ConvertUtil.cs
deleted file mode 100644
index 2802caa..0000000
--- a/EPPlus/Utils/ConvertUtil.cs
+++ /dev/null
@@ -1,171 +0,0 @@
-using System;
-using System.Globalization;
-using System.IO;
-using System.Text;
-using System.Text.RegularExpressions;
-
-namespace OfficeOpenXml.Utils;
-
-internal static class ConvertUtil {
- internal static bool IsNumeric(object candidate) {
- if (candidate == null) {
- return false;
- }
- return (candidate.GetType().IsPrimitive
- || candidate is double
- || candidate is decimal
- || candidate is DateTime
- || candidate is TimeSpan
- || candidate is long);
- }
-
- internal static bool IsNumericString(object candidate) {
- if (candidate != null) {
- return Regex.IsMatch(candidate.ToString(), @"^[\d]+(\,[\d])?");
- }
- return false;
- }
-
- /// <summary>
- /// Convert an object value to a double
- /// </summary>
- /// <param name="v"></param>
- /// <param name="ignoreBool"></param>
- /// <returns></returns>
- internal static double GetValueDouble(object v, bool ignoreBool = false) {
- double d;
- try {
- if (ignoreBool && v is bool) {
- return 0;
- }
- if (IsNumeric(v)) {
- if (v is DateTime time) {
- d = time.ToOADate();
- } else if (v is TimeSpan span) {
- d = DateTime.FromOADate(0).Add(span).ToOADate();
- } else {
- d = Convert.ToDouble(v, CultureInfo.InvariantCulture);
- }
- } else {
- d = 0;
- }
- } catch {
- d = 0;
- }
- return d;
- }
-
- /// <summary>
- /// OOXML requires that "," , and & be escaped, but ' and " should *not* be escaped, nor should
- /// any extended Unicode characters. This function only encodes the required characters.
- /// System.Security.SecurityElement.Escape() escapes ' and " as ' and ", so it cannot
- /// be used reliably. System.Web.HttpUtility.HtmlEncode overreaches as well and uses the numeric
- /// escape equivalent.
- /// </summary>
- /// <param name="s"></param>
- /// <returns></returns>
- internal static string ExcelEscapeString(string s) {
- return s.Replace("&", "&").Replace("<", "<").Replace(">", ">");
- }
-
- /// <summary>
- /// Return true if preserve space attribute is set.
- /// </summary>
- /// <param name="sw"></param>
- /// <param name="t"></param>
- /// <returns></returns>
- internal static void ExcelEncodeString(StreamWriter sw, string t) {
- if (Regex.IsMatch(t, "(_x[0-9A-F]{4,4}_)")) {
- var match = Regex.Match(t, "(_x[0-9A-F]{4,4}_)");
- int indexAdd = 0;
- while (match.Success) {
- t = t.Insert(match.Index + indexAdd, "_x005F");
- indexAdd += 6;
- match = match.NextMatch();
- }
- }
- for (int i = 0; i < t.Length; i++) {
- if (t[i] <= 0x1f
- && t[i] != '\t'
- && t[i] != '\n'
- && t[i]
- != '\r') //Not Tab, CR or LF
- {
- sw.Write("_x00{0}_", (t[i] < 0xf ? "0" : "") + ((int)t[i]).ToString("X"));
- } else {
- sw.Write(t[i]);
- }
- }
- }
-
- /// <summary>
- /// Return true if preserve space attribute is set.
- /// </summary>
- /// <param name="sb"></param>
- /// <param name="t"></param>
- /// <returns></returns>
- internal static void ExcelEncodeString(StringBuilder sb, string t, bool encodeTabCrlf = false) {
- if (Regex.IsMatch(t, "(_x[0-9A-F]{4,4}_)")) {
- var match = Regex.Match(t, "(_x[0-9A-F]{4,4}_)");
- int indexAdd = 0;
- while (match.Success) {
- t = t.Insert(match.Index + indexAdd, "_x005F");
- indexAdd += 6;
- match = match.NextMatch();
- }
- }
- for (int i = 0; i < t.Length; i++) {
- if (t[i] <= 0x1f
- && ((t[i] != '\t' && t[i] != '\n' && t[i] != '\r' && encodeTabCrlf == false)
- || encodeTabCrlf)) //Not Tab, CR or LF
- {
- sb.AppendFormat("_x00{0}_", (t[i] < 0xf ? "0" : "") + ((int)t[i]).ToString("X"));
- } else {
- sb.Append(t[i]);
- }
- }
- }
-
- /// <summary>
- /// Return true if preserve space attribute is set.
- /// </summary>
- /// <param name="sb"></param>
- /// <param name="t"></param>
- /// <returns></returns>
- internal static string ExcelEncodeString(string t) {
- StringBuilder sb = new StringBuilder();
- t = t.Replace("\r\n", "\n"); //For some reason can't table name have cr in them. Replace with nl
- ExcelEncodeString(sb, t, true);
- return sb.ToString();
- }
-
- internal static string ExcelDecodeString(string t) {
- var match = Regex.Match(t, "(_x005F|_x[0-9A-F]{4,4}_)");
- if (!match.Success) {
- return t;
- }
-
- var useNextValue = false;
- var ret = new StringBuilder();
- var prevIndex = 0;
- while (match.Success) {
- if (prevIndex < match.Index) {
- ret.Append(t.Substring(prevIndex, match.Index - prevIndex));
- }
- if (!useNextValue && match.Value == "_x005F") {
- useNextValue = true;
- } else {
- if (useNextValue) {
- ret.Append(match.Value);
- useNextValue = false;
- } else {
- ret.Append((char)int.Parse(match.Value.Substring(2, 4), NumberStyles.AllowHexSpecifier));
- }
- }
- prevIndex = match.Index + match.Length;
- match = match.NextMatch();
- }
- ret.Append(t.Substring(prevIndex, t.Length - prevIndex));
- return ret.ToString();
- }
-}
diff --git a/EPPlus/Utils/IArgument.cs b/EPPlus/Utils/IArgument.cs
deleted file mode 100644
index 8c4f614..0000000
--- a/EPPlus/Utils/IArgument.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-namespace OfficeOpenXml.Utils;
-
-/// <summary>
-/// An argument
-/// </summary>
-/// <typeparam name="T">Argument Type</typeparam>
-public interface IArgument<T> {
- T Value { get; }
-}
diff --git a/EPPlus/Utils/IExcelCell.cs b/EPPlus/Utils/IExcelCell.cs
deleted file mode 100644
index b1087c3..0000000
--- a/EPPlus/Utils/IExcelCell.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-16
- *******************************************************************************/
-
-using System;
-
-namespace OfficeOpenXml.Style;
-
-internal interface IExcelCell {
- object Value { get; set; }
-
- string StyleName { get; }
-
- int StyleID { get; set; }
-
- ExcelStyle Style { get; }
-
- Uri Hyperlink { get; set; }
-
- string Formula { get; set; }
-
- string FormulaR1C1 { get; set; }
-}
diff --git a/EPPlus/Utils/IValidationResult.cs b/EPPlus/Utils/IValidationResult.cs
deleted file mode 100644
index 61ef1c1..0000000
--- a/EPPlus/Utils/IValidationResult.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace OfficeOpenXml.Utils;
-
-public interface IValidationResult {
- void IsTrue();
-
- void IsFalse();
-}
diff --git a/EPPlus/Utils/Require.cs b/EPPlus/Utils/Require.cs
deleted file mode 100644
index 17b98d8..0000000
--- a/EPPlus/Utils/Require.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Added 2011-01-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-namespace OfficeOpenXml.Utils;
-
-/// <summary>
-/// Utility for validation
-/// </summary>
-public static class Require {
- public static IArgument<T> Argument<T>(T argument) {
- return new Argument<T>(argument);
- }
-}
diff --git a/EPPlus/Utils/SqRefUtility.cs b/EPPlus/Utils/SqRefUtility.cs
deleted file mode 100644
index 5115bd3..0000000
--- a/EPPlus/Utils/SqRefUtility.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System.Text.RegularExpressions;
-
-namespace OfficeOpenXml.Utils;
-
-/// <summary>
-/// Class for handling translation between ExcelAddresses and sqref addresses.
-/// </summary>
-public static class SqRefUtility {
- /// <summary>
- /// Transforms an address to a valid sqRef address.
- /// </summary>
- /// <param name="address">The address to transform</param>
- /// <returns>A valid SqRef address</returns>
- public static string ToSqRefAddress(string address) {
- Require.Argument(address).IsNotNullOrEmpty(address);
- address = address.Replace(",", " ");
- address = new Regex("[ ]+").Replace(address, " ");
- return address;
- }
-
- /// <summary>
- /// Transforms an sqRef address into a excel address
- /// </summary>
- /// <param name="address">The address to transform</param>
- /// <returns>A valid excel address</returns>
- public static string FromSqRefAddress(string address) {
- Require.Argument(address).IsNotNullOrEmpty(address);
- address = address.Replace(" ", ",");
- return address;
- }
-}
diff --git a/EPPlus/Utils/UriHelper.cs b/EPPlus/Utils/UriHelper.cs
deleted file mode 100644
index 8f9c04b..0000000
--- a/EPPlus/Utils/UriHelper.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-using System;
-
-namespace OfficeOpenXml.Utils;
-
-internal class UriHelper {
- internal static Uri ResolvePartUri(Uri sourceUri, Uri targetUri) {
- if (targetUri.OriginalString.StartsWith("/")) {
- return targetUri;
- }
- string[] source = sourceUri.OriginalString.Split('/');
- string[] target = targetUri.OriginalString.Split('/');
-
- int t = target.Length - 1;
- int s;
- if (sourceUri.OriginalString.EndsWith(
- "/")) //is the source a directory?
- {
- s = source.Length - 1;
- } else {
- s = source.Length - 2;
- }
-
- string file = target[t--];
-
- while (t >= 0) {
- if (target[t] == ".") {
- break;
- }
- if (target[t] == "..") {
- s--;
- t--;
- } else {
- file = target[t--] + "/" + file;
- }
- }
- if (s >= 0) {
- for (int i = s; i >= 0; i--) {
- file = source[i] + "/" + file;
- }
- }
- return new(file, UriKind.RelativeOrAbsolute);
- }
-
- internal static Uri GetRelativeUri(Uri worksheetUri, Uri uri) {
- string[] source = worksheetUri.OriginalString.Split('/');
- string[] target = uri.OriginalString.Split('/');
-
- int slen;
- if (worksheetUri.OriginalString.EndsWith("/")) {
- slen = source.Length;
- } else {
- slen = source.Length - 1;
- }
- int i = 0;
- while (i < slen && i < target.Length && source[i] == target[i]) {
- i++;
- }
-
- string dirUp = "";
- for (int s = i; s < slen; s++) {
- dirUp += "../";
- }
- string file = "";
- for (int t = i; t < target.Length; t++) {
- file += (file == "" ? "" : "/") + target[t];
- }
- return new(dirUp + file, UriKind.Relative);
- }
-}
diff --git a/EPPlus/Utils/ValidationResult.cs b/EPPlus/Utils/ValidationResult.cs
deleted file mode 100644
index 9985fa5..0000000
--- a/EPPlus/Utils/ValidationResult.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System;
-
-namespace OfficeOpenXml.Utils;
-
-public class ValidationResult : IValidationResult {
- public ValidationResult(bool result)
- : this(result, null) {}
-
- public ValidationResult(bool result, string errorMessage) {
- _result = result;
- _errorMessage = errorMessage;
- }
-
- private readonly bool _result;
- private readonly string _errorMessage;
-
- private void Throw() {
- if (string.IsNullOrEmpty(_errorMessage)) {
- throw new InvalidOperationException();
- }
- throw new InvalidOperationException(_errorMessage);
- }
-
- void IValidationResult.IsTrue() {
- if (!_result) {
- Throw();
- }
- }
-
- void IValidationResult.IsFalse() {
- if (_result) {
- Throw();
- }
- }
-}
diff --git a/EPPlus/XmlHelper.cs b/EPPlus/XmlHelper.cs
deleted file mode 100644
index b311997..0000000
--- a/EPPlus/XmlHelper.cs
+++ /dev/null
@@ -1,628 +0,0 @@
-/*******************************************************************************
- * 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 Initial Release 2009-10-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- * Eyal Seagull Add "CreateComplexNode" 2012-04-03
- * Eyal Seagull Add "DeleteTopNode" 2012-04-13
- *******************************************************************************/
-
-using System;
-using System.Collections.Immutable;
-using System.Globalization;
-using System.IO;
-using System.Text;
-using System.Xml;
-using OfficeOpenXml.Style;
-
-namespace OfficeOpenXml;
-
-/// <summary>
-/// Help class containing XML functions.
-/// Can be Inherited
-/// </summary>
-public abstract class XmlHelper {
- internal delegate int ChangedEventHandler(StyleBase sender, StyleChangeEventArgs e);
-
- internal XmlHelper(XmlNamespaceManager nameSpaceManager) {
- TopNode = null;
- NameSpaceManager = nameSpaceManager;
- }
-
- internal XmlHelper(XmlNamespaceManager nameSpaceManager, XmlNode topNode) {
- TopNode = topNode;
- NameSpaceManager = nameSpaceManager;
- }
-
- //internal bool ChangedFlag;
- internal XmlNamespaceManager NameSpaceManager { get; set; }
-
- internal XmlNode TopNode { get; set; }
-
- /// <summary>
- /// Schema order list
- /// </summary>
- protected virtual ImmutableArray<string> SchemaNodeOrder => ImmutableArray<string>.Empty;
-
- internal XmlNode CreateNode(string path) {
- if (path == "") {
- return TopNode;
- }
- return CreateNode(path, false);
- }
-
- internal XmlNode CreateNode(string path, bool insertFirst) {
- XmlNode node = TopNode;
- XmlNode prependNode = null;
- foreach (string subPath in path.Split('/')) {
- XmlNode subNode = node.SelectSingleNode(subPath, NameSpaceManager);
- if (subNode == null) {
- string nodeName;
- string nodePrefix;
-
- string nameSpaceUri;
- string[] nameSplit = subPath.Split(':');
-
- if (SchemaNodeOrder.Length > 0 && subPath[0] != '@') {
- insertFirst = false;
- prependNode = GetPrependNode(subPath, node);
- }
-
- if (nameSplit.Length > 1) {
- nodePrefix = nameSplit[0];
- if (nodePrefix[0] == '@') {
- nodePrefix = nodePrefix.Substring(1, nodePrefix.Length - 1);
- }
- nameSpaceUri = NameSpaceManager.LookupNamespace(nodePrefix);
- nodeName = nameSplit[1];
- } else {
- nodePrefix = "";
- nameSpaceUri = "";
- nodeName = nameSplit[0];
- }
- if (subPath.StartsWith("@")) {
- XmlAttribute addedAtt = node.OwnerDocument.CreateAttribute(
- subPath.Substring(1, subPath.Length - 1),
- nameSpaceUri); //nameSpaceURI
- node.Attributes.Append(addedAtt);
- } else {
- if (nodePrefix == "") {
- subNode = node.OwnerDocument.CreateElement(nodeName, nameSpaceUri);
- } else {
- if (nodePrefix == ""
- || (node.OwnerDocument != null
- && node.OwnerDocument.DocumentElement != null
- && node.OwnerDocument.DocumentElement.NamespaceURI == nameSpaceUri
- && node.OwnerDocument.DocumentElement.Prefix == "")) {
- subNode = node.OwnerDocument.CreateElement(nodeName, nameSpaceUri);
- } else {
- subNode = node.OwnerDocument.CreateElement(nodePrefix, nodeName, nameSpaceUri);
- }
- }
- if (prependNode != null) {
- node.InsertBefore(subNode, prependNode);
- prependNode = null;
- } else if (insertFirst) {
- node.PrependChild(subNode);
- } else {
- node.AppendChild(subNode);
- }
- }
- }
- node = subNode;
- }
- return node;
- }
-
- /// <summary>
- /// Options to insert a node in the XmlDocument
- /// </summary>
- internal enum eNodeInsertOrder {
- /// <summary>
- /// Insert as first node of "topNode"
- /// </summary>
- First,
-
- /// <summary>
- /// Insert as the last child of "topNode"
- /// </summary>
- Last,
-
- /// <summary>
- /// Insert after the "referenceNode"
- /// </summary>
- After,
-
- /// <summary>
- /// Insert before the "referenceNode"
- /// </summary>
- Before,
-
- /// <summary>
- /// Use the Schema List to insert in the right order. If the Schema list
- /// is null or empty, consider "Last" as the selected option
- /// </summary>
- SchemaOrder,
- }
-
- /// <summary>
- /// Create a complex node. Insert the node according to the <paramref name="path"/>
- /// using the <paramref name="topNode"/> as the parent
- /// </summary>
- /// <param name="topNode"></param>
- /// <param name="path"></param>
- /// <returns></returns>
- internal XmlNode CreateComplexNode(XmlNode topNode, string path) {
- return CreateComplexNode(topNode, path, eNodeInsertOrder.SchemaOrder, null);
- }
-
- /// <summary>
- /// Creates complex XML nodes
- /// </summary>
- /// <remarks>
- /// 1. "d:conditionalFormatting"
- /// 1.1. Creates/find the first "conditionalFormatting" node
- ///
- /// 2. "d:conditionalFormatting/@sqref"
- /// 2.1. Creates/find the first "conditionalFormatting" node
- /// 2.2. Creates (if not exists) the @sqref attribute
- ///
- /// 3. "d:conditionalFormatting/@id='7'/@sqref='A9:B99'"
- /// 3.1. Creates/find the first "conditionalFormatting" node
- /// 3.2. Creates/update its @id attribute to "7"
- /// 3.3. Creates/update its @sqref attribute to "A9:B99"
- ///
- /// 4. "d:conditionalFormatting[@id='7']/@sqref='X1:X5'"
- /// 4.1. Creates/find the first "conditionalFormatting" node with @id=7
- /// 4.2. Creates/update its @sqref attribute to "X1:X5"
- ///
- /// 5. "d:conditionalFormatting[@id='7']/@id='8'/@sqref='X1:X5'/d:cfRule/@id='AB'"
- /// 5.1. Creates/find the first "conditionalFormatting" node with @id=7
- /// 5.2. Set its @id attribute to "8"
- /// 5.2. Creates/update its @sqref attribute and set it to "X1:X5"
- /// 5.3. Creates/find the first "cfRule" node (inside the node)
- /// 5.4. Creates/update its @id attribute to "AB"
- ///
- /// 6. "d:cfRule/@id=''"
- /// 6.1. Creates/find the first "cfRule" node
- /// 6.1. Remove the @id attribute
- /// </remarks>
- /// <param name="topNode"></param>
- /// <param name="path"></param>
- /// <param name="nodeInsertOrder"></param>
- /// <param name="referenceNode"></param>
- /// <returns>The last node creates/found</returns>
- internal XmlNode CreateComplexNode(
- XmlNode topNode,
- string path,
- eNodeInsertOrder nodeInsertOrder,
- XmlNode referenceNode) {
- // Path is obrigatory
- if ((path == null) || (path == string.Empty)) {
- return topNode;
- }
-
- XmlNode node = topNode;
-
- //TODO: BUG: when the "path" contains "/" in an attrribue value, it gives an error.
-
- // Separate the XPath to Nodes and Attributes
- foreach (string subPath in path.Split('/')) {
- // The subPath can be any one of those:
- // nodeName
- // x:nodeName
- // nodeName[find criteria]
- // x:nodeName[find criteria]
- // @attribute
- // @attribute='attribute value'
-
- // Check if the subPath has at least one character
- if (subPath.Length > 0) {
- // Check if the subPath is an attribute (with or without value)
- if (subPath.StartsWith("@")) {
- // @attribute --> Create attribute
- // @attribute='' --> Remove attribute
- // @attribute='attribute value' --> Create attribute + update value
- string[] attributeSplit = subPath.Split('=');
- string attributeName = attributeSplit[0].Substring(1, attributeSplit[0].Length - 1);
- string attributeValue = null; // Null means no attribute value
-
- // Check if we have an attribute value to set
- if (attributeSplit.Length > 1) {
- // Remove the ' or " from the attribute value
- attributeValue = attributeSplit[1].Replace("'", "").Replace("\"", "");
- }
-
- // Get the attribute (if exists)
- XmlAttribute attribute = (XmlAttribute)(node.Attributes.GetNamedItem(attributeName));
-
- // Remove the attribute if value is empty (not null)
- if (attributeValue == string.Empty) {
- // Only if the attribute exists
- if (attribute != null) {
- node.Attributes.Remove(attribute);
- }
- } else {
- // Create the attribue if does not exists
- if (attribute == null) {
- // Create the attribute
- attribute = node.OwnerDocument.CreateAttribute(attributeName);
-
- // Add it to the current node
- node.Attributes.Append(attribute);
- }
-
- // Update the attribute value
- if (attributeValue != null) {
- node.Attributes[attributeName].Value = attributeValue;
- }
- }
- } else {
- // nodeName
- // x:nodeName
- // nodeName[find criteria]
- // x:nodeName[find criteria]
-
- // Look for the node (with or without filter criteria)
- XmlNode subNode = node.SelectSingleNode(subPath, NameSpaceManager);
-
- // Check if the node does not exists
- if (subNode == null) {
- string nodeName;
- string nodePrefix;
- string[] nameSplit = subPath.Split(':');
- string nameSpaceUri;
-
- // Check if the name has a prefix like "d:nodeName"
- if (nameSplit.Length > 1) {
- nodePrefix = nameSplit[0];
- nameSpaceUri = NameSpaceManager.LookupNamespace(nodePrefix);
- nodeName = nameSplit[1];
- } else {
- nodePrefix = string.Empty;
- nameSpaceUri = string.Empty;
- nodeName = nameSplit[0];
- }
-
- // Check if we have a criteria part in the node name
- if (nodeName.IndexOf("[") > 0) {
- // remove the criteria from the node name
- nodeName = nodeName.Substring(0, nodeName.IndexOf("["));
- }
-
- if (nodePrefix == string.Empty) {
- subNode = node.OwnerDocument.CreateElement(nodeName, nameSpaceUri);
- } else {
- if (node.OwnerDocument != null
- && node.OwnerDocument.DocumentElement != null
- && node.OwnerDocument.DocumentElement.NamespaceURI == nameSpaceUri
- && node.OwnerDocument.DocumentElement.Prefix == string.Empty) {
- subNode = node.OwnerDocument.CreateElement(nodeName, nameSpaceUri);
- } else {
- subNode = node.OwnerDocument.CreateElement(nodePrefix, nodeName, nameSpaceUri);
- }
- }
-
- // Check if we need to use the "SchemaOrder"
- if (nodeInsertOrder == eNodeInsertOrder.SchemaOrder) {
- // Check if the Schema Order List is empty
- if (SchemaNodeOrder.Length == 0) {
- // Use the "Insert Last" option when Schema Order List is empty
- nodeInsertOrder = eNodeInsertOrder.Last;
- } else {
- // Find the prepend node in order to insert
- referenceNode = GetPrependNode(nodeName, node);
-
- if (referenceNode != null) {
- nodeInsertOrder = eNodeInsertOrder.Before;
- } else {
- nodeInsertOrder = eNodeInsertOrder.Last;
- }
- }
- }
-
- switch (nodeInsertOrder) {
- case eNodeInsertOrder.After:
- node.InsertAfter(subNode, referenceNode);
- referenceNode = null;
- break;
-
- case eNodeInsertOrder.Before:
- node.InsertBefore(subNode, referenceNode);
- referenceNode = null;
- break;
-
- case eNodeInsertOrder.First:
- node.PrependChild(subNode);
- break;
-
- case eNodeInsertOrder.Last:
- node.AppendChild(subNode);
- break;
- }
- }
-
- // Make the newly created node the top node when the rest of the path
- // is being evaluated. So newly created nodes will be the children of the
- // one we just created.
- node = subNode;
- }
- }
- }
-
- // Return the last created/found node
- return node;
- }
-
- /// <summary>
- /// return Prepend node
- /// </summary>
- /// <param name="nodeName">name of the node to check</param>
- /// <param name="node">Topnode to check children</param>
- /// <returns></returns>
- private XmlNode GetPrependNode(string nodeName, XmlNode node) {
- int pos = GetNodePos(nodeName);
- if (pos < 0) {
- return null;
- }
- XmlNode prependNode = null;
- foreach (XmlNode childNode in node.ChildNodes) {
- int childPos = GetNodePos(childNode.Name);
- if (childPos
- > -1) //Found?
- {
- if (childPos
- > pos) //Position is before
- {
- prependNode = childNode;
- break;
- }
- }
- }
- return prependNode;
- }
-
- private int GetNodePos(string nodeName) {
- int ix = nodeName.IndexOf(":");
- if (ix > 0) {
- nodeName = nodeName.Substring(ix + 1, nodeName.Length - (ix + 1));
- }
- for (int i = 0; i < SchemaNodeOrder.Length; i++) {
- if (nodeName == SchemaNodeOrder[i]) {
- return i;
- }
- }
- return -1;
- }
-
- internal void DeleteAllNode(string path) {
- string[] split = path.Split('/');
- XmlNode node = TopNode;
- foreach (string s in split) {
- node = node.SelectSingleNode(s, NameSpaceManager);
- if (node != null) {
- if (node is XmlAttribute attribute) {
- attribute.OwnerElement.Attributes.Remove(attribute);
- } else {
- node.ParentNode.RemoveChild(node);
- }
- } else {
- break;
- }
- }
- }
-
- internal void DeleteNode(string path) {
- var node = TopNode.SelectSingleNode(path, NameSpaceManager);
- if (node != null) {
- if (node is XmlAttribute att) {
- att.OwnerElement.Attributes.Remove(att);
- } else {
- node.ParentNode.RemoveChild(node);
- }
- }
- }
-
- internal void SetXmlNodeString(string path, string value) {
- SetXmlNodeString(TopNode, path, value, false, false);
- }
-
- internal void SetXmlNodeString(string path, string value, bool removeIfBlank) {
- SetXmlNodeString(TopNode, path, value, removeIfBlank, false);
- }
-
- internal void SetXmlNodeString(XmlNode node, string path, string value, bool removeIfBlank) {
- SetXmlNodeString(node, path, value, removeIfBlank, false);
- }
-
- internal void SetXmlNodeString(
- XmlNode node,
- string path,
- string value,
- bool removeIfBlank,
- bool insertFirst) {
- if (node == null) {
- return;
- }
- if (value == "" && removeIfBlank) {
- DeleteAllNode(path);
- } else {
- XmlNode nameNode = node.SelectSingleNode(path, NameSpaceManager);
- if (nameNode == null) {
- CreateNode(path, insertFirst);
- nameNode = node.SelectSingleNode(path, NameSpaceManager);
- }
- //if (nameNode.InnerText != value) HasChanged();
- nameNode.InnerText = value;
- }
- }
-
- internal void SetXmlNodeBool(string path, bool value) {
- SetXmlNodeString(TopNode, path, value ? "1" : "0", false, false);
- }
-
- internal void SetXmlNodeBool(string path, bool value, bool removeIf) {
- if (value == removeIf) {
- var node = TopNode.SelectSingleNode(path, NameSpaceManager);
- if (node != null) {
- if (node is XmlAttribute attribute) {
- var elem = attribute.OwnerElement;
- elem.ParentNode.RemoveChild(elem);
- } else {
- TopNode.RemoveChild(node);
- }
- }
- } else {
- SetXmlNodeString(TopNode, path, value ? "1" : "0", false, false);
- }
- }
-
- internal bool ExistNode(string path) {
- if (TopNode == null || TopNode.SelectSingleNode(path, NameSpaceManager) == null) {
- return false;
- }
- return true;
- }
-
- internal bool? GetXmlNodeBoolNullable(string path) {
- var value = GetXmlNodeString(path);
- if (string.IsNullOrEmpty(value)) {
- return null;
- }
- return GetXmlNodeBool(path);
- }
-
- internal bool GetXmlNodeBool(string path) {
- return GetXmlNodeBool(path, false);
- }
-
- internal bool GetXmlNodeBool(string path, bool blankValue) {
- string value = GetXmlNodeString(path);
- if (value == "1"
- || value == "-1"
- || value.Equals("true", StringComparison.InvariantCultureIgnoreCase)) {
- return true;
- }
- if (value == "") {
- return blankValue;
- }
- return false;
- }
-
- internal int GetXmlNodeInt(string path) {
- if (int.TryParse(GetXmlNodeString(path), out var i)) {
- return i;
- }
- return int.MinValue;
- }
-
- internal int? GetXmlNodeIntNull(string path) {
- string s = GetXmlNodeString(path);
- if (s != "" && int.TryParse(s, out var i)) {
- return i;
- }
- return null;
- }
-
- internal decimal GetXmlNodeDecimal(string path) {
- if (decimal.TryParse(
- GetXmlNodeString(path),
- NumberStyles.Any,
- CultureInfo.InvariantCulture,
- out var d)) {
- return d;
- }
- return 0;
- }
-
- internal decimal? GetXmlNodeDecimalNull(string path) {
- if (decimal.TryParse(
- GetXmlNodeString(path),
- NumberStyles.Any,
- CultureInfo.InvariantCulture,
- out var d)) {
- return d;
- }
- return null;
- }
-
- internal double? GetXmlNodeDoubleNull(string path) {
- string s = GetXmlNodeString(path);
- if (s == "") {
- return null;
- }
- if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out var v)) {
- return v;
- }
- return null;
- }
-
- internal double GetXmlNodeDouble(string path) {
- string s = GetXmlNodeString(path);
- if (s == "") {
- return double.NaN;
- }
- if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out var v)) {
- return v;
- }
- return double.NaN;
- }
-
- internal string GetXmlNodeString(XmlNode node, string path) {
- if (node == null) {
- return "";
- }
-
- XmlNode nameNode = node.SelectSingleNode(path, NameSpaceManager);
-
- if (nameNode != null) {
- if (nameNode.NodeType == XmlNodeType.Attribute) {
- return nameNode.Value ?? "";
- }
- return nameNode.InnerText;
- }
- return "";
- }
-
- internal string GetXmlNodeString(string path) {
- return GetXmlNodeString(TopNode, path);
- }
-
- internal static void LoadXmlSafe(XmlDocument xmlDoc, Stream stream) {
- XmlReaderSettings settings = new XmlReaderSettings();
- //Disable entity parsing (to aviod xmlbombs, External Entity Attacks etc).
- settings.ProhibitDtd = true;
- XmlReader reader = XmlReader.Create(stream, settings);
- xmlDoc.Load(reader);
- }
-
- internal static void LoadXmlSafe(XmlDocument xmlDoc, string xml, Encoding encoding) {
- var stream = new MemoryStream(encoding.GetBytes(xml));
- LoadXmlSafe(xmlDoc, stream);
- }
-}
diff --git a/EPPlus/XmlHelperFactory.cs b/EPPlus/XmlHelperFactory.cs
deleted file mode 100644
index 0af078b..0000000
--- a/EPPlus/XmlHelperFactory.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-/*******************************************************************************
- * 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
- * ******************************************************************************
- * Mats Alm Initial Release 2011-05-01
- * Jan Källman License changed GPL-->LGPL 2011-12-27
- *******************************************************************************/
-
-using System.Xml;
-
-namespace OfficeOpenXml;
-
-internal class XmlHelperInstance : XmlHelper {
- internal XmlHelperInstance(XmlNamespaceManager namespaceManager)
- : base(namespaceManager) {}
-
- internal XmlHelperInstance(XmlNamespaceManager namespaceManager, XmlNode topNode)
- : base(namespaceManager, topNode) {}
-}
-
-internal static class XmlHelperFactory {
- internal static XmlHelper Create(XmlNamespaceManager namespaceManager) {
- return new XmlHelperInstance(namespaceManager);
- }
-
- internal static XmlHelper Create(XmlNamespaceManager namespaceManager, XmlNode topNode) {
- return new XmlHelperInstance(namespaceManager, topNode);
- }
-}
diff --git a/NetCoreTests/ExcelPackageTest.cs b/NetCoreTests/ExcelPackageTest.cs
index 369e55a..77a5c6b 100644
--- a/NetCoreTests/ExcelPackageTest.cs
+++ b/NetCoreTests/ExcelPackageTest.cs
@@ -1,9 +1,8 @@
using System.IO;
using System.Linq;
+using AppsheetEpplus;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using OfficeOpenXml;
-using OfficeOpenXml.DataValidation;
namespace NetCoreTests;
diff --git a/NetCoreTests/NetCoreTests.csproj b/NetCoreTests/NetCoreTests.csproj
index 275008e..6218500 100644
--- a/NetCoreTests/NetCoreTests.csproj
+++ b/NetCoreTests/NetCoreTests.csproj
@@ -11,8 +11,9 @@
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
- <ProjectReference Include="..\EPPlus\EPPlusSDK.csproj"/>
-
<None Include="TestWorkbooks/**" CopyToOutputDirectory="PreserveNewest"/>
</ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\AppsheetEpplus\AppsheetEpplus.csproj" />
+ </ItemGroup>
</Project>
diff --git a/NetCoreTests/TimeTest.cs b/NetCoreTests/TimeTest.cs
index 8ce92f5..a94ce94 100644
--- a/NetCoreTests/TimeTest.cs
+++ b/NetCoreTests/TimeTest.cs
@@ -2,9 +2,9 @@
using System.IO;
using System.Linq;
using System.Text;
+using AppsheetEpplus;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using OfficeOpenXml;
namespace NetCoreTests;