[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;