[NWD] Format EPPlus with CSharpier.
Also:
- Add dotnet-csharpier and .editorconfig files
- Clean up identifier naming
- Misc cleanup
Change-Id: I73e05e4ff47dd857323ec5da8aec4b3bf021f496
Reviewed-on: https://gnocchi-internal-review.git.corp.google.com/c/third_party/epplus/+/207429
Reviewed-by: Hughes Hilton <hugheshilton@google.com>
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..a054d7d
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,257 @@
+root = true
+
+[*]
+
+indent_style = space
+indent_size = 2
+tab_width = 2
+insert_final_newline = true
+end_of_line = lf
+trim_trailing_whitespace = true
+charset = utf-8
+resharper_enforce_line_ending_style = true
+resharper_apply_auto_detected_rules = false
+resharper_use_indent_from_vs = false
+
+
+[*.{cs, csx, cake, vb, vbx}]
+
+# Enforce go/csstyle
+# Naming rules
+# IDE1006 must be treated as an error for any of the following naming rules to affect builds
+dotnet_diagnostic.IDE1006.severity = error
+
+# this. preferences
+dotnet_style_qualification_for_field = false:error
+dotnet_style_qualification_for_property = false:error
+dotnet_style_qualification_for_method = false:error
+dotnet_style_qualification_for_event = false:error
+
+# Pascal case style
+dotnet_naming_style.pascal.capitalization = pascal_case
+# Interface style
+dotnet_naming_style.interface.capitalization = pascal_case
+dotnet_naming_style.interface.required_prefix = I
+# Camel-case style
+dotnet_naming_style.camel.capitalization = camel_case
+# Camel-case beginning with underscore style
+dotnet_naming_style.underscore_camel.capitalization = camel_case
+dotnet_naming_style.underscore_camel.required_prefix = _
+
+# Symbols for namespaces
+dotnet_naming_symbols.namespaces.applicable_kinds = namespace
+dotnet_naming_symbols.namespaces.applicable_accessibilities = *
+# Symbols for types
+dotnet_naming_symbols.types.applicable_kinds = class, struct, delegate, type_parameter
+dotnet_naming_symbols.types.applicable_accessibilities = *
+# Symbols for interfaces
+dotnet_naming_symbols.interfaces.applicable_kinds = interface
+dotnet_naming_symbols.interfaces.applicable_accessibilities = *
+# Symbols for enums
+dotnet_naming_symbols.enums.applicable_kinds = enum
+dotnet_naming_symbols.enums.applicable_accessibilities = *
+# Symbols for public fields and properties
+dotnet_naming_symbols.public_fields_properties.applicable_kinds = field, property
+dotnet_naming_symbols.public_fields_properties.applicable_accessibilities = public
+# Symbols for non-public fields and properties - Unenforced
+dotnet_naming_symbols.non_public_fields_properties.applicable_kinds = field, property
+dotnet_naming_symbols.non_public_fields_properties.applicable_accessibilities = internal, private, protected, protected_internal
+# Symbols for non-public constants
+dotnet_naming_symbols.private_constants.applicable_kinds = field
+dotnet_naming_symbols.private_constants.applicable_accessibilities = private, protected, internal, protected_internal
+dotnet_naming_symbols.private_constants.required_modifiers = const
+# Symbols for public constants
+dotnet_naming_symbols.public_constants.applicable_kinds = field
+dotnet_naming_symbols.public_constants.applicable_accessibilities = public
+dotnet_naming_symbols.public_constants.required_modifiers = const
+# Symbols for non-public static readonly fields and properties
+dotnet_naming_symbols.private_static_readonly.applicable_kinds = field, property
+dotnet_naming_symbols.private_static_readonly.applicable_accessibilities = private, protected, internal, protected_internal
+dotnet_naming_symbols.private_static_readonly.required_modifiers = static, readonly
+# Symbols for public static readonly fields and properties
+dotnet_naming_symbols.public_static_readonly.applicable_kinds = field, property
+dotnet_naming_symbols.public_static_readonly.applicable_accessibilities = public
+dotnet_naming_symbols.public_static_readonly.required_modifiers = static, readonly
+# Symbols for methods and events
+dotnet_naming_symbols.methods.applicable_kinds = method, event, local_function
+dotnet_naming_symbols.methods.applicable_accessibilities = *
+# Symbols for local variables and parameters
+dotnet_naming_symbols.local_variables.applicable_kinds = local, parameter
+dotnet_naming_symbols.local_variables.applicable_accessibilities = *
+
+# Rule for namespaces
+dotnet_naming_rule.namespace_rule.symbols = namespaces
+dotnet_naming_rule.namespace_rule.style = pascal
+dotnet_naming_rule.namespace_rule.severity = error
+# Rule for types
+dotnet_naming_rule.type_rule.symbols = types
+dotnet_naming_rule.type_rule.style = pascal
+dotnet_naming_rule.type_rule.severity = error
+# Rule for interfaces
+dotnet_naming_rule.interface_rule.symbols = interfaces
+dotnet_naming_rule.interface_rule.style = interface
+dotnet_naming_rule.interface_rule.severity = error
+# Rule for enums - For now, do not enforce due to serialization
+dotnet_naming_rule.enum_rule.symbols = enums
+dotnet_naming_rule.enum_rule.style = pascal
+dotnet_naming_rule.enum_rule.severity = none
+# Rule for public fields and properties - For now, do not enforce due to serialization
+dotnet_naming_rule.public_field_property_rule.symbols = public_fields_properties
+dotnet_naming_rule.public_field_property_rule.style = pascal
+dotnet_naming_rule.public_field_property_rule.severity = none
+# Rule for non-public fields and properties - Not enforced
+dotnet_naming_rule.non_public_field_property_rule.symbols = non_public_fields_properties
+dotnet_naming_rule.non_public_field_property_rule.style = underscore_camel
+dotnet_naming_rule.non_public_field_property_rule.severity = none
+# Rule for non-public constants
+dotnet_naming_rule.private_constant_rule.symbols = private_constants
+dotnet_naming_rule.private_constant_rule.style = underscore_camel
+dotnet_naming_rule.private_constant_rule.severity = error
+# Rule for public constants
+dotnet_naming_rule.public_constant_rule.symbols = public_constants
+dotnet_naming_rule.public_constant_rule.style = pascal
+dotnet_naming_rule.public_constant_rule.severity = error
+# Rule for non-public static readonly fields and properties
+dotnet_naming_rule.private_static_readonly_rule.symbols = private_static_readonly
+dotnet_naming_rule.private_static_readonly_rule.style = underscore_camel
+dotnet_naming_rule.private_static_readonly_rule.severity = error
+# Rule for public static readonly fields and properties
+dotnet_naming_rule.private_static_readonly_rule.symbols = public_static_readonly
+dotnet_naming_rule.private_static_readonly_rule.style = pascal
+dotnet_naming_rule.private_static_readonly_rule.severity = error
+# Rule for methods and events
+dotnet_naming_rule.method_rule.symbols = methods
+dotnet_naming_rule.method_rule.style = pascal
+dotnet_naming_rule.method_rule.severity = error
+# Rule for local variables and parameters
+dotnet_naming_rule.variable_rule.symbols = local_variables
+dotnet_naming_rule.variable_rule.style = camel
+dotnet_naming_rule.variable_rule.severity = error
+
+# Organization
+
+dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
+dotnet_sort_system_directives_first = true
+resharper_sort_usings_with_system_first = true
+csharp_preserve_single_line_statements = false
+# Single-line blocks can be things like auto properties
+csharp_preserve_single_line_blocks = true
+csharp_using_directive_placement = outside_namespace
+csharp_trailing_comma_in_multiline_lists = true
+csharp_trailing_comma_in_singleline_lists = false
+resharper_arrange_trailing_comma_in_multiline_lists_highlighting = warning
+resharper_arrange_trailing_comma_in_singleline_lists_highlighting = warning
+dotnet_style_predefined_type_for_member_access = true:warning
+dotnet_style_predefined_type_for_locals_parameters_members = true:warning
+resharper_arrange_static_member_qualifier_highlighting = warning
+
+# Whitespace
+
+max_line_length = 100
+csharp_max_line_length = 100
+resharper_csharp_max_line_length = 100
+resharper_wrap_lines = true
+resharper_continuous_indent_multiplier = 2
+resharper_align_multiline_binary_expressions_chain = false
+resharper_align_multiline_statement_conditions = false
+csharp_new_line_before_open_brace = none
+csharp_new_line_before_else = false
+csharp_new_line_before_catch = false
+csharp_new_line_before_finally = false
+csharp_new_line_before_members_in_object_initializers = false
+csharp_new_line_before_members_in_anonymous_types = false
+csharp_new_line_between_query_expression_clauses = true
+resharper_blank_lines_after_block_statements = 0
+resharper_blank_lines_around_single_line_auto_property = 1
+resharper_blank_lines_around_single_line_property = 1
+resharper_csharp_blank_lines_around_field = 0
+resharper_csharp_blank_lines_around_single_line_invocable = 1
+resharper_csharp_blank_lines_inside_region = 0
+resharper_csharp_keep_blank_lines_in_code = 1
+resharper_csharp_keep_blank_lines_in_declarations = 1
+resharper_csharp_wrap_after_declaration_lpar = true
+resharper_csharp_wrap_after_invocation_lpar = true
+resharper_csharp_wrap_arguments_style = chop_if_long
+resharper_csharp_wrap_extends_list_style = chop_if_long
+resharper_csharp_wrap_parameters_style = chop_if_long
+resharper_keep_existing_declaration_parens_arrangement = false
+resharper_keep_existing_embedded_arrangement = false
+resharper_keep_existing_invocation_parens_arrangement = false
+resharper_keep_existing_property_patterns_arrangement = false
+resharper_keep_existing_switch_expression_arrangement = false
+resharper_max_array_initializer_elements_on_line = 3
+resharper_max_initializer_elements_on_line = 3
+resharper_place_accessorholder_attribute_on_same_line = false
+resharper_place_field_attribute_on_same_line = false
+resharper_place_simple_embedded_statement_on_same_line = false
+resharper_wrap_array_initializer_style = chop_if_long
+resharper_wrap_chained_method_calls = chop_if_long
+resharper_wrap_verbatim_interpolated_strings = wrap_if_long
+# Braces
+csharp_prefer_braces = true:silent
+resharper_braces_redundant = true
+resharper_csharp_empty_block_style = together_same_line
+resharper_enforce_do_while_statement_braces_highlighting = warning
+resharper_enforce_fixed_statement_braces_highlighting = warning
+resharper_enforce_foreach_statement_braces_highlighting = warning
+resharper_enforce_for_statement_braces_highlighting = warning
+resharper_enforce_if_statement_braces_highlighting = warning
+resharper_enforce_lock_statement_braces_highlighting = warning
+resharper_enforce_using_statement_braces_highlighting = warning
+resharper_enforce_while_statement_braces_highlighting = warning
+csharp_indent_case_contents = true
+csharp_indent_switch_labels = true
+csharp_indent_block_contents = true
+csharp_indent_braces = false
+csharp_indent_case_contents_when_block = false
+csharp_space_after_cast = false
+resharper_space_after_cast = false
+resharper_space_within_single_line_array_initializer_braces = true
+resharper_space_within_empty_braces = false
+csharp_space_before_comma = false
+csharp_space_after_comma = true
+csharp_space_after_dot = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+csharp_space_after_semicolon_in_for_statement = true
+csharp_space_before_semicolon_in_for_statement = false
+csharp_space_around_declaration_statements = false
+csharp_space_before_open_square_brackets = false
+csharp_space_between_empty_square_brackets = false
+csharp_space_between_square_brackets = false
+csharp_place_attribute_on_same_line = false
+resharper_place_attribute_on_same_line = false
+resharper_arrange_attributes_highlighting = warning
+csharp_force_attribute_style = Separate
+# Braces required even when optional
+csharp_braces_for_ifelse = required
+csharp_braces_for_for = required
+csharp_braces_for_foreach = required
+csharp_braces_for_while = required
+csharp_braces_for_dowhile = required
+csharp_braces_for_lock = required
+csharp_braces_for_fixed = required
+resharper_braces_for_for = required
+resharper_braces_for_foreach = required
+resharper_braces_for_ifelse = required
+resharper_braces_for_while = required
+resharper_braces_redundant = false
+resharper_keep_existing_declaration_block_arrangement = true
+resharper_keep_existing_embedded_block_arrangement = true
+# Async/await rules. These don't seem to fail the build in Rider even though they show up as errors
+# in the "Problems" box and in the code, but at least they are visually marked as errors.
+resharper_async_void_lambda_highlighting = error
+resharper_async_void_method_highlighting = error
+dotnet_diagnostic.AsyncFixer01.severity = none
+dotnet_diagnostic.AsyncFixer02.severity = error
+dotnet_diagnostic.AsyncFixer03.severity = error
+dotnet_diagnostic.AsyncFixer04.severity = error
+dotnet_diagnostic.AsyncFixer05.severity = error
+resharper_keep_existing_enum_arrangement = true
diff --git a/EPPlus/CellStore.cs b/EPPlus/CellStore.cs
index 9e05a06..c767a82 100644
--- a/EPPlus/CellStore.cs
+++ b/EPPlus/CellStore.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,1939 +13,1714 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
using System.Collections;
+using System.Collections.Generic;
using OfficeOpenXml;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
-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 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 {
+ internal IndexBase _searchIx = new();
+
+ public ColumnIndex() {
+ _pages = new PageIndex[CellStore<int>._pagesPerColumnMin];
+ PageCount = 0;
+ }
+
+ ~ColumnIndex() {
+ _pages = null;
+ }
+
+ 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;
}
- internal class IndexItem : IndexBase
- {
- internal int IndexPointer
- {
- get;
- set;
- }
- }
- internal class ColumnIndex : IndexBase
- {
- internal IndexBase _searchIx=new IndexBase();
- public ColumnIndex ()
- {
- _pages=new PageIndex[CellStore<int>.PagesPerColumnMin];
- PageCount=0;
- }
- ~ColumnIndex()
- {
- _pages=null;
- }
- 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;
- }
- else
- {
- var p = ~res;
-
- if (GetPage(Row, ref p))
- {
- return p;
- }
- else
- {
- return res;
- }
- }
- }
+ var p = ~res;
- private bool GetPage(int Row, ref int res)
- {
- if (res < PageCount && _pages[res].MinIndex <= Row && _pages[res].MaxIndex >= Row)
- {
- return true;
- }
- else
- {
- 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;
- //}
- }
- else 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;
- }
- else
- {
-
- if (_pages[p].IndexOffset + _pages[p].Rows[0].Index < row)
- {
- if (p + 1 >= PageCount)
- {
- return -1;
- }
- else
- {
- return _pages[p + 1].IndexOffset + _pages[p].Rows[0].Index;
- }
- }
- else
- {
- return _pages[p].IndexOffset + _pages[p].Rows[0].Index;
- }
- }
- }
- else
- {
- 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;
- }
- }
- }
- else
- {
- return -1;
- }
- }
- }
- internal int FindNext(int Page)
- {
- var p = GetPosition(Page);
- if (p < 0)
- {
- return ~p;
- }
- return p;
- }
- internal PageIndex[] _pages;
- internal int PageCount;
+ if (GetPage(row, ref p)) {
+ return p;
}
+ return res;
+ }
- internal class PageIndex : IndexBase
- {
- internal IndexBase _searchIx = new IndexBase();
- 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;
- }
- ~PageIndex()
- {
- Rows=null;
- }
- internal int Offset = 0;
- internal int IndexOffset
- {
- get
- {
- return IndexExpanded + (int)Offset;
- }
- }
- internal int IndexExpanded
- {
- get
- {
- return (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;
- }
- else
- {
- return -1;
- }
- }
- return o;
- }
-
- public int MinIndex
- {
- get
- {
- if (Rows.Length > 0)
- {
- return IndexOffset + Rows[0].Index;
- }
- else
- {
- return -1;
- }
- }
- }
- public int MaxIndex
- {
- get
- {
- if (RowCount > 0)
- {
- return IndexOffset + Rows[RowCount-1].Index;
- }
- else
- {
- return -1;
- }
- }
- }
- public int GetIndex(int pos)
- {
- return IndexOffset + Rows[pos].Index;
- }
+ private bool GetPage(int row, ref int res) {
+ if (res < PageCount && _pages[res].MinIndex <= row && _pages[res].MaxIndex >= row) {
+ return true;
}
- /// <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;
+ 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;
+ }
- List<T> _values = new List<T>();
- internal ColumnIndex[] _columnIndex;
- internal IndexBase _searchIx = new IndexBase();
- internal int ColumnCount;
- public CellStore ()
- {
- _columnIndex = new ColumnIndex[ColSizeMin];
- }
- ~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 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;
}
- internal CellStore<T> Clone()
- {
- int row,col;
- var ret=new CellStore<T>();
- for (int c = 0; c < ColumnCount; c++)
- {
- col = _columnIndex[c].Index;
- for (int p = 0;p < _columnIndex[c].PageCount; p++)
- {
- for (int r = 0; r < _columnIndex[c]._pages[p].RowCount; r++)
- {
- row = _columnIndex[c]._pages[p].IndexOffset + _columnIndex[c]._pages[p].Rows[r].Index;
- ret.SetValue(row, col, _values[_columnIndex[c]._pages[p].Rows[r].IndexPointer]);
- }
- }
- }
- return ret;
+ 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;
}
- internal int Count
- {
- get
- {
- int count=0;
- for (int c = 0; c < ColumnCount; c++)
- {
- for (int p = 0; p < _columnIndex[c].PageCount; p++)
- {
- count += _columnIndex[c]._pages[p].RowCount;
- }
- }
- return count;
- }
- }
- 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;
- }
- else
- {
- 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;
+ }
+ }
+ return -1;
+ }
- 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;
- }
- else
- {
- 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];
- }
- else
- {
- return default(T);
- }
- //var col = GetPosition(Column);
- //if (col >= 0)
- //{
- // var pos = _columnIndex[col].GetPosition(Row);
- // if (pos >= 0)
- // {
- // var pageItem = _columnIndex[col].Pages[pos];
- // if (pageItem.MinIndex > Row)
- // {
- // pos--;
- // if (pos < 0)
- // {
- // return default(T);
- // }
- // else
- // {
- // pageItem = _columnIndex[col].Pages[pos];
- // }
- // }
- // short ix = (short)(Row - pageItem.IndexOffset);
- // var cellPos = Array.BinarySearch(pageItem.Rows, 0, pageItem.RowCount, new IndexBase() { Index = ix });
- // if (cellPos >= 0)
- // {
- // return _values[pageItem.Rows[cellPos].IndexPointer];
- // }
- // else //Cell does not exist
- // {
- // return default(T);
- // }
- // }
- // else //Page does not exist
- // {
- // return default(T);
- // }
- //}
- //else //Column does not exist
- //{
- // return default(T);
- //}
- }
- 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;
- }
- else
- {
- 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;
- }
- else //Cell does not exist
- {
- return -1;
- }
- }
- else //Page does not exist
- {
- return -1;
- }
- }
- else //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;
- }
- else
- {
- return false;
- }
- }
- internal void SetValue(int Row, int Column, T Value)
- {
- lock (_columnIndex)
- {
- 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 Exception("Unexpected error when setting value"));
- }
- pageItem = _columnIndex[col]._pages[pos];
- }
+ internal int FindNext(int page) {
+ var p = GetPosition(page);
+ if (p < 0) {
+ return ~p;
+ }
+ return p;
+ }
- 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 PageIndex[] _pages;
+ internal int PageCount;
+}
+
+internal class PageIndex : IndexBase {
+ internal 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;
+ }
+
+ ~PageIndex() {
+ Rows = null;
+ }
+
+ 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;
+ internal IndexBase _searchIx = new();
+ internal int ColumnCount;
+
+ public CellStore() {
+ _columnIndex = new ColumnIndex[_colSizeMin];
+ }
+
+ ~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 CellStore<T> Clone() {
+ int row,
+ col;
+ var ret = new CellStore<T>();
+ for (int c = 0; c < ColumnCount; c++) {
+ col = _columnIndex[c].Index;
+ for (int p = 0; p < _columnIndex[c].PageCount; p++) {
+ for (int r = 0; r < _columnIndex[c]._pages[p].RowCount; r++) {
+ row = _columnIndex[c]._pages[p].IndexOffset + _columnIndex[c]._pages[p].Rows[r].Index;
+ ret.SetValue(row, col, _values[_columnIndex[c]._pages[p].Rows[r].IndexPointer]);
+ }
+ }
+ }
+ return ret;
+ }
+
+ internal int Count {
+ get {
+ int count = 0;
+ for (int c = 0; c < ColumnCount; c++) {
+ for (int p = 0; p < _columnIndex[c].PageCount; p++) {
+ count += _columnIndex[c]._pages[p].RowCount;
+ }
+ }
+ return count;
+ }
+ }
+
+ 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);
+ //var col = GetPosition(Column);
+ //if (col >= 0)
+ //{
+ // var pos = _columnIndex[col].GetPosition(Row);
+ // if (pos >= 0)
+ // {
+ // var pageItem = _columnIndex[col].Pages[pos];
+ // if (pageItem.MinIndex > Row)
+ // {
+ // pos--;
+ // if (pos < 0)
+ // {
+ // return default(T);
+ // }
+ // else
+ // {
+ // pageItem = _columnIndex[col].Pages[pos];
+ // }
+ // }
+ // short ix = (short)(Row - pageItem.IndexOffset);
+ // var cellPos = Array.BinarySearch(pageItem.Rows, 0, pageItem.RowCount, new IndexBase() { Index = ix });
+ // if (cellPos >= 0)
+ // {
+ // return _values[pageItem.Rows[cellPos].IndexPointer];
+ // }
+ // else //Cell does not exist
+ // {
+ // return default(T);
+ // }
+ // }
+ // else //Page does not exist
+ // {
+ // return default(T);
+ // }
+ //}
+ //else //Column does not exist
+ //{
+ // 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) {
+ lock (_columnIndex) {
+ 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];
}
- internal void Insert(int fromRow, int fromCol, int rows, int columns)
- {
- lock (_columnIndex)
- {
+ 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);
+ }
+ }
+ }
- if (columns > 0)
- {
- var col = GetPosition(fromCol);
- if (col < 0)
- {
- col = ~col;
+ internal void Insert(int fromRow, int fromCol, int rows, int columns) {
+ lock (_columnIndex) {
+ 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) {
+ lock (_columnIndex) {
+ 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);
+ delEndRow = DeleteCells(
+ column._pages[pagePos],
+ fr,
+ shift ? fr + rowsLeft : endRow,
+ shift);
+ if (shift) {
+ UpdatePageOffset(column, pagePos, rowsLeft);
}
- 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);
- }
- }
+ } 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);
+ }
+ }
}
+ }
}
- internal void Clear(int fromRow, int fromCol, int rows, int columns)
- {
- Delete(fromRow, fromCol, rows, columns, false);
+ }
+ }
+ }
+
+ 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;
}
- 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)
- {
- lock (_columnIndex)
- {
- 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);
- delEndRow = 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???
- {
- rows=ResetPageOffset(column, pagePos, rows);
- ////MergePages
- //if (column.Pages[pagePos - 1].Index + 1 == column.Pages[pagePos].Index)
- //{
- // if (column.Pages[pagePos].IndexOffset + column.Pages[pagePos].Rows[column.Pages[pagePos].RowCount - 1].Index + rows -
- // column.Pages[pagePos - 1].IndexOffset + column.Pages[pagePos - 1].Rows[0].Index <= PageSize)
- // {
- // //Merge
- // MergePage(column, pagePos - 1, -rows);
- // }
- // else
- // {
- // //Split
- // }
- //}
- //rows -= PageSize;
- //for (int p = pagePos; p < column.PageCount; p++)
- //{
- // column.Pages[p].Index -= 1;
- //}
- return;
- }
- }
- }
-
- private int 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);
- //var newPage = new PageIndex(toPage, 0, GetSize(fromPage.RowCount + toPage.RowCount));
- //newPage.RowCount = fromPage.RowCount + fromPage.RowCount;
- //Array.Copy(toPage.Rows, 0, newPage.Rows, 0, toPage.RowCount);
- //Array.Copy(fromPage.Rows, 0, newPage.Rows, toPage.RowCount, fromPage.RowCount);
- //for (int r = toPage.RowCount; r < newPage.RowCount; r++)
- //{
- // newPage.Rows[r].Index += (short)(fromPage.IndexOffset - toPage.IndexOffset);
- //}
-
- }
- }
- 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;
- }
- }
- return rows;
- }
-
- 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;
- }
- else
- {
- 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;
- }
- }
- else 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 (_columnIndex[fPos].Index < ColumnCount)
- //{
- 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 = +(int)(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;
- }
- else
- {
- 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 PageIndex(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 IndexItem() { 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;
- }
- //else if (page.Rows[0].Index >= PageSize) //Delete
- //{
- // page.Index++;
- // AddPageRowOffset(page, -PageSize);
- //}
- //else if (page.Rows[0].Index <= -PageSize) //Delete
- //{
- // page.Index--;
- // AddPageRowOffset(page, PageSize);
- //}
- return page;
- }
-
- private void AddPageRowOffset(PageIndex page, short offset)
- {
- for (int r = 0; r < page.RowCount; r++)
- {
- page.Rows[r].Index += offset;
- }
- }
- private void AddPage(ColumnIndex column, int pos, short index)
- {
- AddPage(column, pos);
- column._pages[pos] = new PageIndex() { 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 ColumnIndex() { Index = (short)(Column) };
- ColumnCount++;
- }
- int _colPos = -1, _row;
- public ulong Current
- {
- get
- {
- return ((ulong)_row << 32) | (uint)(_columnIndex[_colPos].Index);
- }
- }
-
- //object IEnumerator.Current
+ if (Math.Abs(column._pages[pagePos].Offset) > _pageSize
+ || Math.Abs(column._pages[pagePos].Rows[column._pages[pagePos].RowCount - 1].Index)
+ > _pageSizeMax) //Split or Merge???
+ {
+ rows = ResetPageOffset(column, pagePos, rows);
+ ////MergePages
+ //if (column.Pages[pagePos - 1].Index + 1 == column.Pages[pagePos].Index)
//{
- // get
+ // if (column.Pages[pagePos].IndexOffset + column.Pages[pagePos].Rows[column.Pages[pagePos].RowCount - 1].Index + rows -
+ // column.Pages[pagePos - 1].IndexOffset + column.Pages[pagePos - 1].Rows[0].Index <= PageSize)
// {
- // return GetValue(_row+1, _columnIndex[_colPos].Index);
+ // //Merge
+ // MergePage(column, pagePos - 1, -rows);
+ // }
+ // else
+ // {
+ // //Split
// }
//}
- public bool MoveNext()
- {
- return GetNextCell(ref _row, ref _colPos, 0, ExcelPackage.MaxRows, ExcelPackage.MaxColumns);
- }
- 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);
- }
- else
- {
- var r=GetNextCell(ref row, ref c, minColPos, maxRow, maxColPos);
- col = _columnIndex[c].Index;
- return r;
- }
- }
- else
- {
- c=~c;
- if (c > _columnIndex[c].Index)
- {
- if (col <= minColPos)
- {
- return false;
- }
- col = minColPos;
- return NextCell(ref row, ref col, minRow, minColPos, maxRow, maxColPos);
- }
- else
- {
- 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;
- }
- else
- {
- if (++colPos < ColumnCount && colPos <=endColPos)
- {
- var r = _columnIndex[colPos].GetNextRow(row);
- if (r == row) //Exists next Row
- {
- return true;
- }
- else
- {
- int minRow, minCol;
- if (r > row)
- {
- minRow = r;
- minCol = colPos;
- }
- else
- {
- minRow = int.MaxValue;
- minCol = 0;
- }
+ //rows -= PageSize;
+ //for (int p = pagePos; p < column.PageCount; p++)
+ //{
+ // column.Pages[p].Index -= 1;
+ //}
+ }
+ }
+ }
- 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;
- }
- else
- {
- row = minRow;
- colPos = minCol;
- return true;
- }
- }
- }
- else
- {
- if (colPos <= startColPos || row>=endRow)
- {
- return false;
- }
- colPos = startColPos - 1;
- row++;
- return GetNextCell(ref row, ref colPos, startColPos, endRow, endColPos);
- }
- }
+ private int 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);
+ //var newPage = new PageIndex(toPage, 0, GetSize(fromPage.RowCount + toPage.RowCount));
+ //newPage.RowCount = fromPage.RowCount + fromPage.RowCount;
+ //Array.Copy(toPage.Rows, 0, newPage.Rows, 0, toPage.RowCount);
+ //Array.Copy(fromPage.Rows, 0, newPage.Rows, toPage.RowCount, fromPage.RowCount);
+ //for (int r = toPage.RowCount; r < newPage.RowCount; r++)
+ //{
+ // newPage.Rows[r].Index += (short)(fromPage.IndexOffset - toPage.IndexOffset);
+ //}
}
- internal bool GetNextCell(ref int row, ref int colPos, int startColPos, int endRow, int endColPos, ref int[] pagePos, ref int[] cellPos)
- {
- if (colPos == endColPos)
- {
- colPos = startColPos;
- row++;
- }
- else
- {
- colPos++;
- }
+ } 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;
+ }
+ }
+ return rows;
+ }
- if (pagePos[colPos] < 0)
- {
- if(pagePos[colPos]==-1)
- {
- pagePos[colPos] = _columnIndex[colPos].GetPosition(row);
- }
- }
- else if (_columnIndex[colPos]._pages[pagePos[colPos]].RowCount <= row)
- {
- if (_columnIndex[colPos].PageCount > pagePos[colPos])
- pagePos[colPos]++;
- else
- {
- pagePos[colPos]=-2;
- }
- }
-
- var r = _columnIndex[colPos]._pages[pagePos[colPos]].IndexOffset + _columnIndex[colPos]._pages[pagePos[colPos]].Rows[cellPos[colPos]].Index;
- if (r == row)
- {
- row = r;
- }
- else
- {
- }
+ 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 (_columnIndex[fPos].Index < ColumnCount)
+ //{
+ 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;
+ }
+ //else if (page.Rows[0].Index >= PageSize) //Delete
+ //{
+ // page.Index++;
+ // AddPageRowOffset(page, -PageSize);
+ //}
+ //else if (page.Rows[0].Index <= -PageSize) //Delete
+ //{
+ // page.Index--;
+ // AddPageRowOffset(page, PageSize);
+ //}
+ return page;
+ }
+
+ private void AddPageRowOffset(PageIndex page, short offset) {
+ for (int r = 0; r < page.RowCount; r++) {
+ page.Rows[r].Index += offset;
+ }
+ }
+
+ 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++;
+ }
+
+ private int _colPos = -1,
+ _row;
+
+ public ulong Current => ((ulong)_row << 32) | (uint)(_columnIndex[_colPos].Index);
+
+ //object IEnumerator.Current
+ //{
+ // get
+ // {
+ // return GetValue(_row+1, _columnIndex[_colPos].Index);
+ // }
+ //}
+ public bool MoveNext() {
+ return GetNextCell(ref _row, ref _colPos, 0, ExcelPackage.MaxRows, ExcelPackage.MaxColumns);
+ }
+
+ 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++;
}
- internal bool PrevCell(ref int row, ref int col)
- {
- return PrevCell(ref row, ref col, 0, 0, ExcelPackage.MaxRows, ExcelPackage.MaxColumns);
- }
- internal 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);
- }
- else
- {
- var ret=GetPrevCell(ref row, ref c, minRow, minColPos, maxColPos);
- if (ret)
- {
- col = _columnIndex[c].Index;
- }
- return ret;
- }
- }
- else
- {
- 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);
- }
- else
- {
- 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;
- }
- else
- {
- if (--colPos >= startColPos)
-// if (++colPos < ColumnCount && colPos <= endColPos)
- {
- var r = _columnIndex[colPos].GetNextRow(row);
- if (r == row) //Exists next Row
- {
- return true;
- }
- else
- {
- 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;
- }
- else
- {
- row = minRow;
- colPos = minCol;
- return true;
- }
- }
- }
- else
- {
- colPos = ColumnCount;
- row--;
- if (row < startRow)
- {
- Reset();
- return false;
- }
- else
- {
- return GetPrevCell(ref colPos, ref row, startRow, startColPos, endColPos);
- }
- }
- }
- }
- public void Reset()
- {
- _colPos = -1;
- _row= 0;
- }
-
- //public IEnumerator<ulong> GetEnumerator()
- //{
- // this.Reset();
- // return this;
- //}
-
- //IEnumerator IEnumerable.GetEnumerator()
- //{
- // this.Reset();
- // return this;
- //}
-
+ if (minRow == int.MaxValue || minRow > endRow) {
+ return false;
+ }
+ row = minRow;
+ colPos = minCol;
+ return true;
}
- internal class CellsStoreEnumerator<T> : IEnumerable<T>, IEnumerator<T>
+ if (colPos <= startColPos || row >= endRow) {
+ return false;
+ }
+ colPos = startColPos - 1;
+ row++;
+ return GetNextCell(ref row, ref colPos, startColPos, endRow, endColPos);
+ }
+
+ internal bool GetNextCell(
+ ref int row,
+ ref int colPos,
+ int startColPos,
+ int endRow,
+ int endColPos,
+ ref int[] pagePos,
+ ref int[] cellPos) {
+ if (colPos == endColPos) {
+ colPos = startColPos;
+ row++;
+ } else {
+ colPos++;
+ }
+
+ if (pagePos[colPos] < 0) {
+ if (pagePos[colPos] == -1) {
+ pagePos[colPos] = _columnIndex[colPos].GetPosition(row);
+ }
+ } else if (_columnIndex[colPos]._pages[pagePos[colPos]].RowCount <= row) {
+ if (_columnIndex[colPos].PageCount > pagePos[colPos]) {
+ pagePos[colPos]++;
+ } else {
+ pagePos[colPos] = -2;
+ }
+ }
+
+ var r =
+ _columnIndex[colPos]._pages[pagePos[colPos]].IndexOffset
+ + _columnIndex[colPos]._pages[pagePos[colPos]].Rows[cellPos[colPos]].Index;
+ if (r == row) {
+ row = r;
+ }
+ return true;
+ }
+
+ internal bool PrevCell(ref int row, ref int col) {
+ return PrevCell(ref row, ref col, 0, 0, ExcelPackage.MaxRows, ExcelPackage.MaxColumns);
+ }
+
+ internal 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);
+ }
{
- CellStore<T> _cellStore;
- int row, colPos;
- int[] pagePos, cellPos;
- int _startRow, _startCol, _endRow, _endCol;
- 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
- {
- get
- {
- return row;
- }
- }
- internal int Column
- {
- get
- {
- if (colPos == -1) MoveNext();
- if (colPos == -1) return 0;
- return _cellStore._columnIndex[colPos].Index;
- }
- }
- internal T Value
- {
- get
- {
- lock (_cellStore)
- {
- return _cellStore.GetValue(row, Column);
- }
- }
- set
- {
- lock (_cellStore)
- {
- _cellStore.SetValue(row, Column, value);
- }
- }
- }
- internal bool Next()
- {
- //return _cellStore.GetNextCell(ref row, ref colPos, minColPos, maxRow, maxColPos);
- return _cellStore.GetNextCell(ref row, ref colPos, minColPos, maxRow, maxColPos);
- }
- internal bool Previous()
- {
- lock (_cellStore)
- {
- return _cellStore.GetPrevCell(ref row, ref colPos, minRow, minColPos, maxColPos);
- }
- }
-
- public string CellAddress
- {
- get
- {
- return ExcelAddressBase.GetAddress(Row, Column);
- }
- }
-
- public IEnumerator<T> GetEnumerator()
- {
- Reset();
- return this;
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- Reset();
- return this;
- }
-
- public T Current
- {
- get
- {
- return Value;
- }
- }
-
- public void Dispose() { }
-
- object IEnumerator.Current
- {
- get
- {
- Reset();
- return this;
- }
- }
-
- public bool MoveNext()
- {
- return Next();
- }
-
- public void Reset()
- {
- Init();
- }
+ var ret = GetPrevCell(ref row, ref c, minRow, minColPos, maxColPos);
+ if (ret) {
+ col = _columnIndex[c].Index;
+ }
+ return ret;
}
- internal class FlagCellStore : CellStore<byte>
+ }
+
+ 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)
{
- 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
- }
+ 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--;
}
- internal bool GetFlagValue(int Row, int Col, CellFlags cellFlags)
- {
- return !(((byte)cellFlags & GetValue(Row, Col)) == 0);
+ }
+ 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) {
+ Reset();
+ return false;
+ }
+ return GetPrevCell(ref colPos, ref row, startRow, startColPos, endColPos);
+ }
+
+ public void Reset() {
+ _colPos = -1;
+ _row = 0;
+ }
+
+ //public IEnumerator<ulong> GetEnumerator()
+ //{
+ // this.Reset();
+ // return this;
+ //}
+
+ //IEnumerator IEnumerable.GetEnumerator()
+ //{
+ // this.Reset();
+ // return this;
+ //}
+}
+
+internal class CellsStoreEnumerator<T> : IEnumerable<T>, IEnumerator<T> {
+ private CellStore<T> _cellStore;
+ private int row,
+ colPos;
+ private int[] pagePos,
+ cellPos;
+ private int _startRow,
+ _startCol,
+ _endRow,
+ _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 {
+ lock (_cellStore) {
+ return _cellStore.GetValue(row, Column);
+ }
+ }
+ set {
+ lock (_cellStore) {
+ _cellStore.SetValue(row, Column, value);
+ }
+ }
+ }
+
+ internal bool Next() {
+ //return _cellStore.GetNextCell(ref row, ref colPos, minColPos, maxRow, maxColPos);
+ return _cellStore.GetNextCell(ref row, ref colPos, minColPos, maxRow, maxColPos);
+ }
+
+ internal bool Previous() {
+ lock (_cellStore) {
+ return _cellStore.GetPrevCell(ref row, ref colPos, minRow, minColPos, 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/CF Implementation.cs b/EPPlus/ConditionalFormatting/CF Implementation.cs
deleted file mode 100644
index 137d3c4..0000000
--- a/EPPlus/ConditionalFormatting/CF Implementation.cs
+++ /dev/null
@@ -1,392 +0,0 @@
-#region TODO
-//TODO: Add the "DataBar" extended options
-//TODO: Add tests for all the rules
-//TODO: Add the IconSet options
-//TODO: Add all the "extList" options
-#endregion
-
-#region §18.3.1.18 conditionalFormatting (Conditional Formatting)
-//Childs:
-//cfRule (Conditional Formatting Rule) §18.3.1.10
-//extLst (Future Feature Data Storage Area) §18.2.10
-
-//Attributes:
-//pivot
-//sqref ST_Sqref simple type (§18.18.76)
-#endregion
-
-#region §18.3.1.10 cfRule (Conditional Formatting Rule)
-//Childs:
-//colorScale (Color Scale) §18.3.1.16
-//dataBar (Data Bar) §18.3.1.28
-//extLst (Future Feature Data Storage Area) §18.2.10
-//formula (Formula) §18.3.1.43
-//iconSet (Icon Set) §18.3.1.49
-
-//Attributes:
-//-----------
-//priority (Priority) 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.
-//stopIfTrue (Stop If True) If this flag is 1, no rules with lower priority shall be applied over this rule, when this rule
-// evaluates to true.
-//type (Type) Type of conditional formatting rule. ST_CfType §18.18.12.
-//aboveAverage Indicates whether the rule is an "above average" rule. 1 indicates 'above average'.
-// This attribute is ignored if type is not equal to aboveAverage.
-//equalAverage (Equal Average)
-// Flag indicating whether the 'aboveAverage' and 'belowAverage' criteria is inclusive of the
-// average itself, or exclusive of that value. 1 indicates to include the average value in the
-// criteria. This attribute is ignored if type is not equal to aboveAverage.
-//bottom (Bottom N) Indicates whether a "top/bottom n" rule is a "bottom n" rule. 1 indicates 'bottom'.
-// This attribute is ignored if type is not equal to top10.
-//dxfId (Differential Formatting Id)
-// 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. ST_DxfId simple type (§18.18.25).
-//operator (Operator) The operator in a "cell value is" conditional formatting rule. This attribute is ignored if
-// type is not equal to cellIs. The possible values ST_ConditionalFormattingOperator simple type (§18.18.15).
-//percent (Top 10 Percent)
-// Indicates whether a "top/bottom n" rule is a "top/bottom n percent" rule. This attribute
-// is ignored if type is not equal to top10.
-//rank (Rank) The value of "n" in a "top/bottom n" conditional formatting rule. This attribute is ignored
-// if type is not equal to top10.
-//stdDev (StdDev) The number of standard deviations to include above or below the average in the
-// conditional formatting rule. This attribute is ignored if type is not equal to aboveAverage.
-// If a value is present for stdDev and the rule type = aboveAverage, then this rule is automatically an
-// "above or below N standard deviations" rule.
-//text (Text) The text value in a "text contains" conditional formatting rule. This attribute is ignored if
-// type is not equal to containsText.
-//timePeriod (Time Period) The applicable time period in a "date occurring…" conditional formatting rule. This
-// attribute is ignored if type is not equal to timePeriod. ST_TimePeriod §18.18.82.
-#endregion
-
-#region Conditional Formatting XML examples
-// All the examples are assumed to be inside <conditionalFormatting sqref="A1:A10">
-
-#region Example "beginsWith"
-//<x:cfRule type="beginsWith" dxfId="6" priority="5" operator="beginsWith" text="a">
-// <x:formula>LEFT(A1,LEN("a"))="a"</x:formula>
-//</x:cfRule>
-
-//<x:cfRule type="beginsWith" dxfId="5" priority="14" operator="beginsWith" text=""<>">
-// <x:formula>LEFT(A3,LEN("""<>"))="""<>"</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "between"
-//<x:cfRule type="cellIs" dxfId="8" priority="10" operator="between">
-// <x:formula>3</x:formula>
-// <x:formula>7</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "containsText"
-//<x:cfRule type="containsText" dxfId="5" priority="4" operator="containsText" text="c">
-// <x:formula>NOT(ISERROR(SEARCH("c",A1)))</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "endsWith"
-//<x:cfRule type="endsWith" dxfId="9" priority="11" operator="endsWith" text="c">
-// <x:formula>RIGHT(A1,LEN("c"))="c"</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "equal"
-//<x:cfRule type="cellIs" dxfId="7" priority="8" operator="equal">
-// <x:formula>"ab"</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "greaterThan"
-//<x:cfRule type="cellIs" dxfId="6" priority="7" operator="greaterThan">
-// <x:formula>4</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "greaterThanOrEqual"
-//<x:cfRule type="cellIs" dxfId="3" priority="4" operator="greaterThanOrEqual">
-// <x:formula>4</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "lessThan"
-//<x:cfRule type="cellIs" dxfId="5" priority="6" operator="lessThan">
-// <x:formula>4</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "lessThanOrEqual"
-//<x:cfRule type="cellIs" dxfId="4" priority="5" operator="lessThanOrEqual">
-// <x:formula>4</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "notBetween"
-//<x:cfRule type="cellIs" dxfId="2" priority="3" operator="notBetween">
-// <x:formula>3</x:formula>
-// <x:formula>7</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "notContainsText"
-//<x:cfRule type="notContainsText" dxfId="4" priority="3" operator="notContains" text="c">
-// <x:formula>ISERROR(SEARCH("c",A1))</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "notEqual"
-//<x:cfRule type="cellIs" dxfId="1" priority="2" operator="notEqual">
-// <x:formula>"ab"</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "containsBlanks"
-//<x:cfRule type="containsBlanks" dxfId="20" priority="37">
-// <x:formula>LEN(TRIM(A1))=0</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "containsErrors"
-//<x:cfRule type="containsErrors" dxfId="15" priority="19">
-// <x:formula>ISERROR(A1)</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "expression"
-//<x:cfRule type="expression" dxfId="0" priority="1">
-// <x:formula>RIGHT(J16,1)="b"</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "duplicateValues"
-//<x:cfRule type="duplicateValues" dxfId="14" priority="16" />
-#endregion
-
-#region Example "notContainsBlanks"
-//<x:cfRule type="notContainsBlanks" dxfId="12" priority="14">
-// <x:formula>LEN(TRIM(A1))>0</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "notContainsErrors"
-//<x:cfRule type="notContainsErrors" dxfId="11" priority="36">
-// <x:formula>NOT(ISERROR(A1))</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "uniqueValues"
-//<x:cfRule type="uniqueValues" dxfId="13" priority="15" />
-#endregion
-
-#region Example "last7Days"
-//<x:cfRule type="timePeriod" dxfId="39" priority="10" timePeriod="last7Days">
-// <x:formula>AND(TODAY()-FLOOR(A1,1)<=6,FLOOR(A1,1)<=TODAY())</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "lastMonth"
-//<x:cfRule type="timePeriod" dxfId="38" priority="9" timePeriod="lastMonth">
-// <x:formula>AND(MONTH(A1)=MONTH(EDATE(TODAY(),0-1)),YEAR(A1)=YEAR(EDATE(TODAY(),0-1)))</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "lastWeek"
-//<x:cfRule type="timePeriod" dxfId="37" priority="8" timePeriod="lastWeek">
-// <x:formula>AND(TODAY()-ROUNDDOWN(A1,0)>=(WEEKDAY(TODAY())),TODAY()-ROUNDDOWN(A1,0)<(WEEKDAY(TODAY())+7))</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "nextMonth"
-//<x:cfRule type="timePeriod" dxfId="36" priority="7" timePeriod="nextMonth">
-// <x:formula>AND(MONTH(A1)=MONTH(EDATE(TODAY(),0+1)),YEAR(A1)=YEAR(EDATE(TODAY(),0+1)))</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "nextWeek"
-//<x:cfRule type="timePeriod" dxfId="35" priority="6" timePeriod="nextWeek">
-// <x:formula>AND(ROUNDDOWN(A1,0)-TODAY()>(7-WEEKDAY(TODAY())),ROUNDDOWN(A1,0)-TODAY()<(15-WEEKDAY(TODAY())))</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "thisMonth"
-//<x:cfRule type="timePeriod" dxfId="34" priority="5" timePeriod="thisMonth">
-// <x:formula>AND(MONTH(A1)=MONTH(TODAY()),YEAR(A1)=YEAR(TODAY()))</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "thisWeek"
-//<x:cfRule type="timePeriod" dxfId="33" priority="4" timePeriod="thisWeek">
-// <x:formula>AND(TODAY()-ROUNDDOWN(A1,0)<=WEEKDAY(TODAY())-1,ROUNDDOWN(A1,0)-TODAY()<=7-WEEKDAY(TODAY()))</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "today"
-//<x:cfRule type="timePeriod" dxfId="32" priority="3" timePeriod="today">
-// <x:formula>FLOOR(A1,1)=TODAY()</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "tomorrow"
-//<x:cfRule type="timePeriod" dxfId="31" priority="2" timePeriod="tomorrow">
-// <x:formula>FLOOR(A1,1)=TODAY()+1</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "yesterday"
-//<x:cfRule type="timePeriod" dxfId="1" priority="1" timePeriod="yesterday">
-// <x:formula>FLOOR(A1,1)=TODAY()-1</x:formula>
-//</x:cfRule>
-#endregion
-
-#region Example "twoColorScale"
-//<cfRule type="colorScale" priority="1">
-// <colorScale>
-// <cfvo type="min"/>
-// <cfvo type="max"/>
-// <color rgb="FFF8696B"/>
-// <color rgb="FF63BE7B"/>
-// </colorScale>
-//</cfRule>
-#endregion
-
-#region Examples "iconSet3" (x all the 3 IconSet options)
-//<x:cfRule type="iconSet" priority="30">
-// <x:iconSet>
-// <x:cfvo type="percent" val="0" />
-// <x:cfvo type="percent" val="33" />
-// <x:cfvo type="percent" val="67" />
-// </x:iconSet>
-//</x:cfRule>
-
-//<x:cfRule type="iconSet" priority="38">
-// <x:iconSet iconSet="3Arrows">
-// <x:cfvo type="percent" val="0" />
-// <x:cfvo type="percent" val="33" />
-// <x:cfvo type="percent" val="67" />
-// </x:iconSet>
-//</x:cfRule>
-#endregion
-
-#region Examples "iconSet4" (x all the 4 IconSet options)
-//<x:cfRule type="iconSet" priority="34">
-// <x:iconSet iconSet="4ArrowsGray">
-// <x:cfvo type="percent" val="0" />
-// <x:cfvo type="percent" val="25" />
-// <x:cfvo type="percent" val="50" />
-// <x:cfvo type="percent" val="75" />
-// </x:iconSet>
-//</x:cfRule>
-#endregion
-
-#region Examples "iconSet5" (x all the 5 IconSet options)
-//<x:cfRule type="iconSet" priority="32">
-// <x:iconSet iconSet="5ArrowsGray">
-// <x:cfvo type="percent" val="0" />
-// <x:cfvo type="percent" val="20" />
-// <x:cfvo type="percent" val="40" />
-// <x:cfvo type="percent" val="60" />
-// <x:cfvo type="percent" val="80" />
-// </x:iconSet>
-//</x:cfRule>
-#endregion
-
-#region Examples "iconSet" Extended (not implemented yet)
-//<x:extLst>
-// <x:ext xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" uri="{78C0D931-6437-407d-A8EE-F0AAD7539E65}">
-// <x14:conditionalFormattings>
-// <x14:conditionalFormatting xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main">
-// <x14:cfRule type="iconSet" priority="35" id="{F5114369-080A-47E6-B7EE-499137A3C896}">
-// <x14:iconSet iconSet="3Triangles">
-// <x14:cfvo type="percent">
-// <xm:f>0</xm:f>
-// </x14:cfvo>
-// <x14:cfvo type="percent">
-// <xm:f>33</xm:f>
-// </x14:cfvo>
-// <x14:cfvo type="percent">
-// <xm:f>67</xm:f>
-// </x14:cfvo>
-// </x14:iconSet>
-// </x14:cfRule>
-// <xm:sqref>C3:C12</xm:sqref>
-// </x14:conditionalFormatting>
-// <x14:conditionalFormatting xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main">
-// <x14:cfRule type="iconSet" priority="6" id="{0A327384-BF2F-4BF5-9767-123CD690A536}">
-// <x14:iconSet iconSet="3Stars">
-// <x14:cfvo type="percent">
-// <xm:f>0</xm:f>
-// </x14:cfvo>
-// <x14:cfvo type="percent">
-// <xm:f>33</xm:f>
-// </x14:cfvo>
-// <x14:cfvo type="percent">
-// <xm:f>67</xm:f>
-// </x14:cfvo>
-// </x14:iconSet>
-// </x14:cfRule>
-// <xm:sqref>A16:A25</xm:sqref>
-// </x14:conditionalFormatting>
-// <x14:conditionalFormatting xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main">
-// <x14:cfRule type="iconSet" priority="19" id="{0DDCA3E4-3536-44B3-A663-4877587295B8}">
-// <x14:iconSet iconSet="3Triangles">
-// <x14:cfvo type="percent">
-// <xm:f>0</xm:f>
-// </x14:cfvo>
-// <x14:cfvo type="percent">
-// <xm:f>33</xm:f>
-// </x14:cfvo>
-// <x14:cfvo type="percent">
-// <xm:f>67</xm:f>
-// </x14:cfvo>
-// </x14:iconSet>
-// </x14:cfRule>
-// <xm:sqref>C16:C25</xm:sqref>
-// </x14:conditionalFormatting>
-// <x14:conditionalFormatting xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main">
-// <x14:cfRule type="iconSet" priority="2" id="{E4EDD7FB-880C-408F-B87C-C8DA446AEB78}">
-// <x14:iconSet iconSet="5Boxes">
-// <x14:cfvo type="percent">
-// <xm:f>0</xm:f>
-// </x14:cfvo>
-// <x14:cfvo type="percent">
-// <xm:f>20</xm:f>
-// </x14:cfvo>
-// <x14:cfvo type="percent">
-// <xm:f>40</xm:f>
-// </x14:cfvo>
-// <x14:cfvo type="percent">
-// <xm:f>60</xm:f>
-// </x14:cfvo>
-// <x14:cfvo type="percent">
-// <xm:f>80</xm:f>
-// </x14:cfvo>
-// </x14:iconSet>
-// </x14:cfRule>
-// <xm:sqref>E16:E25</xm:sqref>
-// </x14:conditionalFormatting>
-// <x14:conditionalFormatting xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main">
-// <x14:cfRule type="iconSet" priority="1" id="{4CC82060-CB0A-4A31-AEF2-D1A587AC1674}">
-// <x14:iconSet iconSet="3Stars" showValue="0" custom="1">
-// <x14:cfvo type="percent">
-// <xm:f>0</xm:f>
-// </x14:cfvo>
-// <x14:cfvo type="formula">
-// <xm:f>$F$17</xm:f>
-// </x14:cfvo>
-// <x14:cfvo type="num">
-// <xm:f>4</xm:f>
-// </x14:cfvo>
-// <x14:cfIcon iconSet="3Triangles" iconId="1" />
-// <x14:cfIcon iconSet="4RedToBlack" iconId="3" />
-// <x14:cfIcon iconSet="3Stars" iconId="2" />
-// </x14:iconSet>
-// </x14:cfRule>
-// <xm:sqref>F16:F25</xm:sqref>
-// </x14:conditionalFormatting>
-// </x14:conditionalFormattings>
-// </x:ext>
-//</x:extLst>
-#endregion
-
-
-#endregion
\ No newline at end of file
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingAverageGroup.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingAverageGroup.cs
index da5bc83..77efc3f 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingAverageGroup.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingAverageGroup.cs
@@ -13,37 +13,25 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingAverageGroup
- /// </summary>
- public interface IExcelConditionalFormattingAverageGroup
- : IExcelConditionalFormattingRule
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
+/// <summary>
+/// IExcelConditionalFormattingAverageGroup
+/// </summary>
+public interface IExcelConditionalFormattingAverageGroup : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBeginsWith.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBeginsWith.cs
index 91bc11b..8bc7c8f 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBeginsWith.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBeginsWith.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingBeginsWith
- /// </summary>
- public interface IExcelConditionalFormattingBeginsWith
+/// <summary>
+/// IExcelConditionalFormattingBeginsWith
+/// </summary>
+public interface IExcelConditionalFormattingBeginsWith
: IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithText
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ IExcelConditionalFormattingWithText {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBetween.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBetween.cs
index 86895a8..6d56a9e 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBetween.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingBetween.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingBetween
- /// </summary>
- public interface IExcelConditionalFormattingBetween
+/// <summary>
+/// IExcelConditionalFormattingBetween
+/// </summary>
+public interface IExcelConditionalFormattingBetween
: IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula2
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ IExcelConditionalFormattingWithFormula2 {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingColorScaleGroup.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingColorScaleGroup.cs
index 4276211..8f33fc0 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingColorScaleGroup.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingColorScaleGroup.cs
@@ -13,37 +13,25 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingColorScaleGroup
- /// </summary>
- public interface IExcelConditionalFormattingColorScaleGroup
- : IExcelConditionalFormattingRule
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+/// <summary>
+/// IExcelConditionalFormattingColorScaleGroup
+/// </summary>
+public interface IExcelConditionalFormattingColorScaleGroup : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsBlanks.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsBlanks.cs
index 7381e32..4d05109 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsBlanks.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsBlanks.cs
@@ -13,37 +13,25 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingContainsBlanks
- /// </summary>
- public interface IExcelConditionalFormattingContainsBlanks
- : IExcelConditionalFormattingRule
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+/// <summary>
+/// IExcelConditionalFormattingContainsBlanks
+/// </summary>
+public interface IExcelConditionalFormattingContainsBlanks : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsErrors.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsErrors.cs
index 37fe317..a668e11 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsErrors.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsErrors.cs
@@ -13,37 +13,25 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingContainsErrors
- /// </summary>
- public interface IExcelConditionalFormattingContainsErrors
- : IExcelConditionalFormattingRule
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+/// <summary>
+/// IExcelConditionalFormattingContainsErrors
+/// </summary>
+public interface IExcelConditionalFormattingContainsErrors : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsText.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsText.cs
index 069b9c8..5919f90 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsText.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingContainsText.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingContainsText
- /// </summary>
- public interface IExcelConditionalFormattingContainsText
+/// <summary>
+/// IExcelConditionalFormattingContainsText
+/// </summary>
+public interface IExcelConditionalFormattingContainsText
: IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithText
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ IExcelConditionalFormattingWithText {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDataBarGroup.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDataBarGroup.cs
index 31b9002..99a44a1 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDataBarGroup.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDataBarGroup.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,55 +13,47 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
using System.Drawing;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingDataBar
- /// </summary>
- public interface IExcelConditionalFormattingDataBarGroup
- : IExcelConditionalFormattingRule
- {
- #region Public Properties
- /// <summary>
- /// ShowValue
- /// </summary>
- bool ShowValue { get; set; }
- /// <summary>
- /// Databar Low Value
- /// </summary>
- ExcelConditionalFormattingIconDataBarValue LowValue { get; }
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
- /// <summary>
- /// Databar High Value
- /// </summary>
- ExcelConditionalFormattingIconDataBarValue HighValue { get; }
- /// <summary>
- /// The color of the databar
- /// </summary>
- Color Color { get; set;}
- #endregion Public Properties
- }
-}
\ No newline at end of file
+/// <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; }
+
+ /// <summary>
+ /// The color of the databar
+ /// </summary>
+ Color Color { get; set; }
+}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDuplicateValues.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDuplicateValues.cs
index 768be37..32427f9 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDuplicateValues.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingDuplicateValues.cs
@@ -13,37 +13,25 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingDuplicateValues
- /// </summary>
- public interface IExcelConditionalFormattingDuplicateValues
- : IExcelConditionalFormattingRule
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+/// <summary>
+/// IExcelConditionalFormattingDuplicateValues
+/// </summary>
+public interface IExcelConditionalFormattingDuplicateValues : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEndsWith.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEndsWith.cs
index 07f58d1..d45c296 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEndsWith.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEndsWith.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingEndsWith
- /// </summary>
- public interface IExcelConditionalFormattingEndsWith
+/// <summary>
+/// IExcelConditionalFormattingEndsWith
+/// </summary>
+public interface IExcelConditionalFormattingEndsWith
: IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithText
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ IExcelConditionalFormattingWithText {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEqual.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEqual.cs
index 16bce16..91c9663 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEqual.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingEqual.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingEqual
- /// </summary>
- public interface IExcelConditionalFormattingEqual
+/// <summary>
+/// IExcelConditionalFormattingEqual
+/// </summary>
+public interface IExcelConditionalFormattingEqual
: IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ IExcelConditionalFormattingWithFormula {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingExpression.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingExpression.cs
index 340db52..aa23a69 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingExpression.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingExpression.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingExpression
- /// </summary>
- public interface IExcelConditionalFormattingExpression
+/// <summary>
+/// IExcelConditionalFormattingExpression
+/// </summary>
+public interface IExcelConditionalFormattingExpression
: IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ IExcelConditionalFormattingWithFormula {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFiveIconSet.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFiveIconSet.cs
index e81d499..2954b3e 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFiveIconSet.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFiveIconSet.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,40 +13,31 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
+/// <summary>
+/// IExcelConditionalFormattingFiveIconSet
+/// </summary>eExcelconditionalFormatting4IconsSetType
+public interface IExcelConditionalFormattingFiveIconSet
+ : IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting5IconsSetType> {
/// <summary>
- /// IExcelConditionalFormattingFiveIconSet
- /// </summary>eExcelconditionalFormatting4IconsSetType
- public interface IExcelConditionalFormattingFiveIconSet : IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting5IconsSetType>
- {
- #region Public Properties
- /// <summary>
- /// Icon5 (part of the 5 Icon Set)
- /// </summary>
- ExcelConditionalFormattingIconDataBarValue Icon5 { get; }
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ /// 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
index 496ad61..67da2ba 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFourIconSet.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingFourIconSet.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,40 +13,31 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
+/// <summary>
+/// IExcelConditionalFormattingFourIconSet
+/// </summary>
+public interface IExcelConditionalFormattingFourIconSet<T>
+ : IExcelConditionalFormattingThreeIconSet<T> {
/// <summary>
- /// IExcelConditionalFormattingFourIconSet
+ /// Icon4 (part of the 4 ou 5 Icon Set)
/// </summary>
- public interface IExcelConditionalFormattingFourIconSet<T> : IExcelConditionalFormattingThreeIconSet<T>
- {
- #region Public Properties
- /// <summary>
- /// Icon4 (part of the 4 ou 5 Icon Set)
- /// </summary>
- ExcelConditionalFormattingIconDataBarValue Icon4 { get; }
- #endregion Public Properties
- }
+ ExcelConditionalFormattingIconDataBarValue Icon4 { get; }
}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThan.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThan.cs
index 7d739fa..9287f3f 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThan.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThan.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingGreaterThan
- /// </summary>
- public interface IExcelConditionalFormattingGreaterThan
+/// <summary>
+/// IExcelConditionalFormattingGreaterThan
+/// </summary>
+public interface IExcelConditionalFormattingGreaterThan
: IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ IExcelConditionalFormattingWithFormula {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThanOrEqual.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThanOrEqual.cs
index 1c3e193..aa084cc 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThanOrEqual.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingGreaterThanOrEqual.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingGreaterThanOrEqual
- /// </summary>
- public interface IExcelConditionalFormattingGreaterThanOrEqual
+/// <summary>
+/// IExcelConditionalFormattingGreaterThanOrEqual
+/// </summary>
+public interface IExcelConditionalFormattingGreaterThanOrEqual
: IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ IExcelConditionalFormattingWithFormula {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingIconSetGroup.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingIconSetGroup.cs
index 78e8d7c..700ffd6 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingIconSetGroup.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingIconSetGroup.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,51 +13,40 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingIconSetGroup
- /// </summary>
- public interface IExcelConditionalFormattingIconSetGroup<T>
- : IExcelConditionalFormattingRule
- {
- #region Public Properties
- /// <summary>
- /// Reverse
- /// </summary>
- bool Reverse { get; set; }
+/// <summary>
+/// IExcelConditionalFormattingIconSetGroup
+/// </summary>
+public interface IExcelConditionalFormattingIconSetGroup<T> : IExcelConditionalFormattingRule {
+ /// <summary>
+ /// Reverse
+ /// </summary>
+ bool Reverse { get; set; }
- /// <summary>
- /// ShowValue
- /// </summary>
- bool ShowValue { get; set; }
+ /// <summary>
+ /// ShowValue
+ /// </summary>
+ bool ShowValue { get; set; }
- /// <summary>
- /// IconSet (3, 4 ou 5 IconSet)
- /// </summary>
- T IconSet { get; set; }
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ /// <summary>
+ /// IconSet (3, 4 ou 5 IconSet)
+ /// </summary>
+ T IconSet { get; set; }
+}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThan.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThan.cs
index 59e25a5..162a16c 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThan.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThan.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingLessThan
- /// </summary>
- public interface IExcelConditionalFormattingLessThan
+/// <summary>
+/// IExcelConditionalFormattingLessThan
+/// </summary>
+public interface IExcelConditionalFormattingLessThan
: IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ IExcelConditionalFormattingWithFormula {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThanOrEqual.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThanOrEqual.cs
index c9a8a2a..fce6064 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThanOrEqual.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingLessThanOrEqual.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingGreaterThanOrEqual
- /// </summary>
- public interface IExcelConditionalFormattingLessThanOrEqual
+/// <summary>
+/// IExcelConditionalFormattingGreaterThanOrEqual
+/// </summary>
+public interface IExcelConditionalFormattingLessThanOrEqual
: IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ IExcelConditionalFormattingWithFormula {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotBetween.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotBetween.cs
index 49835dd..a017b81 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotBetween.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotBetween.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingNotBetween
- /// </summary>
- public interface IExcelConditionalFormattingNotBetween
+/// <summary>
+/// IExcelConditionalFormattingNotBetween
+/// </summary>
+public interface IExcelConditionalFormattingNotBetween
: IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula2
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ IExcelConditionalFormattingWithFormula2 {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsBlanks.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsBlanks.cs
index 0152916..4743b3b 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsBlanks.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsBlanks.cs
@@ -13,37 +13,25 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingNotContainsBlanks
- /// </summary>
- public interface IExcelConditionalFormattingNotContainsBlanks
- : IExcelConditionalFormattingRule
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+/// <summary>
+/// IExcelConditionalFormattingNotContainsBlanks
+/// </summary>
+public interface IExcelConditionalFormattingNotContainsBlanks : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsErrors.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsErrors.cs
index bd7cfee..aa42a1c 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsErrors.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsErrors.cs
@@ -13,37 +13,25 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingNotContainsErrors
- /// </summary>
- public interface IExcelConditionalFormattingNotContainsErrors
- : IExcelConditionalFormattingRule
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+/// <summary>
+/// IExcelConditionalFormattingNotContainsErrors
+/// </summary>
+public interface IExcelConditionalFormattingNotContainsErrors : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsText.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsText.cs
index 9cbcb4a..5a427f4 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsText.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotContainsText.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingNotContainsText
- /// </summary>
- public interface IExcelConditionalFormattingNotContainsText
+/// <summary>
+/// IExcelConditionalFormattingNotContainsText
+/// </summary>
+public interface IExcelConditionalFormattingNotContainsText
: IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithText
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ IExcelConditionalFormattingWithText {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotEqual.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotEqual.cs
index 17f7c3b..f20f33a 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotEqual.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingNotEqual.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingNotEqual
- /// </summary>
- public interface IExcelConditionalFormattingNotEqual
+/// <summary>
+/// IExcelConditionalFormattingNotEqual
+/// </summary>
+public interface IExcelConditionalFormattingNotEqual
: IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithFormula
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ IExcelConditionalFormattingWithFormula {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingRule.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingRule.cs
index cdb899a..e88b5af 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingRule.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingRule.cs
@@ -13,75 +13,70 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
+
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; }
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
- /// <summary>
- /// Type of conditional formatting rule. ST_CfType §18.18.12.
- /// </summary>
- eExcelConditionalFormattingRuleType Type { get; }
+/// <summary>
+/// Interface for conditional formatting rule
+/// </summary>
+public interface IExcelConditionalFormattingRule {
+ /// <summary>
+ /// The 'cfRule' XML node
+ /// </summary>
+ XmlNode Node { 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>
+ /// Type of conditional formatting rule. ST_CfType §18.18.12.
+ /// </summary>
+ eExcelConditionalFormattingRuleType Type { get; }
- /// <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>
+ /// <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>
- /// 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>
+ /// 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>
- ///// <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; }
- }
-}
\ No newline at end of file
+ /// <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
index 6bd768f..1aca982 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingStdDevGroup.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingStdDevGroup.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingStdDevGroup
- /// </summary>
- public interface IExcelConditionalFormattingStdDevGroup
+/// <summary>
+/// IExcelConditionalFormattingStdDevGroup
+/// </summary>
+public interface IExcelConditionalFormattingStdDevGroup
: IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithStdDev
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ IExcelConditionalFormattingWithStdDev {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeColorScale.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeColorScale.cs
index ed2f11f..eca66d1 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeColorScale.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeColorScale.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,41 +13,31 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingThreeColorScale
- /// </summary>
- public interface IExcelConditionalFormattingThreeColorScale
- : IExcelConditionalFormattingTwoColorScale
- {
- #region Public Properties
- /// <summary>
- /// Three Color Scale Middle Value
- /// </summary>
- ExcelConditionalFormattingColorScaleValue MiddleValue { get; set; }
- #endregion Public Properties
- }
-}
\ No newline at end of file
+/// <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
index 3921eb2..0fdc397 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeIconSet.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingThreeIconSet.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,51 +13,41 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingThreeIconSet
- /// </summary>
- public interface IExcelConditionalFormattingThreeIconSet<T>
- : IExcelConditionalFormattingIconSetGroup<T>
- {
- #region Public Properties
- /// <summary>
- /// Icon1 (part of the 3, 4 ou 5 Icon Set)
- /// </summary>
- ExcelConditionalFormattingIconDataBarValue Icon1 { get; }
+/// <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>
+ /// 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; }
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ /// <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
index ddde55e..266c1b8 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTimePeriodGroup.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTimePeriodGroup.cs
@@ -13,37 +13,25 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingTimePeriod
- /// </summary>
- public interface IExcelConditionalFormattingTimePeriodGroup
- : IExcelConditionalFormattingRule
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
+/// <summary>
+/// IExcelConditionalFormattingTimePeriod
+/// </summary>
+public interface IExcelConditionalFormattingTimePeriodGroup : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTopBottomGroup.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTopBottomGroup.cs
index 24f8283..234d925 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTopBottomGroup.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTopBottomGroup.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingTopBottomGroup
- /// </summary>
- public interface IExcelConditionalFormattingTopBottomGroup
+/// <summary>
+/// IExcelConditionalFormattingTopBottomGroup
+/// </summary>
+public interface IExcelConditionalFormattingTopBottomGroup
: IExcelConditionalFormattingRule,
- IExcelConditionalFormattingWithRank
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ IExcelConditionalFormattingWithRank {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTwoColorScale.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTwoColorScale.cs
index 936ed0d..2662b9a 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTwoColorScale.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingTwoColorScale.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,46 +13,36 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingTwoColorScale
- /// </summary>
- public interface IExcelConditionalFormattingTwoColorScale
- : IExcelConditionalFormattingColorScaleGroup
- {
- #region Public Properties
- /// <summary>
- /// Two Color Scale Low Value
- /// </summary>
- ExcelConditionalFormattingColorScaleValue LowValue { get; set; }
+/// <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; }
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ /// <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
index e5aa021..ee55553 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingUniqueValues.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingUniqueValues.cs
@@ -13,37 +13,25 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
- /// <summary>
- /// IExcelConditionalFormattingUniqueValues
- /// </summary>
- public interface IExcelConditionalFormattingUniqueValues
- : IExcelConditionalFormattingRule
- {
- #region Public Properties
- #endregion Public Properties
- }
-}
\ No newline at end of file
+/// <summary>
+/// IExcelConditionalFormattingUniqueValues
+/// </summary>
+public interface IExcelConditionalFormattingUniqueValues : IExcelConditionalFormattingRule {}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula.cs
index d5d0fa1..d612008 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,40 +13,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
+/// <summary>
+/// IExcelConditionalFormattingWithFormula
+/// </summary>
+public interface IExcelConditionalFormattingWithFormula {
/// <summary>
- /// IExcelConditionalFormattingWithFormula
+ /// Formula Attribute
/// </summary>
- public interface IExcelConditionalFormattingWithFormula
- {
- #region Public Properties
- /// <summary>
- /// Formula Attribute
- /// </summary>
- string Formula { get; set; }
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ string Formula { get; set; }
+}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula2.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula2.cs
index 7b4e70e..b7a940a 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula2.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithFormula2.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,41 +13,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
+/// <summary>
+/// IExcelConditionalFormattingWithFormula2
+/// </summary>
+public interface IExcelConditionalFormattingWithFormula2 : IExcelConditionalFormattingWithFormula {
/// <summary>
- /// IExcelConditionalFormattingWithFormula2
+ /// Formula2 Attribute
/// </summary>
- public interface IExcelConditionalFormattingWithFormula2
- : IExcelConditionalFormattingWithFormula
- {
- #region Public Properties
- /// <summary>
- /// Formula2 Attribute
- /// </summary>
- string Formula2 { get; set; }
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ string Formula2 { get; set; }
+}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithRank.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithRank.cs
index f5b0f92..de220ed 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithRank.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithRank.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,40 +13,32 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
+/// <summary>
+/// IExcelConditionalFormattingWithRank
+/// </summary>
+public interface IExcelConditionalFormattingWithRank {
/// <summary>
- /// IExcelConditionalFormattingWithRank
+ /// Rank Attribute
/// </summary>
- public interface IExcelConditionalFormattingWithRank
- {
- #region Public Properties
- /// <summary>
- /// Rank Attribute
- /// </summary>
- UInt16 Rank { get; set; }
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ UInt16 Rank { get; set; }
+}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithReverse.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithReverse.cs
index a710354..405a8a5 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithReverse.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithReverse.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,40 +13,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
+/// <summary>
+/// IExcelConditionalFormattingWithReverse
+/// </summary>
+public interface IExcelConditionalFormattingWithReverse {
/// <summary>
- /// IExcelConditionalFormattingWithReverse
+ /// Reverse Attribute
/// </summary>
- public interface IExcelConditionalFormattingWithReverse
- {
- #region Public Properties
- /// <summary>
- /// Reverse Attribute
- /// </summary>
- bool Reverse { get; set; }
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ bool Reverse { get; set; }
+}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithShowValue.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithShowValue.cs
index c12dbeb..479627b 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithShowValue.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithShowValue.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,40 +13,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
+/// <summary>
+/// IExcelConditionalFormattingWithShowValue
+/// </summary>
+public interface IExcelConditionalFormattingWithShowValue {
/// <summary>
- /// IExcelConditionalFormattingWithShowValue
+ /// ShowValue Attribute
/// </summary>
- public interface IExcelConditionalFormattingWithShowValue
- {
- #region Public Properties
- /// <summary>
- /// ShowValue Attribute
- /// </summary>
- bool ShowValue { get; set; }
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ bool ShowValue { get; set; }
+}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithStdDev.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithStdDev.cs
index 96ae1c6..d3cf330 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithStdDev.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithStdDev.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,40 +13,32 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
+/// <summary>
+/// IExcelConditionalFormattingWithStdDev
+/// </summary>
+public interface IExcelConditionalFormattingWithStdDev {
/// <summary>
- /// IExcelConditionalFormattingWithStdDev
+ /// StdDev Attribute
/// </summary>
- public interface IExcelConditionalFormattingWithStdDev
- {
- #region Public Properties
- /// <summary>
- /// StdDev Attribute
- /// </summary>
- UInt16 StdDev { get; set; }
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ UInt16 StdDev { get; set; }
+}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithText.cs b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithText.cs
index 4602ac4..bfe91a4 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithText.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IExcelConditionalFormattingWithText.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,40 +13,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.ConditionalFormatting;
+namespace OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting.Contracts
-{
+/// <summary>
+/// IExcelConditionalFormattingWithText
+/// </summary>
+public interface IExcelConditionalFormattingWithText {
/// <summary>
- /// IExcelConditionalFormattingWithText
+ /// Text Attribute
/// </summary>
- public interface IExcelConditionalFormattingWithText
- {
- #region Public Properties
- /// <summary>
- /// Text Attribute
- /// </summary>
- string Text { get; set; }
- #endregion Public Properties
- }
-}
\ No newline at end of file
+ string Text { get; set; }
+}
diff --git a/EPPlus/ConditionalFormatting/Contracts/IRangeConditionalFormatting.cs b/EPPlus/ConditionalFormatting/Contracts/IRangeConditionalFormatting.cs
index 6b4f85a..b2d99bf 100644
--- a/EPPlus/ConditionalFormatting/Contracts/IRangeConditionalFormatting.cs
+++ b/EPPlus/ConditionalFormatting/Contracts/IRangeConditionalFormatting.cs
@@ -13,301 +13,306 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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 System.Drawing;
+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();
+namespace OfficeOpenXml.ConditionalFormatting;
- /// <summary>
- /// Adds a Above Or Equal Average rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingAverageGroup AddAboveOrEqualAverage();
+/// <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 Below Average rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingAverageGroup AddBelowAverage();
+ /// <summary>
+ /// Adds a Above Or Equal Average rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingAverageGroup AddAboveOrEqualAverage();
- /// <summary>
- /// Adds a Below Or Equal Average rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingAverageGroup AddBelowOrEqualAverage();
+ /// <summary>
+ /// Adds a Below Average rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingAverageGroup AddBelowAverage();
- /// <summary>
- /// Adds a Above StdDev rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingStdDevGroup AddAboveStdDev();
+ /// <summary>
+ /// Adds a Below Or Equal Average rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingAverageGroup AddBelowOrEqualAverage();
- /// <summary>
- /// Adds a Below StdDev rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingStdDevGroup AddBelowStdDev();
+ /// <summary>
+ /// Adds a Above StdDev rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingStdDevGroup AddAboveStdDev();
- /// <summary>
- /// Adds a Bottom rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTopBottomGroup AddBottom();
+ /// <summary>
+ /// Adds a Below StdDev rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingStdDevGroup AddBelowStdDev();
- /// <summary>
- /// Adds a Bottom Percent rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTopBottomGroup AddBottomPercent();
+ /// <summary>
+ /// Adds a Bottom rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTopBottomGroup AddBottom();
- /// <summary>
- /// Adds a Top rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTopBottomGroup AddTop();
+ /// <summary>
+ /// Adds a Bottom Percent rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTopBottomGroup AddBottomPercent();
- /// <summary>
- /// Adds a Top Percent rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTopBottomGroup AddTopPercent();
+ /// <summary>
+ /// Adds a Top rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTopBottomGroup AddTop();
- /// <summary>
- /// Adds a Last 7 Days rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddLast7Days();
+ /// <summary>
+ /// Adds a Top Percent rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTopBottomGroup AddTopPercent();
- /// <summary>
- /// Adds a Last Month rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddLastMonth();
+ /// <summary>
+ /// Adds a Last 7 Days rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddLast7Days();
- /// <summary>
- /// Adds a Last Week rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddLastWeek();
+ /// <summary>
+ /// Adds a Last Month rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddLastMonth();
- /// <summary>
- /// Adds a Next Month rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddNextMonth();
+ /// <summary>
+ /// Adds a Last Week rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddLastWeek();
- /// <summary>
- /// Adds a Next Week rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddNextWeek();
+ /// <summary>
+ /// Adds a Next Month rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddNextMonth();
- /// <summary>
- /// Adds a This Month rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddThisMonth();
+ /// <summary>
+ /// Adds a Next Week rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddNextWeek();
- /// <summary>
- /// Adds a This Week rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddThisWeek();
+ /// <summary>
+ /// Adds a This Month rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddThisMonth();
- /// <summary>
- /// Adds a Today rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddToday();
+ /// <summary>
+ /// Adds a This Week rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddThisWeek();
- /// <summary>
- /// Adds a Tomorrow rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddTomorrow();
+ /// <summary>
+ /// Adds a Today rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddToday();
- /// <summary>
- /// Adds a Yesterday rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTimePeriodGroup AddYesterday();
+ /// <summary>
+ /// Adds a Tomorrow rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddTomorrow();
- /// <summary>
- /// Adds a Begins With rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingBeginsWith AddBeginsWith();
+ /// <summary>
+ /// Adds a Yesterday rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTimePeriodGroup AddYesterday();
- /// <summary>
- /// Adds a Between rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingBetween AddBetween();
+ /// <summary>
+ /// Adds a Begins With rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingBeginsWith AddBeginsWith();
- /// <summary>
- /// Adds a ContainsBlanks rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingContainsBlanks AddContainsBlanks();
+ /// <summary>
+ /// Adds a Between rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingBetween AddBetween();
- /// <summary>
- /// Adds a ContainsErrors rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingContainsErrors AddContainsErrors();
+ /// <summary>
+ /// Adds a ContainsBlanks rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingContainsBlanks AddContainsBlanks();
- /// <summary>
- /// Adds a ContainsText rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingContainsText AddContainsText();
+ /// <summary>
+ /// Adds a ContainsErrors rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingContainsErrors AddContainsErrors();
- /// <summary>
- /// Adds a DuplicateValues rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingDuplicateValues AddDuplicateValues();
+ /// <summary>
+ /// Adds a ContainsText rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingContainsText AddContainsText();
- /// <summary>
- /// Adds a EndsWith rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingEndsWith AddEndsWith();
+ /// <summary>
+ /// Adds a DuplicateValues rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingDuplicateValues AddDuplicateValues();
- /// <summary>
- /// Adds a Equal rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingEqual AddEqual();
+ /// <summary>
+ /// Adds a EndsWith rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingEndsWith AddEndsWith();
- /// <summary>
- /// Adds a Expression rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingExpression AddExpression();
+ /// <summary>
+ /// Adds a Equal rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingEqual AddEqual();
- /// <summary>
- /// Adds a GreaterThan rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingGreaterThan AddGreaterThan();
+ /// <summary>
+ /// Adds a Expression rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingExpression AddExpression();
- /// <summary>
- /// Adds a GreaterThanOrEqual rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingGreaterThanOrEqual AddGreaterThanOrEqual();
+ /// <summary>
+ /// Adds a GreaterThan rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingGreaterThan AddGreaterThan();
- /// <summary>
- /// Adds a LessThan rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingLessThan AddLessThan();
+ /// <summary>
+ /// Adds a GreaterThanOrEqual rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingGreaterThanOrEqual AddGreaterThanOrEqual();
- /// <summary>
- /// Adds a LessThanOrEqual rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingLessThanOrEqual AddLessThanOrEqual();
+ /// <summary>
+ /// Adds a LessThan rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingLessThan AddLessThan();
- /// <summary>
- /// Adds a NotBetween rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingNotBetween AddNotBetween();
+ /// <summary>
+ /// Adds a LessThanOrEqual rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingLessThanOrEqual AddLessThanOrEqual();
- /// <summary>
- /// Adds a NotContainsBlanks rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingNotContainsBlanks AddNotContainsBlanks();
+ /// <summary>
+ /// Adds a NotBetween rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingNotBetween AddNotBetween();
- /// <summary>
- /// Adds a NotContainsErrors rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingNotContainsErrors AddNotContainsErrors();
+ /// <summary>
+ /// Adds a NotContainsBlanks rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingNotContainsBlanks AddNotContainsBlanks();
- /// <summary>
- /// Adds a NotContainsText rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingNotContainsText AddNotContainsText();
+ /// <summary>
+ /// Adds a NotContainsErrors rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingNotContainsErrors AddNotContainsErrors();
- /// <summary>
- /// Adds a NotEqual rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingNotEqual AddNotEqual();
+ /// <summary>
+ /// Adds a NotContainsText rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingNotContainsText AddNotContainsText();
- /// <summary>
- /// Adds a UniqueValues rule to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingUniqueValues AddUniqueValues();
+ /// <summary>
+ /// Adds a NotEqual rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingNotEqual AddNotEqual();
- /// <summary>
- /// Adds a <see cref="ExcelConditionalFormattingThreeColorScale"/> to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingThreeColorScale AddThreeColorScale();
+ /// <summary>
+ /// Adds a UniqueValues rule to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingUniqueValues AddUniqueValues();
- /// <summary>
- /// Adds a <see cref="ExcelConditionalFormattingTwoColorScale"/> to the range
- /// </summary>
- /// <returns></returns>
- IExcelConditionalFormattingTwoColorScale AddTwoColorScale();
+ /// <summary>
+ /// Adds a <see cref="ExcelConditionalFormattingThreeColorScale"/> to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingThreeColorScale AddThreeColorScale();
- /// <summary>
- /// Adds a <see cref="IExcelConditionalFormattingThreeIconSet<eExcelconditionalFormatting3IconsSetType>"/> to the range
- /// </summary>
- /// <param name="IconSet"></param>
- /// <returns></returns>
- IExcelConditionalFormattingThreeIconSet<eExcelconditionalFormatting3IconsSetType> AddThreeIconSet(eExcelconditionalFormatting3IconsSetType IconSet);
- /// <summary>
- /// Adds a <see cref="IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType>"/> to the range
- /// </summary>
- /// <param name="IconSet"></param>
- /// <returns></returns>
- IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType> AddFourIconSet(eExcelconditionalFormatting4IconsSetType IconSet);
- /// <summary>
- /// Adds a <see cref="IExcelConditionalFormattingFiveIconSet"/> to the range
- /// </summary>
- /// <param name="IconSet"></param>
- /// <returns></returns>
- IExcelConditionalFormattingFiveIconSet AddFiveIconSet(eExcelconditionalFormatting5IconsSetType IconSet);
- /// <summary>
- /// Adds a <see cref="IExcelConditionalFormattingDataBarGroup"/> to the range
- /// </summary>
- /// <param name="color"></param>
- /// <returns></returns>
- IExcelConditionalFormattingDataBarGroup AddDatabar(Color color);
- }
-}
\ No newline at end of file
+ /// <summary>
+ /// Adds a <see cref="ExcelConditionalFormattingTwoColorScale"/> to the range
+ /// </summary>
+ /// <returns></returns>
+ IExcelConditionalFormattingTwoColorScale AddTwoColorScale();
+
+ /// <summary>
+ /// Adds a <see cref="IExcelConditionalFormattingThreeIconSet<eExcelconditionalFormatting3IconsSetType>"/> to the range
+ /// </summary>
+ /// <param name="iconSet"></param>
+ /// <returns></returns>
+ IExcelConditionalFormattingThreeIconSet<eExcelconditionalFormatting3IconsSetType> AddThreeIconSet(
+ eExcelconditionalFormatting3IconsSetType iconSet);
+
+ /// <summary>
+ /// Adds a <see cref="IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType>"/> to the range
+ /// </summary>
+ /// <param name="iconSet"></param>
+ /// <returns></returns>
+ IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType> AddFourIconSet(
+ eExcelconditionalFormatting4IconsSetType iconSet);
+
+ /// <summary>
+ /// Adds a <see cref="IExcelConditionalFormattingFiveIconSet"/> to the range
+ /// </summary>
+ /// <param name="iconSet"></param>
+ /// <returns></returns>
+ IExcelConditionalFormattingFiveIconSet AddFiveIconSet(
+ eExcelconditionalFormatting5IconsSetType iconSet);
+
+ /// <summary>
+ /// Adds a <see cref="IExcelConditionalFormattingDataBarGroup"/> to the range
+ /// </summary>
+ /// <param name="color"></param>
+ /// <returns></returns>
+ IExcelConditionalFormattingDataBarGroup AddDatabar(Color color);
+}
diff --git a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingCollection.cs b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingCollection.cs
index 969bcd1..4fe42f4 100644
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingCollection.cs
+++ b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingCollection.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,987 +13,857 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
using System.Collections;
-using OfficeOpenXml.Utils;
+using System.Collections.Generic;
+using System.Drawing;
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-using System.Text.RegularExpressions;
-using System.Drawing;
+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
+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>
- {
- /****************************************************************************************/
+ IEnumerable<IExcelConditionalFormattingRule> {
+ /****************************************************************************************/
- #region Private Properties
- private List<IExcelConditionalFormattingRule> _rules = new List<IExcelConditionalFormattingRule>();
- private ExcelWorksheet _worksheet = null;
- #endregion Private Properties
- /****************************************************************************************/
+ private List<IExcelConditionalFormattingRule> _rules = new();
+ private ExcelWorksheet _worksheet;
- #region Constructors
- /// <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;
- SchemaNodeOrder = _worksheet.SchemaNodeOrder;
- // Look for all the <conditionalFormatting>
- var conditionalFormattingNodes = TopNode.SelectNodes(
- "//" + ExcelConditionalFormattingConstants.Paths.ConditionalFormatting,
+ /// <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;
+ SchemaNodeOrder = _worksheet.SchemaNodeOrder;
+
+ // 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 Exception(
- ExcelConditionalFormattingConstants.Errors.MissingSqrefAttribute);
- }
+ // 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);
+ // 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,
+ // 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 Exception(
- ExcelConditionalFormattingConstants.Errors.MissingTypeAttribute);
- }
+ // 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 Exception(
- ExcelConditionalFormattingConstants.Errors.MissingPriorityAttribute);
- }
+ // 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(
+ // Get the <cfRule> main attributes
+ string typeAttribute = ExcelConditionalFormattingHelper.GetAttributeString(
cfRuleNode,
- ExcelConditionalFormattingConstants.Attributes.Type);
+ ExcelConditionalFormattingConstants.Attributes._type);
- int priority = ExcelConditionalFormattingHelper.GetAttributeInt(
+ int priority = ExcelConditionalFormattingHelper.GetAttributeInt(
cfRuleNode,
- ExcelConditionalFormattingConstants.Attributes.Priority);
+ ExcelConditionalFormattingConstants.Attributes._priority);
- // Transform the @type attribute to EPPlus Rule Type (slighty diferente)
- var type = ExcelConditionalFormattingRuleType.GetTypeByAttrbiute(
+ // 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(
+ // 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);
+ // Add the new rule to the list
+ if (cfRule != null) {
+ _rules.Add(cfRule);
}
}
}
}
- #endregion Constructors
+ }
- /****************************************************************************************/
+ /****************************************************************************************/
- #region Methods
- /// <summary>
- ///
- /// </summary>
- private void EnsureRootElementExists()
- {
- // Find the <worksheet> node
- if (_worksheet.WorksheetXml.DocumentElement == null)
- {
- throw new Exception(
- ExcelConditionalFormattingConstants.Errors.MissingWorksheetNode);
+
+ /// <summary>
+ ///
+ /// </summary>
+ private void EnsureRootElementExists() {
+ // Find the <worksheet> node
+ if (_worksheet.WorksheetXml.DocumentElement == null) {
+ throw new(ExcelConditionalFormattingConstants.Errors._missingWorksheetNode);
+ }
+ }
+
+ /// <summary>
+ /// GetRootNode
+ /// </summary>
+ /// <returns></returns>
+ private XmlNode GetRootNode() {
+ EnsureRootElementExists();
+ return _worksheet.WorksheetXml.DocumentElement;
+ }
+
+ /// <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;
}
}
- /// <summary>
- /// GetRootNode
- /// </summary>
- /// <returns></returns>
- private XmlNode GetRootNode()
- {
- EnsureRootElementExists();
- return _worksheet.WorksheetXml.DocumentElement;
- }
+ // Our next priority is the last plus one
+ return lastPriority + 1;
+ }
- /// <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;
+ /// <summary>
+ /// Number of validations
+ /// </summary>
+ public int Count => _rules.Count;
- // Search for the last priority
- foreach (var cfRule in _rules)
- {
- if (cfRule.Priority > lastPriority)
- {
- lastPriority = cfRule.Priority;
- }
- }
+ /// <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;
+ }
- // Our next priority is the last plus one
- return lastPriority + 1;
- }
- #endregion Methods
+ /// <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();
+ }
- #region IEnumerable<IExcelConditionalFormatting>
- /// <summary>
- /// Number of validations
- /// </summary>
- public int Count
- {
- get { return _rules.Count; }
- }
-
- /// <summary>
- /// Index operator, returns by 0-based index
- /// </summary>
- /// <param name="index"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingRule this[int index]
- {
- get { return _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 System.Collections.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,
+ /// <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();
+ // Remove all the <conditionalFormatting> nodes one by one
+ foreach (XmlNode conditionalFormattingNode in conditionalFormattingNodes) {
+ conditionalFormattingNode.ParentNode.RemoveChild(conditionalFormattingNode);
}
- /// <summary>
- /// Remove a Conditional Formatting Rule by its object
- /// </summary>
- /// <param name="item"></param>
- public void Remove(
- IExcelConditionalFormattingRule item)
- {
- Require.Argument(item).IsNotNull("item");
+ // Clear the <cfRule> item list
+ _rules.Clear();
+ }
- try
- {
- // Point to the parent node
- var oldParentNode = item.Node.ParentNode;
+ /// <summary>
+ /// Remove a Conditional Formatting Rule by its object
+ /// </summary>
+ /// <param name="item"></param>
+ public void Remove(IExcelConditionalFormattingRule item) {
+ Require.Argument(item).IsNotNull("item");
- // Remove the <cfRule> from the old <conditionalFormatting> parent node
- oldParentNode.RemoveChild(item.Node);
+ try {
+ // Point to the parent node
+ var oldParentNode = item.Node.ParentNode;
- // Check if the old <conditionalFormatting> parent node has <cfRule> node inside it
- if (!oldParentNode.HasChildNodes)
- {
- // Remove the old parent node
- oldParentNode.ParentNode.RemoveChild(oldParentNode);
- }
+ // Remove the <cfRule> from the old <conditionalFormatting> parent node
+ oldParentNode.RemoveChild(item.Node);
- _rules.Remove(item);
+ // Check if the old <conditionalFormatting> parent node has <cfRule> node inside it
+ if (!oldParentNode.HasChildNodes) {
+ // Remove the old parent node
+ oldParentNode.ParentNode.RemoveChild(oldParentNode);
}
- catch
- {
- throw new Exception(
- ExcelConditionalFormattingConstants.Errors.InvalidRemoveRuleOperation);
- }
+
+ _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, this.Count - 1, "index");
+ /// <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]);
- }
+ 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>
+ /// 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);
- }
- #endregion IEnumerable<IExcelConditionalFormatting>
+ /// <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);
+ }
- /****************************************************************************************/
+ /****************************************************************************************/
- #region Conditional Formatting Rules
- /// <summary>
- /// Add rule (internal)
- /// </summary>
- /// <param name="type"></param>
- /// <param name="address"></param>
- /// <returns></returns>F
- internal IExcelConditionalFormattingRule AddRule(
+
+ /// <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");
+ ExcelAddress address) {
+ Require.Argument(address).IsNotNull("address");
- address = ValidateAddress(address);
- EnsureRootElementExists();
+ address = ValidateAddress(address);
+ EnsureRootElementExists();
- // Create the Rule according to the correct type, address and priority
- IExcelConditionalFormattingRule cfRule = ExcelConditionalFormattingRuleFactory.Create(
+ // 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);
+ // Add the newly created rule to the list
+ _rules.Add(cfRule);
- // Return the newly created rule
- return 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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <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(
+ /// <summary>
+ /// Add TwoColorScale Rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTwoColorScale AddTwoColorScale(ExcelAddress address) {
+ return (IExcelConditionalFormattingTwoColorScale)AddRule(
eExcelConditionalFormattingRuleType.TwoColorScale,
address);
- }
-
- /// <summary>
- /// Add ThreeIconSet Rule
- /// </summary>
- /// <param name="Address">The address</param>
- /// <param name="IconSet">Type of iconset</param>
- /// <returns></returns>
- public IExcelConditionalFormattingThreeIconSet<eExcelconditionalFormatting3IconsSetType> AddThreeIconSet(ExcelAddress Address, eExcelconditionalFormatting3IconsSetType IconSet)
- {
- var icon = (IExcelConditionalFormattingThreeIconSet<eExcelconditionalFormatting3IconsSetType>)AddRule(
- eExcelConditionalFormattingRuleType.ThreeIconSet,
- Address);
- icon.IconSet = IconSet;
- return icon;
- }
- /// <summary>
- /// Adds a FourIconSet rule
- /// </summary>
- /// <param name="Address"></param>
- /// <param name="IconSet"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType> AddFourIconSet(ExcelAddress Address, eExcelconditionalFormatting4IconsSetType IconSet)
- {
- var icon = (IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType>)AddRule(
- eExcelConditionalFormattingRuleType.FourIconSet,
- Address);
- icon.IconSet = IconSet;
- return icon;
- }
- /// <summary>
- /// Adds a FiveIconSet rule
- /// </summary>
- /// <param name="Address"></param>
- /// <param name="IconSet"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingFiveIconSet AddFiveIconSet(ExcelAddress Address, eExcelconditionalFormatting5IconsSetType IconSet)
- {
- var icon = (IExcelConditionalFormattingFiveIconSet)AddRule(
- eExcelConditionalFormattingRuleType.FiveIconSet,
- Address);
- icon.IconSet = IconSet;
- return icon;
- }
- /// <summary>
- /// Adds a databar rule
- /// </summary>
- /// <param name="Address"></param>
- /// <param name="color"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingDataBarGroup AddDatabar(ExcelAddress Address, Color color)
- {
- var dataBar = (IExcelConditionalFormattingDataBarGroup)AddRule(
- eExcelConditionalFormattingRuleType.DataBar,
- Address);
- dataBar.Color=color;
- return dataBar;
- }
- #endregion Conditional Formatting Rules
-
}
-}
\ No newline at end of file
+
+ /// <summary>
+ /// Add ThreeIconSet Rule
+ /// </summary>
+ /// <param name="address">The address</param>
+ /// <param name="iconSet">Type of iconset</param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingThreeIconSet<eExcelconditionalFormatting3IconsSetType> AddThreeIconSet(
+ ExcelAddress address,
+ eExcelconditionalFormatting3IconsSetType iconSet) {
+ var icon =
+ (IExcelConditionalFormattingThreeIconSet<eExcelconditionalFormatting3IconsSetType>)
+ AddRule(eExcelConditionalFormattingRuleType.ThreeIconSet, address);
+ icon.IconSet = iconSet;
+ return icon;
+ }
+
+ /// <summary>
+ /// Adds a FourIconSet rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="iconSet"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType> AddFourIconSet(
+ ExcelAddress address,
+ eExcelconditionalFormatting4IconsSetType iconSet) {
+ var icon =
+ (IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType>)
+ AddRule(eExcelConditionalFormattingRuleType.FourIconSet, address);
+ icon.IconSet = iconSet;
+ return icon;
+ }
+
+ /// <summary>
+ /// Adds a FiveIconSet rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="iconSet"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingFiveIconSet AddFiveIconSet(
+ ExcelAddress address,
+ eExcelconditionalFormatting5IconsSetType iconSet) {
+ var icon = (IExcelConditionalFormattingFiveIconSet)AddRule(
+ eExcelConditionalFormattingRuleType.FiveIconSet,
+ address);
+ icon.IconSet = iconSet;
+ return icon;
+ }
+
+ /// <summary>
+ /// Adds a databar rule
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="color"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingDataBarGroup AddDatabar(ExcelAddress address, Color color) {
+ var dataBar = (IExcelConditionalFormattingDataBarGroup)AddRule(
+ eExcelConditionalFormattingRuleType.DataBar,
+ address);
+ dataBar.Color = color;
+ return dataBar;
+ }
+}
diff --git a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingColorScaleValue.cs b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingColorScaleValue.cs
index ac1cdaf..3331b3e 100644
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingColorScaleValue.cs
+++ b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingColorScaleValue.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,499 +13,443 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
using System.Drawing;
using System.Xml;
using OfficeOpenXml.Utils;
-using System.Text.RegularExpressions;
-using System.Globalization;
-using System.Security;
-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
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Private Properties
- private eExcelConditionalFormattingValueObjectPosition _position;
- private eExcelConditionalFormattingRuleType _ruleType;
- private ExcelWorksheet _worksheet;
- #endregion Private Properties
+/// <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 {
+ /****************************************************************************************/
- /****************************************************************************************/
- #region Constructors
- /// <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,
- Color color,
- double value,
- string formula,
- eExcelConditionalFormattingRuleType ruleType,
+ private eExcelConditionalFormattingValueObjectPosition _position;
+ private eExcelConditionalFormattingRuleType _ruleType;
+ private ExcelWorksheet _worksheet;
+
+ /****************************************************************************************/
+
+
+ /// <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,
+ Color color,
+ 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");
+ 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;
+ // Save the worksheet for private methods to use
+ _worksheet = worksheet;
- // Schema order list
- SchemaNodeOrder = new string[]
- {
- ExcelConditionalFormattingConstants.Nodes.Cfvo,
- ExcelConditionalFormattingConstants.Nodes.Color
- };
+ // Schema order list
+ SchemaNodeOrder = new[] {
+ ExcelConditionalFormattingConstants.Nodes._cfvo,
+ ExcelConditionalFormattingConstants.Nodes._color,
+ };
- // 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 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 Exception(
- ExcelConditionalFormattingConstants.Errors.MissingCfvoParentNode);
- }
+ // 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);
+ // 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 Exception(
- ExcelConditionalFormattingConstants.Errors.MissingCfvoParentNode);
- }
- }
+ // 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;
+ // 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;
- Color = color;
- Value = value;
- Formula = formula;
- }
+ // Save the attributes
+ Position = position;
+ RuleType = ruleType;
+ Type = type;
+ Color = color;
+ 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,
- Color color,
- double value,
- string formula,
- eExcelConditionalFormattingRuleType ruleType,
+ /// <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,
+ Color color,
+ double value,
+ string formula,
+ eExcelConditionalFormattingRuleType ruleType,
ExcelAddress address,
int priority,
- ExcelWorksheet worksheet,
- XmlNamespaceManager namespaceManager)
- : this(
- position,
- type,
- color,
- value,
- formula,
- ruleType,
- address,
- priority,
- worksheet,
- null,
- namespaceManager)
- {
- }
+ ExcelWorksheet worksheet,
+ XmlNamespaceManager namespaceManager)
+ : this(
+ position,
+ type,
+ color,
+ 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,
- Color color,
- eExcelConditionalFormattingRuleType ruleType,
+ /// <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,
+ Color color,
+ eExcelConditionalFormattingRuleType ruleType,
ExcelAddress address,
int priority,
- ExcelWorksheet worksheet,
- XmlNamespaceManager namespaceManager)
- : this(
- position,
- type,
- color,
- 0,
- null,
- ruleType,
- address,
- priority,
- worksheet,
- null,
- namespaceManager)
- {
- }
- #endregion Constructors
+ ExcelWorksheet worksheet,
+ XmlNamespaceManager namespaceManager)
+ : this(
+ position,
+ type,
+ color,
+ 0,
+ null,
+ ruleType,
+ address,
+ priority,
+ worksheet,
+ null,
+ namespaceManager) {}
- /****************************************************************************************/
+ /****************************************************************************************/
- #region Methods
- /// <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;
+ /// <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);
+ }
- string nodePath = ExcelConditionalFormattingValueObjectType.GetNodePathByNodeType(nodeType);
- int nodeOrder = GetNodeOrder();
- eNodeInsertOrder nodeInsertOrder = eNodeInsertOrder.SchemaOrder;
- XmlNode referenceNode = null;
+ /// <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;
- 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);
+ string nodePath = ExcelConditionalFormattingValueObjectType.GetNodePathByNodeType(nodeType);
+ int nodeOrder = GetNodeOrder();
+ eNodeInsertOrder nodeInsertOrder = eNodeInsertOrder.SchemaOrder;
+ XmlNode referenceNode = null;
- // Only if the prepend node exists than insert after
- if (referenceNode != null)
- {
- nodeInsertOrder = eNodeInsertOrder.After;
- }
- }
+ 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);
- // Create the node in the right order
- var node = CreateComplexNode(
- TopNode,
- string.Format(
- "{0}[position()={1}]",
- // {0}
- nodePath,
- // {1}
- nodeOrder),
- nodeInsertOrder,
- referenceNode);
+ // Only if the prepend node exists than insert after
+ if (referenceNode != null) {
+ nodeInsertOrder = eNodeInsertOrder.After;
+ }
+ }
- // Point to the new node as the temporary TopNode (we need it for the XmlHelper functions)
- TopNode = node;
+ // Create the node in the right order
+ var node = CreateComplexNode(
+ TopNode,
+ string.Format(
+ "{0}[position()={1}]",
+ // {0}
+ nodePath,
+ // {1}
+ nodeOrder),
+ nodeInsertOrder,
+ referenceNode);
- // Add/Remove the attribute (if the attributeValue is empty then it will be removed)
- SetXmlNodeString(
- node,
- attributePath,
- attributeValue,
- true);
+ // Point to the new node as the temporary TopNode (we need it for the XmlHelper functions)
+ TopNode = node;
- // Point back to the <cfvo>/<color> parent node
- TopNode = currentTopNode;
- }
- #endregion Methos
+ // 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;
+ }
- #region Exposed Properties
- /// <summary>
- ///
- /// </summary>
- internal eExcelConditionalFormattingValueObjectPosition Position
- {
- get { return _position; }
- set { _position = value; }
- }
+ /****************************************************************************************/
- /// <summary>
- ///
- /// </summary>
- internal eExcelConditionalFormattingRuleType RuleType
- {
- get { return _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));
+ /// <summary>
+ ///
+ /// </summary>
+ internal eExcelConditionalFormattingValueObjectPosition Position {
+ get => _position;
+ set => _position = value;
+ }
- return ExcelConditionalFormattingValueObjectType.GetTypeByAttrbiute(typeAttribute);
- }
- set
- {
- CreateNodeByOrdem(
- eExcelConditionalFormattingValueObjectNodeType.Cfvo,
- ExcelConditionalFormattingConstants.Paths.TypeAttribute,
- ExcelConditionalFormattingValueObjectType.GetAttributeByType(value));
+ /// <summary>
+ ///
+ /// </summary>
+ internal eExcelConditionalFormattingRuleType RuleType {
+ get => _ruleType;
+ set => _ruleType = value;
+ }
- bool removeValAttribute = false;
+ /// <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));
- // 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;
- }
+ return ExcelConditionalFormattingValueObjectType.GetTypeByAttrbiute(typeAttribute);
+ }
+ set {
+ CreateNodeByOrdem(
+ eExcelConditionalFormattingValueObjectNodeType.Cfvo,
+ ExcelConditionalFormattingConstants.Paths._typeAttribute,
+ ExcelConditionalFormattingValueObjectType.GetAttributeByType(value));
- // Check if we need to remove the @val attribute
- if (removeValAttribute)
- {
- string nodePath = ExcelConditionalFormattingValueObjectType.GetNodePathByNodeType(
- eExcelConditionalFormattingValueObjectNodeType.Cfvo);
- int nodeOrder = GetNodeOrder();
+ bool removeValAttribute = false;
- // Remove the attribute (removed when the value = '')
- CreateComplexNode(
- TopNode,
- string.Format(
- "{0}[position()={1}]/{2}=''",
- // {0}
- nodePath,
- // {1}
- nodeOrder,
- // {2}
- ExcelConditionalFormattingConstants.Paths.ValAttribute));
- }
- }
- }
+ // 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;
+ }
- /// <summary>
- ///
- /// </summary>
- public Color Color
- {
- get
- {
- // Color Code like "FF5B34F2"
- var colorCode = GetXmlNodeString(
- string.Format(
- "{0}[position()={1}]/{2}",
- // {0}
- ExcelConditionalFormattingConstants.Paths.Color,
- // {1}
- GetNodeOrder(),
- // {2}
- ExcelConditionalFormattingConstants.Paths.RgbAttribute));
+ // Check if we need to remove the @val attribute
+ if (removeValAttribute) {
+ string nodePath = ExcelConditionalFormattingValueObjectType.GetNodePathByNodeType(
+ eExcelConditionalFormattingValueObjectNodeType.Cfvo);
+ int nodeOrder = GetNodeOrder();
- return ExcelConditionalFormattingHelper.ConvertFromColorCode(colorCode);
- }
- set
- {
- // Use the color code to store (Ex. "FF5B35F2")
- CreateNodeByOrdem(
- eExcelConditionalFormattingValueObjectNodeType.Color,
- ExcelConditionalFormattingConstants.Paths.RgbAttribute,
- value.ToArgb().ToString("x"));
- }
- }
+ // 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
- {
- return GetXmlNodeDouble(
- string.Format(
- "{0}[position()={1}]/{2}",
- // {0}
- ExcelConditionalFormattingConstants.Paths.Cfvo,
- // {1}
- GetNodeOrder(),
- // {2}
- ExcelConditionalFormattingConstants.Paths.ValAttribute));
- }
- set
- {
- string valueToStore = string.Empty;
+ /// <summary>
+ ///
+ /// </summary>
+ public Color Color {
+ get {
+ // Color Code like "FF5B34F2"
+ var colorCode = GetXmlNodeString(
+ string.Format(
+ "{0}[position()={1}]/{2}",
+ // {0}
+ ExcelConditionalFormattingConstants.Paths._color,
+ // {1}
+ GetNodeOrder(),
+ // {2}
+ ExcelConditionalFormattingConstants.Paths._rgbAttribute));
- // Only some types use the @val attribute
- if ((Type == eExcelConditionalFormattingValueObjectType.Num)
- || (Type == eExcelConditionalFormattingValueObjectType.Percent)
- || (Type == eExcelConditionalFormattingValueObjectType.Percentile))
- {
- valueToStore = value.ToString();
- }
+ return ExcelConditionalFormattingHelper.ConvertFromColorCode(colorCode);
+ }
+ set =>
+ // Use the color code to store (Ex. "FF5B35F2")
+ CreateNodeByOrdem(
+ eExcelConditionalFormattingValueObjectNodeType.Color,
+ ExcelConditionalFormattingConstants.Paths._rgbAttribute,
+ value.ToArgb().ToString("x"));
+ }
- CreateNodeByOrdem(
- eExcelConditionalFormattingValueObjectNodeType.Cfvo,
- ExcelConditionalFormattingConstants.Paths.ValAttribute,
- valueToStore);
- }
- }
+ /// <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;
- /// <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;
- }
+ // Only some types use the @val attribute
+ if ((Type == eExcelConditionalFormattingValueObjectType.Num)
+ || (Type == eExcelConditionalFormattingValueObjectType.Percent)
+ || (Type == eExcelConditionalFormattingValueObjectType.Percentile)) {
+ valueToStore = value.ToString();
+ }
- // 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 == null) ? string.Empty : value.ToString());
- }
- }
- }
- #endregion Exposed Properties
+ CreateNodeByOrdem(
+ eExcelConditionalFormattingValueObjectNodeType.Cfvo,
+ ExcelConditionalFormattingConstants.Paths._valAttribute,
+ valueToStore);
+ }
+ }
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ /// <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 == null) ? string.Empty : value);
+ }
+ }
+ }
+
+ /****************************************************************************************/
+}
diff --git a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingConstants.cs b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingConstants.cs
index 6f8918c..938c6cd 100644
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingConstants.cs
+++ b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingConstants.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,271 +13,247 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// The conditional formatting constants
- /// </summary>
- internal static class ExcelConditionalFormattingConstants
- {
- #region Errors
- internal class Errors
- {
- internal const string CommaSeparatedAddresses = @"Multiple addresses may not be commaseparated, use space instead";
- internal const string InvalidCfruleObject = @"The supplied item must inherit OfficeOpenXml.ConditionalFormatting.ExcelConditionalFormattingRule";
- internal const string InvalidConditionalFormattingObject = @"The supplied item must inherit OfficeOpenXml.ConditionalFormatting.ExcelConditionalFormatting";
- 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 UnexpectedRuleTypeName = @"Unexpected eExcelConditionalFormattingRuleType TypeName in Conditional Formatting Rule";
- internal const string WrongNumberCfvoColorNodes = @"Wrong number of 'cfvo'/'color' nodes in Conditional Formatting Rule";
- }
- #endregion Errors
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Nodes
- 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";
- }
- #endregion Nodes
-
- #region Attributes
- 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";
- }
- #endregion Attributes
-
- #region XML Paths
- 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;
- }
- #endregion XML Paths
-
- #region Rule Type ST_CfType §18.18.12 (with small EPPlus changes)
- 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";
- }
- #endregion Rule Type ST_CfType §18.18.12 (with small EPPlus changes)
-
- #region CFVO Type ST_CfvoType §18.18.13
- 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";
- }
- #endregion CFVO Type ST_CfvoType §18.18.13
-
- #region Operator Type ST_ConditionalFormattingOperator §18.18.15
- 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";
- }
- #endregion Operator Type ST_ConditionalFormattingOperator §18.18.15
-
- #region Time Period Type ST_TimePeriod §18.18.82
- 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";
- }
- #endregion Time Period Type ST_TimePeriod §18.18.82
-
- #region Colors
- internal class Colors
- {
- internal const string CfvoLowValue = @"#FFF8696B";
- internal const string CfvoMiddleValue = @"#FFFFEB84";
- internal const string CfvoHighValue = @"#FF63BE7B";
- }
- #endregion Colors
+/// <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";
}
-}
\ No newline at end of file
+
+ 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
index bff9726..8885f5c 100644
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingEnums.cs
+++ b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingEnums.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,772 +13,741 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// Enum for Conditional Format Type ST_CfType §18.18.12. With some changes.
+/// </summary>
+public enum eExcelConditionalFormattingRuleType {
/// <summary>
- /// Enum for Conditional Format Type ST_CfType §18.18.12. With some changes.
+ /// This conditional formatting rule highlights cells that are above the average
+ /// for all values in the range.
/// </summary>
- public enum eExcelConditionalFormattingRuleType
- {
- #region Average
- /// <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,
- #endregion
-
- #region StdDev
- /// <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,
- #endregion
-
- #region TopBottom
- /// <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,
- #endregion
-
- #region TimePeriod
- /// <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,
- #endregion
-
- #region CellIs
- /// <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,
- #endregion
-
- #region ColorScale
- /// <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,
- #endregion
-
- #region IconSet
- /// <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,
- #endregion
-
- #region DataBar
- /// <summary>
- /// This conditional formatting rule displays a gradated data bar in the range of cells.
- /// </summary>
- /// <remarks>DataBar Excel CF Rule Type</remarks>
- DataBar
- #endregion
- }
+ /// <remarks>AboveAverage Excel CF Rule Type</remarks>
+ AboveAverage,
/// <summary>
- /// Enum for Conditional Format Value Object Type ST_CfvoType §18.18.13
+ /// This conditional formatting rule highlights cells that are above or equal
+ /// the average for all values in the range.
/// </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
- }
+ /// <remarks>AboveAverage Excel CF Rule Type</remarks>
+ AboveOrEqualAverage,
/// <summary>
- /// Enum for Conditional Formatting Value Object Position
+ /// This conditional formatting rule highlights cells that are below the average
+ /// for all values in the range.
/// </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
- }
+ /// <remarks>AboveAverage Excel CF Rule Type</remarks>
+ BelowAverage,
/// <summary>
- /// Enum for Conditional Formatting Value Object Node Type
+ /// This conditional formatting rule highlights cells that are below or equal
+ /// the average for all values in the range.
/// </summary>
- public enum eExcelConditionalFormattingValueObjectNodeType
- {
- /// <summary>
- /// 'cfvo' node
- /// </summary>
- Cfvo,
-
- /// <summary>
- /// 'color' node
- /// </summary>
- Color
- }
+ /// <remarks>AboveAverage Excel CF Rule Type</remarks>
+ BelowOrEqualAverage,
/// <summary>
- /// Enum for Conditional Formatting Operartor Type ST_ConditionalFormattingOperator §18.18.15
+ /// 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>
- 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
- }
+ AboveStdDev,
/// <summary>
- /// Enum for Conditional Formatting Time Period Type ST_TimePeriod §18.18.82
+ /// This conditional formatting rule highlights cells that are below the standard
+ /// deviationa for all values in the range.
/// </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
- }
+ /// <remarks>AboveAverage Excel CF Rule Type</remarks>
+ BelowStdDev,
/// <summary>
- /// 18.18.42 ST_IconSetType (Icon Set Type) - Only 3 icons
+ /// This conditional formatting rule highlights cells whose values fall in the
+ /// bottom N bracket as specified.
/// </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
- }
+ /// <remarks>Top10 Excel CF Rule Type</remarks>
+ Bottom,
/// <summary>
- /// 18.18.42 ST_IconSetType (Icon Set Type) - Only 4 icons
+ /// This conditional formatting rule highlights cells whose values fall in the
+ /// bottom N percent as specified.
/// </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
- }
+ /// <remarks>Top10 Excel CF Rule Type</remarks>
+ BottomPercent,
/// <summary>
- /// 18.18.42 ST_IconSetType (Icon Set Type) - Only 5 icons
+ /// This conditional formatting rule highlights cells whose values fall in the
+ /// top N bracket as specified.
/// </summary>
- public enum eExcelconditionalFormatting5IconsSetType
- {
- /// <summary>
- /// (5 Arrows) 5 arrows icon set.
- /// </summary>
- Arrows,
+ /// <remarks>Top10 Excel CF Rule Type</remarks>
+ Top,
- /// <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)
+ /// This conditional formatting rule highlights cells whose values fall in the
+ /// top N percent as specified.
/// </summary>
- public enum eExcelconditionalFormattingIconsSetType
- {
- /// <summary>
- /// (3 Arrows) 3 arrows icon set.
- /// </summary>
- ThreeArrows,
+ /// <remarks>Top10 Excel CF Rule Type</remarks>
+ TopPercent,
- /// <summary>
- /// (3 Arrows (Gray)) 3 gray arrows icon set.
- /// </summary>
- ThreeArrowsGray,
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing dates in the
+ /// last 7 days.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ Last7Days,
- /// <summary>
- /// (3 Flags) 3 flags icon set.
- /// </summary>
- ThreeFlags,
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing dates in the
+ /// last month.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ LastMonth,
- /// <summary>
- /// (3 Signs) 3 signs icon set.
- /// </summary>
- ThreeSigns,
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing dates in the
+ /// last week.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ LastWeek,
- /// <summary>
- /// (3 Symbols Circled) 3 symbols icon set.
- /// </summary>
- ThreeSymbols,
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing dates in the
+ /// next month.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ NextMonth,
- /// <summary>
- /// (3 Symbols) 3 Symbols icon set.
- /// </summary>
- ThreeSymbols2,
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing dates in the
+ /// next week.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ NextWeek,
- /// <summary>
- /// (3 Traffic Lights) 3 traffic lights icon set (#1).
- /// </summary>
- ThreeTrafficLights1,
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing dates in this
+ /// month.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ ThisMonth,
- /// <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>
+ /// This conditional formatting rule highlights cells containing dates in this
+ /// week.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ ThisWeek,
- /// <summary>
- /// (4 Arrows (Gray)) 4 gray arrows icon set.
- /// </summary>
- FourArrowsGray,
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing today dates.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ Today,
- /// <summary>
- /// (4 Ratings) 4 ratings icon set.
- /// </summary>
- FourRating,
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing tomorrow dates.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ Tomorrow,
- /// <summary>
- /// (4 Red To Black) 4 'red to black' icon set.
- /// </summary>
- FourRedToBlack,
+ /// <summary>
+ /// This conditional formatting rule highlights cells containing yesterday dates.
+ /// </summary>
+ /// <remarks>TimePeriod Excel CF Rule Type</remarks>
+ Yesterday,
- /// <summary>
- /// (4 Traffic Lights) 4 traffic lights icon set.
- /// </summary>
- FourTrafficLights,
+ /// <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>
- /// (5 Arrows) 5 arrows icon set.
- /// </summary>
- FiveArrows,
+ /// <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>
- /// (5 Arrows (Gray)) 5 gray arrows icon set.
- /// </summary>
- FiveArrowsGray,
+ /// <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>
- /// (5 Quarters) 5 quarters icon set.
- /// </summary>
- FiveQuarters,
+ /// <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>
- /// (5 Ratings Icon Set) 5 rating icon set.
- /// </summary>
- FiveRating
+ /// <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,
}
-}
\ No newline at end of file
+
+/// <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
index 4e86a65..41fbe30 100644
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingHelper.cs
+++ b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingHelper.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,262 +13,207 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
-using OfficeOpenXml.Utils;
using System.Drawing;
using System.Globalization;
+using System.Text.RegularExpressions;
using System.Xml;
+using OfficeOpenXml.Utils;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// Conditional formatting helper
+/// </summary>
+internal static class ExcelConditionalFormattingHelper {
/// <summary>
- /// Conditional formatting helper
+ /// Check and fix an address (string address)
/// </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;
+ /// <param name="address"></param>
+ /// <returns></returns>
+ public static string CheckAndFixRangeAddress(string address) {
+ if (address.Contains(',')) {
+ throw new FormatException(
+ ExcelConditionalFormattingConstants.Errors._commaSeparatedAddresses);
}
- /// <summary>
- /// Convert a color code to Color Object
- /// </summary>
- /// <param name="colorCode">Color Code (Ex. "#FFB43C53" or "FFB43C53")</param>
- /// <returns></returns>
- public static Color ConvertFromColorCode(
- string colorCode)
- {
- try
- {
- return Color.FromArgb(Int32.Parse(colorCode.Replace("#", ""), NumberStyles.HexNumber));
- }
- catch
- {
- // Assume white is the default color (instead of giving an error)
- return Color.White;
- }
+ address = address.ToUpper(CultureInfo.InvariantCulture);
+
+ if (Regex.IsMatch(address, "[A-Z]+:[A-Z]+")) {
+ address = AddressUtility.ParseEntireColumnSelections(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 == null) ? string.Empty : value;
- }
- catch
- {
- return string.Empty;
- }
- }
+ return address;
+ }
- /// <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;
- }
- else
- {
- 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;
- }
- else
- {
- 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("&", "&");
+ /// <summary>
+ /// Convert a color code to Color Object
+ /// </summary>
+ /// <param name="colorCode">Color Code (Ex. "#FFB43C53" or "FFB43C53")</param>
+ /// <returns></returns>
+ public static Color ConvertFromColorCode(string colorCode) {
+ try {
+ return Color.FromArgb(Int32.Parse(colorCode.Replace("#", ""), NumberStyles.HexNumber));
+ } catch {
+ // Assume white is the default color (instead of giving an error)
+ return Color.White;
}
}
-}
\ No newline at end of file
+
+ /// <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 == null) ? string.Empty : value;
+ } 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
index e190cf5..3c7a98b 100644
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingIconDatabarValue.cs
+++ b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingIconDatabarValue.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,346 +13,289 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
using System.Drawing;
+using System.Globalization;
using System.Xml;
using OfficeOpenXml.Utils;
-using System.Text.RegularExpressions;
-using System.Globalization;
-using System.Security;
-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
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Private Properties
- private eExcelConditionalFormattingRuleType _ruleType;
- private ExcelWorksheet _worksheet;
- #endregion Private Properties
+/// <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 {
+ /****************************************************************************************/
- /****************************************************************************************/
- #region Constructors
- /// <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");
+ private eExcelConditionalFormattingRuleType _ruleType;
+ private ExcelWorksheet _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 Exception(
- 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);
+ /// <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 for en error (rule type does not have <cfvo>)
- if (itemElementNode == null)
- {
- throw new Exception(
- ExcelConditionalFormattingConstants.Errors.MissingCfvoParentNode);
- }
- }
+ // Check if the parent does not exists
+ if (itemElementNode == null) {
+ // Get the parent node path by the rule type
+ string parentNodePath = ExcelConditionalFormattingValueObjectType.GetParentPathByRuleType(
+ ruleType);
- TopNode = itemElementNode;
+ // Check for en error (rule type does not have <cfvo>)
+ if (parentNodePath == string.Empty) {
+ throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoParentNode);
+ }
- // Save the attributes
- RuleType = ruleType;
- Type = type;
- Value = value;
- Formula = formula;
- }
- /// <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");
+ // 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);
- // Save the worksheet for private methods to use
- _worksheet = worksheet;
+ // Check for en error (rule type does not have <cfvo>)
+ if (itemElementNode == null) {
+ throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoParentNode);
+ }
+ }
- // Schema order list
- SchemaNodeOrder = new string[]
- {
- ExcelConditionalFormattingConstants.Nodes.Cfvo,
- };
+ TopNode = itemElementNode;
- //Check if the parent does not exists
- if (itemElementNode == null)
- {
- // Get the parent node path by the rule type
- string parentNodePath = ExcelConditionalFormattingValueObjectType.GetParentPathByRuleType(
- ruleType);
+ // Save the attributes
+ RuleType = ruleType;
+ Type = type;
+ Value = value;
+ Formula = formula;
+ }
- // Check for en error (rule type does not have <cfvo>)
- if (parentNodePath == string.Empty)
- {
- throw new Exception(
- 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)
- {
- }
- #endregion Constructors
+ /// <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;
- #region Methods
- #endregion
+ // Schema order list
+ SchemaNodeOrder = new[] { ExcelConditionalFormattingConstants.Nodes._cfvo };
- /****************************************************************************************/
+ //Check if the parent does not exists
+ if (itemElementNode == null) {
+ // Get the parent node path by the rule type
+ string parentNodePath = ExcelConditionalFormattingValueObjectType.GetParentPathByRuleType(
+ ruleType);
- #region Exposed Properties
+ // Check for en error (rule type does not have <cfvo>)
+ if (parentNodePath == string.Empty) {
+ throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoParentNode);
+ }
+ }
+ RuleType = ruleType;
+ }
- /// <summary>
- ///
- /// </summary>
- internal eExcelConditionalFormattingRuleType RuleType
- {
- get { return _ruleType; }
- set { _ruleType = value; }
- }
+ /// <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>
- ///
- /// </summary>
- public eExcelConditionalFormattingValueObjectType Type
- {
- get
- {
- var typeAttribute = GetXmlNodeString(ExcelConditionalFormattingConstants.Paths.TypeAttribute);
+ /// <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) {}
- 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);
- }
- else
- {
- 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>
+ ///
+ /// </summary>
+ internal eExcelConditionalFormattingRuleType RuleType {
+ get => _ruleType;
+ set => _ruleType = value;
+ }
- /// <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;
- }
+ /// <summary>
+ ///
+ /// </summary>
+ public eExcelConditionalFormattingValueObjectType Type {
+ get {
+ var typeAttribute = GetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._typeAttribute);
- // 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);
- }
- }
- }
- #endregion Exposed Properties
+ 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));
+ }
+ }
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ /// <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
index 06e2374..cf0fae8 100644
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingOperatorType.cs
+++ b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingOperatorType.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,133 +13,121 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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
*******************************************************************************/
+
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml;
-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;
+namespace OfficeOpenXml.ConditionalFormatting;
- case eExcelConditionalFormattingOperatorType.Between:
- return ExcelConditionalFormattingConstants.Operators.Between;
+/// <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.ContainsText:
- return ExcelConditionalFormattingConstants.Operators.ContainsText;
+ case eExcelConditionalFormattingOperatorType.Between:
+ return ExcelConditionalFormattingConstants.Operators._between;
- case eExcelConditionalFormattingOperatorType.EndsWith:
- return ExcelConditionalFormattingConstants.Operators.EndsWith;
+ case eExcelConditionalFormattingOperatorType.ContainsText:
+ return ExcelConditionalFormattingConstants.Operators._containsText;
- case eExcelConditionalFormattingOperatorType.Equal:
- return ExcelConditionalFormattingConstants.Operators.Equal;
+ case eExcelConditionalFormattingOperatorType.EndsWith:
+ return ExcelConditionalFormattingConstants.Operators._endsWith;
- case eExcelConditionalFormattingOperatorType.GreaterThan:
- return ExcelConditionalFormattingConstants.Operators.GreaterThan;
+ case eExcelConditionalFormattingOperatorType.Equal:
+ return ExcelConditionalFormattingConstants.Operators._equal;
- case eExcelConditionalFormattingOperatorType.GreaterThanOrEqual:
- return ExcelConditionalFormattingConstants.Operators.GreaterThanOrEqual;
+ case eExcelConditionalFormattingOperatorType.GreaterThan:
+ return ExcelConditionalFormattingConstants.Operators._greaterThan;
- case eExcelConditionalFormattingOperatorType.LessThan:
- return ExcelConditionalFormattingConstants.Operators.LessThan;
+ case eExcelConditionalFormattingOperatorType.GreaterThanOrEqual:
+ return ExcelConditionalFormattingConstants.Operators._greaterThanOrEqual;
- case eExcelConditionalFormattingOperatorType.LessThanOrEqual:
- return ExcelConditionalFormattingConstants.Operators.LessThanOrEqual;
+ case eExcelConditionalFormattingOperatorType.LessThan:
+ return ExcelConditionalFormattingConstants.Operators._lessThan;
- case eExcelConditionalFormattingOperatorType.NotBetween:
- return ExcelConditionalFormattingConstants.Operators.NotBetween;
+ case eExcelConditionalFormattingOperatorType.LessThanOrEqual:
+ return ExcelConditionalFormattingConstants.Operators._lessThanOrEqual;
- case eExcelConditionalFormattingOperatorType.NotContains:
- return ExcelConditionalFormattingConstants.Operators.NotContains;
+ case eExcelConditionalFormattingOperatorType.NotBetween:
+ return ExcelConditionalFormattingConstants.Operators._notBetween;
- case eExcelConditionalFormattingOperatorType.NotEqual:
- return ExcelConditionalFormattingConstants.Operators.NotEqual;
- }
+ case eExcelConditionalFormattingOperatorType.NotContains:
+ return ExcelConditionalFormattingConstants.Operators._notContains;
- 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 Exception(
- ExcelConditionalFormattingConstants.Errors.UnexistentOperatorTypeAttribute);
+ case eExcelConditionalFormattingOperatorType.NotEqual:
+ return ExcelConditionalFormattingConstants.Operators._notEqual;
}
+
+ return string.Empty;
}
-}
\ No newline at end of file
+
+ /// <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
index 088798d..6bc7563 100644
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingRuleFactory.cs
+++ b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingRuleFactory.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,361 +13,334 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
using System.Xml;
using OfficeOpenXml.Utils;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// Factory class for ExcelConditionalFormatting.
- /// </summary>
- internal static class ExcelConditionalFormattingRuleFactory
- {
- public static ExcelConditionalFormattingRule Create(
- eExcelConditionalFormattingRuleType type,
+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(
+ 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(
+ case eExcelConditionalFormattingRuleType.AboveOrEqualAverage:
+ return new ExcelConditionalFormattingAboveOrEqualAverage(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.BelowAverage:
- return new ExcelConditionalFormattingBelowAverage(
+ case eExcelConditionalFormattingRuleType.BelowAverage:
+ return new ExcelConditionalFormattingBelowAverage(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.BelowOrEqualAverage:
- return new ExcelConditionalFormattingBelowOrEqualAverage(
+ case eExcelConditionalFormattingRuleType.BelowOrEqualAverage:
+ return new ExcelConditionalFormattingBelowOrEqualAverage(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.AboveStdDev:
- return new ExcelConditionalFormattingAboveStdDev(
+ case eExcelConditionalFormattingRuleType.AboveStdDev:
+ return new ExcelConditionalFormattingAboveStdDev(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.BelowStdDev:
- return new ExcelConditionalFormattingBelowStdDev(
+ case eExcelConditionalFormattingRuleType.BelowStdDev:
+ return new ExcelConditionalFormattingBelowStdDev(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.Bottom:
- return new ExcelConditionalFormattingBottom(
+ case eExcelConditionalFormattingRuleType.Bottom:
+ return new ExcelConditionalFormattingBottom(address, priority, worksheet, itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.BottomPercent:
+ return new ExcelConditionalFormattingBottomPercent(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.BottomPercent:
- return new ExcelConditionalFormattingBottomPercent(
+ case eExcelConditionalFormattingRuleType.Top:
+ return new ExcelConditionalFormattingTop(address, priority, worksheet, itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.TopPercent:
+ return new ExcelConditionalFormattingTopPercent(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.Top:
- return new ExcelConditionalFormattingTop(
+ case eExcelConditionalFormattingRuleType.Last7Days:
+ return new ExcelConditionalFormattingLast7Days(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.TopPercent:
- return new ExcelConditionalFormattingTopPercent(
+ case eExcelConditionalFormattingRuleType.LastMonth:
+ return new ExcelConditionalFormattingLastMonth(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.Last7Days:
- return new ExcelConditionalFormattingLast7Days(
+ case eExcelConditionalFormattingRuleType.LastWeek:
+ return new ExcelConditionalFormattingLastWeek(
address,
priority,
worksheet,
itemElementNode);
-
- case eExcelConditionalFormattingRuleType.LastMonth:
- return new ExcelConditionalFormattingLastMonth(
+ case eExcelConditionalFormattingRuleType.NextMonth:
+ return new ExcelConditionalFormattingNextMonth(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.LastWeek:
- return new ExcelConditionalFormattingLastWeek(
+ case eExcelConditionalFormattingRuleType.NextWeek:
+ return new ExcelConditionalFormattingNextWeek(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.NextMonth:
- return new ExcelConditionalFormattingNextMonth(
+ case eExcelConditionalFormattingRuleType.ThisMonth:
+ return new ExcelConditionalFormattingThisMonth(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.NextWeek:
- return new ExcelConditionalFormattingNextWeek(
+ case eExcelConditionalFormattingRuleType.ThisWeek:
+ return new ExcelConditionalFormattingThisWeek(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.ThisMonth:
- return new ExcelConditionalFormattingThisMonth(
+ case eExcelConditionalFormattingRuleType.Today:
+ return new ExcelConditionalFormattingToday(address, priority, worksheet, itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.Tomorrow:
+ return new ExcelConditionalFormattingTomorrow(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.ThisWeek:
- return new ExcelConditionalFormattingThisWeek(
+ case eExcelConditionalFormattingRuleType.Yesterday:
+ return new ExcelConditionalFormattingYesterday(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.Today:
- return new ExcelConditionalFormattingToday(
+ case eExcelConditionalFormattingRuleType.BeginsWith:
+ return new ExcelConditionalFormattingBeginsWith(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.Tomorrow:
- return new ExcelConditionalFormattingTomorrow(
+ case eExcelConditionalFormattingRuleType.Between:
+ return new ExcelConditionalFormattingBetween(address, priority, worksheet, itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.ContainsBlanks:
+ return new ExcelConditionalFormattingContainsBlanks(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.Yesterday:
- return new ExcelConditionalFormattingYesterday(
+ case eExcelConditionalFormattingRuleType.ContainsErrors:
+ return new ExcelConditionalFormattingContainsErrors(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.BeginsWith:
- return new ExcelConditionalFormattingBeginsWith(
+ case eExcelConditionalFormattingRuleType.ContainsText:
+ return new ExcelConditionalFormattingContainsText(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.Between:
- return new ExcelConditionalFormattingBetween(
+ case eExcelConditionalFormattingRuleType.DuplicateValues:
+ return new ExcelConditionalFormattingDuplicateValues(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.ContainsBlanks:
- return new ExcelConditionalFormattingContainsBlanks(
+ case eExcelConditionalFormattingRuleType.EndsWith:
+ return new ExcelConditionalFormattingEndsWith(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.ContainsErrors:
- return new ExcelConditionalFormattingContainsErrors(
+ case eExcelConditionalFormattingRuleType.Equal:
+ return new ExcelConditionalFormattingEqual(address, priority, worksheet, itemElementNode);
+
+ case eExcelConditionalFormattingRuleType.Expression:
+ return new ExcelConditionalFormattingExpression(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.ContainsText:
- return new ExcelConditionalFormattingContainsText(
+ case eExcelConditionalFormattingRuleType.GreaterThan:
+ return new ExcelConditionalFormattingGreaterThan(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.DuplicateValues:
- return new ExcelConditionalFormattingDuplicateValues(
+ case eExcelConditionalFormattingRuleType.GreaterThanOrEqual:
+ return new ExcelConditionalFormattingGreaterThanOrEqual(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.EndsWith:
- return new ExcelConditionalFormattingEndsWith(
+ case eExcelConditionalFormattingRuleType.LessThan:
+ return new ExcelConditionalFormattingLessThan(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.Equal:
- return new ExcelConditionalFormattingEqual(
+ case eExcelConditionalFormattingRuleType.LessThanOrEqual:
+ return new ExcelConditionalFormattingLessThanOrEqual(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.Expression:
- return new ExcelConditionalFormattingExpression(
+ case eExcelConditionalFormattingRuleType.NotBetween:
+ return new ExcelConditionalFormattingNotBetween(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.GreaterThan:
- return new ExcelConditionalFormattingGreaterThan(
+ case eExcelConditionalFormattingRuleType.NotContainsBlanks:
+ return new ExcelConditionalFormattingNotContainsBlanks(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.GreaterThanOrEqual:
- return new ExcelConditionalFormattingGreaterThanOrEqual(
+ case eExcelConditionalFormattingRuleType.NotContainsErrors:
+ return new ExcelConditionalFormattingNotContainsErrors(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.LessThan:
- return new ExcelConditionalFormattingLessThan(
+ case eExcelConditionalFormattingRuleType.NotContainsText:
+ return new ExcelConditionalFormattingNotContainsText(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.LessThanOrEqual:
- return new ExcelConditionalFormattingLessThanOrEqual(
+ case eExcelConditionalFormattingRuleType.NotEqual:
+ return new ExcelConditionalFormattingNotEqual(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.NotBetween:
- return new ExcelConditionalFormattingNotBetween(
+ case eExcelConditionalFormattingRuleType.UniqueValues:
+ return new ExcelConditionalFormattingUniqueValues(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.NotContainsBlanks:
- return new ExcelConditionalFormattingNotContainsBlanks(
+ case eExcelConditionalFormattingRuleType.ThreeColorScale:
+ return new ExcelConditionalFormattingThreeColorScale(
address,
priority,
worksheet,
itemElementNode);
- case eExcelConditionalFormattingRuleType.NotContainsErrors:
- return new ExcelConditionalFormattingNotContainsErrors(
+ case eExcelConditionalFormattingRuleType.TwoColorScale:
+ return new ExcelConditionalFormattingTwoColorScale(
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(
+ case eExcelConditionalFormattingRuleType.ThreeIconSet:
+ return new ExcelConditionalFormattingThreeIconSet(
address,
priority,
worksheet,
itemElementNode,
null);
- case eExcelConditionalFormattingRuleType.FourIconSet:
- return new ExcelConditionalFormattingFourIconSet(
+ case eExcelConditionalFormattingRuleType.FourIconSet:
+ return new ExcelConditionalFormattingFourIconSet(
address,
priority,
worksheet,
itemElementNode,
null);
- case eExcelConditionalFormattingRuleType.FiveIconSet:
- return new ExcelConditionalFormattingFiveIconSet(
+ case eExcelConditionalFormattingRuleType.FiveIconSet:
+ return new ExcelConditionalFormattingFiveIconSet(
address,
priority,
worksheet,
itemElementNode,
null);
- case eExcelConditionalFormattingRuleType.DataBar:
- return new ExcelConditionalFormattingDataBar(
+ case eExcelConditionalFormattingRuleType.DataBar:
+ return new ExcelConditionalFormattingDataBar(
eExcelConditionalFormattingRuleType.DataBar,
address,
priority,
@@ -375,14 +348,12 @@
itemElementNode,
null);
+ //TODO: Add DataBar
+ }
- //TODO: Add DataBar
- }
-
- throw new InvalidOperationException(
+ throw new InvalidOperationException(
string.Format(
- ExcelConditionalFormattingConstants.Errors.NonSupportedRuleType,
- type.ToString()));
- }
- }
-}
\ No newline at end of file
+ ExcelConditionalFormattingConstants.Errors._nonSupportedRuleType,
+ type.ToString()));
+ }
+}
diff --git a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingRuleType.cs b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingRuleType.cs
index 488dafa..b1c6b32 100644
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingRuleType.cs
+++ b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingRuleType.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,527 +13,483 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using System.Xml;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// Functions related to the ExcelConditionalFormattingRule
+/// </summary>
+internal static class ExcelConditionalFormattingRuleType {
/// <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(
+ /// <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);
+ XmlNamespaceManager nameSpaceManager) {
+ switch (attribute) {
+ case ExcelConditionalFormattingConstants.RuleType._aboveAverage:
+ return GetAboveAverageType(topNode, nameSpaceManager);
- case ExcelConditionalFormattingConstants.RuleType.Top10:
- return GetTop10Type(
- 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._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.Between:
+ // return eExcelConditionalFormattingRuleType.Between;
- case ExcelConditionalFormattingConstants.RuleType.ContainsBlanks:
- return eExcelConditionalFormattingRuleType.ContainsBlanks;
+ case ExcelConditionalFormattingConstants.RuleType._containsBlanks:
+ return eExcelConditionalFormattingRuleType.ContainsBlanks;
- case ExcelConditionalFormattingConstants.RuleType.ContainsErrors:
- return eExcelConditionalFormattingRuleType.ContainsErrors;
+ case ExcelConditionalFormattingConstants.RuleType._containsErrors:
+ return eExcelConditionalFormattingRuleType.ContainsErrors;
- case ExcelConditionalFormattingConstants.RuleType.ContainsText:
- return eExcelConditionalFormattingRuleType.ContainsText;
+ case ExcelConditionalFormattingConstants.RuleType._containsText:
+ return eExcelConditionalFormattingRuleType.ContainsText;
- case ExcelConditionalFormattingConstants.RuleType.DuplicateValues:
- return eExcelConditionalFormattingRuleType.DuplicateValues;
+ case ExcelConditionalFormattingConstants.RuleType._duplicateValues:
+ return eExcelConditionalFormattingRuleType.DuplicateValues;
- case ExcelConditionalFormattingConstants.RuleType.EndsWith:
- return eExcelConditionalFormattingRuleType.EndsWith;
+ case ExcelConditionalFormattingConstants.RuleType._endsWith:
+ return eExcelConditionalFormattingRuleType.EndsWith;
- //case ExcelConditionalFormattingConstants.RuleType.Equal:
- // return eExcelConditionalFormattingRuleType.Equal;
+ //case ExcelConditionalFormattingConstants.RuleType.Equal:
+ // return eExcelConditionalFormattingRuleType.Equal;
- case ExcelConditionalFormattingConstants.RuleType.Expression:
- return eExcelConditionalFormattingRuleType.Expression;
+ case ExcelConditionalFormattingConstants.RuleType._expression:
+ return eExcelConditionalFormattingRuleType.Expression;
- //case ExcelConditionalFormattingConstants.RuleType.GreaterThan:
- // return eExcelConditionalFormattingRuleType.GreaterThan;
+ //case ExcelConditionalFormattingConstants.RuleType.GreaterThan:
+ // return eExcelConditionalFormattingRuleType.GreaterThan;
- //case ExcelConditionalFormattingConstants.RuleType.GreaterThanOrEqual:
- // return eExcelConditionalFormattingRuleType.GreaterThanOrEqual;
+ //case ExcelConditionalFormattingConstants.RuleType.GreaterThanOrEqual:
+ // return eExcelConditionalFormattingRuleType.GreaterThanOrEqual;
- //case ExcelConditionalFormattingConstants.RuleType.LessThan:
- // return eExcelConditionalFormattingRuleType.LessThan;
+ //case ExcelConditionalFormattingConstants.RuleType.LessThan:
+ // return eExcelConditionalFormattingRuleType.LessThan;
- //case ExcelConditionalFormattingConstants.RuleType.LessThanOrEqual:
- // return eExcelConditionalFormattingRuleType.LessThanOrEqual;
+ //case ExcelConditionalFormattingConstants.RuleType.LessThanOrEqual:
+ // return eExcelConditionalFormattingRuleType.LessThanOrEqual;
- //case ExcelConditionalFormattingConstants.RuleType.NotBetween:
- // return eExcelConditionalFormattingRuleType.NotBetween;
+ //case ExcelConditionalFormattingConstants.RuleType.NotBetween:
+ // return eExcelConditionalFormattingRuleType.NotBetween;
- case ExcelConditionalFormattingConstants.RuleType.NotContainsBlanks:
- return eExcelConditionalFormattingRuleType.NotContainsBlanks;
+ case ExcelConditionalFormattingConstants.RuleType._notContainsBlanks:
+ return eExcelConditionalFormattingRuleType.NotContainsBlanks;
- case ExcelConditionalFormattingConstants.RuleType.NotContainsErrors:
- return eExcelConditionalFormattingRuleType.NotContainsErrors;
+ case ExcelConditionalFormattingConstants.RuleType._notContainsErrors:
+ return eExcelConditionalFormattingRuleType.NotContainsErrors;
- case ExcelConditionalFormattingConstants.RuleType.NotContainsText:
- return eExcelConditionalFormattingRuleType.NotContainsText;
+ case ExcelConditionalFormattingConstants.RuleType._notContainsText:
+ return eExcelConditionalFormattingRuleType.NotContainsText;
- //case ExcelConditionalFormattingConstants.RuleType.NotEqual:
- // return eExcelConditionalFormattingRuleType.NotEqual;
+ //case ExcelConditionalFormattingConstants.RuleType.NotEqual:
+ // return eExcelConditionalFormattingRuleType.NotEqual;
- case ExcelConditionalFormattingConstants.RuleType.UniqueValues:
- return eExcelConditionalFormattingRuleType.UniqueValues;
+ 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 Exception(
- ExcelConditionalFormattingConstants.Errors.UnexpectedRuleTypeAttribute);
+ case ExcelConditionalFormattingConstants.RuleType._colorScale:
+ return GetColorScaleType(topNode, nameSpaceManager);
+ case ExcelConditionalFormattingConstants.RuleType._iconSet:
+ return GetIconSetType(topNode, nameSpaceManager);
+ case ExcelConditionalFormattingConstants.RuleType._dataBar:
+ return eExcelConditionalFormattingRuleType.DataBar;
}
- private static eExcelConditionalFormattingRuleType GetCellIs(XmlElement node)
- {
- switch(node.GetAttribute("operator"))
- {
- case ExcelConditionalFormattingConstants.Operators.BeginsWith:
- return eExcelConditionalFormattingRuleType.BeginsWith;
- case ExcelConditionalFormattingConstants.Operators.Between:
- return eExcelConditionalFormattingRuleType.Between;
+ throw new(ExcelConditionalFormattingConstants.Errors._unexpectedRuleTypeAttribute);
+ }
- case ExcelConditionalFormattingConstants.Operators.ContainsText:
- return eExcelConditionalFormattingRuleType.ContainsText;
+ 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.EndsWith:
- return eExcelConditionalFormattingRuleType.EndsWith;
+ case ExcelConditionalFormattingConstants.Operators._containsText:
+ return eExcelConditionalFormattingRuleType.ContainsText;
- case ExcelConditionalFormattingConstants.Operators.Equal:
- return eExcelConditionalFormattingRuleType.Equal;
+ case ExcelConditionalFormattingConstants.Operators._endsWith:
+ return eExcelConditionalFormattingRuleType.EndsWith;
- case ExcelConditionalFormattingConstants.Operators.GreaterThan:
- return eExcelConditionalFormattingRuleType.GreaterThan;
+ case ExcelConditionalFormattingConstants.Operators._equal:
+ return eExcelConditionalFormattingRuleType.Equal;
- case ExcelConditionalFormattingConstants.Operators.GreaterThanOrEqual:
- return eExcelConditionalFormattingRuleType.GreaterThanOrEqual;
+ case ExcelConditionalFormattingConstants.Operators._greaterThan:
+ return eExcelConditionalFormattingRuleType.GreaterThan;
- case ExcelConditionalFormattingConstants.Operators.LessThan:
- return eExcelConditionalFormattingRuleType.LessThan;
+ case ExcelConditionalFormattingConstants.Operators._greaterThanOrEqual:
+ return eExcelConditionalFormattingRuleType.GreaterThanOrEqual;
- case ExcelConditionalFormattingConstants.Operators.LessThanOrEqual:
- return eExcelConditionalFormattingRuleType.LessThanOrEqual;
+ case ExcelConditionalFormattingConstants.Operators._lessThan:
+ return eExcelConditionalFormattingRuleType.LessThan;
- case ExcelConditionalFormattingConstants.Operators.NotBetween:
- return eExcelConditionalFormattingRuleType.NotBetween;
+ case ExcelConditionalFormattingConstants.Operators._lessThanOrEqual:
+ return eExcelConditionalFormattingRuleType.LessThanOrEqual;
- case ExcelConditionalFormattingConstants.Operators.NotContains:
- return eExcelConditionalFormattingRuleType.NotContains;
+ case ExcelConditionalFormattingConstants.Operators._notBetween:
+ return eExcelConditionalFormattingRuleType.NotBetween;
- case ExcelConditionalFormattingConstants.Operators.NotEqual:
- return eExcelConditionalFormattingRuleType.NotEqual;
- default:
- throw new Exception(
- 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;
- }
- else
- {
- var v = node.Value;
+ case ExcelConditionalFormattingConstants.Operators._notContains:
+ return eExcelConditionalFormattingRuleType.NotContains;
- if (v[0] == '3')
- {
- return eExcelConditionalFormattingRuleType.ThreeIconSet;
- }
- else if (v[0] == '4')
- {
- return eExcelConditionalFormattingRuleType.FourIconSet;
- }
- else
- {
- 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 Exception(
- 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 Exception(
- 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 Exception(
- 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 Exception(
- ExcelConditionalFormattingConstants.Errors.MissingRuleType);
+ case ExcelConditionalFormattingConstants.Operators._notEqual:
+ return eExcelConditionalFormattingRuleType.NotEqual;
+ default:
+ throw new(ExcelConditionalFormattingConstants.Errors._unexistentOperatorTypeAttribute);
}
}
-}
\ No newline at end of file
+
+ 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
index 75d8ab2..2051e7b 100644
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingTimePeriodType.cs
+++ b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingTimePeriodType.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,121 +13,109 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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
*******************************************************************************/
+
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml;
-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;
+namespace OfficeOpenXml.ConditionalFormatting;
- case eExcelConditionalFormattingTimePeriodType.LastMonth:
- return ExcelConditionalFormattingConstants.TimePeriods.LastMonth;
+/// <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.LastWeek:
- return ExcelConditionalFormattingConstants.TimePeriods.LastWeek;
+ case eExcelConditionalFormattingTimePeriodType.LastMonth:
+ return ExcelConditionalFormattingConstants.TimePeriods._lastMonth;
- case eExcelConditionalFormattingTimePeriodType.NextMonth:
- return ExcelConditionalFormattingConstants.TimePeriods.NextMonth;
+ case eExcelConditionalFormattingTimePeriodType.LastWeek:
+ return ExcelConditionalFormattingConstants.TimePeriods._lastWeek;
- case eExcelConditionalFormattingTimePeriodType.NextWeek:
- return ExcelConditionalFormattingConstants.TimePeriods.NextWeek;
+ case eExcelConditionalFormattingTimePeriodType.NextMonth:
+ return ExcelConditionalFormattingConstants.TimePeriods._nextMonth;
- case eExcelConditionalFormattingTimePeriodType.ThisMonth:
- return ExcelConditionalFormattingConstants.TimePeriods.ThisMonth;
+ case eExcelConditionalFormattingTimePeriodType.NextWeek:
+ return ExcelConditionalFormattingConstants.TimePeriods._nextWeek;
- case eExcelConditionalFormattingTimePeriodType.ThisWeek:
- return ExcelConditionalFormattingConstants.TimePeriods.ThisWeek;
+ case eExcelConditionalFormattingTimePeriodType.ThisMonth:
+ return ExcelConditionalFormattingConstants.TimePeriods._thisMonth;
- case eExcelConditionalFormattingTimePeriodType.Today:
- return ExcelConditionalFormattingConstants.TimePeriods.Today;
+ case eExcelConditionalFormattingTimePeriodType.ThisWeek:
+ return ExcelConditionalFormattingConstants.TimePeriods._thisWeek;
- case eExcelConditionalFormattingTimePeriodType.Tomorrow:
- return ExcelConditionalFormattingConstants.TimePeriods.Tomorrow;
+ case eExcelConditionalFormattingTimePeriodType.Today:
+ return ExcelConditionalFormattingConstants.TimePeriods._today;
- case eExcelConditionalFormattingTimePeriodType.Yesterday:
- return ExcelConditionalFormattingConstants.TimePeriods.Yesterday;
- }
+ case eExcelConditionalFormattingTimePeriodType.Tomorrow:
+ return ExcelConditionalFormattingConstants.TimePeriods._tomorrow;
- 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 Exception(
- ExcelConditionalFormattingConstants.Errors.UnexistentTimePeriodTypeAttribute);
+ case eExcelConditionalFormattingTimePeriodType.Yesterday:
+ return ExcelConditionalFormattingConstants.TimePeriods._yesterday;
}
+
+ return string.Empty;
}
-}
\ No newline at end of file
+
+ /// <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
index 2628487..9d28645 100644
--- a/EPPlus/ConditionalFormatting/ExcelConditionalFormattingValueObjectType.cs
+++ b/EPPlus/ConditionalFormatting/ExcelConditionalFormattingValueObjectType.cs
@@ -13,210 +13,188 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
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;
+namespace OfficeOpenXml.ConditionalFormatting;
- case eExcelConditionalFormattingValueObjectPosition.Middle:
- return 2;
+/// <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.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;
- }
+ case eExcelConditionalFormattingValueObjectPosition.Middle:
+ return 2;
- // There are "Low", "Middle" and "High". So "High" is the third
- return 3;
- }
+ 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;
+ }
- return 0;
- }
+ // There are "Low", "Middle" and "High". So "High" is the third
+ return 3;
+ }
- /// <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;
+ return 0;
+ }
- case ExcelConditionalFormattingConstants.CfvoType.Max:
- return eExcelConditionalFormattingValueObjectType.Max;
+ /// <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.Num:
- return eExcelConditionalFormattingValueObjectType.Num;
+ case ExcelConditionalFormattingConstants.CfvoType._max:
+ return eExcelConditionalFormattingValueObjectType.Max;
- case ExcelConditionalFormattingConstants.CfvoType.Formula:
- return eExcelConditionalFormattingValueObjectType.Formula;
+ case ExcelConditionalFormattingConstants.CfvoType._num:
+ return eExcelConditionalFormattingValueObjectType.Num;
- case ExcelConditionalFormattingConstants.CfvoType.Percent:
- return eExcelConditionalFormattingValueObjectType.Percent;
+ case ExcelConditionalFormattingConstants.CfvoType._formula:
+ return eExcelConditionalFormattingValueObjectType.Formula;
- case ExcelConditionalFormattingConstants.CfvoType.Percentile:
- return eExcelConditionalFormattingValueObjectType.Percentile;
- }
+ case ExcelConditionalFormattingConstants.CfvoType._percent:
+ return eExcelConditionalFormattingValueObjectType.Percent;
- throw new Exception(
- ExcelConditionalFormattingConstants.Errors.UnexistentCfvoTypeAttribute);
- }
+ case ExcelConditionalFormattingConstants.CfvoType._percentile:
+ return eExcelConditionalFormattingValueObjectType.Percentile;
+ }
- /// <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}
- ExcelConditionalFormattingValueObjectType.GetOrderByPosition(position, ruleType)),
- nameSpaceManager);
+ throw new(ExcelConditionalFormattingConstants.Errors._unexistentCfvoTypeAttribute);
+ }
- if (node == null)
- {
- throw new Exception(
- ExcelConditionalFormattingConstants.Errors.MissingCfvoNode);
- }
+ /// <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);
- return node;
- }
+ if (node == null) {
+ throw new(ExcelConditionalFormattingConstants.Errors._missingCfvoNode);
+ }
- /// <summary>
- ///
- /// </summary>
- /// <param name="type"></param>
- /// <returns></returns>
- public static string GetAttributeByType(
- eExcelConditionalFormattingValueObjectType type)
- {
- switch (type)
- {
- case eExcelConditionalFormattingValueObjectType.Min:
- return ExcelConditionalFormattingConstants.CfvoType.Min;
+ return node;
+ }
- case eExcelConditionalFormattingValueObjectType.Max:
- return ExcelConditionalFormattingConstants.CfvoType.Max;
+ /// <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.Num:
- return ExcelConditionalFormattingConstants.CfvoType.Num;
+ case eExcelConditionalFormattingValueObjectType.Max:
+ return ExcelConditionalFormattingConstants.CfvoType._max;
- case eExcelConditionalFormattingValueObjectType.Formula:
- return ExcelConditionalFormattingConstants.CfvoType.Formula;
+ case eExcelConditionalFormattingValueObjectType.Num:
+ return ExcelConditionalFormattingConstants.CfvoType._num;
- case eExcelConditionalFormattingValueObjectType.Percent:
- return ExcelConditionalFormattingConstants.CfvoType.Percent;
+ case eExcelConditionalFormattingValueObjectType.Formula:
+ return ExcelConditionalFormattingConstants.CfvoType._formula;
- case eExcelConditionalFormattingValueObjectType.Percentile:
- return ExcelConditionalFormattingConstants.CfvoType.Percentile;
- }
+ case eExcelConditionalFormattingValueObjectType.Percent:
+ return ExcelConditionalFormattingConstants.CfvoType._percent;
- return string.Empty;
- }
+ case eExcelConditionalFormattingValueObjectType.Percentile:
+ return ExcelConditionalFormattingConstants.CfvoType._percentile;
+ }
- /// <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;
+ return string.Empty;
+ }
- case eExcelConditionalFormattingRuleType.ThreeIconSet:
- case eExcelConditionalFormattingRuleType.FourIconSet:
- case eExcelConditionalFormattingRuleType.FiveIconSet:
- return ExcelConditionalFormattingConstants.Paths.IconSet;
+ /// <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.DataBar:
- return ExcelConditionalFormattingConstants.Paths.DataBar;
- }
+ case eExcelConditionalFormattingRuleType.ThreeIconSet:
+ case eExcelConditionalFormattingRuleType.FourIconSet:
+ case eExcelConditionalFormattingRuleType.FiveIconSet:
+ return ExcelConditionalFormattingConstants.Paths._iconSet;
- return string.Empty;
- }
+ case eExcelConditionalFormattingRuleType.DataBar:
+ return ExcelConditionalFormattingConstants.Paths._dataBar;
+ }
- /// <summary>
- ///
- /// </summary>
- /// <param name="nodeType"></param>
- /// <returns></returns>
- public static string GetNodePathByNodeType(
- eExcelConditionalFormattingValueObjectNodeType nodeType)
- {
- switch(nodeType)
- {
- case eExcelConditionalFormattingValueObjectNodeType.Cfvo:
- return ExcelConditionalFormattingConstants.Paths.Cfvo;
+ return string.Empty;
+ }
- case eExcelConditionalFormattingValueObjectNodeType.Color:
- return ExcelConditionalFormattingConstants.Paths.Color;
- }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="nodeType"></param>
+ /// <returns></returns>
+ public static string GetNodePathByNodeType(
+ eExcelConditionalFormattingValueObjectNodeType nodeType) {
+ switch (nodeType) {
+ case eExcelConditionalFormattingValueObjectNodeType.Cfvo:
+ return ExcelConditionalFormattingConstants.Paths._cfvo;
- return string.Empty;
- }
- }
-}
\ No newline at end of file
+ case eExcelConditionalFormattingValueObjectNodeType.Color:
+ return ExcelConditionalFormattingConstants.Paths._color;
+ }
+
+ return string.Empty;
+ }
+}
diff --git a/EPPlus/ConditionalFormatting/RangeConditionalFormatting.cs b/EPPlus/ConditionalFormatting/RangeConditionalFormatting.cs
index 841461d..debf061 100644
--- a/EPPlus/ConditionalFormatting/RangeConditionalFormatting.cs
+++ b/EPPlus/ConditionalFormatting/RangeConditionalFormatting.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,519 +13,426 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.Utils;
+
+using System.Drawing;
using OfficeOpenXml.ConditionalFormatting.Contracts;
+using OfficeOpenXml.Utils;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- internal class RangeConditionalFormatting
- : IRangeConditionalFormatting
- {
- #region Public Properties
- public ExcelWorksheet _worksheet;
- public ExcelAddress _address;
- #endregion Public Properties
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- public RangeConditionalFormatting(
- ExcelWorksheet worksheet,
- ExcelAddress address)
- {
- Require.Argument(worksheet).IsNotNull("worksheet");
- Require.Argument(address).IsNotNull("address");
+internal class RangeConditionalFormatting : IRangeConditionalFormatting {
+ public ExcelWorksheet _worksheet;
+ public ExcelAddress _address;
- _worksheet = worksheet;
- _address = address;
- }
- #endregion Constructors
+ public RangeConditionalFormatting(ExcelWorksheet worksheet, ExcelAddress address) {
+ Require.Argument(worksheet).IsNotNull("worksheet");
+ Require.Argument(address).IsNotNull("address");
- #region Conditional Formatting Rule Types
- /// <summary>
- /// Add AboveOrEqualAverage Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingAverageGroup AddAboveAverage()
- {
- return _worksheet.ConditionalFormatting.AddAboveAverage(
- _address);
- }
+ _worksheet = worksheet;
+ _address = address;
+ }
- /// <summary>
- /// Add AboveOrEqualAverage Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingAverageGroup AddAboveOrEqualAverage()
- {
- return _worksheet.ConditionalFormatting.AddAboveOrEqualAverage(
- _address);
- }
+ /// <summary>
+ /// Add AboveOrEqualAverage Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingAverageGroup AddAboveAverage() {
+ return _worksheet.ConditionalFormatting.AddAboveAverage(_address);
+ }
- /// <summary>
- /// Add BelowOrEqualAverage Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingAverageGroup AddBelowAverage()
- {
- return _worksheet.ConditionalFormatting.AddBelowAverage(
- _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 AddBelowOrEqualAverage()
- {
- return _worksheet.ConditionalFormatting.AddBelowOrEqualAverage(
- _address);
- }
+ /// <summary>
+ /// Add BelowOrEqualAverage Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingAverageGroup AddBelowAverage() {
+ return _worksheet.ConditionalFormatting.AddBelowAverage(_address);
+ }
- /// <summary>
- /// Add AboveStdDev Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingStdDevGroup AddAboveStdDev()
- {
- return _worksheet.ConditionalFormatting.AddAboveStdDev(
- _address);
- }
+ /// <summary>
+ /// Add BelowOrEqualAverage Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingAverageGroup AddBelowOrEqualAverage() {
+ return _worksheet.ConditionalFormatting.AddBelowOrEqualAverage(_address);
+ }
- /// <summary>
- /// Add BelowStdDev Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingStdDevGroup AddBelowStdDev()
- {
- return _worksheet.ConditionalFormatting.AddBelowStdDev(
- _address);
- }
+ /// <summary>
+ /// Add AboveStdDev Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingStdDevGroup AddAboveStdDev() {
+ return _worksheet.ConditionalFormatting.AddAboveStdDev(_address);
+ }
- /// <summary>
- /// Add Bottom Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTopBottomGroup AddBottom()
- {
- return _worksheet.ConditionalFormatting.AddBottom(
- _address);
- }
+ /// <summary>
+ /// Add BelowStdDev Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingStdDevGroup AddBelowStdDev() {
+ return _worksheet.ConditionalFormatting.AddBelowStdDev(_address);
+ }
- /// <summary>
- /// Add BottomPercent Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTopBottomGroup AddBottomPercent()
- {
- return _worksheet.ConditionalFormatting.AddBottomPercent(
- _address);
- }
+ /// <summary>
+ /// Add Bottom Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTopBottomGroup AddBottom() {
+ return _worksheet.ConditionalFormatting.AddBottom(_address);
+ }
- /// <summary>
- /// Add Top Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTopBottomGroup AddTop()
- {
- return _worksheet.ConditionalFormatting.AddTop(
- _address);
- }
+ /// <summary>
+ /// Add BottomPercent Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTopBottomGroup AddBottomPercent() {
+ return _worksheet.ConditionalFormatting.AddBottomPercent(_address);
+ }
- /// <summary>
- /// Add TopPercent Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTopBottomGroup AddTopPercent()
- {
- return _worksheet.ConditionalFormatting.AddTopPercent(
- _address);
- }
+ /// <summary>
+ /// Add Top Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTopBottomGroup AddTop() {
+ return _worksheet.ConditionalFormatting.AddTop(_address);
+ }
- /// <summary>
- /// Add Last7Days Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddLast7Days()
- {
- return _worksheet.ConditionalFormatting.AddLast7Days(
- _address);
- }
+ /// <summary>
+ /// Add TopPercent Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTopBottomGroup AddTopPercent() {
+ return _worksheet.ConditionalFormatting.AddTopPercent(_address);
+ }
- /// <summary>
- /// Add LastMonth Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddLastMonth()
- {
- return _worksheet.ConditionalFormatting.AddLastMonth(
- _address);
- }
+ /// <summary>
+ /// Add Last7Days Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddLast7Days() {
+ return _worksheet.ConditionalFormatting.AddLast7Days(_address);
+ }
- /// <summary>
- /// Add LastWeek Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddLastWeek()
- {
- return _worksheet.ConditionalFormatting.AddLastWeek(
- _address);
- }
+ /// <summary>
+ /// Add LastMonth Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddLastMonth() {
+ return _worksheet.ConditionalFormatting.AddLastMonth(_address);
+ }
- /// <summary>
- /// Add NextMonth Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddNextMonth()
- {
- return _worksheet.ConditionalFormatting.AddNextMonth(
- _address);
- }
+ /// <summary>
+ /// Add LastWeek Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddLastWeek() {
+ return _worksheet.ConditionalFormatting.AddLastWeek(_address);
+ }
- /// <summary>
- /// Add NextWeek Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddNextWeek()
- {
- return _worksheet.ConditionalFormatting.AddNextWeek(
- _address);
- }
+ /// <summary>
+ /// Add NextMonth Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddNextMonth() {
+ return _worksheet.ConditionalFormatting.AddNextMonth(_address);
+ }
- /// <summary>
- /// Add ThisMonth Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddThisMonth()
- {
- return _worksheet.ConditionalFormatting.AddThisMonth(
- _address);
- }
+ /// <summary>
+ /// Add NextWeek Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddNextWeek() {
+ return _worksheet.ConditionalFormatting.AddNextWeek(_address);
+ }
- /// <summary>
- /// Add ThisWeek Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddThisWeek()
- {
- return _worksheet.ConditionalFormatting.AddThisWeek(
- _address);
- }
+ /// <summary>
+ /// Add ThisMonth Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddThisMonth() {
+ return _worksheet.ConditionalFormatting.AddThisMonth(_address);
+ }
- /// <summary>
- /// Add Today Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddToday()
- {
- return _worksheet.ConditionalFormatting.AddToday(
- _address);
- }
+ /// <summary>
+ /// Add ThisWeek Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddThisWeek() {
+ return _worksheet.ConditionalFormatting.AddThisWeek(_address);
+ }
- /// <summary>
- /// Add Tomorrow Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddTomorrow()
- {
- return _worksheet.ConditionalFormatting.AddTomorrow(
- _address);
- }
+ /// <summary>
+ /// Add Today Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddToday() {
+ return _worksheet.ConditionalFormatting.AddToday(_address);
+ }
- /// <summary>
- /// Add Yesterday Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingTimePeriodGroup AddYesterday()
- {
- return _worksheet.ConditionalFormatting.AddYesterday(
- _address);
- }
+ /// <summary>
+ /// Add Tomorrow Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddTomorrow() {
+ return _worksheet.ConditionalFormatting.AddTomorrow(_address);
+ }
- /// <summary>
- /// Add BeginsWith Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingBeginsWith AddBeginsWith()
- {
- return _worksheet.ConditionalFormatting.AddBeginsWith(
- _address);
- }
+ /// <summary>
+ /// Add Yesterday Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTimePeriodGroup AddYesterday() {
+ return _worksheet.ConditionalFormatting.AddYesterday(_address);
+ }
- /// <summary>
- /// Add Between Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingBetween AddBetween()
- {
- return _worksheet.ConditionalFormatting.AddBetween(
- _address);
- }
+ /// <summary>
+ /// Add BeginsWith Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingBeginsWith AddBeginsWith() {
+ return _worksheet.ConditionalFormatting.AddBeginsWith(_address);
+ }
- /// <summary>
- /// Add ContainsBlanks Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingContainsBlanks AddContainsBlanks()
- {
- return _worksheet.ConditionalFormatting.AddContainsBlanks(
- _address);
- }
+ /// <summary>
+ /// Add Between Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingBetween AddBetween() {
+ return _worksheet.ConditionalFormatting.AddBetween(_address);
+ }
- /// <summary>
- /// Add ContainsErrors Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingContainsErrors AddContainsErrors()
- {
- return _worksheet.ConditionalFormatting.AddContainsErrors(
- _address);
- }
+ /// <summary>
+ /// Add ContainsBlanks Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingContainsBlanks AddContainsBlanks() {
+ return _worksheet.ConditionalFormatting.AddContainsBlanks(_address);
+ }
- /// <summary>
- /// Add ContainsText Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingContainsText AddContainsText()
- {
- return _worksheet.ConditionalFormatting.AddContainsText(
- _address);
- }
+ /// <summary>
+ /// Add ContainsErrors Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingContainsErrors AddContainsErrors() {
+ return _worksheet.ConditionalFormatting.AddContainsErrors(_address);
+ }
- /// <summary>
- /// Add DuplicateValues Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingDuplicateValues AddDuplicateValues()
- {
- return _worksheet.ConditionalFormatting.AddDuplicateValues(
- _address);
- }
+ /// <summary>
+ /// Add ContainsText Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingContainsText AddContainsText() {
+ return _worksheet.ConditionalFormatting.AddContainsText(_address);
+ }
- /// <summary>
- /// Add EndsWith Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingEndsWith AddEndsWith()
- {
- return _worksheet.ConditionalFormatting.AddEndsWith(
- _address);
- }
+ /// <summary>
+ /// Add DuplicateValues Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingDuplicateValues AddDuplicateValues() {
+ return _worksheet.ConditionalFormatting.AddDuplicateValues(_address);
+ }
- /// <summary>
- /// Add Equal Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingEqual AddEqual()
- {
- return _worksheet.ConditionalFormatting.AddEqual(
- _address);
- }
+ /// <summary>
+ /// Add EndsWith Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingEndsWith AddEndsWith() {
+ return _worksheet.ConditionalFormatting.AddEndsWith(_address);
+ }
- /// <summary>
- /// Add Expression Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingExpression AddExpression()
- {
- return _worksheet.ConditionalFormatting.AddExpression(
- _address);
- }
+ /// <summary>
+ /// Add Equal Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingEqual AddEqual() {
+ return _worksheet.ConditionalFormatting.AddEqual(_address);
+ }
- /// <summary>
- /// Add GreaterThan Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingGreaterThan AddGreaterThan()
- {
- return _worksheet.ConditionalFormatting.AddGreaterThan(
- _address);
- }
+ /// <summary>
+ /// Add Expression Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingExpression AddExpression() {
+ return _worksheet.ConditionalFormatting.AddExpression(_address);
+ }
- /// <summary>
- /// Add GreaterThanOrEqual Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingGreaterThanOrEqual AddGreaterThanOrEqual()
- {
- return _worksheet.ConditionalFormatting.AddGreaterThanOrEqual(
- _address);
- }
+ /// <summary>
+ /// Add GreaterThan Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingGreaterThan AddGreaterThan() {
+ return _worksheet.ConditionalFormatting.AddGreaterThan(_address);
+ }
- /// <summary>
- /// Add LessThan Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingLessThan AddLessThan()
- {
- return _worksheet.ConditionalFormatting.AddLessThan(
- _address);
- }
+ /// <summary>
+ /// Add GreaterThanOrEqual Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingGreaterThanOrEqual AddGreaterThanOrEqual() {
+ return _worksheet.ConditionalFormatting.AddGreaterThanOrEqual(_address);
+ }
- /// <summary>
- /// Add LessThanOrEqual Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingLessThanOrEqual AddLessThanOrEqual()
- {
- return _worksheet.ConditionalFormatting.AddLessThanOrEqual(
- _address);
- }
+ /// <summary>
+ /// Add LessThan Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingLessThan AddLessThan() {
+ return _worksheet.ConditionalFormatting.AddLessThan(_address);
+ }
- /// <summary>
- /// Add NotBetween Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingNotBetween AddNotBetween()
- {
- return _worksheet.ConditionalFormatting.AddNotBetween(
- _address);
- }
+ /// <summary>
+ /// Add LessThanOrEqual Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingLessThanOrEqual AddLessThanOrEqual() {
+ return _worksheet.ConditionalFormatting.AddLessThanOrEqual(_address);
+ }
- /// <summary>
- /// Add NotContainsBlanks Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingNotContainsBlanks AddNotContainsBlanks()
- {
- return _worksheet.ConditionalFormatting.AddNotContainsBlanks(
- _address);
- }
+ /// <summary>
+ /// Add NotBetween Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingNotBetween AddNotBetween() {
+ return _worksheet.ConditionalFormatting.AddNotBetween(_address);
+ }
- /// <summary>
- /// Add NotContainsErrors Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingNotContainsErrors AddNotContainsErrors()
- {
- return _worksheet.ConditionalFormatting.AddNotContainsErrors(
- _address);
- }
+ /// <summary>
+ /// Add NotContainsBlanks Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingNotContainsBlanks AddNotContainsBlanks() {
+ return _worksheet.ConditionalFormatting.AddNotContainsBlanks(_address);
+ }
- /// <summary>
- /// Add NotContainsText Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingNotContainsText AddNotContainsText()
- {
- return _worksheet.ConditionalFormatting.AddNotContainsText(
- _address);
- }
+ /// <summary>
+ /// Add NotContainsErrors Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingNotContainsErrors AddNotContainsErrors() {
+ return _worksheet.ConditionalFormatting.AddNotContainsErrors(_address);
+ }
- /// <summary>
- /// Add NotEqual Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingNotEqual AddNotEqual()
- {
- return _worksheet.ConditionalFormatting.AddNotEqual(
- _address);
- }
+ /// <summary>
+ /// Add NotContainsText Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingNotContainsText AddNotContainsText() {
+ return _worksheet.ConditionalFormatting.AddNotContainsText(_address);
+ }
- /// <summary>
- /// Add UniqueValues Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingUniqueValues AddUniqueValues()
- {
- return _worksheet.ConditionalFormatting.AddUniqueValues(
- _address);
- }
+ /// <summary>
+ /// Add NotEqual Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingNotEqual AddNotEqual() {
+ return _worksheet.ConditionalFormatting.AddNotEqual(_address);
+ }
- /// <summary>
- /// Add ThreeColorScale Conditional Formatting
- /// </summary>
- /// <returns></returns>
- public IExcelConditionalFormattingThreeColorScale AddThreeColorScale()
- {
- return (IExcelConditionalFormattingThreeColorScale)(_worksheet.ConditionalFormatting.AddRule(
+ /// <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(
+ /// <summary>
+ /// Add TwoColorScale Conditional Formatting
+ /// </summary>
+ /// <returns></returns>
+ public IExcelConditionalFormattingTwoColorScale AddTwoColorScale() {
+ return (IExcelConditionalFormattingTwoColorScale)(_worksheet.ConditionalFormatting.AddRule(
eExcelConditionalFormattingRuleType.TwoColorScale,
_address));
- }
-
- /// <summary>
- /// Adds a ThreeIconSet rule
- /// </summary>
- /// <param name="IconSet"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingThreeIconSet<eExcelconditionalFormatting3IconsSetType> AddThreeIconSet(eExcelconditionalFormatting3IconsSetType IconSet)
- {
- var rule = (IExcelConditionalFormattingThreeIconSet<eExcelconditionalFormatting3IconsSetType>)(_worksheet.ConditionalFormatting.AddRule(
- eExcelConditionalFormattingRuleType.ThreeIconSet,
- _address));
- rule.IconSet = IconSet;
- return rule;
- }
-
- /// <summary>
- /// Adds a FourIconSet rule
- /// </summary>
- /// <param name="IconSet"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType> AddFourIconSet(eExcelconditionalFormatting4IconsSetType IconSet)
- {
- var rule = (IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType>)(_worksheet.ConditionalFormatting.AddRule(
- eExcelConditionalFormattingRuleType.FourIconSet,
- _address));
- rule.IconSet = IconSet;
- return rule;
- }
-
- /// <summary>
- /// Adds a FiveIconSet rule
- /// </summary>
- /// <param name="IconSet"></param>
- /// <returns></returns>
- public IExcelConditionalFormattingFiveIconSet AddFiveIconSet(eExcelconditionalFormatting5IconsSetType IconSet)
- {
- var rule = (IExcelConditionalFormattingFiveIconSet)(_worksheet.ConditionalFormatting.AddRule(
- eExcelConditionalFormattingRuleType.FiveIconSet,
- _address));
- rule.IconSet = IconSet;
- return rule;
- }
-
- /// <summary>
- /// Adds a Databar rule
- /// </summary>
- /// <param name="Color">The color of the databar</param>
- /// <returns></returns>
- public IExcelConditionalFormattingDataBarGroup AddDatabar(System.Drawing.Color Color)
- {
- var rule = (IExcelConditionalFormattingDataBarGroup)(_worksheet.ConditionalFormatting.AddRule(
- eExcelConditionalFormattingRuleType.DataBar,
- _address));
- rule.Color = Color;
- return rule;
- }
- #endregion Conditional Formatting Rule Types
}
-}
\ No newline at end of file
+
+ /// <summary>
+ /// Adds a ThreeIconSet rule
+ /// </summary>
+ /// <param name="iconSet"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingThreeIconSet<eExcelconditionalFormatting3IconsSetType> AddThreeIconSet(
+ eExcelconditionalFormatting3IconsSetType iconSet) {
+ var rule =
+ (IExcelConditionalFormattingThreeIconSet<eExcelconditionalFormatting3IconsSetType>)(_worksheet.ConditionalFormatting.AddRule(
+ eExcelConditionalFormattingRuleType.ThreeIconSet,
+ _address));
+ rule.IconSet = iconSet;
+ return rule;
+ }
+
+ /// <summary>
+ /// Adds a FourIconSet rule
+ /// </summary>
+ /// <param name="iconSet"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType> AddFourIconSet(
+ eExcelconditionalFormatting4IconsSetType iconSet) {
+ var rule =
+ (IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType>)(_worksheet.ConditionalFormatting.AddRule(
+ eExcelConditionalFormattingRuleType.FourIconSet,
+ _address));
+ rule.IconSet = iconSet;
+ return rule;
+ }
+
+ /// <summary>
+ /// Adds a FiveIconSet rule
+ /// </summary>
+ /// <param name="iconSet"></param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingFiveIconSet AddFiveIconSet(
+ eExcelconditionalFormatting5IconsSetType iconSet) {
+ var rule = (IExcelConditionalFormattingFiveIconSet)(_worksheet.ConditionalFormatting.AddRule(
+ eExcelConditionalFormattingRuleType.FiveIconSet,
+ _address));
+ rule.IconSet = iconSet;
+ return rule;
+ }
+
+ /// <summary>
+ /// Adds a Databar rule
+ /// </summary>
+ /// <param name="color">The color of the databar</param>
+ /// <returns></returns>
+ public IExcelConditionalFormattingDataBarGroup AddDatabar(Color color) {
+ var rule = (IExcelConditionalFormattingDataBarGroup)(_worksheet.ConditionalFormatting.AddRule(
+ eExcelConditionalFormattingRuleType.DataBar,
+ _address));
+ rule.Color = color;
+ return rule;
+ }
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveAverage.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveAverage.cs
index f35fe47..6e82c2f 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveAverage.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveAverage.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,110 +13,82 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingAboveAverage
+/// </summary>
+public class ExcelConditionalFormattingAboveAverage : ExcelConditionalFormattingAverageGroup {
/// <summary>
- /// ExcelConditionalFormattingAboveAverage
+ ///
/// </summary>
- public class ExcelConditionalFormattingAboveAverage
- : ExcelConditionalFormattingAverageGroup
- {
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingAboveAverage(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.AboveAverage,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- AboveAverage = true;
- EqualAverage = false;
- }
+ AboveAverage = true;
+ EqualAverage = false;
}
+ }
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingAboveAverage(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingAboveAverage(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveOrEqualAverage.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveOrEqualAverage.cs
index f87e2a8..60a89d0 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveOrEqualAverage.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveOrEqualAverage.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,110 +13,83 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingAboveOrEqualAverage
+/// </summary>
+public class ExcelConditionalFormattingAboveOrEqualAverage
+ : ExcelConditionalFormattingAverageGroup {
/// <summary>
- /// ExcelConditionalFormattingAboveOrEqualAverage
+ ///
/// </summary>
- public class ExcelConditionalFormattingAboveOrEqualAverage
- : ExcelConditionalFormattingAverageGroup
- {
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingAboveOrEqualAverage(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.AboveOrEqualAverage,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- AboveAverage = true;
- EqualAverage = true;
- }
+ AboveAverage = true;
+ EqualAverage = true;
}
+ }
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingAboveOrEqualAverage(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingAboveOrEqualAverage(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveStdDev.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveStdDev.cs
index 5b0fb33..0883462 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveStdDev.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAboveStdDev.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,111 +13,85 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingAboveStdDev
- /// </summary>
- public class ExcelConditionalFormattingAboveStdDev
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingStdDevGroup
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingAboveStdDev(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.AboveStdDev,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- AboveAverage = true;
- StdDev = 1;
- }
+ AboveAverage = true;
+ StdDev = 1;
}
+ }
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingAboveStdDev(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingAboveStdDev(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAverageGroup.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAverageGroup.cs
index dd11eb8..cebdb51 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAverageGroup.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingAverageGroup.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,51 +13,43 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingAverageGroup
- /// </summary>
- public class ExcelConditionalFormattingAverageGroup
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingAverageGroup
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <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(
+/// <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,
@@ -65,62 +57,40 @@
XmlNode itemElementNode,
XmlNamespaceManager namespaceManager)
: base(
- type,
- address,
- priority,
- worksheet,
- itemElementNode,
- (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager)
- {
- }
+ type,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : 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(
+ /// <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)
- {
- }
+ : 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(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(type, address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBeginsWith.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBeginsWith.cs
index a5132c5..9dc918e 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBeginsWith.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBeginsWith.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,138 +13,100 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingBeginsWith
- /// </summary>
- public class ExcelConditionalFormattingBeginsWith
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingBeginsWith
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingBeginsWith(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.BeginsWith,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.BeginsWith;
- Text = string.Empty;
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingBeginsWith(
+ /// <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)
- {
- }
- #endregion Constructors
+ : 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);
- #region Exposed Properties
- /// <summary>
- /// The text to search in the beginning of the cell
- /// </summary>
- public string Text
- {
- get
- {
- return GetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.TextAttribute);
- }
- set
- {
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.TextAttribute,
- value);
-
- Formula = string.Format(
+ Formula = string.Format(
"LEFT({0},LEN(\"{1}\"))=\"{1}\"",
Address.Start.Address,
value.Replace("\"", "\"\""));
- }
}
- #endregion Exposed Properties
-
- /****************************************************************************************/
}
-}
\ No newline at end of file
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowAverage.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowAverage.cs
index f763b47..be13fa3 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowAverage.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowAverage.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,110 +13,82 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingBelowAverage
+/// </summary>
+public class ExcelConditionalFormattingBelowAverage : ExcelConditionalFormattingAverageGroup {
/// <summary>
- /// ExcelConditionalFormattingBelowAverage
+ ///
/// </summary>
- public class ExcelConditionalFormattingBelowAverage
- : ExcelConditionalFormattingAverageGroup
- {
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingBelowAverage(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.BelowAverage,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- AboveAverage = false;
- EqualAverage = false;
- }
+ AboveAverage = false;
+ EqualAverage = false;
}
+ }
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingBelowAverage(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingBelowAverage(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowOrEqualAverage.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowOrEqualAverage.cs
index 42d88a5..39eb327 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowOrEqualAverage.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowOrEqualAverage.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,110 +13,83 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingBelowOrEqualAverage
+/// </summary>
+public class ExcelConditionalFormattingBelowOrEqualAverage
+ : ExcelConditionalFormattingAverageGroup {
/// <summary>
- /// ExcelConditionalFormattingBelowOrEqualAverage
+ ///
/// </summary>
- public class ExcelConditionalFormattingBelowOrEqualAverage
- : ExcelConditionalFormattingAverageGroup
- {
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingBelowOrEqualAverage(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.BelowOrEqualAverage,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- AboveAverage = false;
- EqualAverage = true;
- }
+ AboveAverage = false;
+ EqualAverage = true;
}
+ }
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingBelowOrEqualAverage(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingBelowOrEqualAverage(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowStdDev.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowStdDev.cs
index 95be06d..b2419f6 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowStdDev.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBelowStdDev.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,111 +13,85 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingBelowStdDev
- /// </summary>
- public class ExcelConditionalFormattingBelowStdDev
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingStdDevGroup
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingBelowStdDev(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.BelowStdDev,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- AboveAverage = false;
- StdDev = 1;
- }
+ AboveAverage = false;
+ StdDev = 1;
}
+ }
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingBelowStdDev(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingBelowStdDev(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBetween.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBetween.cs
index 27c1446..b27a308 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBetween.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBetween.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,86 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingBetween
- /// </summary>
- public class ExcelConditionalFormattingBetween
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingBetween
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingBetween(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.Between,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.Between;
- Formula = string.Empty;
- Formula2 = string.Empty;
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingBetween(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottom.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottom.cs
index bea5fd7..4b23f49 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottom.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottom.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,86 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingBottom
- /// </summary>
- public class ExcelConditionalFormattingBottom
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingTopBottomGroup
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingBottom(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.Bottom,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Bottom = true;
- Percent = false;
- Rank = 10; // Last 10 values
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingBottom(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottomPercent.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottomPercent.cs
index a95ad09..494078d 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottomPercent.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingBottomPercent.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,86 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingBottomPercent
- /// </summary>
- public class ExcelConditionalFormattingBottomPercent
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingTopBottomGroup
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingBottomPercent(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.BottomPercent,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Bottom = true;
- Percent = true;
- Rank = 10; // Last 10 percent
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingBottomPercent(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsBlanks.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsBlanks.cs
index 00b1b1f..16ea6c2 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsBlanks.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsBlanks.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingContainsBlanks
- /// </summary>
- public class ExcelConditionalFormattingContainsBlanks
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingContainsBlanks
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingContainsBlanks(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.ContainsBlanks,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Formula = string.Format(
- "LEN(TRIM({0}))=0",
- Address.Start.Address);
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingContainsBlanks(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsErrors.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsErrors.cs
index 7c06f64..5c743dc 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsErrors.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsErrors.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingContainsErrors
- /// </summary>
- public class ExcelConditionalFormattingContainsErrors
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingContainsErrors
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingContainsErrors(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.ContainsErrors,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Formula = string.Format(
- "ISERROR({0})",
- Address.Start.Address);
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingContainsErrors(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsText.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsText.cs
index 59096cf..88a4d43 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsText.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingContainsText.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,138 +13,100 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingContainsText
- /// </summary>
- public class ExcelConditionalFormattingContainsText
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingContainsText
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingContainsText(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.ContainsText,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.ContainsText;
- Text = string.Empty;
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingContainsText(
+ /// <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)
- {
- }
- #endregion Constructors
+ : 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);
- #region Exposed Properties
- /// <summary>
- /// The text to search inside the cell
- /// </summary>
- public string Text
- {
- get
- {
- return GetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.TextAttribute);
- }
- set
- {
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.TextAttribute,
- value);
-
- Formula = string.Format(
+ Formula = string.Format(
"NOT(ISERROR(SEARCH(\"{1}\",{0})))",
Address.Start.Address,
value.Replace("\"", "\"\""));
- }
}
- #endregion Exposed Properties
-
- /****************************************************************************************/
}
-}
\ No newline at end of file
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingDataBar.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingDataBar.cs
index 2db9b02..ed32ace 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingDataBar.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingDataBar.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,221 +13,157 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
+
using System.Drawing;
+using System.Globalization;
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-using System.Globalization;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// Databar
- /// </summary>
- public class ExcelConditionalFormattingDataBar
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingDataBarGroup
- {
- /****************************************************************************************/
- #region Private Properties
+namespace OfficeOpenXml.ConditionalFormatting;
- #endregion Private Properties
-
- /****************************************************************************************/
-
- #region Constructors
- /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
- {
- SchemaNodeOrder = new string[] { "cfvo", "color" };
- //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 ExcelConditionalFormattingIconDataBarValue(
- type,
- address,
- worksheet,
- node,
- namespaceManager);
- high = true;
- }
- else
- {
- HighValue = new ExcelConditionalFormattingIconDataBarValue(
- 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 ExcelConditionalFormattingIconDataBarValue(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 ExcelConditionalFormattingIconDataBarValue(eExcelConditionalFormattingValueObjectType.Max,
- 0,
- "",
- eExcelConditionalFormattingRuleType.DataBar,
- address,
- priority,
- worksheet,
- highNode,
- namespaceManager);
- }
- Type = type;
+/// <summary>
+/// Databar
+/// </summary>
+public class ExcelConditionalFormattingDataBar
+ : ExcelConditionalFormattingRule,
+ IExcelConditionalFormattingDataBarGroup {
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ SchemaNodeOrder = new[] { "cfvo", "color" };
+ //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);
- /// <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)
- {
- }
+ 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);
- /// <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)
- {
- }
- #endregion Constructors
- private const string _showValuePath="d:dataBar/@showValue";
- public bool ShowValue
- {
- get
- {
- return GetXmlNodeBool(_showValuePath, true);
- }
- set
- {
- SetXmlNodeBool(_showValuePath, value);
- }
- }
-
-
- public ExcelConditionalFormattingIconDataBarValue LowValue
- {
- get;
- internal set;
- }
-
- public ExcelConditionalFormattingIconDataBarValue HighValue
- {
- get;
- internal set;
- }
-
-
- private const string _colorPath = "d:dataBar/d:color/@rgb";
- public Color Color
- {
- get
- {
- var rgb=GetXmlNodeString(_colorPath);
- if(!string.IsNullOrEmpty(rgb))
- {
- return Color.FromArgb(int.Parse(rgb, NumberStyles.HexNumber));
- }
- return Color.White;
- }
- set
- {
- SetXmlNodeString(_colorPath, value.ToArgb().ToString("X"));
- }
- }
+ 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);
}
-}
\ No newline at end of file
+ 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; }
+
+ private const string _colorPath = "d:dataBar/d:color/@rgb";
+
+ public Color Color {
+ get {
+ var rgb = GetXmlNodeString(_colorPath);
+ if (!string.IsNullOrEmpty(rgb)) {
+ return Color.FromArgb(int.Parse(rgb, NumberStyles.HexNumber));
+ }
+ return Color.White;
+ }
+ set => SetXmlNodeString(_colorPath, value.ToArgb().ToString("X"));
+ }
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingDuplicateValues.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingDuplicateValues.cs
index d7efca8..1231fc9 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingDuplicateValues.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingDuplicateValues.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,106 +13,78 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingDuplicateValues
- /// </summary>
- public class ExcelConditionalFormattingDuplicateValues
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingDuplicateValues
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingDuplicateValues(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
- {
- }
+ eExcelConditionalFormattingRuleType.DuplicateValues,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingDuplicateValues(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingDuplicateValues(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingEndsWith.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingEndsWith.cs
index d9b58c3..d02ed50 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingEndsWith.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingEndsWith.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,138 +13,100 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingEndsWith
- /// </summary>
- public class ExcelConditionalFormattingEndsWith
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingEndsWith
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingEndsWith(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.EndsWith,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.EndsWith;
- Text = string.Empty;
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingEndsWith(
+ /// <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)
- {
- }
- #endregion Constructors
+ : 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);
- #region Exposed Properties
- /// <summary>
- /// The text to search in the end of the cell
- /// </summary>
- public string Text
- {
- get
- {
- return GetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.TextAttribute);
- }
- set
- {
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.TextAttribute,
- value);
-
- Formula = string.Format(
+ Formula = string.Format(
"RIGHT({0},LEN(\"{1}\"))=\"{1}\"",
Address.Start.Address,
value.Replace("\"", "\"\""));
- }
}
- #endregion Exposed Properties
-
- /****************************************************************************************/
}
-}
\ No newline at end of file
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingEqual.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingEqual.cs
index a93a67d..8a6ed42 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingEqual.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingEqual.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,111 +13,85 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingEqual
- /// </summary>
- public class ExcelConditionalFormattingEqual
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingEqual
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingEqual(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.Equal,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.Equal;
- Formula = string.Empty;
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingEqual(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingExpression.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingExpression.cs
index c653590..8ba9823 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingExpression.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingExpression.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,110 +13,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingExpression
- /// </summary>
- public class ExcelConditionalFormattingExpression
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingExpression
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingExpression(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.Expression,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Formula = string.Empty;
- }
+ Formula = string.Empty;
}
+ }
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingExpression(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingExpression(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingFiveIconSet.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingFiveIconSet.cs
index 627128f..8c557d7 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingFiveIconSet.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingFiveIconSet.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,168 +13,137 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingThreeIconSet
+/// </summary>
+public class ExcelConditionalFormattingFiveIconSet
+ : ExcelConditionalFormattingIconSetBase<eExcelconditionalFormatting5IconsSetType>,
+ IExcelConditionalFormattingFiveIconSet {
/// <summary>
- /// ExcelConditionalFormattingThreeIconSet
+ ///
/// </summary>
- public class ExcelConditionalFormattingFiveIconSet
- : ExcelConditionalFormattingIconSetBase<eExcelconditionalFormatting5IconsSetType>, IExcelConditionalFormattingFiveIconSet
- {
- /****************************************************************************************/
-
- #region Private Properties
-
- #endregion Private Properties
-
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingFiveIconSet(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
- {
- if (itemElementNode != null && itemElementNode.HasChildNodes)
- {
- XmlNode iconNode4 = TopNode.SelectSingleNode("d:iconSet/d:cfvo[position()=4]", NameSpaceManager);
- Icon4 = new ExcelConditionalFormattingIconDataBarValue(
- eExcelConditionalFormattingRuleType.FiveIconSet,
- address,
- worksheet,
- iconNode4,
- namespaceManager);
-
- XmlNode iconNode5 = TopNode.SelectSingleNode("d:iconSet/d:cfvo[position()=5]", NameSpaceManager);
- Icon5 = new ExcelConditionalFormattingIconDataBarValue(
- 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);
+ eExcelConditionalFormattingRuleType.FiveIconSet,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : 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);
- Icon4 = new ExcelConditionalFormattingIconDataBarValue(eExcelConditionalFormattingValueObjectType.Percent,
- 60,
- "",
- eExcelConditionalFormattingRuleType.ThreeIconSet,
- address,
- priority,
- 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);
- var iconNode5 = iconSetNode.OwnerDocument.CreateElement(ExcelConditionalFormattingConstants.Paths.Cfvo, ExcelPackage.schemaMain);
- iconSetNode.AppendChild(iconNode5);
+ Icon4 = new(
+ eExcelConditionalFormattingValueObjectType.Percent,
+ 60,
+ "",
+ eExcelConditionalFormattingRuleType.ThreeIconSet,
+ address,
+ priority,
+ worksheet,
+ iconNode4,
+ namespaceManager);
- Icon5 = new ExcelConditionalFormattingIconDataBarValue(eExcelConditionalFormattingValueObjectType.Percent,
- 80,
- "",
- eExcelConditionalFormattingRuleType.ThreeIconSet,
- address,
- priority,
- worksheet,
- iconNode5,
- 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingFiveIconSet(
+ /// <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)
- {
- }
- #endregion Constructors
+ : this(address, priority, worksheet, null, null) {}
- public ExcelConditionalFormattingIconDataBarValue Icon5
- {
- get;
- internal set;
- }
+ public ExcelConditionalFormattingIconDataBarValue Icon5 { get; internal set; }
- public ExcelConditionalFormattingIconDataBarValue Icon4
- {
- get;
- internal set;
- }
- }
- }
+ public ExcelConditionalFormattingIconDataBarValue Icon4 { get; internal set; }
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingFourIconSet.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingFourIconSet.cs
index 476441f..14430b9 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingFourIconSet.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingFourIconSet.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,142 +13,109 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingThreeIconSet
+/// </summary>
+public class ExcelConditionalFormattingFourIconSet
+ : ExcelConditionalFormattingIconSetBase<eExcelconditionalFormatting4IconsSetType>,
+ IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType> {
/// <summary>
- /// ExcelConditionalFormattingThreeIconSet
+ ///
/// </summary>
- public class ExcelConditionalFormattingFourIconSet
- : ExcelConditionalFormattingIconSetBase<eExcelconditionalFormatting4IconsSetType>, IExcelConditionalFormattingFourIconSet<eExcelconditionalFormatting4IconsSetType>
- {
- /****************************************************************************************/
-
- #region Private Properties
-
- #endregion Private Properties
-
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingFourIconSet(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
- {
- if(itemElementNode!=null && itemElementNode.HasChildNodes)
- {
- XmlNode iconNode4 = TopNode.SelectSingleNode("d:iconSet/d:cfvo[position()=4]", NameSpaceManager);
- Icon4 = new ExcelConditionalFormattingIconDataBarValue(
- 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);
+ eExcelConditionalFormattingRuleType.FourIconSet,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : 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 ExcelConditionalFormattingIconDataBarValue(eExcelConditionalFormattingValueObjectType.Percent,
- 75,
- "",
- eExcelConditionalFormattingRuleType.ThreeIconSet,
- address,
- priority,
- worksheet,
- iconNode4,
- namespaceManager);
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingFourIconSet(
+ /// <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)
- {
- }
- #endregion Constructors
+ : this(address, priority, worksheet, null, null) {}
- public ExcelConditionalFormattingIconDataBarValue Icon4
- {
- get;
- internal set;
- }
- }
- }
+ public ExcelConditionalFormattingIconDataBarValue Icon4 { get; internal set; }
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThan.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThan.cs
index ea5ecac..2e3d9ee 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThan.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThan.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,111 +13,85 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingGreaterThan
- /// </summary>
- public class ExcelConditionalFormattingGreaterThan
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingGreaterThan
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingGreaterThan(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.GreaterThan,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.GreaterThan;
- Formula = string.Empty;
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingGreaterThan(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThanOrEqual.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThanOrEqual.cs
index f0d652b..6a19464 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThanOrEqual.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingGreaterThanOrEqual.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,111 +13,85 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingGreaterThanOrEqual
- /// </summary>
- public class ExcelConditionalFormattingGreaterThanOrEqual
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingGreaterThanOrEqual
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingGreaterThanOrEqual(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.GreaterThanOrEqual,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.GreaterThanOrEqual;
- Formula = string.Empty;
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingGreaterThanOrEqual(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLast7Days.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLast7Days.cs
index ef70a93..e2593d3 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLast7Days.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLast7Days.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingLast7Days
+/// </summary>
+public class ExcelConditionalFormattingLast7Days : ExcelConditionalFormattingTimePeriodGroup {
/// <summary>
- /// ExcelConditionalFormattingLast7Days
+ ///
/// </summary>
- public class ExcelConditionalFormattingLast7Days
- : ExcelConditionalFormattingTimePeriodGroup
- {
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingLast7Days(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.Last7Days,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- 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);
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingLast7Days(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastMonth.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastMonth.cs
index 90689d4..1d31a44 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastMonth.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastMonth.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingLastMonth
+/// </summary>
+public class ExcelConditionalFormattingLastMonth : ExcelConditionalFormattingTimePeriodGroup {
/// <summary>
- /// ExcelConditionalFormattingLastMonth
+ ///
/// </summary>
- public class ExcelConditionalFormattingLastMonth
- : ExcelConditionalFormattingTimePeriodGroup
- {
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingLastMonth(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.LastMonth,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- 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);
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingLastMonth(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastWeek.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastWeek.cs
index b356496..05c6513 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastWeek.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLastWeek.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingLastWeek
+/// </summary>
+public class ExcelConditionalFormattingLastWeek : ExcelConditionalFormattingTimePeriodGroup {
/// <summary>
- /// ExcelConditionalFormattingLastWeek
+ ///
/// </summary>
- public class ExcelConditionalFormattingLastWeek
- : ExcelConditionalFormattingTimePeriodGroup
- {
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingLastWeek(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.LastWeek,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- 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);
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingLastWeek(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThan.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThan.cs
index 91cb2ac..de178ec 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThan.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThan.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,111 +13,85 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingLessThan
- /// </summary>
- public class ExcelConditionalFormattingLessThan
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingLessThan
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingLessThan(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.LessThan,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.LessThan;
- Formula = string.Empty;
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingLessThan(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThanOrEqual.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThanOrEqual.cs
index e774cf6..7c43a2e 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThanOrEqual.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingLessThanOrEqual.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,111 +13,85 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingLessThanOrEqual
- /// </summary>
- public class ExcelConditionalFormattingLessThanOrEqual
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingLessThanOrEqual
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingLessThanOrEqual(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.LessThanOrEqual,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.LessThanOrEqual;
- Formula = string.Empty;
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingLessThanOrEqual(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextMonth.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextMonth.cs
index 98933a6..3d756f4 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextMonth.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextMonth.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingNextMonth
+/// </summary>
+public class ExcelConditionalFormattingNextMonth : ExcelConditionalFormattingTimePeriodGroup {
/// <summary>
- /// ExcelConditionalFormattingNextMonth
+ ///
/// </summary>
- public class ExcelConditionalFormattingNextMonth
- : ExcelConditionalFormattingTimePeriodGroup
- {
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingNextMonth(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.NextMonth,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- 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);
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingNextMonth(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextWeek.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextWeek.cs
index ed610bd..95726a1 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextWeek.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNextWeek.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingNextWeek
+/// </summary>
+public class ExcelConditionalFormattingNextWeek : ExcelConditionalFormattingTimePeriodGroup {
/// <summary>
- /// ExcelConditionalFormattingNextWeek
+ ///
/// </summary>
- public class ExcelConditionalFormattingNextWeek
- : ExcelConditionalFormattingTimePeriodGroup
- {
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingNextWeek(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.NextWeek,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- 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);
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingNextWeek(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotBetween.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotBetween.cs
index 116dd6d..71c565c 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotBetween.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotBetween.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,86 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingNotBetween
- /// </summary>
- public class ExcelConditionalFormattingNotBetween
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingNotBetween
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingNotBetween(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.NotBetween,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.NotBetween;
- Formula = string.Empty;
- Formula2 = string.Empty;
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingNotBetween(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsBlanks.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsBlanks.cs
index 8607db4..b0e06b2 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsBlanks.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsBlanks.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingNotContainsBlanks
- /// </summary>
- public class ExcelConditionalFormattingNotContainsBlanks
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingNotContainsBlanks
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingNotContainsBlanks(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.NotContainsBlanks,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Formula = string.Format(
- "LEN(TRIM({0}))>0",
- Address.Start.Address);
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingNotContainsBlanks(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsErrors.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsErrors.cs
index 9b30895..7d42bd3 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsErrors.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsErrors.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingNotContainsErrors
- /// </summary>
- public class ExcelConditionalFormattingNotContainsErrors
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingNotContainsErrors
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingNotContainsErrors(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.NotContainsErrors,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Formula = string.Format(
- "NOT(ISERROR({0}))",
- Address.Start.Address);
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingNotContainsErrors(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsText.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsText.cs
index 7b8ac46..279d6b4 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsText.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotContainsText.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,138 +13,100 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingNotContainsText
- /// </summary>
- public class ExcelConditionalFormattingNotContainsText
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingNotContainsText
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingNotContainsText(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.NotContainsText,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.NotContains;
- Text = string.Empty;
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingNotContainsText(
+ /// <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)
- {
- }
- #endregion Constructors
+ : 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);
- #region Exposed Properties
- /// <summary>
- /// The text to search inside the cell
- /// </summary>
- public string Text
- {
- get
- {
- return GetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.TextAttribute);
- }
- set
- {
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.TextAttribute,
- value);
-
- Formula = string.Format(
+ Formula = string.Format(
"ISERROR(SEARCH(\"{1}\",{0}))",
Address.Start.Address,
value.Replace("\"", "\"\""));
- }
}
- #endregion Exposed Properties
-
- /****************************************************************************************/
}
-}
\ No newline at end of file
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotEqual.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotEqual.cs
index 06d8d05..e882682 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotEqual.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingNotEqual.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,111 +13,85 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingNotEqual
- /// </summary>
- public class ExcelConditionalFormattingNotEqual
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingNotEqual
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingNotEqual(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.NotEqual,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Operator = eExcelConditionalFormattingOperatorType.NotEqual;
- Formula = string.Empty;
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingNotEqual(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingRule.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingRule.cs
index ae285b1..a9a12ae 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingRule.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingRule.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,616 +13,477 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
using System.Xml;
-using OfficeOpenXml.Utils;
-using System.Text.RegularExpressions;
using OfficeOpenXml.ConditionalFormatting.Contracts;
using OfficeOpenXml.Style.Dxf;
+using OfficeOpenXml.Utils;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+///
+/// </summary>
+public abstract class ExcelConditionalFormattingRule : XmlHelper, IExcelConditionalFormattingRule {
+ private eExcelConditionalFormattingRuleType? _type;
+ private ExcelWorksheet _worksheet;
+
/// <summary>
- ///
+ /// Sinalize that we are in a Cnaging Priorities opeartion so that we won't enter
+ /// a recursive loop.
/// </summary>
- public abstract class ExcelConditionalFormattingRule
- : XmlHelper,
- IExcelConditionalFormattingRule
- {
- /****************************************************************************************/
+ private static bool _changingPriority;
- #region Private Properties
- private eExcelConditionalFormattingRuleType? _type;
- private 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 = false;
- #endregion Private Properties
-
- /****************************************************************************************/
-
- #region Constructors
- /// <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(
+ /// <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");
+ : 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;
- SchemaNodeOrder = _worksheet.SchemaNodeOrder;
+ _type = type;
+ _worksheet = worksheet;
+ SchemaNodeOrder = _worksheet.SchemaNodeOrder;
- if (itemElementNode == null)
- {
- // Create/Get the <cfRule> inside <conditionalFormatting>
- itemElementNode = CreateComplexNode(
+ 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
- }
+ "{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));
}
- /// <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(
+ // 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)
- {
- }
- #endregion Constructors
+ : this(type, address, priority, worksheet, null, namespaceManager) {}
- /****************************************************************************************/
+ /// <summary>
+ /// Get the <cfRule> node
+ /// </summary>
+ public XmlNode Node => TopNode;
- #region Methods
- #endregion Methods
+ /// <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;
- /****************************************************************************************/
-
- #region Exposed Properties
- /// <summary>
- /// Get the <cfRule> node
- /// </summary>
- public XmlNode Node
- {
- get { return 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
- {
- return new ExcelAddress(
- 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(
+ // 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));
+ "{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);
+ // 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);
- }
+ // 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;
+ /// <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);
}
- internal set
- {
- _type = value;
- // Transform the EPPlus Rule Type to @type attribute (slighty diferente)
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.TypeAttribute,
+ 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
- {
- return GetXmlNodeInt(
- ExcelConditionalFormattingConstants.Paths.PriorityAttribute);
- }
- set
- {
- // Save the current CF rule priority
- int priority = Priority;
+ /// <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;
+ // 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);
}
- // Change the priority in the XML
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.PriorityAttribute,
+ // 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
- {
- return GetXmlNodeBool(
- ExcelConditionalFormattingConstants.Paths.StopIfTrueAttribute);
- }
- set
- {
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.StopIfTrueAttribute,
- (value == true) ? "1" : string.Empty,
+ /// <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
- {
- return GetXmlNodeInt(
- ExcelConditionalFormattingConstants.Paths.DxfIdAttribute);
- }
- set
- {
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.DxfIdAttribute,
+ /// <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;
}
- internal ExcelDxfStyleConditionalFormatting _style = null;
- public ExcelDxfStyleConditionalFormatting Style
- {
- get
- {
- if (_style == null)
- {
- _style = new ExcelDxfStyleConditionalFormatting(NameSpaceManager, null, _worksheet.Workbook.Styles);
- }
- return _style;
- }
- }
- /// <summary>
- /// StdDev (zero is not allowed and will be converted to 1)
- /// </summary>
- public UInt16 StdDev
- {
- get
- {
- return Convert.ToUInt16(GetXmlNodeInt(
- ExcelConditionalFormattingConstants.Paths.StdDevAttribute));
- }
- set
- {
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.StdDevAttribute,
+ }
+
+ /// <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
- {
- return Convert.ToUInt16(GetXmlNodeInt(
- ExcelConditionalFormattingConstants.Paths.RankAttribute));
- }
- set
- {
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.RankAttribute,
+ /// <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);
}
- #endregion Exposed Properties
+ set {
+ string aboveAverageValue = string.Empty;
- /****************************************************************************************/
-
- #region Internal Properties
- /// <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)
+ // Only the types that needs the @AboveAverage
+ if ((_type == eExcelConditionalFormattingRuleType.BelowAverage)
|| (_type == eExcelConditionalFormattingRuleType.BelowOrEqualAverage)
- || (_type == eExcelConditionalFormattingRuleType.BelowStdDev))
- {
- aboveAverageValue = "0";
- }
+ || (_type == eExcelConditionalFormattingRuleType.BelowStdDev)) {
+ aboveAverageValue = "0";
+ }
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.AboveAverageAttribute,
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._aboveAverageAttribute,
aboveAverageValue,
true);
- }
}
+ }
- /// <summary>
- /// EqualAverage
- /// </summary>
- internal protected bool? EqualAverage
- {
- get
- {
- bool? equalAverage = GetXmlNodeBoolNullable(
- ExcelConditionalFormattingConstants.Paths.EqualAverageAttribute);
+ /// <summary>
+ /// EqualAverage
+ /// </summary>
+ internal protected bool? EqualAverage {
+ get {
+ bool? equalAverage = GetXmlNodeBoolNullable(
+ ExcelConditionalFormattingConstants.Paths._equalAverageAttribute);
- // Equal Avarege only if TRUE
- return (equalAverage == true);
+ // 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";
}
- 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,
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._equalAverageAttribute,
equalAverageValue,
true);
- }
}
+ }
- /// <summary>
- /// Bottom attribute
- /// </summary>
- internal protected bool? Bottom
- {
- get
- {
- bool? bottom = GetXmlNodeBoolNullable(
- ExcelConditionalFormattingConstants.Paths.BottomAttribute);
+ /// <summary>
+ /// Bottom attribute
+ /// </summary>
+ internal protected bool? Bottom {
+ get {
+ bool? bottom = GetXmlNodeBoolNullable(
+ ExcelConditionalFormattingConstants.Paths._bottomAttribute);
- // Bottom if TRUE
- return (bottom == true);
+ // 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";
}
- 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,
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._bottomAttribute,
bottomValue,
true);
- }
}
+ }
- /// <summary>
- /// Percent attribute
- /// </summary>
- internal protected bool? Percent
- {
- get
- {
- bool? percent = GetXmlNodeBoolNullable(
- ExcelConditionalFormattingConstants.Paths.PercentAttribute);
+ /// <summary>
+ /// Percent attribute
+ /// </summary>
+ internal protected bool? Percent {
+ get {
+ bool? percent = GetXmlNodeBoolNullable(
+ ExcelConditionalFormattingConstants.Paths._percentAttribute);
- // Bottom if TRUE
- return (percent == true);
+ // 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";
}
- 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,
+ SetXmlNodeString(
+ ExcelConditionalFormattingConstants.Paths._percentAttribute,
percentValue,
true);
- }
}
+ }
- /// <summary>
- /// TimePeriod
- /// </summary>
- internal protected eExcelConditionalFormattingTimePeriodType TimePeriod
- {
- get
- {
- return ExcelConditionalFormattingTimePeriodType.GetTypeByAttribute(
- GetXmlNodeString(ExcelConditionalFormattingConstants.Paths.TimePeriodAttribute));
- }
- set
- {
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.TimePeriodAttribute,
+ /// <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
- {
- return ExcelConditionalFormattingOperatorType.GetTypeByAttribute(
- GetXmlNodeString(ExcelConditionalFormattingConstants.Paths.OperatorAttribute));
- }
- set
- {
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.OperatorAttribute,
+ /// <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
- {
- return GetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.Formula);
- }
- set
- {
- SetXmlNodeString(
- ExcelConditionalFormattingConstants.Paths.Formula,
- value);
- }
- }
-
- /// <summary>
- /// Formula2
- /// </summary>
- public string Formula2
- {
- get
- {
- return 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;
- }
- }
- #endregion Internal Properties
- /****************************************************************************************/
}
-}
\ No newline at end of file
+
+ /// <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
index c404ca7..6104959 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisMonth.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisMonth.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingThisMonth
+/// </summary>
+public class ExcelConditionalFormattingThisMonth : ExcelConditionalFormattingTimePeriodGroup {
/// <summary>
- /// ExcelConditionalFormattingThisMonth
+ ///
/// </summary>
- public class ExcelConditionalFormattingThisMonth
- : ExcelConditionalFormattingTimePeriodGroup
- {
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingThisMonth(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.ThisMonth,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- 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);
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingThisMonth(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisWeek.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisWeek.cs
index 9baa8ad..a42007d 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisWeek.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThisWeek.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingThisWeek
+/// </summary>
+public class ExcelConditionalFormattingThisWeek : ExcelConditionalFormattingTimePeriodGroup {
/// <summary>
- /// ExcelConditionalFormattingThisWeek
+ ///
/// </summary>
- public class ExcelConditionalFormattingThisWeek
- : ExcelConditionalFormattingTimePeriodGroup
- {
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingThisWeek(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.ThisWeek,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- 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);
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingThisWeek(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeColorScale.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeColorScale.cs
index cb6d46c..a63bf04 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeColorScale.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeColorScale.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,103 +13,76 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
+
using System.Drawing;
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingThreeColorScale
- /// </summary>
- public class ExcelConditionalFormattingThreeColorScale
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingThreeColorScale
+/// </summary>
+public class ExcelConditionalFormattingThreeColorScale
: ExcelConditionalFormattingRule,
- IExcelConditionalFormattingThreeColorScale
- {
- /****************************************************************************************/
-
- #region Private Properties
- /// <summary>
- /// Private Low Value
- /// </summary>
- private ExcelConditionalFormattingColorScaleValue _lowValue;
-
- /// <summary>
- /// Private Middle Value
- /// </summary>
- private ExcelConditionalFormattingColorScaleValue _middleValue;
-
- /// <summary>
- /// Private High Value
- /// </summary>
- private ExcelConditionalFormattingColorScaleValue _highValue;
- #endregion Private Properties
-
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingThreeColorScale(
+ 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 == null) ? worksheet.NameSpaceManager : namespaceManager)
- {
- // Create the <colorScale> node inside the <cfRule> node
- var colorScaleNode = CreateComplexNode(
+ eExcelConditionalFormattingRuleType.ThreeColorScale,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ // Create the <colorScale> node inside the <cfRule> node
+ var colorScaleNode = CreateComplexNode(
Node,
- ExcelConditionalFormattingConstants.Paths.ColorScale);
+ ExcelConditionalFormattingConstants.Paths._colorScale);
- // LowValue default
- LowValue = new ExcelConditionalFormattingColorScaleValue(
+ // LowValue default
+ LowValue = new(
eExcelConditionalFormattingValueObjectPosition.Low,
eExcelConditionalFormattingValueObjectType.Min,
- ColorTranslator.FromHtml(ExcelConditionalFormattingConstants.Colors.CfvoLowValue),
+ ColorTranslator.FromHtml(ExcelConditionalFormattingConstants.Colors._cfvoLowValue),
eExcelConditionalFormattingRuleType.ThreeColorScale,
address,
priority,
worksheet,
NameSpaceManager);
- // MiddleValue default
- MiddleValue = new ExcelConditionalFormattingColorScaleValue(
+ // MiddleValue default
+ MiddleValue = new(
eExcelConditionalFormattingValueObjectPosition.Middle,
eExcelConditionalFormattingValueObjectType.Percent,
- ColorTranslator.FromHtml(ExcelConditionalFormattingConstants.Colors.CfvoMiddleValue),
+ ColorTranslator.FromHtml(ExcelConditionalFormattingConstants.Colors._cfvoMiddleValue),
50,
string.Empty,
eExcelConditionalFormattingRuleType.ThreeColorScale,
@@ -118,90 +91,56 @@
worksheet,
NameSpaceManager);
- // HighValue default
- HighValue = new ExcelConditionalFormattingColorScaleValue(
+ // HighValue default
+ HighValue = new(
eExcelConditionalFormattingValueObjectPosition.High,
eExcelConditionalFormattingValueObjectType.Max,
- ColorTranslator.FromHtml(ExcelConditionalFormattingConstants.Colors.CfvoHighValue),
+ ColorTranslator.FromHtml(ExcelConditionalFormattingConstants.Colors._cfvoHighValue),
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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingThreeColorScale(
+ /// <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)
- {
- }
- #endregion Constructors
+ : this(address, priority, worksheet, null, null) {}
- /****************************************************************************************/
+ /// <summary>
+ /// Low Value for Three Color Scale Object Value
+ /// </summary>
+ public ExcelConditionalFormattingColorScaleValue LowValue { get; set; }
- #region Public Properties
- /// <summary>
- /// Low Value for Three Color Scale Object Value
- /// </summary>
- public ExcelConditionalFormattingColorScaleValue LowValue
- {
- get { return _lowValue; }
- set { _lowValue = value; }
- }
+ /// <summary>
+ /// Middle Value for Three Color Scale Object Value
+ /// </summary>
+ public ExcelConditionalFormattingColorScaleValue MiddleValue { get; set; }
- /// <summary>
- /// Middle Value for Three Color Scale Object Value
- /// </summary>
- public ExcelConditionalFormattingColorScaleValue MiddleValue
- {
- get { return _middleValue; }
- set { _middleValue = value; }
- }
-
- /// <summary>
- /// High Value for Three Color Scale Object Value
- /// </summary>
- public ExcelConditionalFormattingColorScaleValue HighValue
- {
- get { return _highValue; }
- set { _highValue = value; }
- }
- #endregion Public Properties
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ /// <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
index 4ec19e1..cc0a2ad 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeIconSet.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingThreeIconSet.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,368 +13,278 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
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 == null) ? worksheet.NameSpaceManager : namespaceManager)
- {
+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 == null) ? worksheet.NameSpaceManager : 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 == null) ? worksheet.NameSpaceManager : 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>
- /// ExcelConditionalFormattingThreeIconSet
- /// </summary>
- public class ExcelConditionalFormattingIconSetBase<T>
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingThreeIconSet<T>
- {
- /****************************************************************************************/
+ }
- #region Private Properties
+ /// <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) {}
- #endregion Private Properties
+ /// <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; }
- #region Constructors
- /// <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 == null) ? worksheet.NameSpaceManager : 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 ExcelConditionalFormattingIconDataBarValue(
- type,
- address,
- worksheet,
- node,
- namespaceManager);
- }
- else if (pos == 2)
- {
- Icon2 = new ExcelConditionalFormattingIconDataBarValue(
- type,
- address,
- worksheet,
- node,
- namespaceManager);
- }
- else if (pos == 3)
- {
- Icon3 = new ExcelConditionalFormattingIconDataBarValue(
- type,
- address,
- worksheet,
- node,
- namespaceManager);
- }
- else
- {
- break;
- }
- pos++;
- }
- }
- else
- {
- var iconSetNode = CreateComplexNode(
- Node,
- ExcelConditionalFormattingConstants.Paths.IconSet);
+ /// <summary>
+ /// Settings for icon 2 in the iconset
+ /// </summary>
+ public ExcelConditionalFormattingIconDataBarValue Icon2 { get; internal set; }
- //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;
- }
+ /// <summary>
+ /// Settings for icon 2 in the iconset
+ /// </summary>
+ public ExcelConditionalFormattingIconDataBarValue Icon3 { get; internal set; }
- var iconNode1 = iconSetNode.OwnerDocument.CreateElement(ExcelConditionalFormattingConstants.Paths.Cfvo, ExcelPackage.schemaMain);
- iconSetNode.AppendChild(iconNode1);
- Icon1 = new ExcelConditionalFormattingIconDataBarValue(eExcelConditionalFormattingValueObjectType.Percent,
- 0,
- "",
- eExcelConditionalFormattingRuleType.ThreeIconSet,
- address,
- priority,
- worksheet,
- iconNode1,
- namespaceManager);
+ private const string _reversePath = "d:iconSet/@reverse";
- var iconNode2 = iconSetNode.OwnerDocument.CreateElement(ExcelConditionalFormattingConstants.Paths.Cfvo, ExcelPackage.schemaMain);
- iconSetNode.AppendChild(iconNode2);
- Icon2 = new ExcelConditionalFormattingIconDataBarValue(eExcelConditionalFormattingValueObjectType.Percent,
- Math.Round(100D / spann, 0),
- "",
- eExcelConditionalFormattingRuleType.ThreeIconSet,
- address,
- priority,
- worksheet,
- iconNode2,
- namespaceManager);
+ /// <summary>
+ /// Reverse the order of the icons
+ /// </summary>
+ public bool Reverse {
+ get => GetXmlNodeBool(_reversePath, false);
+ set => SetXmlNodeBool(_reversePath, value);
+ }
- var iconNode3 = iconSetNode.OwnerDocument.CreateElement(ExcelConditionalFormattingConstants.Paths.Cfvo, ExcelPackage.schemaMain);
- iconSetNode.AppendChild(iconNode3);
- Icon3 = new ExcelConditionalFormattingIconDataBarValue(eExcelConditionalFormattingValueObjectType.Percent,
- Math.Round(100D * (2D / spann), 0),
- "",
- eExcelConditionalFormattingRuleType.ThreeIconSet,
- address,
- priority,
- worksheet,
- iconNode3,
- namespaceManager);
- Type = type;
- }
- }
+ private const string _showValuePath = "d:iconSet/@showValue";
- /// <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>
+ /// If the cell values are visible
+ /// </summary>
+ public bool ShowValue {
+ get => GetXmlNodeBool(_showValuePath, true);
+ set => SetXmlNodeBool(_showValuePath, value);
+ }
- /// <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)
- {
- }
- #endregion Constructors
+ private const string _iconSetPath = "d:iconSet/@iconSet";
- /// <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
- {
- return 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
- {
- return GetXmlNodeBool(_showValuePath, true);
- }
- set
- {
- SetXmlNodeBool(_showValuePath, value);
- }
- }
- private const string _iconSetPath = "d:iconSet/@iconSet";
- /// <summary>
- /// Type of iconset
- /// </summary>
- public T IconSet
- {
- get
- {
- var v = GetXmlNodeString(_iconSetPath);
- v = v.Substring(1); //Skip first icon.
- return (T)Enum.Parse(typeof(T), v, true);
- }
- set
- {
- SetXmlNodeString(_iconSetPath, GetIconSetString(value));
- }
- }
- 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"));
- }
- }
- else 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"));
- }
- }
- else
- {
- 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"));
- }
- }
- }
+ /// <summary>
+ /// Type of iconset
+ /// </summary>
+ public T IconSet {
+ get {
+ var v = GetXmlNodeString(_iconSetPath);
+ v = v.Substring(1); //Skip first icon.
+ return (T)Enum.Parse(typeof(T), v, true);
}
-}
\ No newline at end of file
+ set => SetXmlNodeString(_iconSetPath, GetIconSetString(value));
+ }
+
+ 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
index ec7d836..f8ebade 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTimePeriodGroup.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTimePeriodGroup.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,51 +13,43 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingTimePeriodGroup
- /// </summary>
- public class ExcelConditionalFormattingTimePeriodGroup
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingTimePeriodGroup
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <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(
+/// <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,
@@ -65,62 +57,40 @@
XmlNode itemElementNode,
XmlNamespaceManager namespaceManager)
: base(
- type,
- address,
- priority,
- worksheet,
- itemElementNode,
- (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager)
- {
- }
+ type,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : 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(
+ /// <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)
- {
- }
+ : 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(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(type, address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingToday.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingToday.cs
index c217665..6b99262 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingToday.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingToday.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,82 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingToday
+/// </summary>
+public class ExcelConditionalFormattingToday : ExcelConditionalFormattingTimePeriodGroup {
/// <summary>
- /// ExcelConditionalFormattingToday
+ ///
/// </summary>
- public class ExcelConditionalFormattingToday
- : ExcelConditionalFormattingTimePeriodGroup
- {
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingToday(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.Today,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- TimePeriod = eExcelConditionalFormattingTimePeriodType.Today;
- Formula = string.Format(
- "FLOOR({0},1)=TODAY()",
- Address.Start.Address);
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingToday(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTomorrow.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTomorrow.cs
index cec82b0..6b5aa92 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTomorrow.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTomorrow.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,82 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingTomorrow
+/// </summary>
+public class ExcelConditionalFormattingTomorrow : ExcelConditionalFormattingTimePeriodGroup {
/// <summary>
- /// ExcelConditionalFormattingTomorrow
+ ///
/// </summary>
- public class ExcelConditionalFormattingTomorrow
- : ExcelConditionalFormattingTimePeriodGroup
- {
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingTomorrow(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.Tomorrow,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- 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);
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingTomorrow(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTop.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTop.cs
index 787f1c9..95697d0 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTop.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTop.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,86 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingTop
- /// </summary>
- public class ExcelConditionalFormattingTop
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingTopBottomGroup
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingTop(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.Top,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Bottom = false;
- Percent = false;
- Rank = 10; // First 10 values
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingTop(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTopPercent.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTopPercent.cs
index 5c299cc..929369d 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTopPercent.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTopPercent.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,86 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingTopPercent
- /// </summary>
- public class ExcelConditionalFormattingTopPercent
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingTopBottomGroup
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingTopPercent(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.TopPercent,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- if (itemElementNode==null) //Set default values and create attributes if needed
- {
- Bottom = false;
- Percent = true;
- Rank = 10; // First 10 percent
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingTopPercent(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTwoColorScale.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTwoColorScale.cs
index ef322f0..29a5a9e 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTwoColorScale.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingTwoColorScale.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,168 +13,132 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
+
using System.Drawing;
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingTwoColorScale
- /// </summary>
- public class ExcelConditionalFormattingTwoColorScale
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingTwoColorScale
+/// </summary>
+public class ExcelConditionalFormattingTwoColorScale
: ExcelConditionalFormattingRule,
- IExcelConditionalFormattingTwoColorScale
- {
- /****************************************************************************************/
+ IExcelConditionalFormattingTwoColorScale {
+ /// <summary>
+ /// Private Low Value
+ /// </summary>
+ private ExcelConditionalFormattingColorScaleValue _lowValue;
- #region Private Properties
- /// <summary>
- /// Private Low Value
- /// </summary>
- private ExcelConditionalFormattingColorScaleValue _lowValue;
+ /// <summary>
+ /// Private High Value
+ /// </summary>
+ private ExcelConditionalFormattingColorScaleValue _highValue;
- /// <summary>
- /// Private High Value
- /// </summary>
- private ExcelConditionalFormattingColorScaleValue _highValue;
- #endregion Private Properties
-
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingTwoColorScale(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
- {
- // Create the <colorScale> node inside the <cfRule> node
- var colorScaleNode = CreateComplexNode(
+ eExcelConditionalFormattingRuleType.TwoColorScale,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ // Create the <colorScale> node inside the <cfRule> node
+ var colorScaleNode = CreateComplexNode(
Node,
- ExcelConditionalFormattingConstants.Paths.ColorScale);
+ ExcelConditionalFormattingConstants.Paths._colorScale);
- // LowValue default
- LowValue = new ExcelConditionalFormattingColorScaleValue(
+ // LowValue default
+ LowValue = new(
eExcelConditionalFormattingValueObjectPosition.Low,
eExcelConditionalFormattingValueObjectType.Min,
- ColorTranslator.FromHtml(ExcelConditionalFormattingConstants.Colors.CfvoLowValue),
+ ColorTranslator.FromHtml(ExcelConditionalFormattingConstants.Colors._cfvoLowValue),
eExcelConditionalFormattingRuleType.TwoColorScale,
address,
priority,
worksheet,
NameSpaceManager);
- // HighValue default
- HighValue = new ExcelConditionalFormattingColorScaleValue(
+ // HighValue default
+ HighValue = new(
eExcelConditionalFormattingValueObjectPosition.High,
eExcelConditionalFormattingValueObjectType.Max,
- ColorTranslator.FromHtml(ExcelConditionalFormattingConstants.Colors.CfvoHighValue),
+ ColorTranslator.FromHtml(ExcelConditionalFormattingConstants.Colors._cfvoHighValue),
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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingTwoColorScale(
+ /// <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)
- {
- }
- #endregion Constructors
+ : this(address, priority, worksheet, null, null) {}
- /****************************************************************************************/
-
- #region Public Properties
- /// <summary>
- /// Low Value for Two Color Scale Object Value
- /// </summary>
- public ExcelConditionalFormattingColorScaleValue LowValue
- {
- get { return _lowValue; }
- set { _lowValue = value; }
- }
-
- /// <summary>
- /// High Value for Two Color Scale Object Value
- /// </summary>
- public ExcelConditionalFormattingColorScaleValue HighValue
- {
- get { return _highValue; }
- set { _highValue = value; }
- }
- #endregion Public Properties
-
- /****************************************************************************************/
+ /// <summary>
+ /// Low Value for Two Color Scale Object Value
+ /// </summary>
+ public ExcelConditionalFormattingColorScaleValue LowValue {
+ get => _lowValue;
+ set => _lowValue = value;
}
-}
\ No newline at end of file
+
+ /// <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
index fd32210..ef4d72e 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingUniqueValues.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingUniqueValues.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,106 +13,78 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
- /// <summary>
- /// ExcelConditionalFormattingUniqueValues
- /// </summary>
- public class ExcelConditionalFormattingUniqueValues
- : ExcelConditionalFormattingRule,
- IExcelConditionalFormattingUniqueValues
- {
- /****************************************************************************************/
+namespace OfficeOpenXml.ConditionalFormatting;
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="address"></param>
- /// <param name="priority"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingUniqueValues(
+/// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
- {
- }
+ eExcelConditionalFormattingRuleType.UniqueValues,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- internal ExcelConditionalFormattingUniqueValues(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingUniqueValues(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingYesterday.cs b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingYesterday.cs
index 87fe86f..158948c 100644
--- a/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingYesterday.cs
+++ b/EPPlus/ConditionalFormatting/Rules/ExcelConditionalFormattingYesterday.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,112 +13,82 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
+
using System.Xml;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
-namespace OfficeOpenXml.ConditionalFormatting
-{
+namespace OfficeOpenXml.ConditionalFormatting;
+
+/// <summary>
+/// ExcelConditionalFormattingYesterday
+/// </summary>
+public class ExcelConditionalFormattingYesterday : ExcelConditionalFormattingTimePeriodGroup {
/// <summary>
- /// ExcelConditionalFormattingYesterday
+ ///
/// </summary>
- public class ExcelConditionalFormattingYesterday
- : ExcelConditionalFormattingTimePeriodGroup
- {
- /****************************************************************************************/
-
- #region Constructors
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- /// <param name="itemElementNode"></param>
- /// <param name="namespaceManager"></param>
- internal ExcelConditionalFormattingYesterday(
+ /// <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 == null) ? worksheet.NameSpaceManager : namespaceManager)
+ eExcelConditionalFormattingRuleType.Yesterday,
+ address,
+ priority,
+ worksheet,
+ itemElementNode,
+ (namespaceManager == null) ? worksheet.NameSpaceManager : namespaceManager) {
+ if (itemElementNode
+ == null) //Set default values and create attributes if needed
{
- 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);
- }
+ 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(
+ /// <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)
- {
- }
+ : this(address, priority, worksheet, itemElementNode, null) {}
- /// <summary>
- ///
- /// </summary>
- /// <param name="priority"></param>
- /// <param name="address"></param>
- /// <param name="worksheet"></param>
- internal ExcelConditionalFormattingYesterday(
+ /// <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)
- {
- }
- #endregion Constructors
-
- /****************************************************************************************/
- }
-}
\ No newline at end of file
+ : this(address, priority, worksheet, null, null) {}
+}
diff --git a/EPPlus/DataValidation/Contracts/IExcelDataValidation.cs b/EPPlus/DataValidation/Contracts/IExcelDataValidation.cs
index ecc2208..44b5d3e 100644
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidation.cs
+++ b/EPPlus/DataValidation/Contracts/IExcelDataValidation.cs
@@ -13,83 +13,86 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-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; set; }
- /// <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();
+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; set; }
+
+ /// <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
index 350ddaf..c3b6bfd 100644
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationAny.cs
+++ b/EPPlus/DataValidation/Contracts/IExcelDataValidationAny.cs
@@ -13,33 +13,25 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-namespace OfficeOpenXml.DataValidation.Contracts
-{
- /// <summary>
- /// Data validation interface for Any value validation.
- /// </summary>
- public interface IExcelDataValidationAny : IExcelDataValidation
- {
- }
-}
+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
index 1cfdba9..f567ce4 100644
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationCustom.cs
+++ b/EPPlus/DataValidation/Contracts/IExcelDataValidationCustom.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,34 +13,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
+
using OfficeOpenXml.DataValidation.Formulas.Contracts;
-namespace OfficeOpenXml.DataValidation.Contracts
-{
- /// <summary>
- /// Data validation interface for custom validation.
- /// </summary>
- public interface IExcelDataValidationCustom : IExcelDataValidationWithFormula<IExcelDataValidationFormula>, IExcelDataValidationWithOperator
- {
- }
-}
+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
index 3e96b03..6ab40d0 100644
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationDateTime.cs
+++ b/EPPlus/DataValidation/Contracts/IExcelDataValidationDateTime.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,34 +13,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
+
using OfficeOpenXml.DataValidation.Formulas.Contracts;
-namespace OfficeOpenXml.DataValidation.Contracts
-{
- /// <summary>
- /// Validation interface for datetime validations
- /// </summary>
- public interface IExcelDataValidationDateTime : IExcelDataValidationWithFormula2<IExcelDataValidationFormulaDateTime>, IExcelDataValidationWithOperator
- {
- }
-}
+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
index 8b4f356..48983ed 100644
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationDecimal.cs
+++ b/EPPlus/DataValidation/Contracts/IExcelDataValidationDecimal.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,34 +13,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
+
using OfficeOpenXml.DataValidation.Formulas.Contracts;
-namespace OfficeOpenXml.DataValidation.Contracts
-{
- /// <summary>
- /// Data validation interface for decimal values
- /// </summary>
- public interface IExcelDataValidationDecimal : IExcelDataValidationWithFormula2<IExcelDataValidationFormulaDecimal>, IExcelDataValidationWithOperator
- {
- }
-}
+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
index a54863d..9d984e2 100644
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationInt.cs
+++ b/EPPlus/DataValidation/Contracts/IExcelDataValidationInt.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,31 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
+
using OfficeOpenXml.DataValidation.Formulas.Contracts;
-namespace OfficeOpenXml.DataValidation.Contracts
-{
- public interface IExcelDataValidationInt : IExcelDataValidationWithFormula2<IExcelDataValidationFormulaInt>, IExcelDataValidationWithOperator
- {
- }
-}
+namespace OfficeOpenXml.DataValidation.Contracts;
+
+public interface IExcelDataValidationInt
+ : IExcelDataValidationWithFormula2<IExcelDataValidationFormulaInt>,
+ IExcelDataValidationWithOperator {}
diff --git a/EPPlus/DataValidation/Contracts/IExcelDataValidationList.cs b/EPPlus/DataValidation/Contracts/IExcelDataValidationList.cs
index d0ae4f2..13bb5a9 100644
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationList.cs
+++ b/EPPlus/DataValidation/Contracts/IExcelDataValidationList.cs
@@ -13,31 +13,26 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
+
using OfficeOpenXml.DataValidation.Formulas.Contracts;
-namespace OfficeOpenXml.DataValidation.Contracts
-{
- public interface IExcelDataValidationList : IExcelDataValidationWithFormula<IExcelDataValidationFormulaList>
- {
- }
-}
+namespace OfficeOpenXml.DataValidation.Contracts;
+
+public interface IExcelDataValidationList
+ : IExcelDataValidationWithFormula<IExcelDataValidationFormulaList> {}
diff --git a/EPPlus/DataValidation/Contracts/IExcelDataValidationTime.cs b/EPPlus/DataValidation/Contracts/IExcelDataValidationTime.cs
index ea26dd5..4c57587 100644
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationTime.cs
+++ b/EPPlus/DataValidation/Contracts/IExcelDataValidationTime.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,34 +13,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
+
using OfficeOpenXml.DataValidation.Formulas.Contracts;
-namespace OfficeOpenXml.DataValidation.Contracts
-{
- /// <summary>
- /// Data validation interface for time validation.
- /// </summary>
- public interface IExcelDataValidationTime : IExcelDataValidationWithFormula2<IExcelDataValidationFormulaTime>, IExcelDataValidationWithOperator
- {
- }
-}
+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
index 251f079..b93dd30 100644
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationWithFormula.cs
+++ b/EPPlus/DataValidation/Contracts/IExcelDataValidationWithFormula.cs
@@ -13,33 +13,28 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
+
using OfficeOpenXml.DataValidation.Formulas.Contracts;
-namespace OfficeOpenXml.DataValidation.Contracts
-{
- public interface IExcelDataValidationWithFormula<T> : IExcelDataValidation
- where T : IExcelDataValidationFormula
- {
- T Formula { get; }
- }
+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
index 41da1ef..2f6692b 100644
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationWithFormula2.cs
+++ b/EPPlus/DataValidation/Contracts/IExcelDataValidationWithFormula2.cs
@@ -13,40 +13,35 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
+
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; }
- }
+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
index a24bd4f..48b06cb 100644
--- a/EPPlus/DataValidation/Contracts/IExcelDataValidationWithOperator.cs
+++ b/EPPlus/DataValidation/Contracts/IExcelDataValidationWithOperator.cs
@@ -13,37 +13,31 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-namespace OfficeOpenXml.DataValidation.Contracts
-{
- /// <summary>
- /// Represents a validation with an operator
- /// </summary>
- public interface IExcelDataValidationWithOperator
- {
- /// <summary>
- /// Operator type
- /// </summary>
- ExcelDataValidationOperator Operator { get; set; }
- }
+namespace OfficeOpenXml.DataValidation.Contracts;
+
+/// <summary>
+/// Represents a validation with an operator
+/// </summary>
+public interface IExcelDataValidationWithOperator {
+ /// <summary>
+ /// Operator type
+ /// </summary>
+ ExcelDataValidationOperator Operator { get; set; }
}
diff --git a/EPPlus/DataValidation/ExcelDataValidation.cs b/EPPlus/DataValidation/ExcelDataValidation.cs
index cd2fdda..0f74ed9 100644
--- a/EPPlus/DataValidation/ExcelDataValidation.cs
+++ b/EPPlus/DataValidation/ExcelDataValidation.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,387 +13,293 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
using System.Globalization;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.Utils;
-using System.Xml;
using System.Text.RegularExpressions;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
+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";
+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";
+ 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";
- internal ExcelDataValidation(ExcelWorksheet worksheet, string address, ExcelDataValidationType validationType)
- : this(worksheet, address, validationType, null)
- { }
+ 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)</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 != null ? 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 ExcelAddress(address);
- Init();
- }
-
- private void Init()
- {
- // set schema node order
- SchemaNodeOrder = new string[]{
- "type",
- "errorStyle",
- "operator",
- "allowBlank",
- "showInputMessage",
- "showErrorMessage",
- "errorTitle",
- "error",
- "promptTitle",
- "prompt",
- "sqref",
- "formula1",
- "formula2"
- };
- }
-
- 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");
- }
- }
-
- #region Public properties
-
- /// <summary>
- /// True if the validation type allows operator to be set.
- /// </summary>
- public bool AllowsOperator
- {
- get
- {
- return ValidationType.AllowOperator;
- }
- }
-
- /// <summary>
- /// Address of data validation
- /// </summary>
- public ExcelAddress Address
- {
- get
- {
- return new ExcelAddress(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);
- if (!string.IsNullOrEmpty(operatorString))
- {
- return (ExcelDataValidationOperator)Enum.Parse(typeof(ExcelDataValidationOperator), operatorString);
- }
- return default(ExcelDataValidationOperator);
- }
- set
- {
- if (!ValidationType.AllowOperator)
- {
- throw new InvalidOperationException("The current validation type does not allow operator to be set");
- }
- SetXmlNodeString(_operatorPath, value.ToString());
- }
- }
-
- /// <summary>
- /// Warning style
- /// </summary>
- public ExcelDataValidationWarningStyle ErrorStyle
- {
- get
- {
- var errorStyleString = GetXmlNodeString(_errorStylePath);
- if (!string.IsNullOrEmpty(errorStyleString))
- {
- return (ExcelDataValidationWarningStyle)Enum.Parse(typeof(ExcelDataValidationWarningStyle), errorStyleString);
- }
- return ExcelDataValidationWarningStyle.undefined;
- }
- set
- {
- if (value == ExcelDataValidationWarningStyle.undefined)
- {
- DeleteNode(_errorStylePath);
- }
- SetXmlNodeString(_errorStylePath, value.ToString());
- }
- }
-
- /// <summary>
- /// True if blanks should be allowed
- /// </summary>
- public bool? AllowBlank
- {
- get
- {
- return GetXmlNodeBoolNullable(_allowBlankPath);
- }
- set
- {
- SetNullableBoolValue(_allowBlankPath, value);
- }
- }
-
- /// <summary>
- /// True if input message should be shown
- /// </summary>
- public bool? ShowInputMessage
- {
- get
- {
- return GetXmlNodeBoolNullable(_showInputMessagePath);
- }
- set
- {
- SetNullableBoolValue(_showInputMessagePath, value);
- }
- }
-
- /// <summary>
- /// True if error message should be shown
- /// </summary>
- public bool? ShowErrorMessage
- {
- get
- {
- return GetXmlNodeBoolNullable(_showErrorMessagePath);
- }
- set
- {
- SetNullableBoolValue(_showErrorMessagePath, value);
- }
- }
-
- /// <summary>
- /// Title of error message box
- /// </summary>
- public string ErrorTitle
- {
- get
- {
- return GetXmlNodeString(_errorTitlePath);
- }
- set
- {
- SetXmlNodeString(_errorTitlePath, value);
- }
- }
-
- /// <summary>
- /// Error message box text
- /// </summary>
- public string Error
- {
- get
- {
- return GetXmlNodeString(_errorPath);
- }
- set
- {
- SetXmlNodeString(_errorPath, value);
- }
- }
-
- public string PromptTitle
- {
- get
- {
- return GetXmlNodeString(_promptTitlePath);
- }
- set
- {
- SetXmlNodeString(_promptTitlePath, value);
- }
- }
-
- public string Prompt
- {
- get
- {
- return GetXmlNodeString(_promptPath);
- }
- set
- {
- SetXmlNodeString(_promptPath, value);
- }
- }
-
- /// <summary>
- /// Formula 1
- /// </summary>
- protected string Formula1Internal
- {
- get
- {
- return GetXmlNodeString(_formula1Path);
- }
- }
-
- /// <summary>
- /// Formula 2
- /// </summary>
- protected string Formula2Internal
- {
- get
- {
- return GetXmlNodeString(_formula2Path);
- }
- }
-
- #endregion
-
- protected void SetValue<T>(Nullable<T> val, string path)
- where T : struct
- {
- if (!val.HasValue)
- {
- DeleteNode(path);
- }
- var stringValue = val.Value.ToString().Replace(',', '.');
- SetXmlNodeString(path, stringValue);
- }
+ /// <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 != null ? 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);
+ Init();
+ }
+
+ private void Init() {
+ // set schema node order
+ SchemaNodeOrder = new[] {
+ "type",
+ "errorStyle",
+ "operator",
+ "allowBlank",
+ "showInputMessage",
+ "showErrorMessage",
+ "errorTitle",
+ "error",
+ "promptTitle",
+ "prompt",
+ "sqref",
+ "formula1",
+ "formula2",
+ };
+ }
+
+ 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);
+ if (!string.IsNullOrEmpty(operatorString)) {
+ return (ExcelDataValidationOperator)
+ Enum.Parse(typeof(ExcelDataValidationOperator), operatorString);
+ }
+ return default(ExcelDataValidationOperator);
+ }
+ set {
+ if (!ValidationType.AllowOperator) {
+ throw new InvalidOperationException(
+ "The current validation type does not allow operator to be set");
+ }
+ SetXmlNodeString(_operatorPath, value.ToString());
+ }
+ }
+
+ /// <summary>
+ /// Warning style
+ /// </summary>
+ public ExcelDataValidationWarningStyle ErrorStyle {
+ get {
+ var errorStyleString = GetXmlNodeString(_errorStylePath);
+ if (!string.IsNullOrEmpty(errorStyleString)) {
+ return (ExcelDataValidationWarningStyle)
+ Enum.Parse(typeof(ExcelDataValidationWarningStyle), errorStyleString);
+ }
+ return ExcelDataValidationWarningStyle.Undefined;
+ }
+ set {
+ if (value == ExcelDataValidationWarningStyle.Undefined) {
+ DeleteNode(_errorStylePath);
+ }
+ SetXmlNodeString(_errorStylePath, value.ToString());
+ }
+ }
+
+ /// <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
index e8fae1e..8d00268 100644
--- a/EPPlus/DataValidation/ExcelDataValidationAny.cs
+++ b/EPPlus/DataValidation/ExcelDataValidationAny.cs
@@ -13,78 +13,75 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-using OfficeOpenXml.DataValidation.Formulas;
+
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)
- {
- }
+namespace OfficeOpenXml.DataValidation;
- /// <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>
+/// 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>
- /// <param name="namespaceManager"></param>
- internal ExcelDataValidationAny(ExcelWorksheet worksheet, string address, ExcelDataValidationType validationType, XmlNode itemElementNode, XmlNamespaceManager namespaceManager)
- : base(worksheet, address, validationType, itemElementNode, namespaceManager)
- {
- }
+ /// <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>
- /// This method will validate the state of the validation
- /// </summary>
- public override void Validate()
- {
- }
- }
+ /// <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
index d13791b..6692f9d 100644
--- a/EPPlus/DataValidation/ExcelDataValidationCollection.cs
+++ b/EPPlus/DataValidation/ExcelDataValidationCollection.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,17 +13,17 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
@@ -32,377 +32,358 @@
* 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.Generic;
-using System.Linq;
-using System.Text;
using System.Collections;
-using OfficeOpenXml.Utils;
+using System.Collections.Generic;
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 List<IExcelDataValidation> _validations = new List<IExcelDataValidation>();
- private ExcelWorksheet _worksheet = null;
+namespace OfficeOpenXml.DataValidation;
- private const string DataValidationPath = "//d:dataValidations";
- private readonly string DataValidationItemsPath = string.Format("{0}/d:dataValidation", DataValidationPath);
+/// <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 List<IExcelDataValidation> _validations = new();
+ private ExcelWorksheet _worksheet;
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="worksheet"></param>
- internal ExcelDataValidationCollection(ExcelWorksheet worksheet)
- : base(worksheet.NameSpaceManager, worksheet.WorksheetXml.DocumentElement)
- {
- Require.Argument(worksheet).IsNotNull("worksheet");
- _worksheet = worksheet;
- SchemaNodeOrder = worksheet.SchemaNodeOrder;
+ private const string _dataValidationPath = "//d:dataValidations";
+ private readonly string DataValidationItemsPath = string.Format(
+ "{0}/d:dataValidation",
+ _dataValidationPath);
- // 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;
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="worksheet"></param>
+ internal ExcelDataValidationCollection(ExcelWorksheet worksheet)
+ : base(worksheet.NameSpaceManager, worksheet.WorksheetXml.DocumentElement) {
+ Require.Argument(worksheet).IsNotNull("worksheet");
+ _worksheet = worksheet;
+ SchemaNodeOrder = worksheet.SchemaNodeOrder;
- 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));
- }
- }
- if (_validations.Count > 0)
- {
- OnValidationCountChanged();
- }
+ // 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;
}
- private void EnsureRootElementExists()
- {
- var node = _worksheet.WorksheetXml.SelectSingleNode(DataValidationPath, _worksheet.NameSpaceManager);
- if (node == null)
- {
- CreateNode(DataValidationPath.TrimStart('/'));
- }
- }
+ var addr = node.Attributes["sqref"].Value;
- private void OnValidationCountChanged()
- {
- //if (TopNode != null)
- //{
- // SetXmlNodeString("@count", _validations.Count.ToString());
- //}
- }
+ var typeSchema = node.Attributes["type"] != null ? node.Attributes["type"].Value : "";
- private XmlNode GetRootNode()
- {
- EnsureRootElementExists();
- TopNode = _worksheet.WorksheetXml.SelectSingleNode(DataValidationPath, _worksheet.NameSpaceManager);
- return TopNode;
- }
-
- /// <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);
- OnValidationCountChanged();
- 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);
- OnValidationCountChanged();
- 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);
- OnValidationCountChanged();
- 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);
- OnValidationCountChanged();
- 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);
- OnValidationCountChanged();
- 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);
- OnValidationCountChanged();
- return item;
- }
-
-
- public IExcelDataValidationTime AddTimeValidation(string address)
- {
- ValidateAddress(address);
- EnsureRootElementExists();
- var item = new ExcelDataValidationTime(_worksheet, address, ExcelDataValidationType.Time);
- _validations.Add(item);
- OnValidationCountChanged();
- 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);
- OnValidationCountChanged();
- 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))
- {
- throw new InvalidCastException("The supplied item must inherit OfficeOpenXml.DataValidation.ExcelDataValidation");
- }
- Require.Argument(item).IsNotNull("item");
- TopNode.RemoveChild(((ExcelDataValidation)item).TopNode);
- var retVal = _validations.Remove(item);
- if (retVal) OnValidationCountChanged();
- return retVal;
- }
-
- /// <summary>
- /// Number of validations
- /// </summary>
- public int Count
- {
- get { return _validations.Count; }
- }
-
- /// <summary>
- /// Index operator, returns by 0-based index
- /// </summary>
- /// <param name="index"></param>
- /// <returns></returns>
- public IExcelDataValidation this[int index]
- {
- get { return _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))
- {
- throw new InvalidCastException("The supplied item must inherit OfficeOpenXml.DataValidation.ExcelDataValidation");
- }
- TopNode.SelectSingleNode(DataValidationPath.TrimStart('/'), NameSpaceManager).RemoveChild(((ExcelDataValidation)m).TopNode);
- }
- _validations.RemoveAll(match);
- OnValidationCountChanged();
- }
-
- IEnumerator<IExcelDataValidation> IEnumerable<IExcelDataValidation>.GetEnumerator()
- {
- return _validations.GetEnumerator();
- }
-
- IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return _validations.GetEnumerator();
- }
+ var type = ExcelDataValidationType.GetBySchemaName(typeSchema);
+ _validations.Add(ExcelDataValidationFactory.Create(type, worksheet, addr, node));
+ }
}
+ if (_validations.Count > 0) {
+ OnValidationCountChanged();
+ }
+ }
+
+ private void EnsureRootElementExists() {
+ var node = _worksheet.WorksheetXml.SelectSingleNode(
+ _dataValidationPath,
+ _worksheet.NameSpaceManager);
+ if (node == null) {
+ CreateNode(_dataValidationPath.TrimStart('/'));
+ }
+ }
+
+ private void OnValidationCountChanged() {
+ //if (TopNode != null)
+ //{
+ // SetXmlNodeString("@count", _validations.Count.ToString());
+ //}
+ }
+
+ private XmlNode GetRootNode() {
+ EnsureRootElementExists();
+ TopNode = _worksheet.WorksheetXml.SelectSingleNode(
+ _dataValidationPath,
+ _worksheet.NameSpaceManager);
+ return TopNode;
+ }
+
+ /// <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);
+ OnValidationCountChanged();
+ 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);
+ OnValidationCountChanged();
+ 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);
+ OnValidationCountChanged();
+ 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);
+ OnValidationCountChanged();
+ 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);
+ OnValidationCountChanged();
+ 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);
+ OnValidationCountChanged();
+ return item;
+ }
+
+ public IExcelDataValidationTime AddTimeValidation(string address) {
+ ValidateAddress(address);
+ EnsureRootElementExists();
+ var item = new ExcelDataValidationTime(_worksheet, address, ExcelDataValidationType.Time);
+ _validations.Add(item);
+ OnValidationCountChanged();
+ 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);
+ OnValidationCountChanged();
+ 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)) {
+ throw new InvalidCastException(
+ "The supplied item must inherit OfficeOpenXml.DataValidation.ExcelDataValidation");
+ }
+ Require.Argument(item).IsNotNull("item");
+ TopNode.RemoveChild(((ExcelDataValidation)item).TopNode);
+ var retVal = _validations.Remove(item);
+ if (retVal) {
+ OnValidationCountChanged();
+ }
+ return retVal;
+ }
+
+ /// <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 { return _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)) {
+ throw new InvalidCastException(
+ "The supplied item must inherit OfficeOpenXml.DataValidation.ExcelDataValidation");
+ }
+ TopNode
+ .SelectSingleNode(_dataValidationPath.TrimStart('/'), NameSpaceManager)
+ .RemoveChild(((ExcelDataValidation)m).TopNode);
+ }
+ _validations.RemoveAll(match);
+ OnValidationCountChanged();
+ }
+
+ 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
index 10718f3..f98b2f6 100644
--- a/EPPlus/DataValidation/ExcelDataValidationCustom.cs
+++ b/EPPlus/DataValidation/ExcelDataValidationCustom.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,75 +13,81 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-using OfficeOpenXml.DataValidation.Formulas;
+
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);
- }
+namespace OfficeOpenXml.DataValidation;
- /// <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>
+/// 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>
- /// <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);
- }
- }
+ /// <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
index 2a99ca0..c72a83d 100644
--- a/EPPlus/DataValidation/ExcelDataValidationDateTime.cs
+++ b/EPPlus/DataValidation/ExcelDataValidationDateTime.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,78 +13,85 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-using OfficeOpenXml.DataValidation.Formulas;
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);
- }
+namespace OfficeOpenXml.DataValidation;
- /// <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>
+/// 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>
- /// <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);
- }
- }
+ /// <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
index 04c9a1e..1e8e8af 100644
--- a/EPPlus/DataValidation/ExcelDataValidationDecimal.cs
+++ b/EPPlus/DataValidation/ExcelDataValidationDecimal.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,79 +13,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-using System.Globalization;
+
using System.Xml;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-using OfficeOpenXml.DataValidation.Formulas;
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);
- }
+namespace OfficeOpenXml.DataValidation;
- /// <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>
+/// 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>
- /// <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);
- }
- }
+ /// <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
index 023cfd4..86dcba6 100644
--- a/EPPlus/DataValidation/ExcelDataValidationFactory.cs
+++ b/EPPlus/DataValidation/ExcelDataValidationFactory.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,68 +13,66 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Collections.Generic;
-using System.Linq;
-using System.Text;
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.ToString());
- }
- }
+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
index c7aac88..12cdb94 100644
--- a/EPPlus/DataValidation/ExcelDataValidationInt.cs
+++ b/EPPlus/DataValidation/ExcelDataValidationInt.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,78 +13,90 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.DataValidation.Formulas;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
+
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);
- }
+namespace OfficeOpenXml.DataValidation;
- /// <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>
+/// 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>
- /// <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);
- }
- }
+ /// <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
index 6368938..e9dbdf1 100644
--- a/EPPlus/DataValidation/ExcelDataValidationList.cs
+++ b/EPPlus/DataValidation/ExcelDataValidationList.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,76 +13,81 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-using OfficeOpenXml.DataValidation.Formulas;
+
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);
- }
+namespace OfficeOpenXml.DataValidation;
- /// <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>
+/// 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>
- /// <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);
- }
- }
+ /// <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
index 55db9dd..a6f3fe2 100644
--- a/EPPlus/DataValidation/ExcelDataValidationOperator.cs
+++ b/EPPlus/DataValidation/ExcelDataValidationOperator.cs
@@ -13,42 +13,36 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-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
- }
+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
index 3a1f70b..3c37d13 100644
--- a/EPPlus/DataValidation/ExcelDataValidationTime.cs
+++ b/EPPlus/DataValidation/ExcelDataValidationTime.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,79 +13,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-using OfficeOpenXml.DataValidation.Formulas;
+
using System.Xml;
using OfficeOpenXml.DataValidation.Contracts;
-using System.Runtime.CompilerServices;
+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);
- }
+namespace OfficeOpenXml.DataValidation;
- /// <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>
+/// 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>
- /// <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);
- }
- }
+ /// <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
index 6ca1786..50b8571 100644
--- a/EPPlus/DataValidation/ExcelDataValidationType.cs
+++ b/EPPlus/DataValidation/ExcelDataValidationType.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,307 +13,277 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Collections.Generic;
-using System.Linq;
-using System.Text;
-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
+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; }
+
+ /// <summary>
+ /// Returns a validation type by <see cref="eDataValidationType"/>
+ /// </summary>
+ /// <param name="type"></param>
+ /// <returns></returns>
+ internal static ExcelDataValidationType GetByValidationType(eDataValidationType type) {
+ switch (type) {
+ case eDataValidationType.Any:
+ return Any;
+ case eDataValidationType.Whole:
+ return Whole;
+ case eDataValidationType.List:
+ return List;
+ case eDataValidationType.Decimal:
+ return Decimal;
+ case eDataValidationType.TextLength:
+ return TextLength;
+ case eDataValidationType.DateTime:
+ return DateTime;
+ case eDataValidationType.Time:
+ return Time;
+ case eDataValidationType.Custom:
+ return Custom;
+ default:
+ throw new InvalidOperationException("Non supported Validationtype : " + type);
}
+ }
- 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";
+ 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>
- /// 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;
- }
-
- /// <summary>
- /// Returns a validation type by <see cref="eDataValidationType"/>
- /// </summary>
- /// <param name="type"></param>
- /// <returns></returns>
- internal static ExcelDataValidationType GetByValidationType(eDataValidationType type)
- {
- switch (type)
- {
- case eDataValidationType.Any:
- return ExcelDataValidationType.Any;
- case eDataValidationType.Whole:
- return ExcelDataValidationType.Whole;
- case eDataValidationType.List:
- return ExcelDataValidationType.List;
- case eDataValidationType.Decimal:
- return ExcelDataValidationType.Decimal;
- case eDataValidationType.TextLength:
- return ExcelDataValidationType.TextLength;
- case eDataValidationType.DateTime:
- return ExcelDataValidationType.DateTime;
- case eDataValidationType.Time:
- return ExcelDataValidationType.Time;
- case eDataValidationType.Custom:
- return ExcelDataValidationType.Custom;
- default:
- throw new InvalidOperationException("Non supported Validationtype : " + type.ToString());
- }
- }
-
- internal static ExcelDataValidationType GetBySchemaName(string schemaName)
- {
- switch (schemaName)
- {
- case DataValidationSchemaNames.Any:
- return ExcelDataValidationType.Any;
- case DataValidationSchemaNames.Whole:
- return ExcelDataValidationType.Whole;
- case DataValidationSchemaNames.Decimal:
- return ExcelDataValidationType.Decimal;
- case DataValidationSchemaNames.List:
- return ExcelDataValidationType.List;
- case DataValidationSchemaNames.TextLength:
- return ExcelDataValidationType.TextLength;
- case DataValidationSchemaNames.Date:
- return ExcelDataValidationType.DateTime;
- case DataValidationSchemaNames.Time:
- return ExcelDataValidationType.Time;
- case DataValidationSchemaNames.Custom:
- return ExcelDataValidationType.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))
- {
- return false;
- }
- return ((ExcelDataValidationType)obj).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 ExcelDataValidationType(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 ExcelDataValidationType(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 ExcelDataValidationType(eDataValidationType.List, false, DataValidationSchemaNames.List);
- }
- return _list;
- }
- }
-
- private static ExcelDataValidationType _decimal;
- public static ExcelDataValidationType Decimal
- {
- get
- {
- if (_decimal == null)
- {
- _decimal = new ExcelDataValidationType(eDataValidationType.Decimal, true, DataValidationSchemaNames.Decimal);
- }
- return _decimal;
- }
- }
-
- private static ExcelDataValidationType _textLength;
- public static ExcelDataValidationType TextLength
- {
- get
- {
- if (_textLength == null)
- {
- _textLength = new ExcelDataValidationType(eDataValidationType.TextLength, true, DataValidationSchemaNames.TextLength);
- }
- return _textLength;
- }
- }
-
- private static ExcelDataValidationType _dateTime;
- public static ExcelDataValidationType DateTime
- {
- get
- {
- if (_dateTime == null)
- {
- _dateTime = new ExcelDataValidationType(eDataValidationType.DateTime, true, DataValidationSchemaNames.Date);
- }
- return _dateTime;
- }
- }
-
- private static ExcelDataValidationType _time;
- public static ExcelDataValidationType Time
- {
- get
- {
- if (_time == null)
- {
- _time = new ExcelDataValidationType(eDataValidationType.Time, true, DataValidationSchemaNames.Time);
- }
- return _time;
- }
- }
-
- private static ExcelDataValidationType _custom;
- public static ExcelDataValidationType Custom
- {
- get
- {
- if (_custom == null)
- {
- _custom = new ExcelDataValidationType(eDataValidationType.Custom, true, DataValidationSchemaNames.Custom);
- }
- return _custom;
- }
- }
+ /// <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)) {
+ return false;
}
+ return ((ExcelDataValidationType)obj).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
index f6a0578..ae808bb 100644
--- a/EPPlus/DataValidation/ExcelDataValidationWarningStyle.cs
+++ b/EPPlus/DataValidation/ExcelDataValidationWarningStyle.cs
@@ -13,49 +13,46 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-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
- }
+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
index 30b66d3..7c20825 100644
--- a/EPPlus/DataValidation/ExcelDataValidationWithFormula.cs
+++ b/EPPlus/DataValidation/ExcelDataValidationWithFormula.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,97 +13,92 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
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)
- {
+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>
+ 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>
+ /// 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; }
-
- /// <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'");
- }
- }
- }
+ 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
index a8fecd3..3b9b7c0 100644
--- a/EPPlus/DataValidation/ExcelDataValidationWithFormula2.cs
+++ b/EPPlus/DataValidation/ExcelDataValidationWithFormula2.cs
@@ -13,79 +13,74 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
+
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)
- {
+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>
+ 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>
+ /// 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;
- }
- }
+ /// <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
index c60a5c0..783eb17 100644
--- a/EPPlus/DataValidation/ExcelTime.cs
+++ b/EPPlus/DataValidation/ExcelTime.cs
@@ -13,257 +13,212 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
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 _timeChanged;
- 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;
+namespace OfficeOpenXml.DataValidation;
- /// <summary>
- /// Default constructor
- /// </summary>
- public ExcelTime()
- {
+/// <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>
- /// 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");
- }
- else if (value >= 1M)
- {
- throw new ArgumentException("Value cannot be greater or equal to 1");
- }
- Init(value);
- }
+ /// <summary>
+ /// Max number of decimals when rounding.
+ /// </summary>
+ public const int NumberOfDecimals = 15;
- private void Init(decimal value)
- {
- // handle hour
- decimal totalSeconds = value * SecondsPerDay;
- decimal hour = Math.Floor(totalSeconds / SecondsPerHour);
- Hour = (int)hour;
+ /// <summary>
+ /// Default constructor
+ /// </summary>
+ public ExcelTime() {}
- // 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 { _timeChanged += value; }
- remove { _timeChanged -= value; }
- }
-
- private void OnTimeChanged()
- {
- if (_timeChanged != null)
- {
- _timeChanged(this, EventArgs.Empty);
- }
- }
-
- private int _hour;
- /// <summary>
- /// Hour between 0 and 23
- /// </summary>
- public int Hour
- {
- get
- {
- return _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
- {
- return _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
- {
- return _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 (decimal)result;
- }
-
- /// <summary>
- /// Returns the excel decimal representation of a time.
- /// </summary>
- /// <returns></returns>
- public decimal ToExcelTime()
- {
- var seconds = ToSeconds();
- return Round(seconds / (decimal)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.ToString() : Hour.ToString(),
- Minute < 10 ? "0" + Minute.ToString() : Minute.ToString(),
- second < 10 ? "0" + second.ToString() : second.ToString());
- }
-
+ /// <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
index b25c1ad..fee785c 100644
--- a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormula.cs
+++ b/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormula.cs
@@ -13,37 +13,31 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-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; }
- }
+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
index 1380c48..2cc6df2 100644
--- a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDateTime.cs
+++ b/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDateTime.cs
@@ -13,33 +13,29 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-namespace OfficeOpenXml.DataValidation.Formulas.Contracts
-{
- /// <summary>
- /// Validation formula interface for <see cref="DateTime"/>
- /// </summary>
- public interface IExcelDataValidationFormulaDateTime : IExcelDataValidationFormulaWithValue<DateTime?>
- {
- }
-}
+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
index a77761e..0a87a75 100644
--- a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDecimal.cs
+++ b/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaDecimal.cs
@@ -13,33 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-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?>
- {
- }
-}
+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
index ba1d47c..47ecfaa 100644
--- a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaInt.cs
+++ b/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaInt.cs
@@ -13,33 +13,26 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-namespace OfficeOpenXml.DataValidation.Formulas.Contracts
-{
- /// <summary>
- /// Interface for a data validation formula of <see cref="System.Int32"/> value
- /// </summary>
- public interface IExcelDataValidationFormulaInt : IExcelDataValidationFormulaWithValue<int?>
- {
- }
-}
+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
index 2162b57..6a799b4 100644
--- a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaList.cs
+++ b/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaList.cs
@@ -13,37 +13,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-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; }
- }
+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
index 26fc36a..a9f1f5d 100644
--- a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaTime.cs
+++ b/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaTime.cs
@@ -13,31 +13,24 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.DataValidation;
-namespace OfficeOpenXml.DataValidation.Formulas.Contracts
-{
- public interface IExcelDataValidationFormulaTime : IExcelDataValidationFormulaWithValue<ExcelTime>
- {
- }
-}
+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
index 70b1bbc..21b937b 100644
--- a/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaWithValue.cs
+++ b/EPPlus/DataValidation/Formulas/Contracts/IExcelDataValidationFormulaWithValue.cs
@@ -13,38 +13,32 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-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; }
- }
+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
index 7663192..bbc9819 100644
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormula.cs
+++ b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormula.cs
@@ -13,126 +13,107 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
using System.Xml;
using OfficeOpenXml.Utils;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-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
+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);
}
+ }
- /// <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;
- }
+ internal abstract void ResetValue();
- 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
- {
- return _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();
+ /// <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
index 2975c8d..1072535 100644
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaCustom.cs
+++ b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaCustom.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,60 +13,55 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
+
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;
- }
+namespace OfficeOpenXml.DataValidation.Formulas;
- internal override string GetXmlValue()
- {
- return ExcelFormula;
- }
-
- protected override string GetValueAsString()
- {
- return ExcelFormula;
- }
-
- internal override void ResetValue()
- {
- ExcelFormula = null;
- }
+/// <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
index 6381be8..5543046 100644
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaDateTime.cs
+++ b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaDateTime.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,56 +13,52 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
+using System.Globalization;
using System.Xml;
using OfficeOpenXml.DataValidation.Formulas.Contracts;
-using System.Globalization;
-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))
- {
- double oADate = default(double);
- if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out oADate))
- {
- Value = DateTime.FromOADate(oADate);
- }
- else
- {
- ExcelFormula = value;
- }
- }
- }
+namespace OfficeOpenXml.DataValidation.Formulas;
- protected override string GetValueAsString()
- {
- return Value.HasValue ? Value.Value.ToOADate().ToString(CultureInfo.InvariantCulture) : string.Empty;
- }
-
+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)) {
+ double oADate = default(double);
+ if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out 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
index dda4d92..67b921d 100644
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaDecimal.cs
+++ b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaDecimal.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,58 +13,54 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
+
+using System.Globalization;
using System.Xml;
using OfficeOpenXml.DataValidation.Formulas.Contracts;
-using System.Globalization;
-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))
- {
- double dValue = default(double);
- if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out dValue))
- {
- Value = dValue;
- }
- else
- {
- ExcelFormula = value;
- }
- }
- }
+namespace OfficeOpenXml.DataValidation.Formulas;
- protected override string GetValueAsString()
- {
- return Value.HasValue ? Value.Value.ToString("R15", CultureInfo.InvariantCulture) : string.Empty;
- }
+/// <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)) {
+ double dValue = default(double);
+ if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out 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
index c898a39..70dc8cc 100644
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaInt.cs
+++ b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaInt.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,55 +13,48 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
+
using System.Xml;
using OfficeOpenXml.DataValidation.Formulas.Contracts;
-using System.Globalization;
-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))
- {
- int intValue = default(int);
- if (int.TryParse(value, out intValue))
- {
- Value = intValue;
- }
- else
- {
- ExcelFormula = value;
- }
- }
- }
+namespace OfficeOpenXml.DataValidation.Formulas;
- protected override string GetValueAsString()
- {
- return Value.HasValue ? Value.Value.ToString() : string.Empty;
- }
+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)) {
+ int intValue = default(int);
+ if (int.TryParse(value, out 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
index 53527fa..bfe5301 100644
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaList.cs
+++ b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaList.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,235 +13,180 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Linq;
using System.Text;
using System.Xml;
-using OfficeOpenXml.Utils;
using OfficeOpenXml.DataValidation.Formulas.Contracts;
-using System.Text.RegularExpressions;
-using System.Collections;
+using OfficeOpenXml.Utils;
-namespace OfficeOpenXml.DataValidation.Formulas
-{
- internal class ExcelDataValidationFormulaList : ExcelDataValidationFormula, IExcelDataValidationFormulaList
- {
- #region class DataValidationList
- private class DataValidationList : IList<string>, ICollection
- {
- private IList<string> _items = new List<string>();
- private EventHandler<EventArgs> _listChanged;
+namespace OfficeOpenXml.DataValidation.Formulas;
- public event EventHandler<EventArgs> ListChanged
- {
- add { _listChanged += value; }
- remove { _listChanged -= value; }
- }
+internal class ExcelDataValidationFormulaList
+ : ExcelDataValidationFormula,
+ IExcelDataValidationFormulaList {
+ private class DataValidationList : IList<string>, ICollection {
+ private IList<string> _items = new List<string>();
+ private EventHandler<EventArgs> _listChanged;
- private void OnListChanged()
- {
- if (_listChanged != null)
- {
- _listChanged(this, EventArgs.Empty);
- }
- }
-
- #region IList members
- 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
- {
- return _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
- {
- get { return _items.Count; }
- }
-
- bool ICollection<string>.IsReadOnly
- {
- get { return false; }
- }
-
- bool ICollection<string>.Remove(string item)
- {
- var retVal = _items.Remove(item);
- OnListChanged();
- return retVal;
- }
-
- IEnumerator<string> IEnumerable<string>.GetEnumerator()
- {
- return _items.GetEnumerator();
- }
-
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return _items.GetEnumerator();
- }
- #endregion
-
- public void CopyTo(Array array, int index)
- {
- _items.CopyTo((string[])array, index);
- }
-
- int ICollection.Count
- {
- get { return _items.Count; }
- }
-
- public bool IsSynchronized
- {
- get { return ((ICollection)_items).IsSynchronized; }
- }
-
- public object SyncRoot
- {
- get { return ((ICollection)_items).SyncRoot; }
- }
- }
- #endregion
-
- 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 += new EventHandler<EventArgs>(values_ListChanged);
- Values = values;
- SetInitialValues();
- }
-
- private 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 char[]{','}, StringSplitOptions.RemoveEmptyEntries);
- foreach (var item in items)
- {
- Values.Add(item);
- }
- }
- else
- {
- ExcelFormula = @value;
- }
- }
- }
-
- 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();
- }
+ 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 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
index 1ee1972..38a8176 100644
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaTime.cs
+++ b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaTime.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,76 +13,65 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.DataValidation.Formulas.Contracts;
-using OfficeOpenXml.DataValidation;
-using System.Xml;
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))
- {
- decimal time = default(decimal);
- if (decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out time))
- {
- Value = new ExcelTime(time);
- }
- else
- {
- Value = new ExcelTime();
- ExcelFormula = value;
- }
- }
- else
- {
- Value = new ExcelTime();
- }
- Value.TimeChanged += new EventHandler(Value_TimeChanged);
- }
+namespace OfficeOpenXml.DataValidation.Formulas;
- 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 ExcelTime();
- }
+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)) {
+ decimal time = default(decimal);
+ if (decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out 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
index 66a7f99..8490c7a 100644
--- a/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaValue.cs
+++ b/EPPlus/DataValidation/Formulas/ExcelDataValidationFormulaValue.cs
@@ -13,72 +13,59 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.Utils;
+
using System.Xml;
-namespace OfficeOpenXml.DataValidation.Formulas
-{
+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)
- {
+/// <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;
- private T _value;
- /// <summary>
- /// Typed value
- /// </summary>
- public T Value
- {
- get
- {
- return _value;
- }
- set
- {
- State = FormulaState.Value;
- _value = value;
- SetXmlNodeString(FormulaPath, GetValueAsString());
- }
- }
-
- internal override void ResetValue()
- {
- Value = default(T);
- }
-
+ /// <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
index f7cb3ba..0002560 100644
--- a/EPPlus/DataValidation/IRangeDataValidation.cs
+++ b/EPPlus/DataValidation/IRangeDataValidation.cs
@@ -13,73 +13,77 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Linq;
-using System.Text;
+
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();
- }
+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
index 90c517b..82bf95d 100644
--- a/EPPlus/DataValidation/RangeDataValidation.cs
+++ b/EPPlus/DataValidation/RangeDataValidation.cs
@@ -13,82 +13,68 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.Utils;
+
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;
- }
+namespace OfficeOpenXml.DataValidation;
- ExcelWorksheet _worksheet;
- string _address;
+internal class RangeDataValidation : IRangeDataValidation {
+ public RangeDataValidation(ExcelWorksheet worksheet, string address) {
+ Require.Argument(worksheet).IsNotNull("worksheet");
+ Require.Argument(address).IsNotNullOrEmpty("address");
+ _worksheet = worksheet;
+ _address = address;
+ }
- public IExcelDataValidationAny AddAnyDataValidation()
- {
- return _worksheet.DataValidations.AddAnyValidation(_address);
- }
+ private ExcelWorksheet _worksheet;
+ private string _address;
- public IExcelDataValidationInt AddIntegerDataValidation()
- {
- return _worksheet.DataValidations.AddIntegerValidation(_address);
- }
+ public IExcelDataValidationAny AddAnyDataValidation() {
+ return _worksheet.DataValidations.AddAnyValidation(_address);
+ }
- public IExcelDataValidationDecimal AddDecimalDataValidation()
- {
- return _worksheet.DataValidations.AddDecimalValidation(_address);
- }
+ public IExcelDataValidationInt AddIntegerDataValidation() {
+ return _worksheet.DataValidations.AddIntegerValidation(_address);
+ }
- public IExcelDataValidationDateTime AddDateTimeDataValidation()
- {
- return _worksheet.DataValidations.AddDateTimeValidation(_address);
- }
+ public IExcelDataValidationDecimal AddDecimalDataValidation() {
+ return _worksheet.DataValidations.AddDecimalValidation(_address);
+ }
- public IExcelDataValidationList AddListDataValidation()
- {
- return _worksheet.DataValidations.AddListValidation(_address);
- }
+ public IExcelDataValidationDateTime AddDateTimeDataValidation() {
+ return _worksheet.DataValidations.AddDateTimeValidation(_address);
+ }
- public IExcelDataValidationInt AddTextLengthDataValidation()
- {
- return _worksheet.DataValidations.AddTextLengthValidation(_address);
- }
+ public IExcelDataValidationList AddListDataValidation() {
+ return _worksheet.DataValidations.AddListValidation(_address);
+ }
- public IExcelDataValidationTime AddTimeDataValidation()
- {
- return _worksheet.DataValidations.AddTimeValidation(_address);
- }
+ public IExcelDataValidationInt AddTextLengthDataValidation() {
+ return _worksheet.DataValidations.AddTextLengthValidation(_address);
+ }
- public IExcelDataValidationCustom AddCustomDataValidation()
- {
- return _worksheet.DataValidations.AddCustomValidation(_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
index cef41dc..df934c8 100644
--- a/EPPlus/Drawing/Vml/ExcelVmlDrawingBase.cs
+++ b/EPPlus/Drawing/Vml/ExcelVmlDrawingBase.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,17 +13,17 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
@@ -32,131 +32,121 @@
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
- {
- internal ExcelVmlDrawingBase(XmlNode topNode, XmlNamespaceManager ns) :
- base(ns, topNode)
- {
- SchemaNodeOrder = new string[] { "fill", "stroke", "shadow", "path", "textbox", "ClientData", "MoveWithCells", "SizeWithCells", "Anchor", "Locked", "AutoFill", "LockText", "TextHAlign", "TextVAlign", "Row", "Column", "Visible" };
- }
- public string Id
- {
- get
- {
- return GetXmlNodeString("@id");
- }
- set
- {
- SetXmlNodeString("@id",value);
- }
+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 {
+ internal ExcelVmlDrawingBase(XmlNode topNode, XmlNamespaceManager ns)
+ : base(ns, topNode) {
+ SchemaNodeOrder = new[] {
+ "fill",
+ "stroke",
+ "shadow",
+ "path",
+ "textbox",
+ "ClientData",
+ "MoveWithCells",
+ "SizeWithCells",
+ "Anchor",
+ "Locked",
+ "AutoFill",
+ "LockText",
+ "TextHAlign",
+ "TextVAlign",
+ "Row",
+ "Column",
+ "Visible",
+ };
+ }
+
+ 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;
}
- /// <summary>
- /// Alternative text to be displayed instead of a graphic.
- /// </summary>
- public string AlternativeText
- {
- get
- {
- return GetXmlNodeString("@alt");
- }
- set
- {
- SetXmlNodeString("@alt", value);
- }
- }
- #region "Style Handling methods"
- 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;
- }
- #endregion
+ } 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
index 5fa0e82..912214e 100644
--- a/EPPlus/Drawing/Vml/ExcelVmlDrawingBaseCollection.cs
+++ b/EPPlus/Drawing/Vml/ExcelVmlDrawingBaseCollection.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,54 +13,51 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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 = new XmlDocument();
- VmlDrawingXml.PreserveWhitespace = false;
-
- NameTable nt=new NameTable();
- NameSpaceManager = new XmlNamespaceManager(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; }
- internal Uri Uri { get; set; }
- internal string RelId { get; set; }
- internal Packaging.ZipPackagePart Part { get; set; }
- internal XmlNamespaceManager NameSpaceManager { get; set; }
+namespace OfficeOpenXml.Drawing.Vml;
+
+public class ExcelVmlDrawingBaseCollection {
+ internal ExcelVmlDrawingBaseCollection(ExcelPackage pck, ExcelWorksheet ws, Uri uri) {
+ VmlDrawingXml = new();
+ 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; }
+ 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
index 270eb24..560529e 100644
--- a/EPPlus/Drawing/Vml/ExcelVmlDrawingComment.cs
+++ b/EPPlus/Drawing/Vml/ExcelVmlDrawingComment.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,446 +13,402 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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 System.Globalization;
using System.Drawing;
+using System.Globalization;
+using System.Xml;
-namespace OfficeOpenXml.Drawing.Vml
-{
- /// <summary>
- /// Drawing object used for comments
- /// </summary>
- public class ExcelVmlDrawingComment : ExcelVmlDrawingBase, IRangeID
- {
- internal ExcelVmlDrawingComment(XmlNode topNode, ExcelRangeBase range, XmlNamespaceManager ns) :
- base(topNode, ns)
- {
- Range = range;
- SchemaNodeOrder = new string[] { "fill", "stroke", "shadow", "path", "textbox", "ClientData", "MoveWithCells", "SizeWithCells", "Anchor", "Locked", "AutoFill", "LockText", "TextHAlign", "TextVAlign", "Row", "Column", "Visible" };
- }
- internal ExcelRangeBase Range { get; set; }
+namespace OfficeOpenXml.Drawing.Vml;
- /// <summary>
- /// Address in the worksheet
- /// </summary>
- public string Address
- {
- get
- {
- return Range.Address;
- }
- }
+/// <summary>
+/// Drawing object used for comments
+/// </summary>
+public class ExcelVmlDrawingComment : ExcelVmlDrawingBase, IRangeId {
+ internal ExcelVmlDrawingComment(XmlNode topNode, ExcelRangeBase range, XmlNamespaceManager ns)
+ : base(topNode, ns) {
+ Range = range;
+ SchemaNodeOrder = new[] {
+ "fill",
+ "stroke",
+ "shadow",
+ "path",
+ "textbox",
+ "ClientData",
+ "MoveWithCells",
+ "SizeWithCells",
+ "Anchor",
+ "Locked",
+ "AutoFill",
+ "LockText",
+ "TextHAlign",
+ "TextVAlign",
+ "Row",
+ "Column",
+ "Visible",
+ };
+ }
- const string VERTICAL_ALIGNMENT_PATH="x:ClientData/x:TextVAlign";
- /// <summary>
- /// Vertical alignment for text
- /// </summary>
- public eTextAlignVerticalVml VerticalAlignment
- {
- get
- {
- switch (GetXmlNodeString(VERTICAL_ALIGNMENT_PATH))
- {
- case "Center":
- return eTextAlignVerticalVml.Center;
- case "Bottom":
- return eTextAlignVerticalVml.Bottom;
- default:
- return eTextAlignVerticalVml.Top;
- }
- }
- set
- {
- switch (value)
- {
- case eTextAlignVerticalVml.Center:
- SetXmlNodeString(VERTICAL_ALIGNMENT_PATH, "Center");
- break;
- case eTextAlignVerticalVml.Bottom:
- SetXmlNodeString(VERTICAL_ALIGNMENT_PATH, "Bottom");
- break;
- default:
- DeleteNode(VERTICAL_ALIGNMENT_PATH);
- break;
- }
- }
- }
- const string HORIZONTAL_ALIGNMENT_PATH="x:ClientData/x:TextHAlign";
- /// <summary>
- /// Horizontal alignment for text
- /// </summary>
- public eTextAlignHorizontalVml HorizontalAlignment
- {
- get
- {
- switch (GetXmlNodeString(HORIZONTAL_ALIGNMENT_PATH))
- {
- case "Center":
- return eTextAlignHorizontalVml.Center;
- case "Right":
- return eTextAlignHorizontalVml.Right;
- default:
- return eTextAlignHorizontalVml.Left;
- }
- }
- set
- {
- switch (value)
- {
- case eTextAlignHorizontalVml.Center:
- SetXmlNodeString(HORIZONTAL_ALIGNMENT_PATH, "Center");
- break;
- case eTextAlignHorizontalVml.Right:
- SetXmlNodeString(HORIZONTAL_ALIGNMENT_PATH, "Right");
- break;
- default:
- DeleteNode(HORIZONTAL_ALIGNMENT_PATH);
- break;
- }
- }
- }
- const string VISIBLE_PATH = "x:ClientData/x:Visible";
- /// <summary>
- /// If the drawing object is visible.
- /// </summary>
- public bool Visible
- {
- get
- {
- return (TopNode.SelectSingleNode(VISIBLE_PATH, NameSpaceManager)!=null);
- }
- set
- {
- if (value)
- {
- CreateNode(VISIBLE_PATH);
- Style = SetStyle(Style,"visibility", "visible");
- }
- else
- {
- DeleteNode(VISIBLE_PATH);
- Style = SetStyle(Style,"visibility", "hidden");
- }
- }
- }
- const string BACKGROUNDCOLOR_PATH = "@fillcolor";
- const string BACKGROUNDCOLOR2_PATH = "v:fill/@color2";
- /// <summary>
- /// Background color
- /// </summary>
- public Color BackgroundColor
- {
- get
- {
- string col = GetXmlNodeString(BACKGROUNDCOLOR_PATH);
- if (col == "")
- {
- return Color.FromArgb(0xff, 0xff, 0xe1);
- }
- else
- {
- if(col.StartsWith("#")) col=col.Substring(1,col.Length-1);
- int res;
- if (int.TryParse(col,System.Globalization.NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out res))
- {
- return Color.FromArgb(res);
- }
- else
- {
- return Color.Empty;
- }
- }
- }
- set
- {
- string color = "#" + value.ToArgb().ToString("X").Substring(2, 6);
- SetXmlNodeString(BACKGROUNDCOLOR_PATH, color);
- //SetXmlNode(BACKGROUNDCOLOR2_PATH, color);
- }
- }
- const string LINESTYLE_PATH="v:stroke/@dashstyle";
- const string ENDCAP_PATH = "v:stroke/@endcap";
- /// <summary>
- /// Linestyle for border
- /// </summary>
- public eLineStyleVml LineStyle
- {
- get
- {
- string v=GetXmlNodeString(LINESTYLE_PATH);
- if (v == "")
- {
- return eLineStyleVml.Solid;
- }
- else if (v == "1 1")
- {
- v = GetXmlNodeString(ENDCAP_PATH);
- return (eLineStyleVml)Enum.Parse(typeof(eLineStyleVml), v, true);
- }
- else
- {
- return (eLineStyleVml)Enum.Parse(typeof(eLineStyleVml), v, true);
- }
- }
- set
- {
- if (value == eLineStyleVml.Round || value == eLineStyleVml.Square)
- {
- SetXmlNodeString(LINESTYLE_PATH, "1 1");
- if (value == eLineStyleVml.Round)
- {
- SetXmlNodeString(ENDCAP_PATH, "round");
- }
- else
- {
- DeleteNode(ENDCAP_PATH);
- }
- }
- else
- {
- string v = value.ToString();
- v = v.Substring(0, 1).ToLower(CultureInfo.InvariantCulture) + v.Substring(1, v.Length - 1);
- SetXmlNodeString(LINESTYLE_PATH, v);
- DeleteNode(ENDCAP_PATH);
- }
- }
- }
- const string LINECOLOR_PATH="@strokecolor";
- /// <summary>
- /// Line color
- /// </summary>
- public Color LineColor
- {
- get
- {
- string col = GetXmlNodeString(LINECOLOR_PATH);
- if (col == "")
- {
- return Color.Black;
- }
- else
- {
- if (col.StartsWith("#")) col = col.Substring(1, col.Length - 1);
- int res;
- if (int.TryParse(col, System.Globalization.NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out res))
- {
- return Color.FromArgb(res);
- }
- else
- {
- return Color.Empty;
- }
- }
- }
- set
- {
- string color = "#" + value.ToArgb().ToString("X").Substring(2, 6);
- SetXmlNodeString(LINECOLOR_PATH, color);
- }
- }
- const string LINEWIDTH_PATH="@strokeweight";
- /// <summary>
- /// Width of the border
- /// </summary>
- public Single LineWidth
- {
- get
- {
- string wt=GetXmlNodeString(LINEWIDTH_PATH);
- if (wt == "") return (Single).75;
- if(wt.EndsWith("pt")) wt=wt.Substring(0,wt.Length-2);
+ internal ExcelRangeBase Range { get; set; }
- Single ret;
- if(Single.TryParse(wt,System.Globalization.NumberStyles.Any, CultureInfo.InvariantCulture, out ret))
- {
- return ret;
- }
- else
- {
- return 0;
- }
- }
- set
- {
- SetXmlNodeString(LINEWIDTH_PATH, value.ToString(CultureInfo.InvariantCulture) + "pt");
- }
- }
- ///// <summary>
- ///// Width of the Comment
- ///// </summary>
- //public Single Width
- //{
- // get
- // {
- // string v;
- // GetStyle("width", out v);
- // if(v.EndsWith("pt"))
- // {
- // v = v.Substring(0, v.Length - 2);
- // }
- // short ret;
- // if (short.TryParse(v,System.Globalization.NumberStyles.Any, CultureInfo.InvariantCulture, out ret))
- // {
- // return ret;
- // }
- // else
- // {
- // return 0;
- // }
- // }
- // set
- // {
- // SetStyle("width", value.ToString("N2",CultureInfo.InvariantCulture) + "pt");
- // }
- //}
- ///// <summary>
- ///// Height of the Comment
- ///// </summary>
- //public Single Height
- //{
- // get
- // {
- // string v;
- // GetStyle("height", out v);
- // if (v.EndsWith("pt"))
- // {
- // v = v.Substring(0, v.Length - 2);
- // }
- // short ret;
- // if (short.TryParse(v, System.Globalization.NumberStyles.Any, CultureInfo.InvariantCulture, out ret))
- // {
- // return ret;
- // }
- // else
- // {
- // return 0;
- // }
- // }
- // set
- // {
- // SetStyle("height", value.ToString("N2", CultureInfo.InvariantCulture) + "pt");
- // }
- //}
- const string TEXTBOX_STYLE_PATH = "v:textbox/@style";
- /// <summary>
- /// Autofits the drawingobject
- /// </summary>
- public bool AutoFit
- {
- get
- {
- string value;
- GetStyle(GetXmlNodeString(TEXTBOX_STYLE_PATH), "mso-fit-shape-to-text", out value);
- return value=="t";
- }
- set
- {
- SetXmlNodeString(TEXTBOX_STYLE_PATH, SetStyle(GetXmlNodeString(TEXTBOX_STYLE_PATH),"mso-fit-shape-to-text", value?"t":""));
- }
- }
- const string LOCKED_PATH = "x:ClientData/x:Locked";
- /// <summary>
- /// If the object is locked when the sheet is protected
- /// </summary>
- public bool Locked
- {
- get
- {
- return GetXmlNodeBool(LOCKED_PATH, false);
- }
- set
- {
- SetXmlNodeBool(LOCKED_PATH, value, false);
- }
- }
- const string LOCK_TEXT_PATH = "x:ClientData/x:LockText";
- /// <summary>
- /// Specifies that the object's text is locked
- /// </summary>
- public bool LockText
- {
- get
- {
- return GetXmlNodeBool(LOCK_TEXT_PATH, false);
- }
- set
- {
- SetXmlNodeBool(LOCK_TEXT_PATH, value, false);
- }
- }
- ExcelVmlDrawingPosition _from = null;
- /// <summary>
- /// From position. For comments only when Visible=true.
- /// </summary>
- public ExcelVmlDrawingPosition From
- {
- get
- {
- if (_from == null)
- {
- _from = new ExcelVmlDrawingPosition(NameSpaceManager, TopNode.SelectSingleNode("x:ClientData", NameSpaceManager), 0);
- }
- return _from;
- }
- }
- ExcelVmlDrawingPosition _to = null;
- /// <summary>
- /// To position. For comments only when Visible=true.
- /// </summary>
- public ExcelVmlDrawingPosition To
- {
- get
- {
- if (_to == null)
- {
- _to = new ExcelVmlDrawingPosition(NameSpaceManager, TopNode.SelectSingleNode("x:ClientData", NameSpaceManager), 4);
- }
- return _to;
- }
- }
- const string STYLE_PATH = "@style";
- internal string Style
- {
- get
- {
- return GetXmlNodeString(STYLE_PATH);
- }
- set
- {
- SetXmlNodeString(STYLE_PATH, value);
- }
- }
- #region IRangeID Members
+ /// <summary>
+ /// Address in the worksheet
+ /// </summary>
+ public string Address => Range.Address;
- ulong IRangeID.RangeID
- {
- get
- {
- return ExcelCellBase.GetCellID(Range.Worksheet.SheetID, Range.Start.Row, Range.Start.Column);
- }
- set
- {
-
- }
- }
+ private const string _verticalAlignmentPath = "x:ClientData/x:TextVAlign";
- #endregion
+ /// <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 { return (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 _backgroundcolorPath = "@fillcolor";
+ private const string _backgroundcolor2Path = "v:fill/@color2";
+
+ /// <summary>
+ /// Background color
+ /// </summary>
+ public Color BackgroundColor {
+ get {
+ string col = GetXmlNodeString(_backgroundcolorPath);
+ if (col == "") {
+ return Color.FromArgb(0xff, 0xff, 0xe1);
+ }
+ if (col.StartsWith("#")) {
+ col = col.Substring(1, col.Length - 1);
+ }
+ int res;
+ if (int.TryParse(
+ col,
+ NumberStyles.AllowHexSpecifier,
+ CultureInfo.InvariantCulture,
+ out res)) {
+ return Color.FromArgb(res);
+ }
+ return Color.Empty;
+ }
+ set {
+ string color = "#" + value.ToArgb().ToString("X").Substring(2, 6);
+ SetXmlNodeString(_backgroundcolorPath, color);
+ //SetXmlNode(BACKGROUNDCOLOR2_PATH, color);
+ }
+ }
+
+ private const string _linestylePath = "v:stroke/@dashstyle";
+ private const string _endcapPath = "v:stroke/@endcap";
+
+ /// <summary>
+ /// Linestyle for border
+ /// </summary>
+ public eLineStyleVml LineStyle {
+ get {
+ string v = GetXmlNodeString(_linestylePath);
+ if (v == "") {
+ return eLineStyleVml.Solid;
+ }
+ if (v == "1 1") {
+ v = GetXmlNodeString(_endcapPath);
+ return (eLineStyleVml)Enum.Parse(typeof(eLineStyleVml), v, true);
+ }
+ return (eLineStyleVml)Enum.Parse(typeof(eLineStyleVml), v, true);
+ }
+ set {
+ if (value == eLineStyleVml.Round || value == eLineStyleVml.Square) {
+ SetXmlNodeString(_linestylePath, "1 1");
+ if (value == eLineStyleVml.Round) {
+ SetXmlNodeString(_endcapPath, "round");
+ } else {
+ DeleteNode(_endcapPath);
+ }
+ } else {
+ string v = value.ToString();
+ v = v.Substring(0, 1).ToLower(CultureInfo.InvariantCulture) + v.Substring(1, v.Length - 1);
+ SetXmlNodeString(_linestylePath, v);
+ DeleteNode(_endcapPath);
+ }
+ }
+ }
+
+ private const string _linecolorPath = "@strokecolor";
+
+ /// <summary>
+ /// Line color
+ /// </summary>
+ public Color LineColor {
+ get {
+ string col = GetXmlNodeString(_linecolorPath);
+ if (col == "") {
+ return Color.Black;
+ }
+ if (col.StartsWith("#")) {
+ col = col.Substring(1, col.Length - 1);
+ }
+ int res;
+ if (int.TryParse(
+ col,
+ NumberStyles.AllowHexSpecifier,
+ CultureInfo.InvariantCulture,
+ out res)) {
+ return Color.FromArgb(res);
+ }
+ return Color.Empty;
+ }
+ set {
+ string color = "#" + value.ToArgb().ToString("X").Substring(2, 6);
+ SetXmlNodeString(_linecolorPath, color);
+ }
+ }
+
+ private const string _linewidthPath = "@strokeweight";
+
+ /// <summary>
+ /// Width of the border
+ /// </summary>
+ public Single LineWidth {
+ get {
+ string wt = GetXmlNodeString(_linewidthPath);
+ if (wt == "") {
+ return (Single).75;
+ }
+ if (wt.EndsWith("pt")) {
+ wt = wt.Substring(0, wt.Length - 2);
+ }
+
+ Single ret;
+ if (Single.TryParse(wt, NumberStyles.Any, CultureInfo.InvariantCulture, out ret)) {
+ return ret;
+ }
+ return 0;
+ }
+ set { SetXmlNodeString(_linewidthPath, value.ToString(CultureInfo.InvariantCulture) + "pt"); }
+ }
+
+ ///// <summary>
+ ///// Width of the Comment
+ ///// </summary>
+ //public Single Width
+ //{
+ // get
+ // {
+ // string v;
+ // GetStyle("width", out v);
+ // if(v.EndsWith("pt"))
+ // {
+ // v = v.Substring(0, v.Length - 2);
+ // }
+ // short ret;
+ // if (short.TryParse(v,System.Globalization.NumberStyles.Any, CultureInfo.InvariantCulture, out ret))
+ // {
+ // return ret;
+ // }
+ // else
+ // {
+ // return 0;
+ // }
+ // }
+ // set
+ // {
+ // SetStyle("width", value.ToString("N2",CultureInfo.InvariantCulture) + "pt");
+ // }
+ //}
+ ///// <summary>
+ ///// Height of the Comment
+ ///// </summary>
+ //public Single Height
+ //{
+ // get
+ // {
+ // string v;
+ // GetStyle("height", out v);
+ // if (v.EndsWith("pt"))
+ // {
+ // v = v.Substring(0, v.Length - 2);
+ // }
+ // short ret;
+ // if (short.TryParse(v, System.Globalization.NumberStyles.Any, CultureInfo.InvariantCulture, out ret))
+ // {
+ // return ret;
+ // }
+ // else
+ // {
+ // return 0;
+ // }
+ // }
+ // set
+ // {
+ // SetStyle("height", value.ToString("N2", CultureInfo.InvariantCulture) + "pt");
+ // }
+ //}
+ private const string _textboxStylePath = "v:textbox/@style";
+
+ /// <summary>
+ /// Autofits the drawingobject
+ /// </summary>
+ public bool AutoFit {
+ get {
+ string value;
+ GetStyle(GetXmlNodeString(_textboxStylePath), "mso-fit-shape-to-text", out 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 { return 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 { return 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 { return GetXmlNodeString(_stylePath); }
+ set { SetXmlNodeString(_stylePath, value); }
+ }
+
+ ulong IRangeId.RangeID {
+ get {
+ return 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
index 27add95..6a908e3 100644
--- a/EPPlus/Drawing/Vml/ExcelVmlDrawingCommentCollection.cs
+++ b/EPPlus/Drawing/Vml/ExcelVmlDrawingCommentCollection.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,193 +13,179 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
-using System.Collections;
-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 RangeCollection(new List<IRangeID>());
- }
- 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(new Comparison<IRangeID>((r1, r2) => (r1.RangeID < r2.RangeID ? -1 : r1.RangeID > r2.RangeID ? 1 : 0))); //Vml drawings are not sorted. Sort to avoid missmatches.
- _drawings = new RangeCollection(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>";
+namespace OfficeOpenXml.Drawing.Vml;
- 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>";
+internal class ExcelVmlDrawingCommentCollection : ExcelVmlDrawingBaseCollection, IEnumerable {
+ internal RangeCollection _drawings;
- 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;
- }
- int _nextID = 0;
- /// <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"))
- {
- int id;
- if (int.TryParse(draw.Id.Substring(3, draw.Id.Length - 3), out id))
- {
- if (id > _nextID)
- {
- _nextID = id;
- }
- }
- }
- }
- }
- _nextID++;
- return "vml" + _nextID.ToString();
- }
- internal ExcelVmlDrawingBase this[ulong rangeID]
- {
- get
- {
- return _drawings[rangeID] as ExcelVmlDrawingComment;
- }
- }
- internal bool ContainsKey(ulong rangeID)
- {
- return _drawings.ContainsKey(rangeID);
- }
- internal int Count
- {
- get
- {
- return _drawings.Count;
- }
- }
- #region IEnumerable Members
-
- #endregion
-
- public IEnumerator GetEnumerator()
- {
- return _drawings;
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return _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")) {
+ int id;
+ if (int.TryParse(draw.Id.Substring(3, draw.Id.Length - 3), out 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 {
+ get { return _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
index bd3d1b4..755fad0 100644
--- a/EPPlus/Drawing/Vml/ExcelVmlDrawingPosition.cs
+++ b/EPPlus/Drawing/Vml/ExcelVmlDrawingPosition.cs
@@ -13,121 +13,91 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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 OfficeOpenXml.Drawing.Vml
-{
- /// <summary>
- /// The position of a VML drawing. Used for comments
- /// </summary>
- public class ExcelVmlDrawingPosition : XmlHelper
- {
- int _startPos;
- internal ExcelVmlDrawingPosition(XmlNamespaceManager ns, XmlNode topNode, int startPos) :
- base(ns, topNode)
- {
- _startPos = startPos;
- }
- /// <summary>
- /// Row. Zero based
- /// </summary>
- public int Row
- {
- get
- {
- return GetNumber(2);
- }
- set
- {
- SetNumber(2, value);
- }
- }
- /// <summary>
- /// Row offset in pixels. Zero based
- /// </summary>
- public int RowOffset
- {
- get
- {
- return GetNumber(3);
- }
- set
- {
- SetNumber(3, value);
- }
- }
- /// <summary>
- /// Column. Zero based
- /// </summary>
- public int Column
- {
- get
- {
- return GetNumber(0);
- }
- set
- {
- SetNumber(0, value);
- }
- }
- /// <summary>
- /// Column offset. Zero based
- /// </summary>
- public int ColumnOffset
- {
- get
- {
- return 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 Exception("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)
- {
- int ret;
- if (int.TryParse(numbers[_startPos + pos], out ret))
- {
- return ret;
- }
- }
- throw(new Exception("Anchor element is invalid in vmlDrawing"));
- }
+namespace OfficeOpenXml.Drawing.Vml;
+
+/// <summary>
+/// The position of a VML drawing. Used for comments
+/// </summary>
+public class ExcelVmlDrawingPosition : XmlHelper {
+ private 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) {
+ int ret;
+ if (int.TryParse(numbers[_startPos + pos], out ret)) {
+ return ret;
+ }
+ }
+ throw (new("Anchor element is invalid in vmlDrawing"));
+ }
}
diff --git a/EPPlus/EPPlusSDK.csproj b/EPPlus/EPPlusSDK.csproj
index c81fe9a..00f19ed 100644
--- a/EPPlus/EPPlusSDK.csproj
+++ b/EPPlus/EPPlusSDK.csproj
@@ -10,11 +10,11 @@
<ImplicitUsings>disable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
- <PackageReference Include="System.CodeDom" Version="5.0.0" />
- <PackageReference Include="System.Drawing.Common" Version="6.0.0" />
- <PackageReference Include="System.Security.Cryptography.Pkcs" Version="5.0.1" />
- <PackageReference Include="System.Security.Permissions" Version="5.0.0" />
- <PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />
+ <PackageReference Include="Microsoft.CSharp" Version="4.7.0"/>
+ <PackageReference Include="System.CodeDom" Version="5.0.0"/>
+ <PackageReference Include="System.Drawing.Common" Version="6.0.0"/>
+ <PackageReference Include="System.Security.Cryptography.Pkcs" Version="5.0.1"/>
+ <PackageReference Include="System.Security.Permissions" Version="5.0.0"/>
+ <PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0"/>
</ItemGroup>
</Project>
diff --git a/EPPlus/ExcelAddress.cs b/EPPlus/ExcelAddress.cs
index 70f3012..54e5460 100644
--- a/EPPlus/ExcelAddress.cs
+++ b/EPPlus/ExcelAddress.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,1414 +13,1342 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
-using System.Text;
using System.Text.RegularExpressions;
-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; }
+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>
+ public ExcelAddressBase(string address, ExcelPackage pck, ExcelAddressBase referenceAddress) {
+ SetAddress(address);
+ SetRcFromTable(pck, referenceAddress);
+ }
+
+ internal void SetRcFromTable(ExcelPackage pck, ExcelAddressBase referenceAddress) {
+ if (string.IsNullOrEmpty(_wb) && Table != null) {
+ foreach (var ws in pck.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>
- /// 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
+ }
+
+ /// <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
{
- internal protected int _fromRow=-1, _toRow, _fromCol, _toCol;
- protected internal bool _fromRowFixed, _fromColFixed, _toRowFixed, _toColFixed;
- internal protected string _wb;
- internal protected string _ws;
- internal protected string _address;
- internal protected event EventHandler AddressChange;
+ 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 enum eAddressCollition
- {
- No,
- Partly,
- Inside,
- Equal
- }
- internal enum eShiftType
- {
- Right,
- Down,
- EntireRow,
- EntireColumn
- }
- #region "Constructors"
- 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();
+ internal void ChangeAddress() {
+ if (AddressChange != null) {
+ AddressChange(this, new());
+ }
+ }
- _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();
+ private void SetWbWs(string address) {
+ int pos = 0;
- _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>
- public ExcelAddressBase(string address, ExcelPackage pck, ExcelAddressBase referenceAddress)
- {
- SetAddress(address);
- SetRCFromTable(pck, referenceAddress);
- }
+ // Get Workbook, if any
+ if (address[pos] == '[') {
+ pos = address.IndexOf("]");
+ _wb = address.Substring(1, pos - 1);
+ pos++;
+ } else {
+ _wb = "";
+ }
- internal void SetRCFromTable(ExcelPackage pck, ExcelAddressBase referenceAddress)
- {
- if (string.IsNullOrEmpty(_wb) && Table != null)
- {
- foreach (var ws in pck.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;
- }
- }
+ // 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);
+ }
+ }
- if (string.IsNullOrEmpty(Table.ColumnSpan))
- {
- _fromCol = t.Address._fromCol;
- _toCol = t.Address._toCol;
- return;
- }
- else
- {
- 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;
- }
+ // Get Address
+ pos = address.IndexOf("!", pos);
+ if (pos > -1) {
+ _address = address.Substring(pos + 1);
+ } else {
+ _address = "";
+ }
+ }
- col++;
- }
- }
- }
- }
+ 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 {
+ get { return _address; }
+ }
+
+ /// <summary>
+ /// If the address is a defined name
+ /// </summary>
+ public bool IsName {
+ get { return _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 {
+ get {
+ return _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 {
+ get { return _ws; }
+ }
+
+ protected internal List<ExcelAddress> _addresses;
+
+ internal virtual List<ExcelAddress> Addresses {
+ get { return _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);
}
- }
- }
-
- /// <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 char[] {',','!', '['}) > -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 EventArgs());
- }
- }
- 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;
- }
-
- ExcelCellAddress _start = null;
- #endregion
- /// <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 ExcelCellAddress(_fromRow, _fromCol);
- }
- return _start;
- }
- }
- ExcelCellAddress _end = null;
- /// <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 ExcelCellAddress(_toRow, _toCol);
- }
- return _end;
- }
- }
- ExcelTableAddress _table=null;
- public ExcelTableAddress Table
- {
- get
- {
- return _table;
- }
- }
-
- /// <summary>
- /// The address for the range
- /// </summary>
- public virtual string Address
- {
- get
- {
- return _address;
- }
- }
- /// <summary>
- /// If the address is a defined name
- /// </summary>
- public bool IsName
- {
- get
- {
- return _fromRow < 0;
- }
- }
- /// <summary>
- /// Returns the address text
- /// </summary>
- /// <returns></returns>
- public override string ToString()
- {
- return _address;
- }
- 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;
- }
- else
- {
- return _firstAddress;
- }
- }
- }
- internal string AddressSpaceSeparated
- {
- get
- {
- return _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
- {
- get
- {
- return _ws;
- }
- }
- internal protected List<ExcelAddress> _addresses = null;
- internal virtual List<ExcelAddress> Addresses
- {
- get
- {
- return _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;
- }
- else 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
- {
+ } 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 ExcelTableAddress();
- 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;
- }
- }
- }
- }
+ 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;
+ }
}
- #region Address manipulation methods
- 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;
- }
- else if (address._fromRow == _fromRow && address._fromCol == _fromCol &&
- address._toRow == _toRow && address._toCol == _toCol)
- {
- return eAddressCollition.Equal;
- }
- else if (address._fromRow >= _fromRow && address._toRow <= _toRow &&
- address._fromCol >= _fromCol && address._toCol <= _toCol)
- {
- return eAddressCollition.Inside;
- }
- else
- return eAddressCollition.Partly;
- }
- internal ExcelAddressBase AddRow(int row, int rows, bool setFixed=false)
- {
- if (row > _toRow)
- {
- return this;
- }
- else if (row <= _fromRow)
- {
- return new ExcelAddressBase((setFixed && _fromRowFixed ? _fromRow : _fromRow + rows), _fromCol, (setFixed && _toRowFixed ? _toRow : _toRow + rows), _toCol, _fromRowFixed, _fromColFixed, _toRowFixed, _toColFixed);
- }
- else
- {
- return new ExcelAddressBase(_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;
- }
- else if (row+rows <= _fromRow) //Before
- {
- return new ExcelAddressBase((setFixed && _fromRowFixed ? _fromRow : _fromRow - rows), _fromCol, (setFixed && _toRowFixed ? _toRow : _toRow - rows), _toCol, _fromRowFixed, _fromColFixed, _toRowFixed, _toColFixed);
- }
- else if (row <= _fromRow && row + rows > _toRow) //Inside
- {
- return null;
- }
- else //Partly
- {
- if (row <= _fromRow)
- {
- return new ExcelAddressBase(row, _fromCol, (setFixed && _toRowFixed ? _toRow : _toRow - rows), _toCol, _fromRowFixed, _fromColFixed, _toRowFixed, _toColFixed);
- }
- else
- {
- return new ExcelAddressBase(_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;
- }
- else if (col <= _fromCol)
- {
- return new ExcelAddressBase(_fromRow, (setFixed && _fromColFixed ? _fromCol : _fromCol + cols), _toRow, (setFixed && _toColFixed ? _toCol : _toCol + cols), _fromRowFixed, _fromColFixed, _toRowFixed, _toColFixed);
- }
- else
- {
- return new ExcelAddressBase(_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;
- }
- else if (col + cols <= _fromCol) //Before
- {
- return new ExcelAddressBase(_fromRow, (setFixed && _fromColFixed ? _fromCol : _fromCol - cols), _toRow, (setFixed && _toColFixed ? _toCol :_toCol - cols), _fromRowFixed, _fromColFixed, _toRowFixed, _toColFixed);
- }
- else if (col <= _fromCol && col + cols > _toCol) //Inside
- {
- return null;
- }
- else //Partly
- {
- if (col <= _fromCol)
- {
- return new ExcelAddressBase(_fromRow, col, _toRow, (setFixed && _toColFixed ? _toCol : _toCol - cols), _fromRowFixed, _fromColFixed, _toRowFixed, _toColFixed);
- }
- else
- {
- return new ExcelAddressBase(_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;
- }
+ internal eAddressCollition Collide(ExcelAddressBase address) {
+ if (address.WorkSheet != WorkSheet && address.WorkSheet != null) {
+ return eAddressCollition.No;
+ }
- 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)
- {
+ 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;
+ }
- }
- else
- {
- }
- }
- return null;
+ 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) {
+ double d;
+ if (address == "#REF!") {
+ return AddressType.Invalid;
+ }
+ if (double.TryParse(
+ address,
+ NumberStyles.Any,
+ CultureInfo.InvariantCulture,
+ out d)) //A double, no valid address
+ {
+ return AddressType.Invalid;
+ }
+ if (IsFormula(address)) {
+ return AddressType.Formula;
+ }
+ string wb,
+ ws,
+ intAddress;
+ if (SplitAddress(address, out wb, out ws, out 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;
+
+ //if(string.IsNullOrEmpty(wb));
+ //ExcelAddress a = new ExcelAddress(Address);
+ //if (Address.IndexOf('!') > 0)
+ //{
+ // string[] split = Address.Split('!');
+ // if (split.Length == 2)
+ // {
+ // ws = split[0];
+ // Address = split[1];
+ // }
+ // else if (split.Length == 3 && split[1] == "#REF" && split[2] == "")
+ // {
+ // ws = split[0];
+ // Address = "#REF!";
+ // if (ws.StartsWith("[") && ws.IndexOf("]") > 1)
+ // {
+ // return AddressType.ExternalAddress;
+ // }
+ // else
+ // {
+ // return AddressType.InternalAddress;
+ // }
+ // }
+ // else
+ // {
+ // return AddressType.Invalid;
+ // }
+ //}
+ //int _fromRow, column, _toRow, _toCol;
+ //if (ExcelAddressBase.GetRowColFromAddress(Address, out _fromRow, out column, out _toRow, out _toCol))
+ //{
+ // if (_fromRow > 0 && column > 0 && _toRow <= ExcelPackage.MaxRows && _toCol <= ExcelPackage.MaxColumns)
+ // {
+ // if (ws.StartsWith("[") && ws.IndexOf("]") > 1)
+ // {
+ // return AddressType.ExternalAddress;
+ // }
+ // else
+ // {
+ // return AddressType.InternalAddress;
+ // }
+ // }
+ // else
+ // {
+ // return AddressType.Invalid;
+ // }
+ //}
+ //else
+ //{
+ // if(IsValidName(Address))
+ // {
+ // if (ws.StartsWith("[") && ws.IndexOf("]") > 1)
+ // {
+ // return AddressType.ExternalName;
+ // }
+ // else
+ // {
+ // return AddressType.InternalName;
+ // }
+ // }
+ // else
+ // {
+ // return AddressType.Invalid;
+ // }
+ //}
+ }
+
+ private static bool IsAddress(string intAddress) {
+ if (string.IsNullOrEmpty(intAddress)) {
+ return false;
+ }
+ var cells = intAddress.Split(':');
+ int fromRow,
+ toRow,
+ fromCol,
+ toCol;
+
+ if (!GetRowCol(cells[0], out fromRow, out 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 += "'";
}
- #endregion
- 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 List<ExcelAddress>();
- _addresses.Add(new ExcelAddress(_ws, address));
- }
+ } 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;
}
- internal enum AddressType
- {
- Invalid,
- InternalAddress,
- ExternalAddress,
- InternalName,
- ExternalName,
- Formula
- }
-
- internal static AddressType IsValid(string Address)
- {
- double d;
- if (Address == "#REF!")
- {
- return AddressType.Invalid;
- }
- else if(double.TryParse(Address, NumberStyles.Any, CultureInfo.InvariantCulture, out d)) //A double, no valid address
- {
- return AddressType.Invalid;
- }
- else if (IsFormula(Address))
- {
- return AddressType.Formula;
- }
- else
- {
- string wb, ws, intAddress;
- if(SplitAddress(Address, out wb, out ws, out intAddress))
- {
- if(intAddress.Contains("[")) //Table reference
- {
- return string.IsNullOrEmpty(wb) ? AddressType.InternalAddress : AddressType.ExternalAddress;
- }
- else if(intAddress.Contains(","))
- {
- intAddress=intAddress.Substring(0, intAddress.IndexOf(','));
- }
- if(IsAddress(intAddress))
- {
- return string.IsNullOrEmpty(wb) ? AddressType.InternalAddress : AddressType.ExternalAddress;
- }
- else
- {
- return string.IsNullOrEmpty(wb) ? AddressType.InternalName : AddressType.ExternalName;
- }
- }
- else
- {
- return AddressType.Invalid;
- }
-
- //if(string.IsNullOrEmpty(wb));
-
- }
- //ExcelAddress a = new ExcelAddress(Address);
- //if (Address.IndexOf('!') > 0)
- //{
- // string[] split = Address.Split('!');
- // if (split.Length == 2)
- // {
- // ws = split[0];
- // Address = split[1];
- // }
- // else if (split.Length == 3 && split[1] == "#REF" && split[2] == "")
- // {
- // ws = split[0];
- // Address = "#REF!";
- // if (ws.StartsWith("[") && ws.IndexOf("]") > 1)
- // {
- // return AddressType.ExternalAddress;
- // }
- // else
- // {
- // return AddressType.InternalAddress;
- // }
- // }
- // else
- // {
- // return AddressType.Invalid;
- // }
- //}
- //int _fromRow, column, _toRow, _toCol;
- //if (ExcelAddressBase.GetRowColFromAddress(Address, out _fromRow, out column, out _toRow, out _toCol))
- //{
- // if (_fromRow > 0 && column > 0 && _toRow <= ExcelPackage.MaxRows && _toCol <= ExcelPackage.MaxColumns)
- // {
- // if (ws.StartsWith("[") && ws.IndexOf("]") > 1)
- // {
- // return AddressType.ExternalAddress;
- // }
- // else
- // {
- // return AddressType.InternalAddress;
- // }
- // }
- // else
- // {
- // return AddressType.Invalid;
- // }
- //}
- //else
- //{
- // if(IsValidName(Address))
- // {
- // if (ws.StartsWith("[") && ws.IndexOf("]") > 1)
- // {
- // return AddressType.ExternalName;
- // }
- // else
- // {
- // return AddressType.InternalName;
- // }
- // }
- // else
- // {
- // return AddressType.Invalid;
- // }
- //}
-
- }
-
- private static bool IsAddress(string intAddress)
- {
- if(string.IsNullOrEmpty(intAddress)) return false;
- var cells = intAddress.Split(':');
- int fromRow,toRow, fromCol, toCol;
-
- if(!GetRowCol(cells[0], out fromRow, out 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;
- }
- else
- {
- 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;
- }
- else
- {
- 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;
+ if (address[i] == '[' && !isText) {
+ if (i
+ > 0) //Table reference return full address;
+ {
+ intAddress = address;
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 char[] { '(', ')', '+', '-', '*', '/', '.', '=', '^', '&', '%', '\"' }) > -1)
- {
- return true;
- }
- }
- }
+ }
+ brackPos = i;
+ } else if (address[i] == ']' && !isText) {
+ if (brackPos > -1) {
+ wb = text;
+ text = "";
+ } else {
return false;
+ }
+ } else {
+ text += address[i];
}
-
- private static bool IsValidName(string address)
- {
- if (Regex.IsMatch(address, "[^0-9./*-+,½!\"@#£%&/{}()\\[\\]=?`^~':;<>|][^/*-+,½!\"@#£%&/{}()\\[\\]=?`^~':;<>|]*"))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
-
- public int Rows
- {
- get
- {
- return _toRow - _fromRow+1;
- }
- }
- public int Columns
- {
- get
- {
- return _toCol - _fromCol + 1;
- }
- }
-
- internal bool IsMultiCell()
- {
- return (_fromRow < _fromCol || _fromCol < _toCol);
- }
- internal static String GetWorkbookPart(string address)
- {
- var ix = 0;
- 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)
- {
- int ix=0;
- return GetWorksheetPart(address, defaultWorkSheet, ref ix);
- }
- 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);
- }
- else
- {
- var ixEnd = address.IndexOf('!',ix);
- if(ixEnd>ix)
- {
- return address.Substring(ix, ixEnd-ix);
- }
- else
- {
- return defaultWorkSheet;
- }
- }
- }
- else
- {
- return defaultWorkSheet;
- }
- }
- internal static string GetAddressPart(string address)
- {
- var ix=0;
- GetWorksheetPart(address, "", ref ix);
- if(ix<address.Length)
- {
- if (address[ix] == '!')
- {
- return address.Substring(ix + 1);
- }
- else
- {
- return "";
- }
- }
- else
- {
- return "";
- }
-
- }
- 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("''");
- var prevStrIx = ix;
- while(strIx > -1)
- {
- prevStrIx = strIx;
- 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()
- : base()
- {
+ 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;
}
-
- 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, ExcelPackage package, ExcelAddressBase referenceAddress) :
- base(Address, package, 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);
- base.ChangeAddress();
- }
- }
+ }
}
- public class ExcelFormulaAddress : ExcelAddressBase
- {
- bool _fromRowFixed, _toRowFixed, _fromColFixed, _toColFixed;
- internal ExcelFormulaAddress()
- : base()
- {
- }
+ return false;
+ }
- public ExcelFormulaAddress(int fromRow, int fromCol, int toRow, int toColumn)
- : base(fromRow, fromCol, toRow, toColumn)
- {
- _ws = "";
- }
- public ExcelFormulaAddress(string address)
- : base(address)
- {
- SetFixed();
- }
-
- internal ExcelFormulaAddress(string ws, string address)
- : base(address)
- {
- if (string.IsNullOrEmpty(_ws)) _ws = ws;
- SetFixed();
- }
- internal ExcelFormulaAddress(string ws, string address, bool isName)
- : base(address, isName)
- {
- if (string.IsNullOrEmpty(_ws)) _ws = ws;
- if(!isName)
- 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;
- }
- else
- {
- 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);
- base.ChangeAddress();
- SetFixed();
- }
- }
- internal new List<ExcelFormulaAddress> _addresses;
- public new List<ExcelFormulaAddress> Addresses
- {
- get
- {
- if (_addresses == null)
- {
- _addresses = new List<ExcelFormulaAddress>();
- }
- 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;
- }
+ private static bool IsValidName(string address) {
+ if (Regex.IsMatch(
+ address,
+ "[^0-9./*-+,½!\"@#£%&/{}()\\[\\]=?`^~':;<>|][^/*-+,½!\"@#£%&/{}()\\[\\]=?`^~':;<>|]*")) {
+ return true;
}
+ return false;
+ }
+
+ public int Rows {
+ get { return _toRow - _fromRow + 1; }
+ }
+
+ public int Columns {
+ get { return _toCol - _fromCol + 1; }
+ }
+
+ internal bool IsMultiCell() {
+ return (_fromRow < _fromCol || _fromCol < _toCol);
+ }
+
+ internal static String GetWorkbookPart(string address) {
+ var ix = 0;
+ 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) {
+ int ix = 0;
+ return GetWorksheetPart(address, defaultWorkSheet, ref ix);
+ }
+
+ 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 string GetAddressPart(string address) {
+ var ix = 0;
+ GetWorksheetPart(address, "", ref ix);
+ if (ix < address.Length) {
+ if (address[ix] == '!') {
+ return address.Substring(ix + 1);
+ }
+ return "";
+ }
+ return "";
+ }
+
+ 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("''");
+ var prevStrIx = ix;
+ while (strIx > -1) {
+ prevStrIx = strIx;
+ 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, ExcelPackage package, ExcelAddressBase referenceAddress)
+ : base(address, package, 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;
+
+ internal ExcelFormulaAddress() {}
+
+ public ExcelFormulaAddress(int fromRow, int fromCol, int toRow, int toColumn)
+ : base(fromRow, fromCol, toRow, toColumn) {
+ _ws = "";
+ }
+
+ public ExcelFormulaAddress(string address)
+ : base(address) {
+ SetFixed();
+ }
+
+ internal ExcelFormulaAddress(string ws, string address)
+ : base(address) {
+ if (string.IsNullOrEmpty(_ws)) {
+ _ws = ws;
+ }
+ SetFixed();
+ }
+
+ internal ExcelFormulaAddress(string ws, string address, bool isName)
+ : base(address, isName) {
+ if (string.IsNullOrEmpty(_ws)) {
+ _ws = ws;
+ }
+ if (!isName) {
+ 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
index 99433ef..b765a73 100644
--- a/EPPlus/ExcelCellAddress.cs
+++ b/EPPlus/ExcelCellAddress.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,143 +13,121 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or 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;
-using System.Collections.Generic;
-using System.Text;
-namespace OfficeOpenXml
-{
- /// <summary>
- /// A single cell address
- /// </summary>
- public class ExcelCellAddress
- {
- public ExcelCellAddress()
- : this(1, 1)
- {
+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)
- {
- this.Row = row;
- this.Column = column;
- }
- /// <summary>
- /// Initializes a new instance of the ExcelCellAddress class.
- /// </summary>
- ///<param name="address">The address</param>
- public ExcelCellAddress(string address)
- {
- this.Address = address;
- }
- /// <summary>
- /// Row
- /// </summary>
- public int Row
- {
- get
- {
- return this._row;
- }
- private set
- {
- if (value <= 0)
- {
- throw new ArgumentOutOfRangeException("value", "Row cannot be less than 1.");
- }
- this._row = value;
- if(_column>0)
- _address = ExcelCellBase.GetAddress(_row, _column);
- else
- _address = "#REF!";
- }
- }
- /// <summary>
- /// Column
- /// </summary>
- public int Column
- {
- get
- {
- return this._column;
- }
- private set
- {
- if (value <= 0)
- {
- throw new ArgumentOutOfRangeException("value", "Column cannot be less than 1.");
- }
- this._column = value;
- if (_row > 0)
- _address = ExcelCellBase.GetAddress(_row, _column);
- else
- _address = "#REF!";
- }
- }
- /// <summary>
- /// Celladdress
- /// </summary>
- public string Address
- {
- get
- {
- return _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
- {
- get
- {
- return _row <= 0;
- }
- }
+ private int _row;
+ private int _column;
+ private string _address;
- /// <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);
- }
+ /// <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
index e7a8f25..36e1450 100644
--- a/EPPlus/ExcelCellBase.cs
+++ b/EPPlus/ExcelCellBase.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,1457 +13,1368 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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 System.Text;
-using OfficeOpenXml.Style;
-using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-using System.Linq;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
using OfficeOpenXml.FormulaParsing;
-namespace OfficeOpenXml
-{
- /// <summary>
- /// Base class containing cell address manipulating methods.
- /// </summary>
- public abstract class ExcelCellBase
- {
- #region "public functions"
- /// <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);
- }
- #endregion
- #region "Formula Functions"
- private delegate string dlgTransl(string part, int row, int col, int rowIncr, int colIncr);
- #region R1C1 Functions"
- /// <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);
- }
+using OfficeOpenXml.FormulaParsing.Excel.Functions;
+using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
- /// <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);
- }
+namespace OfficeOpenXml;
- /// <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>
+/// 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>
- /// 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>
+ /// 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);
+ }
- /// <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, dlgTransl 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 == true && prevTQ != c)
- {
- ret += c;
- continue;
- }
+ private delegate string AddressTranslator(
+ string part,
+ int row,
+ int col,
+ int rowIncr,
+ int colIncr);
- if (isText == false && part != "" && prevTQ==c)
- {
- ret += addressTranslator(part, row, col, rowIncr, colIncr);
- part = "";
- prevTQ = (char)0;
- }
- 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;
- }
+ /// <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);
+ }
- private static string Translate_V1(string value, dlgTransl 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 == true && prevTQ != c)
- {
- ret += c;
- continue;
- }
+ /// <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);
+ }
- if (isText == false && part != "" && prevTQ == c)
- {
- ret += addressTranslator(part, row, col, rowIncr, colIncr);
- part = "";
- prevTQ = (char)0;
- }
- 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>
+ /// 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>
- /// 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)
- {
- int addrRow, addrCol;
- string Ret = "R";
- if (GetRowCol(part, out addrRow, out 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);
- }
+ /// <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);
+ }
- if (part.StartsWith("$"))
- {
- return Ret + "C" + addrCol;
- }
- else if (addrCol - col != 0)
- {
- return Ret + "C" + string.Format("[{0}]", addrCol - col);
- }
- else
- {
- return Ret + "C";
- }
- }
- else
- {
- return part;
- }
- }
-
- private static string ToR1C1_V1(string part, int row, int col, int rowIncr, int colIncr)
- {
- int addrRow, addrCol;
-
- // 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 addrRow, out 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;
- }
- else if (addrCol - col != 0)
- {
- return Ret + "C" + string.Format("[{0}]", addrCol - col);
- }
- else
- {
- return Ret + "C";
- }
- }
- else
- {
- 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 char[] { ':' }, 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)
- {
- int addrRow, addrCol;
- bool fixedRow, fixedCol;
-
- string result = "";
- if (GetRowCol_V1(part, out addrRow, out addrCol, false, out fixedRow, out 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;
- }
- else
- {
- 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, absoluteCol;
- if (cStart == -1)
- {
- int RNum = GetRC(part, row, out absoluteRow);
- if (RNum > int.MinValue)
- {
- return GetAddress(RNum, absoluteRow, col, false);
- }
- else
- {
- 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 absoluteCol);
- if (RNum > int.MinValue && CNum > int.MinValue)
- {
- return GetAddress(RNum, absoluteRow, CNum, absoluteCol);
- }
- else
- {
- 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
- int result;
- return (int.TryParse(value.Substring(0, length), out 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 char[] { ':' }, 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;
- }
-
- private static string RangeCellToA1_V1(string part, int row, int col, int rowIncr, int colIncr)
- {
- int addrRow, addrCol;
- bool fixedRow, fixedCol;
-
- string result = "";
- if (GetRowCol_V1(part, out addrRow, out addrCol, false, out fixedRow, out 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;
- }
- else
- {
- return part;
- }
- }
-
- /// <summary>
- /// Adds or subtracts a row or column to an address
- /// </summary>
- /// <param name="Address"></param>
- /// <param name="row"></param>
- /// <param name="col"></param>
- /// <param name="rowIncr"></param>
- /// <param name="colIncr"></param>
- /// <returns></returns>
- private static string AddToRowColumnTranslator(string Address, int row, int col, int rowIncr, int colIncr)
- {
- int fromRow, fromCol;
- if (Address == "#REF!")
- {
- return Address;
- }
- if (GetRowCol(Address, out fromRow, out fromCol, false))
- {
- if (fromRow == 0 || fromCol == 0)
- {
- return Address;
- }
- if (rowIncr != 0 && row != 0 && fromRow >= row && Address.IndexOf('$', 1) == -1)
- {
- if (fromRow < row - rowIncr)
- {
- return "#REF!";
- }
-
- fromRow = fromRow + rowIncr;
- }
-
- if (colIncr != 0 && col != 0 && fromCol >= col && Address.StartsWith("$") == false)
- {
- if (fromCol < col - colIncr)
- {
- return "#REF!";
- }
-
- fromCol = fromCol + colIncr;
- }
-
- Address = GetAddress(fromRow, Address.IndexOf('$', 1) > -1, fromCol, Address.StartsWith("$"));
- }
- return Address;
- }
-
- /// <summary>
- /// Returns with brackets if the value is negative
- /// </summary>
- /// <param name="v">The value</param>
- /// <returns></returns>
- private static string GetRCFmt(int v)
- {
- return (v < 0 ? string.Format("[{0}]", v) : v > 0 ? v.ToString() : "");
- }
- /// <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);
- }
- else
- {
- return int.MinValue;
- }
- }
- else
- {
- // Absolute address
- fixedAddr = true;
- if (int.TryParse(value, out num))
- {
- return num;
- }
- else
- {
- return int.MinValue;
- }
- }
- }
-
- private static int GetRC_V1(string value, int OffsetValue, out bool fixedAddr)
- {
- if ((value == "") || (value == "R") || (value == "C"))
- {
- // Relative address with no offset
- fixedAddr = false;
- return OffsetValue;
- }
- int num;
- if (value[1] == '[' && value[value.Length - 1] == ']') //Offset?
- {
- // Relative address
- fixedAddr = false;
- if (int.TryParse(value.Substring(2, value.Length - 3), out num))
- {
- return (OffsetValue + num);
- }
- else
- {
- return int.MinValue;
- }
- }
- else
- {
- // Absolute address
- fixedAddr = true;
- if (int.TryParse(value.Substring(1, value.Length - 1), out num))
- {
- return num;
- }
- else
- {
- return int.MinValue;
- }
- }
- }
- #endregion
- #region "Address Functions"
- #region GetColumnLetter
- /// <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;
- }
- #endregion
-
- 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 += ((int)c) - 64;
- colLength++;
- }
- else if (c >= '0' && c <= '9')
- {
- row *= 10;
- row += ((int)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 Exception(string.Format("Invalid Address format {0}", address)));
- }
- else
- {
- 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 += ((int)c) - 64;
- colLength++;
- }
- else if (c >= '0' && c <= '9')
- {
- // Row portion of address
- if (isFixed)
- {
- fixedRow = true;
- isFixed = false;
- }
-
- row *= 10;
- row += ((int)c) - 48;
- colPart = false;
- }
- else
- {
- row = 0;
- col = 0;
- if (throwException)
- {
- throw (new Exception(string.Format("Invalid Address format {0}", address)));
- }
- else
- {
- 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 += (((int)sCol[i]) - 64) * (int)(Math.Pow(26, len - i));
- }
- return col;
- }
- #region GetAddress
- /// <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.ToString();
- }
- /// <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.ToString());
- }
- else
- {
- return (GetColumnLetter(Column) + Row.ToString());
- }
- }
- /// <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);
- }
- else
- {
- if (FromRow == 1 && ToRow == ExcelPackage.MaxRows)
- {
- var absChar = Absolute ? "$" : "";
- return absChar + GetColumnLetter(FromColumn) + ":" + absChar + GetColumnLetter(ToColumn);
- }
- else if(FromColumn==1 && ToColumn==ExcelPackage.MaxColumns)
- {
- var absChar = Absolute ? "$" : "";
- return absChar + FromRow.ToString() + ":" + absChar + ToRow.ToString();
- }
- else
- {
- 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);
- }
- else
- {
- if (FromRow == 1 && ToRow == ExcelPackage.MaxRows)
- {
- return GetColumnLetter(FromColumn, FixedFromColumn) + ":" + GetColumnLetter(ToColumn, FixedToColumn);
- }
- else if (FromColumn == 1 && ToColumn == ExcelPackage.MaxColumns)
- {
- return (FixedFromRow ? "$":"") + FromRow.ToString() + ":" + (FixedToRow ? "$":"") + ToRow.ToString();
- }
- else
- {
- 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, ExcelAddress.GetColumnLetter(a._fromCol), a._fromRow, ExcelAddress.GetColumnLetter(a._toCol), a._toRow);
- }
- else
- {
- address=GetFullAddress(worksheetName, address, true);
- }
- }
- }
- return address;
- }
- #endregion
- #region IsValidCellAddress
- 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);
- }
- else 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;
-
- }
- else if (r1 == "" && r2 == "" && c1 != "" && c2 != "") //Full Column
- {
- var c2n=GetColumn(c2);
- return (GetColumn(c1) <= c2n && c2n <= ExcelPackage.MaxColumns);
- }
- else if (r1 != "" && r2 != "" && c1 == "" && c2 == "")
- {
- var iR2 = int.Parse(r2);
-
- return int.Parse(r1) <= iR2 && iR2 <= ExcelPackage.MaxRows;
- }
- else
- {
- 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
- {
- int row, col;
- if (GetRowColFromAddress(cellAddress, out row, out col))
- {
- if (row > 0 && col > 0 && row <= ExcelPackage.MaxRows && col <= ExcelPackage.MaxColumns)
- result = true;
- else
- result = false;
- }
- }
- catch { }
- return result;
- }
- #endregion
- #region UpdateFormulaReferences
- /// <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;
- }
- }
-
- #endregion
- #endregion
- #endregion
+ /// <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 = (char)0;
+ }
+ 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 = (char)0;
+ }
+ 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) {
+ int addrRow,
+ addrCol;
+ string ret = "R";
+ if (GetRowCol(part, out addrRow, out 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) {
+ int addrRow,
+ addrCol;
+
+ // 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 addrRow, out 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) {
+ int addrRow,
+ addrCol;
+ bool fixedRow,
+ fixedCol;
+
+ string result = "";
+ if (GetRowCol_V1(part, out addrRow, out addrCol, false, out fixedRow, out 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,
+ absoluteCol;
+ 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 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
+ int result;
+ return (int.TryParse(value.Substring(0, length), out 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;
+ }
+
+ private static string RangeCellToA1_V1(string part, int row, int col, int rowIncr, int colIncr) {
+ int addrRow,
+ addrCol;
+ bool fixedRow,
+ fixedCol;
+
+ string result = "";
+ if (GetRowCol_V1(part, out addrRow, out addrCol, false, out fixedRow, out 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>
+ /// Adds or subtracts a row or column to an address
+ /// </summary>
+ /// <param name="address"></param>
+ /// <param name="row"></param>
+ /// <param name="col"></param>
+ /// <param name="rowIncr"></param>
+ /// <param name="colIncr"></param>
+ /// <returns></returns>
+ private static string AddToRowColumnTranslator(
+ string address,
+ int row,
+ int col,
+ int rowIncr,
+ int colIncr) {
+ int fromRow,
+ fromCol;
+ if (address == "#REF!") {
+ return address;
+ }
+ if (GetRowCol(address, out fromRow, out fromCol, false)) {
+ if (fromRow == 0 || fromCol == 0) {
+ return address;
+ }
+ if (rowIncr != 0 && row != 0 && fromRow >= row && address.IndexOf('$', 1) == -1) {
+ if (fromRow < row - rowIncr) {
+ return "#REF!";
+ }
+
+ fromRow = fromRow + rowIncr;
+ }
+
+ if (colIncr != 0 && col != 0 && fromCol >= col && address.StartsWith("$") == false) {
+ if (fromCol < col - colIncr) {
+ return "#REF!";
+ }
+
+ fromCol = fromCol + colIncr;
+ }
+
+ address = GetAddress(fromRow, address.IndexOf('$', 1) > -1, fromCol, address.StartsWith("$"));
+ }
+ return address;
+ }
+
+ /// <summary>
+ /// Returns with brackets if the value is negative
+ /// </summary>
+ /// <param name="v">The value</param>
+ /// <returns></returns>
+ private static string GetRcFmt(int v) {
+ return (v < 0
+ ? string.Format("[{0}]", v)
+ : v > 0
+ ? v.ToString()
+ : "");
+ }
+
+ /// <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;
+ }
+
+ private static int GetRC_V1(string value, int offsetValue, out bool fixedAddr) {
+ if ((value == "") || (value == "R") || (value == "C")) {
+ // Relative address with no offset
+ fixedAddr = false;
+ return offsetValue;
+ }
+ int num;
+ if (value[1] == '['
+ && value[value.Length - 1]
+ == ']') //Offset?
+ {
+ // Relative address
+ fixedAddr = false;
+ if (int.TryParse(value.Substring(2, value.Length - 3), out num)) {
+ return (offsetValue + num);
+ }
+ return int.MinValue;
+ }
+ // Absolute address
+ fixedAddr = true;
+ if (int.TryParse(value.Substring(1, value.Length - 1), 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 {
+ int row,
+ col;
+ if (GetRowColFromAddress(cellAddress, out row, out 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
index 56ea994..bb26958 100644
--- a/EPPlus/ExcelColumn.cs
+++ b/EPPlus/ExcelColumn.cs
@@ -13,299 +13,242 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
-{
- /// <summary>
- /// Represents one or more columns within the worksheet
- /// </summary>
- public class ExcelColumn : IRangeID
- {
- private ExcelWorksheet _worksheet;
- private XmlElement _colElement = null;
- #region ExcelColumn Constructor
- /// <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;
- }
- #endregion
- internal int _columnMin;
- /// <summary>
- /// Sets the first column the definition refers to.
- /// </summary>
- public int ColumnMin
- {
- get { return _columnMin; }
- //set { _columnMin=value; }
- }
+namespace OfficeOpenXml;
- internal int _columnMax;
- /// <summary>
- /// Sets the last column the definition refers to.
- /// </summary>
- public int ColumnMax
- {
- get { return _columnMax; }
- set
- {
- if (value < _columnMin && value > ExcelPackage.MaxColumns)
- {
- throw new Exception("ColumnMax out of range");
- }
+/// <summary>
+/// Represents one or more columns within the worksheet
+/// </summary>
+public class ExcelColumn : IRangeId {
+ private ExcelWorksheet _worksheet;
+ private XmlElement _colElement = null;
- 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 Exception(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
- {
- get
- {
- return ExcelColumn.GetColumnID(_worksheet.SheetID, ColumnMin);
- }
- }
- #region ExcelColumn Hidden
- /// <summary>
- /// Allows the column to be hidden in the worksheet
- /// </summary>
- internal bool _hidden=false;
- public bool Hidden
- {
- get
- {
- return _hidden;
- }
- set
- {
- _hidden = value;
- }
- }
- #endregion
+ /// <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;
+ }
- #region ExcelColumn Width
- internal double VisualWidth
- {
- get
- {
- if (_hidden || (Collapsed && OutlineLevel>0))
- {
- return 0;
- }
- else
- {
- return _width;
- }
- }
- }
- internal double _width;
- /// <summary>
- /// Sets the width of the column in the worksheet
- /// </summary>
- public double Width
- {
- get
- {
- return _width;
- }
- set
- {
- _width = value;
+ internal int _columnMin;
- 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; }
- #endregion
+ /// <summary>
+ /// Sets the first column the definition refers to.
+ /// </summary>
+ public int ColumnMin => _columnMin;
- #region ExcelColumn Style
- /// <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
- {
- return _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
- {
- return _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
- {
- return _worksheet.MergedCells[ColumnMin, 0] != null;
- }
- set
- {
- _worksheet.MergedCells.Add(new ExcelAddressBase(1, ColumnMin, ExcelPackage.MaxRows, ColumnMax), true);
- }
- }
- #endregion
+ //set { _columnMin=value; }
+ internal int _columnMax;
- /// <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);
- }
+ /// <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");
+ }
- #region IRangeID Members
-
- ulong IRangeID.RangeID
- {
- get
- {
- return ColumnID;
- }
- set
- {
- int prevColMin = _columnMin;
- _columnMin = ((int)(value >> 15) & 0x3FF);
- _columnMax += prevColMin - ColumnMin;
- //Todo:More Validation
- if (_columnMax > ExcelPackage.MaxColumns) _columnMax = ExcelPackage.MaxColumns;
- }
+ 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));
}
-
- #endregion
-
- /// <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;
- }
+ }
+ _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
index e25e7d8..acd42ad 100644
--- a/EPPlus/ExcelComment.cs
+++ b/EPPlus/ExcelComment.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,139 +13,134 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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 Initial Release
* Jan Källman License changed GPL-->LGPL 2011-12-27
*******************************************************************************/
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.Style;
+
using System.Xml;
-using OfficeOpenXml.Drawing;
using OfficeOpenXml.Drawing.Vml;
+using OfficeOpenXml.Style;
-namespace OfficeOpenXml
-{
- /// <summary>
- /// An Excel Cell Comment
- /// </summary>
- public class ExcelComment : ExcelVmlDrawingComment
- {
- internal XmlHelper _commentHelper;
- private 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(ExcelAddress.GetCellID(cell.Worksheet.SheetID, cell.Start.Row, cell.Start.Column)))
- {
- cell.Worksheet._vmlDrawings.Add(cell);
- }
+namespace OfficeOpenXml;
- TopNode = cell.Worksheet.VmlDrawingsComments[ExcelCellBase.GetCellID(cell.Worksheet.SheetID, cell.Start.Row, cell.Start.Column)].TopNode;
- RichText = new ExcelRichTextCollection(ns,textElem);
- var tNode = textElem.SelectSingleNode("d:t", ns);
- if (tNode != null)
- {
- _text = tNode.InnerText;
- }
- }
- const string AUTHORS_PATH = "d:comments/d:authors";
- const string AUTHOR_PATH = "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}]", AUTHOR_PATH, authorRef+1), _commentHelper.NameSpaceManager).InnerText;
- }
- set
- {
- int authorRef = GetAuthor(value);
- _commentHelper.SetXmlNodeString("@authorId", authorRef.ToString());
- }
- }
- private int GetAuthor(string value)
- {
- int authorRef = 0;
- bool found = false;
- foreach (XmlElement node in _commentHelper.TopNode.OwnerDocument.SelectNodes(AUTHOR_PATH, _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(AUTHORS_PATH, _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;
- }
- set
- {
- RichText.Text = value;
- }
- }
- /// <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>
- public ExcelRichTextCollection RichText
- {
- get;
- set;
- }
+/// <summary>
+/// An Excel Cell Comment
+/// </summary>
+public class ExcelComment : ExcelVmlDrawingComment {
+ internal XmlHelper _commentHelper;
+ private 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;
+ }
+ set {
+ int authorRef = GetAuthor(value);
+ _commentHelper.SetXmlNodeString("@authorId", authorRef.ToString());
+ }
+ }
+
+ 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;
+ }
+ set => RichText.Text = value;
+ }
+
+ /// <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>
+ public ExcelRichTextCollection RichText { get; set; }
}
diff --git a/EPPlus/ExcelCommentCollection.cs b/EPPlus/ExcelCommentCollection.cs
index cf0a540..b4a60af 100644
--- a/EPPlus/ExcelCommentCollection.cs
+++ b/EPPlus/ExcelCommentCollection.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,223 +13,204 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Text;
-using System.Xml;
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 = new XmlDocument();
- 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 XmlDocument();
- 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 ExcelRangeBase(Worksheet, node.GetAttribute("ref")));
- lst.Add(comment);
- }
- _comments = new RangeCollection(lst);
- }
- /// <summary>
- /// Access to the comment xml document
- /// </summary>
- public XmlDocument CommentXml { get; set; }
- internal Uri Uri { get; set; }
- internal string RelId { get; set; }
- internal XmlNamespaceManager NameSpaceManager { get; set; }
- internal Packaging.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
- {
- get
- {
- return _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;
- }
- else
- {
- return null;
- }
- }
- }
- /// <summary>
- /// Adds a comment to the top left cell of the range
- /// </summary>
- /// <param name="cell">The cell</param>
- /// <param name="Text">The comment text</param>
- /// <param name="author">Author</param>
- /// <returns>The comment</returns>
- public ExcelComment Add(ExcelRangeBase cell, string Text, string author)
- {
- var elem = CommentXml.CreateElement("comment", ExcelPackage.schemaMain);
- int ix=_comments.IndexOf(ExcelAddress.GetCellID(Worksheet.SheetID, cell._fromRow, cell._fromCol));
- //Make sure the nodes come on order.
- if (ix < 0 && (~ix < _comments.Count))
- {
- ix = ~ix;
- var preComment = _comments[ix] as ExcelComment;
- preComment._commentHelper.TopNode.ParentNode.InsertBefore(elem, preComment._commentHelper.TopNode);
- }
- else
- {
- CommentXml.SelectSingleNode("d:comments/d:commentList", NameSpaceManager).AppendChild(elem);
- }
- elem.SetAttribute("ref", cell.Start.Address);
- ExcelComment comment = new ExcelComment(NameSpaceManager, elem , cell);
- comment.RichText.Add(Text);
- if(author!="")
- {
- comment.Author=author;
- }
- _comments.Add(comment);
- //Check if a value exists otherwise add one so it is saved when the cells collection is iterated
- if (!Worksheet._values.Exists(cell._fromRow, cell._fromCol))
- {
- Worksheet._values.SetValue(cell._fromRow, cell._fromCol, null);
- }
- return comment;
- }
- /// <summary>
- /// Removes the comment
- /// </summary>
- /// <param name="comment">The comment to remove</param>
- public void Remove(ExcelComment comment)
- {
- ulong id = ExcelAddress.GetCellID(Worksheet.SheetID, comment.Range._fromRow, comment.Range._fromCol);
- int ix=_comments.IndexOf(id);
- if (ix >= 0 && comment == _comments[ix])
- {
- comment.TopNode.ParentNode.RemoveChild(comment.TopNode); //Remove VML
- comment._commentHelper.TopNode.ParentNode.RemoveChild(comment._commentHelper.TopNode); //Remove Comment
- Worksheet.VmlDrawingsComments._drawings.Delete(id);
- _comments.Delete(id);
- }
- else
- {
- throw (new ArgumentException("Comment does not exist in the worksheet"));
- }
- }
+namespace OfficeOpenXml;
- void IDisposable.Dispose() { }
-
- /// <summary>
- /// Removes the comment at the specified position
- /// </summary>
- /// <param name="Index">The index</param>
- public void RemoveAt(int Index)
- {
- Remove(this[Index]);
- }
- #region IEnumerable Members
+/// <summary>
+/// Collection of Excelcomment objects
+/// </summary>
+public class ExcelCommentCollection : IEnumerable, IDisposable {
+ internal RangeCollection _comments;
- IEnumerator IEnumerable.GetEnumerator()
- {
- return _comments;
- }
- #endregion
+ internal ExcelCommentCollection(ExcelPackage pck, ExcelWorksheet ws, XmlNamespaceManager ns) {
+ CommentXml = new();
+ CommentXml.PreserveWhitespace = false;
+ NameSpaceManager = ns;
+ Worksheet = ws;
+ CreateXml(pck);
+ AddCommentsFromXml();
+ }
- internal void Clear()
- {
- while(Count>0)
- {
- RemoveAt(0);
- }
- }
+ 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; }
+
+ 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;
+ }
+ }
+
+ /// <summary>
+ /// Adds a comment to the top left cell of the range
+ /// </summary>
+ /// <param name="cell">The cell</param>
+ /// <param name="text">The comment text</param>
+ /// <param name="author">Author</param>
+ /// <returns>The comment</returns>
+ public ExcelComment Add(ExcelRangeBase cell, string text, string author) {
+ var elem = CommentXml.CreateElement("comment", ExcelPackage._schemaMain);
+ int ix = _comments.IndexOf(
+ ExcelCellBase.GetCellId(Worksheet.SheetID, cell._fromRow, cell._fromCol));
+ //Make sure the nodes come on order.
+ if (ix < 0 && (~ix < _comments.Count)) {
+ ix = ~ix;
+ var preComment = _comments[ix] as ExcelComment;
+ preComment._commentHelper.TopNode.ParentNode.InsertBefore(
+ elem,
+ preComment._commentHelper.TopNode);
+ } else {
+ CommentXml.SelectSingleNode("d:comments/d:commentList", NameSpaceManager).AppendChild(elem);
+ }
+ elem.SetAttribute("ref", cell.Start.Address);
+ ExcelComment comment = new ExcelComment(NameSpaceManager, elem, cell);
+ comment.RichText.Add(text);
+ if (author != "") {
+ comment.Author = author;
+ }
+ _comments.Add(comment);
+ //Check if a value exists otherwise add one so it is saved when the cells collection is iterated
+ if (!Worksheet._values.Exists(cell._fromRow, cell._fromCol)) {
+ Worksheet._values.SetValue(cell._fromRow, cell._fromCol, null);
+ }
+ return comment;
+ }
+
+ /// <summary>
+ /// Removes the comment
+ /// </summary>
+ /// <param name="comment">The comment to remove</param>
+ public void Remove(ExcelComment comment) {
+ ulong id = ExcelCellBase.GetCellId(
+ Worksheet.SheetID,
+ comment.Range._fromRow,
+ comment.Range._fromCol);
+ int ix = _comments.IndexOf(id);
+ if (ix >= 0 && comment == _comments[ix]) {
+ comment.TopNode.ParentNode.RemoveChild(comment.TopNode); //Remove VML
+ comment._commentHelper.TopNode.ParentNode.RemoveChild(comment._commentHelper.TopNode); //Remove Comment
+
+ Worksheet.VmlDrawingsComments._drawings.Delete(id);
+ _comments.Delete(id);
+ } else {
+ throw (new ArgumentException("Comment does not exist in the worksheet"));
+ }
+ }
+
+ void IDisposable.Dispose() {}
+
+ /// <summary>
+ /// Removes the comment at the specified position
+ /// </summary>
+ /// <param name="index">The index</param>
+ public void RemoveAt(int index) {
+ Remove(this[index]);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _comments;
+ }
+
+ internal void Clear() {
+ while (Count > 0) {
+ RemoveAt(0);
+ }
+ }
}
diff --git a/EPPlus/ExcelHeaderFooter.cs b/EPPlus/ExcelHeaderFooter.cs
index ce72dd8..9a53f92 100644
--- a/EPPlus/ExcelHeaderFooter.cs
+++ b/EPPlus/ExcelHeaderFooter.cs
@@ -13,365 +13,337 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
* *******************************************************************************/
+
using System.Xml;
-namespace OfficeOpenXml
-{
- #region class ExcelHeaderFooterText
- /// <summary>
- /// Print header and footer
- /// </summary>
- public class ExcelHeaderFooterText
- {
- ExcelWorksheet _ws;
- string _hf;
- internal ExcelHeaderFooterText(XmlNode TextNode, ExcelWorksheet ws, string hf)
- {
- _ws = ws;
- _hf = hf;
- if (TextNode == null || string.IsNullOrEmpty(TextNode.InnerText)) return;
- string text = TextNode.InnerText;
- string code = text.Substring(0, 2);
- int startPos=2;
- for (int pos=startPos;pos<text.Length-2;pos++)
- {
- string newCode = text.Substring(pos, 2);
- if (newCode == "&C" || newCode == "&R")
- {
- SetText(code, text.Substring(startPos, pos-startPos));
- startPos = pos+2;
- pos = startPos;
- code = newCode;
- }
- }
- SetText(code, text.Substring(startPos, text.Length - startPos));
- }
- private void SetText(string code, string text)
- {
- switch (code)
- {
- case "&L":
- LeftAlignedText=text;
- break;
- case "&C":
- CenteredText=text;
- break;
- default:
- RightAlignedText=text;
- break;
- }
- }
- /// <summary>
- /// Get/set the text to appear on the left hand side of the header (or footer) on the worksheet.
- /// </summary>
- public string LeftAlignedText = null;
- /// <summary>
- /// Get/set the text to appear in the center of the header (or footer) on the worksheet.
- /// </summary>
- public string CenteredText = null;
- /// <summary>
- /// Get/set the text to appear on the right hand side of the header (or footer) on the worksheet.
- /// </summary>
- public string RightAlignedText = null;
- }
- #endregion
- #region ExcelHeaderFooter
- /// <summary>
- /// Represents the Header and Footer on an Excel Worksheet
- /// </summary>
- public sealed class ExcelHeaderFooter : XmlHelper
- {
- #region Static Properties
- /// <summary>
- /// The code for "current page #"
- /// </summary>
- public const string PageNumber = @"&P";
- /// <summary>
- /// The code for "total pages"
- /// </summary>
- public const string NumberOfPages = @"&N";
- /// <summary>
- /// The code for "text font color"
- /// RGB Color is specified as RRGGBB
- /// Theme Color is specified as TTSNN where TT is the theme color Id, S is either "+" or "-" of the tint/shade value, NN is the tint/shade value.
- /// </summary>
- public const string FontColor = @"&K";
- /// <summary>
- /// The code for "sheet tab name"
- /// </summary>
- public const string SheetName = @"&A";
- /// <summary>
- /// The code for "this workbook's file path"
- /// </summary>
- public const string FilePath = @"&Z";
- /// <summary>
- /// The code for "this workbook's file name"
- /// </summary>
- public const string FileName = @"&F";
- /// <summary>
- /// The code for "date"
- /// </summary>
- public const string CurrentDate = @"&D";
- /// <summary>
- /// The code for "time"
- /// </summary>
- public const string CurrentTime = @"&T";
- /// <summary>
- /// The code for "picture as background"
- /// </summary>
- public const string Image = @"&G";
- /// <summary>
- /// The code for "outline style"
- /// </summary>
- public const string OutlineStyle = @"&O";
- /// <summary>
- /// The code for "shadow style"
- /// </summary>
- public const string ShadowStyle = @"&H";
- #endregion
+namespace OfficeOpenXml;
- #region ExcelHeaderFooter Private Properties
- internal ExcelHeaderFooterText _oddHeader;
- internal ExcelHeaderFooterText _oddFooter;
- internal ExcelHeaderFooterText _evenHeader;
- internal ExcelHeaderFooterText _evenFooter;
- internal ExcelHeaderFooterText _firstHeader;
- internal ExcelHeaderFooterText _firstFooter;
- private ExcelWorksheet _ws;
- #endregion
+/// <summary>
+/// Print header and footer
+/// </summary>
+public class ExcelHeaderFooterText {
+ private ExcelWorksheet _ws;
+ private string _hf;
- #region ExcelHeaderFooter Constructor
- /// <summary>
- /// ExcelHeaderFooter Constructor
- /// </summary>
- /// <param name="nameSpaceManager"></param>
- /// <param name="topNode"></param>
- /// <param name="ws">The worksheet</param>
- internal ExcelHeaderFooter(XmlNamespaceManager nameSpaceManager, XmlNode topNode, ExcelWorksheet ws) :
- base(nameSpaceManager, topNode)
- {
- _ws = ws;
- SchemaNodeOrder = new string[] { "headerFooter", "oddHeader", "oddFooter", "evenHeader", "evenFooter", "firstHeader", "firstFooter" };
- }
- #endregion
+ internal ExcelHeaderFooterText(XmlNode textNode, ExcelWorksheet ws, string hf) {
+ _ws = ws;
+ _hf = hf;
+ if (textNode == null || string.IsNullOrEmpty(textNode.InnerText)) {
+ return;
+ }
+ string text = textNode.InnerText;
+ string code = text.Substring(0, 2);
+ int startPos = 2;
+ for (int pos = startPos; pos < text.Length - 2; pos++) {
+ string newCode = text.Substring(pos, 2);
+ if (newCode == "&C" || newCode == "&R") {
+ SetText(code, text.Substring(startPos, pos - startPos));
+ startPos = pos + 2;
+ pos = startPos;
+ code = newCode;
+ }
+ }
+ SetText(code, text.Substring(startPos, text.Length - startPos));
+ }
- #region alignWithMargins
- const string alignWithMarginsPath="@alignWithMargins";
- /// <summary>
- /// Gets/sets the alignWithMargins attribute
- /// </summary>
- public bool AlignWithMargins
- {
- get
- {
- return GetXmlNodeBool(alignWithMarginsPath);
- }
- set
- {
- SetXmlNodeString(alignWithMarginsPath, value ? "1" : "0");
- }
- }
- #endregion
+ private void SetText(string code, string text) {
+ switch (code) {
+ case "&L":
+ LeftAlignedText = text;
+ break;
+ case "&C":
+ CenteredText = text;
+ break;
+ default:
+ RightAlignedText = text;
+ break;
+ }
+ }
- #region differentOddEven
- const string differentOddEvenPath = "@differentOddEven";
- /// <summary>
- /// Gets/sets the flag that tells Excel to display different headers and footers on odd and even pages.
- /// </summary>
- public bool differentOddEven
- {
- get
- {
- return GetXmlNodeBool(differentOddEvenPath);
- }
- set
- {
- SetXmlNodeString(differentOddEvenPath, value ? "1" : "0");
- }
- }
- #endregion
+ /// <summary>
+ /// Get/set the text to appear on the left hand side of the header (or footer) on the worksheet.
+ /// </summary>
+ public string LeftAlignedText;
- #region differentFirst
- const string differentFirstPath = "@differentFirst";
+ /// <summary>
+ /// Get/set the text to appear in the center of the header (or footer) on the worksheet.
+ /// </summary>
+ public string CenteredText;
- /// <summary>
- /// Gets/sets the flag that tells Excel to display different headers and footers on the first page of the worksheet.
- /// </summary>
- public bool differentFirst
- {
- get
- {
- return GetXmlNodeBool(differentFirstPath);
- }
- set
- {
- SetXmlNodeString(differentFirstPath, value ? "1" : "0");
- }
- }
- #endregion
+ /// <summary>
+ /// Get/set the text to appear on the right hand side of the header (or footer) on the worksheet.
+ /// </summary>
+ public string RightAlignedText;
+}
- #region ExcelHeaderFooter Public Properties
- /// <summary>
- /// Provides access to the header on odd numbered pages of the document.
- /// If you want the same header on both odd and even pages, then only set values in this ExcelHeaderFooterText class.
- /// </summary>
- public ExcelHeaderFooterText OddHeader
- {
- get
- {
- if (_oddHeader == null)
- {
- _oddHeader = new ExcelHeaderFooterText(TopNode.SelectSingleNode("d:oddHeader", NameSpaceManager), _ws, "H");
- }
- return _oddHeader; }
- }
- /// <summary>
- /// Provides access to the footer on odd numbered pages of the document.
- /// If you want the same footer on both odd and even pages, then only set values in this ExcelHeaderFooterText class.
- /// </summary>
- public ExcelHeaderFooterText OddFooter
- {
- get
- {
- if (_oddFooter == null)
- {
- _oddFooter = new ExcelHeaderFooterText(TopNode.SelectSingleNode("d:oddFooter", NameSpaceManager), _ws, "F"); ;
- }
- return _oddFooter;
- }
- }
- // evenHeader and evenFooter set differentOddEven = true
- /// <summary>
- /// Provides access to the header on even numbered pages of the document.
- /// </summary>
- public ExcelHeaderFooterText EvenHeader
- {
- get
- {
- if (_evenHeader == null)
- {
- _evenHeader = new ExcelHeaderFooterText(TopNode.SelectSingleNode("d:evenHeader", NameSpaceManager), _ws, "HEVEN");
- differentOddEven = true;
- }
- return _evenHeader;
- }
- }
- /// <summary>
- /// Provides access to the footer on even numbered pages of the document.
- /// </summary>
- public ExcelHeaderFooterText EvenFooter
- {
- get
- {
- if (_evenFooter == null)
- {
- _evenFooter = new ExcelHeaderFooterText(TopNode.SelectSingleNode("d:evenFooter", NameSpaceManager), _ws, "FEVEN");
- differentOddEven = true;
- }
- return _evenFooter ;
- }
- }
- /// <summary>
- /// Provides access to the header on the first page of the document.
- /// </summary>
- public ExcelHeaderFooterText FirstHeader
- {
- get
- {
- if (_firstHeader == null)
- {
- _firstHeader = new ExcelHeaderFooterText(TopNode.SelectSingleNode("d:firstHeader", NameSpaceManager), _ws, "HFIRST");
- differentFirst = true;
- }
- return _firstHeader;
- }
- }
- /// <summary>
- /// Provides access to the footer on the first page of the document.
- /// </summary>
- public ExcelHeaderFooterText FirstFooter
- {
- get
- {
- if (_firstFooter == null)
- {
- _firstFooter = new ExcelHeaderFooterText(TopNode.SelectSingleNode("d:firstFooter", NameSpaceManager), _ws, "FFIRST");
- differentFirst = true;
- }
- return _firstFooter;
- }
- }
- #endregion
- #region Save // ExcelHeaderFooter
- /// <summary>
- /// Saves the header and footer information to the worksheet XML
- /// </summary>
- internal void Save()
- {
- if (_oddHeader != null)
- {
- SetXmlNodeString("d:oddHeader", GetText(OddHeader));
- }
- if (_oddFooter != null)
- {
- SetXmlNodeString("d:oddFooter", GetText(OddFooter));
- }
+/// <summary>
+/// Represents the Header and Footer on an Excel Worksheet
+/// </summary>
+public sealed class ExcelHeaderFooter : XmlHelper {
+ /// <summary>
+ /// The code for "current page #"
+ /// </summary>
+ public const string PageNumber = "&P";
- // only set evenHeader and evenFooter
- if (differentOddEven)
- {
- if (_evenHeader != null)
- {
- SetXmlNodeString("d:evenHeader", GetText(EvenHeader));
- }
- if (_evenFooter != null)
- {
- SetXmlNodeString("d:evenFooter", GetText(EvenFooter));
- }
- }
+ /// <summary>
+ /// The code for "total pages"
+ /// </summary>
+ public const string NumberOfPages = "&N";
- // only set firstHeader and firstFooter
- if (differentFirst)
- {
- if (_firstHeader != null)
- {
- SetXmlNodeString("d:firstHeader", GetText(FirstHeader));
- }
- if (_firstFooter != null)
- {
- SetXmlNodeString("d:firstFooter", GetText(FirstFooter));
- }
- }
- }
- private string GetText(ExcelHeaderFooterText headerFooter)
- {
- string ret = "";
- if (headerFooter.LeftAlignedText != null)
- ret += "&L" + headerFooter.LeftAlignedText;
- if (headerFooter.CenteredText != null)
- ret += "&C" + headerFooter.CenteredText;
- if (headerFooter.RightAlignedText != null)
- ret += "&R" + headerFooter.RightAlignedText;
- return ret;
- }
- #endregion
- }
- #endregion
+ /// <summary>
+ /// The code for "text font color"
+ /// RGB Color is specified as RRGGBB
+ /// Theme Color is specified as TTSNN where TT is the theme color Id, S is either "+" or "-" of the tint/shade value, NN is the tint/shade value.
+ /// </summary>
+ public const string FontColor = "&K";
+
+ /// <summary>
+ /// The code for "sheet tab name"
+ /// </summary>
+ public const string SheetName = "&A";
+
+ /// <summary>
+ /// The code for "this workbook's file path"
+ /// </summary>
+ public const string FilePath = "&Z";
+
+ /// <summary>
+ /// The code for "this workbook's file name"
+ /// </summary>
+ public const string FileName = "&F";
+
+ /// <summary>
+ /// The code for "date"
+ /// </summary>
+ public const string CurrentDate = "&D";
+
+ /// <summary>
+ /// The code for "time"
+ /// </summary>
+ public const string CurrentTime = "&T";
+
+ /// <summary>
+ /// The code for "picture as background"
+ /// </summary>
+ public const string Image = "&G";
+
+ /// <summary>
+ /// The code for "outline style"
+ /// </summary>
+ public const string OutlineStyle = "&O";
+
+ /// <summary>
+ /// The code for "shadow style"
+ /// </summary>
+ public const string ShadowStyle = "&H";
+
+ internal ExcelHeaderFooterText _oddHeader;
+ internal ExcelHeaderFooterText _oddFooter;
+ internal ExcelHeaderFooterText _evenHeader;
+ internal ExcelHeaderFooterText _evenFooter;
+ internal ExcelHeaderFooterText _firstHeader;
+ internal ExcelHeaderFooterText _firstFooter;
+ private ExcelWorksheet _ws;
+
+ /// <summary>
+ /// ExcelHeaderFooter Constructor
+ /// </summary>
+ /// <param name="nameSpaceManager"></param>
+ /// <param name="topNode"></param>
+ /// <param name="ws">The worksheet</param>
+ internal ExcelHeaderFooter(
+ XmlNamespaceManager nameSpaceManager,
+ XmlNode topNode,
+ ExcelWorksheet ws)
+ : base(nameSpaceManager, topNode) {
+ _ws = ws;
+ SchemaNodeOrder = new[] {
+ "headerFooter",
+ "oddHeader",
+ "oddFooter",
+ "evenHeader",
+ "evenFooter",
+ "firstHeader",
+ "firstFooter",
+ };
+ }
+
+ private const string _alignWithMarginsPath = "@alignWithMargins";
+
+ /// <summary>
+ /// Gets/sets the alignWithMargins attribute
+ /// </summary>
+ public bool AlignWithMargins {
+ get => GetXmlNodeBool(_alignWithMarginsPath);
+ set => SetXmlNodeString(_alignWithMarginsPath, value ? "1" : "0");
+ }
+
+ private const string _differentOddEvenPath = "@differentOddEven";
+
+ /// <summary>
+ /// Gets/sets the flag that tells Excel to display different headers and footers on odd and even pages.
+ /// </summary>
+ public bool differentOddEven {
+ get => GetXmlNodeBool(_differentOddEvenPath);
+ set => SetXmlNodeString(_differentOddEvenPath, value ? "1" : "0");
+ }
+
+ private const string _differentFirstPath = "@differentFirst";
+
+ /// <summary>
+ /// Gets/sets the flag that tells Excel to display different headers and footers on the first page of the worksheet.
+ /// </summary>
+ public bool differentFirst {
+ get => GetXmlNodeBool(_differentFirstPath);
+ set => SetXmlNodeString(_differentFirstPath, value ? "1" : "0");
+ }
+
+ /// <summary>
+ /// Provides access to the header on odd numbered pages of the document.
+ /// If you want the same header on both odd and even pages, then only set values in this ExcelHeaderFooterText class.
+ /// </summary>
+ public ExcelHeaderFooterText OddHeader {
+ get {
+ if (_oddHeader == null) {
+ _oddHeader = new(TopNode.SelectSingleNode("d:oddHeader", NameSpaceManager), _ws, "H");
+ }
+ return _oddHeader;
+ }
+ }
+
+ /// <summary>
+ /// Provides access to the footer on odd numbered pages of the document.
+ /// If you want the same footer on both odd and even pages, then only set values in this ExcelHeaderFooterText class.
+ /// </summary>
+ public ExcelHeaderFooterText OddFooter {
+ get {
+ if (_oddFooter == null) {
+ _oddFooter = new(TopNode.SelectSingleNode("d:oddFooter", NameSpaceManager), _ws, "F");
+ ;
+ }
+ return _oddFooter;
+ }
+ }
+
+ // evenHeader and evenFooter set differentOddEven = true
+ /// <summary>
+ /// Provides access to the header on even numbered pages of the document.
+ /// </summary>
+ public ExcelHeaderFooterText EvenHeader {
+ get {
+ if (_evenHeader == null) {
+ _evenHeader = new(TopNode.SelectSingleNode("d:evenHeader", NameSpaceManager), _ws, "HEVEN");
+ differentOddEven = true;
+ }
+ return _evenHeader;
+ }
+ }
+
+ /// <summary>
+ /// Provides access to the footer on even numbered pages of the document.
+ /// </summary>
+ public ExcelHeaderFooterText EvenFooter {
+ get {
+ if (_evenFooter == null) {
+ _evenFooter = new(TopNode.SelectSingleNode("d:evenFooter", NameSpaceManager), _ws, "FEVEN");
+ differentOddEven = true;
+ }
+ return _evenFooter;
+ }
+ }
+
+ /// <summary>
+ /// Provides access to the header on the first page of the document.
+ /// </summary>
+ public ExcelHeaderFooterText FirstHeader {
+ get {
+ if (_firstHeader == null) {
+ _firstHeader = new(
+ TopNode.SelectSingleNode("d:firstHeader", NameSpaceManager),
+ _ws,
+ "HFIRST");
+ differentFirst = true;
+ }
+ return _firstHeader;
+ }
+ }
+
+ /// <summary>
+ /// Provides access to the footer on the first page of the document.
+ /// </summary>
+ public ExcelHeaderFooterText FirstFooter {
+ get {
+ if (_firstFooter == null) {
+ _firstFooter = new(
+ TopNode.SelectSingleNode("d:firstFooter", NameSpaceManager),
+ _ws,
+ "FFIRST");
+ differentFirst = true;
+ }
+ return _firstFooter;
+ }
+ }
+
+ /// <summary>
+ /// Saves the header and footer information to the worksheet XML
+ /// </summary>
+ internal void Save() {
+ if (_oddHeader != null) {
+ SetXmlNodeString("d:oddHeader", GetText(OddHeader));
+ }
+ if (_oddFooter != null) {
+ SetXmlNodeString("d:oddFooter", GetText(OddFooter));
+ }
+
+ // only set evenHeader and evenFooter
+ if (differentOddEven) {
+ if (_evenHeader != null) {
+ SetXmlNodeString("d:evenHeader", GetText(EvenHeader));
+ }
+ if (_evenFooter != null) {
+ SetXmlNodeString("d:evenFooter", GetText(EvenFooter));
+ }
+ }
+
+ // only set firstHeader and firstFooter
+ if (differentFirst) {
+ if (_firstHeader != null) {
+ SetXmlNodeString("d:firstHeader", GetText(FirstHeader));
+ }
+ if (_firstFooter != null) {
+ SetXmlNodeString("d:firstFooter", GetText(FirstFooter));
+ }
+ }
+ }
+
+ private string GetText(ExcelHeaderFooterText headerFooter) {
+ string ret = "";
+ if (headerFooter.LeftAlignedText != null) {
+ ret += "&L" + headerFooter.LeftAlignedText;
+ }
+ if (headerFooter.CenteredText != null) {
+ ret += "&C" + headerFooter.CenteredText;
+ }
+ if (headerFooter.RightAlignedText != null) {
+ ret += "&R" + headerFooter.RightAlignedText;
+ }
+ return ret;
+ }
}
diff --git a/EPPlus/ExcelHyperLink.cs b/EPPlus/ExcelHyperLink.cs
index 3d1a027..dc4aa3b 100644
--- a/EPPlus/ExcelHyperLink.cs
+++ b/EPPlus/ExcelHyperLink.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,155 +13,125 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
-using System.Collections.Generic;
-using System.Text;
-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 = (Uri)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 = (Uri)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 = (Uri)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;
- }
- string _referenceAddress = null;
- /// <summary>
- /// The Excel address for internal links.
- /// </summary>
- public string ReferenceAddress
- {
- get
- {
- return _referenceAddress;
- }
- set
- {
- _referenceAddress = value;
- }
- }
- string _display = "";
- /// <summary>
- /// Displayed text
- /// </summary>
- public string Display
- {
- get
- {
- return _display;
- }
- set
- {
- _display = value;
- }
- }
- /// <summary>
- /// Tooltip
- /// </summary>
- public string ToolTip
- {
- get;
- set;
- }
- int _colSpann = 0;
- /// <summary>
- /// If the hyperlink spans multiple columns
- /// </summary>
- public int ColSpann
- {
- get
- {
- return _colSpann;
- }
- set
- {
- _colSpann = value;
- }
- }
- int _rowSpann = 0;
- /// <summary>
- /// If the hyperlink spans multiple rows
- /// </summary>
- public int RowSpann
- {
- get
- {
- return _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;
- }
- }
+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
index e8bef17..da86830 100644
--- a/EPPlus/ExcelNamedRange.cs
+++ b/EPPlus/ExcelNamedRange.cs
@@ -13,110 +13,92 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Text;
-namespace OfficeOpenXml
-{
- /// <summary>
- /// A named range.
- /// </summary>
- public sealed class ExcelNamedRange : ExcelRangeBase
- {
- 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;
+namespace OfficeOpenXml;
- }
- internal ExcelNamedRange(string name,ExcelWorkbook wb, ExcelWorksheet nameSheet, int index) :
- base(wb, nameSheet, name, true)
- {
- Name = name;
- _sheet = nameSheet;
- Index = index;
- }
+/// <summary>
+/// A named range.
+/// </summary>
+public sealed class ExcelNamedRange : ExcelRangeBase {
+ private ExcelWorksheet _sheet;
- /// <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;
- }
- else
- {
- 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;
- }
+ /// <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
index 2cad528..ab281f9 100644
--- a/EPPlus/ExcelNamedRangeCollection.cs
+++ b/EPPlus/ExcelNamedRangeCollection.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,228 +13,198 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Text;
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;
- }
- List<ExcelNamedRange> _list = new List<ExcelNamedRange>();
- Dictionary<string, int> _dic = new Dictionary<string, int>(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)
- {
+namespace OfficeOpenXml;
- item = new ExcelNamedRange(Name, _wb,_ws, _dic.Count);
- }
- else
- {
- item = new ExcelNamedRange(Name, _ws, Range.Worksheet, Range.Address, _dic.Count);
- }
+/// <summary>
+/// Collection for named ranges
+/// </summary>
+public class ExcelNamedRangeCollection : IEnumerable<ExcelNamedRange> {
+ internal ExcelWorksheet _ws;
+ internal ExcelWorkbook _wb;
- AddName(Name, item);
+ internal ExcelNamedRangeCollection(ExcelWorkbook wb) {
+ _wb = wb;
+ _ws = null;
+ }
- return item;
- }
+ internal ExcelNamedRangeCollection(ExcelWorkbook wb, ExcelWorksheet ws) {
+ _wb = wb;
+ _ws = ws;
+ }
- 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;
+ private List<ExcelNamedRange> _list = new();
+ private Dictionary<string, int> _dic = new(StringComparer.InvariantCultureIgnoreCase);
- //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 this.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
- {
- get
- {
- return _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]
- {
- get
- {
- return _list[_dic[Name]];
- }
- }
- public ExcelNamedRange this[int Index]
- {
- get
- {
- return _list[Index];
- }
- }
-
- #region "IEnumerable"
- #region IEnumerable<ExcelNamedRange> Members
- /// <summary>
- /// Implement interface method IEnumerator<ExcelNamedRange> GetEnumerator()
- /// </summary>
- /// <returns></returns>
- public IEnumerator<ExcelNamedRange> GetEnumerator()
- {
- return _list.GetEnumerator();
- }
- #endregion
- #region IEnumerable Members
- /// <summary>
- /// Implement interface method IEnumeratable GetEnumerator()
- /// </summary>
- /// <returns></returns>
- IEnumerator IEnumerable.GetEnumerator()
- {
- return _list.GetEnumerator();
- }
-
- #endregion
- #endregion
-
- internal void Clear()
- {
- while(Count>0)
- {
- Remove(_list[0].Name);
- }
- }
+ /// <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] {
+ get { return _list[_dic[name]]; }
+ }
+
+ public ExcelNamedRange this[int index] {
+ get { return _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
index 78c4083..5bd9395 100644
--- a/EPPlus/ExcelPackage.cs
+++ b/EPPlus/ExcelPackage.cs
@@ -13,352 +13,349 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
+ * 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.Xml;
using System.IO;
-using System.Collections.Generic;
-using System.Security.Cryptography;
+using System.Xml;
+using OfficeOpenXml.Packaging;
using OfficeOpenXml.Utils;
-namespace OfficeOpenXml
-{
- /// <summary>
- /// Maps to DotNetZips CompressionLevel enum
- /// </summary>
- public enum CompressionLevel
- {
- Level0 = 0,
- None = 0,
- Level1 = 1,
- BestSpeed = 1,
- Level2 = 2,
- Level3 = 3,
- Level4 = 4,
- Level5 = 5,
- Level6 = 6,
- Default = 6,
- Level7 = 7,
- Level8 = 8,
- BestCompression = 9,
- Level9 = 9,
- }
- /// <summary>
- /// Represents an Excel 2007/2010 XLSX file package.
- /// This is the top-level object to access all parts of the document.
- /// <code>
- /// FileInfo newFile = new FileInfo(outputDir.FullName + @"\sample1.xlsx");
- /// if (newFile.Exists)
- /// {
- /// newFile.Delete(); // ensures we create a new workbook
- /// newFile = new FileInfo(outputDir.FullName + @"\sample1.xlsx");
- /// }
- /// using (ExcelPackage package = new ExcelPackage(newFile))
- /// {
- /// // add a new worksheet to the empty workbook
- /// ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Inventory");
- /// //Add the headers
- /// worksheet.Cells[1, 1].Value = "ID";
- /// worksheet.Cells[1, 2].Value = "Product";
- /// worksheet.Cells[1, 3].Value = "Quantity";
- /// worksheet.Cells[1, 4].Value = "Price";
- /// worksheet.Cells[1, 5].Value = "Value";
- ///
- /// //Add some items...
- /// worksheet.Cells["A2"].Value = "12001";
- /// worksheet.Cells["B2"].Value = "Nails";
- /// worksheet.Cells["C2"].Value = 37;
- /// worksheet.Cells["D2"].Value = 3.99;
- ///
- /// worksheet.Cells["A3"].Value = "12002";
- /// worksheet.Cells["B3"].Value = "Hammer";
- /// worksheet.Cells["C3"].Value = 5;
- /// worksheet.Cells["D3"].Value = 12.10;
- ///
- /// worksheet.Cells["A4"].Value = "12003";
- /// worksheet.Cells["B4"].Value = "Saw";
- /// worksheet.Cells["C4"].Value = 12;
- /// worksheet.Cells["D4"].Value = 15.37;
- ///
- /// //Add a formula for the value-column
- /// worksheet.Cells["E2:E4"].Formula = "C2*D2";
- ///
- /// //Ok now format the values;
- /// using (var range = worksheet.Cells[1, 1, 1, 5])
- /// {
- /// range.Style.Font.Bold = true;
- /// range.Style.Fill.PatternType = ExcelFillStyle.Solid;
- /// range.Style.Fill.BackgroundColor.SetColor(Color.DarkBlue);
- /// range.Style.Font.Color.SetColor(Color.White);
- /// }
- ///
- /// worksheet.Cells["A5:E5"].Style.Border.Top.Style = ExcelBorderStyle.Thin;
- /// worksheet.Cells["A5:E5"].Style.Font.Bold = true;
- ///
- /// worksheet.Cells[5, 3, 5, 5].Formula = string.Format("SUBTOTAL(9,{0})", new ExcelAddress(2,3,4,3).Address);
- /// worksheet.Cells["C2:C5"].Style.Numberformat.Format = "#,##0";
- /// worksheet.Cells["D2:E5"].Style.Numberformat.Format = "#,##0.00";
- ///
- /// //Create an autofilter for the range
- /// worksheet.Cells["A1:E4"].AutoFilter = true;
- ///
- /// worksheet.Cells["A1:E5"].AutoFitColumns(0);
- ///
- /// // lets set the header text
- /// worksheet.HeaderFooter.oddHeader.CenteredText = "&24&U&\"Arial,Regular Bold\" Inventory";
- /// // add the page number to the footer plus the total number of pages
- /// worksheet.HeaderFooter.oddFooter.RightAlignedText =
- /// string.Format("Page {0} of {1}", ExcelHeaderFooter.PageNumber, ExcelHeaderFooter.NumberOfPages);
- /// // add the sheet name to the footer
- /// worksheet.HeaderFooter.oddFooter.CenteredText = ExcelHeaderFooter.SheetName;
- /// // add the file path to the footer
- /// worksheet.HeaderFooter.oddFooter.LeftAlignedText = ExcelHeaderFooter.FilePath + ExcelHeaderFooter.FileName;
- ///
- /// worksheet.PrinterSettings.RepeatRows = worksheet.Cells["1:2"];
- /// worksheet.PrinterSettings.RepeatColumns = worksheet.Cells["A:G"];
- ///
- /// // Change the sheet view to show it in page layout mode
- /// worksheet.View.PageLayoutView = true;
- ///
- /// // set some document properties
- /// package.Workbook.Properties.Title = "Invertory";
- /// package.Workbook.Properties.Author = "Jan K�llman";
- /// package.Workbook.Properties.Comments = "This sample demonstrates how to create an Excel 2007 workbook using EPPlus";
- ///
- /// // set some extended property values
- /// package.Workbook.Properties.Company = "AdventureWorks Inc.";
- ///
- /// // set some custom property values
- /// package.Workbook.Properties.SetCustomPropertyValue("Checked by", "Jan K�llman");
- /// package.Workbook.Properties.SetCustomPropertyValue("AssemblyName", "EPPlus");
- ///
- /// // save our new workbook and we are done!
- /// package.Save();
- ///
- /// }
- ///
- /// return newFile.FullName;
- /// </code>
- /// More samples can be found at <a href="http://epplus.codeplex.com/">http://epplus.codeplex.com/</a>
- /// </summary>
- public sealed class ExcelPackage
- {
- internal const bool preserveWhitespace=false;
-
- #region Properties
- /// <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 schemaDrawings = @"http://schemas.openxmlformats.org/drawingml/2006/main";
- 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";
+namespace OfficeOpenXml;
- 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";
+/// <summary>
+/// Maps to DotNetZips CompressionLevel enum
+/// </summary>
+public enum CompressionLevel {
+ Level0 = 0,
+ None = 0,
+ Level1 = 1,
+ BestSpeed = 1,
+ Level2 = 2,
+ Level3 = 3,
+ Level4 = 4,
+ Level5 = 5,
+ Level6 = 6,
+ Default = 6,
+ Level7 = 7,
+ Level8 = 8,
+ BestCompression = 9,
+ Level9 = 9,
+}
- //Pivottables
- internal const string schemaPivotTable = @"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml";
- internal const string schemaPivotCacheDefinition = @"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml";
- internal const string schemaPivotCacheRecords = @"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml";
+/// <summary>
+/// Represents an Excel 2007/2010 XLSX file package.
+/// This is the top-level object to access all parts of the document.
+/// <code>
+/// FileInfo newFile = new FileInfo(outputDir.FullName + @"\sample1.xlsx");
+/// if (newFile.Exists)
+/// {
+/// newFile.Delete(); // ensures we create a new workbook
+/// newFile = new FileInfo(outputDir.FullName + @"\sample1.xlsx");
+/// }
+/// using (ExcelPackage package = new ExcelPackage(newFile))
+/// {
+/// // add a new worksheet to the empty workbook
+/// ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Inventory");
+/// //Add the headers
+/// worksheet.Cells[1, 1].Value = "ID";
+/// worksheet.Cells[1, 2].Value = "Product";
+/// worksheet.Cells[1, 3].Value = "Quantity";
+/// worksheet.Cells[1, 4].Value = "Price";
+/// worksheet.Cells[1, 5].Value = "Value";
+///
+/// //Add some items...
+/// worksheet.Cells["A2"].Value = "12001";
+/// worksheet.Cells["B2"].Value = "Nails";
+/// worksheet.Cells["C2"].Value = 37;
+/// worksheet.Cells["D2"].Value = 3.99;
+///
+/// worksheet.Cells["A3"].Value = "12002";
+/// worksheet.Cells["B3"].Value = "Hammer";
+/// worksheet.Cells["C3"].Value = 5;
+/// worksheet.Cells["D3"].Value = 12.10;
+///
+/// worksheet.Cells["A4"].Value = "12003";
+/// worksheet.Cells["B4"].Value = "Saw";
+/// worksheet.Cells["C4"].Value = 12;
+/// worksheet.Cells["D4"].Value = 15.37;
+///
+/// //Add a formula for the value-column
+/// worksheet.Cells["E2:E4"].Formula = "C2*D2";
+///
+/// //Ok now format the values;
+/// using (var range = worksheet.Cells[1, 1, 1, 5])
+/// {
+/// range.Style.Font.Bold = true;
+/// range.Style.Fill.PatternType = ExcelFillStyle.Solid;
+/// range.Style.Fill.BackgroundColor.SetColor(Color.DarkBlue);
+/// range.Style.Font.Color.SetColor(Color.White);
+/// }
+///
+/// worksheet.Cells["A5:E5"].Style.Border.Top.Style = ExcelBorderStyle.Thin;
+/// worksheet.Cells["A5:E5"].Style.Font.Bold = true;
+///
+/// worksheet.Cells[5, 3, 5, 5].Formula = string.Format("SUBTOTAL(9,{0})", new ExcelAddress(2,3,4,3).Address);
+/// worksheet.Cells["C2:C5"].Style.Numberformat.Format = "#,##0";
+/// worksheet.Cells["D2:E5"].Style.Numberformat.Format = "#,##0.00";
+///
+/// //Create an autofilter for the range
+/// worksheet.Cells["A1:E4"].AutoFilter = true;
+///
+/// worksheet.Cells["A1:E5"].AutoFitColumns(0);
+///
+/// // lets set the header text
+/// worksheet.HeaderFooter.oddHeader.CenteredText = "&24&U&\"Arial,Regular Bold\" Inventory";
+/// // add the page number to the footer plus the total number of pages
+/// worksheet.HeaderFooter.oddFooter.RightAlignedText =
+/// string.Format("Page {0} of {1}", ExcelHeaderFooter.PageNumber, ExcelHeaderFooter.NumberOfPages);
+/// // add the sheet name to the footer
+/// worksheet.HeaderFooter.oddFooter.CenteredText = ExcelHeaderFooter.SheetName;
+/// // add the file path to the footer
+/// worksheet.HeaderFooter.oddFooter.LeftAlignedText = ExcelHeaderFooter.FilePath + ExcelHeaderFooter.FileName;
+///
+/// worksheet.PrinterSettings.RepeatRows = worksheet.Cells["1:2"];
+/// worksheet.PrinterSettings.RepeatColumns = worksheet.Cells["A:G"];
+///
+/// // Change the sheet view to show it in page layout mode
+/// worksheet.View.PageLayoutView = true;
+///
+/// // set some document properties
+/// package.Workbook.Properties.Title = "Invertory";
+/// package.Workbook.Properties.Author = "Jan K�llman";
+/// package.Workbook.Properties.Comments = "This sample demonstrates how to create an Excel 2007 workbook using EPPlus";
+///
+/// // set some extended property values
+/// package.Workbook.Properties.Company = "AdventureWorks Inc.";
+///
+/// // set some custom property values
+/// package.Workbook.Properties.SetCustomPropertyValue("Checked by", "Jan K�llman");
+/// package.Workbook.Properties.SetCustomPropertyValue("AssemblyName", "EPPlus");
+///
+/// // save our new workbook and we are done!
+/// package.Save();
+///
+/// }
+///
+/// return newFile.FullName;
+/// </code>
+/// More samples can be found at <a href="http://epplus.codeplex.com/">http://epplus.codeplex.com/</a>
+/// </summary>
+public sealed class ExcelPackage {
+ internal const bool _preserveWhitespace = false;
- internal const string contentTypeWorkbookDefault = @"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml";
- internal const string contentTypeWorkbookMacroEnabled = "application/vnd.ms-excel.sheet.macroEnabled.main+xml";
- 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;
- #endregion
+ /// <summary>
+ /// Extention Schema types
+ /// </summary>
+ internal const string _schemaXmlExtension = "application/xml";
+ internal const string _schemaRelsExtension =
+ "application/vnd.openxmlformats-package.relationships+xml";
- #region ExcelPackage Constructors
- /// <summary>
- /// Create a new instance of the ExcelPackage. Output is accessed through the Stream property.
- /// </summary>
- public ExcelPackage()
- {
- Package = new();
- Workbook = CreateWorkbook();
- _ = Workbook.WorkbookXml;
- // create the relationship to the main part
- Package.CreateRelationship(UriHelper.GetRelativeUri(new Uri("/xl", UriKind.Relative), Workbook.WorkbookUri), Packaging.TargetMode.Internal, schemaRelationships + "/officeDocument");
- }
-
- /// <summary>
- /// Create a new instance of the ExcelPackage class based on a existing file or creates a new file.
- /// </summary>
- /// <param name="newFile">If newFile exists, it is opened. Otherwise it is created from scratch.</param>
- public ExcelPackage(FileInfo newFile)
- {
- using var inputStream = newFile.OpenRead();
- Package = new(inputStream);
- Workbook = CreateWorkbook();
- }
-
- /// <summary>
- /// Create a new instance of the ExcelPackage class based on a stream
- /// </summary>
- /// <param name="newStream">The stream object can be empty or contain a package. The stream must be Read/Write</param>
- public ExcelPackage(Stream newStream)
- {
- Package = new(newStream);
- Workbook = CreateWorkbook();
- }
+ /// <summary>
+ /// Main Xml schema name
+ /// </summary>
+ internal const string _schemaMain = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
- private ExcelWorkbook CreateWorkbook()
- {
- ExcelWorkbook workbook = new(this, CreateDefaultNSM());
- workbook.GetExternalReferences();
- workbook.GetDefinedNames();
- return workbook;
- }
-
- #endregion
-
- /// <summary>
- /// Returns a reference to the package
- /// </summary>
- internal Packaging.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; }
+ /// <summary>
+ /// Relationship schema name
+ /// </summary>
+ internal const string _schemaRelationships =
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
- 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, ExcelPackage.schemaMain);
- ns.AddNamespace("d", ExcelPackage.schemaMain);
- ns.AddNamespace("r", ExcelPackage.schemaRelationships);
- ns.AddNamespace("c", ExcelPackage.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;
- }
-
- #region SavePart
- /// <summary>
- /// Saves the XmlDocument into the package at the specified Uri.
- /// </summary>
- /// <param name="uri">The Uri of the component</param>
- /// <param name="xmlDoc">The XmlDocument to save</param>
- internal void SavePart(Uri uri, XmlDocument xmlDoc)
- {
- Packaging.ZipPackagePart part = Package.GetPart(uri);
- xmlDoc.Save(part.GetStream(FileMode.Create, FileAccess.Write));
- }
+ internal const string _schemaDrawings = "http://schemas.openxmlformats.org/drawingml/2006/main";
- #endregion
+ 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";
- /// <summary>
- /// Compression option for the package
- /// </summary>
- public CompressionLevel Compression
- {
- get
- {
- return Package.Compression;
- }
- set
- {
- Package.Compression = value;
- }
- }
- #region GetXmlFromUri
- /// <summary>
- /// Get the XmlDocument from an URI
- /// </summary>
- /// <param name="uri">The Uri to the part</param>
- /// <returns>The XmlDocument</returns>
- internal XmlDocument GetXmlFromUri(Uri uri)
- {
- XmlDocument xml = new XmlDocument();
- Packaging.ZipPackagePart part = Package.GetPart(uri);
- XmlHelper.LoadXmlSafe(xml, part.GetStream());
- return (xml);
- }
- #endregion
+ 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";
- /// <summary>
- /// Saves and returns the Excel files as a bytearray.
- /// Note that the package is closed upon save
- /// </summary>
- /// <example>
- /// Example how to return a document from a Webserver...
- /// <code>
- /// ExcelPackage package=new ExcelPackage();
- /// /**** ... Create the document ****/
- /// Byte[] bin = package.GetAsByteArray();
- /// Response.ContentType = "Application/vnd.ms-Excel";
- /// Response.AddHeader("content-disposition", "attachment; filename=TheFile.xlsx");
- /// Response.BinaryWrite(bin);
- /// </code>
- /// </example>
- /// <returns></returns>
- public byte[] GetAsByteArray()
- {
- var result = new MemoryStream();
- Workbook.Save();
- Package.Save(result);
- return result.ToArray();
- }
- }
-}
\ No newline at end of file
+ //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";
+
+ //Pivottables
+ internal const string _schemaPivotTable =
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml";
+ internal const string _schemaPivotCacheDefinition =
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml";
+ internal const string _schemaPivotCacheRecords =
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml";
+
+ internal const string _contentTypeWorkbookDefault =
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml";
+ internal const string _contentTypeWorkbookMacroEnabled =
+ "application/vnd.ms-excel.sheet.macroEnabled.main+xml";
+ 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 instance of the ExcelPackage. Output is accessed through the Stream property.
+ /// </summary>
+ public ExcelPackage() {
+ Package = new();
+ Workbook = CreateWorkbook();
+ _ = Workbook.WorkbookXml;
+ // create the relationship to the main part
+ Package.CreateRelationship(
+ UriHelper.GetRelativeUri(new("/xl", UriKind.Relative), Workbook.WorkbookUri),
+ TargetMode.Internal,
+ _schemaRelationships + "/officeDocument");
+ }
+
+ /// <summary>
+ /// Create a new instance of the ExcelPackage class based on a existing file or creates a new file.
+ /// </summary>
+ /// <param name="newFile">If newFile exists, it is opened. Otherwise it is created from scratch.</param>
+ public ExcelPackage(FileInfo newFile) {
+ using var inputStream = newFile.OpenRead();
+ Package = new(inputStream);
+ Workbook = CreateWorkbook();
+ }
+
+ /// <summary>
+ /// Create a new instance of the ExcelPackage class based on a stream
+ /// </summary>
+ /// <param name="newStream">The stream object can be empty or contain a package. The stream must be Read/Write</param>
+ public ExcelPackage(Stream newStream) {
+ Package = new(newStream);
+ Workbook = CreateWorkbook();
+ }
+
+ private ExcelWorkbook CreateWorkbook() {
+ ExcelWorkbook workbook = new(this, CreateDefaultNsm());
+ workbook.GetExternalReferences();
+ workbook.GetDefinedNames();
+ return workbook;
+ }
+
+ /// <summary>
+ /// Returns a reference to the package
+ /// </summary>
+ 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;
+ }
+
+ /// <summary>
+ /// Saves the XmlDocument into the package at the specified Uri.
+ /// </summary>
+ /// <param name="uri">The Uri of the component</param>
+ /// <param name="xmlDoc">The XmlDocument to save</param>
+ internal void SavePart(Uri uri, XmlDocument xmlDoc) {
+ ZipPackagePart part = Package.GetPart(uri);
+ xmlDoc.Save(part.GetStream(FileMode.Create, FileAccess.Write));
+ }
+
+ /// <summary>
+ /// Compression option for the package
+ /// </summary>
+ public CompressionLevel Compression {
+ get => Package.Compression;
+ set => Package.Compression = value;
+ }
+
+ /// <summary>
+ /// Get the XmlDocument from an URI
+ /// </summary>
+ /// <param name="uri">The Uri to the part</param>
+ /// <returns>The XmlDocument</returns>
+ internal XmlDocument GetXmlFromUri(Uri uri) {
+ XmlDocument xml = new XmlDocument();
+ ZipPackagePart part = Package.GetPart(uri);
+ XmlHelper.LoadXmlSafe(xml, part.GetStream());
+ return (xml);
+ }
+
+ /// <summary>
+ /// Saves and returns the Excel files as a bytearray.
+ /// Note that the package is closed upon save
+ /// </summary>
+ /// <example>
+ /// Example how to return a document from a Webserver...
+ /// <code>
+ /// ExcelPackage package=new ExcelPackage();
+ /// /**** ... Create the document ****/
+ /// Byte[] bin = package.GetAsByteArray();
+ /// Response.ContentType = "Application/vnd.ms-Excel";
+ /// Response.AddHeader("content-disposition", "attachment; filename=TheFile.xlsx");
+ /// Response.BinaryWrite(bin);
+ /// </code>
+ /// </example>
+ /// <returns></returns>
+ public byte[] GetAsByteArray() {
+ var result = new MemoryStream();
+ Workbook.Save();
+ Package.Save(result);
+ return result.ToArray();
+ }
+}
diff --git a/EPPlus/ExcelPrinterSettings.cs b/EPPlus/ExcelPrinterSettings.cs
index f362650..17ed052 100644
--- a/EPPlus/ExcelPrinterSettings.cs
+++ b/EPPlus/ExcelPrinterSettings.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,831 +13,761 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
-using System.Xml;
using System.Globalization;
+using System.Xml;
-namespace OfficeOpenXml
-{
- #region "Enums"
- /// <summary>
- /// Printer orientation
- /// </summary>
- public enum eOrientation
- {
- /// <summary>
- /// Portrait orientation
- /// </summary>
- Portrait,
- /// <summary>
- /// Landscape orientation
- /// </summary>
- Landscape
+namespace OfficeOpenXml;
+
+/// <summary>
+/// Printer orientation
+/// </summary>
+public enum eOrientation {
+ /// <summary>
+ /// Portrait orientation
+ /// </summary>
+ Portrait,
+
+ /// <summary>
+ /// Landscape orientation
+ /// </summary>
+ Landscape,
+}
+
+/// <summary>
+/// Papersize
+/// </summary>
+public enum ePaperSize {
+ /// <summary>
+ /// Letter paper (8.5 in. by 11 in.)
+ /// </summary>
+ Letter = 1,
+
+ /// <summary>
+ /// Letter small paper (8.5 in. by 11 in.)
+ /// </summary>
+ LetterSmall = 2,
+
+ /// <summary>
+ /// // Tabloid paper (11 in. by 17 in.)
+ /// </summary>
+ Tabloid = 3,
+
+ /// <summary>
+ /// Ledger paper (17 in. by 11 in.)
+ /// </summary>
+ Ledger = 4,
+
+ /// <summary>
+ /// Legal paper (8.5 in. by 14 in.)
+ /// </summary>
+ Legal = 5,
+
+ /// <summary>
+ /// Statement paper (5.5 in. by 8.5 in.)
+ /// </summary>
+ Statement = 6,
+
+ /// <summary>
+ /// Executive paper (7.25 in. by 10.5 in.)
+ /// </summary>
+ Executive = 7,
+
+ /// <summary>
+ /// A3 paper (297 mm by 420 mm)
+ /// </summary>
+ A3 = 8,
+
+ /// <summary>
+ /// A4 paper (210 mm by 297 mm)
+ /// </summary>
+ A4 = 9,
+
+ /// <summary>
+ /// A4 small paper (210 mm by 297 mm)
+ /// </summary>
+ A4Small = 10,
+
+ /// <summary>
+ /// A5 paper (148 mm by 210 mm)
+ /// </summary>
+ A5 = 11,
+
+ /// <summary>
+ /// B4 paper (250 mm by 353 mm)
+ /// </summary>
+ B4 = 12,
+
+ /// <summary>
+ /// B5 paper (176 mm by 250 mm)
+ /// </summary>
+ B5 = 13,
+
+ /// <summary>
+ /// Folio paper (8.5 in. by 13 in.)
+ /// </summary>
+ Folio = 14,
+
+ /// <summary>
+ /// Quarto paper (215 mm by 275 mm)
+ /// </summary>
+ Quarto = 15,
+
+ /// <summary>
+ /// Standard paper (10 in. by 14 in.)
+ /// </summary>
+ Standard1014 = 16,
+
+ /// <summary>
+ /// Standard paper (11 in. by 17 in.)
+ /// </summary>
+ Standard1117 = 17,
+
+ /// <summary>
+ /// Note paper (8.5 in. by 11 in.)
+ /// </summary>
+ Note = 18,
+
+ /// <summary>
+ /// #9 envelope (3.875 in. by 8.875 in.)
+ /// </summary>
+ Envelope9 = 19,
+
+ /// <summary>
+ /// #10 envelope (4.125 in. by 9.5 in.)
+ /// </summary>
+ Envelope10 = 20,
+
+ /// <summary>
+ /// #11 envelope (4.5 in. by 10.375 in.)
+ /// </summary>
+ Envelope11 = 21,
+
+ /// <summary>
+ /// #12 envelope (4.75 in. by 11 in.)
+ /// </summary>
+ Envelope12 = 22,
+
+ /// <summary>
+ /// #14 envelope (5 in. by 11.5 in.)
+ /// </summary>
+ Envelope14 = 23,
+
+ /// <summary>
+ /// C paper (17 in. by 22 in.)
+ /// </summary>
+ C = 24,
+
+ /// <summary>
+ /// D paper (22 in. by 34 in.)
+ /// </summary>
+ D = 25,
+
+ /// <summary>
+ /// E paper (34 in. by 44 in.)
+ /// </summary>
+ E = 26,
+
+ /// <summary>
+ /// DL envelope (110 mm by 220 mm)
+ /// </summary>
+ DlEnvelope = 27,
+
+ /// <summary>
+ /// C5 envelope (162 mm by 229 mm)
+ /// </summary>
+ C5Envelope = 28,
+
+ /// <summary>
+ /// C3 envelope (324 mm by 458 mm)
+ /// </summary>
+ C3Envelope = 29,
+
+ /// <summary>
+ /// C4 envelope (229 mm by 324 mm)
+ /// </summary>
+ C4Envelope = 30,
+
+ /// <summary>
+ /// C6 envelope (114 mm by 162 mm)
+ /// </summary>
+ C6Envelope = 31,
+
+ /// <summary>
+ /// C65 envelope (114 mm by 229 mm)
+ /// </summary>
+ C65Envelope = 32,
+
+ /// <summary>
+ /// B4 envelope (250 mm by 353 mm)
+ /// </summary>
+ B4Envelope = 33,
+
+ /// <summary>
+ /// B5 envelope (176 mm by 250 mm)
+ /// </summary>
+ B5Envelope = 34,
+
+ /// <summary>
+ /// B6 envelope (176 mm by 125 mm)
+ /// </summary>
+ B6Envelope = 35,
+
+ /// <summary>
+ /// Italy envelope (110 mm by 230 mm)
+ /// </summary>
+ ItalyEnvelope = 36,
+
+ /// <summary>
+ /// Monarch envelope (3.875 in. by 7.5 in.).
+ /// </summary>
+ MonarchEnvelope = 37,
+
+ /// <summary>
+ /// 6 3/4 envelope (3.625 in. by 6.5 in.)
+ /// </summary>
+ Six34Envelope = 38,
+
+ /// <summary>
+ /// US standard fanfold (14.875 in. by 11 in.)
+ /// </summary>
+ UsStandard = 39,
+
+ /// <summary>
+ /// German standard fanfold (8.5 in. by 12 in.)
+ /// </summary>
+ GermanStandard = 40,
+
+ /// <summary>
+ /// German legal fanfold (8.5 in. by 13 in.)
+ /// </summary>
+ GermanLegal = 41,
+
+ /// <summary>
+ /// ISO B4 (250 mm by 353 mm)
+ /// </summary>
+ Isob4 = 42,
+
+ /// <summary>
+ /// Japanese double postcard (200 mm by 148 mm)
+ /// </summary>
+ JapaneseDoublePostcard = 43,
+
+ /// <summary>
+ /// Standard paper (9 in. by 11 in.)
+ /// </summary>
+ Standard9 = 44,
+
+ /// <summary>
+ /// Standard paper (10 in. by 11 in.)
+ /// </summary>
+ Standard10 = 45,
+
+ /// <summary>
+ /// Standard paper (15 in. by 11 in.)
+ /// </summary>
+ Standard15 = 46,
+
+ /// <summary>
+ /// Invite envelope (220 mm by 220 mm)
+ /// </summary>
+ InviteEnvelope = 47,
+
+ /// <summary>
+ /// Letter extra paper (9.275 in. by 12 in.)
+ /// </summary>
+ LetterExtra = 50,
+
+ /// <summary>
+ /// Legal extra paper (9.275 in. by 15 in.)
+ /// </summary>
+ LegalExtra = 51,
+
+ /// <summary>
+ /// Tabloid extra paper (11.69 in. by 18 in.)
+ /// </summary>
+ TabloidExtra = 52,
+
+ /// <summary>
+ /// A4 extra paper (236 mm by 322 mm)
+ /// </summary>
+ A4Extra = 53,
+
+ /// <summary>
+ /// Letter transverse paper (8.275 in. by 11 in.)
+ /// </summary>
+ LetterTransverse = 54,
+
+ /// <summary>
+ /// A4 transverse paper (210 mm by 297 mm)
+ /// </summary>
+ A4Transverse = 55,
+
+ /// <summary>
+ /// Letter extra transverse paper (9.275 in. by 12 in.)
+ /// </summary>
+ LetterExtraTransverse = 56,
+
+ /// <summary>
+ /// SuperA/SuperA/A4 paper (227 mm by 356 mm)
+ /// </summary>
+ SuperA = 57,
+
+ /// <summary>
+ /// SuperB/SuperB/A3 paper (305 mm by 487 mm)
+ /// </summary>
+ SuperB = 58,
+
+ /// <summary>
+ /// Letter plus paper (8.5 in. by 12.69 in.)
+ /// </summary>
+ LetterPlus = 59,
+
+ /// <summary>
+ /// A4 plus paper (210 mm by 330 mm)
+ /// </summary>
+ A4Plus = 60,
+
+ /// <summary>
+ /// A5 transverse paper (148 mm by 210 mm)
+ /// </summary>
+ A5Transverse = 61,
+
+ /// <summary>
+ /// JIS B5 transverse paper (182 mm by 257 mm)
+ /// </summary>
+ Jisb5Transverse = 62,
+
+ /// <summary>
+ /// A3 extra paper (322 mm by 445 mm)
+ /// </summary>
+ A3Extra = 63,
+
+ /// <summary>
+ /// A5 extra paper (174 mm by 235 mm)
+ /// </summary>
+ A5Extra = 64,
+
+ /// <summary>
+ /// ISO B5 extra paper (201 mm by 276 mm)
+ /// </summary>
+ Isob5 = 65,
+
+ /// <summary>
+ /// A2 paper (420 mm by 594 mm)
+ /// </summary>
+ A2 = 66,
+
+ /// <summary>
+ /// A3 transverse paper (297 mm by 420 mm)
+ /// </summary>
+ A3Transverse = 67,
+
+ /// <summary>
+ /// A3 extra transverse paper (322 mm by 445 mm*/
+ /// </summary>
+ A3ExtraTransverse = 68,
+}
+
+/// <summary>
+/// Specifies printed page order
+/// </summary>
+public enum ePageOrder {
+ /// <summary>
+ /// Order pages vertically first, then move horizontally.
+ /// </summary>
+ DownThenOver,
+
+ /// <summary>
+ /// Order pages horizontally first, then move vertically
+ /// </summary>
+ OverThenDown,
+}
+
+/// <summary>
+/// Printer settings
+/// </summary>
+public sealed class ExcelPrinterSettings : XmlHelper {
+ private ExcelWorksheet _ws;
+ private bool _marginsCreated;
+
+ internal ExcelPrinterSettings(XmlNamespaceManager ns, XmlNode topNode, ExcelWorksheet ws)
+ : base(ns, topNode) {
+ _ws = ws;
+ SchemaNodeOrder = ws.SchemaNodeOrder;
+ }
+
+ private const string _leftMarginPath = "d:pageMargins/@left";
+
+ /// <summary>
+ /// Left margin in inches
+ /// </summary>
+ public decimal LeftMargin {
+ get => GetXmlNodeDecimal(_leftMarginPath);
+ set {
+ CreateMargins();
+ SetXmlNodeString(_leftMarginPath, value.ToString(CultureInfo.InvariantCulture));
}
- /// <summary>
- /// Papersize
- /// </summary>
- public enum ePaperSize
- {
- /// <summary>
- /// Letter paper (8.5 in. by 11 in.)
- /// </summary>
- Letter= 1,
- /// <summary>
- /// Letter small paper (8.5 in. by 11 in.)
- /// </summary>
- LetterSmall=2,
- /// <summary>
- /// // Tabloid paper (11 in. by 17 in.)
- /// </summary>
- Tabloid=3,
- /// <summary>
- /// Ledger paper (17 in. by 11 in.)
- /// </summary>
- Ledger=4,
- /// <summary>
- /// Legal paper (8.5 in. by 14 in.)
- /// </summary>
- Legal=5,
- /// <summary>
- /// Statement paper (5.5 in. by 8.5 in.)
- /// </summary>
- Statement=6,
- /// <summary>
- /// Executive paper (7.25 in. by 10.5 in.)
- /// </summary>
- Executive=7,
- /// <summary>
- /// A3 paper (297 mm by 420 mm)
- /// </summary>
- A3=8,
- /// <summary>
- /// A4 paper (210 mm by 297 mm)
- /// </summary>
- A4=9,
- /// <summary>
- /// A4 small paper (210 mm by 297 mm)
- /// </summary>
- A4Small=10,
- /// <summary>
- /// A5 paper (148 mm by 210 mm)
- /// </summary>
- A5=11,
- /// <summary>
- /// B4 paper (250 mm by 353 mm)
- /// </summary>
- B4=12,
- /// <summary>
- /// B5 paper (176 mm by 250 mm)
- /// </summary>
- B5=13,
- /// <summary>
- /// Folio paper (8.5 in. by 13 in.)
- /// </summary>
- Folio=14,
- /// <summary>
- /// Quarto paper (215 mm by 275 mm)
- /// </summary>
- Quarto=15,
- /// <summary>
- /// Standard paper (10 in. by 14 in.)
- /// </summary>
- Standard10_14=16,
- /// <summary>
- /// Standard paper (11 in. by 17 in.)
- /// </summary>
- Standard11_17=17,
- /// <summary>
- /// Note paper (8.5 in. by 11 in.)
- /// </summary>
- Note=18,
- /// <summary>
- /// #9 envelope (3.875 in. by 8.875 in.)
- /// </summary>
- Envelope9=19,
- /// <summary>
- /// #10 envelope (4.125 in. by 9.5 in.)
- /// </summary>
- Envelope10=20,
- /// <summary>
- /// #11 envelope (4.5 in. by 10.375 in.)
- /// </summary>
- Envelope11=21,
- /// <summary>
- /// #12 envelope (4.75 in. by 11 in.)
- /// </summary>
- Envelope12=22,
- /// <summary>
- /// #14 envelope (5 in. by 11.5 in.)
- /// </summary>
- Envelope14=23,
- /// <summary>
- /// C paper (17 in. by 22 in.)
- /// </summary>
- C=24,
- /// <summary>
- /// D paper (22 in. by 34 in.)
- /// </summary>
- D=25,
- /// <summary>
- /// E paper (34 in. by 44 in.)
- /// </summary>
- E=26,
- /// <summary>
- /// DL envelope (110 mm by 220 mm)
- /// </summary>
- DLEnvelope = 27,
- /// <summary>
- /// C5 envelope (162 mm by 229 mm)
- /// </summary>
- C5Envelope = 28,
- /// <summary>
- /// C3 envelope (324 mm by 458 mm)
- /// </summary>
- C3Envelope = 29,
- /// <summary>
- /// C4 envelope (229 mm by 324 mm)
- /// </summary>
- C4Envelope = 30,
- /// <summary>
- /// C6 envelope (114 mm by 162 mm)
- /// </summary>
- C6Envelope = 31,
- /// <summary>
- /// C65 envelope (114 mm by 229 mm)
- /// </summary>
- C65Envelope = 32,
- /// <summary>
- /// B4 envelope (250 mm by 353 mm)
- /// </summary>
- B4Envelope= 33,
- /// <summary>
- /// B5 envelope (176 mm by 250 mm)
- /// </summary>
- B5Envelope= 34,
- /// <summary>
- /// B6 envelope (176 mm by 125 mm)
- /// </summary>
- B6Envelope = 35,
- /// <summary>
- /// Italy envelope (110 mm by 230 mm)
- /// </summary>
- ItalyEnvelope = 36,
- /// <summary>
- /// Monarch envelope (3.875 in. by 7.5 in.).
- /// </summary>
- MonarchEnvelope = 37,
- /// <summary>
- /// 6 3/4 envelope (3.625 in. by 6.5 in.)
- /// </summary>
- Six3_4Envelope = 38,
- /// <summary>
- /// US standard fanfold (14.875 in. by 11 in.)
- /// </summary>
- USStandard=39,
- /// <summary>
- /// German standard fanfold (8.5 in. by 12 in.)
- /// </summary>
- GermanStandard=40,
- /// <summary>
- /// German legal fanfold (8.5 in. by 13 in.)
- /// </summary>
- GermanLegal=41,
- /// <summary>
- /// ISO B4 (250 mm by 353 mm)
- /// </summary>
- ISOB4=42,
- /// <summary>
- /// Japanese double postcard (200 mm by 148 mm)
- /// </summary>
- JapaneseDoublePostcard=43,
- /// <summary>
- /// Standard paper (9 in. by 11 in.)
- /// </summary>
- Standard9=44,
- /// <summary>
- /// Standard paper (10 in. by 11 in.)
- /// </summary>
- Standard10=45,
- /// <summary>
- /// Standard paper (15 in. by 11 in.)
- /// </summary>
- Standard15=46,
- /// <summary>
- /// Invite envelope (220 mm by 220 mm)
- /// </summary>
- InviteEnvelope = 47,
- /// <summary>
- /// Letter extra paper (9.275 in. by 12 in.)
- /// </summary>
- LetterExtra=50,
- /// <summary>
- /// Legal extra paper (9.275 in. by 15 in.)
- /// </summary>
- LegalExtra=51,
- /// <summary>
- /// Tabloid extra paper (11.69 in. by 18 in.)
- /// </summary>
- TabloidExtra=52,
- /// <summary>
- /// A4 extra paper (236 mm by 322 mm)
- /// </summary>
- A4Extra=53,
- /// <summary>
- /// Letter transverse paper (8.275 in. by 11 in.)
- /// </summary>
- LetterTransverse=54,
- /// <summary>
- /// A4 transverse paper (210 mm by 297 mm)
- /// </summary>
- A4Transverse=55,
- /// <summary>
- /// Letter extra transverse paper (9.275 in. by 12 in.)
- /// </summary>
- LetterExtraTransverse=56,
- /// <summary>
- /// SuperA/SuperA/A4 paper (227 mm by 356 mm)
- /// </summary>
- SuperA=57,
- /// <summary>
- /// SuperB/SuperB/A3 paper (305 mm by 487 mm)
- /// </summary>
- SuperB=58,
- /// <summary>
- /// Letter plus paper (8.5 in. by 12.69 in.)
- /// </summary>
- LetterPlus=59,
- /// <summary>
- /// A4 plus paper (210 mm by 330 mm)
- /// </summary>
- A4Plus=60,
- /// <summary>
- /// A5 transverse paper (148 mm by 210 mm)
- /// </summary>
- A5Transverse=61,
- /// <summary>
- /// JIS B5 transverse paper (182 mm by 257 mm)
- /// </summary>
- JISB5Transverse=62,
- /// <summary>
- /// A3 extra paper (322 mm by 445 mm)
- /// </summary>
- A3Extra=63,
- /// <summary>
- /// A5 extra paper (174 mm by 235 mm)
- /// </summary>
- A5Extra=64,
- /// <summary>
- /// ISO B5 extra paper (201 mm by 276 mm)
- /// </summary>
- ISOB5=65,
- /// <summary>
- /// A2 paper (420 mm by 594 mm)
- /// </summary>
- A2=66,
- /// <summary>
- /// A3 transverse paper (297 mm by 420 mm)
- /// </summary>
- A3Transverse=67,
- /// <summary>
- /// A3 extra transverse paper (322 mm by 445 mm*/
- /// </summary>
- A3ExtraTransverse = 68
+ }
+
+ private const string _rightMarginPath = "d:pageMargins/@right";
+
+ /// <summary>
+ /// Right margin in inches
+ /// </summary>
+ public decimal RightMargin {
+ get => GetXmlNodeDecimal(_rightMarginPath);
+ set {
+ CreateMargins();
+ SetXmlNodeString(_rightMarginPath, value.ToString(CultureInfo.InvariantCulture));
}
- /// <summary>
- /// Specifies printed page order
- /// </summary>
- public enum ePageOrder
- {
+ }
- /// <summary>
- /// Order pages vertically first, then move horizontally.
- /// </summary>
- DownThenOver,
- /// <summary>
- /// Order pages horizontally first, then move vertically
- /// </summary>
- OverThenDown
+ private const string _topMarginPath = "d:pageMargins/@top";
+
+ /// <summary>
+ /// Top margin in inches
+ /// </summary>
+ public decimal TopMargin {
+ get => GetXmlNodeDecimal(_topMarginPath);
+ set {
+ CreateMargins();
+ SetXmlNodeString(_topMarginPath, value.ToString(CultureInfo.InvariantCulture));
}
- #endregion
- /// <summary>
- /// Printer settings
- /// </summary>
- public sealed class ExcelPrinterSettings : XmlHelper
- {
- ExcelWorksheet _ws;
- bool _marginsCreated = false;
+ }
- internal ExcelPrinterSettings(XmlNamespaceManager ns, XmlNode topNode,ExcelWorksheet ws) :
- base(ns, topNode)
- {
- _ws = ws;
- SchemaNodeOrder = ws.SchemaNodeOrder;
- }
- const string _leftMarginPath = "d:pageMargins/@left";
- /// <summary>
- /// Left margin in inches
- /// </summary>
- public decimal LeftMargin
- {
- get
- {
- return GetXmlNodeDecimal(_leftMarginPath);
- }
- set
- {
- CreateMargins();
- SetXmlNodeString(_leftMarginPath, value.ToString(CultureInfo.InvariantCulture));
- }
- }
- const string _rightMarginPath = "d:pageMargins/@right";
- /// <summary>
- /// Right margin in inches
- /// </summary>
- public decimal RightMargin
- {
- get
- {
- return GetXmlNodeDecimal(_rightMarginPath);
- }
- set
- {
- CreateMargins();
- SetXmlNodeString(_rightMarginPath, value.ToString(CultureInfo.InvariantCulture));
- }
- }
- const string _topMarginPath = "d:pageMargins/@top";
- /// <summary>
- /// Top margin in inches
- /// </summary>
- public decimal TopMargin
- {
- get
- {
- return GetXmlNodeDecimal(_topMarginPath);
- }
- set
- {
- CreateMargins();
- SetXmlNodeString(_topMarginPath, value.ToString(CultureInfo.InvariantCulture));
- }
- }
- const string _bottomMarginPath = "d:pageMargins/@bottom";
- /// <summary>
- /// Bottom margin in inches
- /// </summary>
- public decimal BottomMargin
- {
- get
- {
- return GetXmlNodeDecimal(_bottomMarginPath);
- }
- set
- {
- CreateMargins();
- SetXmlNodeString(_bottomMarginPath, value.ToString(CultureInfo.InvariantCulture));
- }
- }
- const string _headerMarginPath = "d:pageMargins/@header";
- /// <summary>
- /// Header margin in inches
- /// </summary>
- public decimal HeaderMargin
- {
- get
- {
- return GetXmlNodeDecimal(_headerMarginPath);
- }
- set
- {
- CreateMargins();
- SetXmlNodeString(_headerMarginPath, value.ToString(CultureInfo.InvariantCulture));
- }
- }
- const string _footerMarginPath = "d:pageMargins/@footer";
- /// <summary>
- /// Footer margin in inches
- /// </summary>
- public decimal FooterMargin
- {
- get
- {
- return GetXmlNodeDecimal(_footerMarginPath);
- }
- set
- {
- CreateMargins();
- SetXmlNodeString(_footerMarginPath, value.ToString(CultureInfo.InvariantCulture));
- }
- }
- const string _orientationPath = "d:pageSetup/@orientation";
- /// <summary>
- /// Orientation
- /// Portrait or Landscape
- /// </summary>
- public eOrientation Orientation
- {
- get
- {
- return (eOrientation)Enum.Parse(typeof(eOrientation), GetXmlNodeString(_orientationPath), true);
- }
- set
- {
- SetXmlNodeString(_orientationPath, value.ToString().ToLower(CultureInfo.InvariantCulture));
- }
- }
- const string _fitToWidthPath = "d:pageSetup/@fitToWidth";
- /// <summary>
- /// Fit to Width in pages.
- /// Set FitToPage to true when using this one.
- /// 0 is automatic
- /// </summary>
- public int FitToWidth
- {
- get
- {
- return GetXmlNodeInt(_fitToWidthPath);
- }
- set
- {
- SetXmlNodeString(_fitToWidthPath, value.ToString());
- }
- }
- const string _fitToHeightPath = "d:pageSetup/@fitToHeight";
- /// <summary>
- /// Fit to height in pages.
- /// Set FitToPage to true when using this one.
- /// 0 is automatic
- /// </summary>
- public int FitToHeight
- {
- get
- {
- return GetXmlNodeInt(_fitToHeightPath);
- }
- set
- {
- SetXmlNodeString(_fitToHeightPath, value.ToString());
- }
- }
- const string _scalePath = "d:pageSetup/@scale";
- /// <summary>
- /// Print scale
- /// </summary>
- public int Scale
- {
- get
- {
- return GetXmlNodeInt(_scalePath);
- }
- set
- {
- SetXmlNodeString(_scalePath, value.ToString());
- }
- }
- const string _fitToPagePath = "d:sheetPr/d:pageSetUpPr/@fitToPage";
- /// <summary>
- /// Fit To Page.
- /// </summary>
- public bool FitToPage
- {
- get
- {
- return GetXmlNodeBool(_fitToPagePath);
- }
- set
- {
- SetXmlNodeString(_fitToPagePath, value ? "1" : "0");
- }
- }
- const string _headersPath = "d:printOptions/@headings";
- /// <summary>
- /// Print headings (column letter and row numbers)
- /// </summary>
- public bool ShowHeaders
- {
- get
- {
- return GetXmlNodeBool(_headersPath, false);
- }
- set
- {
- SetXmlNodeBool(_headersPath, value, false);
- }
- }
- /// <summary>
- /// Print titles
- /// Rows to be repeated after each pagebreak.
- /// The address must be a full row address (ex. 1:1)
- /// </summary>
- public ExcelAddress RepeatRows
- {
- get
- {
- if (_ws.Names.ContainsKey("_xlnm.Print_Titles"))
- {
- ExcelRangeBase r = _ws.Names["_xlnm.Print_Titles"] as ExcelRangeBase;
- if (r.Start.Column == 1 && r.End.Column == ExcelPackage.MaxColumns)
- {
- return new ExcelAddress(r.FirstAddress);
- }
- else if (r._addresses != null && r.Addresses[0].Start.Column == 1 && r.Addresses[0].End.Column == ExcelPackage.MaxColumns)
- {
- return r._addresses[0];
- }
- else
- {
- return null;
- }
- }
- else
- {
- return null;
- }
- }
- set
- {
+ private const string _bottomMarginPath = "d:pageMargins/@bottom";
- //Must span entire columns
- if (!(value.Start.Column == 1 && value.End.Column == ExcelPackage.MaxColumns))
- {
- throw new InvalidOperationException("Address must span full columns only (for ex. Address=\"A:A\" for the first column).");
- }
-
- var vertAddr = RepeatColumns;
- string addr;
- if (vertAddr == null)
- {
- addr = value.Address;
- }
- else
- {
- addr = vertAddr.Address + "," + value.Address;
- }
-
- if (_ws.Names.ContainsKey("_xlnm.Print_Titles"))
- {
- _ws.Names["_xlnm.Print_Titles"].Address = addr;
- }
- else
- {
- _ws.Names.Add("_xlnm.Print_Titles", new ExcelRangeBase(_ws, addr));
- }
- }
- }
- /// <summary>
- /// Print titles
- /// Columns to be repeated after each pagebreak.
- /// The address must be a full column address (ex. A:A)
- /// </summary>
- public ExcelAddress RepeatColumns
- {
- get
- {
- if (_ws.Names.ContainsKey("_xlnm.Print_Titles"))
- {
- ExcelRangeBase r = _ws.Names["_xlnm.Print_Titles"] as ExcelRangeBase;
- if (r.Start.Row == 1 && r.End.Row == ExcelPackage.MaxRows)
- {
- return new ExcelAddress(r.FirstAddress);
- }
- else if (r._addresses != null && (r._addresses[0].Start.Row == 1 && r._addresses[0].End.Row == ExcelPackage.MaxRows))
- {
- return r._addresses[0];
- }
- else
- {
- return null;
- }
- }
- else
- {
- return null;
- }
- }
- set
- {
- //Must span entire rows
- if (!(value.Start.Row == 1 && value.End.Row== ExcelPackage.MaxRows))
- {
- throw new InvalidOperationException("Address must span rows only (for ex. Address=\"1:1\" for the first row).");
- }
-
- var horAddr = RepeatRows;
- string addr;
- if (horAddr == null)
- {
- addr = value.Address;
- }
- else
- {
- addr = value.Address + "," + horAddr.Address;
- }
-
- if (_ws.Names.ContainsKey("_xlnm.Print_Titles"))
- {
- _ws.Names["_xlnm.Print_Titles"].Address = addr;
- }
- else
- {
- _ws.Names.Add("_xlnm.Print_Titles", new ExcelRangeBase(_ws, addr));
- }
- }
- }
- /// <summary>
- /// The printarea.
- /// Null if no print area is set.
- /// </summary>
- public ExcelRangeBase PrintArea
- {
- get
- {
- if (_ws.Names.ContainsKey("_xlnm.Print_Area"))
- {
- return _ws.Names["_xlnm.Print_Area"];
- }
- else
- {
- return null;
- }
- }
- set
- {
- if (value == null)
- {
- _ws.Names.Remove("_xlnm.Print_Area");
- }
- else if (_ws.Names.ContainsKey("_xlnm.Print_Area"))
- {
- _ws.Names["_xlnm.Print_Area"].Address = value.Address;
- }
- else
- {
- _ws.Names.Add("_xlnm.Print_Area", value);
- }
- }
- }
- const string _gridLinesPath = "d:printOptions/@gridLines";
- /// <summary>
- /// Print gridlines
- /// </summary>
- public bool ShowGridLines
- {
- get
- {
- return GetXmlNodeBool(_gridLinesPath, false);
- }
- set
- {
- SetXmlNodeBool(_gridLinesPath, value, false);
- }
- }
- const string _horizontalCenteredPath = "d:printOptions/@horizontalCentered";
- /// <summary>
- /// Horizontal centered when printing
- /// </summary>w
- public bool HorizontalCentered
- {
- get
- {
- return GetXmlNodeBool(_horizontalCenteredPath, false);
- }
- set
- {
- SetXmlNodeBool(_horizontalCenteredPath, value, false);
- }
- }
- const string _verticalCenteredPath = "d:printOptions/@verticalCentered";
- /// <summary>
- /// Vertical centered when printing
- /// </summary>
- public bool VerticalCentered
- {
- get
- {
- return GetXmlNodeBool(_verticalCenteredPath, false);
- }
- set
- {
- SetXmlNodeBool(_verticalCenteredPath, value, false);
- }
- }
- const string _pageOrderPath = "d:pageSetup/@pageOrder";
- /// <summary>
- /// Specifies printed page order
- /// </summary>
- public ePageOrder PageOrder
- {
- get
- {
- if (GetXmlNodeString(_pageOrderPath) == "overThenDown")
- {
- return ePageOrder.OverThenDown;
- }
- else
- {
- return ePageOrder.DownThenOver;
- }
- }
- set
- {
- if (value == ePageOrder.OverThenDown)
- {
- SetXmlNodeString(_pageOrderPath, "overThenDown");
- }
- else
- {
- DeleteNode(_pageOrderPath);
- }
- }
- }
- const string _blackAndWhitePath = "d:pageSetup/@blackAndWhite";
- /// <summary>
- /// Print black and white
- /// </summary>
- public bool BlackAndWhite
- {
- get
- {
- return GetXmlNodeBool(_blackAndWhitePath, false);
- }
- set
- {
- SetXmlNodeBool(_blackAndWhitePath, value, false);
- }
- }
- const string _draftPath = "d:pageSetup/@draft";
- /// <summary>
- /// Print a draft
- /// </summary>
- public bool Draft
- {
- get
- {
- return GetXmlNodeBool(_draftPath, false);
- }
- set
- {
- SetXmlNodeBool(_draftPath, value, false);
- }
- }
- const string _paperSizePath = "d:pageSetup/@paperSize";
- /// <summary>
- /// Paper size
- /// </summary>
- public ePaperSize PaperSize
- {
- get
- {
- string s = GetXmlNodeString(_paperSizePath);
- if (s != "")
- {
- return (ePaperSize)int.Parse(s);
- }
- else
- {
- return ePaperSize.Letter;
-
- }
- }
- set
- {
- SetXmlNodeString(_paperSizePath, ((int)value).ToString());
- }
- }
- /// <summary>
- /// All or none of the margin attributes must exist. Create all att ones.
- /// </summary>
- private void CreateMargins()
- {
- if (_marginsCreated==false && TopNode.SelectSingleNode(_leftMarginPath, NameSpaceManager) == null)
- {
- _marginsCreated=true;
- LeftMargin = 0.7087M;
- RightMargin = 0.7087M;
- TopMargin = 0.7480M;
- BottomMargin = 0.7480M;
- HeaderMargin = 0.315M;
- FooterMargin = 0.315M;
- }
- }
+ /// <summary>
+ /// Bottom margin in inches
+ /// </summary>
+ public decimal BottomMargin {
+ get => GetXmlNodeDecimal(_bottomMarginPath);
+ set {
+ CreateMargins();
+ SetXmlNodeString(_bottomMarginPath, value.ToString(CultureInfo.InvariantCulture));
}
+ }
+
+ private const string _headerMarginPath = "d:pageMargins/@header";
+
+ /// <summary>
+ /// Header margin in inches
+ /// </summary>
+ public decimal HeaderMargin {
+ get => GetXmlNodeDecimal(_headerMarginPath);
+ set {
+ CreateMargins();
+ SetXmlNodeString(_headerMarginPath, value.ToString(CultureInfo.InvariantCulture));
+ }
+ }
+
+ private const string _footerMarginPath = "d:pageMargins/@footer";
+
+ /// <summary>
+ /// Footer margin in inches
+ /// </summary>
+ public decimal FooterMargin {
+ get => GetXmlNodeDecimal(_footerMarginPath);
+ set {
+ CreateMargins();
+ SetXmlNodeString(_footerMarginPath, value.ToString(CultureInfo.InvariantCulture));
+ }
+ }
+
+ private const string _orientationPath = "d:pageSetup/@orientation";
+
+ /// <summary>
+ /// Orientation
+ /// Portrait or Landscape
+ /// </summary>
+ public eOrientation Orientation {
+ get => (eOrientation)Enum.Parse(typeof(eOrientation), GetXmlNodeString(_orientationPath), true);
+ set =>
+ SetXmlNodeString(_orientationPath, value.ToString().ToLower(CultureInfo.InvariantCulture));
+ }
+
+ private const string _fitToWidthPath = "d:pageSetup/@fitToWidth";
+
+ /// <summary>
+ /// Fit to Width in pages.
+ /// Set FitToPage to true when using this one.
+ /// 0 is automatic
+ /// </summary>
+ public int FitToWidth {
+ get => GetXmlNodeInt(_fitToWidthPath);
+ set => SetXmlNodeString(_fitToWidthPath, value.ToString());
+ }
+
+ private const string _fitToHeightPath = "d:pageSetup/@fitToHeight";
+
+ /// <summary>
+ /// Fit to height in pages.
+ /// Set FitToPage to true when using this one.
+ /// 0 is automatic
+ /// </summary>
+ public int FitToHeight {
+ get => GetXmlNodeInt(_fitToHeightPath);
+ set => SetXmlNodeString(_fitToHeightPath, value.ToString());
+ }
+
+ private const string _scalePath = "d:pageSetup/@scale";
+
+ /// <summary>
+ /// Print scale
+ /// </summary>
+ public int Scale {
+ get => GetXmlNodeInt(_scalePath);
+ set => SetXmlNodeString(_scalePath, value.ToString());
+ }
+
+ private const string _fitToPagePath = "d:sheetPr/d:pageSetUpPr/@fitToPage";
+
+ /// <summary>
+ /// Fit To Page.
+ /// </summary>
+ public bool FitToPage {
+ get => GetXmlNodeBool(_fitToPagePath);
+ set => SetXmlNodeString(_fitToPagePath, value ? "1" : "0");
+ }
+
+ private const string _headersPath = "d:printOptions/@headings";
+
+ /// <summary>
+ /// Print headings (column letter and row numbers)
+ /// </summary>
+ public bool ShowHeaders {
+ get => GetXmlNodeBool(_headersPath, false);
+ set => SetXmlNodeBool(_headersPath, value, false);
+ }
+
+ /// <summary>
+ /// Print titles
+ /// Rows to be repeated after each pagebreak.
+ /// The address must be a full row address (ex. 1:1)
+ /// </summary>
+ public ExcelAddress RepeatRows {
+ get {
+ if (_ws.Names.ContainsKey("_xlnm.Print_Titles")) {
+ ExcelRangeBase r = _ws.Names["_xlnm.Print_Titles"];
+ if (r.Start.Column == 1 && r.End.Column == ExcelPackage.MaxColumns) {
+ return new(r.FirstAddress);
+ }
+ if (r._addresses != null
+ && r.Addresses[0].Start.Column == 1
+ && r.Addresses[0].End.Column == ExcelPackage.MaxColumns) {
+ return r._addresses[0];
+ }
+ return null;
+ }
+ return null;
+ }
+ set {
+ //Must span entire columns
+ if (!(value.Start.Column == 1 && value.End.Column == ExcelPackage.MaxColumns)) {
+ throw new InvalidOperationException(
+ "Address must span full columns only (for ex. Address=\"A:A\" for the first column).");
+ }
+
+ var vertAddr = RepeatColumns;
+ string addr;
+ if (vertAddr == null) {
+ addr = value.Address;
+ } else {
+ addr = vertAddr.Address + "," + value.Address;
+ }
+
+ if (_ws.Names.ContainsKey("_xlnm.Print_Titles")) {
+ _ws.Names["_xlnm.Print_Titles"].Address = addr;
+ } else {
+ _ws.Names.Add("_xlnm.Print_Titles", new(_ws, addr));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Print titles
+ /// Columns to be repeated after each pagebreak.
+ /// The address must be a full column address (ex. A:A)
+ /// </summary>
+ public ExcelAddress RepeatColumns {
+ get {
+ if (_ws.Names.ContainsKey("_xlnm.Print_Titles")) {
+ ExcelRangeBase r = _ws.Names["_xlnm.Print_Titles"];
+ if (r.Start.Row == 1 && r.End.Row == ExcelPackage.MaxRows) {
+ return new(r.FirstAddress);
+ }
+ if (r._addresses != null
+ && (r._addresses[0].Start.Row == 1
+ && r._addresses[0].End.Row == ExcelPackage.MaxRows)) {
+ return r._addresses[0];
+ }
+ return null;
+ }
+ return null;
+ }
+ set {
+ //Must span entire rows
+ if (!(value.Start.Row == 1 && value.End.Row == ExcelPackage.MaxRows)) {
+ throw new InvalidOperationException(
+ "Address must span rows only (for ex. Address=\"1:1\" for the first row).");
+ }
+
+ var horAddr = RepeatRows;
+ string addr;
+ if (horAddr == null) {
+ addr = value.Address;
+ } else {
+ addr = value.Address + "," + horAddr.Address;
+ }
+
+ if (_ws.Names.ContainsKey("_xlnm.Print_Titles")) {
+ _ws.Names["_xlnm.Print_Titles"].Address = addr;
+ } else {
+ _ws.Names.Add("_xlnm.Print_Titles", new(_ws, addr));
+ }
+ }
+ }
+
+ /// <summary>
+ /// The printarea.
+ /// Null if no print area is set.
+ /// </summary>
+ public ExcelRangeBase PrintArea {
+ get {
+ if (_ws.Names.ContainsKey("_xlnm.Print_Area")) {
+ return _ws.Names["_xlnm.Print_Area"];
+ }
+ return null;
+ }
+ set {
+ if (value == null) {
+ _ws.Names.Remove("_xlnm.Print_Area");
+ } else if (_ws.Names.ContainsKey("_xlnm.Print_Area")) {
+ _ws.Names["_xlnm.Print_Area"].Address = value.Address;
+ } else {
+ _ws.Names.Add("_xlnm.Print_Area", value);
+ }
+ }
+ }
+
+ private const string _gridLinesPath = "d:printOptions/@gridLines";
+
+ /// <summary>
+ /// Print gridlines
+ /// </summary>
+ public bool ShowGridLines {
+ get => GetXmlNodeBool(_gridLinesPath, false);
+ set => SetXmlNodeBool(_gridLinesPath, value, false);
+ }
+
+ private const string _horizontalCenteredPath = "d:printOptions/@horizontalCentered";
+
+ /// <summary>
+ /// Horizontal centered when printing
+ /// </summary>w
+ public bool HorizontalCentered {
+ get => GetXmlNodeBool(_horizontalCenteredPath, false);
+ set => SetXmlNodeBool(_horizontalCenteredPath, value, false);
+ }
+
+ private const string _verticalCenteredPath = "d:printOptions/@verticalCentered";
+
+ /// <summary>
+ /// Vertical centered when printing
+ /// </summary>
+ public bool VerticalCentered {
+ get => GetXmlNodeBool(_verticalCenteredPath, false);
+ set => SetXmlNodeBool(_verticalCenteredPath, value, false);
+ }
+
+ private const string _pageOrderPath = "d:pageSetup/@pageOrder";
+
+ /// <summary>
+ /// Specifies printed page order
+ /// </summary>
+ public ePageOrder PageOrder {
+ get {
+ if (GetXmlNodeString(_pageOrderPath) == "overThenDown") {
+ return ePageOrder.OverThenDown;
+ }
+ return ePageOrder.DownThenOver;
+ }
+ set {
+ if (value == ePageOrder.OverThenDown) {
+ SetXmlNodeString(_pageOrderPath, "overThenDown");
+ } else {
+ DeleteNode(_pageOrderPath);
+ }
+ }
+ }
+
+ private const string _blackAndWhitePath = "d:pageSetup/@blackAndWhite";
+
+ /// <summary>
+ /// Print black and white
+ /// </summary>
+ public bool BlackAndWhite {
+ get => GetXmlNodeBool(_blackAndWhitePath, false);
+ set => SetXmlNodeBool(_blackAndWhitePath, value, false);
+ }
+
+ private const string _draftPath = "d:pageSetup/@draft";
+
+ /// <summary>
+ /// Print a draft
+ /// </summary>
+ public bool Draft {
+ get => GetXmlNodeBool(_draftPath, false);
+ set => SetXmlNodeBool(_draftPath, value, false);
+ }
+
+ private const string _paperSizePath = "d:pageSetup/@paperSize";
+
+ /// <summary>
+ /// Paper size
+ /// </summary>
+ public ePaperSize PaperSize {
+ get {
+ string s = GetXmlNodeString(_paperSizePath);
+ if (s != "") {
+ return (ePaperSize)int.Parse(s);
+ }
+ return ePaperSize.Letter;
+ }
+ set => SetXmlNodeString(_paperSizePath, ((int)value).ToString());
+ }
+
+ /// <summary>
+ /// All or none of the margin attributes must exist. Create all att ones.
+ /// </summary>
+ private void CreateMargins() {
+ if (_marginsCreated == false
+ && TopNode.SelectSingleNode(_leftMarginPath, NameSpaceManager) == null) {
+ _marginsCreated = true;
+ LeftMargin = 0.7087M;
+ RightMargin = 0.7087M;
+ TopMargin = 0.7480M;
+ BottomMargin = 0.7480M;
+ HeaderMargin = 0.315M;
+ FooterMargin = 0.315M;
+ }
+ }
}
diff --git a/EPPlus/ExcelProtectedRange.cs b/EPPlus/ExcelProtectedRange.cs
index bb66945..ef0da39 100644
--- a/EPPlus/ExcelProtectedRange.cs
+++ b/EPPlus/ExcelProtectedRange.cs
@@ -1,44 +1,35 @@
-using OfficeOpenXml.Utils;
using System.Xml;
+using OfficeOpenXml.Utils;
-namespace OfficeOpenXml
-{
- public class ExcelProtectedRange : XmlHelper
- {
- public string Name
- {
- get
- {
- return GetXmlNodeString("@name");
- }
- set
- {
- SetXmlNodeString("@name",value);
- }
- }
- ExcelAddress _address=null;
- public ExcelAddress Address
- {
- get
- {
- if(_address==null)
- {
- _address=new ExcelAddress(GetXmlNodeString("@sqref"));
- }
- return _address;
- }
- set
- {
- SetXmlNodeString("@sqref", SqRefUtility.ToSqRefAddress(value.Address));
- _address=value;
- }
- }
+namespace OfficeOpenXml;
- internal ExcelProtectedRange(string name, ExcelAddress address, XmlNamespaceManager ns, XmlNode topNode) :
- base(ns,topNode)
- {
- Name = name;
- Address = address;
- }
+public class ExcelProtectedRange : XmlHelper {
+ public string Name {
+ get => GetXmlNodeString("@name");
+ set => SetXmlNodeString("@name", value);
+ }
+
+ private ExcelAddress _address;
+ public ExcelAddress Address {
+ get {
+ if (_address == null) {
+ _address = new(GetXmlNodeString("@sqref"));
+ }
+ return _address;
}
+ set {
+ SetXmlNodeString("@sqref", SqRefUtility.ToSqRefAddress(value.Address));
+ _address = value;
+ }
+ }
+
+ internal ExcelProtectedRange(
+ string name,
+ ExcelAddress address,
+ XmlNamespaceManager ns,
+ XmlNode topNode)
+ : base(ns, topNode) {
+ Name = name;
+ Address = address;
+ }
}
diff --git a/EPPlus/ExcelProtectedRangeCollection.cs b/EPPlus/ExcelProtectedRangeCollection.cs
index 9285975..72afcc3 100644
--- a/EPPlus/ExcelProtectedRangeCollection.cs
+++ b/EPPlus/ExcelProtectedRangeCollection.cs
@@ -1,94 +1,89 @@
-using OfficeOpenXml.Utils;
-using System;
+using System.Collections;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Linq;
-using System.Text;
using System.Xml;
+using OfficeOpenXml.Utils;
-namespace OfficeOpenXml
-{
- public class ExcelProtectedRangeCollection : XmlHelper, IEnumerable<ExcelProtectedRange>
- {
- internal ExcelProtectedRangeCollection(XmlNamespaceManager nsm, XmlNode topNode, ExcelWorksheet ws)
- : base(nsm, topNode)
- {
- foreach (XmlNode protectedRangeNode in topNode.SelectNodes("d:protectedRanges/d:protectedRange", nsm))
- {
- if (!(protectedRangeNode is XmlElement))
- continue;
- _baseList.Add(new ExcelProtectedRange(protectedRangeNode.Attributes["name"].Value, new ExcelAddress(SqRefUtility.FromSqRefAddress(protectedRangeNode.Attributes["sqref"].Value)), nsm, topNode));
- }
- }
+namespace OfficeOpenXml;
- private List<ExcelProtectedRange> _baseList = new List<ExcelProtectedRange>();
-
- public ExcelProtectedRange Add(string name, ExcelAddress address)
- {
- if (!ExistNode("d:protectedRanges"))
- CreateNode("d:protectedRanges");
-
- var newNode = CreateNode("d:protectedRanges/d:protectedRange");
- var item = new ExcelProtectedRange(name, address, base.NameSpaceManager, newNode);
- _baseList.Add(item);
- return item;
- }
-
- public void Clear()
- {
- DeleteNode("d:protectedRanges");
- _baseList.Clear();
- }
-
- public bool Contains(ExcelProtectedRange item)
- {
- return _baseList.Contains(item);
- }
-
- public void CopyTo(ExcelProtectedRange[] array, int arrayIndex)
- {
- _baseList.CopyTo(array, arrayIndex);
- }
-
- public int Count
- {
- get { return _baseList.Count; }
- }
-
- public bool Remove(ExcelProtectedRange item)
- {
- DeleteAllNode("d:protectedRanges/d:protectedRange[@name='" + item.Name + "' and @sqref='" + item.Address.Address + "']");
- if (_baseList.Count == 0)
- DeleteNode("d:protectedRanges");
- return _baseList.Remove(item);
- }
-
- public int IndexOf(ExcelProtectedRange item)
- {
- return _baseList.IndexOf(item);
- }
-
- public void RemoveAt(int index)
- {
- _baseList.RemoveAt(index);
- }
-
- public ExcelProtectedRange this[int index]
- {
- get
- {
- return _baseList[index];
- }
- }
-
- IEnumerator<ExcelProtectedRange> IEnumerable<ExcelProtectedRange>.GetEnumerator()
- {
- return _baseList.GetEnumerator();
- }
-
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return _baseList.GetEnumerator();
- }
+public class ExcelProtectedRangeCollection : XmlHelper, IEnumerable<ExcelProtectedRange> {
+ internal ExcelProtectedRangeCollection(
+ XmlNamespaceManager nsm,
+ XmlNode topNode,
+ ExcelWorksheet ws)
+ : base(nsm, topNode) {
+ foreach (XmlNode protectedRangeNode in topNode.SelectNodes(
+ "d:protectedRanges/d:protectedRange",
+ nsm)) {
+ if (!(protectedRangeNode is XmlElement)) {
+ continue;
+ }
+ _baseList.Add(
+ new(
+ protectedRangeNode.Attributes["name"].Value,
+ new(SqRefUtility.FromSqRefAddress(protectedRangeNode.Attributes["sqref"].Value)),
+ nsm,
+ topNode));
}
+ }
+
+ private List<ExcelProtectedRange> _baseList = new();
+
+ public ExcelProtectedRange Add(string name, ExcelAddress address) {
+ if (!ExistNode("d:protectedRanges")) {
+ CreateNode("d:protectedRanges");
+ }
+
+ var newNode = CreateNode("d:protectedRanges/d:protectedRange");
+ var item = new ExcelProtectedRange(name, address, NameSpaceManager, newNode);
+ _baseList.Add(item);
+ return item;
+ }
+
+ public void Clear() {
+ DeleteNode("d:protectedRanges");
+ _baseList.Clear();
+ }
+
+ public bool Contains(ExcelProtectedRange item) {
+ return _baseList.Contains(item);
+ }
+
+ public void CopyTo(ExcelProtectedRange[] array, int arrayIndex) {
+ _baseList.CopyTo(array, arrayIndex);
+ }
+
+ public int Count => _baseList.Count;
+
+ public bool Remove(ExcelProtectedRange item) {
+ DeleteAllNode(
+ "d:protectedRanges/d:protectedRange[@name='"
+ + item.Name
+ + "' and @sqref='"
+ + item.Address.Address
+ + "']");
+ if (_baseList.Count == 0) {
+ DeleteNode("d:protectedRanges");
+ }
+ return _baseList.Remove(item);
+ }
+
+ public int IndexOf(ExcelProtectedRange item) {
+ return _baseList.IndexOf(item);
+ }
+
+ public void RemoveAt(int index) {
+ _baseList.RemoveAt(index);
+ }
+
+ public ExcelProtectedRange this[int index] {
+ get { return _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
index 6e307a3..bf10612 100644
--- a/EPPlus/ExcelProtection.cs
+++ b/EPPlus/ExcelProtection.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,82 +13,65 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Xml;
-namespace OfficeOpenXml
-{
- /// <summary>
- /// Sets protection on the workbook level
- ///<seealso cref="ExcelEncryption"/>
- ///<seealso cref="ExcelSheetProtection"/>
- /// </summary>
- public class ExcelProtection : XmlHelper
- {
- internal ExcelProtection(XmlNamespaceManager ns, XmlNode topNode, ExcelWorkbook wb) :
- base(ns, topNode)
- {
- SchemaNodeOrder = wb.SchemaNodeOrder;
- }
- 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
- {
- return GetXmlNodeBool(lockStructurePath, false);
- }
- set
- {
- SetXmlNodeBool(lockStructurePath, value, false);
- }
- }
- const string lockWindowsPath = "d:workbookProtection/@lockWindows";
- /// <summary>
- /// Locks the position of the workbook window.
- /// </summary>
- public bool LockWindows
- {
- get
- {
- return GetXmlNodeBool(lockWindowsPath, false);
- }
- set
- {
- SetXmlNodeBool(lockWindowsPath, value, false);
- }
- }
- const string lockRevisionPath = "d:workbookProtection/@lockRevision";
- /// <summary>
- /// Lock the workbook for revision
- /// </summary>
- public bool LockRevision
- {
- get
- {
- return GetXmlNodeBool(lockRevisionPath, false);
- }
- set
- {
- SetXmlNodeBool(lockRevisionPath, value, false);
- }
- }
- }
+using System.Xml;
+
+namespace OfficeOpenXml;
+
+/// <summary>
+/// Sets protection on the workbook level
+///<seealso cref="ExcelEncryption"/>
+///<seealso cref="ExcelSheetProtection"/>
+/// </summary>
+public class ExcelProtection : XmlHelper {
+ internal ExcelProtection(XmlNamespaceManager ns, XmlNode topNode, ExcelWorkbook wb)
+ : base(ns, topNode) {
+ SchemaNodeOrder = wb.SchemaNodeOrder;
+ }
+
+ 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
index 8396c9d..92352fc 100644
--- a/EPPlus/ExcelRange.cs
+++ b/EPPlus/ExcelRange.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,155 +13,111 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
-using OfficeOpenXml.Style;
-using System.Data;
-namespace OfficeOpenXml
-{
- /// <summary>
- /// A range of cells.
- /// </summary>
- public class ExcelRange : ExcelRangeBase
- {
- #region "Constructors"
- internal ExcelRange(ExcelWorksheet sheet) :
- base(sheet)
- {
- }
- internal ExcelRange(ExcelWorksheet sheet, string address)
- : base(sheet, address)
- {
+namespace OfficeOpenXml;
- }
- internal ExcelRange(ExcelWorksheet sheet, int fromRow, int fromCol, int toRow, int toCol)
- : base(sheet)
- {
- _fromRow = fromRow;
- _fromCol = fromCol;
- _toRow = toRow;
- _toCol = toCol;
- }
- #endregion
- #region "Indexers"
- /// <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;
- }
- else
- {
- base.Address = _worksheet.Names[Address].Address;
- }
- }
- else
- {
- base.Address = Address;
- }
- return this;
- }
- }
+/// <summary>
+/// A range of cells.
+/// </summary>
+public class ExcelRange : ExcelRangeBase {
+ internal ExcelRange(ExcelWorksheet sheet)
+ : base(sheet) {}
- private ExcelRange GetTableAddess(ExcelWorksheet _worksheet, string address)
- {
- int ixStart = address.IndexOf('[');
- if (ixStart == 0) //External Address
- {
- int ixEnd = address.IndexOf(']',ixStart+1);
- if (ixStart >= 0 & ixEnd >= 0)
- {
- var external = address.Substring(ixStart + 1, ixEnd - 1);
- //if (Worksheet.Workbook._externalReferences.Count < external)
- //{
- //foreach(var
- //}
- }
- }
- return null;
- }
- /// <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);
+ internal ExcelRange(ExcelWorksheet sheet, string address)
+ : base(sheet, address) {}
- _fromCol = Col;
- _fromRow = Row;
- _toCol = Col;
- _toRow = Row;
- base.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);
+ internal ExcelRange(ExcelWorksheet sheet, int fromRow, int fromCol, int toRow, int toCol)
+ : base(sheet) {
+ _fromRow = fromRow;
+ _fromCol = fromCol;
+ _toRow = toRow;
+ _toCol = toCol;
+ }
- _fromCol = FromCol;
- _fromRow = FromRow;
- _toCol = ToCol;
- _toRow = ToRow;
- base.Address = GetAddress(_fromRow, _fromCol, _toRow, _toCol);
- return this;
- }
+ /// <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;
}
- #endregion
- 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"));
- }
- }
-
+ 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
index a4cf198..fd753d6 100644
--- a/EPPlus/ExcelRangeBase.cs
+++ b/EPPlus/ExcelRangeBase.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,2750 +13,2409 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.ComponentModel;
-using System.Text;
using System.Data;
-using System.Threading;
-using OfficeOpenXml.FormulaParsing;
-using OfficeOpenXml.Style;
-using System.Xml;
-using System.Drawing;
using System.Globalization;
-using System.Collections;
-using OfficeOpenXml.Table;
-using System.Text.RegularExpressions;
using System.IO;
using System.Linq;
-using OfficeOpenXml.DataValidation;
-using OfficeOpenXml.DataValidation.Contracts;
using System.Reflection;
-using OfficeOpenXml.Style.XmlAccess;
using System.Security;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Xml;
using OfficeOpenXml.ConditionalFormatting;
-using OfficeOpenXml.ConditionalFormatting.Contracts;
+using OfficeOpenXml.DataValidation;
using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-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 = null;
- private delegate void _changeProp(_setValue method, object value);
- private delegate void _setValue(object value, int row, int col);
- private _changeProp _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; }
- //}
- #region Constructors
- internal ExcelRangeBase(ExcelWorksheet xlWorksheet)
- {
- _worksheet = xlWorksheet;
- _ws = _worksheet.Name;
- _workbook = _worksheet.Workbook;
- this.AddressChange += new EventHandler(ExcelRangeBase_AddressChange);
- SetDelegate();
- }
+using OfficeOpenXml.Style;
+using OfficeOpenXml.Style.XmlAccess;
+using OfficeOpenXml.Table;
- void ExcelRangeBase_AddressChange(object sender, EventArgs e)
- {
- if (Table != null)
- {
- SetRCFromTable(_workbook._package, null);
- }
- SetDelegate();
- }
- internal ExcelRangeBase(ExcelWorksheet xlWorksheet, string address) :
- base(xlWorksheet == null ? "" : xlWorksheet.Name, address)
- {
- _worksheet = xlWorksheet;
- _workbook = _worksheet.Workbook;
- base.SetRCFromTable(_worksheet._package, null);
- if (string.IsNullOrEmpty(_ws)) _ws = _worksheet == null ? "" : _worksheet.Name;
- this.AddressChange += new EventHandler(ExcelRangeBase_AddressChange);
- SetDelegate();
- }
- internal ExcelRangeBase(ExcelWorkbook wb, ExcelWorksheet xlWorksheet, string address, bool isName) :
- base(xlWorksheet == null ? "" : xlWorksheet.Name, address, isName)
- {
- SetRCFromTable(wb._package, null);
- _worksheet = xlWorksheet;
- _workbook = wb;
- if (string.IsNullOrEmpty(_ws)) _ws = (xlWorksheet == null ? null : xlWorksheet.Name);
- this.AddressChange += new EventHandler(ExcelRangeBase_AddressChange);
- SetDelegate();
- }
- ~ExcelRangeBase()
- {
- //this.AddressChange -= new EventHandler(ExcelRangeBase_AddressChange);
- }
- #endregion
- #region Set Value Delegates
- 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(_setValue 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(_setValue valueMethod, object value)
- {
- valueMethod(value, _fromRow, _fromCol);
- }
- /// <summary>
- /// Set a range
- /// </summary>
- /// <param name="valueMethod"></param>
- /// <param name="value"></param>
- private void SetRange(_setValue 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(_setValue 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, _setValue 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"));
- }
- else
- {
- 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);
- }
- }
- }
- }
- #endregion
- #region Set property methods
- private void Set_StyleID(object value, int row, int col)
- {
- _worksheet._styles.SetValue(row, col, (int)value);
- }
- private void Set_StyleName(object value, int row, int col)
- {
- //_worksheet.Cell(row, col).SetNewStyleName(value.ToString(), _styleID);
- _worksheet._styles.SetValue(row, col, _styleID);
- }
- 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 && (int)f >= 0) SplitFormulas(_worksheet.Cells[row, col]);
+namespace OfficeOpenXml;
- 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"));
- }
- else 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;
+/// <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;
- _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;
+ private delegate void ChangePropHandler(SetValueHandler method, object 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)
- {
- _worksheet._hyperLinks.SetValue(row, col, (Uri)value);
+ private delegate void SetValueHandler(object value, int row, int col);
- if (value is ExcelHyperLink)
- {
- _worksheet._values.SetValue(row, col, ((ExcelHyperLink)value).Display);
- }
- else
- {
- _worksheet._values.SetValue(row, col, ((Uri)value).OriginalString);
- }
- }
- else
- {
- _worksheet._hyperLinks.SetValue(row, col, (Uri)null);
- _worksheet._values.SetValue(row, col, (Uri)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 ChangePropHandler _changePropMethod;
+ private int _styleID;
- }
- private void Set_Comment(object value, int row, int col)
- {
- string[] v = (string[])value;
- Worksheet.Comments.Add(new ExcelRangeBase(_worksheet, GetAddress(_fromRow, _fromCol)), v[0], v[1]);
- // _worksheet.Cell(row, col).Comment = comment;
- }
- #endregion
- 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)));
- }
- else
- {
- throw (new InvalidOperationException(string.Format("Range is not valid for {0} : {1}", type, _address)));
- }
- }
- }
- }
- #region Public Properties
- /// <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;
- }
+ private class CopiedCell {
+ internal int Row { get; set; }
- column.StyleName = value;
- column.StyleID = _styleID;
+ internal int Column { get; set; }
- //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;
- }
+ internal object Value { get; set; }
- column._styleName = value;
- column.StyleID = _styleID;
+ internal string Type { get; set; }
- if (cols.Value == null)
- {
- break;
- }
- else
- {
- 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;
+ internal object Formula { get; set; }
- // 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;
- }
- }
+ internal int? StyleID { get; set; }
- 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);
- }
- }
+ internal Uri HyperLink { get; set; }
- private int GetColumnStyle(int col)
- {
- object c=null;
- if (_worksheet._values.Exists(0, col, ref c))
- {
- return (c as ExcelColumn).StyleID;
- }
- else
- {
- 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;
- }
- else
- {
- return _worksheet.Names[_address].NameValue;
- }
- }
- else
- {
- if (_fromRow == _toRow && _fromCol == _toCol)
- {
- return _worksheet.GetValue(_fromRow, _fromCol);
- }
- else
- {
- return GetValueArray();
- }
- }
- }
- set
- {
- if (IsName)
- {
- if (_worksheet == null)
- {
- _workbook._names[_address].NameValue = value;
- }
- else
- {
- _worksheet.Names[_address].NameValue = value;
- }
- }
- else
- {
- _changePropMethod(Set_Value, value);
- }
- }
- }
+ internal ExcelComment Comment { get; set; }
- private bool IsInfinityValue(object value)
- {
- double? valueAsDouble = value as double?;
+ internal Byte Flag { get; set; }
+ }
- if(valueAsDouble.HasValue &&
- (double.IsNegativeInfinity(valueAsDouble.Value) || double.IsPositiveInfinity(valueAsDouble.Value)))
- {
- return true;
- }
+ //private class CopiedFlag
+ //{
+ // internal int Row { get; set; }
+ // internal int Column { get; set; }
+ // internal Byte Flag { get; set; }
+ //}
- return false;
- }
- 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];
+ internal ExcelRangeBase(ExcelWorksheet xlWorksheet) {
+ _worksheet = xlWorksheet;
+ _ws = _worksheet.Name;
+ _workbook = _worksheet.Workbook;
+ AddressChange += ExcelRangeBase_AddressChange;
+ SetDelegate();
+ }
- 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;
- }
- private ExcelAddressBase GetAddressDim(ExcelRangeBase addr)
- {
- int fromRow, fromCol, toRow, toCol;
- var d = _worksheet.Dimension;
- fromRow = addr._fromRow < d._fromRow ? d._fromRow : addr._fromRow;
- fromCol = addr._fromCol < d._fromCol ? d._fromCol : addr._fromCol;
-
- toRow = addr._toRow > d._toRow ? d._toRow : addr._toRow;
- toCol = addr._toCol > d._toCol ? d._toCol : addr._toCol;
-
- if (addr._fromCol == fromRow && addr._toRow == toRow && addr._toCol == _toCol)
- {
- return addr;
- }
- else
- {
- if (_fromRow > _toRow || _fromCol > _toCol)
- {
- return null;
- }
- else
- {
- return new ExcelAddressBase(fromRow, fromCol, toRow, toCol);
- }
- }
- }
-
- private object GetSingleValue()
- {
- if (IsRichText)
- {
- return RichText.Text;
- }
- else
- {
- return _worksheet._values.GetValue(_fromRow, _fromCol);
- }
- }
- /// <summary>
- /// Returns the formatted value.
- /// </summary>
- public string Text
- {
- get
- {
- return GetFormattedText(false);
- }
- }
-
- private void SetMinWidth(double minimumWidth, int fromCol, int toCol)
- {
- var iterator = new CellsStoreEnumerator<object>(_worksheet._values, 0, fromCol, 0, toCol);
- var prevCol = fromCol;
- foreach (ExcelColumn col in iterator)
- {
- col.Width = minimumWidth;
- if (_worksheet.DefaultColWidth > minimumWidth && col.ColumnMin > prevCol)
- {
- var newCol = _worksheet.Column(prevCol);
- newCol.ColumnMax = col.ColumnMin - 1;
- newCol.Width = minimumWidth;
- }
- prevCol = col.ColumnMax + 1;
- }
- if (_worksheet.DefaultColWidth > minimumWidth && prevCol<toCol)
- {
- var newCol = _worksheet.Column(prevCol);
- newCol.ColumnMax = toCol;
- newCol.Width = minimumWidth;
- }
- }
-
- internal string TextForWidth
- {
- get
- {
- return GetFormattedText(true);
- }
- }
- 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);
- }
- else
- {
- return nf.FormatFraction(d);
- }
- }
- else if (nf.DataType == ExcelNumberFormatXml.eFormatType.DateTime)
- {
- var date = DateTime.FromOADate(d);
- return date.ToString(format, nf.Culture);
- }
- }
- else if (v is DateTime)
- {
- if (nf.DataType == ExcelNumberFormatXml.eFormatType.DateTime)
- {
- return ((DateTime)v).ToString(format, nf.Culture);
- }
- else
- {
- double d = ((DateTime)v).ToOADate();
- if (string.IsNullOrEmpty(nf.FractionFormat))
- {
- return d.ToString(format, nf.Culture);
- }
- else
- {
- return nf.FormatFraction(d);
- }
- }
- }
- else if (v is TimeSpan)
- {
- if (nf.DataType == ExcelNumberFormatXml.eFormatType.DateTime)
- {
- return new DateTime(((TimeSpan)v).Ticks).ToString(format, nf.Culture);
- }
- else
- {
- double d = (new DateTime(((TimeSpan)v).Ticks)).ToOADate();
- if (string.IsNullOrEmpty(nf.FractionFormat))
- {
- return d.ToString(format, nf.Culture);
- }
- else
- {
- return nf.FormatFraction(d);
- }
- }
- }
- else
- {
- if (textFormat == "")
- {
- return v.ToString();
- }
- else
- {
- 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;
- }
- else
- {
- return _worksheet.Names[_address].NameFormula;
- }
- }
- else
- {
- 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[ExcelCellBase.TranslateFromR1C1(value, _fromRow, _fromCol)].Value = null;
- }
- else if (Addresses == null)
- {
- Set_SharedFormula(ExcelCellBase.TranslateFromR1C1(value, _fromRow, _fromCol), this, false);
- }
- else
- {
- Set_SharedFormula(ExcelCellBase.TranslateFromR1C1(value, _fromRow, _fromCol), new ExcelAddress(WorkSheet, FirstAddress), false);
- foreach (var address in Addresses)
- {
- Set_SharedFormula(ExcelCellBase.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 ExcelAddressBase(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);
- }
- }
- ExcelRichTextCollection _rtc = null;
- /// <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.ToString() + "</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
- {
- get
- {
- return _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(base._wb) ? base._ws : "[" + base._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(base._wb) ? base._ws : "[" + base._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;
- }
- }
- #endregion
- #region Private Methods
- ///// <summary>
- ///// Check if the range is partly merged
- ///// </summary>
- ///// <param name="startValue">the starting value</param>
- ///// <param name="address">the address</param>
- ///// <returns></returns>
- //private bool CheckMergeDiff(bool startValue, string address)
- //{
- // ExcelAddress a = new ExcelAddress(address);
- // for (int col = a.column; col <= a._toCol; col++)
- // {
- // for (int row = a._fromRow; row <= a._toRow; row++)
- // {
- // if (_worksheet._flags.GetFlagValue(row, col, CellFlags.Merged) != startValue)
- // {
- // return false;
- // }
- // }
- // }
- // return true;
- //}
- ///// <summary>
- ///// Set the merge flag for the range
- ///// </summary>
- ///// <param name="value"></param>
- ///// <param name="address"></param>
- //internal void SetCellMerge(bool value, string address)
- //{
- // ExcelAddress a = new ExcelAddress(address);
- // for (int col = a.column; col <= a._toCol; col++)
- // {
- // for (int row = a._fromRow; row <= a._toRow; row++)
- // {
- // _worksheet._flags.SetFlagValue(row, col,value,CellFlags.Merged);
- // }
- // }
- //}
- /// <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, "");
- }
- /// <summary>
- /// Removes a shared formula
- /// </summary>
- //private void RemoveFormuls(ExcelAddress address)
- //{
- // List<int> removed = new List<int>();
- // int fFromRow, fFromCol, fToRow, fToCol;
- // foreach (int index in _worksheet._sharedFormulas.Keys)
- // {
- // ExcelWorksheet.Formulas f = _worksheet._sharedFormulas[index];
- // ExcelCellBase.GetRowColFromAddress(f.Address, out fFromRow, out fFromCol, out fToRow, out fToCol);
- // if (((fFromCol >= address.Start.Column && fFromCol <= address.End.Column) ||
- // (fToCol >= address.Start.Column && fToCol <= address.End.Column)) &&
- // ((fFromRow >= address.Start.Row && fFromRow <= address.End.Row) ||
- // (fToRow >= address.Start.Row && fToRow <= address.End.Row)))
- // {
- // for (int col = fFromCol; col <= fToCol; col++)
- // {
- // for (int row = fFromRow; row <= fToRow; row++)
- // {
- // _worksheet._formulas.SetValue(row, col, int.MinValue);
- // }
- // }
- // removed.Add(index);
- // }
- // }
- // foreach (int index in removed)
- // {
- // _worksheet._sharedFormulas.Remove(index);
- // }
- //}
- 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 && (int)f >= 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)
- {
- int id = (int)f;
- 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 ExcelAddressBase(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 = ExcelCellBase.GetAddress(fRange._fromRow, fRange._fromCol, _fromRow - 1, fRange._toCol);
- fIsSet = true;
- }
- //Left Range
- if (fRange._fromCol < address._fromCol)
- {
- if (fIsSet)
- {
- f = new ExcelWorksheet.Formulas(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 = ExcelCellBase.GetAddress(f.StartRow, f.StartCol,
- fRange._toRow, address._fromCol - 1);
- }
- else
- {
- f.Address = ExcelCellBase.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 ExcelWorksheet.Formulas(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 = ExcelCellBase.GetAddress(f.StartRow, f.StartCol,
- fRange._toRow, fRange._toCol);
- }
- else
- {
- f.Address = ExcelCellBase.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 ExcelWorksheet.Formulas(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 = ExcelCellBase.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;
- }
- else
- {
- return d / 100;
- }
- }
- if (DateTime.TryParse(v, Format.Culture, DateTimeStyles.None, out dt))
- {
- return dt;
- }
- else
- {
- return v;
- }
- }
- else
- {
- switch (Format.DataTypes[col])
- {
- case eDataTypes.Number:
- if (double.TryParse(v, NumberStyles.Any, Format.Culture, out d))
- {
- return d;
- }
- else
- {
- return v;
- }
- case eDataTypes.DateTime:
- if (DateTime.TryParse(v, Format.Culture, DateTimeStyles.None, out dt))
- {
- return dt;
- }
- else
- {
- 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;
- }
- else
- {
- return v;
- }
-
- default:
- return v;
-
- }
- }
- }
- #endregion
- #region Public Methods
- #region ConditionalFormatting
- /// <summary>
- /// Conditional Formatting for this range.
- /// </summary>
- public IRangeConditionalFormatting ConditionalFormatting
- {
- get
- {
- return new RangeConditionalFormatting(_worksheet, new ExcelAddress(Address));
- }
- }
- #endregion
- #region DataValidation
- /// <summary>
- /// Data validation for this range.
- /// </summary>
- public IRangeDataValidation DataValidation
- {
- get
- {
- return new RangeDataValidation(_worksheet, Address);
- }
- }
- #endregion
- #region LoadFromDataReader
- /// <summary>
- /// Load the data from the datareader starting from the top left cell of the range
- /// </summary>
- /// <param name="Reader">The datareader to loadfrom</param>
- /// <param name="PrintHeaders">Print the column caption property (if set) or the columnname property if not, on first row</param>
- /// <param name="TableName">The name of the table</param>
- /// <param name="TableStyle">The table style to apply to the data</param>
- /// <returns>The filled range</returns>
- public ExcelRangeBase LoadFromDataReader(IDataReader Reader, bool PrintHeaders, string TableName, TableStyles TableStyle = TableStyles.None)
- {
- var r = LoadFromDataReader(Reader, PrintHeaders);
-
- int rows = r.Rows - 1;
- if (rows >= 0 && r.Columns > 0)
- {
- var tbl = _worksheet.Tables.Add(new ExcelAddressBase(_fromRow, _fromCol, _fromRow + (rows <= 0 ? 1 : rows), _fromCol + r.Columns - 1), TableName);
- tbl.ShowHeader = PrintHeaders;
- tbl.TableStyle = TableStyle;
- }
- return r;
- }
-
- /// <summary>
- /// Load the data from the datareader starting from the top left cell of the range
- /// </summary>
- /// <param name="Reader">The datareader to load from</param>
- /// <param name="PrintHeaders">Print the caption property (if set) or the columnname property if not, on first row</param>
- /// <returns>The filled range</returns>
- public ExcelRangeBase LoadFromDataReader(IDataReader Reader, bool PrintHeaders)
- {
- if (Reader == null)
- {
- throw (new ArgumentNullException("Reader", "Reader can't be null"));
- }
- int fieldCount = Reader.FieldCount;
-
- int col = _fromCol, row = _fromRow;
- if (PrintHeaders)
- {
- for (int i = 0; i < fieldCount; i++)
- {
- // If no caption is set, the ColumnName property is called implicitly.
- _worksheet._values.SetValue(row, col++, Reader.GetName(i));
- }
- row++;
- col = _fromCol;
- }
- while(Reader.Read())
- {
- for (int i = 0; i < fieldCount; i++)
- {
- _worksheet._values.SetValue(row, col++, Reader.GetValue(i));
- }
- row++;
- col = _fromCol;
- }
- return _worksheet.Cells[_fromRow, _fromCol, row - 1, _fromCol + fieldCount - 1];
- }
- #endregion
- #region LoadFromDataTable
- /// <summary>
- /// Load the data from the datatable starting from the top left cell of the range
- /// </summary>
- /// <param name="Table">The datatable to load</param>
- /// <param name="PrintHeaders">Print the column caption property (if set) or the columnname property if not, on first row</param>
- /// <param name="TableStyle">The table style to apply to the data</param>
- /// <returns>The filled range</returns>
- public ExcelRangeBase LoadFromDataTable(DataTable Table, bool PrintHeaders, TableStyles TableStyle)
- {
- var r = LoadFromDataTable(Table, PrintHeaders);
-
- int rows = (Table.Rows.Count == 0 ? 1 : Table.Rows.Count) + (PrintHeaders ? 1 : 0);
- if (rows >= 0 && Table.Columns.Count>0)
- {
- var tbl = _worksheet.Tables.Add(new ExcelAddressBase(_fromRow, _fromCol, _fromRow + rows - 1, _fromCol + Table.Columns.Count-1), Table.TableName);
- tbl.ShowHeader = PrintHeaders;
- tbl.TableStyle = TableStyle;
- }
- return r;
- }
- /// <summary>
- /// Load the data from the datatable starting from the top left cell of the range
- /// </summary>
- /// <param name="Table">The datatable to load</param>
- /// <param name="PrintHeaders">Print the caption property (if set) or the columnname property if not, on first row</param>
- /// <returns>The filled range</returns>
- public ExcelRangeBase LoadFromDataTable(DataTable Table, bool PrintHeaders)
- {
- if (Table == null)
- {
- throw (new ArgumentNullException("Table can't be null"));
- }
-
- int col = _fromCol, row = _fromRow;
- if (PrintHeaders)
- {
- foreach (DataColumn dc in Table.Columns)
- {
- // If no caption is set, the ColumnName property is called implicitly.
- _worksheet._values.SetValue(row, col++, dc.Caption);
- }
- row++;
- col = _fromCol;
- }
- else if (Table.Rows.Count == 0)
- {
- return null;
- }
- foreach (DataRow dr in Table.Rows)
- {
- foreach (object value in dr.ItemArray)
- {
- if (value != null && value != DBNull.Value && !string.IsNullOrEmpty(value.ToString()))
- {
- _worksheet._values.SetValue(row, col++, value);
- }
- else
- {
- col++;
- }
- }
- row++;
- col = _fromCol;
- }
- return _worksheet.Cells[_fromRow, _fromCol, (row == _fromRow ? _fromRow : row - 1), _fromCol + Table.Columns.Count - 1];
- }
- #endregion
- #region LoadFromArrays
- /// <summary>
- /// Loads data from the collection of arrays of objects into the range, starting from
- /// the top-left cell.
- /// </summary>
- /// <param name="Data">The data.</param>
- public ExcelRangeBase LoadFromArrays(IEnumerable<object[]> Data)
- {
- //thanx to Abdullin for the code contribution
- if (Data == null) throw new ArgumentNullException("data");
-
- int column = _fromCol, row = _fromRow;
-
- foreach (var rowData in Data)
- {
- column = _fromCol;
- foreach (var cellData in rowData)
- {
- _worksheet._values.SetValue(row, column, cellData);
- column += 1;
- }
- row += 1;
- }
- return _worksheet.Cells[_fromRow, _fromCol, row - 1, column - 1];
- }
- #endregion
- #region LoadFromCollection
- /// <summary>
- /// Load a collection into a the worksheet starting from the top left row of the range.
- /// </summary>
- /// <typeparam name="T">The datatype in the collection</typeparam>
- /// <param name="Collection">The collection to load</param>
- /// <returns>The filled range</returns>
- public ExcelRangeBase LoadFromCollection<T>(IEnumerable<T> Collection)
- {
- return LoadFromCollection<T>(Collection, false, TableStyles.None, BindingFlags.Public | BindingFlags.Instance, null);
- }
- /// <summary>
- /// Load a collection of T into the worksheet starting from the top left row of the range.
- /// Default option will load all public instance properties of T
- /// </summary>
- /// <typeparam name="T">The datatype in the collection</typeparam>
- /// <param name="Collection">The collection to load</param>
- /// <param name="PrintHeaders">Print the property names on the first row. If the property is decorated with a <see cref="DisplayNameAttribute"/> or a <see cref="DescriptionAttribute"/> that attribute will be used instead of the reflected member name.</param>
- /// <returns>The filled range</returns>
- public ExcelRangeBase LoadFromCollection<T>(IEnumerable<T> Collection, bool PrintHeaders)
- {
- return LoadFromCollection<T>(Collection, PrintHeaders, TableStyles.None, BindingFlags.Public | BindingFlags.Instance, null);
- }
- /// <summary>
- /// Load a collection of T into the worksheet starting from the top left row of the range.
- /// Default option will load all public instance properties of T
- /// </summary>
- /// <typeparam name="T">The datatype in the collection</typeparam>
- /// <param name="Collection">The collection to load</param>
- /// <param name="PrintHeaders">Print the property names on the first row. If the property is decorated with a <see cref="DisplayNameAttribute"/> or a <see cref="DescriptionAttribute"/> that attribute will be used instead of the reflected member name.</param>
- /// <param name="TableStyle">Will create a table with this style. If set to TableStyles.None no table will be created</param>
- /// <returns>The filled range</returns>
- public ExcelRangeBase LoadFromCollection<T>(IEnumerable<T> Collection, bool PrintHeaders, TableStyles TableStyle)
- {
- return LoadFromCollection<T>(Collection, PrintHeaders, TableStyle, BindingFlags.Public | BindingFlags.Instance, null);
- }
- /// <summary>
- /// Load a collection into the worksheet starting from the top left row of the range.
- /// </summary>
- /// <typeparam name="T">The datatype in the collection</typeparam>
- /// <param name="Collection">The collection to load</param>
- /// <param name="PrintHeaders">Print the property names on the first row. Any underscore in the property name will be converted to a space. If the property is decorated with a <see cref="DisplayNameAttribute"/> or a <see cref="DescriptionAttribute"/> that attribute will be used instead of the reflected member name.</param>
- /// <param name="TableStyle">Will create a table with this style. If set to TableStyles.None no table will be created</param>
- /// <param name="memberFlags">Property flags to use</param>
- /// <param name="Members">The properties to output. Must be of type T</param>
- /// <returns>The filled range</returns>
- public ExcelRangeBase LoadFromCollection<T>(IEnumerable<T> Collection, bool PrintHeaders, TableStyles TableStyle, BindingFlags memberFlags, MemberInfo[] Members)
- {
- var type = typeof(T);
- if (Members == null)
- {
- Members = type.GetProperties(memberFlags);
- }
- else
- {
- foreach (var t in Members)
- {
- if (t.DeclaringType!=null && t.DeclaringType != type && !t.DeclaringType.IsSubclassOf(type))
- {
- throw new InvalidCastException("Supplied properties in parameter Properties must be of the same type as T (or an assignable type from T");
- }
- }
- }
-
- int col = _fromCol, row = _fromRow;
- if (Members.Length > 0 && PrintHeaders)
- {
- foreach (var t in Members)
- {
- var descriptionAttribute = t.GetCustomAttributes(typeof(DescriptionAttribute), false).FirstOrDefault() as DescriptionAttribute;
- var header = string.Empty;
- if (descriptionAttribute != null)
- {
- header = descriptionAttribute.Description;
- }
- else
- {
- var displayNameAttribute =
- t.GetCustomAttributes(typeof (DisplayNameAttribute), false).FirstOrDefault() as
- DisplayNameAttribute;
- if (displayNameAttribute != null)
- {
- header = displayNameAttribute.DisplayName;
- }
- else
- {
- header = t.Name.Replace('_', ' ');
- }
- }
- _worksheet._values.SetValue(row, col++, header);
- }
- row++;
- }
-
- if (!Collection.Any() && (Members.Length == 0 || PrintHeaders == false))
- {
- return null;
- }
-
- if (Members.Length == 0)
- {
- foreach (var item in Collection)
- {
- _worksheet.Cells[row++, col].Value = item;
- }
- }
- else
- {
- foreach (var item in Collection)
- {
- col = _fromCol;
- if (item is string || item is decimal || item is DateTime || item.GetType().IsPrimitive)
- {
- _worksheet.Cells[row, col++].Value = item;
- }
- else
- {
- foreach (var t in Members)
- {
- if (t is PropertyInfo)
- {
- _worksheet.Cells[row, col++].Value = ((PropertyInfo)t).GetValue(item, null);
- }
- else if (t is FieldInfo)
- {
- _worksheet.Cells[row, col++].Value = ((FieldInfo)t).GetValue(item);
- }
- else if (t is MethodInfo)
- {
- _worksheet.Cells[row, col++].Value = ((MethodInfo)t).Invoke(item, null);
- }
- }
- }
- row++;
- }
- }
-
- if (_fromRow == row-1 && PrintHeaders)
- {
- row++;
- }
-
- var r = _worksheet.Cells[_fromRow, _fromCol, row - 1, Members.Length==0 ? col : col - 1];
-
- if (TableStyle != TableStyles.None)
- {
- var tbl = _worksheet.Tables.Add(r, "");
- tbl.ShowHeader = PrintHeaders;
- tbl.TableStyle = TableStyle;
- }
- return r;
- }
- #endregion
- #region LoadFromText
- /// <summary>
- /// Loads a CSV text into a range starting from the top left cell.
- /// Default settings is Comma separation
- /// </summary>
- /// <param name="Text">The Text</param>
- /// <returns>The range containing the data</returns>
- public ExcelRangeBase LoadFromText(string Text)
- {
- return LoadFromText(Text, new ExcelTextFormat());
- }
- /// <summary>
- /// Loads a CSV text into a range starting from the top left cell.
- /// </summary>
- /// <param name="Text">The Text</param>
- /// <param name="Format">Information how to load the text</param>
- /// <returns>The range containing the data</returns>
- public ExcelRangeBase LoadFromText(string Text, ExcelTextFormat Format)
- {
- if (string.IsNullOrEmpty(Text))
- {
- var r = _worksheet.Cells[_fromRow, _fromCol];
- r.Value = "";
- return r;
- }
-
- if (Format == null) Format = new ExcelTextFormat();
-
- string splitRegex = String.Format("{0}(?=(?:[^{1}]*{1}[^{1}]*{1})*[^{1}]*$)", Format.EOL, Format.TextQualifier);
- string[] lines = Regex.Split(Text, splitRegex);
- int row = _fromRow;
- int col = _fromCol;
- int maxCol = col;
- int lineNo = 1;
- foreach (string line in lines)
- {
- if (lineNo > Format.SkipLinesBeginning && lineNo <= lines.Length - Format.SkipLinesEnd)
- {
- col = _fromCol;
- string v = "";
- bool isText = false, isQualifier = false;
- int QCount = 0;
- int lineQCount = 0;
- foreach (char c in line)
- {
- if (Format.TextQualifier != 0 && c == Format.TextQualifier)
- {
- if (!isText && v != "")
- {
- throw (new Exception(string.Format("Invalid Text Qualifier in line : {0}", line)));
- }
- isQualifier = !isQualifier;
- QCount += 1;
- lineQCount++;
- isText = true;
- }
- else
- {
- if (QCount > 1 && !string.IsNullOrEmpty(v))
- {
- v += new string(Format.TextQualifier, QCount / 2);
- }
- else if (QCount > 2 && string.IsNullOrEmpty(v))
- {
- v += new string(Format.TextQualifier, (QCount - 1) / 2);
- }
-
- if (isQualifier)
- {
- v += c;
- }
- else
- {
- if (c == Format.Delimiter)
- {
- _worksheet.SetValue(row, col, ConvertData(Format, v, col - _fromCol, isText));
- v = "";
- isText = false;
- col++;
- }
- else
- {
- if (QCount % 2 == 1)
- {
- throw (new Exception(string.Format("Text delimiter is not closed in line : {0}", line)));
- }
- v += c;
- }
- }
- QCount = 0;
- }
- }
- if (QCount > 1)
- {
- v += new string(Format.TextQualifier, QCount / 2);
- }
- if (lineQCount % 2 == 1)
- throw (new Exception(string.Format("Text delimiter is not closed in line : {0}", line)));
-
- _worksheet._values.SetValue(row, col, ConvertData(Format, v, col - _fromCol, isText));
- if (col > maxCol) maxCol = col;
- row++;
- }
- lineNo++;
- }
- return _worksheet.Cells[_fromRow, _fromCol, row - 1, maxCol];
- }
- /// <summary>
- /// Loads a CSV text into a range starting from the top left cell.
- /// </summary>
- /// <param name="Text">The Text</param>
- /// <param name="Format">Information how to load the text</param>
- /// <param name="TableStyle">Create a table with this style</param>
- /// <param name="FirstRowIsHeader">Use the first row as header</param>
- /// <returns></returns>
- public ExcelRangeBase LoadFromText(string Text, ExcelTextFormat Format, TableStyles TableStyle, bool FirstRowIsHeader)
- {
- var r = LoadFromText(Text, Format);
-
- var tbl = _worksheet.Tables.Add(r, "");
- tbl.ShowHeader = FirstRowIsHeader;
- tbl.TableStyle = TableStyle;
-
- return r;
- }
- /// <summary>
- /// Loads a CSV file into a range starting from the top left cell.
- /// </summary>
- /// <param name="TextFile">The Textfile</param>
- /// <returns></returns>
- public ExcelRangeBase LoadFromText(FileInfo TextFile)
- {
- return LoadFromText(File.ReadAllText(TextFile.FullName, Encoding.ASCII));
- }
- /// <summary>
- /// Loads a CSV file into a range starting from the top left cell.
- /// </summary>
- /// <param name="TextFile">The Textfile</param>
- /// <param name="Format">Information how to load the text</param>
- /// <returns></returns>
- public ExcelRangeBase LoadFromText(FileInfo TextFile, ExcelTextFormat Format)
- {
- return LoadFromText(File.ReadAllText(TextFile.FullName, Format.Encoding), Format);
- }
- /// <summary>
- /// Loads a CSV file into a range starting from the top left cell.
- /// </summary>
- /// <param name="TextFile">The Textfile</param>
- /// <param name="Format">Information how to load the text</param>
- /// <param name="TableStyle">Create a table with this style</param>
- /// <param name="FirstRowIsHeader">Use the first row as header</param>
- /// <returns></returns>
- public ExcelRangeBase LoadFromText(FileInfo TextFile, ExcelTextFormat Format, TableStyles TableStyle, bool FirstRowIsHeader)
- {
- return LoadFromText(File.ReadAllText(TextFile.FullName, Format.Encoding), Format, TableStyle, FirstRowIsHeader);
- }
- #endregion
- #region GetValue
- /// <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);
- }
- #endregion
- /// <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 ExcelRangeBase(_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 Exception("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 ExcelRangeBase(_worksheet, address);
- }
- /// <summary>
- /// Adds a new comment for the range.
- /// If this range contains more than one cell, the top left comment is returned by the method.
- /// </summary>
- /// <param name="Text"></param>
- /// <param name="Author"></param>
- /// <returns>A reference comment of the top left cell</returns>
- public ExcelComment AddComment(string Text, string Author)
- {
- if (string.IsNullOrEmpty(Author))
- {
- Author = Thread.CurrentPrincipal.Identity.Name;
- }
- //Check if any comments exists in the range and throw an exception
- _changePropMethod(Exists_Comment, null);
- //Create the comments
- _changePropMethod(Set_Comment, new string[] { Text, Author });
-
- return _worksheet.Comments[new ExcelCellAddress(_fromRow, _fromCol)];
- }
-
- ///// <summary>
- ///// Copies the range of cells to an other range
- ///// </summary>
- ///// <param name="Destination">The start cell where the range will be copied.</param>
- public void Copy(ExcelRangeBase Destination)
- {
- bool sameWorkbook = Destination._worksheet.Workbook == _worksheet.Workbook;
- ExcelStyles sourceStyles = _worksheet.Workbook.Styles,
- styles = Destination._worksheet.Workbook.Styles;
- Dictionary<int, int> styleCashe = new Dictionary<int, int>();
-
- //Clear all existing cells;
- int toRow = _toRow - _fromRow + 1,
- toCol = _toCol - _fromCol + 1;
-
- string s = "";
- int i=0;
- object o = null;
- byte flag=0;
- Uri hl = null;
- ExcelComment comment=null;
-
- var cse = new CellsStoreEnumerator<object>(_worksheet._values, _fromRow, _fromCol, _toRow, _toCol);
- var copiedValue = new List<CopiedCell>();
- while (cse.Next())
- {
- var row=cse.Row;
- var col = cse.Column; //Issue 15070
- var cell = new CopiedCell
- {
- Row = Destination._fromRow + (row - _fromRow),
- Column = Destination._fromCol + (col - _fromCol),
- Value=cse.Value
- };
-
- //Destination._worksheet._values.SetValue(row, col, cse.Value);
-
- if (_worksheet._types.Exists(row, col, ref s))
- {
- //Destination._worksheet._types.SetValue(row, col,s);
- cell.Type=s;
- }
-
- if (_worksheet._formulas.Exists(row, col, ref o))
- {
- if (o is int)
- {
- // Destination._worksheet._formulas.SetValue(row, col, _worksheet.GetFormula(cse.Row, cse.Column)); //Shared formulas, set the formula per cell to simplify
- cell.Formula=_worksheet.GetFormula(cse.Row, cse.Column);
- }
- else
- {
- //Destination._worksheet._formulas.SetValue(row, col, o);
- cell.Formula=o;
- }
- }
- if(_worksheet._styles.Exists(row, col, ref i))
- {
- if (sameWorkbook)
- {
- //Destination._worksheet._styles.SetValue(row, col, i);
- cell.StyleID=i;
- }
- else
- {
- if (styleCashe.ContainsKey(i))
- {
- i = styleCashe[i];
- }
- else
- {
- var oldStyleID = i;
- i = styles.CloneStyle(sourceStyles, i);
- styleCashe.Add(oldStyleID, i);
- }
- //Destination._worksheet._styles.SetValue(row, col, i);
- cell.StyleID=i;
- }
- }
-
- if (_worksheet._hyperLinks.Exists(row, col, ref hl))
- {
- //Destination._worksheet._hyperLinks.SetValue(row, col, hl);
- cell.HyperLink=hl;
- }
-
- if(_worksheet._commentsStore.Exists(row, col, ref comment))
- {
- cell.Comment=comment;
- }
-
- if (_worksheet._flags.Exists(row, col, ref flag))
- {
- cell.Flag = flag;
- }
- copiedValue.Add(cell);
- }
-
- //Copy styles with no cell value
- var cses = new CellsStoreEnumerator<int>(_worksheet._styles, _fromRow, _fromCol, _toRow, _toCol);
- while (cses.Next())
- {
- if (!_worksheet._values.Exists(cses.Row, cses.Column))
- {
- var row = Destination._fromRow + (cses.Row - _fromRow);
- var col = Destination._fromCol + (cses.Column - _fromCol);
- var cell = new CopiedCell
- {
- Row = row,
- Column = col,
- Value = null
- };
-
- i = cses.Value;
- if (sameWorkbook)
- {
- cell.StyleID = i;
- }
- else
- {
- if (styleCashe.ContainsKey(i))
- {
- i = styleCashe[i];
- }
- else
- {
- var oldStyleID = i;
- i = styles.CloneStyle(sourceStyles, i);
- styleCashe.Add(oldStyleID, i);
- }
- //Destination._worksheet._styles.SetValue(row, col, i);
- cell.StyleID = i;
- }
- copiedValue.Add(cell);
- }
- }
- var copiedMergedCells = new Dictionary<int, ExcelAddress>();
- //Merged cells
- var csem = new CellsStoreEnumerator<int>(_worksheet.MergedCells._cells, _fromRow, _fromCol, _toRow, _toCol);
- while (csem.Next())
- {
- if(!copiedMergedCells.ContainsKey(csem.Value))
- {
- var adr = new ExcelAddress(_worksheet.Name, _worksheet.MergedCells.List[csem.Value]);
- if(this.Collide(adr)==eAddressCollition.Inside)
- {
- copiedMergedCells.Add(csem.Value, new ExcelAddress(
- Destination._fromRow + (adr.Start.Row - _fromRow),
- Destination._fromCol + (adr.Start.Column - _fromCol),
- Destination._fromRow + (adr.End.Row - _fromRow),
- Destination._fromCol + (adr.End.Column - _fromCol)));
- }
- else
- {
- //Partial merge of the address ignore.
- copiedMergedCells.Add(csem.Value, null);
- }
- }
- }
-
- Destination._worksheet.MergedCells.Clear(new ExcelAddressBase(Destination._fromRow, Destination._fromCol, Destination._fromRow+toRow-1, Destination._fromCol+toCol-1));
-
- Destination._worksheet._values.Clear(Destination._fromRow, Destination._fromCol, toRow, toCol);
- Destination._worksheet._formulas.Clear(Destination._fromRow, Destination._fromCol, toRow, toCol);
- Destination._worksheet._styles.Clear(Destination._fromRow, Destination._fromCol, toRow, toCol);
- Destination._worksheet._types.Clear(Destination._fromRow, Destination._fromCol, toRow, toCol);
- Destination._worksheet._hyperLinks.Clear(Destination._fromRow, Destination._fromCol, toRow, toCol);
- Destination._worksheet._flags.Clear(Destination._fromRow, Destination._fromCol, toRow, toCol);
- Destination._worksheet._commentsStore.Clear(Destination._fromRow, Destination._fromCol, toRow, toCol);
-
- foreach(var cell in copiedValue)
- {
- Destination._worksheet._values.SetValue(cell.Row, cell.Column, cell.Value);
-
- if(cell.Type!=null)
- {
- Destination._worksheet._types.SetValue(cell.Row, cell.Column, cell.Type);
- }
-
- if(cell.StyleID!=null)
- {
- Destination._worksheet._styles.SetValue(cell.Row, cell.Column, cell.StyleID.Value);
- }
-
- if(cell.Formula!=null)
- {
- cell.Formula = UpdateFormulaReferences(cell.Formula.ToString(), Destination._fromRow - _fromRow, Destination._fromCol - _fromCol, 0, 0, true);
- Destination._worksheet._formulas.SetValue(cell.Row, cell.Column, cell.Formula);
- }
- if(cell.HyperLink!=null)
- {
- Destination._worksheet._hyperLinks.SetValue(cell.Row, cell.Column, cell.HyperLink);
- }
-
- if (cell.Comment != null)
- {
- //Destination._worksheet._commentsStore.SetValue(cell.Row, cell.Column, cell.Comment);
- }
- if (cell.Flag != 0)
- {
- Destination._worksheet._flags.SetValue(cell.Row, cell.Column, cell.Flag);
- }
- }
-
- //Add merged cells
- foreach(var m in copiedMergedCells.Values)
- {
- if(m!=null)
- {
- Destination._worksheet.MergedCells.Add(m, true);
- }
- }
-
-
- //Clone the cell
- //var copiedCell = (_worksheet._cells[GetCellID(_worksheet.SheetID, cell._fromRow, cell.column)] as ExcelCell);
-
- //var newCell = copiedCell.Clone(Destination._worksheet,
- // Destination._fromRow + (copiedCell.Row - _fromRow),
- // Destination.column + (copiedCell.Column - column));
-
- // newCell.MergeId = _worksheet.GetMergeCellId(copiedCell.Row, copiedCell.Column);
-
-
- // if (!string.IsNullOrEmpty(newCell.Formula))
- // {
- // newCell.Formula = ExcelCell.UpdateFormulaReferences(newCell.Formula, newCell.Row - copiedCell.Row, (newCell.Column - copiedCell.Column), 1, 1);
- // }
-
- // //If its not the same workbook we must copy the styles to the new workbook.
- // if (!sameWorkbook)
- // {
- // if (styleCashe.ContainsKey(cell.StyleID))
- // {
- // newCell.StyleID = styleCashe[cell.StyleID];
- // }
- // else
- // {
- // newCell.StyleID = styles.CloneStyle(sourceStyles, cell.StyleID);
- // styleCashe.Add(cell.StyleID, newCell.StyleID);
- // }
- // }
- // newCells.Add(newCell);
- // if (newCell.Merge) mergedCells.Add(newCell.CellID, newCell);
- // }
-
- // //Now clear the destination.
- // Destination.Offset(0, 0, (_toRow - _fromRow) + 1, (_toCol - column) + 1).Clear();
-
- // //And last add the new cells to the worksheet
- // foreach (var cell in newCells)
- // {
- // Destination.Worksheet._cells.Add(cell);
- // }
- // //Add merged cells
- // if (mergedCells.Count > 0)
- // {
- // List<ExcelAddressBase> mergedAddresses = new List<ExcelAddressBase>();
- // foreach (var cell in mergedCells.Values)
- // {
- // if (!IsAdded(cell, mergedAddresses))
- // {
- // int startRow = cell.Row, startCol = cell.Column, endRow = cell.Row, endCol = cell.Column + 1;
- // while (mergedCells.ContainsKey(ExcelCell.GetCellID(Destination.Worksheet.SheetID, endRow, endCol)))
- // {
- // ExcelCell next = mergedCells[ExcelCell.GetCellID(Destination.Worksheet.SheetID, endRow, endCol)];
- // if (cell.MergeId != next.MergeId)
- // {
- // break;
- // }
- // endCol++;
- // }
-
- // while (IsMerged(mergedCells, Destination.Worksheet, endRow, startCol, endCol - 1, cell))
- // {
- // endRow++;
- // }
-
- // mergedAddresses.Add(new ExcelAddressBase(startRow, startCol, endRow - 1, endCol - 1));
- // }
- // }
- // Destination.Worksheet.MergedCells.List.AddRange((from r in mergedAddresses select r.Address));
- // }
- //}
-
- //private bool IsAdded(ExcelCell cell, List<ExcelAddressBase> mergedAddresses)
- //{
- // foreach (var address in mergedAddresses)
- // {
- // if (address.Collide(new ExcelAddressBase(cell.CellAddress)) == eAddressCollition.Inside)
- // {
- // return true;
- // }
- // }
- // return false;
- //}
-
- //private bool IsMerged(Dictionary<ulong, ExcelCell> mergedCells, ExcelWorksheet worksheet, int row, int startCol, int endCol, ExcelCell cell)
- //{
- // for (int col = startCol; col <= endCol; col++)
- // {
- // if (!mergedCells.ContainsKey(ExcelCell.GetCellID(worksheet.SheetID, row, col)))
- // {
- // return false;
- // }
- // else
- // {
- // ExcelCell next = mergedCells[ExcelCell.GetCellID(worksheet.SheetID, row, col)];
- // if (cell.MergeId != next.MergeId)
- // {
- // return false;
- // }
- // }
- // }
- // return true;
- }
-
- /// <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 Exception("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);
- }
- }
- }
-
- private void DeleteCheckMergedCells(ExcelAddressBase Range)
- {
- var removeItems = new List<string>();
- foreach (var addr in Worksheet.MergedCells)
- {
- var addrCol = Range.Collide(new ExcelAddress(Range.WorkSheet, addr));
- if (addrCol != eAddressCollition.No)
- {
- if (addrCol == eAddressCollition.Inside)
- {
- removeItems.Add(addr);
- }
- else
- {
- throw (new InvalidOperationException("Can't remove/overwrite a part of cells that are merged"));
- }
- }
- }
- foreach (var item in removeItems)
- {
- Worksheet.MergedCells.Remove(item);
- }
- }
- #endregion
- #region IDisposable Members
-
- public void Dispose()
- {
- }
-
- #endregion
- #region "Enumerator"
- //int _index;
- //ulong _toCellId;
- //int _enumAddressIx;
- 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
- {
- get
- {
- return new ExcelRangeBase(_worksheet, ExcelAddressBase.GetAddress(cellEnum.Row, cellEnum.Column));
- }
- }
-
- /// <summary>
- /// The current range when enumerating
- /// </summary>
- object IEnumerator.Current
- {
- get
- {
- return ((object)(new ExcelRangeBase(_worksheet, ExcelAddressBase.GetAddress(cellEnum.Row, cellEnum.Column))));
- }
- }
-
- int _enumAddressIx = -1;
- public bool MoveNext()
- {
- if (cellEnum.Next())
- {
- return true;
- }
- else if (_addresses!=null)
- {
- _enumAddressIx++;
- if (_enumAddressIx < _addresses.Count)
- {
- cellEnum = new CellsStoreEnumerator<object>(_worksheet._values,
- _addresses[_enumAddressIx]._fromRow,
- _addresses[_enumAddressIx]._fromCol,
- _addresses[_enumAddressIx]._toRow,
- _addresses[_enumAddressIx]._toCol);
- return MoveNext();
- }
- else
- {
- return false;
- }
- }
- return false;
- }
-
- public void Reset()
- {
- _enumAddressIx = -1;
- cellEnum = new CellsStoreEnumerator<object>(_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--;
- //}
- #endregion
+ private void ExcelRangeBase_AddressChange(object sender, EventArgs e) {
+ if (Table != null) {
+ SetRcFromTable(_workbook._package, null);
}
+ SetDelegate();
+ }
+
+ internal ExcelRangeBase(ExcelWorksheet xlWorksheet, string address)
+ : base(xlWorksheet == null ? "" : xlWorksheet.Name, address) {
+ _worksheet = xlWorksheet;
+ _workbook = _worksheet.Workbook;
+ SetRcFromTable(_worksheet._package, 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._package, null);
+ _worksheet = xlWorksheet;
+ _workbook = wb;
+ if (string.IsNullOrEmpty(_ws)) {
+ _ws = (xlWorksheet == null ? null : 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_StyleName(object value, int row, int col) {
+ //_worksheet.Cell(row, col).SetNewStyleName(value.ToString(), _styleID);
+ _worksheet._styles.SetValue(row, col, _styleID);
+ }
+
+ 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 && (int)f >= 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) {
+ _worksheet._hyperLinks.SetValue(row, col, (Uri)value);
+
+ if (value is ExcelHyperLink) {
+ _worksheet._values.SetValue(row, col, ((ExcelHyperLink)value).Display);
+ } else {
+ _worksheet._values.SetValue(row, col, ((Uri)value).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 Set_Comment(object value, int row, int col) {
+ string[] v = (string[])value;
+ Worksheet.Comments.Add(new(_worksheet, GetAddress(_fromRow, _fromCol)), v[0], v[1]);
+ // _worksheet.Cell(row, col).Comment = comment;
+ }
+
+ 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 bool IsInfinityValue(object value) {
+ double? valueAsDouble = value as double?;
+
+ if (valueAsDouble.HasValue
+ && (double.IsNegativeInfinity(valueAsDouble.Value)
+ || double.IsPositiveInfinity(valueAsDouble.Value))) {
+ return true;
+ }
+
+ return false;
+ }
+
+ 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;
+ }
+
+ private ExcelAddressBase GetAddressDim(ExcelRangeBase addr) {
+ int fromRow,
+ fromCol,
+ toRow,
+ toCol;
+ var d = _worksheet.Dimension;
+ fromRow = addr._fromRow < d._fromRow ? d._fromRow : addr._fromRow;
+ fromCol = addr._fromCol < d._fromCol ? d._fromCol : addr._fromCol;
+
+ toRow = addr._toRow > d._toRow ? d._toRow : addr._toRow;
+ toCol = addr._toCol > d._toCol ? d._toCol : addr._toCol;
+
+ if (addr._fromCol == fromRow && addr._toRow == toRow && addr._toCol == _toCol) {
+ return addr;
+ }
+ if (_fromRow > _toRow || _fromCol > _toCol) {
+ return null;
+ }
+ return new(fromRow, fromCol, toRow, toCol);
+ }
+
+ private object GetSingleValue() {
+ if (IsRichText) {
+ return RichText.Text;
+ }
+ return _worksheet._values.GetValue(_fromRow, _fromCol);
+ }
+
+ /// <summary>
+ /// Returns the formatted value.
+ /// </summary>
+ public string Text => GetFormattedText(false);
+
+ private void SetMinWidth(double minimumWidth, int fromCol, int toCol) {
+ var iterator = new CellsStoreEnumerator<object>(_worksheet._values, 0, fromCol, 0, toCol);
+ var prevCol = fromCol;
+ foreach (ExcelColumn col in iterator) {
+ col.Width = minimumWidth;
+ if (_worksheet.DefaultColWidth > minimumWidth && col.ColumnMin > prevCol) {
+ var newCol = _worksheet.Column(prevCol);
+ newCol.ColumnMax = col.ColumnMin - 1;
+ newCol.Width = minimumWidth;
+ }
+ prevCol = col.ColumnMax + 1;
+ }
+ if (_worksheet.DefaultColWidth > minimumWidth && prevCol < toCol) {
+ var newCol = _worksheet.Column(prevCol);
+ newCol.ColumnMax = toCol;
+ newCol.Width = minimumWidth;
+ }
+ }
+
+ internal string TextForWidth => GetFormattedText(true);
+
+ 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) {
+ if (nf.DataType == ExcelNumberFormatXml.eFormatType.DateTime) {
+ return ((DateTime)v).ToString(format, nf.Culture);
+ }
+ double d = ((DateTime)v).ToOADate();
+ if (string.IsNullOrEmpty(nf.FractionFormat)) {
+ return d.ToString(format, nf.Culture);
+ }
+ return nf.FormatFraction(d);
+ } else if (v is TimeSpan) {
+ if (nf.DataType == ExcelNumberFormatXml.eFormatType.DateTime) {
+ return new DateTime(((TimeSpan)v).Ticks).ToString(format, nf.Culture);
+ }
+ double d = (new DateTime(((TimeSpan)v).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 && (int)f >= 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) {
+ int id = (int)f;
+ 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>
+ /// Load the data from the datareader starting from the top left cell of the range
+ /// </summary>
+ /// <param name="reader">The datareader to loadfrom</param>
+ /// <param name="printHeaders">Print the column caption property (if set) or the columnname property if not, on first row</param>
+ /// <param name="tableName">The name of the table</param>
+ /// <param name="tableStyle">The table style to apply to the data</param>
+ /// <returns>The filled range</returns>
+ public ExcelRangeBase LoadFromDataReader(
+ IDataReader reader,
+ bool printHeaders,
+ string tableName,
+ TableStyles tableStyle = TableStyles.None) {
+ var r = LoadFromDataReader(reader, printHeaders);
+
+ int rows = r.Rows - 1;
+ if (rows >= 0 && r.Columns > 0) {
+ var tbl = _worksheet.Tables.Add(
+ new(_fromRow, _fromCol, _fromRow + (rows <= 0 ? 1 : rows), _fromCol + r.Columns - 1),
+ tableName);
+ tbl.ShowHeader = printHeaders;
+ tbl.TableStyle = tableStyle;
+ }
+ return r;
+ }
+
+ /// <summary>
+ /// Load the data from the datareader starting from the top left cell of the range
+ /// </summary>
+ /// <param name="reader">The datareader to load from</param>
+ /// <param name="printHeaders">Print the caption property (if set) or the columnname property if not, on first row</param>
+ /// <returns>The filled range</returns>
+ public ExcelRangeBase LoadFromDataReader(IDataReader reader, bool printHeaders) {
+ if (reader == null) {
+ throw (new ArgumentNullException("reader", "Reader can't be null"));
+ }
+ int fieldCount = reader.FieldCount;
+
+ int col = _fromCol,
+ row = _fromRow;
+ if (printHeaders) {
+ for (int i = 0; i < fieldCount; i++) {
+ // If no caption is set, the ColumnName property is called implicitly.
+ _worksheet._values.SetValue(row, col++, reader.GetName(i));
+ }
+ row++;
+ col = _fromCol;
+ }
+ while (reader.Read()) {
+ for (int i = 0; i < fieldCount; i++) {
+ _worksheet._values.SetValue(row, col++, reader.GetValue(i));
+ }
+ row++;
+ col = _fromCol;
+ }
+ return _worksheet.Cells[_fromRow, _fromCol, row - 1, _fromCol + fieldCount - 1];
+ }
+
+ /// <summary>
+ /// Load the data from the datatable starting from the top left cell of the range
+ /// </summary>
+ /// <param name="table">The datatable to load</param>
+ /// <param name="printHeaders">Print the column caption property (if set) or the columnname property if not, on first row</param>
+ /// <param name="tableStyle">The table style to apply to the data</param>
+ /// <returns>The filled range</returns>
+ public ExcelRangeBase LoadFromDataTable(
+ DataTable table,
+ bool printHeaders,
+ TableStyles tableStyle) {
+ var r = LoadFromDataTable(table, printHeaders);
+
+ int rows = (table.Rows.Count == 0 ? 1 : table.Rows.Count) + (printHeaders ? 1 : 0);
+ if (rows >= 0 && table.Columns.Count > 0) {
+ var tbl = _worksheet.Tables.Add(
+ new(_fromRow, _fromCol, _fromRow + rows - 1, _fromCol + table.Columns.Count - 1),
+ table.TableName);
+ tbl.ShowHeader = printHeaders;
+ tbl.TableStyle = tableStyle;
+ }
+ return r;
+ }
+
+ /// <summary>
+ /// Load the data from the datatable starting from the top left cell of the range
+ /// </summary>
+ /// <param name="table">The datatable to load</param>
+ /// <param name="printHeaders">Print the caption property (if set) or the columnname property if not, on first row</param>
+ /// <returns>The filled range</returns>
+ public ExcelRangeBase LoadFromDataTable(DataTable table, bool printHeaders) {
+ if (table == null) {
+ throw (new ArgumentNullException("Table can't be null"));
+ }
+
+ int col = _fromCol,
+ row = _fromRow;
+ if (printHeaders) {
+ foreach (DataColumn dc in table.Columns) {
+ // If no caption is set, the ColumnName property is called implicitly.
+ _worksheet._values.SetValue(row, col++, dc.Caption);
+ }
+ row++;
+ col = _fromCol;
+ } else if (table.Rows.Count == 0) {
+ return null;
+ }
+ foreach (DataRow dr in table.Rows) {
+ foreach (object value in dr.ItemArray) {
+ if (value != null && value != DBNull.Value && !string.IsNullOrEmpty(value.ToString())) {
+ _worksheet._values.SetValue(row, col++, value);
+ } else {
+ col++;
+ }
+ }
+ row++;
+ col = _fromCol;
+ }
+ return _worksheet.Cells[_fromRow,
+ _fromCol,
+ (row == _fromRow ? _fromRow : row - 1),
+ _fromCol + table.Columns.Count - 1];
+ }
+
+ /// <summary>
+ /// Loads data from the collection of arrays of objects into the range, starting from
+ /// the top-left cell.
+ /// </summary>
+ /// <param name="data">The data.</param>
+ public ExcelRangeBase LoadFromArrays(IEnumerable<object[]> data) {
+ //thanx to Abdullin for the code contribution
+ if (data == null) {
+ throw new ArgumentNullException("data");
+ }
+
+ int column = _fromCol,
+ row = _fromRow;
+
+ foreach (var rowData in data) {
+ column = _fromCol;
+ foreach (var cellData in rowData) {
+ _worksheet._values.SetValue(row, column, cellData);
+ column += 1;
+ }
+ row += 1;
+ }
+ return _worksheet.Cells[_fromRow, _fromCol, row - 1, column - 1];
+ }
+
+ /// <summary>
+ /// Load a collection into a the worksheet starting from the top left row of the range.
+ /// </summary>
+ /// <typeparam name="T">The datatype in the collection</typeparam>
+ /// <param name="collection">The collection to load</param>
+ /// <returns>The filled range</returns>
+ public ExcelRangeBase LoadFromCollection<T>(IEnumerable<T> collection) {
+ return LoadFromCollection(
+ collection,
+ false,
+ TableStyles.None,
+ BindingFlags.Public | BindingFlags.Instance,
+ null);
+ }
+
+ /// <summary>
+ /// Load a collection of T into the worksheet starting from the top left row of the range.
+ /// Default option will load all public instance properties of T
+ /// </summary>
+ /// <typeparam name="T">The datatype in the collection</typeparam>
+ /// <param name="collection">The collection to load</param>
+ /// <param name="printHeaders">Print the property names on the first row. If the property is decorated with a <see cref="DisplayNameAttribute"/> or a <see cref="DescriptionAttribute"/> that attribute will be used instead of the reflected member name.</param>
+ /// <returns>The filled range</returns>
+ public ExcelRangeBase LoadFromCollection<T>(IEnumerable<T> collection, bool printHeaders) {
+ return LoadFromCollection(
+ collection,
+ printHeaders,
+ TableStyles.None,
+ BindingFlags.Public | BindingFlags.Instance,
+ null);
+ }
+
+ /// <summary>
+ /// Load a collection of T into the worksheet starting from the top left row of the range.
+ /// Default option will load all public instance properties of T
+ /// </summary>
+ /// <typeparam name="T">The datatype in the collection</typeparam>
+ /// <param name="collection">The collection to load</param>
+ /// <param name="printHeaders">Print the property names on the first row. If the property is decorated with a <see cref="DisplayNameAttribute"/> or a <see cref="DescriptionAttribute"/> that attribute will be used instead of the reflected member name.</param>
+ /// <param name="tableStyle">Will create a table with this style. If set to TableStyles.None no table will be created</param>
+ /// <returns>The filled range</returns>
+ public ExcelRangeBase LoadFromCollection<T>(
+ IEnumerable<T> collection,
+ bool printHeaders,
+ TableStyles tableStyle) {
+ return LoadFromCollection(
+ collection,
+ printHeaders,
+ tableStyle,
+ BindingFlags.Public | BindingFlags.Instance,
+ null);
+ }
+
+ /// <summary>
+ /// Load a collection into the worksheet starting from the top left row of the range.
+ /// </summary>
+ /// <typeparam name="T">The datatype in the collection</typeparam>
+ /// <param name="collection">The collection to load</param>
+ /// <param name="printHeaders">Print the property names on the first row. Any underscore in the property name will be converted to a space. If the property is decorated with a <see cref="DisplayNameAttribute"/> or a <see cref="DescriptionAttribute"/> that attribute will be used instead of the reflected member name.</param>
+ /// <param name="tableStyle">Will create a table with this style. If set to TableStyles.None no table will be created</param>
+ /// <param name="memberFlags">Property flags to use</param>
+ /// <param name="members">The properties to output. Must be of type T</param>
+ /// <returns>The filled range</returns>
+ public ExcelRangeBase LoadFromCollection<T>(
+ IEnumerable<T> collection,
+ bool printHeaders,
+ TableStyles tableStyle,
+ BindingFlags memberFlags,
+ MemberInfo[] members) {
+ var type = typeof(T);
+ if (members == null) {
+ members = type.GetProperties(memberFlags);
+ } else {
+ foreach (var t in members) {
+ if (t.DeclaringType != null
+ && t.DeclaringType != type
+ && !t.DeclaringType.IsSubclassOf(type)) {
+ throw new InvalidCastException(
+ "Supplied properties in parameter Properties must be of the same type as T (or an assignable type from T");
+ }
+ }
+ }
+
+ int col = _fromCol,
+ row = _fromRow;
+ if (members.Length > 0 && printHeaders) {
+ foreach (var t in members) {
+ var descriptionAttribute =
+ t.GetCustomAttributes(typeof(DescriptionAttribute), false).FirstOrDefault()
+ as DescriptionAttribute;
+ var header = string.Empty;
+ if (descriptionAttribute != null) {
+ header = descriptionAttribute.Description;
+ } else {
+ var displayNameAttribute =
+ t.GetCustomAttributes(typeof(DisplayNameAttribute), false).FirstOrDefault()
+ as DisplayNameAttribute;
+ if (displayNameAttribute != null) {
+ header = displayNameAttribute.DisplayName;
+ } else {
+ header = t.Name.Replace('_', ' ');
+ }
+ }
+ _worksheet._values.SetValue(row, col++, header);
+ }
+ row++;
+ }
+
+ if (!collection.Any() && (members.Length == 0 || printHeaders == false)) {
+ return null;
+ }
+
+ if (members.Length == 0) {
+ foreach (var item in collection) {
+ _worksheet.Cells[row++, col].Value = item;
+ }
+ } else {
+ foreach (var item in collection) {
+ col = _fromCol;
+ if (item is string || item is decimal || item is DateTime || item.GetType().IsPrimitive) {
+ _worksheet.Cells[row, col++].Value = item;
+ } else {
+ foreach (var t in members) {
+ if (t is PropertyInfo) {
+ _worksheet.Cells[row, col++].Value = ((PropertyInfo)t).GetValue(item, null);
+ } else if (t is FieldInfo) {
+ _worksheet.Cells[row, col++].Value = ((FieldInfo)t).GetValue(item);
+ } else if (t is MethodInfo) {
+ _worksheet.Cells[row, col++].Value = ((MethodInfo)t).Invoke(item, null);
+ }
+ }
+ }
+ row++;
+ }
+ }
+
+ if (_fromRow == row - 1 && printHeaders) {
+ row++;
+ }
+
+ var r = _worksheet.Cells[_fromRow, _fromCol, row - 1, members.Length == 0 ? col : col - 1];
+
+ if (tableStyle != TableStyles.None) {
+ var tbl = _worksheet.Tables.Add(r, "");
+ tbl.ShowHeader = printHeaders;
+ tbl.TableStyle = tableStyle;
+ }
+ return r;
+ }
+
+ /// <summary>
+ /// Loads a CSV text into a range starting from the top left cell.
+ /// Default settings is Comma separation
+ /// </summary>
+ /// <param name="text">The Text</param>
+ /// <returns>The range containing the data</returns>
+ public ExcelRangeBase LoadFromText(string text) {
+ return LoadFromText(text, new());
+ }
+
+ /// <summary>
+ /// Loads a CSV text into a range starting from the top left cell.
+ /// </summary>
+ /// <param name="text">The Text</param>
+ /// <param name="format">Information how to load the text</param>
+ /// <returns>The range containing the data</returns>
+ public ExcelRangeBase LoadFromText(string text, ExcelTextFormat format) {
+ if (string.IsNullOrEmpty(text)) {
+ var r = _worksheet.Cells[_fromRow, _fromCol];
+ r.Value = "";
+ return r;
+ }
+
+ if (format == null) {
+ format = new();
+ }
+
+ string splitRegex = String.Format(
+ "{0}(?=(?:[^{1}]*{1}[^{1}]*{1})*[^{1}]*$)",
+ format.EOL,
+ format.TextQualifier);
+ string[] lines = Regex.Split(text, splitRegex);
+ int row = _fromRow;
+ int col = _fromCol;
+ int maxCol = col;
+ int lineNo = 1;
+ foreach (string line in lines) {
+ if (lineNo > format.SkipLinesBeginning && lineNo <= lines.Length - format.SkipLinesEnd) {
+ col = _fromCol;
+ string v = "";
+ bool isText = false,
+ isQualifier = false;
+ int qCount = 0;
+ int lineQCount = 0;
+ foreach (char c in line) {
+ if (format.TextQualifier != 0 && c == format.TextQualifier) {
+ if (!isText && v != "") {
+ throw (new(string.Format("Invalid Text Qualifier in line : {0}", line)));
+ }
+ isQualifier = !isQualifier;
+ qCount += 1;
+ lineQCount++;
+ isText = true;
+ } else {
+ if (qCount > 1 && !string.IsNullOrEmpty(v)) {
+ v += new string(format.TextQualifier, qCount / 2);
+ } else if (qCount > 2 && string.IsNullOrEmpty(v)) {
+ v += new string(format.TextQualifier, (qCount - 1) / 2);
+ }
+
+ if (isQualifier) {
+ v += c;
+ } else {
+ if (c == format.Delimiter) {
+ _worksheet.SetValue(row, col, ConvertData(format, v, col - _fromCol, isText));
+ v = "";
+ isText = false;
+ col++;
+ } else {
+ if (qCount % 2 == 1) {
+ throw (new(string.Format("Text delimiter is not closed in line : {0}", line)));
+ }
+ v += c;
+ }
+ }
+ qCount = 0;
+ }
+ }
+ if (qCount > 1) {
+ v += new string(format.TextQualifier, qCount / 2);
+ }
+ if (lineQCount % 2 == 1) {
+ throw (new(string.Format("Text delimiter is not closed in line : {0}", line)));
+ }
+
+ _worksheet._values.SetValue(row, col, ConvertData(format, v, col - _fromCol, isText));
+ if (col > maxCol) {
+ maxCol = col;
+ }
+ row++;
+ }
+ lineNo++;
+ }
+ return _worksheet.Cells[_fromRow, _fromCol, row - 1, maxCol];
+ }
+
+ /// <summary>
+ /// Loads a CSV text into a range starting from the top left cell.
+ /// </summary>
+ /// <param name="text">The Text</param>
+ /// <param name="format">Information how to load the text</param>
+ /// <param name="tableStyle">Create a table with this style</param>
+ /// <param name="firstRowIsHeader">Use the first row as header</param>
+ /// <returns></returns>
+ public ExcelRangeBase LoadFromText(
+ string text,
+ ExcelTextFormat format,
+ TableStyles tableStyle,
+ bool firstRowIsHeader) {
+ var r = LoadFromText(text, format);
+
+ var tbl = _worksheet.Tables.Add(r, "");
+ tbl.ShowHeader = firstRowIsHeader;
+ tbl.TableStyle = tableStyle;
+
+ return r;
+ }
+
+ /// <summary>
+ /// Loads a CSV file into a range starting from the top left cell.
+ /// </summary>
+ /// <param name="textFile">The Textfile</param>
+ /// <returns></returns>
+ public ExcelRangeBase LoadFromText(FileInfo textFile) {
+ return LoadFromText(File.ReadAllText(textFile.FullName, Encoding.ASCII));
+ }
+
+ /// <summary>
+ /// Loads a CSV file into a range starting from the top left cell.
+ /// </summary>
+ /// <param name="textFile">The Textfile</param>
+ /// <param name="format">Information how to load the text</param>
+ /// <returns></returns>
+ public ExcelRangeBase LoadFromText(FileInfo textFile, ExcelTextFormat format) {
+ return LoadFromText(File.ReadAllText(textFile.FullName, format.Encoding), format);
+ }
+
+ /// <summary>
+ /// Loads a CSV file into a range starting from the top left cell.
+ /// </summary>
+ /// <param name="textFile">The Textfile</param>
+ /// <param name="format">Information how to load the text</param>
+ /// <param name="tableStyle">Create a table with this style</param>
+ /// <param name="firstRowIsHeader">Use the first row as header</param>
+ /// <returns></returns>
+ public ExcelRangeBase LoadFromText(
+ FileInfo textFile,
+ ExcelTextFormat format,
+ TableStyles tableStyle,
+ bool firstRowIsHeader) {
+ return LoadFromText(
+ File.ReadAllText(textFile.FullName, format.Encoding),
+ format,
+ tableStyle,
+ firstRowIsHeader);
+ }
+
+ /// <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>
+ /// Adds a new comment for the range.
+ /// If this range contains more than one cell, the top left comment is returned by the method.
+ /// </summary>
+ /// <param name="text"></param>
+ /// <param name="author"></param>
+ /// <returns>A reference comment of the top left cell</returns>
+ public ExcelComment AddComment(string text, string author) {
+ if (string.IsNullOrEmpty(author)) {
+ author = Thread.CurrentPrincipal.Identity.Name;
+ }
+ //Check if any comments exists in the range and throw an exception
+ _changePropMethod(Exists_Comment, null);
+ //Create the comments
+ _changePropMethod(Set_Comment, new[] { text, author });
+
+ return _worksheet.Comments[new ExcelCellAddress(_fromRow, _fromCol)];
+ }
+
+ ///// <summary>
+ ///// Copies the range of cells to an other range
+ ///// </summary>
+ ///// <param name="Destination">The start cell where the range will be copied.</param>
+ public void Copy(ExcelRangeBase destination) {
+ bool sameWorkbook = destination._worksheet.Workbook == _worksheet.Workbook;
+ ExcelStyles sourceStyles = _worksheet.Workbook.Styles,
+ styles = destination._worksheet.Workbook.Styles;
+ Dictionary<int, int> styleCashe = new Dictionary<int, int>();
+
+ //Clear all existing cells;
+ int toRow = _toRow - _fromRow + 1,
+ toCol = _toCol - _fromCol + 1;
+
+ string s = "";
+ int i = 0;
+ object o = null;
+ byte flag = 0;
+ Uri hl = null;
+ ExcelComment comment = null;
+
+ var cse = new CellsStoreEnumerator<object>(
+ _worksheet._values,
+ _fromRow,
+ _fromCol,
+ _toRow,
+ _toCol);
+ var copiedValue = new List<CopiedCell>();
+ while (cse.Next()) {
+ var row = cse.Row;
+ var col = cse.Column; //Issue 15070
+ var cell = new CopiedCell {
+ Row = destination._fromRow + (row - _fromRow),
+ Column = destination._fromCol + (col - _fromCol),
+ Value = cse.Value,
+ };
+
+ //Destination._worksheet._values.SetValue(row, col, cse.Value);
+
+ if (_worksheet._types.Exists(row, col, ref s)) {
+ //Destination._worksheet._types.SetValue(row, col,s);
+ cell.Type = s;
+ }
+
+ if (_worksheet._formulas.Exists(row, col, ref o)) {
+ if (o is int) {
+ // Destination._worksheet._formulas.SetValue(row, col, _worksheet.GetFormula(cse.Row, cse.Column)); //Shared formulas, set the formula per cell to simplify
+ cell.Formula = _worksheet.GetFormula(cse.Row, cse.Column);
+ } else {
+ //Destination._worksheet._formulas.SetValue(row, col, o);
+ cell.Formula = o;
+ }
+ }
+ if (_worksheet._styles.Exists(row, col, ref i)) {
+ if (sameWorkbook) {
+ //Destination._worksheet._styles.SetValue(row, col, i);
+ cell.StyleID = i;
+ } else {
+ if (styleCashe.ContainsKey(i)) {
+ i = styleCashe[i];
+ } else {
+ var oldStyleId = i;
+ i = styles.CloneStyle(sourceStyles, i);
+ styleCashe.Add(oldStyleId, i);
+ }
+ //Destination._worksheet._styles.SetValue(row, col, i);
+ cell.StyleID = i;
+ }
+ }
+
+ if (_worksheet._hyperLinks.Exists(row, col, ref hl)) {
+ //Destination._worksheet._hyperLinks.SetValue(row, col, hl);
+ cell.HyperLink = hl;
+ }
+
+ if (_worksheet._commentsStore.Exists(row, col, ref comment)) {
+ cell.Comment = comment;
+ }
+
+ if (_worksheet._flags.Exists(row, col, ref flag)) {
+ cell.Flag = flag;
+ }
+ copiedValue.Add(cell);
+ }
+
+ //Copy styles with no cell value
+ var cses = new CellsStoreEnumerator<int>(
+ _worksheet._styles,
+ _fromRow,
+ _fromCol,
+ _toRow,
+ _toCol);
+ while (cses.Next()) {
+ if (!_worksheet._values.Exists(cses.Row, cses.Column)) {
+ var row = destination._fromRow + (cses.Row - _fromRow);
+ var col = destination._fromCol + (cses.Column - _fromCol);
+ var cell = new CopiedCell {
+ Row = row,
+ Column = col,
+ Value = null,
+ };
+
+ i = cses.Value;
+ if (sameWorkbook) {
+ cell.StyleID = i;
+ } else {
+ if (styleCashe.ContainsKey(i)) {
+ i = styleCashe[i];
+ } else {
+ var oldStyleId = i;
+ i = styles.CloneStyle(sourceStyles, i);
+ styleCashe.Add(oldStyleId, i);
+ }
+ //Destination._worksheet._styles.SetValue(row, col, i);
+ cell.StyleID = i;
+ }
+ copiedValue.Add(cell);
+ }
+ }
+ var copiedMergedCells = new Dictionary<int, ExcelAddress>();
+ //Merged cells
+ var csem = new CellsStoreEnumerator<int>(
+ _worksheet.MergedCells._cells,
+ _fromRow,
+ _fromCol,
+ _toRow,
+ _toCol);
+ while (csem.Next()) {
+ if (!copiedMergedCells.ContainsKey(csem.Value)) {
+ var adr = new ExcelAddress(_worksheet.Name, _worksheet.MergedCells.List[csem.Value]);
+ if (Collide(adr) == eAddressCollition.Inside) {
+ copiedMergedCells.Add(
+ csem.Value,
+ new(
+ destination._fromRow + (adr.Start.Row - _fromRow),
+ destination._fromCol + (adr.Start.Column - _fromCol),
+ destination._fromRow + (adr.End.Row - _fromRow),
+ destination._fromCol + (adr.End.Column - _fromCol)));
+ } else {
+ //Partial merge of the address ignore.
+ copiedMergedCells.Add(csem.Value, null);
+ }
+ }
+ }
+
+ destination._worksheet.MergedCells.Clear(
+ new(
+ destination._fromRow,
+ destination._fromCol,
+ destination._fromRow + toRow - 1,
+ destination._fromCol + toCol - 1));
+
+ destination._worksheet._values.Clear(destination._fromRow, destination._fromCol, toRow, toCol);
+ destination._worksheet._formulas.Clear(
+ destination._fromRow,
+ destination._fromCol,
+ toRow,
+ toCol);
+ destination._worksheet._styles.Clear(destination._fromRow, destination._fromCol, toRow, toCol);
+ destination._worksheet._types.Clear(destination._fromRow, destination._fromCol, toRow, toCol);
+ destination._worksheet._hyperLinks.Clear(
+ destination._fromRow,
+ destination._fromCol,
+ toRow,
+ toCol);
+ destination._worksheet._flags.Clear(destination._fromRow, destination._fromCol, toRow, toCol);
+ destination._worksheet._commentsStore.Clear(
+ destination._fromRow,
+ destination._fromCol,
+ toRow,
+ toCol);
+
+ foreach (var cell in copiedValue) {
+ destination._worksheet._values.SetValue(cell.Row, cell.Column, cell.Value);
+
+ if (cell.Type != null) {
+ destination._worksheet._types.SetValue(cell.Row, cell.Column, cell.Type);
+ }
+
+ if (cell.StyleID != null) {
+ destination._worksheet._styles.SetValue(cell.Row, cell.Column, cell.StyleID.Value);
+ }
+
+ if (cell.Formula != null) {
+ cell.Formula = UpdateFormulaReferences(
+ cell.Formula.ToString(),
+ destination._fromRow - _fromRow,
+ destination._fromCol - _fromCol,
+ 0,
+ 0,
+ true);
+ destination._worksheet._formulas.SetValue(cell.Row, cell.Column, cell.Formula);
+ }
+ if (cell.HyperLink != null) {
+ destination._worksheet._hyperLinks.SetValue(cell.Row, cell.Column, cell.HyperLink);
+ }
+
+ if (cell.Comment != null) {
+ //Destination._worksheet._commentsStore.SetValue(cell.Row, cell.Column, cell.Comment);
+ }
+ if (cell.Flag != 0) {
+ destination._worksheet._flags.SetValue(cell.Row, cell.Column, cell.Flag);
+ }
+ }
+
+ //Add merged cells
+ foreach (var m in copiedMergedCells.Values) {
+ if (m != null) {
+ destination._worksheet.MergedCells.Add(m, true);
+ }
+ }
+
+ //Clone the cell
+ //var copiedCell = (_worksheet._cells[GetCellID(_worksheet.SheetID, cell._fromRow, cell.column)] as ExcelCell);
+
+ //var newCell = copiedCell.Clone(Destination._worksheet,
+ // Destination._fromRow + (copiedCell.Row - _fromRow),
+ // Destination.column + (copiedCell.Column - column));
+
+ // newCell.MergeId = _worksheet.GetMergeCellId(copiedCell.Row, copiedCell.Column);
+
+ // if (!string.IsNullOrEmpty(newCell.Formula))
+ // {
+ // newCell.Formula = ExcelCell.UpdateFormulaReferences(newCell.Formula, newCell.Row - copiedCell.Row, (newCell.Column - copiedCell.Column), 1, 1);
+ // }
+
+ // //If its not the same workbook we must copy the styles to the new workbook.
+ // if (!sameWorkbook)
+ // {
+ // if (styleCashe.ContainsKey(cell.StyleID))
+ // {
+ // newCell.StyleID = styleCashe[cell.StyleID];
+ // }
+ // else
+ // {
+ // newCell.StyleID = styles.CloneStyle(sourceStyles, cell.StyleID);
+ // styleCashe.Add(cell.StyleID, newCell.StyleID);
+ // }
+ // }
+ // newCells.Add(newCell);
+ // if (newCell.Merge) mergedCells.Add(newCell.CellID, newCell);
+ // }
+
+ // //Now clear the destination.
+ // Destination.Offset(0, 0, (_toRow - _fromRow) + 1, (_toCol - column) + 1).Clear();
+
+ // //And last add the new cells to the worksheet
+ // foreach (var cell in newCells)
+ // {
+ // Destination.Worksheet._cells.Add(cell);
+ // }
+ // //Add merged cells
+ // if (mergedCells.Count > 0)
+ // {
+ // List<ExcelAddressBase> mergedAddresses = new List<ExcelAddressBase>();
+ // foreach (var cell in mergedCells.Values)
+ // {
+ // if (!IsAdded(cell, mergedAddresses))
+ // {
+ // int startRow = cell.Row, startCol = cell.Column, endRow = cell.Row, endCol = cell.Column + 1;
+ // while (mergedCells.ContainsKey(ExcelCell.GetCellID(Destination.Worksheet.SheetID, endRow, endCol)))
+ // {
+ // ExcelCell next = mergedCells[ExcelCell.GetCellID(Destination.Worksheet.SheetID, endRow, endCol)];
+ // if (cell.MergeId != next.MergeId)
+ // {
+ // break;
+ // }
+ // endCol++;
+ // }
+
+ // while (IsMerged(mergedCells, Destination.Worksheet, endRow, startCol, endCol - 1, cell))
+ // {
+ // endRow++;
+ // }
+
+ // mergedAddresses.Add(new ExcelAddressBase(startRow, startCol, endRow - 1, endCol - 1));
+ // }
+ // }
+ // Destination.Worksheet.MergedCells.List.AddRange((from r in mergedAddresses select r.Address));
+ // }
+ //}
+
+ //private bool IsAdded(ExcelCell cell, List<ExcelAddressBase> mergedAddresses)
+ //{
+ // foreach (var address in mergedAddresses)
+ // {
+ // if (address.Collide(new ExcelAddressBase(cell.CellAddress)) == eAddressCollition.Inside)
+ // {
+ // return true;
+ // }
+ // }
+ // return false;
+ //}
+
+ //private bool IsMerged(Dictionary<ulong, ExcelCell> mergedCells, ExcelWorksheet worksheet, int row, int startCol, int endCol, ExcelCell cell)
+ //{
+ // for (int col = startCol; col <= endCol; col++)
+ // {
+ // if (!mergedCells.ContainsKey(ExcelCell.GetCellID(worksheet.SheetID, row, col)))
+ // {
+ // return false;
+ // }
+ // else
+ // {
+ // ExcelCell next = mergedCells[ExcelCell.GetCellID(worksheet.SheetID, row, col)];
+ // if (cell.MergeId != next.MergeId)
+ // {
+ // return false;
+ // }
+ // }
+ // }
+ // return true;
+ }
+
+ /// <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);
+ }
+ }
+ }
+
+ private void DeleteCheckMergedCells(ExcelAddressBase range) {
+ var removeItems = new List<string>();
+ foreach (var addr in Worksheet.MergedCells) {
+ var addrCol = range.Collide(new ExcelAddress(range.WorkSheet, addr));
+ if (addrCol != eAddressCollition.No) {
+ if (addrCol == eAddressCollition.Inside) {
+ removeItems.Add(addr);
+ } else {
+ throw (new InvalidOperationException(
+ "Can't remove/overwrite a part of cells that are merged"));
+ }
+ }
+ }
+ foreach (var item in removeItems) {
+ Worksheet.MergedCells.Remove(item);
+ }
+ }
+
+ 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
index 39853ca..684a49c 100644
--- a/EPPlus/ExcelRangeCopyOptionFlags.cs
+++ b/EPPlus/ExcelRangeCopyOptionFlags.cs
@@ -1,16 +1,14 @@
using System;
-namespace OfficeOpenXml
-{
- /// <summary>
- /// Flag enum, specify all flags that you want to exclude from the copy.
- /// </summary>
- [Flags]
- public enum ExcelRangeCopyOptionFlags : int
- {
- /// <summary>
- /// Exclude formulas from being copied
- /// </summary>
- ExcludeFormulas = 0x1,
- }
+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
index 18eaf34..fbb0db3 100644
--- a/EPPlus/ExcelRow.cs
+++ b/EPPlus/ExcelRow.cs
@@ -13,17 +13,17 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
@@ -33,352 +33,264 @@
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;
- internal int MergeID;
- internal RowInternal Clone()
- {
- return new RowInternal()
- {
- Height=Height,
- Hidden=Hidden,
- Collapsed=Collapsed,
- OutlineLevel=OutlineLevel,
- PageBreak=PageBreak,
- Phonetic=Phonetic,
- CustomHeight=CustomHeight,
- MergeID=MergeID
- };
- }
+
+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;
+ internal int MergeID;
+
+ internal RowInternal Clone() {
+ return new() {
+ Height = Height,
+ Hidden = Hidden,
+ Collapsed = Collapsed,
+ OutlineLevel = OutlineLevel,
+ PageBreak = PageBreak,
+ Phonetic = Phonetic,
+ CustomHeight = CustomHeight,
+ MergeID = MergeID,
+ };
+ }
+}
+
+/// <summary>
+/// Represents an individual row in the spreadsheet.
+/// </summary>
+public class ExcelRow : IRangeId {
+ private ExcelWorksheet _worksheet;
+ private 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 {
+ get { return (_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;
}
- /// <summary>
- /// Represents an individual row in the spreadsheet.
- /// </summary>
- public class ExcelRow : IRangeID
- {
- private ExcelWorksheet _worksheet;
- private XmlElement _rowElement = null;
- /// <summary>
- /// Internal RowID.
- /// </summary>
- [Obsolete]
- public ulong RowID
- {
- get
- {
- return GetRowID(_worksheet.SheetID, Row);
- }
- }
- #region ExcelRow Constructor
- /// <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;
- }
- #endregion
-
- /// <summary>
- /// Provides access to the node representing the row.
- /// </summary>
- internal XmlNode Node { get { return (_rowElement); } }
-
- #region ExcelRow Hidden
- /// <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;
- }
- else
- {
- return r.Hidden;
- }
- }
- set
- {
- var r = GetRowInternal();
- r.Hidden=value;
- }
- }
- #endregion
-
- #region ExcelRow Height
- /// <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;
- }
- else
- {
- 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;
- }
- else
- {
- return r.CustomHeight;
- }
- }
- set
- {
- var r = GetRowInternal();
- r.CustomHeight = value;
- }
- }
- #endregion
-
- internal string _styleName = "";
- /// <summary>
- /// Sets the style for the entire column using a style name.
- /// </summary>
- public string StyleName
- {
- get
- {
- return _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
- {
- return _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;
- }
- else
- {
- 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;
- }
- else
- {
- 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 RowInternal();
- _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;
- }
- else
- {
- 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
- {
- get
- {
- return _worksheet.Workbook.Styles.GetStyleObject(StyleID,_worksheet.PositionID ,Row.ToString() + ":" + Row.ToString());
- }
- }
- /// <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;
- }
- else
- {
- return r.PageBreak;
- }
- }
- set
- {
- var r = GetRowInternal();
- r.PageBreak = value;
- }
- }
- public bool Merged
- {
- get
- {
- return _worksheet.MergedCells[Row, 0] != null;
- }
- set
- {
- _worksheet.MergedCells.Add(new ExcelAddressBase(Row, 1, Row, ExcelPackage.MaxColumns), true);
- }
- }
- internal static ulong GetRowID(int sheetID, int row)
- {
- return ((ulong)sheetID) + (((ulong)row) << 29);
-
- }
-
- #region IRangeID Members
-
- [Obsolete]
- ulong IRangeID.RangeID
- {
- get
- {
- return RowID;
- }
- set
- {
- Row = ((int)(value >> 29));
- }
- }
-
- #endregion
- /// <summary>
- /// Copies the current row to a new worksheet
- /// </summary>
- /// <param name="added">The worksheet where the copy will be created</param>
- internal void Clone(ExcelWorksheet added)
- {
- ExcelRow newRow = added.Row(Row);
- newRow.Collapsed = Collapsed;
- newRow.Height = Height;
- newRow.Hidden = Hidden;
- newRow.OutlineLevel = OutlineLevel;
- newRow.PageBreak = PageBreak;
- newRow.Phonetic = Phonetic;
- newRow._styleName = _styleName;
- newRow.StyleID = StyleID;
- }
+ 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 { return _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 { return _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 {
+ get {
+ return _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 { return _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 { return RowID; }
+ set { Row = ((int)(value >> 29)); }
+ }
+
+ /// <summary>
+ /// Copies the current row to a new worksheet
+ /// </summary>
+ /// <param name="added">The worksheet where the copy will be created</param>
+ internal void Clone(ExcelWorksheet added) {
+ ExcelRow newRow = added.Row(Row);
+ newRow.Collapsed = Collapsed;
+ newRow.Height = Height;
+ newRow.Hidden = Hidden;
+ newRow.OutlineLevel = OutlineLevel;
+ newRow.PageBreak = PageBreak;
+ newRow.Phonetic = Phonetic;
+ newRow._styleName = _styleName;
+ newRow.StyleID = StyleID;
+ }
}
diff --git a/EPPlus/ExcelSheetProtection.cs b/EPPlus/ExcelSheetProtection.cs
index 2caa7b9..bc7996d 100644
--- a/EPPlus/ExcelSheetProtection.cs
+++ b/EPPlus/ExcelSheetProtection.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,290 +13,203 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Xml;
-namespace OfficeOpenXml
-{
- /// <summary>
- /// Sheet protection
- ///<seealso cref="ExcelEncryption"/>
- ///<seealso cref="ExcelProtection"/>
- /// </summary>
- public sealed class ExcelSheetProtection : XmlHelper
- {
- internal ExcelSheetProtection (XmlNamespaceManager nsm, XmlNode topNode,ExcelWorksheet ws) :
- base(nsm, topNode)
- {
- SchemaNodeOrder = ws.SchemaNodeOrder;
- }
- private const string _isProtectedPath="d:sheetProtection/@sheet";
- /// <summary>
- /// If the worksheet is protected.
- /// </summary>
- public bool IsProtected
- {
- get
- {
- return 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
- {
- return !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
- {
- return !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
- {
- return !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
- {
- return !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
- {
- return !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
- {
- return !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
- {
- return !GetXmlNodeBool(_allowFormatRowsPath, true);
- }
- set
- {
- SetXmlNodeBool(_allowFormatRowsPath, !value, true);
- }
- }
+namespace OfficeOpenXml;
- private const string _allowInsertColumnsPath = "d:sheetProtection/@insertColumns";
- /// <summary>
- /// Allow users to insert columns
- /// </summary>
- public bool AllowInsertColumns
- {
- get
- {
- return !GetXmlNodeBool(_allowInsertColumnsPath, true);
- }
- set
- {
- SetXmlNodeBool(_allowInsertColumnsPath, !value, true);
- }
- }
+/// <summary>
+/// Sheet protection
+///<seealso cref="ExcelEncryption"/>
+///<seealso cref="ExcelProtection"/>
+/// </summary>
+public sealed class ExcelSheetProtection : XmlHelper {
+ internal ExcelSheetProtection(XmlNamespaceManager nsm, XmlNode topNode, ExcelWorksheet ws)
+ : base(nsm, topNode) {
+ SchemaNodeOrder = ws.SchemaNodeOrder;
+ }
- private const string _allowInsertRowsPath = "d:sheetProtection/@insertRows";
- /// <summary>
- /// Allow users to Format rows
- /// </summary>
- public bool AllowInsertRows
- {
- get
- {
- return !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
- {
- return !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
- {
- return !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
- {
- return !GetXmlNodeBool(_allowDeleteRowsPath, true);
- }
- set
- {
- SetXmlNodeBool(_allowDeleteRowsPath, !value, true);
- }
- }
+ private const string _isProtectedPath = "d:sheetProtection/@sheet";
- private const string _allowSortPath = "d:sheetProtection/@sort";
- /// <summary>
- /// Allow users to sort a range
- /// </summary>
- public bool AllowSort
- {
- get
- {
- return !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
- {
- return !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
- {
- return !GetXmlNodeBool(_allowPivotTablesPath, true);
- }
- set
- {
- SetXmlNodeBool(_allowPivotTablesPath, !value, true);
- }
- }
+ /// <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
index da408fe..6ca76f9 100644
--- a/EPPlus/ExcelStyleCollection.cs
+++ b/EPPlus/ExcelStyleCollection.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,132 +13,114 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
using System.Xml;
-using System.Linq;
-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;
- }
- bool _setNextIdManual;
- public ExcelStyleCollection(bool SetNextIdManual)
- {
- _setNextIdManual = SetNextIdManual;
- }
- public XmlNode TopNode { get; set; }
- internal List<T> _list = new List<T>();
- Dictionary<string, int> _dic = new Dictionary<string, int>(StringComparer.InvariantCultureIgnoreCase);
- internal int NextId=0;
- #region IEnumerable<T> Members
- public IEnumerator<T> GetEnumerator()
- {
- return _list.GetEnumerator();
- }
+namespace OfficeOpenXml;
- #endregion
- #region IEnumerable Members
+/// <summary>
+/// Base collection class for styles.
+/// </summary>
+/// <typeparam name="T">The style type</typeparam>
+public class ExcelStyleCollection<T> : IEnumerable<T> {
+ public ExcelStyleCollection() {
+ _setNextIdManual = false;
+ }
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return _list.GetEnumerator();
- }
- #endregion
- public T this[int PositionID]
- {
- get
- {
- return _list[PositionID];
- }
- }
- public int Count
- {
- get
- {
- return _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;
- }
- else
- {
- return false;
- }
- }
- /// <summary>
- /// Find Index
- /// </summary>
- /// <param name="key"></param>
- /// <returns></returns>
- internal int FindIndexByID(string key)
- {
- if (_dic.ContainsKey(key))
- {
- return _dic[key];
- }
- else
- {
- return int.MinValue;
- }
- }
- internal bool ExistsKey(string key)
- {
- return _dic.ContainsKey(key);
- }
- internal void Sort(Comparison<T> c)
- {
- _list.Sort(c);
- }
+ private bool _setNextIdManual;
+
+ public ExcelStyleCollection(bool setNextIdManual) {
+ _setNextIdManual = setNextIdManual;
+ }
+
+ public XmlNode TopNode { get; set; }
+
+ internal List<T> _list = new();
+ private 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 {
+ get { return _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
index cfaed4d..086189d 100644
--- a/EPPlus/ExcelStyles.cs
+++ b/EPPlus/ExcelStyles.cs
@@ -13,993 +13,877 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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 System.Linq;
using System.Collections.Generic;
-using OfficeOpenXml.Style;
-using OfficeOpenXml.Style.XmlAccess;
-using OfficeOpenXml.Style.Dxf;
+using System.Linq;
+using System.Xml;
using OfficeOpenXml.ConditionalFormatting;
-namespace OfficeOpenXml
-{
- /// <summary>
- /// Containts all shared cell styles for a workbook
- /// </summary>
- public sealed class ExcelStyles : XmlHelper
- {
- const string NumberFormatsPath = "d:styleSheet/d:numFmts";
- const string FontsPath = "d:styleSheet/d:fonts";
- const string FillsPath = "d:styleSheet/d:fills";
- const string BordersPath = "d:styleSheet/d:borders";
- const string CellStyleXfsPath = "d:styleSheet/d:cellStyleXfs";
- const string CellXfsPath = "d:styleSheet/d:cellXfs";
- const string CellStylesPath = "d:styleSheet/d:cellStyles";
- const string dxfsPath = "d:styleSheet/d:dxfs";
+using OfficeOpenXml.Style;
+using OfficeOpenXml.Style.Dxf;
+using OfficeOpenXml.Style.XmlAccess;
- //internal Dictionary<int, ExcelXfs> Styles = new Dictionary<int, ExcelXfs>();
- XmlDocument _styleXml;
- ExcelWorkbook _wb;
- XmlNamespaceManager _nameSpaceManager;
- internal int _nextDfxNumFmtID = 164;
- internal ExcelStyles(XmlNamespaceManager NameSpaceManager, XmlDocument xml, ExcelWorkbook wb) :
- base(NameSpaceManager, xml)
- {
- _styleXml=xml;
- _wb = wb;
- _nameSpaceManager = NameSpaceManager;
- SchemaNodeOrder = new string[] { "numFmts", "fonts", "fills", "borders", "cellStyleXfs", "cellXfs", "cellStyles", "dxfs" };
- LoadFromDocument();
+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 XmlDocument _styleXml;
+ private ExcelWorkbook _wb;
+ private XmlNamespaceManager _nameSpaceManager;
+ internal int _nextDfxNumFmtID = 164;
+
+ internal ExcelStyles(XmlNamespaceManager nameSpaceManager, XmlDocument xml, ExcelWorkbook wb)
+ : base(nameSpaceManager, xml) {
+ _styleXml = xml;
+ _wb = wb;
+ _nameSpaceManager = nameSpaceManager;
+ SchemaNodeOrder = new[] {
+ "numFmts",
+ "fonts",
+ "fills",
+ "borders",
+ "cellStyleXfs",
+ "cellXfs",
+ "cellStyles",
+ "dxfs",
+ };
+ 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;
}
- /// <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 ExcelFillXml(_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 ExcelStyle(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, Style.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
- lock (ws._styles)
- {
- 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, Style.StyleChangeEventArgs e, ExcelAddressBase address, ExcelWorksheet ws, ref Dictionary<int, int> styleCashe)
- {
- if (address.Start.Column == 0 || address.Start.Row == 0)
- {
- throw (new Exception("error address"));
- }
- //Columns
- else 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;
- }
- else
- {
- column = (ws._values.GetValue(0, col) as ExcelColumn);
- }
- }
-
- if (column._columnMax < address.End.Column)
- {
- var newCol = ws.Column(column._columnMax + 1) as ExcelColumn;
- 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 CellsStoreEnumerator<int>(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 CellsStoreEnumerator<int>(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;
- }
- else
- {
- if (ws._styles.Exists(row, 0, ref v)) //First Row
- {
- return v;
- }
- else // then column
- {
- if (ws._styles.Exists(0, col, ref v))
- {
- return v;
- }
- else
- {
- 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);
- }
- else
- {
- return 0;
- }
- }
- else
- {
- 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, Style.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 ExcelStyleCollection<ExcelNumberFormatXml>();
- public ExcelStyleCollection<ExcelFontXml> Fonts = new ExcelStyleCollection<ExcelFontXml>();
- public ExcelStyleCollection<ExcelFillXml> Fills = new ExcelStyleCollection<ExcelFillXml>();
- public ExcelStyleCollection<ExcelBorderXml> Borders = new ExcelStyleCollection<ExcelBorderXml>();
- public ExcelStyleCollection<ExcelXfs> CellStyleXfs = new ExcelStyleCollection<ExcelXfs>();
- public ExcelStyleCollection<ExcelXfs> CellXfs = new ExcelStyleCollection<ExcelXfs>();
- public ExcelStyleCollection<ExcelNamedStyleXml> NamedStyles = new ExcelStyleCollection<ExcelNamedStyleXml>();
- public ExcelStyleCollection<ExcelDxfStyleConditionalFormatting> Dxfs = new ExcelStyleCollection<ExcelDxfStyleConditionalFormatting>();
-
- internal string Id
- {
- get { return ""; }
- }
-
- public ExcelNamedStyleXml CreateNamedStyle(string name)
- {
- return CreateNamedStyle(name, null);
- }
- public ExcelNamedStyleXml CreateNamedStyle(string name, ExcelStyle Template)
- {
- if (_wb.Styles.NamedStyles.ExistsKey(name))
- {
- throw new Exception(string.Format("Key {0} already exists in collection", name));
- }
-
- ExcelNamedStyleXml style;
- style = new ExcelNamedStyleXml(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 ExcelStyle(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;
- }
- else
- {
- return 0;
- //throw(new Exception("Named style does not exist"));
- }
- }
- #region XmlHelpFunctions
- private int GetXmlNodeInt(XmlNode node)
- {
- int i;
- if (int.TryParse(GetXmlNode(node), out i))
- {
- return i;
- }
- else
- {
- return 0;
- }
- }
- private string GetXmlNode(XmlNode node)
- {
- if (node == null)
- {
- return "";
- }
- if (node.Value != null)
- {
- return node.Value;
- }
- else
- {
- return "";
- }
- }
-
-#endregion
- 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)
- {
- ExcelXfs xfs;
- lock (style)
- {
- if (isNamedStyle)
- {
- xfs = style.CellStyleXfs[styleID];
- }
- else
- {
- xfs = 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;
- }
- }
+ }
}
+
+ //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
+ lock (ws._styles) {
+ 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 int GetXmlNodeInt(XmlNode node) {
+ int i;
+ if (int.TryParse(GetXmlNode(node), out i)) {
+ return i;
+ }
+ return 0;
+ }
+
+ 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) {
+ ExcelXfs xfs;
+ lock (style) {
+ if (isNamedStyle) {
+ xfs = style.CellStyleXfs[styleId];
+ } else {
+ xfs = 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
index 0484925..83b0c59 100644
--- a/EPPlus/ExcelTextFormat.cs
+++ b/EPPlus/ExcelTextFormat.cs
@@ -13,119 +13,127 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
-using System.Collections.Generic;
-using System.Text;
-using System.Globalization;
-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()
- {
- Delimiter = ',';
- TextQualifier = '\0';
- EOL = "\r\n";
- Culture = CultureInfo.InvariantCulture;
- DataTypes=null;
- SkipLinesBeginning = 0;
- SkipLinesEnd = 0;
- Encoding=Encoding.ASCII;
- }
- /// <summary>
- /// Delimiter character
- /// </summary>
- public char Delimiter { get; set; }
- /// <summary>
- /// Text qualifier character
- /// </summary>
- public char TextQualifier {get; set; }
- /// <summary>
- /// End of line characters. Default CRLF
- /// </summary>
- public string EOL { get; set; }
- /// <summary>
- /// Datatypes list for each column (if column is not present Unknown is assumed)
- /// </summary>
- public eDataTypes[] DataTypes { get; set; }
- /// <summary>
- /// Culture used when parsing. Default CultureInfo.InvariantCulture
- /// </summary>
- public CultureInfo Culture {get; set; }
- /// <summary>
- /// Number of lines skiped in the begining of the file. Default 0.
- /// </summary>
- public int SkipLinesBeginning { get; set; }
- /// <summary>
- /// Number of lines skiped at the end of the file. Default 0.
- /// </summary>
- public int SkipLinesEnd { get; set; }
- /// <summary>
- /// Only used when reading files from disk using a FileInfo object. Default AscII
- /// </summary>
- public Encoding Encoding { get; set; }
- }
+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() {
+ Delimiter = ',';
+ TextQualifier = '\0';
+ EOL = "\r\n";
+ Culture = CultureInfo.InvariantCulture;
+ DataTypes = null;
+ SkipLinesBeginning = 0;
+ SkipLinesEnd = 0;
+ Encoding = Encoding.ASCII;
+ }
+
+ /// <summary>
+ /// Delimiter character
+ /// </summary>
+ public char Delimiter { get; set; }
+
+ /// <summary>
+ /// Text qualifier character
+ /// </summary>
+ public char TextQualifier { get; set; }
+
+ /// <summary>
+ /// End of line characters. Default CRLF
+ /// </summary>
+ public string EOL { get; set; }
+
+ /// <summary>
+ /// Datatypes list for each column (if column is not present Unknown is assumed)
+ /// </summary>
+ public eDataTypes[] DataTypes { get; set; }
+
+ /// <summary>
+ /// Culture used when parsing. Default CultureInfo.InvariantCulture
+ /// </summary>
+ public CultureInfo Culture { get; set; }
+
+ /// <summary>
+ /// Number of lines skiped in the begining of the file. Default 0.
+ /// </summary>
+ public int SkipLinesBeginning { get; set; }
+
+ /// <summary>
+ /// Number of lines skiped at the end of the file. Default 0.
+ /// </summary>
+ public int SkipLinesEnd { get; set; }
+
+ /// <summary>
+ /// Only used when reading files from disk using a FileInfo object. Default AscII
+ /// </summary>
+ public Encoding Encoding { get; set; }
}
diff --git a/EPPlus/ExcelWorkbook.cs b/EPPlus/ExcelWorkbook.cs
index f529826..ada35ea 100644
--- a/EPPlus/ExcelWorkbook.cs
+++ b/EPPlus/ExcelWorkbook.cs
@@ -13,936 +13,876 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Xml;
-using System.IO;
using System.Collections.Generic;
-using System.Text;
using System.Globalization;
-using OfficeOpenXml.Utils;
+using System.IO;
+using System.Text;
+using System.Xml;
using OfficeOpenXml.FormulaParsing;
using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-using System.Drawing;
+using OfficeOpenXml.Packaging;
+using OfficeOpenXml.Utils;
-namespace OfficeOpenXml
-{
- #region Public Enum ExcelCalcMode
- /// <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
- }
- #endregion
+namespace OfficeOpenXml;
- /// <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 = false;
- }
- #region Private Properties
- internal ExcelPackage _package;
- private ExcelWorksheets _worksheets;
- private OfficeProperties _properties;
+/// <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,
- private ExcelStyles _styles;
- #endregion
+ /// <summary>
+ /// Indicates tables be excluded during automatic calculation
+ /// </summary>
+ AutomaticNoTable,
- #region ExcelWorkbook Constructor
- /// <summary>
- /// Creates a new instance of the ExcelWorkbook class.
- /// </summary>
- /// <param name="package">The parent package</param>
- /// <param name="namespaceManager">NamespaceManager</param>
- internal ExcelWorkbook(ExcelPackage package, XmlNamespaceManager namespaceManager) :
- base(namespaceManager)
- {
- _package = package;
- WorkbookUri = new Uri("/xl/workbook.xml", UriKind.Relative);
- SharedStringsUri = new Uri("/xl/sharedStrings.xml", UriKind.Relative);
- StylesUri = new Uri("/xl/styles.xml", UriKind.Relative);
+ /// <summary>
+ /// Indicates that calculations in the workbook be triggered manually by the user.
+ /// </summary>
+ Manual,
+}
- _names = new ExcelNamedRangeCollection(this);
- _namespaceManager = namespaceManager;
- TopNode = WorkbookXml.DocumentElement;
- SchemaNodeOrder = new string[] { "fileVersion", "fileSharing", "workbookPr", "workbookProtection", "bookViews", "sheets", "functionGroups", "functionPrototypes", "externalReferences", "definedNames", "calcPr", "oleSize", "customWorkbookViews", "pivotCaches", "smartTagPr", "smartTagTypes", "webPublishing", "fileRecoveryPr", };
- FullCalcOnLoad = true; //Full calculation on load by default, for both new workbooks and templates.
- GetSharedStrings();
- }
- #endregion
+/// <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;
+ }
- internal Dictionary<string, SharedStringItem> _sharedStrings = new Dictionary<string, SharedStringItem>(); //Used when reading cells.
- internal List<SharedStringItem> _sharedStringsList = new List<SharedStringItem>(); //Used when reading cells.
- internal ExcelNamedRangeCollection _names;
- internal int _nextDrawingID = 0;
- internal int _nextTableID = int.MinValue;
- internal int _nextPivotTableID = int.MinValue;
- internal XmlNamespaceManager _namespaceManager;
- internal FormulaParser _formulaParser = null;
- internal 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.GetXmlFromUri(SharedStringsUri);
- XmlNodeList nl = xml.SelectNodes("//d:sst/d:si", NameSpaceManager);
- _sharedStringsList = new List<SharedStringItem>();
- if (nl != null)
- {
- foreach (XmlNode node in nl)
- {
- XmlNode n = node.SelectSingleNode("d:t", NameSpaceManager);
- if (n != null)
- {
- _sharedStringsList.Add(new SharedStringItem() { Text = ConvertUtil.ExcelDecodeString(n.InnerText) });
- }
- else
- {
- _sharedStringsList.Add(new SharedStringItem() { 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;
+ internal ExcelPackage _package;
+ private ExcelWorksheets _worksheets;
+ private OfficeProperties _properties;
- int localSheetID;
- ExcelWorksheet nameWorksheet;
- if(!int.TryParse(elem.GetAttribute("localSheetId"), out localSheetID))
- {
- localSheetID = -1;
- nameWorksheet=null;
- }
- else
- {
- nameWorksheet=Worksheets[localSheetID + 1];
- }
- var addressType = ExcelAddressBase.IsValid(fullAddress);
- ExcelRangeBase range;
- ExcelNamedRange namedRange;
+ private ExcelStyles _styles;
- if (fullAddress.IndexOf("[") == 0)
- {
- int start = fullAddress.IndexOf("[");
- int end = fullAddress.IndexOf("]", start);
- if (start >= 0 && end >= 0)
- {
+ /// <summary>
+ /// Creates a new instance of the ExcelWorkbook class.
+ /// </summary>
+ /// <param name="package">The parent package</param>
+ /// <param name="namespaceManager">NamespaceManager</param>
+ internal ExcelWorkbook(ExcelPackage package, XmlNamespaceManager namespaceManager)
+ : base(namespaceManager) {
+ _package = package;
+ WorkbookUri = new("/xl/workbook.xml", UriKind.Relative);
+ SharedStringsUri = new("/xl/sharedStrings.xml", UriKind.Relative);
+ StylesUri = new("/xl/styles.xml", UriKind.Relative);
- string externalIndex = fullAddress.Substring(start + 1, end - start - 1);
- int index;
- if (int.TryParse(externalIndex, out index))
- {
- if (index > 0 && index <= _externalReferences.Count)
- {
- fullAddress = fullAddress.Substring(0, start) + "[" + _externalReferences[index - 1] + "]" + fullAddress.Substring(end + 1);
- }
- }
- }
- }
+ _names = new(this);
+ _namespaceManager = namespaceManager;
+ TopNode = WorkbookXml.DocumentElement;
+ SchemaNodeOrder = new[] {
+ "fileVersion",
+ "fileSharing",
+ "workbookPr",
+ "workbookProtection",
+ "bookViews",
+ "sheets",
+ "functionGroups",
+ "functionPrototypes",
+ "externalReferences",
+ "definedNames",
+ "calcPr",
+ "oleSize",
+ "customWorkbookViews",
+ "pivotCaches",
+ "smartTagPr",
+ "smartTagTypes",
+ "webPublishing",
+ "fileRecoveryPr",
+ };
+ FullCalcOnLoad = true; //Full calculation on load by default, for both new workbooks and templates.
+ GetSharedStrings();
+ }
- 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
- {
- double value;
- range = new ExcelRangeBase(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 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, _package, null);
- if (localSheetID > -1)
- {
- if (string.IsNullOrEmpty(addr._ws))
- {
- namedRange = Worksheets[localSheetID + 1].Names.Add(elem.GetAttribute("name"), new ExcelRangeBase(this, Worksheets[localSheetID + 1], fullAddress, false));
- }
- else
- {
- namedRange = Worksheets[localSheetID + 1].Names.Add(elem.GetAttribute("name"), new ExcelRangeBase(this, Worksheets[addr._ws], fullAddress, false));
- }
- }
- else
- {
- var ws = Worksheets[addr._ws];
- namedRange = _names.Add(elem.GetAttribute("name"), new ExcelRangeBase(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");
- }
- }
- }
- #region Worksheets
- /// <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 ExcelWorksheets(_package, _namespaceManager, sheetsNode);
- }
- return (_worksheets);
- }
- }
- #endregion
+ internal Dictionary<string, SharedStringItem> _sharedStrings = new(); //Used when reading cells.
+ internal List<SharedStringItem> _sharedStringsList = new(); //Used when reading cells.
+ internal ExcelNamedRangeCollection _names;
+ internal int _nextDrawingID = 0;
+ internal int _nextTableID = int.MinValue;
+ internal int _nextPivotTableID = int.MinValue;
+ internal XmlNamespaceManager _namespaceManager;
+ internal FormulaParser _formulaParser;
+ internal FormulaParserManager _parserManager;
+ internal CellStore<List<Token>> _formulaTokens;
- /// <summary>
- /// Provides access to named ranges
- /// </summary>
- public ExcelNamedRangeCollection Names
- {
- get
- {
- return _names;
- }
- }
- #region Workbook Properties
- internal FormulaParser FormulaParser
- {
- get
- {
- if (_formulaParser == null)
- {
- _formulaParser = new FormulaParser(new EpplusExcelDataProvider(_package));
- }
- return _formulaParser;
+ /// <summary>
+ /// Read shared strings to list
+ /// </summary>
+ private void GetSharedStrings() {
+ if (_package.Package.PartExists(SharedStringsUri)) {
+ var xml = _package.GetXmlFromUri(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;
+
+ int localSheetId;
+ ExcelWorksheet nameWorksheet;
+ if (!int.TryParse(elem.GetAttribute("localSheetId"), out 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);
+ int index;
+ if (int.TryParse(externalIndex, out index)) {
+ if (index > 0 && index <= _externalReferences.Count) {
+ fullAddress =
+ fullAddress.Substring(0, start)
+ + "["
+ + _externalReferences[index - 1]
+ + "]"
+ + fullAddress.Substring(end + 1);
+ }
}
+ }
}
- public FormulaParserManager FormulaParserManager
- {
- get
- {
- if (_parserManager == null)
- {
- _parserManager = new FormulaParserManager(FormulaParser);
- }
- return _parserManager;
- }
- }
+ 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
+ {
+ double value;
+ 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);
+ }
- ExcelProtection _protection = null;
- /// <summary>
- /// Access properties to protect or unprotect a workbook
- /// </summary>
- public ExcelProtection Protection
- {
- get
- {
- if (_protection == null)
- {
- _protection = new ExcelProtection(NameSpaceManager, TopNode, this);
- _protection.SchemaNodeOrder = SchemaNodeOrder;
- }
- return _protection;
- }
- }
- ExcelWorkbookView _view = null;
- /// <summary>
- /// Access to workbook view properties
- /// </summary>
- public ExcelWorkbookView View
- {
- get
- {
- if (_view == null)
- {
- _view = new ExcelWorkbookView(NameSpaceManager, TopNode, this);
- }
- return _view;
- }
- }
-
- /// <summary>
- /// URI to the workbook inside the package
- /// </summary>
- internal Uri WorkbookUri { get; private set; }
- /// <summary>
- /// URI to the styles inside the package
- /// </summary>
- internal Uri StylesUri { get; private set; }
- /// <summary>
- /// URI to the shared strings inside the package
- /// </summary>
- internal Uri SharedStringsUri { get; private set; }
- /// <summary>
- /// Returns a reference to the workbook's part within the package
- /// </summary>
- internal Packaging.ZipPackagePart Part { get { return (_package.Package.GetPart(WorkbookUri)); } }
-
- #region WorkbookXml
- private XmlDocument _workbookXml;
- /// <summary>
- /// Provides access to the XML data representing the workbook in the package.
- /// </summary>
- public XmlDocument WorkbookXml
- {
- get
- {
- if (_workbookXml == null)
- {
- CreateWorkbookXml(_namespaceManager);
- }
- return (_workbookXml);
- }
- }
- const string codeModuleNamePath = "d:workbookPr/@codeName";
- internal string CodeModuleName
- {
- get
- {
- return GetXmlNodeString(codeModuleNamePath);
+ if (fullAddress.StartsWith(
+ "\"")) //String value
+ {
+ namedRange.NameValue = fullAddress.Substring(1, fullAddress.Length - 2);
+ } else if (double.TryParse(
+ fullAddress,
+ NumberStyles.Any,
+ CultureInfo.InvariantCulture,
+ out 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, _package, 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));
}
- set
- {
- SetXmlNodeString(codeModuleNamePath,value);
- }
+ } else {
+ var ws = Worksheets[addr._ws];
+ namedRange = _names.Add(elem.GetAttribute("name"), new(this, ws, fullAddress, false));
+ }
}
- internal void CodeNameChange(string value)
- {
- CodeModuleName = value;
+ 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");
}
- 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
- {
- return 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();
- }
- }
+ _worksheets = new(_package, _namespaceManager, sheetsNode);
+ }
+ return (_worksheets);
+ }
+ }
- SetXmlNodeBool(date1904Path, value, false);
- }
+ /// <summary>
+ /// Provides access to named ranges
+ /// </summary>
+ public ExcelNamedRangeCollection Names => _names;
+
+ internal FormulaParser FormulaParser {
+ get {
+ if (_formulaParser == null) {
+ _formulaParser = new(new EpplusExcelDataProvider(_package));
+ }
+ 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 {
+ get {
+ if (_protection == null) {
+ _protection = new(NameSpaceManager, TopNode, this);
+ _protection.SchemaNodeOrder = SchemaNodeOrder;
+ }
+ return _protection;
+ }
+ }
+
+ 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 Uri WorkbookUri { get; private set; }
+
+ /// <summary>
+ /// URI to the styles inside the package
+ /// </summary>
+ internal Uri StylesUri { get; private set; }
+
+ /// <summary>
+ /// URI to the shared strings inside the package
+ /// </summary>
+ internal Uri SharedStringsUri { get; private set; }
+
+ /// <summary>
+ /// Returns a reference to the workbook's part within the package
+ /// </summary>
+ internal ZipPackagePart Part {
+ get { return (_package.Package.GetPart(WorkbookUri)); }
+ }
+
+ private XmlDocument _workbookXml;
+
+ /// <summary>
+ /// Provides access to the XML data representing the workbook in the package.
+ /// </summary>
+ public XmlDocument WorkbookXml {
+ get {
+ if (_workbookXml == null) {
+ CreateWorkbookXml(_namespaceManager);
+ }
+ return (_workbookXml);
+ }
+ }
+
+ private const string _codeModuleNamePath = "d:workbookPr/@codeName";
+
+ internal string CodeModuleName {
+ get { return 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 { return 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();
}
-
-
- /// <summary>
- /// Create or read the XML for the workbook.
- /// </summary>
- private void CreateWorkbookXml(XmlNamespaceManager namespaceManager)
- {
- if (_package.Package.PartExists(WorkbookUri))
- _workbookXml = _package.GetXmlFromUri(WorkbookUri);
- else
- {
- // create a new workbook part and add to the package
- Packaging.ZipPackagePart partWorkbook = _package.Package.CreatePart(WorkbookUri, @"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml", _package.Compression);
+ }
- // create the workbook
- _workbookXml = new XmlDocument(namespaceManager.NameTable);
-
- _workbookXml.PreserveWhitespace = ExcelPackage.preserveWhitespace;
- // create the workbook element
- XmlElement wbElem = _workbookXml.CreateElement("workbook", ExcelPackage.schemaMain);
+ SetXmlNodeBool(_date1904Path, value, false);
+ }
+ }
- // Add the relationships namespace
- wbElem.SetAttribute("xmlns:r", ExcelPackage.schemaRelationships);
+ /// <summary>
+ /// Create or read the XML for the workbook.
+ /// </summary>
+ private void CreateWorkbookXml(XmlNamespaceManager namespaceManager) {
+ if (_package.Package.PartExists(WorkbookUri)) {
+ _workbookXml = _package.GetXmlFromUri(WorkbookUri);
+ } else {
+ // create a new workbook part and add to the package
+ ZipPackagePart partWorkbook = _package.Package.CreatePart(
+ WorkbookUri,
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
+ _package.Compression);
- _workbookXml.AppendChild(wbElem);
+ // create the workbook
+ _workbookXml = new(namespaceManager.NameTable);
- // create the bookViews and workbooks element
- XmlElement bookViews = _workbookXml.CreateElement("bookViews", ExcelPackage.schemaMain);
- wbElem.AppendChild(bookViews);
- XmlElement workbookView = _workbookXml.CreateElement("workbookView", ExcelPackage.schemaMain);
- bookViews.AppendChild(workbookView);
+ _workbookXml.PreserveWhitespace = ExcelPackage._preserveWhitespace;
+ // create the workbook element
+ XmlElement wbElem = _workbookXml.CreateElement("workbook", ExcelPackage._schemaMain);
- // save it to the package
- StreamWriter stream = new StreamWriter(partWorkbook.GetStream(FileMode.Create, FileAccess.Write));
- _workbookXml.Save(stream);
- //stream.Close();
- }
- }
- #endregion
- #region StylesXml
- private XmlDocument _stylesXml;
- /// <summary>
- /// Provides access to the XML data representing the styles in the package.
- /// </summary>
- public XmlDocument StylesXml
- {
- get
- {
- if (_stylesXml == null)
- {
- if (_package.Package.PartExists(StylesUri))
- _stylesXml = _package.GetXmlFromUri(StylesUri);
- else
- {
- // create a new styles part and add to the package
- Packaging.ZipPackagePart part = _package.Package.CreatePart(StylesUri, @"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml", _package.Compression);
- // create the style sheet
+ // Add the relationships namespace
+ wbElem.SetAttribute("xmlns:r", ExcelPackage._schemaRelationships);
- 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>");
-
- _stylesXml = new XmlDocument();
- _stylesXml.LoadXml(xml.ToString());
-
- //Save it to the package
- StreamWriter stream = new StreamWriter(part.GetStream(FileMode.Create, FileAccess.Write));
+ _workbookXml.AppendChild(wbElem);
- _stylesXml.Save(stream);
- //stream.Close();
+ // create the bookViews and workbooks element
+ XmlElement bookViews = _workbookXml.CreateElement("bookViews", ExcelPackage._schemaMain);
+ wbElem.AppendChild(bookViews);
+ XmlElement workbookView = _workbookXml.CreateElement(
+ "workbookView",
+ ExcelPackage._schemaMain);
+ bookViews.AppendChild(workbookView);
- // create the relationship between the workbook and the new shared strings part
- _package.Workbook.Part.CreateRelationship(UriHelper.GetRelativeUri(WorkbookUri, StylesUri), Packaging.TargetMode.Internal, ExcelPackage.schemaRelationships + "/styles");
- }
- }
- return (_stylesXml);
- }
- set
- {
- _stylesXml = value;
- }
- }
- /// <summary>
- /// Package styles collection. Used internally to access style data.
- /// </summary>
- public ExcelStyles Styles
- {
- get
- {
- if (_styles == null)
- {
- _styles = new ExcelStyles(NameSpaceManager, StylesXml, this);
- }
- return _styles;
- }
- }
- #endregion
+ // save it to the package
+ StreamWriter stream = new StreamWriter(
+ partWorkbook.GetStream(FileMode.Create, FileAccess.Write));
+ _workbookXml.Save(stream);
+ //stream.Close();
+ }
+ }
- #region Office Document Properties
- /// <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 OfficeProperties(_package, NameSpaceManager);
- }
- return _properties;
- }
- }
- #endregion
+ private XmlDocument _stylesXml;
- #region CalcMode
- private string CALC_MODE_PATH = "d:calcPr/@calcMode";
- /// <summary>
- /// Calculation mode for the workbook.
- /// </summary>
- public ExcelCalcMode CalcMode
- {
- get
- {
- string calcMode = GetXmlNodeString(CALC_MODE_PATH);
- switch (calcMode)
- {
- case "autoNoTable":
- return ExcelCalcMode.AutomaticNoTable;
- case "manual":
- return ExcelCalcMode.Manual;
- default:
- return ExcelCalcMode.Automatic;
-
- }
- }
- set
- {
- switch (value)
- {
- case ExcelCalcMode.AutomaticNoTable:
- SetXmlNodeString(CALC_MODE_PATH, "autoNoTable") ;
- break;
- case ExcelCalcMode.Manual:
- SetXmlNodeString(CALC_MODE_PATH, "manual");
- break;
- default:
- SetXmlNodeString(CALC_MODE_PATH, "auto");
- break;
+ /// <summary>
+ /// Provides access to the XML data representing the styles in the package.
+ /// </summary>
+ public XmlDocument StylesXml {
+ get {
+ if (_stylesXml == null) {
+ if (_package.Package.PartExists(StylesUri)) {
+ _stylesXml = _package.GetXmlFromUri(StylesUri);
+ } else {
+ // create a new styles part and add to the package
+ ZipPackagePart part = _package.Package.CreatePart(
+ StylesUri,
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
+ _package.Compression);
+ // create the style sheet
- }
- }
- #endregion
- }
+ 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>");
- private const string FULL_CALC_ON_LOAD_PATH = "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
- {
- return GetXmlNodeBool(FULL_CALC_ON_LOAD_PATH);
- }
- set
- {
- SetXmlNodeBool(FULL_CALC_ON_LOAD_PATH, value);
- }
- }
- #endregion
- #region Workbook Private Methods
-
- #region Save // Workbook Save
- /// <summary>
- /// Saves the workbook and all its components to the package.
- /// For internal use only!
- /// </summary>
- internal void Save() // Workbook Save
- {
- if (Worksheets.Count == 0)
- throw new InvalidOperationException("The workbook must contain at least one worksheet");
+ _stylesXml = new();
+ _stylesXml.LoadXml(xml.ToString());
- DeleteCalcChain();
+ //Save it to the package
+ StreamWriter stream = new StreamWriter(part.GetStream(FileMode.Create, FileAccess.Write));
- const string vbaPartUri = "/xl/vbaProject.bin";
- if (!_package.Package.PartExists(new Uri(vbaPartUri, UriKind.Relative)))
- {
- if (Part.ContentType != ExcelPackage.contentTypeWorkbookDefault)
- {
- Part.ContentType = ExcelPackage.contentTypeWorkbookDefault;
- }
- }
- else
- {
- if (Part.ContentType != ExcelPackage.contentTypeWorkbookMacroEnabled)
- {
- Part.ContentType = ExcelPackage.contentTypeWorkbookMacroEnabled;
- }
- }
-
- UpdateDefinedNamesXml();
+ _stylesXml.Save(stream);
+ //stream.Close();
- // save the workbook
- if (_workbookXml != null)
- {
- _package.SavePart(WorkbookUri, _workbookXml);
- }
-
- // save the properties of the workbook
- if (_properties != null)
- {
- _properties.Save();
- }
-
- // save the style sheet
- Styles.UpdateXml();
- _package.SavePart(StylesUri, _stylesXml);
-
- // 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();
- worksheet.Part.SaveHandler = worksheet.SaveHandler;
- }
-
- var part = _package.Package.CreatePart(SharedStringsUri, ExcelPackage.contentTypeSharedString, _package.Compression);
- part.SaveHandler = SaveSharedStringHandler;
- Part.CreateRelationship(UriHelper.GetRelativeUri(WorkbookUri, SharedStringsUri), Packaging.TargetMode.Internal, ExcelPackage.schemaRelationships + "/sharedStrings");
- //UpdateSharedStringsXml();
-
- // 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 _package.Workbook.Part.GetRelationships())
- {
- if (relationship.TargetUri == calcChain)
- {
- _package.Workbook.Part.DeleteRelationship(relationship.Id);
- break;
- }
- }
- // delete the calcChain part
- _package.Package.DeletePart(uriCalcChain);
- }
- }
-
- private void ValidateDataValidations()
- {
- foreach (var sheet in _package.Workbook.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 StringBuilder();
- }
- }
- cache.Append("</sst>");
- sw.Write(cache.ToString());
- sw.Flush();
- Part.CreateRelationship(UriHelper.GetRelativeUri(WorkbookUri, SharedStringsUri), Packaging.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;
- }
- else
- {
- 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 Exception("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)
- {
- elem.InnerText = ((DateTime)name.NameValue).ToOADate().ToString(CultureInfo.InvariantCulture);
- }
- else
- {
- elem.InnerText = "\"" + name.NameValue.ToString() + "\"";
- }
- }
- 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;
- }
- #endregion
-
- #endregion
- 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), Packaging.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 List<string>();
- //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 rId_ExtRef = book.GetAttribute("r:id");
- var rel_extRef = part.GetRelationship(rId_ExtRef);
- if (rel_extRef != null)
- {
- _externalReferences.Add(rel_extRef.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;
- }
- }
- }
- }
+ // create the relationship between the workbook and the new shared strings part
+ _package.Workbook.Part.CreateRelationship(
+ UriHelper.GetRelativeUri(WorkbookUri, StylesUri),
+ TargetMode.Internal,
+ ExcelPackage._schemaRelationships + "/styles");
}
- } // end Workbook
+ }
+ return (_stylesXml);
+ }
+ set { _stylesXml = value; }
+ }
+
+ /// <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 string CALC_MODE_PATH = "d:calcPr/@calcMode";
+
+ /// <summary>
+ /// Calculation mode for the workbook.
+ /// </summary>
+ public ExcelCalcMode CalcMode {
+ get {
+ string calcMode = GetXmlNodeString(CALC_MODE_PATH);
+ switch (calcMode) {
+ case "autoNoTable":
+ return ExcelCalcMode.AutomaticNoTable;
+ case "manual":
+ return ExcelCalcMode.Manual;
+ default:
+ return ExcelCalcMode.Automatic;
+ }
+ }
+ set {
+ switch (value) {
+ case ExcelCalcMode.AutomaticNoTable:
+ SetXmlNodeString(CALC_MODE_PATH, "autoNoTable");
+ break;
+ case ExcelCalcMode.Manual:
+ SetXmlNodeString(CALC_MODE_PATH, "manual");
+ break;
+ default:
+ SetXmlNodeString(CALC_MODE_PATH, "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 { return GetXmlNodeBool(_fullCalcOnLoadPath); }
+ set { SetXmlNodeBool(_fullCalcOnLoadPath, value); }
+ }
+
+ /// <summary>
+ /// Saves the workbook and all its components to the package.
+ /// For internal use only!
+ /// </summary>
+ internal void Save() // Workbook Save
+ {
+ if (Worksheets.Count == 0) {
+ throw new InvalidOperationException("The workbook must contain at least one worksheet");
+ }
+
+ DeleteCalcChain();
+
+ const string vbaPartUri = "/xl/vbaProject.bin";
+ if (!_package.Package.PartExists(new(vbaPartUri, UriKind.Relative))) {
+ if (Part.ContentType != ExcelPackage._contentTypeWorkbookDefault) {
+ Part.ContentType = ExcelPackage._contentTypeWorkbookDefault;
+ }
+ } else {
+ if (Part.ContentType != ExcelPackage._contentTypeWorkbookMacroEnabled) {
+ Part.ContentType = ExcelPackage._contentTypeWorkbookMacroEnabled;
+ }
+ }
+
+ UpdateDefinedNamesXml();
+
+ // save the workbook
+ if (_workbookXml != null) {
+ _package.SavePart(WorkbookUri, _workbookXml);
+ }
+
+ // save the properties of the workbook
+ if (_properties != null) {
+ _properties.Save();
+ }
+
+ // save the style sheet
+ Styles.UpdateXml();
+ _package.SavePart(StylesUri, _stylesXml);
+
+ // 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();
+ worksheet.Part.SaveHandler = worksheet.SaveHandler;
+ }
+
+ var part = _package.Package.CreatePart(
+ SharedStringsUri,
+ ExcelPackage._contentTypeSharedString,
+ _package.Compression);
+ part.SaveHandler = SaveSharedStringHandler;
+ Part.CreateRelationship(
+ UriHelper.GetRelativeUri(WorkbookUri, SharedStringsUri),
+ TargetMode.Internal,
+ ExcelPackage._schemaRelationships + "/sharedStrings");
+ //UpdateSharedStringsXml();
+
+ // 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 _package.Workbook.Part.GetRelationships()) {
+ if (relationship.TargetUri == calcChain) {
+ _package.Workbook.Part.DeleteRelationship(relationship.Id);
+ break;
+ }
+ }
+ // delete the calcChain part
+ _package.Package.DeletePart(uriCalcChain);
+ }
+ }
+
+ private void ValidateDataValidations() {
+ foreach (var sheet in _package.Workbook.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) {
+ elem.InnerText =
+ ((DateTime)name.NameValue).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
index 69a1749..6772936 100644
--- a/EPPlus/ExcelWorkbookView.cs
+++ b/EPPlus/ExcelWorkbookView.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,200 +13,148 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
-using System.Collections.Generic;
+
using System.Globalization;
-using System.Text;
using System.Xml;
-namespace OfficeOpenXml
-{
- /// <summary>
- /// Access to workbook view properties
- /// </summary>
- public class ExcelWorkbookView : XmlHelper
- {
- #region ExcelWorksheetView Constructor
- /// <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)
- {
- SchemaNodeOrder = wb.SchemaNodeOrder;
- }
- #endregion
- const string LEFT_PATH="d:bookViews/d:workbookView/@xWindow";
- /// <summary>
- /// Position of the upper left corner of the workbook window. In twips.
- /// </summary>
- public int Left
- {
- get
- {
- return GetXmlNodeInt(LEFT_PATH);
- }
- internal set
- {
- SetXmlNodeString(LEFT_PATH,value.ToString());
- }
- }
- const string TOP_PATH="d:bookViews/d:workbookView/@yWindow";
- /// <summary>
- /// Position of the upper left corner of the workbook window. In twips.
- /// </summary>
- public int Top
- {
- get
- {
- return GetXmlNodeInt(TOP_PATH);
- }
- internal set
- {
- SetXmlNodeString(TOP_PATH, value.ToString());
- }
- }
- const string WIDTH_PATH="d:bookViews/d:workbookView/@windowWidth";
- /// <summary>
- /// Width of the workbook window. In twips.
- /// </summary>
- public int Width
- {
- get
- {
- return GetXmlNodeInt(WIDTH_PATH);
- }
- internal set
- {
- SetXmlNodeString(WIDTH_PATH, value.ToString());
- }
- }
- const string HEIGHT_PATH="d:bookViews/d:workbookView/@windowHeight";
- /// <summary>
- /// Height of the workbook window. In twips.
- /// </summary>
- public int Height
- {
- get
- {
- return GetXmlNodeInt(HEIGHT_PATH);
- }
- internal set
- {
- SetXmlNodeString(HEIGHT_PATH, value.ToString());
- }
- }
- const string MINIMIZED_PATH="d:bookViews/d:workbookView/@minimized";
- /// <summary>
- /// If true the the workbook window is minimized.
- /// </summary>
- public bool Minimized
- {
- get
- {
- return GetXmlNodeBool(MINIMIZED_PATH);
- }
- set
- {
- SetXmlNodeString(MINIMIZED_PATH, value.ToString());
- }
- }
- const string SHOWVERTICALSCROLL_PATH = "d:bookViews/d:workbookView/@showVerticalScroll";
- /// <summary>
- /// Show the vertical scrollbar
- /// </summary>
- public bool ShowVerticalScrollBar
- {
- get
- {
- return GetXmlNodeBool(SHOWVERTICALSCROLL_PATH,true);
- }
- set
- {
- SetXmlNodeBool(SHOWVERTICALSCROLL_PATH, value, true);
- }
- }
- const string SHOWHORIZONTALSCR_PATH = "d:bookViews/d:workbookView/@showHorizontalScroll";
- /// <summary>
- /// Show the horizontal scrollbar
- /// </summary>
- public bool ShowHorizontalScrollBar
- {
- get
- {
- return GetXmlNodeBool(SHOWHORIZONTALSCR_PATH, true);
- }
- set
- {
- SetXmlNodeBool(SHOWHORIZONTALSCR_PATH, value, true);
- }
- }
- const string SHOWSHEETTABS_PATH = "d:bookViews/d:workbookView/@showSheetTabs";
- /// <summary>
- /// Show the sheet tabs
- /// </summary>
- public bool ShowSheetTabs
- {
- get
- {
- return GetXmlNodeBool(SHOWSHEETTABS_PATH, true);
- }
- set
- {
- SetXmlNodeBool(SHOWSHEETTABS_PATH, 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;
- }
- const string ACTIVETAB_PATH = "d:bookViews/d:workbookView/@activeTab";
- public int ActiveTab
- {
- get
- {
- var v=GetXmlNodeInt(ACTIVETAB_PATH);
- if (v < 0)
- return 0;
- else
- return v;
+namespace OfficeOpenXml;
- }
- set
- {
- SetXmlNodeString(ACTIVETAB_PATH, value.ToString(CultureInfo.InvariantCulture));
- }
- }
+/// <summary>
+/// Access to workbook view properties
+/// </summary>
+public class ExcelWorkbookView : XmlHelper {
+ /// <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) {
+ SchemaNodeOrder = wb.SchemaNodeOrder;
+ }
+
+ 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));
+ }
}
-
\ No newline at end of file
diff --git a/EPPlus/ExcelWorksheet.cs b/EPPlus/ExcelWorksheet.cs
index c2bf6e7..2579a7e 100644
--- a/EPPlus/ExcelWorksheet.cs
+++ b/EPPlus/ExcelWorksheet.cs
@@ -1,4144 +1,3913 @@
- /*******************************************************************************
- * You may amend and distribute as you like, but don't remove this header!
- *
- * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
- * See http://www.codeplex.com/EPPlus for details.
- *
- * Copyright (C) 2011 Jan Källman
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+/*******************************************************************************
+* You may amend and distribute as you like, but don't remove this header!
+*
+* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
+* See http://www.codeplex.com/EPPlus for details.
+*
+* Copyright (C) 2011 Jan Källman
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
- * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
- *
- * All code and executables are provided "as is" with no warranty either express or implied.
- * The author 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
- *******************************************************************************/
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU Lesser General Public License for more details.
+*
+* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
+* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
+*
+* All code and executables are provided "as is" with no warranty either express or implied.
+* The author 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.Xml;
+using System.Collections;
using System.Collections.Generic;
-using System.IO;
-using System.Globalization;
-using System.Text;
-using System.Security;
-using OfficeOpenXml.Style.XmlAccess;
-using System.Text.RegularExpressions;
-using OfficeOpenXml.Drawing.Vml;
-using OfficeOpenXml.Table;
-using OfficeOpenXml.DataValidation;
-using OfficeOpenXml.Table.PivotTable;
using System.ComponentModel;
-using System.IO.Compression;
+using System.Globalization;
+using System.IO;
+using System.Security;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml;
using OfficeOpenXml.ConditionalFormatting;
-using OfficeOpenXml.Utils;
+using OfficeOpenXml.DataValidation;
+using OfficeOpenXml.Drawing.Vml;
using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-
-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
+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,
+ string relId,
+ Uri uriWorksheet,
+ string sheetName,
+ int sheetId,
+ int positionId,
+ eWorkSheetHidden hidden)
+ : base(ns, pck, relId, uriWorksheet, sheetName, 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;
}
- [Flags]
- internal enum CellFlags
- {
- //Merged = 0x1,
- RichText = 0x2,
- SharedFormula = 0x4,
- ArrayFormula = 0x8
+
+ 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;
}
- /// <summary>
- /// Represents an Excel Chartsheet and provides access to its properties and methods
- /// </summary>
- public class ExcelChartsheet : ExcelWorksheet
- {
- public ExcelChartsheet(XmlNamespaceManager ns, ExcelPackage pck, string relID, Uri uriWorksheet, string sheetName, int sheetID, int positionID, eWorkSheetHidden hidden) :
- base(ns, pck, relID, uriWorksheet, sheetName, sheetID, positionID, hidden)
- {
+
+ private 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>
- /// Represents an Excel worksheet and provides access to its properties and methods
- /// </summary>
- public class ExcelWorksheet : XmlHelper, IEqualityComparer<ExcelWorksheet>
- {
- internal class Formulas
+ }
+
+ /// <summary>
+ /// Collection containing merged cell addresses
+ /// </summary>
+ public class MergeCellsCollection : IEnumerable<string> {
+ internal MergeCellsCollection() {}
+
+ internal CellStore<int> _cells = new();
+ private 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
{
- 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 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;
- }
+ return List[ix];
}
- /// <summary>
- /// Collection containing merged cell addresses
- /// </summary>
- public class MergeCellsCollection : IEnumerable<string>
- {
- internal MergeCellsCollection()
- {
+ return null;
+ }
+ }
- }
- internal CellStore<int> _cells = new CellStore<int>();
- List<string> _list = new List<string>();
- internal List<string> List { get {return _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];
- }
- else
- {
- return null;
- }
- }
- }
- public string this[int index]
- {
- get
- {
- return _list[index];
- }
- }
- internal void Add(ExcelAddressBase address, bool doValidate)
- {
- int ix=0;
+ public string this[int index] => _list[index];
- //Validate
- if (doValidate && Validate(address) == false)
- {
- throw(new ArgumentException("Can't merge and already merged range"));
- }
- lock(this)
- {
- ix = _list.Count;
- _list.Add(address.Address);
- SetIndex(address, ix);
- }
- }
+ internal void Add(ExcelAddressBase address, bool doValidate) {
+ int ix = 0;
- 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;
- }
- else
- {
- 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 CellsStoreEnumerator<int>(_cells, 0, address._fromCol, 0, address._toCol);
- while (cse.Next())
- {
- return false;
- }
- //Entire row
- cse = new CellsStoreEnumerator<int>(_cells, address._fromRow, 0, address._toRow, 0);
- while (cse.Next())
- {
- return false;
- }
- return true;
- }
+ //Validate
+ if (doValidate && Validate(address) == false) {
+ throw (new ArgumentException("Can't merge and already merged range"));
+ }
+ lock (this) {
+ ix = _list.Count;
+ _list.Add(address.Address);
+ SetIndex(address, ix);
+ }
+ }
- 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
- {
- get
- {
- return _list.Count;
- }
- }
- internal void Remove(string Item)
- {
- _list.Remove(Item);
- }
- #region IEnumerable<string> Members
-
- public IEnumerator<string> GetEnumerator()
- {
- return _list.GetEnumerator();
- }
-
- #endregion
-
- #region IEnumerable Members
-
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return _list.GetEnumerator();
- }
-
- #endregion
- 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;
- }
- }
+ 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;
}
- internal CellStore<object> _values;
- internal CellStore<string> _types;
- internal CellStore<int> _styles;
- internal CellStore<object> _formulas;
- internal FlagCellStore _flags;
- internal CellStore<List<Token>> _formulaTokens;
+ return false;
+ }
- internal CellStore<Uri> _hyperLinks;
- internal CellStore<ExcelComment> _commentsStore;
+ 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 Dictionary<int, Formulas> _sharedFormulas = new Dictionary<int, Formulas>();
- internal int _minCol = ExcelPackage.MaxColumns;
- internal int _maxCol = 0;
- #region Worksheet Private Properties
- internal ExcelPackage _package;
- private Uri _worksheetUri;
- private string _name;
- private int _sheetID;
- private int _positionID;
- private string _relationshipID;
- private XmlDocument _worksheetXml;
- internal ExcelWorksheetView _sheetView;
- internal ExcelHeaderFooter _headerFooter;
- #endregion
- #region ExcelWorksheet Constructor
- /// <summary>
- /// A worksheet
- /// </summary>
- /// <param name="ns">Namespacemanager</param>
- /// <param name="excelPackage">Package</param>
- /// <param name="relID">Relationship ID</param>
- /// <param name="uriWorksheet">URI</param>
- /// <param name="sheetName">Name of the sheet</param>
- /// <param name="sheetID">Sheet id</param>
- /// <param name="positionID">Position</param>
- /// <param name="hide">hide</param>
- public ExcelWorksheet(XmlNamespaceManager ns, ExcelPackage excelPackage, string relID,
- Uri uriWorksheet, string sheetName, int sheetID, int positionID,
- eWorkSheetHidden hide) :
- base(ns, null)
- {
- SchemaNodeOrder = new string[] { "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" };
- _package = excelPackage;
- _relationshipID = relID;
- _worksheetUri = uriWorksheet;
- _name = sheetName;
- _sheetID = sheetID;
- _positionID = positionID;
- Hidden = hide;
-
- /**** Cellstore ****/
- _values=new CellStore<object>();
- _types = new CellStore<string>();
- _styles = new CellStore<int>();
- _formulas = new CellStore<object>();
- _flags = new FlagCellStore();
- _commentsStore = new CellStore<ExcelComment>();
- _hyperLinks = new CellStore<Uri>();
-
- _names = new ExcelNamedRangeCollection(Workbook,this);
+ 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);
+ }
+ }
+ }
+ }
- CreateXml();
- TopNode = _worksheetXml.DocumentElement;
+ 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 CellStore<object> _values;
+ internal CellStore<string> _types;
+ internal CellStore<int> _styles;
+ internal CellStore<object> _formulas;
+ internal FlagCellStore _flags;
+ internal CellStore<List<Token>> _formulaTokens;
+
+ internal CellStore<Uri> _hyperLinks;
+ internal CellStore<ExcelComment> _commentsStore;
+
+ internal Dictionary<int, Formulas> _sharedFormulas = new();
+ internal int _minCol = ExcelPackage.MaxColumns;
+ internal int _maxCol = 0;
+
+ internal ExcelPackage _package;
+ private Uri _worksheetUri;
+ private string _name;
+ private int _sheetID;
+ private int _positionID;
+ private string _relationshipID;
+ private XmlDocument _worksheetXml;
+ internal ExcelWorksheetView _sheetView;
+ internal ExcelHeaderFooter _headerFooter;
+
+ /// <summary>
+ /// A worksheet
+ /// </summary>
+ /// <param name="ns">Namespacemanager</param>
+ /// <param name="excelPackage">Package</param>
+ /// <param name="relId">Relationship ID</param>
+ /// <param name="uriWorksheet">URI</param>
+ /// <param name="sheetName">Name of the sheet</param>
+ /// <param name="sheetId">Sheet id</param>
+ /// <param name="positionId">Position</param>
+ /// <param name="hide">hide</param>
+ public ExcelWorksheet(
+ XmlNamespaceManager ns,
+ ExcelPackage excelPackage,
+ string relId,
+ Uri uriWorksheet,
+ string sheetName,
+ int sheetId,
+ int positionId,
+ eWorkSheetHidden hide)
+ : base(ns, null) {
+ SchemaNodeOrder = new[] {
+ "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",
+ };
+ _package = excelPackage;
+ _relationshipID = relId;
+ _worksheetUri = uriWorksheet;
+ _name = sheetName;
+ _sheetID = sheetId;
+ _positionID = positionId;
+ Hidden = hide;
+
+ /**** Cellstore ****/
+ _values = new();
+ _types = new();
+ _styles = new();
+ _formulas = new();
+ _flags = new();
+ _commentsStore = new();
+ _hyperLinks = new();
+
+ _names = new(Workbook, this);
+
+ CreateXml();
+ TopNode = _worksheetXml.DocumentElement;
+ }
+
+ /// <summary>
+ /// The Uri to the worksheet within the package
+ /// </summary>
+ internal Uri WorksheetUri => (_worksheetUri);
+
+ /// <summary>
+ /// The Zip.ZipPackagePart for the worksheet within the package
+ /// </summary>
+ internal ZipPackagePart Part => (_package.Package.GetPart(WorksheetUri));
+
+ /// <summary>
+ /// The ID for the worksheet's relationship with the workbook in the package
+ /// </summary>
+ internal string RelationshipID => (_relationshipID);
+
+ /// <summary>
+ /// The unique identifier for the worksheet.
+ /// </summary>
+ internal int SheetID => (_sheetID);
+
+ /// <summary>
+ /// The position of the worksheet.
+ /// </summary>
+ internal int PositionID {
+ get => (_positionID);
+ set => _positionID = value;
+ }
+
+ /// <summary>
+ /// The index in the worksheets collection
+ /// </summary>
+ public int Index => (_positionID);
+
+ /// <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 => (_name);
+ set {
+ if (value == _name) {
+ return;
+ }
+ value = _package.Workbook.Worksheets.ValidateFixSheetName(value);
+ foreach (var ws in Workbook.Worksheets) {
+ if (ws.PositionID != PositionID
+ && ws.Name.Equals(value, StringComparison.InvariantCultureIgnoreCase)) {
+ throw (new ArgumentException("Worksheet name must be unique"));
+ }
+ }
+ _package.Workbook.SetXmlNodeString(
+ string.Format("d:sheets/d:sheet[@sheetId={0}]/@name", _sheetID),
+ value);
+ ChangeNames(value);
+
+ _name = value;
+ }
+ }
+
+ private void ChangeNames(string value) {
+ //Renames name in this Worksheet;
+ foreach (var n in Workbook.Names) {
+ if (string.IsNullOrEmpty(n.NameFormula) && n.NameValue == null) {
+ n.ChangeWorksheet(_name, value);
+ }
+ }
+ foreach (var ws in Workbook.Worksheets) {
+ if (!(ws is ExcelChartsheet)) {
+ foreach (var n in ws.Names) {
+ if (string.IsNullOrEmpty(n.NameFormula) && n.NameValue == null) {
+ n.ChangeWorksheet(_name, value);
+ }
+ }
+ }
+ }
+ }
+
+ internal 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 = _package.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) {
+ _package.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);
+ _package.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 _tabColorPath = "d:sheetPr/d:tabColor/@rgb";
+ private const string _codeModuleNamePath = "d:sheetPr/@codeName";
+
+ internal string CodeModuleName {
+ get => GetXmlNodeString(_codeModuleNamePath);
+ set => SetXmlNodeString(_codeModuleNamePath, value);
+ }
+
+ internal void CodeNameChange(string value) {
+ CodeModuleName = 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>
+ public XmlDocument WorksheetXml => (_worksheetXml);
+
+ 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;
+ }
+ }
+ }
+
+ private void CreateXml() {
+ _worksheetXml = new();
+ _worksheetXml.PreserveWhitespace = ExcelPackage._preserveWhitespace;
+ ZipPackagePart packPart = _package.Package.GetPart(WorksheetUri);
+ string xml = "";
+
+ // First Columns, rows, cells, mergecells, hyperlinks and pagebreakes are loaded from a xmlstream to optimize speed...
+ Stream stream = packPart.GetStream();
+
+ XmlTextReader 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);
+ Encoding encoding;
+ xml = GetWorkSheetXml(stream, start, end, out encoding);
+
+ //first char is invalid sometimes??
+ if (xml[0] != '<') {
+ LoadXmlSafe(_worksheetXml, xml.Substring(1, xml.Length - 1), encoding);
+ } else {
+ LoadXmlSafe(_worksheetXml, xml, encoding);
+ }
+
+ ClearNodes();
+ }
+
+ /// <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) {
+ int id;
+ if (int.TryParse(xr.GetAttribute("id"), out 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) {
+ int id;
+ if (int.TryParse(xr.GetAttribute("id"), out 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);
+
+ int style;
+ if (!(xr.GetAttribute("style") == null
+ || !int.TryParse(xr.GetAttribute("style"), out style))) {
+ _styles.SetValue(0, min, style);
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Read until the node is found. If not found the xmlreader is reseted.
+ /// </summary>
+ /// <param name="xr">The reader</param>
+ /// <param name="nodeText">Text to search for</param>
+ /// <param name="altNode">Alternative text to search for</param>
+ /// <returns></returns>
+ private static bool ReadXmlReaderUntil(XmlTextReader xr, string nodeText, string altNode) {
+ do {
+ if (xr.LocalName == nodeText || xr.LocalName == altNode) {
+ return true;
+ }
+ } while (xr.Read());
+ xr.Close();
+ return false;
+ }
+
+ /// <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") {
+ int fromRow,
+ fromCol,
+ toRow,
+ toCol;
+ ExcelCellBase.GetRowColFromAddress(
+ xr.GetAttribute("ref"),
+ out fromRow,
+ out fromCol,
+ out toRow,
+ out 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;
}
- #endregion
- /// <summary>
- /// The Uri to the worksheet within the package
- /// </summary>
- internal Uri WorksheetUri { get { return (_worksheetUri); } }
- /// <summary>
- /// The Zip.ZipPackagePart for the worksheet within the package
- /// </summary>
- internal Packaging.ZipPackagePart Part { get { return (_package.Package.GetPart(WorksheetUri)); } }
- /// <summary>
- /// The ID for the worksheet's relationship with the workbook in the package
- /// </summary>
- internal string RelationshipID { get { return (_relationshipID); } }
- /// <summary>
- /// The unique identifier for the worksheet.
- /// </summary>
- internal int SheetID { get { return (_sheetID); } }
- /// <summary>
- /// The position of the worksheet.
- /// </summary>
- internal int PositionID { get { return (_positionID); } set { _positionID = value; } }
- #region Worksheet Public Properties
- /// <summary>
- /// The index in the worksheets collection
- /// </summary>
- public int Index { get { return (_positionID); } }
- /// <summary>
- /// Address for autofilter
- /// <seealso cref="ExcelRangeBase.AutoFilter" />
- /// </summary>
- public ExcelAddressBase AutoFilterAddress
- {
- get
- {
- CheckSheetType();
- string address = GetXmlNodeString("d:autoFilter/@ref");
- if (address == "")
- {
- return null;
- }
- else
- {
- return new ExcelAddressBase(address);
- }
- }
- internal set
- {
- CheckSheetType();
- SetXmlNodeString("d:autoFilter/@ref", value.Address);
- }
+ 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);
}
- internal void CheckSheetType()
- {
- if (this is ExcelChartsheet)
- {
- throw (new NotSupportedException("This property or method is not supported for a Chartsheet"));
- }
+ 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;
}
- /// <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 ExcelWorksheetView(NameSpaceManager, node, this);
- }
- return (_sheetView);
- }
- }
+ //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);
- /// <summary>
- /// The worksheet's display name as it appears on the tab
- /// </summary>
- public string Name
- {
- get { return (_name); }
- set
- {
- if (value == _name) return;
- value=_package.Workbook.Worksheets.ValidateFixSheetName(value);
- foreach(var ws in Workbook.Worksheets)
- {
- if(ws.PositionID!=PositionID && ws.Name.Equals(value,StringComparison.InvariantCultureIgnoreCase))
- {
- throw (new ArgumentException("Worksheet name must be unique"));
- }
- }
- _package.Workbook.SetXmlNodeString(string.Format("d:sheets/d:sheet[@sheetId={0}]/@name", _sheetID), value);
- ChangeNames(value);
+ 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;
+ }
+ }
+ //if (cell != null) cellList.Add(cell);
- _name = value;
- }
- }
+ //_cells = new RangeCollection(cellList);
+ //_rows = new RangeCollection(rowList);
+ //_formulaCells = new RangeCollection(formulaList);
+ }
- private void ChangeNames(string value)
- {
- //Renames name in this Worksheet;
- foreach (var n in Workbook.Names)
- {
- if (string.IsNullOrEmpty(n.NameFormula) && n.NameValue==null)
- {
- n.ChangeWorksheet(_name, value);
- }
- }
- foreach (var ws in Workbook.Worksheets)
- {
- if (!(ws is ExcelChartsheet))
- {
- foreach (var n in ws.Names)
- {
- if (string.IsNullOrEmpty(n.NameFormula) && n.NameValue == null)
- {
- n.ChangeWorksheet(_name, value);
- }
- }
- }
- }
- }
- internal 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=_package.Workbook.GetXmlNodeString(string.Format("d:sheets/d:sheet[@sheetId={0}]/@state", _sheetID));
- if (state == "hidden")
- {
- return eWorkSheetHidden.Hidden;
- }
- else if (state == "veryHidden")
- {
- return eWorkSheetHidden.VeryHidden;
- }
- return eWorkSheetHidden.Visible;
- }
- set
- {
- if (value == eWorkSheetHidden.Visible)
- {
- _package.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);
- _package.Workbook.SetXmlNodeString(string.Format("d:sheets/d:sheet[@sheetId={0}]/@state", _sheetID),v );
- }
- }
- }
- 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);
+ private bool DoAddRow(XmlTextReader xr) {
+ var c = xr.GetAttribute("r") == null ? 0 : 1;
+ if (xr.GetAttribute("spans") != null) {
+ c++;
+ }
+ return xr.AttributeCount > c;
+ }
- 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));
+ /// <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");
+ //int fromRow, fromCol, toRow, toCol;
+ //ExcelCellBase.GetRowColFromAddress(address, out fromRow, out fromCol, out toRow, out toCol);
+ //for (int row = fromRow; row <= toRow; row++)
+ //{
+ // for (int col = fromCol; col <= toCol; col++)
+ // {
+ // _flags.SetFlagValue(row, col, true,CellFlags.Merged);
+ // }
+ //}
+ //_mergedCells.List.Add(address);
+ _mergedCells.Add(new ExcelAddress(address), false);
+ }
+ }
+ }
+ }
- if (double.IsNaN(GetXmlNodeDouble("d:sheetFormatPr/@defaultRowHeight")))
- {
- DefaultRowHeight = 15;
- }
- }
+ /// <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 >= _package.Workbook._sharedStringsList.Count) {
+ throw new(
+ string.Format(
+ "ReadElementContentAsInt returned index value '{0}' which is greater than _sharedStringsList count of {1}.",
+ ix,
+ _package.Workbook._sharedStringsList.Count));
+ }
+
+ _values.SetValue(row, col, _package.Workbook._sharedStringsList[ix].Text);
+ if (_package.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
+ {
+ double res;
+ if (double.TryParse(v, NumberStyles.Any, CultureInfo.InvariantCulture, out 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);
}
- /** <outlinePr applyStyles="1" summaryBelow="0" summaryRight="0" /> **/
- 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");
- }
+ } else if ((nf >= 14 && nf <= 19)
+ || (nf
+ == 22)) // DateTime
+ {
+ double res;
+ if (double.TryParse(v, NumberStyles.Any, CultureInfo.InvariantCulture, out 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);
}
- 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");
- }
+ } else {
+ double d;
+ if (double.TryParse(v, NumberStyles.Any, CultureInfo.InvariantCulture, out 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);
}
- 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 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);
+ //}
+ }
+
+ //private string GetSharedString(int stringID)
+ //{
+ // string retValue = null;
+ // XmlNodeList stringNodes = xlPackage.Workbook.SharedStringsXml.SelectNodes(string.Format("//d:si", stringID), NameSpaceManager);
+ // XmlNode stringNode = stringNodes[stringID];
+ // if (stringNode != null)
+ // retValue = stringNode.InnerText;
+ // return (retValue);
+ //}
+
+
+
+ /// <summary>
+ /// A reference to the header and footer class which allows you to
+ /// set the header and footer for all odd, even and first pages of the worksheet
+ /// </summary>
+ /// <remarks>
+ /// To format the text you can use the following format
+ /// <list type="table">
+ /// <listheader><term>Prefix</term><description>Description</description></listheader>
+ /// <item><term>&U</term><description>Underlined</description></item>
+ /// <item><term>&E</term><description>Double Underline</description></item>
+ /// <item><term>&K:xxxxxx</term><description>Color. ex &K:FF0000 for red</description></item>
+ /// <item><term>&"Font,Regular Bold Italic"</term><description>Changes the font. Regular or Bold or Italic or Bold Italic can be used. ex &"Arial,Bold Italic"</description></item>
+ /// <item><term>&nn</term><description>Change font size. nn is an integer. ex &24</description></item>
+ /// <item><term>&G</term><description>Placeholder for images. Images can not be added by the library, but its possible to use in a template.</description></item>
+ /// </list>
+ /// </remarks>
+ public ExcelHeaderFooter HeaderFooter {
+ get {
+ if (_headerFooter == null) {
+ XmlNode headerFooterNode = TopNode.SelectSingleNode("d:headerFooter", NameSpaceManager);
+ if (headerFooterNode == null) {
+ headerFooterNode = CreateNode("d:headerFooter");
}
- const string tabColorPath = "d:sheetPr/d:tabColor/@rgb";
- const string codeModuleNamePath = "d:sheetPr/@codeName";
- internal string CodeModuleName
- {
- get
- {
- return GetXmlNodeString(codeModuleNamePath);
- }
- set
- {
- SetXmlNodeString(codeModuleNamePath, value);
- }
+ _headerFooter = new(NameSpaceManager, headerFooterNode, this);
+ }
+ return (_headerFooter);
+ }
+ }
+
+ /// <summary>
+ /// Printer settings
+ /// </summary>
+ public ExcelPrinterSettings PrinterSettings {
+ get {
+ var ps = new ExcelPrinterSettings(NameSpaceManager, TopNode, this);
+ ps.SchemaNodeOrder = SchemaNodeOrder;
+ return ps;
+ }
+ }
+
+ ///// <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 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);
}
- internal void CodeNameChange(string value)
- {
- CodeModuleName = value;
+ }
+ //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 fromCol,
+ fromRow,
+ toCol,
+ toRow;
+ //Get rows and columns and validate as well
+ ExcelCellBase.GetRowColFromAddress(address, out fromRow, out 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."));
+ }
+
+ lock (this) {
+ _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."));
+ }
+
+ lock (this) {
+ _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) {
+ lst.Add((ExcelColumn)col);
+ }
+ }
+
+ 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);
}
- #region WorksheetXml
- /// <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>
- public XmlDocument WorksheetXml
- {
- get
- {
- return (_worksheetXml);
- }
- }
- internal ExcelVmlDrawingCommentCollection _vmlDrawings = null;
- /// <summary>
- /// Vml drawings. underlaying object for comments
- /// </summary>
- internal ExcelVmlDrawingCommentCollection VmlDrawingsComments
- {
- get
- {
- if (_vmlDrawings == null)
- {
- CreateVmlCollection();
- }
- return _vmlDrawings;
- }
- }
- internal ExcelCommentCollection _comments = null;
- /// <summary>
- /// Collection of comments
- /// </summary>
- public ExcelCommentCollection Comments
- {
- get
- {
- CheckSheetType();
- if (_comments == null)
- {
- CreateVmlCollection();
- _comments = new ExcelCommentCollection(_package, this, NameSpaceManager);
- }
- return _comments;
- }
- }
- private void CreateVmlCollection()
- {
- var vmlNode = _worksheetXml.DocumentElement.SelectSingleNode("d:legacyDrawing/@r:id", NameSpaceManager);
- if (vmlNode == null)
- {
- _vmlDrawings = new ExcelVmlDrawingCommentCollection(_package, this, null);
- }
- else
- {
- if (Part.RelationshipExists(vmlNode.Value))
- {
- var rel = Part.GetRelationship(vmlNode.Value);
- var vmlUri = UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri);
+ tbl.Address = tbl.Address.AddColumn(columnFrom, columns);
+ }
+ }
+ }
- _vmlDrawings = new ExcelVmlDrawingCommentCollection(_package, this, vmlUri);
- _vmlDrawings.RelId = rel.Id;
- }
- }
+ 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);
+ }
}
- private void CreateXml()
- {
- _worksheetXml = new XmlDocument();
- _worksheetXml.PreserveWhitespace = ExcelPackage.preserveWhitespace;
- Packaging.ZipPackagePart packPart = _package.Package.GetPart(WorksheetUri);
- string xml = "";
-
- // First Columns, rows, cells, mergecells, hyperlinks and pagebreakes are loaded from a xmlstream to optimize speed...
- Stream stream = packPart.GetStream();
-
- XmlTextReader 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);
- Encoding encoding;
- xml = GetWorkSheetXml(stream, start, end, out encoding);
-
- //first char is invalid sometimes??
- if (xml[0] != '<')
- LoadXmlSafe(_worksheetXml, xml.Substring(1, xml.Length - 1), encoding);
- else
- LoadXmlSafe(_worksheetXml, xml, encoding);
-
- ClearNodes();
+ if (newAddr.Address != addr.Address) {
+ _mergedCells.List[i] = newAddr._address;
}
- /// <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)
- {
- int id;
- if (int.TryParse(xr.GetAttribute("id"), out 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)
- {
- int id;
- if (int.TryParse(xr.GetAttribute("id"), out id))
- {
- Column(id).PageBreak = true;
- }
- }
- }
- else
- {
- break;
- }
- }
+ }
+ }
+ 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);
+ }
}
- 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();
- }
+ if (newAddr.Address != addr.Address) {
+ _mergedCells.List[i] = newAddr._address;
}
- 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();
- }
- else
- {
- 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;
+ }
+ }
+ for (int i = removeIndex.Count - 1; i >= 0; i--) {
+ _mergedCells.List.RemoveAt(removeIndex[i]);
+ }
+ }
- 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 StreamReader(stream);
- pos = sr.ReadBlock(block, 0, size);
- sb = new StringBuilder();
- 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 FixSharedFormulasRows(int position, int rows) {
+ List<Formulas> added = new List<Formulas>();
+ List<Formulas> deleted = new List<Formulas>();
+
+ foreach (int id in _sharedFormulas.Keys) {
+ var f = _sharedFormulas[id];
+ int fromCol,
+ fromRow,
+ toCol,
+ toRow;
+
+ ExcelCellBase.GetRowColFromAddress(f.Address, out fromRow, out fromCol, out toRow, out toCol);
+ if (position >= fromRow
+ && position + (Math.Abs(rows))
+ <= toRow) //Insert/delete is whithin the share formula address
+ {
+ if (rows
+ > 0) //Insert
+ {
+ f.Address =
+ ExcelCellBase.GetAddress(fromRow, fromCol)
+ + ":"
+ + ExcelCellBase.GetAddress(position - 1, toCol);
+ if (toRow != fromRow) {
+ Formulas newF = new Formulas(SourceCodeTokenizer.Default);
+ newF.StartCol = f.StartCol;
+ newF.StartRow = position + rows;
+ newF.Address =
+ ExcelCellBase.GetAddress(position + rows, fromCol)
+ + ":"
+ + ExcelCellBase.GetAddress(toRow + rows, toCol);
+ newF.Formula = ExcelCellBase.TranslateFromR1C1(
+ ExcelCellBase.TranslateToR1C1(f.Formula, f.StartRow, f.StartCol),
+ position,
+ f.StartCol);
+ added.Add(newF);
+ }
+ } else {
+ if (fromRow - rows < toRow) {
+ f.Address = ExcelCellBase.GetAddress(fromRow, fromCol, toRow + rows, toCol);
+ } else {
+ f.Address =
+ ExcelCellBase.GetAddress(fromRow, fromCol)
+ + ":"
+ + ExcelCellBase.GetAddress(toRow + rows, toCol);
+ }
}
- private void GetBlockPos(string xml, string tag, ref int start, ref int end)
+ } else if (position <= toRow) {
+ if (rows
+ > 0) //Insert before shift down
{
- Match startmMatch, endMatch;
- startmMatch = Regex.Match(xml.Substring(start), string.Format("(<[^>]*{0}[^>]*>)", tag)); //"<[a-zA-Z:]*" + tag + "[?]*>");
+ f.StartRow += rows;
+ //f.Formula = ExcelCell.UpdateFormulaReferences(f.Formula, rows, 0, position, 0); //Recalc the cells positions
+ f.Address =
+ ExcelCellBase.GetAddress(fromRow + rows, fromCol)
+ + ":"
+ + ExcelCellBase.GetAddress(toRow + rows, toCol);
+ } else {
+ //Cells[f.Address].SetSharedFormulaID(int.MinValue);
+ if (position <= fromRow
+ && position + Math.Abs(rows)
+ > toRow) //Delete the formula
+ {
+ deleted.Add(f);
+ } else {
+ toRow = toRow + rows < position - 1 ? position - 1 : toRow + rows;
+ if (position <= fromRow) {
+ fromRow = fromRow + rows < position ? position : fromRow + rows;
+ }
- 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;
+ f.Address = ExcelCellBase.GetAddress(fromRow, fromCol, toRow, toCol);
+ Cells[f.Address].SetSharedFormulaId(f.Index);
+ //f.StartRow = fromRow;
+
+ //f.Formula = ExcelCell.UpdateFormulaReferences(f.Formula, rows, 0, position, 0);
+ }
}
- 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]));
+ }
+ }
+
+ AddFormulas(added, position, rows);
+
+ //Remove formulas
+ foreach (Formulas f in deleted) {
+ _sharedFormulas.Remove(f.Index);
+ }
+
+ //Fix Formulas
+ added = new();
+ foreach (int id in _sharedFormulas.Keys) {
+ var f = _sharedFormulas[id];
+ UpdateSharedFormulaRow(ref f, position, rows, ref added);
+ }
+ AddFormulas(added, position, rows);
+ }
+
+ private void AddFormulas(List<Formulas> added, int position, int rows) {
+ //Add new formulas
+ foreach (Formulas f in added) {
+ f.Index = GetMaxShareFunctionIndex(false);
+ _sharedFormulas.Add(f.Index, f);
+ Cells[f.Address].SetSharedFormulaId(f.Index);
+ }
+ }
+
+ private void UpdateSharedFormulaRow(
+ ref Formulas formula,
+ int startRow,
+ int rows,
+ ref List<Formulas> newFormulas) {
+ int fromRow,
+ fromCol,
+ toRow,
+ toCol;
+ int newFormulasCount = newFormulas.Count;
+ ExcelCellBase.GetRowColFromAddress(
+ formula.Address,
+ out fromRow,
+ out fromCol,
+ out toRow,
+ out toCol);
+ //int refSplits = Regex.Split(formula.Formula, "#REF!").GetUpperBound(0);
+ string formualR1C1;
+ if (rows > 0 || fromRow <= startRow) {
+ formualR1C1 = ExcelCellBase.TranslateToR1C1(
+ formula.Formula,
+ formula.StartRow,
+ formula.StartCol);
+ formula.Formula = ExcelCellBase.TranslateFromR1C1(formualR1C1, fromRow, formula.StartCol);
+ } else {
+ formualR1C1 = ExcelCellBase.TranslateToR1C1(
+ formula.Formula,
+ formula.StartRow - rows,
+ formula.StartCol);
+ formula.Formula = ExcelCellBase.TranslateFromR1C1(
+ formualR1C1,
+ formula.StartRow,
+ formula.StartCol);
+ }
+ //bool isRef = false;
+ //Formulas restFormula=formula;
+ string prevFormualR1C1 = formualR1C1;
+ for (int row = fromRow; row <= toRow; row++) {
+ for (int col = fromCol; col <= toCol; col++) {
+ string newFormula;
+ string currentFormulaR1C1;
+ if (rows > 0 || row < startRow) {
+ newFormula = ExcelCellBase.UpdateFormulaReferences(
+ ExcelCellBase.TranslateFromR1C1(formualR1C1, row, col),
+ rows,
+ 0,
+ startRow,
+ 0);
+ currentFormulaR1C1 = ExcelCellBase.TranslateToR1C1(newFormula, row, col);
+ } else {
+ newFormula = ExcelCellBase.UpdateFormulaReferences(
+ ExcelCellBase.TranslateFromR1C1(formualR1C1, row - rows, col),
+ rows,
+ 0,
+ startRow,
+ 0);
+ currentFormulaR1C1 = ExcelCellBase.TranslateToR1C1(newFormula, row, col);
}
- private void LoadColumns (XmlTextReader xr)//(string xml)
+ if (currentFormulaR1C1
+ != prevFormualR1C1) //newFormula.Contains("#REF!"))
{
- 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);
-
- int style;
- if (!(xr.GetAttribute("style") == null || !int.TryParse(xr.GetAttribute("style"), out style)))
- {
- _styles.SetValue(0, min, style);
- }
- }
- }
+ //if (refSplits == 0 || Regex.Split(newFormula, "#REF!").GetUpperBound(0) != refSplits)
+ //{
+ //isRef = true;
+ if (row == fromRow && col == fromCol) {
+ formula.Formula = newFormula;
+ } else {
+ if (newFormulas.Count == newFormulasCount) {
+ formula.Address = ExcelCellBase.GetAddress(
+ formula.StartRow,
+ formula.StartCol,
+ row - 1,
+ col);
+ } else {
+ newFormulas[newFormulas.Count - 1].Address = ExcelCellBase.GetAddress(
+ newFormulas[newFormulas.Count - 1].StartRow,
+ newFormulas[newFormulas.Count - 1].StartCol,
+ row - 1,
+ col);
}
+ var refFormula = new Formulas(SourceCodeTokenizer.Default);
+ refFormula.Formula = newFormula;
+ refFormula.StartRow = row;
+ refFormula.StartCol = col;
+ newFormulas.Add(refFormula);
+
+ //restFormula = null;
+ prevFormualR1C1 = currentFormulaR1C1;
+ }
}
- /// <summary>
- /// Read until the node is found. If not found the xmlreader is reseted.
- /// </summary>
- /// <param name="xr">The reader</param>
- /// <param name="nodeText">Text to search for</param>
- /// <param name="altNode">Alternative text to search for</param>
- /// <returns></returns>
- private static bool ReadXmlReaderUntil(XmlTextReader xr, string nodeText, string altNode)
- {
- do
- {
- if (xr.LocalName == nodeText || xr.LocalName == altNode) return true;
- }
- while(xr.Read());
- xr.Close();
- return false;
- }
- /// <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")
- {
- int fromRow, fromCol, toRow, toCol;
- ExcelCellBase.GetRowColFromAddress(xr.GetAttribute("ref"), out fromRow, out fromCol, out toRow, out 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 ExcelHyperLink(uri.AbsoluteUri + location);
- }
- catch
- {
- hl = new ExcelHyperLink(uri.OriginalString + location, UriKind.Absolute);
- }
- }
- else
- {
- hl = new ExcelHyperLink(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 ExcelHyperLink(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();
- continue;
- }
- 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 ExcelAddressBase(row, col, row, col);
- }
- else
- {
- address = new ExcelAddressBase(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 Formulas(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 Formulas(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 Formulas(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;
- }
- }
- //if (cell != null) cellList.Add(cell);
-
- //_cells = new RangeCollection(cellList);
- //_rows = new RangeCollection(rowList);
- //_formulaCells = new RangeCollection(formulaList);
- }
-
- 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");
- //int fromRow, fromCol, toRow, toCol;
- //ExcelCellBase.GetRowColFromAddress(address, out fromRow, out fromCol, out toRow, out toCol);
- //for (int row = fromRow; row <= toRow; row++)
- //{
- // for (int col = fromCol; col <= toCol; col++)
- // {
- // _flags.SetFlagValue(row, col, true,CellFlags.Merged);
- // }
- //}
- //_mergedCells.List.Add(address);
- _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 RowInternal()
- {
- 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 DateTime(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);
- }
- else
- {
- // 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 Exception(string.Format("ReadElementContentAsInt returned value '{0}' which is less than zero.", ix));
- }
- if (ix >= _package.Workbook._sharedStringsList.Count)
- {
- throw new Exception(string.Format("ReadElementContentAsInt returned index value '{0}' which is greater than _sharedStringsList count of {1}.", ix, _package.Workbook._sharedStringsList.Count));
- }
-
- _values.SetValue(row, col, _package.Workbook._sharedStringsList[ix].Text);
- if (_package.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
- {
- double res;
- if (double.TryParse(v, NumberStyles.Any, CultureInfo.InvariantCulture, out 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
- {
- double res;
- if (double.TryParse(v, NumberStyles.Any, CultureInfo.InvariantCulture, out 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
- {
- double d;
- if (double.TryParse(v, NumberStyles.Any, CultureInfo.InvariantCulture, out 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);
- //}
- }
- //private string GetSharedString(int stringID)
- //{
- // string retValue = null;
- // XmlNodeList stringNodes = xlPackage.Workbook.SharedStringsXml.SelectNodes(string.Format("//d:si", stringID), NameSpaceManager);
- // XmlNode stringNode = stringNodes[stringID];
- // if (stringNode != null)
- // retValue = stringNode.InnerText;
- // return (retValue);
+ // }
+ // else
+ // {
+ // isRef = false;
+ // }
//}
- #endregion
- #region HeaderFooter
- /// <summary>
- /// A reference to the header and footer class which allows you to
- /// set the header and footer for all odd, even and first pages of the worksheet
- /// </summary>
- /// <remarks>
- /// To format the text you can use the following format
- /// <list type="table">
- /// <listheader><term>Prefix</term><description>Description</description></listheader>
- /// <item><term>&U</term><description>Underlined</description></item>
- /// <item><term>&E</term><description>Double Underline</description></item>
- /// <item><term>&K:xxxxxx</term><description>Color. ex &K:FF0000 for red</description></item>
- /// <item><term>&"Font,Regular Bold Italic"</term><description>Changes the font. Regular or Bold or Italic or Bold Italic can be used. ex &"Arial,Bold Italic"</description></item>
- /// <item><term>&nn</term><description>Change font size. nn is an integer. ex &24</description></item>
- /// <item><term>&G</term><description>Placeholder for images. Images can not be added by the library, but its possible to use in a template.</description></item>
- /// </list>
- /// </remarks>
- public ExcelHeaderFooter HeaderFooter
- {
- get
- {
- if (_headerFooter == null)
- {
- XmlNode headerFooterNode = TopNode.SelectSingleNode("d:headerFooter", NameSpaceManager);
- if (headerFooterNode == null)
- headerFooterNode= CreateNode("d:headerFooter");
- _headerFooter = new ExcelHeaderFooter(NameSpaceManager, headerFooterNode, this);
- }
- return (_headerFooter);
- }
- }
- #endregion
-
- #region "PrinterSettings"
- /// <summary>
- /// Printer settings
- /// </summary>
- public ExcelPrinterSettings PrinterSettings
- {
- get
- {
- var ps = new ExcelPrinterSettings(NameSpaceManager, TopNode, this);
- ps.SchemaNodeOrder = SchemaNodeOrder;
- return ps;
- }
- }
- #endregion
-
- #endregion // END Worksheet Public Properties
-
- #region Worksheet Public Methods
-
- ///// <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)
+ //else
//{
- // return new ExcelCell(_values, row, col);
+ // isRef = false;
//}
- /// <summary>
- /// Provides access to a range of cells
- /// </summary>
- public ExcelRange Cells
- {
- get
- {
- CheckSheetType();
- return new ExcelRange(this, 1, 1, ExcelPackage.MaxRows, ExcelPackage.MaxColumns);
- }
- }
- /// <summary>
- /// Provides access to the selected range of cells
- /// </summary>
- public ExcelRange SelectedRange
- {
- get
- {
- CheckSheetType();
- return new ExcelRange(this, View.SelectedRange);
- }
- }
- MergeCellsCollection _mergedCells = new MergeCellsCollection();
- /// <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 ExcelRow(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 ExcelColumn(this, col);
- _values.SetValue(0, col, column);
- //_columns.Add(column);
- }
- return column;
- }
+ //if (restFormula==null)
+ //{
+ //if (newFormulas.Count == newFormulasCount)
+ //{
+ // formula.Address = ExcelCellBase.GetAddress(formula.StartRow, formula.StartCol, row - 1, col);
+ //}
+ //else
+ //{
+ // newFormulas[newFormulas.Count - 1].Address = ExcelCellBase.GetAddress(newFormulas[newFormulas.Count - 1].StartRow, newFormulas[0].StartCol, row - 1, col);
+ //}
- /// <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;
+ //restFormula = new Formulas();
+ //restFormula.Formula = newFormula;
+ //restFormula.StartRow = row;
+ //restFormula.StartCol = col;
+ //newFormulas.Add(restFormula);
+ //}
+ }
+ }
+ if (rows < 0 && formula.StartRow > startRow) {
+ if (formula.StartRow + rows < startRow) {
+ formula.StartRow = startRow;
+ } else {
+ formula.StartRow += rows;
+ }
+ }
+ if (newFormulas.Count > newFormulasCount) {
+ newFormulas[newFormulas.Count - 1].Address = ExcelCellBase.GetAddress(
+ newFormulas[newFormulas.Count - 1].StartRow,
+ newFormulas[newFormulas.Count - 1].StartCol,
+ toRow,
+ toCol);
+ }
+ }
- 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 fromCol, fromRow, toCol, toRow;
- //Get rows and columns and validate as well
- ExcelCellBase.GetRowColFromAddress(Address, out fromRow, out fromCol, out toRow, out toCol);
+ /// <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);
+ }
- 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)
- {
+ /// <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)));
+ }
+ lock (this) {
+ _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);
- 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);
- }
+ AdjustFormulasRow(rowFrom, rows);
+ FixMergedCellsRow(rowFrom, rows, true);
- #region InsertRow
- /// <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;
+ foreach (var tbl in Tables) {
+ tbl.Address = tbl.Address.DeleteRow(rowFrom, rows);
+ }
+ }
+ }
- if (rowFrom < 1)
- {
- throw (new ArgumentOutOfRangeException("rowFrom can't be lesser that 1"));
- }
+ /// <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);
+ }
- //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."));
- }
+ /// <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)));
+ }
+ lock (this) {
+ 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;
+ }
+ }
+ }
- lock (this)
- {
- _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);
+ _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);
- 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 = ExcelAddressBase.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);
- }
- }
+ AdjustFormulasColumn(columnFrom, columns);
+ FixMergedCellsColumn(columnFrom, columns, true);
- 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);
+ var csec = new CellsStoreEnumerator<object>(
+ _values,
+ 0,
+ columnFrom,
+ 0,
+ ExcelPackage.MaxColumns);
+ foreach (var column in csec) {
+ if (column is ExcelColumn) {
+ var c = (ExcelColumn)column;
+ if (c._columnMin >= columnFrom) {
+ c._columnMin -= columns;
+ c._columnMax -= columns;
+ }
}
- ///<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."));
+ 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);
+ }
- lock (this)
- {
- _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);
+ tbl.Address = tbl.Address.DeleteColumn(columnFrom, 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 = ExcelAddressBase.GetAddress(a._fromRow, a._fromCol, a._toRow, a._toCol);
- f.Formula = ExcelCellBase.UpdateFormulaReferences(f.Formula, 0, columns, 0, columnFrom);
- }
+ 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);
+ }
+ delSf = null;
+ 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);
+ }
+ }
+ }
- 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);
- }
- }
+ 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;
+ //sf.Formula = ExcelCellBase.UpdateFormulaReferences(sf.Formula, 0, -columns, 0, columnFrom);
+ 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;
+ }
- FixMergedCellsColumn(columnFrom, columns, false);
+ //sf.Address = a.Address;
+ //sf.Formula = ExcelCellBase.UpdateFormulaReferences(sf.Formula, 0,-columns,0, columnFrom);
+ //if (sf.StartCol >= columnFrom)
+ //{
+ // sf.StartCol -= sf.StartCol;
+ //}
+ }
+ }
+ foreach (var ix in delSf) {
+ _sharedFormulas.Remove(ix);
+ }
+ delSf = null;
+ 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);
+ }
+ }
+ }
- 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)
- {
- lst.Add((ExcelColumn)col);
- }
- }
+ /// <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);
+ }
- 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);
- }
- }
+ /// <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();
+ //ulong cellID = ExcelCellBase.GetCellID(SheetID, Row, Column);
+ var v = _values.GetValue(row, column);
+ if (v != null) {
+ //var cell = ((ExcelCell)_cells[cellID]);
+ 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);
+ }
- if (copyStylesFromColumn > 0)
- {
- for (var c = 0; c < columns; c++)
- {
- var col = this.Column(columnFrom + c);
- col.StyleID = this.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);
- }
+ //var cell=((ExcelCell)_cells[cellID]);
+ if (_flags.GetFlagValue(row, column, CellFlags.RichText)) {
+ return (T)(object)Cells[row, column].RichText.Text;
+ }
+ return GetTypedValue<T>(v);
+ }
- tbl.Address=tbl.Address.AddColumn(columnFrom, columns);
- }
- }
+ //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)) {
+ DateTime dt;
+ if (DateTime.TryParse(v.ToString(), out 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)) {
+ TimeSpan ts;
+ if (TimeSpan.TryParse(v.ToString(), out 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));
+ }
+ }
- 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 ExcelTableColumnCollection(tbl);
- }
+ 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>
- /// 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);
- }
+ /// <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);
+ }
- List<int> removeIndex = new List<int>();
- for (int i = 0; i < _mergedCells.Count; i++)
- {
- if (!string.IsNullOrEmpty( _mergedCells[i]))
- {
- ExcelAddressBase addr = new ExcelAddressBase(_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);
- }
- }
+ /// <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();
+ int row,
+ col;
+ ExcelCellBase.GetRowCol(address, out row, out 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);
+ }
- 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 ExcelAddressBase(_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);
- }
- }
+ /// <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 (newAddr.Address != addr.Address)
- {
- _mergedCells.List[i] = newAddr._address;
- }
- }
- }
- for (int i = removeIndex.Count - 1; i >= 0; i--)
- {
- _mergedCells.List.RemoveAt(removeIndex[i]);
- }
+ if (range.Start.Row <= row && row <= range.End.Row) {
+ if (range.Start.Column <= column && column <= range.End.Column) {
+ return i + 1;
+ }
}
- private void FixSharedFormulasRows(int position, int rows)
- {
- List<Formulas> added = new List<Formulas>();
- List<Formulas> deleted = new List<Formulas>();
+ }
+ }
+ return 0;
+ }
- foreach (int id in _sharedFormulas.Keys)
- {
- var f = _sharedFormulas[id];
- int fromCol, fromRow, toCol, toRow;
+ internal void Save() {
+ DeletePrinterSettings();
- ExcelCellBase.GetRowColFromAddress(f.Address, out fromRow, out fromCol, out toRow, out toCol);
- if (position >= fromRow && position+(Math.Abs(rows)) <= toRow) //Insert/delete is whithin the share formula address
- {
- if (rows > 0) //Insert
- {
- f.Address = ExcelCellBase.GetAddress(fromRow, fromCol) + ":" + ExcelCellBase.GetAddress(position - 1, toCol);
- if (toRow != fromRow)
- {
- Formulas newF = new Formulas(SourceCodeTokenizer.Default);
- newF.StartCol = f.StartCol;
- newF.StartRow = position + rows;
- newF.Address = ExcelCellBase.GetAddress(position + rows, fromCol) + ":" + ExcelCellBase.GetAddress(toRow + rows, toCol);
- newF.Formula = ExcelCellBase.TranslateFromR1C1(ExcelCellBase.TranslateToR1C1(f.Formula, f.StartRow, f.StartCol), position, f.StartCol);
- added.Add(newF);
- }
- }
- else
- {
- if (fromRow - rows < toRow)
- {
- f.Address = ExcelCellBase.GetAddress(fromRow, fromCol, toRow+rows, toCol);
- }
- else
- {
- f.Address = ExcelCellBase.GetAddress(fromRow, fromCol) + ":" + ExcelCellBase.GetAddress(toRow + rows, toCol);
- }
- }
- }
- else if (position <= toRow)
- {
- if (rows > 0) //Insert before shift down
- {
- f.StartRow += rows;
- //f.Formula = ExcelCell.UpdateFormulaReferences(f.Formula, rows, 0, position, 0); //Recalc the cells positions
- f.Address = ExcelCellBase.GetAddress(fromRow + rows, fromCol) + ":" + ExcelCellBase.GetAddress(toRow + rows, toCol);
- }
- else
- {
- //Cells[f.Address].SetSharedFormulaID(int.MinValue);
- if (position <= fromRow && position + Math.Abs(rows) > toRow) //Delete the formula
- {
- deleted.Add(f);
- }
- else
- {
- toRow = toRow + rows < position - 1 ? position - 1 : toRow + rows;
- if (position <= fromRow)
- {
- fromRow = fromRow + rows < position ? position : fromRow + rows;
- }
-
- f.Address = ExcelCellBase.GetAddress(fromRow, fromCol, toRow, toCol);
- Cells[f.Address].SetSharedFormulaID(f.Index);
- //f.StartRow = fromRow;
+ if (_worksheetXml != null) {
+ if (!(this is ExcelChartsheet)) {
+ // save the header & footer (if defined)
+ if (_headerFooter != null) {
+ HeaderFooter.Save();
+ }
- //f.Formula = ExcelCell.UpdateFormulaReferences(f.Formula, rows, 0, position, 0);
-
- }
- }
- }
- }
+ var d = Dimension;
+ if (d == null) {
+ DeleteAllNode("d:dimension/@ref");
+ } else {
+ SetXmlNodeString("d:dimension/@ref", d.Address);
+ }
- AddFormulas(added, position, rows);
+ SaveComments();
+ SaveTables();
+ SavePivotTables();
+ }
+ }
+ }
- //Remove formulas
- foreach (Formulas f in deleted)
- {
- _sharedFormulas.Remove(f.Index);
- }
+ 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");
- //Fix Formulas
- added = new List<Formulas>();
- foreach (int id in _sharedFormulas.Keys)
- {
- var f = _sharedFormulas[id];
- UpdateSharedFormulaRow(ref f, position, rows, ref added);
- }
- AddFormulas(added, position, rows);
- }
+ //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);
- private void AddFormulas(List<Formulas> added, int position, int rows)
- {
- //Add new formulas
- foreach (Formulas f in added)
- {
- f.Index = GetMaxShareFunctionIndex(false);
- _sharedFormulas.Add(f.Index, f);
- Cells[f.Address].SetSharedFormulaID(f.Index);
- }
- }
+ streamWriter.Write(xml.Substring(0, colStart));
+ var colBreaks = new List<int>();
+ //if (_columns.Count > 0)
+ //{
+ UpdateColumnData(streamWriter);
+ //}
- private void UpdateSharedFormulaRow(ref Formulas formula, int startRow, int rows, ref List<Formulas> newFormulas)
- {
- int fromRow,fromCol, toRow, toCol;
- int newFormulasCount = newFormulas.Count;
- ExcelCellBase.GetRowColFromAddress(formula.Address, out fromRow, out fromCol, out toRow, out toCol);
- //int refSplits = Regex.Split(formula.Formula, "#REF!").GetUpperBound(0);
- string formualR1C1;
- if (rows > 0 || fromRow <= startRow)
- {
- formualR1C1 = ExcelRangeBase.TranslateToR1C1(formula.Formula, formula.StartRow, formula.StartCol);
- formula.Formula = ExcelRangeBase.TranslateFromR1C1(formualR1C1, fromRow, formula.StartCol);
- }
- else
- {
- formualR1C1 = ExcelRangeBase.TranslateToR1C1(formula.Formula, formula.StartRow-rows, formula.StartCol);
- formula.Formula = ExcelRangeBase.TranslateFromR1C1(formualR1C1, formula.StartRow, formula.StartCol);
- }
- //bool isRef = false;
- //Formulas restFormula=formula;
- string prevFormualR1C1 = formualR1C1;
- for (int row = fromRow; row <= toRow; row++)
- {
- for (int col = fromCol; col <= toCol; col++)
- {
- string newFormula;
- string currentFormulaR1C1;
- if (rows > 0 || row < startRow)
- {
- newFormula = ExcelCellBase.UpdateFormulaReferences(ExcelCellBase.TranslateFromR1C1(formualR1C1, row, col), rows, 0, startRow, 0);
- currentFormulaR1C1 = ExcelRangeBase.TranslateToR1C1(newFormula, row, col);
- }
- else
- {
- newFormula = ExcelCellBase.UpdateFormulaReferences(ExcelCellBase.TranslateFromR1C1(formualR1C1, row-rows, col), rows, 0, startRow, 0);
- currentFormulaR1C1 = ExcelRangeBase.TranslateToR1C1(newFormula, row, col);
- }
- if (currentFormulaR1C1 != prevFormualR1C1) //newFormula.Contains("#REF!"))
- {
- //if (refSplits == 0 || Regex.Split(newFormula, "#REF!").GetUpperBound(0) != refSplits)
- //{
- //isRef = true;
- if (row == fromRow && col == fromCol)
- {
- formula.Formula = newFormula;
- }
- else
- {
- if (newFormulas.Count == newFormulasCount)
- {
- formula.Address = ExcelCellBase.GetAddress(formula.StartRow, formula.StartCol, row - 1, col);
- }
- else
- {
- newFormulas[newFormulas.Count - 1].Address = ExcelCellBase.GetAddress(newFormulas[newFormulas.Count - 1].StartRow, newFormulas[newFormulas.Count - 1].StartCol, row - 1, col);
- }
- var refFormula = new Formulas(SourceCodeTokenizer.Default);
- refFormula.Formula = newFormula;
- refFormula.StartRow = row;
- refFormula.StartCol = col;
- newFormulas.Add(refFormula);
+ int cellStart = colEnd,
+ cellEnd = colEnd;
+ GetBlockPos(xml, "sheetData", ref cellStart, ref cellEnd);
- //restFormula = null;
- prevFormualR1C1 = currentFormulaR1C1;
- }
- }
- // }
- // else
- // {
- // isRef = false;
- // }
- //}
- //else
- //{
- // isRef = false;
- //}
- //if (restFormula==null)
- //{
- //if (newFormulas.Count == newFormulasCount)
- //{
- // formula.Address = ExcelCellBase.GetAddress(formula.StartRow, formula.StartCol, row - 1, col);
- //}
- //else
- //{
-// newFormulas[newFormulas.Count - 1].Address = ExcelCellBase.GetAddress(newFormulas[newFormulas.Count - 1].StartRow, newFormulas[0].StartCol, row - 1, col);
- //}
+ streamWriter.Write(xml.Substring(colEnd, cellStart - colEnd));
+ var rowBreaks = new List<int>();
+ UpdateRowCellData(streamWriter);
- //restFormula = new Formulas();
- //restFormula.Formula = newFormula;
- //restFormula.StartRow = row;
- //restFormula.StartCol = col;
- //newFormulas.Add(restFormula);
- //}
- }
- }
- if (rows < 0 && formula.StartRow > startRow)
- {
- if (formula.StartRow + rows < startRow)
- {
- formula.StartRow = startRow;
- }
- else
- {
- formula.StartRow += rows;
- }
- }
- if (newFormulas.Count > newFormulasCount)
- {
- newFormulas[newFormulas.Count - 1].Address = ExcelCellBase.GetAddress(newFormulas[newFormulas.Count - 1].StartRow, newFormulas[newFormulas.Count - 1].StartCol, toRow, toCol);
- }
- }
- #endregion
+ int mergeStart = cellEnd,
+ mergeEnd = cellEnd;
- #region DeleteRow
- /// <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)));
- }
- lock (this)
- {
- _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);
+ GetBlockPos(xml, "mergeCells", ref mergeStart, ref mergeEnd);
+ streamWriter.Write(xml.Substring(cellEnd, mergeStart - cellEnd));
- AdjustFormulasRow(rowFrom, rows);
- FixMergedCellsRow(rowFrom, rows, true);
+ CleanupMergedCells(_mergedCells);
+ if (_mergedCells.Count > 0) {
+ UpdateMergedCells(streamWriter);
+ }
- 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)));
- }
- lock (this)
- {
- 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;
- }
- }
- }
+ int hyperStart = mergeEnd,
+ hyperEnd = mergeEnd;
+ GetBlockPos(xml, "hyperlinks", ref hyperStart, ref hyperEnd);
+ streamWriter.Write(xml.Substring(mergeEnd, hyperStart - mergeEnd));
+ //if (_hyperLinkCells.Count > 0)
+ //{
+ UpdateHyperLinks(streamWriter);
+ // }
- _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);
+ int rowBreakStart = hyperEnd,
+ rowBreakEnd = hyperEnd;
+ GetBlockPos(xml, "rowBreaks", ref rowBreakStart, ref rowBreakEnd);
+ streamWriter.Write(xml.Substring(hyperEnd, rowBreakStart - hyperEnd));
+ //if (rowBreaks.Count > 0)
+ //{
+ UpdateRowBreaks(streamWriter);
+ //}
- AdjustFormulasColumn(columnFrom, columns);
- FixMergedCellsColumn(columnFrom, columns, true);
+ int colBreakStart = rowBreakEnd,
+ colBreakEnd = rowBreakEnd;
+ GetBlockPos(xml, "colBreaks", ref colBreakStart, ref colBreakEnd);
+ streamWriter.Write(xml.Substring(rowBreakEnd, colBreakStart - rowBreakEnd));
+ //if (colBreaks.Count > 0)
+ //{
+ UpdateColBreaks(streamWriter);
+ //}
+ streamWriter.Write(xml.Substring(colBreakEnd, xml.Length - colBreakEnd));
+ }
+ }
- var csec = new CellsStoreEnumerator<object>(_values, 0, columnFrom, 0, ExcelPackage.MaxColumns);
- foreach (var column in csec)
- {
- if (column is ExcelColumn)
- {
- var c = (ExcelColumn)column;
- if (c._columnMin >= columnFrom)
- {
- c._columnMin -= columns;
- c._columnMax -= columns;
- }
- }
- }
+ /// <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);
- 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 ExcelTableColumnCollection(tbl);
- }
+ //Delete the part from the package
+ if (_package.Package.PartExists(printerSettingsUri)) {
+ _package.Package.DeletePart(printerSettingsUri);
+ }
+ }
+ }
+ }
- tbl.Address = tbl.Address.DeleteColumn(columnFrom, columns);
- }
- }
+ private void SaveComments() {
+ if (_comments != null) {
+ if (_comments.Count == 0) {
+ if (_comments.Uri != null) {
+ Part.DeleteRelationship(_comments.RelId);
+ _package.Package.DeletePart(_comments.Uri);
}
- 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);
- }
- delSF = null;
- 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);
- }
- }
+ RemoveLegacyDrawingRel(VmlDrawingsComments.RelId);
+ } else {
+ if (_comments.Uri == null) {
+ _comments.Uri = new(string.Format("/xl/comments{0}.xml", SheetID), UriKind.Relative);
+ }
+ if (_comments.Part == null) {
+ _comments.Part = _package.Package.CreatePart(
+ _comments.Uri,
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
+ _package.Compression);
+ var rel = Part.CreateRelationship(
+ UriHelper.GetRelativeUri(WorksheetUri, _comments.Uri),
+ TargetMode.Internal,
+ ExcelPackage._schemaRelationships + "/comments");
}
- 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;
- //sf.Formula = ExcelCellBase.UpdateFormulaReferences(sf.Formula, 0, -columns, 0, columnFrom);
- 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;
- }
+ _comments.CommentXml.Save(_comments.Part.GetStream(FileMode.Create));
+ }
+ }
- //sf.Address = a.Address;
- //sf.Formula = ExcelCellBase.UpdateFormulaReferences(sf.Formula, 0,-columns,0, columnFrom);
- //if (sf.StartCol >= columnFrom)
- //{
- // sf.StartCol -= sf.StartCol;
- //}
- }
- }
- foreach (var ix in delSF)
- {
- _sharedFormulas.Remove(ix);
- }
- delSF = null;
- 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);
- }
- }
+ if (_vmlDrawings != null) {
+ if (_vmlDrawings.Count == 0) {
+ if (_vmlDrawings.Uri != null) {
+ Part.DeleteRelationship(_vmlDrawings.RelId);
+ _package.Package.DeletePart(_vmlDrawings.Uri);
}
- /// <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);
+ } else {
+ if (_vmlDrawings.Uri == null) {
+ _vmlDrawings.Uri = GetNewUri(_package.Package, "/xl/drawings/vmlDrawing{0}.vml");
}
- #endregion
- /// <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();
- //ulong cellID = ExcelCellBase.GetCellID(SheetID, Row, Column);
- var v = _values.GetValue(Row, Column);
- if (v!=null)
- {
- //var cell = ((ExcelCell)_cells[cellID]);
- if (_flags.GetFlagValue(Row, Column, CellFlags.RichText))
- {
- return (object)Cells[Row, Column].RichText.Text;
- }
- else
- {
- return v;
- }
- }
- else
- {
- return null;
- }
+ if (_vmlDrawings.Part == null) {
+ _vmlDrawings.Part = _package.Package.CreatePart(
+ _vmlDrawings.Uri,
+ "application/vnd.openxmlformats-officedocument.vmlDrawing",
+ _package.Compression);
+ var rel = Part.CreateRelationship(
+ UriHelper.GetRelativeUri(WorksheetUri, _vmlDrawings.Uri),
+ TargetMode.Internal,
+ ExcelPackage._schemaRelationships + "/vmlDrawing");
+ SetXmlNodeString("d:legacyDrawing/@r:id", rel.Id);
+ _vmlDrawings.RelId = rel.Id;
}
+ _vmlDrawings.VmlDrawingXml.Save(_vmlDrawings.Part.GetStream());
+ }
+ }
+ }
- /// <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);
+ /// <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);
+ }
- //var cell=((ExcelCell)_cells[cellID]);
- if (_flags.GetFlagValue(Row, Column, CellFlags.RichText))
- {
- return (T)(object)Cells[Row, Column].RichText.Text;
- }
- else
- {
- return GetTypedValue<T>(v);
+ 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++;
}
- //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)));
- }
- else if (fromType == typeof(string))
- {
- DateTime dt;
- if (DateTime.TryParse(v.ToString(), out dt))
- {
- return (T)(object)(dt);
- }
- else
- {
- return default(T);
- }
+ }
+ if (tbl.Part == null) {
+ tbl.TableUri = GetNewUri(_package.Package, "/xl/tables/table{0}.xml", tbl.Id);
+ tbl.Part = _package.Package.CreatePart(
+ tbl.TableUri,
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml",
+ Workbook._package.Compression);
+ var stream = tbl.Part.GetStream(FileMode.Create);
+ tbl.TableXml.Save(stream);
+ var rel = Part.CreateRelationship(
+ UriHelper.GetRelativeUri(WorksheetUri, tbl.TableUri),
+ TargetMode.Internal,
+ ExcelPackage._schemaRelationships + "/table");
+ tbl.RelationshipID = rel.Id;
- }
- else
- {
- if (cnv.CanConvertTo(typeof(double)))
- {
- return (T)(object)(DateTime.FromOADate((double)cnv.ConvertTo(v, typeof(double))));
- }
- else
- {
- return default(T);
- }
- }
- }
- else if (toType == typeof(TimeSpan)) //Handle timespan
- {
- if (fromType == typeof(DateTime))
- {
- return ((T)(object)(new TimeSpan(((DateTime)v).Ticks)));
- }
- else if (fromType == typeof(string))
- {
- TimeSpan ts;
- if (TimeSpan.TryParse(v.ToString(), out ts))
- {
- return (T)(object)(ts);
- }
- else
- {
- return default(T);
- }
- }
- else
- {
- if (cnv.CanConvertTo(typeof(double)))
- {
+ CreateNode("d:tableParts");
+ XmlNode tbls = TopNode.SelectSingleNode("d:tableParts", NameSpaceManager);
- return (T)(object)(new TimeSpan(DateTime.FromOADate((double)cnv.ConvertTo(v, typeof(double))).Ticks));
- }
- else
- {
- 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);
- }
- }
- }
- }
- else
- {
- if (cnv.CanConvertTo(toType))
- {
- return (T)cnv.ConvertTo(v, typeof(T));
- }
- else
- {
- if (toType.IsGenericType && toType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
- {
- toType = Nullable.GetUnderlyingType(toType);
- if (cnv.CanConvertTo(toType))
- {
- return (T)cnv.ConvertTo(v, typeof(T));
- }
- }
+ var tblNode = tbls.OwnerDocument.CreateElement("tablePart", ExcelPackage._schemaMain);
+ tbls.AppendChild(tblNode);
+ tblNode.SetAttribute("id", ExcelPackage._schemaRelationships, rel.Id);
+ } else {
+ var stream = tbl.Part.GetStream(FileMode.Create);
+ tbl.TableXml.Save(stream);
+ }
+ }
+ }
- if(fromType==typeof(double) && toType==typeof(decimal))
- {
- return (T)(object)Convert.ToDecimal(v);
- }
- else if (fromType == typeof(decimal) && toType == typeof(double))
- {
- return (T)(object)Convert.ToDouble(v);
- }
- else
- {
- return default(T);
- }
- }
- }
+ 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;
}
- /// <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();
- int row, col;
- ExcelAddressBase.GetRowCol(Address, out row, out 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);
- }
+ }
+ }
+ 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);
+ }
+ }
- #region MergeCellId
+ internal void SetFormula(int row, int col, object value) {
+ _formulas.SetValue(row, col, value);
+ if (!_values.Exists(row, col)) {
+ _values.SetValue(row, col, null);
+ }
+ }
- /// <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]];
+ 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 (range.Start.Row <= row && row <= range.End.Row)
- {
- if (range.Start.Column <= column && column <= range.End.Column)
- {
- return i + 1;
- }
- }
- }
+ 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);
}
- return 0;
+ df.Name = newName;
+ }
}
+ }
+ pt.PivotTableXml.Save(pt.Part.GetStream(FileMode.Create));
+ pt.CacheDefinition.CacheDefinitionXml.Save(
+ pt.CacheDefinition.Part.GetStream(FileMode.Create));
+ }
+ }
- #endregion
- #endregion // END Worksheet Public Methods
+ 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);
+ }
- #region Worksheet Private Methods
+ private static string GetTotalFunction(ExcelTableColumn col, string functionNum) {
+ return string.Format("SUBTOTAL({0},{1}[{2}])", functionNum, col._tbl.Name, col.Name);
+ }
- #region Worksheet Save
- internal void Save()
- {
- DeletePrinterSettings();
+ private void CleanupMergedCells(MergeCellsCollection mergedCells) {
+ int i = 0;
+ while (i < mergedCells.List.Count) {
+ if (mergedCells[i] == null) {
+ mergedCells.List.RemoveAt(i);
+ } else {
+ i++;
+ }
+ }
+ }
- if (_worksheetXml != null)
- {
+ private void UpdateColBreaks(StreamWriter sw) {
+ StringBuilder breaks = new StringBuilder();
+ int count = 0;
+ var cse = new CellsStoreEnumerator<object>(_values, 0, 0, 0, ExcelPackage.MaxColumns);
+ //foreach (ExcelColumn col in _columns)
+ 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);
+ }
+ }
- if (!(this is ExcelChartsheet))
- {
- // save the header & footer (if defined)
- if (_headerFooter != null)
- HeaderFooter.Save();
+ /// <summary>
+ /// Inserts the cols collection into the XML document
+ /// </summary>
+ private void UpdateColumnData(StreamWriter sw) {
+ //ExcelColumn prevCol = null; //commented out 11/1-12 JK
+ //foreach (ExcelColumn col in _columns)
+ //{
+ // if (prevCol != null)
+ // {
+ // if(prevCol.ColumnMax != col.ColumnMin-1)
+ // {
+ // prevCol._columnMax=col.ColumnMin-1;
+ // }
+ // }
+ // prevCol = col;
+ //}
+ var cse = new CellsStoreEnumerator<object>(_values, 0, 1, 0, ExcelPackage.MaxColumns);
+ //sw.Write("<cols>");
+ //foreach (ExcelColumn col in _columns)
+ bool first = true;
+ while (cse.Next()) {
+ if (first) {
+ sw.Write("<cols>");
+ first = false;
+ }
+ var col = cse.Value as ExcelColumn;
+ ExcelStyleCollection<ExcelXfs> cellXfs = _package.Workbook.Styles.CellXfs;
- var d = Dimension;
- if (d == null)
- {
- this.DeleteAllNode("d:dimension/@ref");
- }
- else
- {
- this.SetXmlNodeString("d:dimension/@ref", d.Address);
- }
-
- SaveComments();
- SaveTables();
- SavePivotTables();
- }
- }
+ 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
+ }
}
- 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");
+ }
+ if (col.Phonetic) {
+ sw.Write(" phonetic=\"1\"");
+ }
- //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));
- var colBreaks = new List<int>();
- //if (_columns.Count > 0)
- //{
- UpdateColumnData(streamWriter);
- //}
-
- int cellStart = colEnd, cellEnd = colEnd;
- GetBlockPos(xml, "sheetData", ref cellStart, ref cellEnd);
-
- streamWriter.Write(xml.Substring(colEnd, cellStart - colEnd));
- var rowBreaks = new List<int>();
- UpdateRowCellData(streamWriter);
+ var styleId = col.StyleID >= 0 ? cellXfs[col.StyleID].newID : col.StyleID;
+ if (styleId > 0) {
+ sw.Write(" style=\"{0}\"", styleId);
+ }
+ sw.Write(" />");
- int mergeStart = cellEnd, mergeEnd = cellEnd;
+ //if (col.PageBreak)
+ //{
+ // colBreaks.Add(col.ColumnMin);
+ //}
+ }
+ if (!first) {
+ sw.Write("</cols>");
+ }
+ }
- GetBlockPos(xml, "mergeCells", ref mergeStart, ref mergeEnd);
- streamWriter.Write(xml.Substring(cellEnd, mergeStart - cellEnd));
+ /// <summary>
+ /// Insert row and cells into the XML document
+ /// </summary>
+ private void UpdateRowCellData(StreamWriter sw) {
+ ExcelStyleCollection<ExcelXfs> cellXfs = _package.Workbook.Styles.CellXfs;
- CleanupMergedCells(_mergedCells);
- if (_mergedCells.Count > 0)
- {
- UpdateMergedCells(streamWriter);
- }
+ int row = -1;
- int hyperStart = mergeEnd, hyperEnd = mergeEnd;
- GetBlockPos(xml, "hyperlinks", ref hyperStart, ref hyperEnd);
- streamWriter.Write(xml.Substring(mergeEnd, hyperStart - mergeEnd));
- //if (_hyperLinkCells.Count > 0)
- //{
- UpdateHyperLinks(streamWriter);
- // }
+ StringBuilder sbXml = new StringBuilder();
+ var ss = _package.Workbook._sharedStrings;
+ var styles = _package.Workbook.Styles;
+ var cache = new StringBuilder();
+ cache.Append("<sheetData>");
- int rowBreakStart = hyperEnd, rowBreakEnd = hyperEnd;
- GetBlockPos(xml, "rowBreaks", ref rowBreakStart, ref rowBreakEnd);
- streamWriter.Write(xml.Substring(hyperEnd, rowBreakStart - hyperEnd));
- //if (rowBreaks.Count > 0)
- //{
- UpdateRowBreaks(streamWriter);
- //}
+ //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);
+ }
+ }
- int colBreakStart = rowBreakEnd, colBreakEnd = rowBreakEnd;
- GetBlockPos(xml, "colBreaks", ref colBreakStart, ref colBreakEnd);
- streamWriter.Write(xml.Substring(rowBreakEnd, colBreakStart - rowBreakEnd));
- //if (colBreaks.Count > 0)
- //{
- UpdateColBreaks(streamWriter);
- //}
- streamWriter.Write(xml.Substring(colBreakEnd, xml.Length - colBreakEnd));
- }
+ 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;
}
-
- /// <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);
- }
- }
+ object v = cse.Value;
+ object formula = _formulas.GetValue(cse.Row, cse.Column);
+ if (formula is int) {
+ int sfId = (int)formula;
+ 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));
}
- }
- private void SaveComments()
- {
- if (_comments != null)
- {
- if (_comments.Count == 0)
- {
- if (_comments.Uri != null)
- {
- Part.DeleteRelationship(_comments.RelId);
- _package.Package.DeletePart(_comments.Uri);
- }
- RemoveLegacyDrawingRel(VmlDrawingsComments.RelId);
- }
- else
- {
- if (_comments.Uri == null)
- {
- _comments.Uri=new Uri(string.Format(@"/xl/comments{0}.xml", SheetID), UriKind.Relative);
- }
- if(_comments.Part==null)
- {
- _comments.Part = _package.Package.CreatePart(_comments.Uri, "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml", _package.Compression);
- var rel = Part.CreateRelationship(UriHelper.GetRelativeUri(WorksheetUri, _comments.Uri), Packaging.TargetMode.Internal, ExcelPackage.schemaRelationships+"/comments");
- }
- _comments.CommentXml.Save(_comments.Part.GetStream(FileMode.Create));
- }
+ } 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));
}
-
- if (_vmlDrawings != null)
- {
- if (_vmlDrawings.Count == 0)
- {
- if (_vmlDrawings.Uri != null)
- {
- Part.DeleteRelationship(_vmlDrawings.RelId);
- _package.Package.DeletePart(_vmlDrawings.Uri);
- }
- }
- else
- {
- if (_vmlDrawings.Uri == null)
- {
- _vmlDrawings.Uri = XmlHelper.GetNewUri(_package.Package, @"/xl/drawings/vmlDrawing{0}.vml");
- }
- if (_vmlDrawings.Part == null)
- {
- _vmlDrawings.Part = _package.Package.CreatePart(_vmlDrawings.Uri, "application/vnd.openxmlformats-officedocument.vmlDrawing", _package.Compression);
- var rel = Part.CreateRelationship(UriHelper.GetRelativeUri(WorksheetUri, _vmlDrawings.Uri), Packaging.TargetMode.Internal, ExcelPackage.schemaRelationships + "/vmlDrawing");
- SetXmlNodeString("d:legacyDrawing/@r:id", rel.Id);
- _vmlDrawings.RelId = rel.Id;
- }
- _vmlDrawings.VmlDrawingXml.Save(_vmlDrawings.Part.GetStream());
- }
+ }
+ } 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);
}
+ }
}
- /// <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++;
- }
- }
- if (tbl.Part == null)
- {
- tbl.TableUri = GetNewUri(_package.Package, @"/xl/tables/table{0}.xml", tbl.Id);
- tbl.Part = _package.Package.CreatePart(tbl.TableUri, "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml", Workbook._package.Compression);
- var stream = tbl.Part.GetStream(FileMode.Create);
- tbl.TableXml.Save(stream);
- var rel = Part.CreateRelationship(UriHelper.GetRelativeUri(WorksheetUri, tbl.TableUri), Packaging.TargetMode.Internal, ExcelPackage.schemaRelationships + "/table");
- tbl.RelationshipID = rel.Id;
+ ////Update hyperlinks.
+ //if (cell.Hyperlink != null)
+ //{
+ // _hyperLinkCells.Add(cell.CellID);
+ //}
+ } else //ExcelRow
+ {
+ //int newRow=((ExcelRow)cse.Value).Row;
+ WriteRow(cache, cellXfs, row, cse.Row);
+ row = cse.Row;
+ }
+ if (cache.Length > 0x600000) {
+ sw.Write(cache.ToString());
+ cache = new();
+ }
+ }
- CreateNode("d:tableParts");
- XmlNode tbls = TopNode.SelectSingleNode("d:tableParts",NameSpaceManager);
+ if (row != -1) {
+ cache.Append("</row>");
+ }
+ cache.Append("</sheetData>");
+ sw.Write(cache.ToString());
+ sw.Flush();
+ }
+
+ private object GetFormulaValue(object v) {
+ //if (_package.Workbook._isCalculated)
+ //{
+ if (v != null && v.ToString() != "") {
+ return "<v>" + SecurityElement.Escape(GetValueForXml(v)) + "</v>"; //Fixes issue 15071
+ }
+ return "";
+ }
- var tblNode = tbls.OwnerDocument.CreateElement("tablePart",ExcelPackage.schemaMain);
- tbls.AppendChild(tblNode);
- tblNode.SetAttribute("id",ExcelPackage.schemaRelationships, rel.Id);
- }
- else
- {
- var stream = tbl.Part.GetStream(FileMode.Create);
- tbl.TableXml.Save(stream);
- }
- }
- }
+ private string GetCellType(object v, bool allowStr = false) {
+ if (v is bool) {
+ return " t=\"b\"";
+ }
+ if ((v is double && double.IsInfinity((double)v)) || 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 "";
+ }
- 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 Exception("Unknown RowFunction enum"));
- }
- }
- else
- {
- _values.SetValue(tbl.Address._toRow, colNum, col.TotalsRowLabel);
+ private string GetValueForXml(object v) {
+ string s;
+ try {
+ if (v is DateTime) {
+ double sdv = ((DateTime)v).ToOADate();
- }
+ if (Workbook.Date1904) {
+ sdv -= ExcelWorkbook._date1904Offset;
}
- internal void SetFormula(int row, int col, object value)
- {
- _formulas.SetValue(row, col, value);
- if (!_values.Exists(row, col)) _values.SetValue(row, col, null);
+ s = sdv.ToString(CultureInfo.InvariantCulture);
+ } else if (v is TimeSpan) {
+ s = new DateTime(((TimeSpan)v).Ticks).ToOADate().ToString(CultureInfo.InvariantCulture);
+ ;
+ } else if (v.GetType().IsPrimitive || v is double || v is decimal) {
+ if (v is double && double.IsNaN((double)v)) {
+ s = "";
+ } else if (v is double && double.IsInfinity((double)v)) {
+ s = "#NUM!";
+ } else {
+ s = Convert
+ .ToDouble(v, CultureInfo.InvariantCulture)
+ .ToString("R15", CultureInfo.InvariantCulture);
}
- internal void SetStyle(int row, int col, int value)
- {
- _styles.SetValue(row, col, value);
- if(!_values.Exists(row,col)) _values.SetValue(row, col, null);
+ } 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\" ");
}
-
- private void SavePivotTables()
- {
- foreach (var pt in PivotTables)
- {
- if (pt.DataFields.Count > 1)
- {
- XmlElement parentNode;
- if(pt.DataOnRows==true)
- {
- 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.ToString() + " 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;
- }
- }
- }
- pt.PivotTableXml.Save(pt.Part.GetStream(FileMode.Create));
- pt.CacheDefinition.CacheDefinitionXml.Save(pt.CacheDefinition.Part.GetStream(FileMode.Create));
- }
+ 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(">");
+ }
- 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 void WriteRow(
+ StreamWriter sw,
+ ExcelStyleCollection<ExcelXfs> cellXfs,
+ int prevRow,
+ int row) {
+ if (prevRow != -1) {
+ sw.Write("</row>");
+ }
+ //ulong rowID = ExcelRow.GetRowID(SheetID, row);
+ sw.Write("<row r=\"{0}\" ", row);
+ RowInternal currRow = _values.GetValue(row, 0) as RowInternal;
+ if (currRow != null) {
+ if (currRow.Hidden) {
+ sw.Write("ht=\"0\" hidden=\"1\" ");
+ } else if (currRow.Height != DefaultRowHeight) {
+ sw.Write(string.Format(CultureInfo.InvariantCulture, "ht=\"{0}\" ", currRow.Height));
+ if (currRow.CustomHeight) {
+ sw.Write("customHeight=\"1\" ");
}
+ }
- private static string GetTotalFunction(ExcelTableColumn col,string FunctionNum)
- {
- return string.Format("SUBTOTAL({0},{1}[{2}])", FunctionNum, col._tbl.Name, col.Name);
+ if (currRow.OutlineLevel > 0) {
+ sw.Write("outlineLevel =\"{0}\" ", currRow.OutlineLevel);
+ if (currRow.Collapsed) {
+ if (currRow.Hidden) {
+ sw.Write(" collapsed=\"1\" ");
+ } else {
+ sw.Write(" collapsed=\"1\" hidden=\"1\" "); //Always hidden
+ }
}
+ }
+ if (currRow.Phonetic) {
+ sw.Write("ph=\"1\" ");
+ }
+ }
+ var s = _styles.GetValue(row, 0);
+ if (s > 0) {
+ sw.Write("s=\"{0}\" customFormat=\"1\"", cellXfs[s].newID);
+ }
+ sw.Write(">");
+ }
- private void CleanupMergedCells(MergeCellsCollection _mergedCells)
- {
- int i=0;
- while (i < _mergedCells.List.Count)
- {
- if (_mergedCells[i] == null)
- {
- _mergedCells.List.RemoveAt(i);
- }
- else
- {
- i++;
- }
- }
+ /// <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
+ && !string.IsNullOrEmpty((uri as ExcelHyperLink).ReferenceAddress)) {
+ ExcelHyperLink hl = uri as ExcelHyperLink;
+ sw.Write(
+ "<hyperlink ref=\"{0}\" location=\"{1}\" {2}{3}/>",
+ Cells[cse.Row, cse.Column, cse.Row + hl.RowSpann, cse.Column + hl.ColSpann].Address,
+ ExcelCellBase.GetFullAddress(
+ SecurityElement.Escape(Name),
+ SecurityElement.Escape(hl.ReferenceAddress)),
+ string.IsNullOrEmpty(hl.Display)
+ ? ""
+ : "display=\"" + SecurityElement.Escape(hl.Display) + "\" ",
+ string.IsNullOrEmpty(hl.ToolTip)
+ ? ""
+ : "tooltip=\"" + SecurityElement.Escape(hl.ToolTip) + "\" ");
+ } else if (uri != null) {
+ string id;
+ Uri hyp;
+ if (uri is ExcelHyperLink) {
+ hyp = ((ExcelHyperLink)uri).OriginalUri;
+ } else {
+ hyp = uri;
}
- private void UpdateColBreaks(StreamWriter sw)
- {
- StringBuilder breaks = new StringBuilder();
- int count = 0;
- var cse = new CellsStoreEnumerator<object>(_values, 0, 0, 0, ExcelPackage.MaxColumns);
- //foreach (ExcelColumn col in _columns)
- 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(string.Format("<colBreaks count=\"{0}\" manualBreakCount=\"{0}\">{1}</colBreaks>", count, breaks.ToString()));
- }
+ if (hyps.ContainsKey(hyp.OriginalString)) {
+ id = hyps[hyp.OriginalString];
+ } else {
+ var relationship = Part.CreateRelationship(
+ hyp,
+ TargetMode.External,
+ ExcelPackage._schemaHyperlink);
+ if (uri is ExcelHyperLink) {
+ ExcelHyperLink hl = uri as ExcelHyperLink;
+ 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);
+ }
+ id = relationship.Id;
}
+ //cell.HyperLinkRId = id;
+ }
+ }
+ if (!first) {
+ sw.Write("</hyperlinks>");
+ }
+ }
- 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(string.Format("<rowBreaks count=\"{0}\" manualBreakCount=\"{0}\">{1}</rowBreaks>", count, breaks.ToString()));
- }
- }
- /// <summary>
- /// Inserts the cols collection into the XML document
- /// </summary>
- private void UpdateColumnData(StreamWriter sw)
- {
- //ExcelColumn prevCol = null; //commented out 11/1-12 JK
- //foreach (ExcelColumn col in _columns)
- //{
- // if (prevCol != null)
- // {
- // if(prevCol.ColumnMax != col.ColumnMin-1)
- // {
- // prevCol._columnMax=col.ColumnMin-1;
- // }
- // }
- // prevCol = col;
- //}
- var cse = new CellsStoreEnumerator<object>(_values, 0, 1, 0, ExcelPackage.MaxColumns);
- //sw.Write("<cols>");
- //foreach (ExcelColumn col in _columns)
- bool first = true;
- while(cse.Next())
- {
- if (first)
- {
- sw.Write("<cols>");
- first = false;
- }
- var col = cse.Value as ExcelColumn;
- ExcelStyleCollection<ExcelXfs> cellXfs = _package.Workbook.Styles.CellXfs;
+ /// <summary>
+ /// Create the hyperlinks node in the XML
+ /// </summary>
+ /// <returns></returns>
+ private XmlNode CreateHyperLinkCollection() {
+ XmlElement hl = _worksheetXml.CreateElement("hyperlinks", ExcelPackage._schemaMain);
+ XmlNode prevNode = _worksheetXml.SelectSingleNode(
+ "//d:conditionalFormatting",
+ NameSpaceManager);
+ if (prevNode == null) {
+ prevNode = _worksheetXml.SelectSingleNode("//d:mergeCells", NameSpaceManager);
+ if (prevNode == null) {
+ prevNode = _worksheetXml.SelectSingleNode("//d:sheetData", NameSpaceManager);
+ }
+ }
+ return _worksheetXml.DocumentElement.InsertAfter(hl, prevNode);
+ }
- sw.Write("<col min=\"{0}\" max=\"{1}\"", col.ColumnMin, col.ColumnMax);
- if (col.Hidden == true)
- {
- //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\"");
- }
+ /// <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();
+ int fromRow,
+ fromCol,
+ toRow,
+ toCol;
+ if (_values.GetDimension(out fromRow, out fromCol, out toRow, out 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, this);
+ }
+ return _protection;
+ }
+ }
- var styleID = col.StyleID >= 0 ? cellXfs[col.StyleID].newID : col.StyleID;
- if (styleID > 0)
- {
- sw.Write(" style=\"{0}\"", styleID);
- }
- sw.Write(" />");
+ private ExcelProtectedRangeCollection _protectedRanges;
- //if (col.PageBreak)
- //{
- // colBreaks.Add(col.ColumnMin);
- //}
- }
- if (!first)
- {
- sw.Write("</cols>");
- }
- }
- /// <summary>
- /// Insert row and cells into the XML document
- /// </summary>
- private void UpdateRowCellData(StreamWriter sw)
- {
- ExcelStyleCollection<ExcelXfs> cellXfs = _package.Workbook.Styles.CellXfs;
-
- int row = -1;
+ public ExcelProtectedRangeCollection ProtectedRanges {
+ get {
+ if (_protectedRanges == null) {
+ _protectedRanges = new(NameSpaceManager, TopNode, this);
+ }
+ return _protectedRanges;
+ }
+ }
- StringBuilder sbXml = new StringBuilder();
- var ss = _package.Workbook._sharedStrings;
- var styles = _package.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);
- }
- }
+ private ExcelTableCollection _tables;
- 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)
- {
- int sfId = (int)formula;
- var f = _sharedFormulas[(int)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));
- }
+ /// <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;
+ }
+ }
- }
- 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 ExcelWorkbook.SharedStringItem() { 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);
- }
- }
- }
- ////Update hyperlinks.
- //if (cell.Hyperlink != null)
- //{
- // _hyperLinkCells.Add(cell.CellID);
- //}
- }
- else //ExcelRow
- {
- //int newRow=((ExcelRow)cse.Value).Row;
- WriteRow(cache, cellXfs, row, cse.Row);
- row = cse.Row;
- }
- if (cache.Length > 0x600000)
- {
- sw.Write(cache.ToString());
- cache = new StringBuilder();
- }
- }
+ private ExcelPivotTableCollection _pivotTables;
- if (row != -1) cache.Append("</row>");
- cache.Append("</sheetData>");
- sw.Write(cache.ToString());
- sw.Flush();
+ /// <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 object GetFormulaValue(object v)
- {
- //if (_package.Workbook._isCalculated)
- //{
- if (v != null && v.ToString()!="")
- {
- return "<v>" + SecurityElement.Escape(GetValueForXml(v)) + "</v>"; //Fixes issue 15071
- }
- else
- {
- return "";
- }
- }
+ private ExcelConditionalFormattingCollection _conditionalFormatting;
- private string GetCellType(object v, bool allowStr=false)
- {
- if (v is bool)
- {
- return " t=\"b\"";
- }
- else if ((v is double && double.IsInfinity((double)v)) || v is ExcelErrorValue)
- {
- return " t=\"e\"";
- }
- else if(allowStr && v!=null && !(v.GetType().IsPrimitive || v is double || v is decimal || v is DateTime || v is TimeSpan))
- {
- return " t=\"str\"";
- }
- else
- {
- return "";
- }
- }
+ /// <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 string GetValueForXml(object v)
- {
- string s;
- try
- {
- if (v is DateTime)
- {
- double sdv = ((DateTime)v).ToOADate();
+ private ExcelDataValidationCollection _dataValidation;
- if (Workbook.Date1904)
- {
- sdv -= ExcelWorkbook.date1904Offset;
- }
+ /// <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;
+ }
+ }
- s = sdv.ToString(CultureInfo.InvariantCulture);
- }
- else if (v is TimeSpan)
- {
- s = new DateTime(((TimeSpan)v).Ticks).ToOADate().ToString(CultureInfo.InvariantCulture); ;
- }
- else if(v.GetType().IsPrimitive || v is double || v is decimal)
- {
- if (v is double && double.IsNaN((double)v))
- {
- s = "";
- }
- else if (v is double && double.IsInfinity((double)v))
- {
- s = "#NUM!";
- }
- else
- {
- s = Convert.ToDouble(v, CultureInfo.InvariantCulture).ToString("R15", CultureInfo.InvariantCulture);
- }
- }
- else
- {
- s = v.ToString();
- }
- }
+ /// <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;
+ }
- 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)
- {
+ /// <summary>
+ /// The workbook object
+ /// </summary>
+ public ExcelWorkbook Workbook => _package.Workbook;
- if (currRow.Hidden == true)
- {
- cache.Append("ht=\"0\" hidden=\"1\" ");
- }
- else if (currRow.Height != DefaultRowHeight && currRow.Height>=0)
- {
- cache.AppendFormat(string.Format(CultureInfo.InvariantCulture, "ht=\"{0}\" ", currRow.Height));
- if (currRow.CustomHeight)
- {
- cache.Append("customHeight=\"1\" ");
- }
- }
+ /// <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;
+ }
- 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(">");
- }
- private void WriteRow(StreamWriter sw, ExcelStyleCollection<ExcelXfs> cellXfs, int prevRow, int row)
- {
- if (prevRow != -1) sw.Write("</row>");
- //ulong rowID = ExcelRow.GetRowID(SheetID, row);
- sw.Write("<row r=\"{0}\" ", row);
- RowInternal currRow = _values.GetValue(row, 0) as RowInternal;
- if (currRow!=null)
- {
-
- if (currRow.Hidden == true)
- {
- sw.Write("ht=\"0\" hidden=\"1\" ");
- }
- else if (currRow.Height != DefaultRowHeight)
- {
- sw.Write(string.Format(CultureInfo.InvariantCulture, "ht=\"{0}\" ", currRow.Height));
- if (currRow.CustomHeight)
- {
- sw.Write("customHeight=\"1\" ");
- }
- }
+ while (_sharedFormulas.ContainsKey(i)) {
+ i++;
+ }
+ return i;
+ }
- if (currRow.OutlineLevel > 0)
- {
- sw.Write("outlineLevel =\"{0}\" ", currRow.OutlineLevel);
- if (currRow.Collapsed)
- {
- if (currRow.Hidden)
- {
- sw.Write(" collapsed=\"1\" ");
- }
- else
- {
- sw.Write(" collapsed=\"1\" hidden=\"1\" "); //Always hidden
- }
- }
- }
- if (currRow.Phonetic)
- {
- sw.Write("ph=\"1\" ");
- }
- }
- var s = _styles.GetValue(row, 0);
- if (s > 0)
- {
- sw.Write("s=\"{0}\" customFormat=\"1\"", cellXfs[s].newID);
- }
- sw.Write(">");
- }
+ internal void SetHfLegacyDrawingRel(string relId) {
+ SetXmlNodeString("d:legacyDrawingHF/@r:id", relId);
+ }
- /// <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 && !string.IsNullOrEmpty((uri as ExcelHyperLink).ReferenceAddress))
- {
- ExcelHyperLink hl = uri as ExcelHyperLink;
- sw.Write("<hyperlink ref=\"{0}\" location=\"{1}\" {2}{3}/>",
- Cells[cse.Row, cse.Column, cse.Row + hl.RowSpann, cse.Column + hl.ColSpann].Address,
- ExcelCellBase.GetFullAddress(SecurityElement.Escape(Name), SecurityElement.Escape(hl.ReferenceAddress)),
- string.IsNullOrEmpty(hl.Display) ? "" : "display=\"" + SecurityElement.Escape(hl.Display) + "\" ",
- string.IsNullOrEmpty(hl.ToolTip) ? "" : "tooltip=\"" + SecurityElement.Escape(hl.ToolTip) + "\" ");
- }
- else if( uri!=null)
- {
- string id;
- Uri hyp;
- if (uri is ExcelHyperLink)
- {
- hyp = ((ExcelHyperLink)uri).OriginalUri;
- }
- else
- {
- hyp = uri;
- }
- if (hyps.ContainsKey(hyp.OriginalString))
- {
- id = hyps[hyp.OriginalString];
- }
- else
- {
- var relationship = Part.CreateRelationship(hyp, Packaging.TargetMode.External, ExcelPackage.schemaHyperlink);
- if (uri is ExcelHyperLink)
- {
- ExcelHyperLink hl = uri as ExcelHyperLink;
- 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);
- }
- id = relationship.Id;
- }
- //cell.HyperLinkRId = id;
- }
- }
- if (!first)
- {
- sw.Write("</hyperlinks>");
- }
- }
- /// <summary>
- /// Create the hyperlinks node in the XML
- /// </summary>
- /// <returns></returns>
- private XmlNode CreateHyperLinkCollection()
- {
- XmlElement hl=_worksheetXml.CreateElement("hyperlinks",ExcelPackage.schemaMain);
- XmlNode prevNode = _worksheetXml.SelectSingleNode("//d:conditionalFormatting", NameSpaceManager);
- if (prevNode == null)
- {
- prevNode = _worksheetXml.SelectSingleNode("//d:mergeCells", NameSpaceManager);
- if (prevNode == null)
- {
- prevNode = _worksheetXml.SelectSingleNode("//d:sheetData", NameSpaceManager);
- }
- }
- return _worksheetXml.DocumentElement.InsertAfter(hl, prevNode);
- }
- /// <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();
- int fromRow, fromCol, toRow, toCol;
- if (_values.GetDimension(out fromRow, out fromCol, out toRow, out toCol))
- {
- var addr = new ExcelAddressBase(fromRow, fromCol, toRow, toCol);
- addr._ws = Name;
- return addr;
- }
- else
- {
- return null;
- }
- }
- }
- ExcelSheetProtection _protection=null;
- /// <summary>
- /// Access to sheet protection properties
- /// </summary>
- public ExcelSheetProtection Protection
- {
- get
- {
- if (_protection == null)
- {
- _protection = new ExcelSheetProtection(NameSpaceManager, TopNode, this);
- }
- return _protection;
- }
- }
+ internal void RemoveLegacyDrawingRel(string relId) {
+ var n = WorksheetXml.DocumentElement.SelectSingleNode(
+ string.Format("d:legacyDrawing[@r:id=\"{0}\"]", relId),
+ NameSpaceManager);
+ if (n != null) {
+ n.ParentNode.RemoveChild(n);
+ }
+ }
- private ExcelProtectedRangeCollection _protectedRanges;
- public ExcelProtectedRangeCollection ProtectedRanges
- {
- get
- {
- if (_protectedRanges == null)
- _protectedRanges = new ExcelProtectedRangeCollection(NameSpaceManager, TopNode, this);
- return _protectedRanges;
- }
- }
-
- ExcelTableCollection _tables = null;
- /// <summary>
- /// Tables defined in the worksheet.
- /// </summary>
- public ExcelTableCollection Tables
- {
- get
- {
- CheckSheetType();
- if (Workbook._nextTableID == int.MinValue) Workbook.ReadAllTables();
- if (_tables == null)
- {
- _tables = new ExcelTableCollection(this);
- }
- return _tables;
- }
- }
- ExcelPivotTableCollection _pivotTables = null;
- /// <summary>
- /// Pivottables defined in the worksheet.
- /// </summary>
- public ExcelPivotTableCollection PivotTables
- {
- get
- {
- CheckSheetType();
- if (_pivotTables == null)
- {
- if (Workbook._nextPivotTableID == int.MinValue) Workbook.ReadAllTables();
- _pivotTables = new ExcelPivotTableCollection(this);
- }
- return _pivotTables;
- }
- }
- private ExcelConditionalFormattingCollection _conditionalFormatting = null;
- /// <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 ExcelConditionalFormattingCollection(this);
- }
- return _conditionalFormatting;
- }
- }
- private ExcelDataValidationCollection _dataValidation = null;
- /// <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 ExcelDataValidationCollection(this);
- }
- return _dataValidation;
- }
- }
+ 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) {
+ try {
+ double sdv = ((DateTime)cse.Value).ToOADate();
+ sdv += offset;
- /// <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
- {
- get
- {
- return _package.Workbook;
- }
- }
- #endregion
- #endregion // END Worksheet Private Methods
+ cse.Value = DateTime.FromOADate(sdv);
+ } catch {}
+ }
+ }
+ }
- /// <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;
+ public string GetFormula(int row, int col) {
+ var v = _formulas.GetValue(row, col);
+ if (v is int) {
+ return _sharedFormulas[(int)v].GetFormula(row, col, Name);
+ }
+ if (v != null) {
+ return v.ToString();
+ }
+ return "";
+ }
- while(_sharedFormulas.ContainsKey(i))
- {
- i++;
- }
- return i;
- }
- internal void SetHFLegacyDrawingRel(string relID)
- {
- SetXmlNodeString("d:legacyDrawingHF/@r:id", relID);
- }
- internal void RemoveLegacyDrawingRel(string relID)
- {
- var n = WorksheetXml.DocumentElement.SelectSingleNode(string.Format("d:legacyDrawing[@r:id=\"{0}\"]", relID), NameSpaceManager);
- if (n != null)
- {
- n.ParentNode.RemoveChild(n);
- }
- }
+ public string GetFormulaR1C1(int row, int col) {
+ var v = _formulas.GetValue(row, col);
+ if (v is int) {
+ var sf = _sharedFormulas[(int)v];
+ return ExcelCellBase.TranslateToR1C1(
+ Formulas.RemoveDummyFunction(sf.Formula),
+ sf.StartRow,
+ sf.StartCol);
+ }
+ if (v != null) {
+ return ExcelCellBase.TranslateToR1C1(Formulas.RemoveDummyFunction(v.ToString()), row, col);
+ }
+ return "";
+ }
- 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)
- {
- try
- {
- double sdv = ((DateTime)cse.Value).ToOADate();
- sdv += offset;
+ public string GetFormulaR1C1_V1(int row, int col) {
+ var v = _formulas.GetValue(row, col);
+ if (v is int) {
+ var sf = _sharedFormulas[(int)v];
+ 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 "";
+ }
- cse.Value = DateTime.FromOADate(sdv);
- }
- catch
- {
- }
- }
- }
- }
- public string GetFormula(int row, int col)
- {
- var v = _formulas.GetValue(row, col);
- if (v is int)
- {
- return _sharedFormulas[(int)v].GetFormula(row,col, Name);
- }
- else if (v != null)
- {
- return v.ToString();
- }
- else
- {
- return "";
- }
- }
- public string GetFormulaR1C1(int row, int col)
- {
- var v = _formulas.GetValue(row, col);
- if (v is int)
- {
- var sf = _sharedFormulas[(int)v];
- return ExcelCellBase.TranslateToR1C1(Formulas.RemoveDummyFunction(sf.Formula), sf.StartRow, sf.StartCol);
- }
- else if (v != null)
- {
- return ExcelCellBase.TranslateToR1C1(Formulas.RemoveDummyFunction(v.ToString()), row, col);
- }
- else
- {
- return "";
- }
- }
+ public bool IsArrayFormula(int row, int col) =>
+ _flags.GetFlagValue(row, col, CellFlags.ArrayFormula);
- public string GetFormulaR1C1_V1(int row, int col)
- {
- var v = _formulas.GetValue(row, col);
- if (v is int)
- {
- var sf = _sharedFormulas[(int)v];
- return ExcelCellBase.TranslateToR1C1_V1(Formulas.RemoveDummyFunction(sf.Formula), sf.StartRow, sf.StartCol);
- }
- else if (v != null)
- {
- return ExcelCellBase.TranslateToR1C1_V1(Formulas.RemoveDummyFunction(v.ToString()), row, col);
- }
- else
- {
- return "";
- }
- }
+ public string GetArrayFormulaAddress(int row, int col) {
+ var v = _formulas.GetValue(row, col);
+ if ((v is int) && (_sharedFormulas[(int)v].IsArray)) {
+ return _sharedFormulas[(int)v].Address;
+ }
+ 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) && (_sharedFormulas[(int)v].IsArray))
- {
- return _sharedFormulas[(int)v].Address;
- }
- else
- {
- 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 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 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();
- }
- } // END class Worksheet
+ public int GetHashCode(ExcelWorksheet obj) {
+ return obj.WorksheetXml.OuterXml.GetHashCode();
+ }
}
diff --git a/EPPlus/ExcelWorksheetView.cs b/EPPlus/ExcelWorksheetView.cs
index 254a0d0..c3047a2 100644
--- a/EPPlus/ExcelWorksheetView.cs
+++ b/EPPlus/ExcelWorksheetView.cs
@@ -4,7 +4,7 @@
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
* See http://www.codeplex.com/EPPlus for details.
*
- * Copyright (C) 2011 Jan Källman
+ * Copyright (C) 2011 Jan K�llman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -13,455 +13,388 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
+ * Jan K�llman Initial Release 2009-10-01
+ * Jan K�llman License changed GPL-->LGPL 2011-12-27
*******************************************************************************/
+
using System;
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
- {
- XmlElement _selectionNode = null;
- internal ExcelWorksheetPanes(XmlNamespaceManager ns, XmlNode topNode) :
- base(ns, topNode)
- {
- if(topNode.Name=="selection")
- {
- _selectionNode=topNode as XmlElement;
- }
- }
+namespace OfficeOpenXml;
- 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 fromCol, fromRow, toCol, toRow;
- if(_selectionNode==null) CreateSelectionElement();
- ExcelCellBase.GetRowColFromAddress(value, out fromRow, out fromCol, out toRow, out toCol);
- SetXmlNodeString(_activeCellPath, value);
- if (((XmlElement)TopNode).GetAttribute("sqref") == "")
- {
+/// <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;
- SelectedRange = ExcelCellBase.GetAddress(fromRow, fromCol);
- }
- else
- {
- //TODO:Add fix for out of range here
- }
- }
- }
-
- private void CreateSelectionElement()
- {
- _selectionNode=TopNode.OwnerDocument.CreateElement("selection", ExcelPackage.schemaMain);
- TopNode.AppendChild(_selectionNode);
- TopNode=_selectionNode;
- }
- 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 fromCol, fromRow, toCol, toRow;
- if(_selectionNode==null) CreateSelectionElement();
- ExcelCellBase.GetRowColFromAddress(value, out fromRow, out fromCol, out toRow, out toCol);
- SetXmlNodeString(_selectionRangePath, value);
- if (((XmlElement)TopNode).GetAttribute("activeCell") == "")
- {
-
- ActiveCell = ExcelCellBase.GetAddress(fromRow, fromCol);
- }
- else
- {
- //TODO:Add fix for out of range here
- }
- }
- }
- }
- private ExcelWorksheet _worksheet;
-
- #region ExcelWorksheetView Constructor
- /// <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;
- SchemaNodeOrder = new string[] { "sheetViews", "sheetView", "pane", "selection" };
- Panes = LoadPanes();
- }
-
- #endregion
- private ExcelWorksheetPanes[] LoadPanes()
- {
- XmlNodeList nodes = TopNode.SelectNodes("//d:selection", NameSpaceManager);
- if(nodes.Count==0)
- {
- return new ExcelWorksheetPanes[] { new ExcelWorksheetPanes(NameSpaceManager, TopNode) };
- }
- else
- {
- ExcelWorksheetPanes[] panes = new ExcelWorksheetPanes[nodes.Count];
- int i=0;
- foreach(XmlElement elem in nodes)
- {
- panes[i++] = new ExcelWorksheetPanes(NameSpaceManager, elem);
- }
- return panes;
- }
- }
- #region SheetViewElement
- /// <summary>
- /// Returns a reference to the sheetView element
- /// </summary>
- protected internal XmlElement SheetViewElement
- {
- get
- {
- return (XmlElement)TopNode;
- }
- }
- #endregion
- #region TabSelected
- private XmlElement _selectionNode = null;
- private XmlElement SelectionNode
- {
- get
- {
- _selectionNode = SheetViewElement.SelectSingleNode("//d:selection", _worksheet.NameSpaceManager) as XmlElement;
- if (_selectionNode == null)
- {
- _selectionNode = _worksheet.WorksheetXml.CreateElement("selection", ExcelPackage.schemaMain);
- SheetViewElement.AppendChild(_selectionNode);
- }
- return _selectionNode;
- }
- }
- #endregion
- #region Public Methods & Properties
- /// <summary>
- /// The active cell.
- /// </summary>
- public string ActiveCell
- {
- get
- {
- return 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
- {
- return 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
- {
- return GetXmlNodeBool("@tabSelected");
- }
- set
- {
- if (value)
- {
- // // ensure no other worksheet has its tabSelected attribute set to 1
- foreach (ExcelWorksheet sheet in _worksheet._package.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
- {
- return 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
- {
- return GetXmlNodeString("@view") == "pageBreakPreview";
- }
- set
- {
- if (value)
- SetXmlNodeString("@view", "pageBreakPreview");
- else
- SheetViewElement.RemoveAttribute("view");
- }
- }
- /// <summary>
- /// Show gridlines in the worksheet
- /// </summary>
- public bool ShowGridLines
- {
- get
- {
- return 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
- {
- return GetXmlNodeBool("@showRowColHeaders");
- }
- set
- {
- SetXmlNodeString("@showRowColHeaders", value ? "1" : "0");
- }
- }
- /// <summary>
- /// Window zoom magnification for current view representing percent values.
- /// </summary>
- public int ZoomScale
- {
- get
- {
- return 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
- {
- return GetXmlNodeBool("@rightToLeft");
- }
- set
- {
- SetXmlNodeString("@rightToLeft", value == true ? "1" : "0");
- }
- }
- internal bool WindowProtection
- {
- get
- {
- return GetXmlNodeBool("@windowProtection",false);
- }
- set
- {
- SetXmlNodeBool("@windowProtection",value,false);
- }
- }
- /// <summary>
- /// Reference to the panes
- /// </summary>
- public ExcelWorksheetPanes[] Panes
- {
- get;
- internal set;
- }
- string _paneNodePath = "d:pane";
- 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;
- }
- #endregion
+ 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 fromCol,
+ fromRow,
+ toCol,
+ toRow;
+ if (_selectionNode == null) {
+ CreateSelectionElement();
+ }
+ ExcelCellBase.GetRowColFromAddress(value, out fromRow, out 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 fromCol,
+ fromRow,
+ toCol,
+ toRow;
+ if (_selectionNode == null) {
+ CreateSelectionElement();
+ }
+ ExcelCellBase.GetRowColFromAddress(value, out fromRow, out 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 ExcelWorksheet _worksheet;
+
+ /// <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;
+ SchemaNodeOrder = new[] { "sheetViews", "sheetView", "pane", "selection" };
+ 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;
+
+ private XmlElement _selectionNode;
+
+ private XmlElement SelectionNode {
+ get {
+ _selectionNode =
+ SheetViewElement.SelectSingleNode("//d:selection", _worksheet.NameSpaceManager)
+ as XmlElement;
+ if (_selectionNode == null) {
+ _selectionNode = _worksheet.WorksheetXml.CreateElement(
+ "selection",
+ ExcelPackage._schemaMain);
+ SheetViewElement.AppendChild(_selectionNode);
+ }
+ return _selectionNode;
+ }
+ }
+
+ /// <summary>
+ /// The active cell.
+ /// </summary>
+ public string ActiveCell {
+ get { return 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 { return 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 { return GetXmlNodeBool("@tabSelected"); }
+ set {
+ if (value) {
+ // // ensure no other worksheet has its tabSelected attribute set to 1
+ foreach (ExcelWorksheet sheet in _worksheet._package.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 { return 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 { return GetXmlNodeString("@view") == "pageBreakPreview"; }
+ set {
+ if (value) {
+ SetXmlNodeString("@view", "pageBreakPreview");
+ } else {
+ SheetViewElement.RemoveAttribute("view");
+ }
+ }
+ }
+
+ /// <summary>
+ /// Show gridlines in the worksheet
+ /// </summary>
+ public bool ShowGridLines {
+ get { return 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 { return GetXmlNodeBool("@showRowColHeaders"); }
+ set { SetXmlNodeString("@showRowColHeaders", value ? "1" : "0"); }
+ }
+
+ /// <summary>
+ /// Window zoom magnification for current view representing percent values.
+ /// </summary>
+ public int ZoomScale {
+ get { return 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 { return GetXmlNodeBool("@rightToLeft"); }
+ set { SetXmlNodeString("@rightToLeft", value ? "1" : "0"); }
+ }
+
+ internal bool WindowProtection {
+ get { return GetXmlNodeBool("@windowProtection", false); }
+ set { SetXmlNodeBool("@windowProtection", value, false); }
+ }
+
+ /// <summary>
+ /// Reference to the panes
+ /// </summary>
+ public ExcelWorksheetPanes[] Panes { get; internal set; }
+
+ private string _paneNodePath = "d:pane";
+ private 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
index 18c2ecf..91e3cdb 100644
--- a/EPPlus/ExcelWorksheets.cs
+++ b/EPPlus/ExcelWorksheets.cs
@@ -13,516 +13,516 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Xml;
using System.IO;
+using System.Text.RegularExpressions;
+using System.Xml;
+using OfficeOpenXml.Packaging;
using OfficeOpenXml.Utils;
-namespace OfficeOpenXml
-{
- /// <summary>
- /// The collection of worksheets for the workbook
- /// </summary>
- public class ExcelWorksheets : XmlHelper, IEnumerable<ExcelWorksheet>
- {
- #region Private Properties
- private ExcelPackage _pck;
- private Dictionary<int, ExcelWorksheet> _worksheets;
- private XmlNamespaceManager _namespaceManager;
- #endregion
- #region ExcelWorksheets Constructor
- internal ExcelWorksheets(ExcelPackage pck, XmlNamespaceManager nsm, XmlNode topNode) :
- base(nsm, topNode)
- {
- _pck = pck;
- _namespaceManager = nsm;
- _worksheets = new Dictionary<int, ExcelWorksheet>();
- 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);
+namespace OfficeOpenXml;
- //Hidden property
- eWorkSheetHidden hidden = eWorkSheetHidden.Visible;
- XmlNode attr = sheetNode.Attributes["state"];
- if (attr != null)
- hidden = TranslateHidden(attr.Value);
+/// <summary>
+/// The collection of worksheets for the workbook
+/// </summary>
+public class ExcelWorksheets : XmlHelper, IEnumerable<ExcelWorksheet> {
+ private ExcelPackage _pck;
+ private Dictionary<int, ExcelWorksheet> _worksheets;
+ private XmlNamespaceManager _namespaceManager;
- var sheetRelation = pck.Workbook.Part.GetRelationship(relId);
- Uri uriWorksheet = UriHelper.ResolvePartUri(pck.Workbook.WorkbookUri, sheetRelation.TargetUri);
+ internal ExcelWorksheets(ExcelPackage pck, XmlNamespaceManager nsm, XmlNode topNode)
+ : base(nsm, topNode) {
+ _pck = pck;
+ _namespaceManager = nsm;
+ _worksheets = new();
+ int positionId = 1;
- //add the worksheet
- if (sheetRelation.RelationshipType.EndsWith("chartsheet"))
- {
- _worksheets.Add(positionID, new ExcelChartsheet(_namespaceManager, _pck, relId, uriWorksheet, name, sheetID, positionID, hidden));
- }
- else
- {
- _worksheets.Add(positionID, new ExcelWorksheet(_namespaceManager, _pck, relId, uriWorksheet, name, sheetID, positionID, hidden));
- }
- positionID++;
- }
- }
- }
+ 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);
- private eWorkSheetHidden TranslateHidden(string value)
- {
- switch (value)
- {
- case "hidden":
- return eWorkSheetHidden.Hidden;
- case "veryHidden":
- return eWorkSheetHidden.VeryHidden;
- default:
- return eWorkSheetHidden.Visible;
- }
- }
- #endregion
- #region ExcelWorksheets Public Properties
- /// <summary>
- /// Returns the number of worksheets in the workbook
- /// </summary>
- public int Count
- {
- get { return (_worksheets.Count); }
- }
- #endregion
- private const string ERR_DUP_WORKSHEET = "A worksheet with this name already exists in the workbook";
- internal const string WORKSHEET_CONTENTTYPE = @"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml";
- internal const string CHARTSHEET_CONTENTTYPE = @"application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml";
- #region ExcelWorksheets Public Methods
- /// <summary>
- /// Foreach support
- /// </summary>
- /// <returns>An enumerator</returns>
- public IEnumerator<ExcelWorksheet> GetEnumerator()
- {
- return (_worksheets.Values.GetEnumerator());
- }
- #region IEnumerable Members
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return (_worksheets.Values.GetEnumerator());
+ //Hidden property
+ eWorkSheetHidden hidden = eWorkSheetHidden.Visible;
+ XmlNode attr = sheetNode.Attributes["state"];
+ if (attr != null) {
+ hidden = TranslateHidden(attr.Value);
}
- #endregion
- #region Add Worksheet
- /// <summary>
- /// Adds a new blank worksheet.
- /// </summary>
- /// <param name="Name">The name of the workbook</param>
- public ExcelWorksheet Add(string Name)
- {
- int sheetID;
- Uri uriWorksheet;
- lock (_worksheets)
- {
- Name = ValidateFixSheetName(Name);
- if (GetByName(Name) != null)
- {
- throw (new InvalidOperationException(ERR_DUP_WORKSHEET + " : " + Name));
- }
- GetSheetURI(ref Name, out sheetID, out uriWorksheet, false);
- Packaging.ZipPackagePart worksheetPart = _pck.Package.CreatePart(uriWorksheet, WORKSHEET_CONTENTTYPE, _pck.Compression);
+ var sheetRelation = pck.Workbook.Part.GetRelationship(relId);
+ Uri uriWorksheet = UriHelper.ResolvePartUri(
+ pck.Workbook.WorkbookUri,
+ sheetRelation.TargetUri);
- //Create the new, empty worksheet and save it to the package
- StreamWriter streamWorksheet = new StreamWriter(worksheetPart.GetStream(FileMode.Create, FileAccess.Write));
- XmlDocument worksheetXml = CreateNewWorksheet(false);
- worksheetXml.Save(streamWorksheet);
-
- string rel = CreateWorkbookRel(Name, sheetID, uriWorksheet, false);
-
- int positionID = _worksheets.Count + 1;
- ExcelWorksheet worksheet;
-
- {
- worksheet = new ExcelWorksheet(_namespaceManager, _pck, rel, uriWorksheet, Name, sheetID, positionID, eWorkSheetHidden.Visible);
- }
-
- _worksheets.Add(positionID, worksheet);
- return worksheet;
- }
+ //add the worksheet
+ if (sheetRelation.RelationshipType.EndsWith("chartsheet")) {
+ _worksheets.Add(
+ positionId,
+ new ExcelChartsheet(
+ _namespaceManager,
+ _pck,
+ relId,
+ uriWorksheet,
+ name,
+ sheetId,
+ positionId,
+ hidden));
+ } else {
+ _worksheets.Add(
+ positionId,
+ new(_namespaceManager, _pck, relId, uriWorksheet, name, sheetId, positionId, hidden));
}
+ positionId++;
+ }
+ }
+ }
- string CreateWorkbookRel(string Name, int sheetID, Uri uriWorksheet, bool isChart)
- {
- //Create the relationship between the workbook and the new worksheet
- var rel = _pck.Workbook.Part.CreateRelationship(UriHelper.GetRelativeUri(_pck.Workbook.WorkbookUri, uriWorksheet), Packaging.TargetMode.Internal, ExcelPackage.schemaRelationships + "/" + (isChart ? "chartsheet" : "worksheet"));
+ private eWorkSheetHidden TranslateHidden(string value) {
+ switch (value) {
+ case "hidden":
+ return eWorkSheetHidden.Hidden;
+ case "veryHidden":
+ return eWorkSheetHidden.VeryHidden;
+ default:
+ return eWorkSheetHidden.Visible;
+ }
+ }
- //Create the new sheet node
- XmlElement worksheetNode = _pck.Workbook.WorkbookXml.CreateElement("sheet", ExcelPackage.schemaMain);
- worksheetNode.SetAttribute("name", Name);
- worksheetNode.SetAttribute("sheetId", sheetID.ToString());
- worksheetNode.SetAttribute("id", ExcelPackage.schemaRelationships, rel.Id);
+ /// <summary>
+ /// Returns the number of worksheets in the workbook
+ /// </summary>
+ public int Count => (_worksheets.Count);
- TopNode.AppendChild(worksheetNode);
- return rel.Id;
+ 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";
+ internal const string _chartsheetContenttype =
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+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) {
+ int sheetId;
+ Uri uriWorksheet;
+ lock (_worksheets) {
+ name = ValidateFixSheetName(name);
+ if (GetByName(name) != null) {
+ throw (new InvalidOperationException(_errDupWorksheet + " : " + name));
+ }
+ GetSheetUri(ref name, out sheetId, out uriWorksheet, false);
+ ZipPackagePart worksheetPart = _pck.Package.CreatePart(
+ uriWorksheet,
+ _worksheetContenttype,
+ _pck.Compression);
+
+ //Create the new, empty worksheet and save it to the package
+ StreamWriter streamWorksheet = new StreamWriter(
+ worksheetPart.GetStream(FileMode.Create, FileAccess.Write));
+ XmlDocument worksheetXml = CreateNewWorksheet(false);
+ worksheetXml.Save(streamWorksheet);
+
+ string rel = CreateWorkbookRel(name, sheetId, uriWorksheet, false);
+
+ int positionId = _worksheets.Count + 1;
+ ExcelWorksheet worksheet;
+
+ {
+ worksheet = new(
+ _namespaceManager,
+ _pck,
+ rel,
+ uriWorksheet,
+ name,
+ sheetId,
+ positionId,
+ eWorkSheetHidden.Visible);
+ }
+
+ _worksheets.Add(positionId, worksheet);
+ return worksheet;
+ }
+ }
+
+ private string CreateWorkbookRel(string name, int sheetId, Uri uriWorksheet, bool isChart) {
+ //Create the relationship between the workbook and the new worksheet
+ var rel = _pck.Workbook.Part.CreateRelationship(
+ UriHelper.GetRelativeUri(_pck.Workbook.WorkbookUri, uriWorksheet),
+ TargetMode.Internal,
+ ExcelPackage._schemaRelationships + "/" + (isChart ? "chartsheet" : "worksheet"));
+
+ //Create the new sheet node
+ XmlElement worksheetNode = _pck.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);
+ return rel.Id;
+ }
+
+ 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] {
+ get { return 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);
+ }
+
+ /// <summary>
+ /// Moves the source worksheet to the position before the target worksheet
+ /// </summary>
+ /// <param name="sourceName">The name of the source worksheet</param>
+ /// <param name="targetName">The name of the target worksheet</param>
+ public void MoveBefore(string sourceName, string targetName) {
+ Move(sourceName, targetName, false);
+ }
+
+ /// <summary>
+ /// Moves the source worksheet to the position before the target worksheet
+ /// </summary>
+ /// <param name="sourcePositionId">The id of the source worksheet</param>
+ /// <param name="targetPositionId">The id of the target worksheet</param>
+ public void MoveBefore(int sourcePositionId, int targetPositionId) {
+ Move(sourcePositionId, targetPositionId, false);
+ }
+
+ /// <summary>
+ /// Moves the source worksheet to the position after the target worksheet
+ /// </summary>
+ /// <param name="sourceName">The name of the source worksheet</param>
+ /// <param name="targetName">The name of the target worksheet</param>
+ public void MoveAfter(string sourceName, string targetName) {
+ Move(sourceName, targetName, true);
+ }
+
+ /// <summary>
+ /// Moves the source worksheet to the position after the target worksheet
+ /// </summary>
+ /// <param name="sourcePositionId">The id of the source worksheet</param>
+ /// <param name="targetPositionId">The id of the target worksheet</param>
+ public void MoveAfter(int sourcePositionId, int targetPositionId) {
+ Move(sourcePositionId, targetPositionId, true);
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="sourceName"></param>
+ public void MoveToStart(string sourceName) {
+ var sourceSheet = this[sourceName];
+ if (sourceSheet == null) {
+ throw new(
+ string.Format(
+ "Move worksheet error: Could not find worksheet to move '{0}'",
+ sourceName));
+ }
+ Move(sourceSheet.PositionID, 1, false);
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="sourcePositionId"></param>
+ public void MoveToStart(int sourcePositionId) {
+ Move(sourcePositionId, 1, false);
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="sourceName"></param>
+ public void MoveToEnd(string sourceName) {
+ var sourceSheet = this[sourceName];
+ if (sourceSheet == null) {
+ throw new(
+ string.Format(
+ "Move worksheet error: Could not find worksheet to move '{0}'",
+ sourceName));
+ }
+ Move(sourceSheet.PositionID, _worksheets.Count, true);
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="sourcePositionId"></param>
+ public void MoveToEnd(int sourcePositionId) {
+ Move(sourcePositionId, _worksheets.Count, true);
+ }
+
+ private void Move(string sourceName, string targetName, bool placeAfter) {
+ var sourceSheet = this[sourceName];
+ if (sourceSheet == null) {
+ throw new(
+ string.Format(
+ "Move worksheet error: Could not find worksheet to move '{0}'",
+ sourceName));
+ }
+ var targetSheet = this[targetName];
+ if (targetSheet == null) {
+ throw new(
+ string.Format(
+ "Move worksheet error: Could not find worksheet to move '{0}'",
+ targetName));
+ }
+ Move(sourceSheet.PositionID, targetSheet.PositionID, placeAfter);
+ }
+
+ private void Move(int sourcePositionId, int targetPositionId, bool placeAfter) {
+ // Bugfix: if source and target are the same worksheet the following code will create a duplicate
+ // which will cause a corrupt workbook. /swmal 2014-05-10
+ if (sourcePositionId == targetPositionId) {
+ return;
+ }
+
+ lock (_worksheets) {
+ var sourceSheet = this[sourcePositionId];
+ if (sourceSheet == null) {
+ throw new(
+ string.Format(
+ "Move worksheet error: Could not find worksheet at position '{0}'",
+ sourcePositionId));
+ }
+ var targetSheet = this[targetPositionId];
+ if (targetSheet == null) {
+ throw new(
+ string.Format(
+ "Move worksheet error: Could not find worksheet at position '{0}'",
+ targetPositionId));
+ }
+ if (sourcePositionId == targetPositionId && _worksheets.Count < 2) {
+ return; //--- no reason to attempt to re-arrange a single item with itself
+ }
+
+ var index = 1;
+ var newOrder = new Dictionary<int, ExcelWorksheet>();
+ foreach (var entry in _worksheets) {
+ if (entry.Key == targetPositionId) {
+ if (!placeAfter) {
+ sourceSheet.PositionID = index;
+ newOrder.Add(index++, sourceSheet);
+ }
+
+ entry.Value.PositionID = index;
+ newOrder.Add(index++, entry.Value);
+
+ if (placeAfter) {
+ sourceSheet.PositionID = index;
+ newOrder.Add(index++, sourceSheet);
+ }
+ } else if (entry.Key == sourcePositionId) {
+ //--- do nothing
+ } else {
+ entry.Value.PositionID = index;
+ newOrder.Add(index++, entry.Value);
}
- private void GetSheetURI(ref string Name, out int sheetID, out Uri uriWorksheet, bool isChart)
- {
- Name = ValidateFixSheetName(Name);
+ }
+ _worksheets = newOrder;
- //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++;
+ MoveSheetXmlNode(sourceSheet, targetSheet, placeAfter);
+ }
+ }
- // add the new worksheet to the package
- if (isChart)
- {
- uriWorksheet = new Uri("/xl/chartsheets/chartsheet" + sheetID.ToString() + ".xml", UriKind.Relative);
- }
- else
- {
- uriWorksheet = new Uri("/xl/worksheets/sheet" + sheetID.ToString() + ".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 System.Text.RegularExpressions.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;
- }
- #endregion
-
- /// <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];
- }
- else
- {
- 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]
- {
- get
- {
- return GetByName(Name);
- }
- }
- #endregion
- 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);
- }
- #region MoveBefore and MoveAfter Methods
- /// <summary>
- /// Moves the source worksheet to the position before the target worksheet
- /// </summary>
- /// <param name="sourceName">The name of the source worksheet</param>
- /// <param name="targetName">The name of the target worksheet</param>
- public void MoveBefore(string sourceName, string targetName)
- {
- Move(sourceName, targetName, false);
- }
-
- /// <summary>
- /// Moves the source worksheet to the position before the target worksheet
- /// </summary>
- /// <param name="sourcePositionId">The id of the source worksheet</param>
- /// <param name="targetPositionId">The id of the target worksheet</param>
- public void MoveBefore(int sourcePositionId, int targetPositionId)
- {
- Move(sourcePositionId, targetPositionId, false);
- }
-
- /// <summary>
- /// Moves the source worksheet to the position after the target worksheet
- /// </summary>
- /// <param name="sourceName">The name of the source worksheet</param>
- /// <param name="targetName">The name of the target worksheet</param>
- public void MoveAfter(string sourceName, string targetName)
- {
- Move(sourceName, targetName, true);
- }
-
- /// <summary>
- /// Moves the source worksheet to the position after the target worksheet
- /// </summary>
- /// <param name="sourcePositionId">The id of the source worksheet</param>
- /// <param name="targetPositionId">The id of the target worksheet</param>
- public void MoveAfter(int sourcePositionId, int targetPositionId)
- {
- Move(sourcePositionId, targetPositionId, true);
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="sourceName"></param>
- public void MoveToStart(string sourceName)
- {
- var sourceSheet = this[sourceName];
- if (sourceSheet == null)
- {
- throw new Exception(string.Format("Move worksheet error: Could not find worksheet to move '{0}'", sourceName));
- }
- Move(sourceSheet.PositionID, 1, false);
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="sourcePositionId"></param>
- public void MoveToStart(int sourcePositionId)
- {
- Move(sourcePositionId, 1, false);
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="sourceName"></param>
- public void MoveToEnd(string sourceName)
- {
- var sourceSheet = this[sourceName];
- if (sourceSheet == null)
- {
- throw new Exception(string.Format("Move worksheet error: Could not find worksheet to move '{0}'", sourceName));
- }
- Move(sourceSheet.PositionID, _worksheets.Count, true);
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="sourcePositionId"></param>
- public void MoveToEnd(int sourcePositionId)
- {
- Move(sourcePositionId, _worksheets.Count, true);
- }
-
- private void Move(string sourceName, string targetName, bool placeAfter)
- {
- var sourceSheet = this[sourceName];
- if (sourceSheet == null)
- {
- throw new Exception(string.Format("Move worksheet error: Could not find worksheet to move '{0}'", sourceName));
- }
- var targetSheet = this[targetName];
- if (targetSheet == null)
- {
- throw new Exception(string.Format("Move worksheet error: Could not find worksheet to move '{0}'", targetName));
- }
- Move(sourceSheet.PositionID, targetSheet.PositionID, placeAfter);
- }
-
- private void Move(int sourcePositionId, int targetPositionId, bool placeAfter)
- {
- // Bugfix: if source and target are the same worksheet the following code will create a duplicate
- // which will cause a corrupt workbook. /swmal 2014-05-10
- if (sourcePositionId == targetPositionId) return;
-
- lock (_worksheets)
- {
- var sourceSheet = this[sourcePositionId];
- if (sourceSheet == null)
- {
- throw new Exception(string.Format("Move worksheet error: Could not find worksheet at position '{0}'", sourcePositionId));
- }
- var targetSheet = this[targetPositionId];
- if (targetSheet == null)
- {
- throw new Exception(string.Format("Move worksheet error: Could not find worksheet at position '{0}'", targetPositionId));
- }
- if (sourcePositionId == targetPositionId && _worksheets.Count < 2)
- {
- return; //--- no reason to attempt to re-arrange a single item with itself
- }
-
- var index = 1;
- var newOrder = new Dictionary<int, ExcelWorksheet>();
- foreach (var entry in _worksheets)
- {
- if (entry.Key == targetPositionId)
- {
- if (!placeAfter)
- {
- sourceSheet.PositionID = index;
- newOrder.Add(index++, sourceSheet);
- }
-
- entry.Value.PositionID = index;
- newOrder.Add(index++, entry.Value);
-
- if (placeAfter)
- {
- sourceSheet.PositionID = index;
- newOrder.Add(index++, sourceSheet);
- }
- }
- else if (entry.Key == sourcePositionId)
- {
- //--- do nothing
- }
- else
- {
- entry.Value.PositionID = index;
- newOrder.Add(index++, entry.Value);
- }
- }
- _worksheets = newOrder;
-
- MoveSheetXmlNode(sourceSheet, targetSheet, placeAfter);
- }
- }
-
- private void MoveSheetXmlNode(ExcelWorksheet sourceSheet, ExcelWorksheet targetSheet, bool placeAfter)
- {
- lock (TopNode.OwnerDocument)
- {
- var sourceNode = TopNode.SelectSingleNode(string.Format("d:sheet[@sheetId = '{0}']", sourceSheet.SheetID), _namespaceManager);
- var targetNode = TopNode.SelectSingleNode(string.Format("d:sheet[@sheetId = '{0}']", targetSheet.SheetID), _namespaceManager);
- if (sourceNode == null || targetNode == null)
- {
- throw new Exception("Source SheetId and Target SheetId must be valid");
- }
- if (placeAfter)
- {
- TopNode.InsertAfter(sourceNode, targetNode);
- }
- else
- {
- TopNode.InsertBefore(sourceNode, targetNode);
- }
- }
- }
-
- #endregion
- } // end class Worksheets
-}
+ private void MoveSheetXmlNode(
+ ExcelWorksheet sourceSheet,
+ ExcelWorksheet targetSheet,
+ bool placeAfter) {
+ lock (TopNode.OwnerDocument) {
+ var sourceNode = TopNode.SelectSingleNode(
+ string.Format("d:sheet[@sheetId = '{0}']", sourceSheet.SheetID),
+ _namespaceManager);
+ var targetNode = TopNode.SelectSingleNode(
+ string.Format("d:sheet[@sheetId = '{0}']", targetSheet.SheetID),
+ _namespaceManager);
+ if (sourceNode == null || targetNode == null) {
+ throw new("Source SheetId and Target SheetId must be valid");
+ }
+ if (placeAfter) {
+ TopNode.InsertAfter(sourceNode, targetNode);
+ } else {
+ TopNode.InsertBefore(sourceNode, targetNode);
+ }
+ }
+ }
+} // end class Worksheets
diff --git a/EPPlus/FormulaParsing/CalculateExtentions.cs b/EPPlus/FormulaParsing/CalculateExtentions.cs
index 69bc3ee..9cb1c28 100644
--- a/EPPlus/FormulaParsing/CalculateExtentions.cs
+++ b/EPPlus/FormulaParsing/CalculateExtentions.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,193 +13,181 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
+ * Jan Källman Added 2012-03-04
*******************************************************************************/
-using System.Threading;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
using System;
using System.Collections.Generic;
-using System.Linq;
+using System.IO;
using System.Text;
using OfficeOpenXml.FormulaParsing;
+using OfficeOpenXml.FormulaParsing.Excel.Functions;
using OfficeOpenXml.FormulaParsing.Exceptions;
-using System.IO;
-namespace OfficeOpenXml
-{
- public static class CalculationExtension
- {
- public static void Calculate(this ExcelWorkbook workbook)
- {
- Calculate(workbook, new ExcelCalculationOption(){AllowCirculareReferences=false});
- }
- public static void Calculate(this ExcelWorkbook workbook, ExcelCalculationOption options)
- {
- Init(workbook);
+using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
- 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);
+namespace OfficeOpenXml;
- // Display Calc Chain to determine why formula calculation is taking so long.
- // Uncomment the following line to display the Calc Chain.
- // DisplayCalcChain(worksheet, dc);
+public static class CalculationExtension {
+ public static void Calculate(this ExcelWorkbook workbook) {
+ Calculate(
+ workbook,
+ new() {
+ AllowCirculareReferences = false,
+ });
+ }
- var parser = worksheet.Workbook.FormulaParser;
- parser.InitNewCalc();
- CalcChain(worksheet.Workbook, parser, dc);
- }
+ public static void Calculate(this ExcelWorkbook workbook, ExcelCalculationOption options) {
+ Init(workbook);
- // I added this method in December 2019 to analyze why formula calculation was taking
- // so long during a 'Regenerate' of a Microsoft Excel table.
- private static void DisplayCalcChain(ExcelWorksheet worksheet, DependencyChain dc)
- {
- // Open Output file
- string outputFolderName = @"C:\\EPPlus";
- Directory.CreateDirectory(outputFolderName);
- DateTime invocationDateTime = DateTime.Now;
- string outputFileName = Path.Combine(outputFolderName, $"CalcChain_{worksheet.Name}_{invocationDateTime.ToString("yyyyMMdd_HHmmss_fff")}.txt");
- FileStream fileStream = new FileStream(outputFileName, FileMode.CreateNew);
- StreamWriter streamWriter = new System.IO.StreamWriter(fileStream, Encoding.UTF8, 65536);
+ var dc = DependencyChainFactory.Create(workbook, options);
+ workbook.FormulaParser.InitNewCalc();
+ CalcChain(workbook, workbook.FormulaParser, dc);
+ }
- // Display CalcChain
- foreach (int index in dc.CalcOrder)
- {
- FormulaCell formulaCell = dc.list[index];
- string calcChainValue = "";
- calcChainValue += $"Index {index}, ";
- calcChainValue += $"Worksheet '{formulaCell.ws.Name}', ";
- calcChainValue += $"Row {formulaCell.Row}, ";
- calcChainValue += $"Col {formulaCell.Column}, ";
- calcChainValue += $" Formula '{formulaCell.Formula}'";
- streamWriter.WriteLine(calcChainValue);
- }
+ public static void Calculate(this ExcelWorksheet worksheet) {
+ Calculate(worksheet, new ExcelCalculationOption());
+ }
- // Close Output file
- streamWriter.Flush();
- streamWriter.Close();
- }
+ 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);
- public static void Calculate(this ExcelRangeBase range)
- {
- Calculate(range, new ExcelCalculationOption());
- }
- 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 ExcelCalculationOption());
- }
- 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);
+ // Display Calc Chain to determine why formula calculation is taking so long.
+ // Uncomment the following line to display the Calc Chain.
+ // DisplayCalcChain(worksheet, dc);
- CalcChain(worksheet.Workbook, parser, dc);
+ var parser = worksheet.Workbook.FormulaParser;
+ parser.InitNewCalc();
+ 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 (OfficeOpenXml.FormulaParsing.Excel.Functions.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 CellStore<List<Token>>();;
- foreach (var ws in workbook.Worksheets)
- {
- if (!(ws is ExcelChartsheet))
- {
- ws._formulaTokens = new CellStore<List<Token>>();
- }
- }
- }
+ // I added this method in December 2019 to analyze why formula calculation was taking
+ // so long during a 'Regenerate' of a Microsoft Excel table.
+ private static void DisplayCalcChain(ExcelWorksheet worksheet, DependencyChain dc) {
+ // Open Output file
+ string outputFolderName = @"C:\\EPPlus";
+ Directory.CreateDirectory(outputFolderName);
+ DateTime invocationDateTime = DateTime.Now;
+ string outputFileName = Path.Combine(
+ outputFolderName,
+ $"CalcChain_{worksheet.Name}_{invocationDateTime.ToString("yyyyMMdd_HHmmss_fff")}.txt");
+ FileStream fileStream = new FileStream(outputFileName, FileMode.CreateNew);
+ StreamWriter streamWriter = new StreamWriter(fileStream, Encoding.UTF8, 65536);
- 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);
- }
- }
+ // Display CalcChain
+ foreach (int index in dc.CalcOrder) {
+ FormulaCell formulaCell = dc.list[index];
+ string calcChainValue = "";
+ calcChainValue += $"Index {index}, ";
+ calcChainValue += $"Worksheet '{formulaCell.ws.Name}', ";
+ calcChainValue += $"Row {formulaCell.Row}, ";
+ calcChainValue += $"Col {formulaCell.Column}, ";
+ calcChainValue += $" Formula '{formulaCell.Formula}'";
+ streamWriter.WriteLine(calcChainValue);
}
+
+ // Close Output file
+ streamWriter.Flush();
+ streamWriter.Close();
+ }
+
+ 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
index 9bc936f..74a0a7e 100644
--- a/EPPlus/FormulaParsing/DependencyChain/DependencyChain.cs
+++ b/EPPlus/FormulaParsing/DependencyChain/DependencyChain.cs
@@ -1,17 +1,15 @@
using System.Collections.Generic;
-namespace OfficeOpenXml.FormulaParsing
-{
- internal class DependencyChain
- {
- internal List<FormulaCell> list = new List<FormulaCell>();
- internal Dictionary<ulong, int> index = new Dictionary<ulong, int>();
- internal List<int> CalcOrder = new List<int>();
- 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);
- }
- }
-}
\ No newline at end of file
+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
index c150817..bd3bbd9 100644
--- a/EPPlus/FormulaParsing/DependencyChain/DependenyChainFactory.cs
+++ b/EPPlus/FormulaParsing/DependencyChain/DependenyChainFactory.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,354 +13,363 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
+ * Jan Källman Added 2012-03-04
*******************************************************************************/
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-using System;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using OfficeOpenXml.FormulaParsing;
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;
- }
+namespace OfficeOpenXml.FormulaParsing;
- 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==null?0:ws.SheetID, name.Index, 0);
- if (!depChain.index.ContainsKey(id))
- {
- var f = new FormulaCell() { SheetID = ws == null ? 0 : ws.SheetID, Row = name.Index, Column = 0, Formula=name.NameFormula };
- if (!string.IsNullOrEmpty(f.Formula))
- {
- f.Tokens = lexer.Tokenize(f.Formula, (ws==null ? null : 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)
- {
- f.Formula = ws._sharedFormulas[(int)fs.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._package, new ExcelAddressBase(f.Row, f.Column, f.Row, f.Column));
- }
-
- if (adr.WorkSheet == null && adr.Collide(new ExcelAddressBase(f.Row, f.Column, f.Row, f.Column))!=ExcelAddressBase.eAddressCollition.No)
- {
- throw (new CircularReferenceException(string.Format("Circular Reference in cell {0}", ExcelAddressBase.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 CellsStoreEnumerator<object>(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, adrWs, adrName;
- ExcelNamedRange name;
- ExcelAddressBase.SplitAddress(t.Value, out adrWb, out adrWs, out 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 CellsStoreEnumerator<object>(f.ws._formulas, name.Start.Row,
- name.Start.Column, name.End.Row, name.End.Column);
- goto iterateCells;
- }
- }
- else
- {
- var id = ExcelAddressBase.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;
- }
- else
- {
- if (stack.Count > 0)
- {
- //Check for circular references
- foreach (var par in stack)
- {
- if (ExcelAddressBase.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 = ExcelAddressBase.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;
- }
- else
- {
- if (stack.Count > 0)
- {
- //Check for circular references
- foreach (var par in stack)
- {
- if (ExcelAddressBase.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, ExcelAddress.GetAddress(f.Row, f.Column))));
- }
- else
- {
- f = stack.Pop();
- goto iterateCells;
- }
- }
- }
- }
- }
- }
- f.tokenIx++;
- goto iterateToken;
- }
+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 == null ? 0 : ws.SheetID, name.Index, 0);
+ if (!depChain.index.ContainsKey(id)) {
+ var f = new FormulaCell {
+ SheetID = ws == null ? 0 : ws.SheetID,
+ Row = name.Index,
+ Column = 0,
+ Formula = name.NameFormula,
+ };
+ if (!string.IsNullOrEmpty(f.Formula)) {
+ f.Tokens = lexer.Tokenize(f.Formula, (ws == null ? null : 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) {
+ f.Formula = ws._sharedFormulas[(int)fs.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._package, 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,
+ adrWs,
+ adrName;
+ ExcelNamedRange name;
+ ExcelAddressBase.SplitAddress(
+ t.Value,
+ out adrWb,
+ out adrWs,
+ out 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
index da92828..2b96a7d 100644
--- a/EPPlus/FormulaParsing/DependencyChain/FormulaCell.cs
+++ b/EPPlus/FormulaParsing/DependencyChain/FormulaCell.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan K�llman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,37 +7,42 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or 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;
- }
-}
\ No newline at end of file
+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
index 174f303..85d297a 100644
--- a/EPPlus/FormulaParsing/EpplusExcelDataProvider.cs
+++ b/EPPlus/FormulaParsing/EpplusExcelDataProvider.cs
@@ -1,480 +1,368 @@
-using System.Collections.Generic;
+using System.Collections;
+using System.Collections.Generic;
using System.Linq;
using OfficeOpenXml.FormulaParsing.ExcelUtilities;
using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-using OfficeOpenXml.Utils;
using OfficeOpenXml.Style.XmlAccess;
+using OfficeOpenXml.Utils;
-namespace OfficeOpenXml.FormulaParsing
-{
- public class EpplusExcelDataProvider : ExcelDataProvider
- {
- public class RangeInfo : IRangeInfo
- {
- internal ExcelWorksheet _ws;
- CellsStoreEnumerator<object> _values = null;
- int _fromRow, _toRow, _fromCol, _toCol;
- int _cellCount = 0;
- ExcelAddressBase _address;
- ICellInfo _cell;
+namespace OfficeOpenXml.FormulaParsing;
- public RangeInfo(ExcelWorksheet ws, int fromRow, int fromCol, int toRow, int toCol)
- {
- _ws = ws;
- _fromRow = fromRow;
- _fromCol = fromCol;
- _toRow = toRow;
- _toCol = toCol;
- _address = new ExcelAddressBase(_fromRow, _fromCol, _toRow, _toCol);
- _address._ws = ws.Name;
- _values = new CellsStoreEnumerator<object>(ws._values, _fromRow, _fromCol, _toRow, _toCol);
- _cell = new CellInfo(_ws, _values);
- }
+public class EpplusExcelDataProvider : ExcelDataProvider {
+ public class RangeInfo : IRangeInfo {
+ internal ExcelWorksheet _ws;
+ private CellsStoreEnumerator<object> _values;
+ private int _fromRow,
+ _toRow,
+ _fromCol,
+ _toCol;
+ private int _cellCount;
+ private ExcelAddressBase _address;
+ private ICellInfo _cell;
- public int GetNCells()
- {
- return ((_toRow - _fromRow) + 1) * ((_toCol - _fromCol) + 1);
- }
-
- public bool IsEmpty
- {
- get
- {
- if (_cellCount > 0)
- {
- return false;
- }
- else if (_values.Next())
- {
- _values.Reset();
- return false;
- }
- else
- {
- return true;
- }
- }
- }
- public bool IsMulti
- {
- get
- {
- if (_cellCount == 0)
- {
- if (_values.Next() && _values.Next())
- {
- _values.Reset();
- return true;
- }
- else
- {
- _values.Reset();
- return false;
- }
- }
- else if (_cellCount > 1)
- {
- return true;
- }
- return false;
- }
- }
-
- public ICellInfo Current
- {
- get { return _cell; }
- }
-
- public ExcelWorksheet Worksheet
- {
- get { return _ws; }
- }
-
- public void Dispose()
- {
- }
-
- object System.Collections.IEnumerator.Current
- {
- get
- {
- return 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;
- }
-
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return this;
- }
-
- public ExcelAddressBase Address
- {
- get { return _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);
- }
- else
- {
- return _ws.GetValue(_values.Row + rowOffset, _values.Column + colOffset);
- }
- }
- }
-
- public class CellInfo : ICellInfo
- {
- ExcelWorksheet _ws;
- CellsStoreEnumerator<object> _values;
- internal CellInfo(ExcelWorksheet ws, CellsStoreEnumerator<object> values)
- {
- _ws = ws;
- _values = values;
- }
- public string Address
- {
- get { return _values.CellAddress; }
- }
-
- public int Row
- {
- get { return _values.Row; }
- }
-
- public int Column
- {
- get { return _values.Column; }
- }
-
- public string Formula
- {
- get
- {
- return _ws.GetFormula(_values.Row, _values.Column);
- }
- }
-
- public object Value
- {
- get { return _values.Value; }
- }
-
- public double ValueDouble
- {
- get { return ConvertUtil.GetValueDouble(_values.Value, true); }
- }
- public double ValueDoubleLogical
- {
- get { return ConvertUtil.GetValueDouble(_values.Value, false); }
- }
- public bool IsHiddenRow
- {
- get
- {
- var row=_ws._values.GetValue(_values.Row, 0) as RowInternal;
- if(row != null)
- {
- return row.Hidden || row.Height==0;
- }
- else
- {
- return false;
- }
- }
- }
-
- public bool IsExcelError
- {
- get { return ExcelErrorValue.Values.IsErrorValue(_values.Value); }
- }
-
- public IList<Token> Tokens
- {
- get
- {
- return _ws._formulaTokens.GetValue(_values.Row, _values.Column);
- }
- }
-
- }
- public class NameInfo : ExcelDataProvider.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 ExcelPackage _package;
- private ExcelWorksheet _currentWorksheet;
- private RangeAddressFactory _rangeAddressFactory;
- private Dictionary<ulong, INameInfo> _names=new Dictionary<ulong,INameInfo>();
-
- public EpplusExcelDataProvider(ExcelPackage package)
- {
- _package = package;
-
- _rangeAddressFactory = new RangeAddressFactory(this);
- }
-
- public override ExcelNamedRangeCollection GetWorksheetNames(string worksheet)
- {
- var ws=_package.Workbook.Worksheets[worksheet];
- if (ws != null)
- {
- return ws.Names;
- }
- else
- {
- return null;
- }
- }
-
- public override ExcelNamedRangeCollection GetWorkbookNameValues()
- {
- return _package.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 = _package.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(_package, new ExcelAddressBase(row, column, row, column));
- }
- //SetCurrentWorksheet(addr.WorkSheet);
- var wsName = string.IsNullOrEmpty(addr.WorkSheet) ? _currentWorksheet.Name : addr.WorkSheet;
- var ws = _package.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(_package.Workbook.Names.ContainsKey(name))
- {
- nameItem = _package.Workbook.Names[name];
- }
- else
- {
- return null;
- }
- ws = null;
- }
- else
- {
- ws = _package.Workbook.Worksheets[worksheet];
- if (ws !=null && ws.Names.ContainsKey(name))
- {
- nameItem = ws.Names[name];
- }
- else if (_package.Workbook.Names.ContainsKey(name))
- {
- nameItem = _package.Workbook.Names[name];
- }
- else
- {
- return null;
- }
- }
- id = ExcelAddressBase.GetCellID(nameItem.LocalSheetId, nameItem.Index, 0);
-
- if (_names.ContainsKey(id))
- {
- return _names[id];
- }
- else
- {
- 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 = _package.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 = _package.Workbook.Worksheets[worksheet].Dimension.End;
- }
- catch{}
-
- return address;
- }
-
- private void SetCurrentWorksheet(ExcelAddressInfo addressInfo)
- {
- if (addressInfo.WorksheetIsSpecified)
- {
- _currentWorksheet = _package.Workbook.Worksheets[addressInfo.Worksheet];
- }
- else if (_currentWorksheet == null)
- {
- _currentWorksheet = _package.Workbook.Worksheets.First();
- }
- }
-
- private void SetCurrentWorksheet(string worksheetName)
- {
- if (!string.IsNullOrEmpty(worksheetName))
- {
- _currentWorksheet = _package.Workbook.Worksheets[worksheetName];
- }
- else
- {
- _currentWorksheet = _package.Workbook.Worksheets.First();
- }
-
- }
-
- public override int ExcelMaxColumns
- {
- get { return ExcelPackage.MaxColumns; }
- }
-
- public override int ExcelMaxRows
- {
- get { return 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 = _package.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 ExcelNumberFormatXml.ExcelFormatTranslator(format, -1);
- }
- return ExcelRangeBase.FormatValue(value, ft,format, ft.NetFormat);
- }
- public override List<LexicalAnalysis.Token> GetRangeFormulaTokens(string worksheetName, int row, int column)
- {
- return _package.Workbook.Worksheets[worksheetName]._formulaTokens.GetValue(row, column);
- }
-
- public override bool IsRowHidden(string worksheetName, int row)
- {
- var b = _package.Workbook.Worksheets[worksheetName].Row(row).Height == 0 ||
- _package.Workbook.Worksheets[worksheetName].Row(row).Hidden;
-
- return b;
- }
-
- public override void Reset()
- {
- _names = new Dictionary<ulong, INameInfo>(); //Reset name cache.
- }
+ 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 {
+ get { return _ws; }
+ }
+
+ public void Dispose() {}
+
+ object IEnumerator.Current {
+ get { return 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 {
+ get { return _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 ExcelWorksheet _ws;
+ private 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 ExcelPackage _package;
+ private ExcelWorksheet _currentWorksheet;
+ private RangeAddressFactory _rangeAddressFactory;
+ private Dictionary<ulong, INameInfo> _names = new();
+
+ public EpplusExcelDataProvider(ExcelPackage package) {
+ _package = package;
+
+ _rangeAddressFactory = new(this);
+ }
+
+ public override ExcelNamedRangeCollection GetWorksheetNames(string worksheet) {
+ var ws = _package.Workbook.Worksheets[worksheet];
+ if (ws != null) {
+ return ws.Names;
+ }
+ return null;
+ }
+
+ public override ExcelNamedRangeCollection GetWorkbookNameValues() {
+ return _package.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 = _package.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(_package, new(row, column, row, column));
+ }
+ //SetCurrentWorksheet(addr.WorkSheet);
+ var wsName = string.IsNullOrEmpty(addr.WorkSheet) ? _currentWorksheet.Name : addr.WorkSheet;
+ var ws = _package.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 (_package.Workbook.Names.ContainsKey(name)) {
+ nameItem = _package.Workbook.Names[name];
+ } else {
+ return null;
+ }
+ ws = null;
+ } else {
+ ws = _package.Workbook.Worksheets[worksheet];
+ if (ws != null && ws.Names.ContainsKey(name)) {
+ nameItem = ws.Names[name];
+ } else if (_package.Workbook.Names.ContainsKey(name)) {
+ nameItem = _package.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 = _package.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 = _package.Workbook.Worksheets[worksheet].Dimension.End;
+ } catch {}
+
+ return address;
+ }
+
+ private void SetCurrentWorksheet(ExcelAddressInfo addressInfo) {
+ if (addressInfo.WorksheetIsSpecified) {
+ _currentWorksheet = _package.Workbook.Worksheets[addressInfo.Worksheet];
+ } else if (_currentWorksheet == null) {
+ _currentWorksheet = _package.Workbook.Worksheets.First();
+ }
+ }
+
+ private void SetCurrentWorksheet(string worksheetName) {
+ if (!string.IsNullOrEmpty(worksheetName)) {
+ _currentWorksheet = _package.Workbook.Worksheets[worksheetName];
+ } else {
+ _currentWorksheet = _package.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 = _package.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 _package.Workbook.Worksheets[worksheetName]._formulaTokens.GetValue(row, column);
+ }
+
+ public override bool IsRowHidden(string worksheetName, int row) {
+ var b =
+ _package.Workbook.Worksheets[worksheetName].Row(row).Height == 0
+ || _package.Workbook.Worksheets[worksheetName].Row(row).Hidden;
+
+ return b;
+ }
+
+ public override void Reset() {
+ _names = new(); //Reset name cache.
+ }
}
-
\ No newline at end of file
diff --git a/EPPlus/FormulaParsing/EpplusNameValueProvider.cs b/EPPlus/FormulaParsing/EpplusNameValueProvider.cs
index a40790e..60becec 100644
--- a/EPPlus/FormulaParsing/EpplusNameValueProvider.cs
+++ b/EPPlus/FormulaParsing/EpplusNameValueProvider.cs
@@ -1,43 +1,29 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.FormulaParsing;
+namespace OfficeOpenXml.FormulaParsing;
-namespace OfficeOpenXml.FormulaParsing
-{
- public class EpplusNameValueProvider : INameValueProvider
- {
- private ExcelDataProvider _excelDataProvider;
- private ExcelNamedRangeCollection _values;
+public class EpplusNameValueProvider : INameValueProvider {
+ private ExcelDataProvider _excelDataProvider;
+ private ExcelNamedRangeCollection _values;
- public EpplusNameValueProvider(ExcelDataProvider excelDataProvider)
- {
- _excelDataProvider = excelDataProvider;
- _values = _excelDataProvider.GetWorkbookNameValues();
- }
+ 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();
- }
+ 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
index 7a6556d..3551b8a 100644
--- a/EPPlus/FormulaParsing/Excel/ExcelCellState.cs
+++ b/EPPlus/FormulaParsing/Excel/ExcelCellState.cs
@@ -13,33 +13,29 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.Excel
-{
- [Flags]
- public enum ExcelCellState
- {
- HiddenCell = 1,
- ContainsError = 2,
- IsResultOfSubtotal = 4
- }
+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
index 7375ecf..3abd514 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/ArgumentCollectionUtil.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/ArgumentCollectionUtil.cs
@@ -13,73 +13,71 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions
-{
- public class ArgumentCollectionUtil
- {
- private readonly DoubleEnumerableArgConverter _doubleEnumerableArgConverter;
- private readonly ObjectEnumerableArgConverter _objectEnumerableArgConverter;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
- public ArgumentCollectionUtil()
- : this(new DoubleEnumerableArgConverter(), new ObjectEnumerableArgConverter())
- {
+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 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<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 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>)
- {
- result = CalculateCollection((IEnumerable<FunctionArgument>)item.Value, result, action);
- }
- else
- {
- result = action(item, result);
- }
- }
- return result;
- }
+ 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>) {
+ result = CalculateCollection((IEnumerable<FunctionArgument>)item.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
index cdad8b1..d198dea 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/ArgumentParser.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/ArgumentParser.cs
@@ -1,36 +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.
+/* Copyright (C) 2011 Jan Källman
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
- * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
- *
- * All code and executables are provided "as is" with no warranty either express or implied.
- * The author accepts no liability for any 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;
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU Lesser General Public License for more details.
+*
+* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
+* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
+*
+* All code and executables are provided "as is" with no warranty either express or implied.
+* The author accepts no liability 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);
- }
+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
index 997173d..817f85a 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/ArgumentParserFactory.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/ArgumentParserFactory.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,44 +7,38 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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.ToString());
- }
- }
+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
index a8ca838..1c4d10e 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/ArgumentParsers.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/ArgumentParsers.cs
@@ -1,5 +1,4 @@
-using System;
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -8,60 +7,49 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or 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 System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
using OfficeOpenXml.FormulaParsing.Utilities;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions
-{
- public class ArgumentParsers
- {
- private static object _syncRoot = new object();
- private readonly Dictionary<DataType, ArgumentParser> _parsers = new Dictionary<DataType, ArgumentParser>();
- private readonly ArgumentParserFactory _parserFactory;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
- public ArgumentParsers()
- : this(new ArgumentParserFactory())
- {
+public class ArgumentParsers {
+ private static object _syncRoot = new();
+ 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)) {
+ lock (_syncRoot) {
+ if (!_parsers.ContainsKey(dataType)) {
+ _parsers.Add(dataType, _parserFactory.CreateArgumentParser(dataType));
}
-
- public ArgumentParsers(ArgumentParserFactory factory)
- {
- Require.That(factory).Named("argumentParserfactory").IsNotNull();
- _parserFactory = factory;
- }
-
- public ArgumentParser GetParser(DataType dataType)
- {
- if (!_parsers.ContainsKey(dataType))
- {
- lock (_syncRoot)
- {
- if (!_parsers.ContainsKey(dataType))
- {
- _parsers.Add(dataType, _parserFactory.CreateArgumentParser(dataType));
- }
- }
- }
- return _parsers[dataType];
- }
+ }
}
+ return _parsers[dataType];
+ }
}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/BoolArgumentParser.cs b/EPPlus/FormulaParsing/Excel/Functions/BoolArgumentParser.cs
index 03e6dad..f492580 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/BoolArgumentParser.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/BoolArgumentParser.cs
@@ -7,47 +7,47 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
using OfficeOpenXml.FormulaParsing.Utilities;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions
-{
- public class BoolArgumentParser : ArgumentParser
- {
- public override object Parse(object obj)
- {
- if (obj is ExcelDataProvider.IRangeInfo)
- {
- var r = ((ExcelDataProvider.IRangeInfo)obj).FirstOrDefault();
- obj = (r == null ? null : r.Value);
- }
- if (obj == null) return false;
- if (obj is bool) return (bool)obj;
- if (obj.IsNumeric()) return Convert.ToBoolean(obj);
- bool result;
- if (bool.TryParse(obj.ToString(), out result))
- {
- return result;
- }
- return result;
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
+
+public class BoolArgumentParser : ArgumentParser {
+ public override object Parse(object obj) {
+ if (obj is ExcelDataProvider.IRangeInfo) {
+ var r = ((ExcelDataProvider.IRangeInfo)obj).FirstOrDefault();
+ obj = (r == null ? null : r.Value);
}
+ if (obj == null) {
+ return false;
+ }
+ if (obj is bool) {
+ return (bool)obj;
+ }
+ if (obj.IsNumeric()) {
+ return Convert.ToBoolean(obj);
+ }
+ bool result;
+ if (bool.TryParse(obj.ToString(), out result)) {
+ return result;
+ }
+ return result;
+ }
}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/BuiltInFunctions.cs b/EPPlus/FormulaParsing/Excel/Functions/BuiltInFunctions.cs
index aa4bcb1..c7d56b2 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/BuiltInFunctions.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/BuiltInFunctions.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,188 +7,196 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for 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.Text;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
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.Information;
+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();
- }
- }
+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
index 1af20ca..e461919 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/CellStateHelper.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/CellStateHelper.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,46 +7,51 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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 == LexicalAnalysis.TokenType.Function
- && token.Value.Equals("SUBTOTAL", StringComparison.InvariantCultureIgnoreCase)
- );
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
- 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));
- }
+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
index c13d759..04eeab3 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/CollectionFlattener.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/CollectionFlattener.cs
@@ -7,50 +7,46 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-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;
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
- 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>)
- {
- FuncArgsToFlatEnumerable((IEnumerable<FunctionArgument>)arg.Value, argList, convertFunc);
- }
- else
- {
- convertFunc(arg, argList);
- }
- }
- }
+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>) {
+ FuncArgsToFlatEnumerable((IEnumerable<FunctionArgument>)arg.Value, argList, convertFunc);
+ } else {
+ convertFunc(arg, argList);
+ }
}
+ }
}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/CompileResultValidator.cs b/EPPlus/FormulaParsing/Excel/Functions/CompileResultValidator.cs
index 2582f80..e936798 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/CompileResultValidator.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/CompileResultValidator.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,40 +7,35 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no 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);
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
- private static CompileResultValidator _empty;
- public static CompileResultValidator Empty
- {
- get { return _empty ?? (_empty = new EmptyCompileResultValidator()); }
- }
- }
+public abstract class CompileResultValidator {
+ public abstract void Validate(object obj);
- internal class EmptyCompileResultValidator : CompileResultValidator
- {
- public override void Validate(object obj)
- {
- // empty validator - do nothing
- }
- }
+ 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
index 82dccbf..40f74c5 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/CompileResultValidators.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/CompileResultValidators.cs
@@ -7,49 +7,41 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no 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;
+
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions
-{
- public class CompileResultValidators
- {
- private readonly Dictionary<DataType, CompileResultValidator> _validators = new Dictionary<DataType, CompileResultValidator>();
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
- 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 class CompileResultValidators {
+ private readonly Dictionary<DataType, CompileResultValidator> _validators = new();
- public CompileResultValidator GetValidator(DataType dataType)
- {
- return CreateOrGet(dataType);
- }
+ 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
index f604253..5522539 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/DSum.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/DSum.cs
@@ -7,48 +7,43 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database
-{
- public class Dsum : DatabaseFunction
- {
- public Dsum()
- : this(new RowMatcher())
- {
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- }
+public class Dsum : DatabaseFunction {
+ public Dsum()
+ : this(new()) {}
- public Dsum(RowMatcher rowMatcher)
- : base(rowMatcher)
- {
+ 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);
- }
+ 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
index 8e74635..f686f8e 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/DatabaseFunction.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/DatabaseFunction.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,67 +7,63 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using System.Text;
using OfficeOpenXml.Utils;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database
-{
- public abstract class DatabaseFunction : ExcelFunction
- {
- protected RowMatcher RowMatcher { get; private set; }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- public DatabaseFunction()
- : this(new RowMatcher())
- {
-
- }
+public abstract class DatabaseFunction : ExcelFunction {
+ protected RowMatcher RowMatcher { get; private set; }
- public DatabaseFunction(RowMatcher rowMatcher)
- {
- RowMatcher = rowMatcher;
- }
+ public DatabaseFunction()
+ : this(new()) {}
- 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;
+ public DatabaseFunction(RowMatcher rowMatcher) {
+ RowMatcher = rowMatcher;
+ }
- var db = new ExcelDatabase(context.ExcelDataProvider, dbAddress);
- var criteria = new ExcelDatabaseCriteria(context.ExcelDataProvider, criteriaRange);
- var values = new List<double>();
+ 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;
- 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;
- }
+ 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
index a32de6c..21a890a 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/Daverage.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/Daverage.cs
@@ -7,48 +7,43 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database
-{
- public class Daverage : DatabaseFunction
- {
- public Daverage()
- : this(new RowMatcher())
- {
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- }
+public class Daverage : DatabaseFunction {
+ public Daverage()
+ : this(new()) {}
- public Daverage(RowMatcher rowMatcher)
- : base(rowMatcher)
- {
+ 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);
- }
+ 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
index a354af4..2ad31fa 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/Dcount.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/Dcount.cs
@@ -7,88 +7,73 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
using OfficeOpenXml.Utils;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database
-{
- public class Dcount : ExcelFunction
- {
- private readonly RowMatcher _rowMatcher;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- public Dcount()
- : this(new RowMatcher())
- {
-
- }
+public class Dcount : ExcelFunction {
+ private readonly RowMatcher _rowMatcher;
- public Dcount(RowMatcher rowMatcher)
- {
- _rowMatcher = rowMatcher;
- }
+ public Dcount()
+ : this(new()) {}
- 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);
+ public Dcount(RowMatcher rowMatcher) {
+ _rowMatcher = rowMatcher;
+ }
- 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);
- }
+ 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
index b90a5b5..0316950 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/DcountA.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/DcountA.cs
@@ -7,94 +7,76 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.Utils;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database
-{
- public class DcountA : DatabaseFunction
- {
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- public DcountA()
- : this(new RowMatcher())
- {
+public class DcountA : DatabaseFunction {
+ public DcountA()
+ : this(new()) {}
- }
+ public DcountA(RowMatcher rowMatcher)
+ : base(rowMatcher) {}
- 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 = 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 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()));
- }
+ 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 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
index a351374..e8aa790 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/Dget.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/Dget.cs
@@ -7,65 +7,59 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database
-{
- public class Dget : DatabaseFunction
- {
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- public Dget()
- : this(new RowMatcher())
- {
-
- }
+public class Dget : DatabaseFunction {
+ public Dget()
+ : this(new()) {}
- public Dget(RowMatcher rowMatcher)
- : base(rowMatcher)
- {
+ 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;
- 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 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);
- }
+ 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
index b817b9d..62f7d1c 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/Dmax.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/Dmax.cs
@@ -7,48 +7,43 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database
-{
- public class Dmax : DatabaseFunction
- {
- public Dmax()
- : this(new RowMatcher())
- {
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- }
+public class Dmax : DatabaseFunction {
+ public Dmax()
+ : this(new()) {}
- public Dmax(RowMatcher rowMatcher)
- : base(rowMatcher)
- {
+ 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);
- }
+ 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
index 53b983b..8203884 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/Dmin.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/Dmin.cs
@@ -7,48 +7,43 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database
-{
- public class Dmin : DatabaseFunction
- {
- public Dmin()
- : this(new RowMatcher())
- {
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- }
+public class Dmin : DatabaseFunction {
+ public Dmin()
+ : this(new()) {}
- public Dmin(RowMatcher rowMatcher)
- : base(rowMatcher)
- {
+ 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);
- }
+ 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
index bd6b09c..d961b82 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/Dvar.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/Dvar.cs
@@ -7,50 +7,44 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database
-{
- public class Dvar : DatabaseFunction
- {
- public Dvar()
- : this(new RowMatcher())
- {
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- }
+public class Dvar : DatabaseFunction {
+ public Dvar()
+ : this(new()) {}
- public Dvar(RowMatcher rowMatcher)
- : base(rowMatcher)
- {
+ 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);
- }
+ 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
index 8607f6e..7c43e88 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/Dvarp.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/Dvarp.cs
@@ -7,50 +7,44 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database
-{
- public class Dvarp : DatabaseFunction
- {
- public Dvarp()
- : this(new RowMatcher())
- {
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- }
+public class Dvarp : DatabaseFunction {
+ public Dvarp()
+ : this(new()) {}
- public Dvarp(RowMatcher rowMatcher)
- : base(rowMatcher)
- {
+ 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);
- }
+ 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
index 231d870..90e3f97 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabase.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabase.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,90 +7,75 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
-using System.Text;
-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 List<ExcelDatabaseField>();
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- public IEnumerable<ExcelDatabaseField> Fields
- {
- get { return _fields; }
- }
+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 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();
- }
+ public IEnumerable<ExcelDatabaseField> Fields => _fields;
- 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 ExcelDatabaseField(name, fieldIx++));
- }
- }
+ 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 object GetCellValue(int row, int col)
- {
- return _dataProvider.GetRangeValue(_worksheet, row, col);
- }
-
- public bool HasMoreRows
- {
- get { return _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;
- }
+ 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
index 522e810..f8b8846 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteria.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteria.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,77 +7,62 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.FormulaParsing.Utilities;
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 Dictionary<ExcelDatabaseCriteriaField, object>();
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- 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();
+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);
}
-
- 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
- {
- get { return _criterias; }
- }
+ }
}
+ }
+
+ 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
index beb77d0..eec151c 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteriaField.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseCriteriaField.cs
@@ -7,51 +7,41 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database
-{
- public class ExcelDatabaseCriteriaField
- {
- public ExcelDatabaseCriteriaField(string fieldName)
- {
- FieldName = fieldName;
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- public ExcelDatabaseCriteriaField(int fieldIndex)
- {
- FieldIndex = fieldIndex;
- }
+public class ExcelDatabaseCriteriaField {
+ public ExcelDatabaseCriteriaField(string fieldName) {
+ FieldName = fieldName;
+ }
- public override string ToString()
- {
- if (!string.IsNullOrEmpty(FieldName))
- {
- return FieldName;
- }
- return base.ToString();
- }
+ public ExcelDatabaseCriteriaField(int fieldIndex) {
+ FieldIndex = fieldIndex;
+ }
- public string FieldName { get; private set; }
-
- public int? FieldIndex { get; private set; }
+ 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
index 9687b3c..9578486 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseField.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseField.cs
@@ -7,38 +7,31 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database
-{
- public class ExcelDatabaseField
- {
-
- public string FieldName { get; private set; }
- public int ColIndex { get; private set; }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- public ExcelDatabaseField(string fieldName, int colIndex)
- {
- FieldName = fieldName;
- ColIndex = colIndex;
- }
- }
+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
index 0a216db..7b694cf 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseRow.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/ExcelDatabaseRow.cs
@@ -7,54 +7,43 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.FormulaParsing.Excel.Operators;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database
-{
- public class ExcelDatabaseRow
- {
- private Dictionary<int, string> _fieldIndexes = new Dictionary<int, string>();
- private readonly Dictionary<string, object> _items = new Dictionary<string, object>();
- private int _colIndex = 1;
- public object this[string field]
- {
- get { return _items[field]; }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- set
- {
- _items[field] = value;
- _fieldIndexes[_colIndex++] = field;
- }
- }
+public class ExcelDatabaseRow {
+ private Dictionary<int, string> _fieldIndexes = new();
+ private readonly Dictionary<string, object> _items = new();
+ private int _colIndex = 1;
- public object this[int index]
- {
- get
- {
- var field = _fieldIndexes[index];
- return _items[field];
- }
- }
-
-
+ 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
index e0b32d7..3493872 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Database/RowMatcher.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Database/RowMatcher.cs
@@ -7,84 +7,76 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+
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;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Database;
- public RowMatcher()
- : this(new WildCardValueMatcher(), new NumericExpressionEvaluator())
- {
-
- }
+public class RowMatcher {
+ private readonly WildCardValueMatcher _wildCardValueMatcher;
+ private readonly NumericExpressionEvaluator _numericExpressionEvaluator;
- public RowMatcher(WildCardValueMatcher wildCardValueMatcher, NumericExpressionEvaluator numericExpressionEvaluator)
- {
- _wildCardValueMatcher = wildCardValueMatcher;
- _numericExpressionEvaluator = numericExpressionEvaluator;
- }
+ public RowMatcher()
+ : this(new(), new()) {}
- 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;
- }
+ public RowMatcher(
+ WildCardValueMatcher wildCardValueMatcher,
+ NumericExpressionEvaluator numericExpressionEvaluator) {
+ _wildCardValueMatcher = wildCardValueMatcher;
+ _numericExpressionEvaluator = numericExpressionEvaluator;
+ }
- 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;
+ 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
index aa5233e..e2e8ad9 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Date.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Date.cs
@@ -7,42 +7,39 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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((double)(day - 1));
- return CreateResult(date.ToOADate(), DataType.Date);
- }
- }
+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
index 1756686..fbac43c 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/DateParsingFunction.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/DateParsingFunction.cs
@@ -1,26 +1,17 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
-using System.Text;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime
-{
- public abstract class DateParsingFunction : ExcelFunction
- {
- protected System.DateTime ParseDate(IEnumerable<FunctionArgument> arguments, object dateObj)
- {
- System.DateTime date = System.DateTime.MinValue;
- 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;
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
+
+public abstract class DateParsingFunction : ExcelFunction {
+ protected System.DateTime ParseDate(IEnumerable<FunctionArgument> arguments, object dateObj) {
+ System.DateTime date = System.DateTime.MinValue;
+ 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
index 3310d64..74860bf 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/DateStringParser.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/DateStringParser.cs
@@ -7,29 +7,22 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime
-{
- public class DateStringParser
- {
- }
-}
+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
index 2840c49..0b5f372 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/DateValue.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/DateValue.cs
@@ -1,32 +1,26 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Text;
+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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
- internal CompileResult Execute(string dateString)
- {
- System.DateTime result;
- System.DateTime.TryParse(dateString, out result);
- return result != System.DateTime.MinValue ?
- CreateResult(result.ToOADate(), DataType.Date) :
- CreateResult(ExcelErrorValue.Create(eErrorType.Value), DataType.ExcelError);
- }
- }
+/// <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 result;
+ System.DateTime.TryParse(dateString, out 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
index 48bb47a..dc4d39c 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Day.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Day.cs
@@ -7,38 +7,35 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
- return CreateResult(date.Day, DataType.Integer);
- }
- }
+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
index 9b3b9ac..20810ef 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Days360.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Days360.cs
@@ -1,81 +1,77 @@
-using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using System.Text;
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);
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
- var calcType = Days360Calctype.Us;
- if (arguments.Count() > 2)
- {
- var european = ArgToBool(arguments, 2);
- if(european) calcType = Days360Calctype.European;
- }
+public class Days360 : ExcelFunction {
+ private enum Days360Calctype {
+ European,
+ Us,
+ }
- var startYear = dt1.Year;
- var startMonth = dt1.Month;
- var startDay = dt1.Day;
- var endYear = dt2.Year;
- var endMonth = dt2.Month;
- var endDay = dt2.Day;
+ 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);
- 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);
- }
-
- private int GetNumWholeMonths(System.DateTime dt1, System.DateTime dt2)
- {
- var startDate = new System.DateTime(dt1.Year, dt1.Month, 1).AddMonths(1);
- var endDate = new System.DateTime(dt2.Year, dt2.Month, 1);
- return ((endDate.Year - startDate.Year)*12) + (endDate.Month - startDate.Month);
- }
+ 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);
+ }
+
+ private int GetNumWholeMonths(System.DateTime dt1, System.DateTime dt2) {
+ var startDate = new System.DateTime(dt1.Year, dt1.Month, 1).AddMonths(1);
+ var endDate = new System.DateTime(dt2.Year, dt2.Month, 1);
+ return ((endDate.Year - startDate.Year) * 12) + (endDate.Month - startDate.Month);
+ }
}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Edate.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Edate.cs
index ad6dae2..7a1af10 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Edate.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Edate.cs
@@ -1,21 +1,17 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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);
- }
- }
+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
index f056a9e..33454da 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Eomonth.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Eomonth.cs
@@ -1,20 +1,18 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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);
- }
- }
+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
index 0215aa3..5509889 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Hour.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Hour.cs
@@ -1,5 +1,4 @@
-
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -8,39 +7,35 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using System.Globalization;
-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);
- }
+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
index f42483e..45b838b 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/IsoWeekNum.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/IsoWeekNum.cs
@@ -1,50 +1,47 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
- /// <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;
- }
+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
index 4ca338d..57426d0 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Minute.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Minute.cs
@@ -7,46 +7,41 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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 = 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.Minute, DataType.Integer);
- }
+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 = 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.Minute, DataType.Integer);
+ }
}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Month.cs b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Month.cs
index 1118b0a..c6aaba4 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Month.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Month.cs
@@ -7,37 +7,35 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 762cab3..93e419e 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Networkdays.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Networkdays.cs
@@ -1,28 +1,24 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
-using System.Text;
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 CompileResult(result.NumberOfWorkdays, DataType.Integer);
- }
+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
index ac1c80c..e3e1891 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/NetworkdaysIntl.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/NetworkdaysIntl.cs
@@ -1,46 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
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 WorkdayCalculator(weekdayFactory.Create(holidayArg.ToString()));
- }
- else if (IsNumeric(holidayArg))
- {
- var holidayCode = Convert.ToInt32(holidayArg);
- calculator = new WorkdayCalculator(weekdayFactory.Create(holidayCode));
- }
- else
- {
- return new CompileResult(eErrorType.Value);
- }
- }
- var result = calculator.CalculateNumberOfWorkdays(startDate, endDate);
- if (functionArguments.Length > 3)
- {
- result = calculator.ReduceWorkdaysWithHolidays(result, functionArguments[3]);
- }
- return new CompileResult(result.NumberOfWorkdays, DataType.Integer);
- }
+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
index b93048e..b4bd17d 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Now.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Now.cs
@@ -7,34 +7,31 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 137ea1d..443e913 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Second.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Second.cs
@@ -7,37 +7,35 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index c781317..fb1144e 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Time.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Time.cs
@@ -7,58 +7,48 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime
-{
- public class Time : TimeBaseFunction
- {
- public Time()
- : base()
- {
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
- }
-
- 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 CompileResult(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);
- }
+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
index 59382d3..879fc64 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/TimeBaseFunction.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/TimeBaseFunction.cs
@@ -7,85 +7,62 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime
-{
- public abstract class TimeBaseFunction : ExcelFunction
- {
- public TimeBaseFunction()
- {
- TimeStringParser = new TimeStringParser();
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
- protected TimeStringParser TimeStringParser
- {
- get;
- private set;
- }
+public abstract class TimeBaseFunction : ExcelFunction {
+ public TimeBaseFunction() {
+ TimeStringParser = new();
+ }
- protected double SerialNumber
- {
- get;
- private set;
- }
+ protected TimeStringParser TimeStringParser { get; private set; }
- public void ValidateAndInitSerialNumber(IEnumerable<FunctionArgument> arguments)
- {
- ValidateArguments(arguments, 1);
- SerialNumber = (double)ArgToDecimal(arguments, 0);
- }
+ protected double SerialNumber { get; private set; }
- protected double SecondsInADay
- {
- get{ return 24 * 60 * 60; }
- }
+ public void ValidateAndInitSerialNumber(IEnumerable<FunctionArgument> arguments) {
+ ValidateArguments(arguments, 1);
+ SerialNumber = ArgToDecimal(arguments, 0);
+ }
- protected double GetTimeSerialNumber(double seconds)
- {
- return seconds / SecondsInADay;
- }
+ protected double SecondsInADay => 24 * 60 * 60;
- protected double GetSeconds(double serialNumber)
- {
- return serialNumber * SecondsInADay;
- }
+ protected double GetTimeSerialNumber(double seconds) {
+ return seconds / SecondsInADay;
+ }
- protected double GetHour(double serialNumber)
- {
- var seconds = GetSeconds(serialNumber);
- return (int)seconds / (60 * 60);
- }
+ protected double GetSeconds(double serialNumber) {
+ return serialNumber * SecondsInADay;
+ }
- protected double GetMinute(double serialNumber)
- {
- var seconds = GetSeconds(serialNumber);
- seconds -= GetHour(serialNumber) * 60 * 60;
- return (seconds - (seconds % 60)) / 60;
- }
+ protected double GetHour(double serialNumber) {
+ var seconds = GetSeconds(serialNumber);
+ return (int)seconds / (60 * 60);
+ }
- protected double GetSecond(double serialNumber)
- {
- return GetSeconds(serialNumber) % 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
index f9c213d..4a76f6f 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/TimeStringParser.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/TimeStringParser.cs
@@ -7,122 +7,111 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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)$";
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
- private double GetSerialNumber(int hour, int minute, int second)
- {
- var secondsInADay = 24d * 60d * 60d;
- return ((double)hour * 60 * 60 + (double)minute * 60 + (double)second) / secondsInADay;
- }
+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 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);
- }
- }
+ private double GetSerialNumber(int hour, int minute, int second) {
+ var secondsInADay = 24d * 60d * 60d;
+ return ((double)hour * 60 * 60 + (double)minute * 60 + second) / secondsInADay;
+ }
- 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);
- }
- System.DateTime dateTime;
- if (System.DateTime.TryParse(input, out dateTime))
- {
- return GetSerialNumber(dateTime.Hour, dateTime.Minute, dateTime.Second);
- }
- return -1;
- }
-
- private double Parse12HourTimeString(string input)
- {
- string dayPart = string.Empty;
- dayPart = input.Substring(input.Length - 2, 2);
- int hour;
- int minute;
- int second;
- GetValuesFromString(input, out hour, out minute, out second);
- if (dayPart == "PM") hour += 12;
- ValidateValues(hour, minute, second);
- return GetSerialNumber(hour, minute, second);
- }
-
- private double Parse24HourTimeString(string input)
- {
- int hour;
- int minute;
- int second;
- GetValuesFromString(input, out hour, out minute, out 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);
- }
- }
+ 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);
+ }
+ System.DateTime dateTime;
+ if (System.DateTime.TryParse(input, out dateTime)) {
+ return GetSerialNumber(dateTime.Hour, dateTime.Minute, dateTime.Second);
+ }
+ return -1;
+ }
+
+ private double Parse12HourTimeString(string input) {
+ string dayPart = string.Empty;
+ dayPart = input.Substring(input.Length - 2, 2);
+ int hour;
+ int minute;
+ int second;
+ GetValuesFromString(input, out hour, out minute, out second);
+ if (dayPart == "PM") {
+ hour += 12;
+ }
+ ValidateValues(hour, minute, second);
+ return GetSerialNumber(hour, minute, second);
+ }
+
+ private double Parse24HourTimeString(string input) {
+ int hour;
+ int minute;
+ int second;
+ GetValuesFromString(input, out hour, out minute, out 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
index 89a6017..ac259b8 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/TimeValue.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/TimeValue.cs
@@ -1,36 +1,32 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
- internal CompileResult Execute(string dateString)
- {
- System.DateTime result;
- System.DateTime.TryParse(dateString, out result);
- return result != System.DateTime.MinValue ?
- CreateResult(GetTimeValue(result), DataType.Date) :
- CreateResult(ExcelErrorValue.Create(eErrorType.Value), DataType.ExcelError);
- }
+/// <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);
+ }
- private double GetTimeValue(System.DateTime result)
- {
- return (int)result.TimeOfDay.TotalSeconds == 0 ? 0d : result.TimeOfDay.TotalSeconds/ (3600 * 24);
- }
- }
+ internal CompileResult Execute(string dateString) {
+ System.DateTime result;
+ System.DateTime.TryParse(dateString, out 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
index 1727e51..e6ff48f 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Today.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Today.cs
@@ -7,34 +7,31 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index f9ba7d4..533ce2a 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Weekday.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Weekday.cs
@@ -7,58 +7,56 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
- private static List<int> _oneBasedStartOnSunday = new List<int> { 1, 2, 3, 4, 5, 6, 7 };
- private static List<int> _oneBasedStartOnMonday = new List<int> { 7, 1, 2, 3, 4, 5, 6 };
- private static List<int> _zeroBasedStartOnSunday = new List<int> { 6, 0, 1, 2, 3, 4, 5 };
+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 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);
- }
- }
+ private static List<int> _oneBasedStartOnSunday = new() { 1, 2, 3, 4, 5, 6, 7 };
+ private static List<int> _oneBasedStartOnMonday = new() { 7, 1, 2, 3, 4, 5, 6 };
+ private static 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
index 84b6629..f5c1b05 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Weeknum.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Weeknum.cs
@@ -2,62 +2,57 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime
-{
- public class Weeknum : ExcelFunction
- {
- public override ExpressionGraph.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);
- }
-
-
+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
index 429191e..947bc3e 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workday.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workday.cs
@@ -1,88 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
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;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
- // 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;
- }
+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
index 9f89b3e..38bd021 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/AdditionalHolidayDays.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/AdditionalHolidayDays.cs
@@ -1,46 +1,41 @@
-using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using OfficeOpenXml.Utils;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays
-{
- public class AdditionalHolidayDays
- {
- private readonly FunctionArgument _holidayArg;
- private readonly List<System.DateTime> _holidayDates = new List<System.DateTime>();
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays;
- public AdditionalHolidayDays(FunctionArgument holidayArg)
- {
- _holidayArg = holidayArg;
- Initialize();
- }
+public class AdditionalHolidayDays {
+ private readonly FunctionArgument _holidayArg;
+ private readonly List<System.DateTime> _holidayDates = new();
- public IEnumerable<System.DateTime> AdditionalDates => _holidayDates;
+ public AdditionalHolidayDays(FunctionArgument holidayArg) {
+ _holidayArg = holidayArg;
+ Initialize();
+ }
- 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)));
- }
- }
+ 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
index de18cd7..3e866b0 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdays.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdays.cs
@@ -1,87 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using OfficeOpenXml.Utils;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays
-{
- public class HolidayWeekdays
- {
- private readonly List<DayOfWeek> _holidayDays = new List<DayOfWeek>();
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays;
- public HolidayWeekdays()
- :this(DayOfWeek.Saturday, DayOfWeek.Sunday)
- {
-
- }
+public class HolidayWeekdays {
+ private readonly List<DayOfWeek> _holidayDays = new();
- public int NumberOfWorkdaysPerWeek => 7 - _holidayDays.Count;
+ public HolidayWeekdays()
+ : this(DayOfWeek.Saturday, DayOfWeek.Sunday) {}
- public HolidayWeekdays(params DayOfWeek[] holidayDays)
- {
- foreach (var dayOfWeek in holidayDays)
- {
- _holidayDays.Add(dayOfWeek);
- }
- }
+ public int NumberOfWorkdaysPerWeek => 7 - _holidayDays.Count;
- 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;
- }
+ 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
index 2a94e0f..cf17962 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdaysFactory.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/HolidayWeekdaysFactory.cs
@@ -1,76 +1,67 @@
-using System;
+using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays
-{
- public class HolidayWeekdaysFactory
- {
- private readonly DayOfWeek[] _dayOfWeekArray = new DayOfWeek[]
- {
- DayOfWeek.Monday,
- DayOfWeek.Tuesday,
- DayOfWeek.Wednesday,
- DayOfWeek.Thursday,
- DayOfWeek.Friday,
- DayOfWeek.Saturday,
- DayOfWeek.Sunday
- };
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays;
- public HolidayWeekdays Create(string weekdays)
- {
- if(string.IsNullOrEmpty(weekdays) || weekdays.Length != 7)
- throw new ArgumentException("Illegal weekday string", nameof(Weekday));
+public class HolidayWeekdaysFactory {
+ private readonly DayOfWeek[] _dayOfWeekArray = {
+ DayOfWeek.Monday,
+ DayOfWeek.Tuesday,
+ DayOfWeek.Wednesday,
+ DayOfWeek.Thursday,
+ DayOfWeek.Friday,
+ DayOfWeek.Saturday,
+ DayOfWeek.Sunday,
+ };
- 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 HolidayWeekdays(retVal.ToArray());
- }
-
- public HolidayWeekdays Create(int code)
- {
- switch (code)
- {
- case 1:
- return new HolidayWeekdays(DayOfWeek.Saturday, DayOfWeek.Sunday);
- case 2:
- return new HolidayWeekdays(DayOfWeek.Sunday, DayOfWeek.Monday);
- case 3:
- return new HolidayWeekdays(DayOfWeek.Monday, DayOfWeek.Tuesday);
- case 4:
- return new HolidayWeekdays(DayOfWeek.Tuesday, DayOfWeek.Wednesday);
- case 5:
- return new HolidayWeekdays(DayOfWeek.Wednesday, DayOfWeek.Thursday);
- case 6:
- return new HolidayWeekdays(DayOfWeek.Thursday, DayOfWeek.Friday);
- case 7:
- return new HolidayWeekdays(DayOfWeek.Friday, DayOfWeek.Saturday);
- case 11:
- return new HolidayWeekdays(DayOfWeek.Sunday);
- case 12:
- return new HolidayWeekdays(DayOfWeek.Monday);
- case 13:
- return new HolidayWeekdays(DayOfWeek.Tuesday);
- case 14:
- return new HolidayWeekdays(DayOfWeek.Wednesday);
- case 15:
- return new HolidayWeekdays(DayOfWeek.Thursday);
- case 16:
- return new HolidayWeekdays(DayOfWeek.Friday);
- case 17:
- return new HolidayWeekdays(DayOfWeek.Saturday);
- default:
- throw new ArgumentException("Invalid code supplied to HolidayWeekdaysFactory: " + code);
- }
- }
+ 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
index ee10b65..c0f56b4 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculationDirection.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculationDirection.cs
@@ -1,14 +1,6 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Text;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays
-{
- public enum WorkdayCalculationDirection
- {
- Forward = 1,
- Backward = -1
- }
+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
index cbff556..e09e7ba 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculator.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculator.cs
@@ -1,128 +1,123 @@
-using System;
-using System.Collections.Generic;
using System.Linq;
-using System.Security.Cryptography;
-using System.Text;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays;
-using OfficeOpenXml.Utils;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays
-{
- public class WorkdayCalculator
- {
- private readonly HolidayWeekdays _holidayWeekdays;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays;
- public WorkdayCalculator()
- : this(new HolidayWeekdays())
- {}
+public class WorkdayCalculator {
+ private readonly HolidayWeekdays _holidayWeekdays;
- public WorkdayCalculator(HolidayWeekdays holidayWeekdays)
- {
- _holidayWeekdays = holidayWeekdays;
- }
+ public WorkdayCalculator()
+ : this(new()) {}
- 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 WorkdayCalculatorResult(workdaysCounted, startDate, endDate, calcDirection);
- }
+ public WorkdayCalculator(HolidayWeekdays holidayWeekdays) {
+ _holidayWeekdays = holidayWeekdays;
+ }
- 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 WorkdayCalculatorResult(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 WorkdayCalculatorResult(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 WorkdayCalculatorResult(workdaysCounted, calculatedResult.StartDate, endDate, direction);
- }
+ 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
index 420c5d8..a61a05e 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculatorResult.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Workdays/WorkdayCalculatorResult.cs
@@ -1,26 +1,22 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Cryptography.X509Certificates;
-using System.Text;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime.Workdays;
-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 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 int NumberOfWorkdays { get; }
- public System.DateTime StartDate { get; }
+ public System.DateTime StartDate { get; }
- public System.DateTime EndDate { get; }
- public WorkdayCalculationDirection Direction { get; set; }
- }
+ 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
index 4bdb565..103c487 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Year.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Year.cs
@@ -7,47 +7,41 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
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);
- }
+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
index fcf39b6..440c46a 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DateTime/Yearfrac.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DateTime/Yearfrac.cs
@@ -1,89 +1,85 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using System.Text;
-using OfficeOpenXml.FormulaParsing.Exceptions;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime
-{
- public class Yearfrac : ExcelFunction
+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
{
- 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 FunctionArgument(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/(double) nYears;
- }
+ 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
index 5ebf850..208cfa2 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DecimalCompileResultValidator.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DecimalCompileResultValidator.cs
@@ -7,39 +7,32 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+
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);
- }
- }
+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
index f614909..d987c85 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DoubleArgumentParser.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DoubleArgumentParser.cs
@@ -7,53 +7,49 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using System.Globalization;
-using OfficeOpenXml.FormulaParsing.Utilities;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using util=OfficeOpenXml.Utils;
-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)
- {
- var r=((ExcelDataProvider.IRangeInfo)obj).FirstOrDefault();
- return r == null ? 0 : r.ValueDouble;
- }
- if (obj is double) return obj;
- if (obj.IsNumeric()) return util.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));
- }
- }
+using System.Globalization;
+using System.Linq;
+using OfficeOpenXml.FormulaParsing.Exceptions;
+using OfficeOpenXml.FormulaParsing.Utilities;
+using util = OfficeOpenXml.Utils;
+
+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) {
+ var r = ((ExcelDataProvider.IRangeInfo)obj).FirstOrDefault();
+ return r == null ? 0 : r.ValueDouble;
}
+ if (obj is double) {
+ return obj;
+ }
+ if (obj.IsNumeric()) {
+ return util.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
index 5d21b0c..2ff7a2c 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/DoubleEnumerableArgConverter.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/DoubleEnumerableArgConverter.cs
@@ -7,83 +7,78 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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));
- }
- }
- });
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
- 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)
- {
- foreach (var cell in (ExcelDataProvider.IRangeInfo)arg.Value)
- {
- 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);
- }
- }
- });
- }
- }
+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) {
+ foreach (var cell in (ExcelDataProvider.IRangeInfo)arg.Value) {
+ 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
index bfc73ee..fb950a8 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/ErrorHandlingFunction.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/ErrorHandlingFunction.cs
@@ -7,54 +7,42 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
+
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-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
- {
- get
- {
- return true;
- }
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
- /// <summary>
- /// Method that should be implemented to handle the error.
- /// </summary>
- /// <param name="errorCode"></param>
- /// <returns></returns>
- public abstract CompileResult HandleError(string errorCode);
- }
+/// <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
index 01e3568..ad03cae 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/ExcelFunction.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/ExcelFunction.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,447 +7,433 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using System.Globalization;
-using OfficeOpenXml.FormulaParsing.Utilities;
using OfficeOpenXml.FormulaParsing.Exceptions;
-using System.Collections;
+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 ArgumentCollectionUtil(), new ArgumentParsers(), new CompileResultValidators())
- {
+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;
- }
+ 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;
+ 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>
+ ///
+ /// </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) { }
+ /// <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
- {
- get
- {
- return false;
- }
- }
+ public virtual bool IsLookupFuction => false;
- public virtual bool IsErrorHandlingFunction
- {
- get
- {
- return 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 = ((IEnumerable<FunctionArgument>)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);
- }
- else
- {
- return arg==null?null: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);
- }
+ public virtual bool IsErrorHandlingFunction => false;
- /// <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>
+ /// Used for some Lookupfunctions to indicate that function arguments should
+ /// not be compiled before the function is called.
+ /// </summary>
+ public bool SkipArgumentEvaluation { get; set; }
- /// <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 CompileResult(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);
- }
+ 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 == null ? null : 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
index 7e22905..7dec4b3 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/FunctionArgument.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/FunctionArgument.cs
@@ -7,92 +7,63 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions
-{
- public class FunctionArgument
- {
- public FunctionArgument(object val)
- {
- Value = val;
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
- private ExcelCellState _excelCellState;
+public class FunctionArgument {
+ public FunctionArgument(object val) {
+ Value = val;
+ }
- public void SetExcelStateFlag(ExcelCellState state)
- {
- _excelCellState |= state;
- }
+ private ExcelCellState _excelCellState;
- public bool ExcelStateFlagIsSet(ExcelCellState state)
- {
- return (_excelCellState & state) != 0;
- }
+ public void SetExcelStateFlag(ExcelCellState state) {
+ _excelCellState |= state;
+ }
- public object Value { get; private set; }
+ public bool ExcelStateFlagIsSet(ExcelCellState state) {
+ return (_excelCellState & state) != 0;
+ }
- public Type Type
- {
- get { return Value != null ? Value.GetType() : null; }
- }
+ public object Value { get; private set; }
- public bool IsExcelRange
- {
- get { return Value != null && Value is EpplusExcelDataProvider.IRangeInfo; }
- }
+ public Type Type => Value != null ? Value.GetType() : null;
- public bool ValueIsExcelError
- {
- get { return ExcelErrorValue.Values.IsErrorValue(Value); }
- }
+ public bool IsExcelRange => Value != null && Value is ExcelDataProvider.IRangeInfo;
- public ExcelErrorValue ValueAsExcelErrorValue
- {
- get { return ExcelErrorValue.Parse(Value.ToString()); }
- }
+ public bool ValueIsExcelError => ExcelErrorValue.Values.IsErrorValue(Value);
- public EpplusExcelDataProvider.IRangeInfo ValueAsRangeInfo
- {
- get { return Value as EpplusExcelDataProvider.IRangeInfo; }
- }
- public object ValueFirst
- {
- get
- {
- if (Value is ExcelDataProvider.INameInfo)
- {
- Value = ((ExcelDataProvider.INameInfo)Value).Value;
- }
- var v = Value as ExcelDataProvider.IRangeInfo;
- if (v==null)
- {
- return Value;
- }
- else
- {
- return v.GetValue(v.Address._fromRow, v.Address._fromCol);
- }
- }
- }
+ public ExcelErrorValue ValueAsExcelErrorValue => ExcelErrorValue.Parse(Value.ToString());
+ public ExcelDataProvider.IRangeInfo ValueAsRangeInfo => Value as ExcelDataProvider.IRangeInfo;
+
+ public object ValueFirst {
+ get {
+ if (Value is ExcelDataProvider.INameInfo) {
+ Value = ((ExcelDataProvider.INameInfo)Value).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
index 514cc65..012a7c7 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/FunctionNameProvider.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/FunctionNameProvider.cs
@@ -7,44 +7,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions
-{
- public class FunctionNameProvider : IFunctionNameProvider
- {
- private FunctionNameProvider()
- {
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
- }
+public class FunctionNameProvider : IFunctionNameProvider {
+ private FunctionNameProvider() {}
- public static FunctionNameProvider Empty
- {
- get { return new FunctionNameProvider(); }
- }
+ public static FunctionNameProvider Empty => new();
- public virtual bool IsFunctionName(string name)
- {
- return false;
- }
- }
+ public virtual bool IsFunctionName(string name) {
+ return false;
+ }
}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/FunctionRepository.cs b/EPPlus/FormulaParsing/Excel/Functions/FunctionRepository.cs
index 818cc56..42d7f0b 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/FunctionRepository.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/FunctionRepository.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,138 +7,114 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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 System.Linq;
-using System.Text;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
using OfficeOpenXml.FormulaParsing.Utilities;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-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()
- : base()
- {
- }
- //
- // 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)
- {
- }
+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 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];
}
+ }
- /// <summary>
- /// This class provides methods for accessing/modifying VBA Functions.
- /// </summary>
- public class FunctionRepository : IFunctionNameProvider
- {
- private Dictionary<string, ExcelFunction> _functions = new Dictionary<string, ExcelFunction>(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
- {
- get { return _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;
- }
+ 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
index ff6d42b..522451a 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/FunctionsModule.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/FunctionsModule.cs
@@ -7,38 +7,31 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions
-{
- /// <summary>
- /// Base class
- /// </summary>
- public abstract class FunctionsModule : IFunctionModule
- {
- private readonly Dictionary<string, ExcelFunction> _functions = new Dictionary<string, ExcelFunction>();
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
- public IDictionary<string, ExcelFunction> Functions
- {
- get { return _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
index 2c9f745..81b3cc8 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/HiddenValuesHandlingFunction.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/HiddenValuesHandlingFunction.cs
@@ -7,74 +7,64 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-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;
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions;
- protected override IEnumerable<double> ArgsToDoubleEnumerable(IEnumerable<FunctionArgument> arguments, ParsingContext context)
- {
- return ArgsToDoubleEnumerable(arguments, context, true);
- }
+/// <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 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 override IEnumerable<double> ArgsToDoubleEnumerable(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ return ArgsToDoubleEnumerable(arguments, context, true);
+ }
- 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;
- }
-
+ 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
index 9e3762a..6ab248f 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/IFunctionModule.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/IFunctionModule.cs
@@ -7,30 +7,26 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions
-{
- public interface IFunctionModule
- {
- IDictionary<string, ExcelFunction> Functions { get; }
- }
+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
index b5a9940..5722862 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/IFunctionNameProvider.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/IFunctionNameProvider.cs
@@ -7,30 +7,24 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions
-{
- public interface IFunctionNameProvider
- {
- bool IsFunctionName(string name);
- }
+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
index f361ee7..9c565cc 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/ErrorType.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Information/ErrorType.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,64 +7,60 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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 OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using System;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
+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;
- int retValue;
- 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);
- }
+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;
+ int retValue;
+ 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
index bfca497..e231841 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsBlank.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Information/IsBlank.cs
@@ -7,58 +7,49 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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)
- {
- var r=(ExcelDataProvider.IRangeInfo)arg.Value;
- if (r.GetValue(r.Address._fromRow, r.Address._fromCol) != null)
- {
- result = false;
- }
- }
- else
- {
- if (arg.Value != null && (arg.Value.ToString() != string.Empty))
- {
- result = false;
- break;
- }
- }
- }
- return CreateResult(result, DataType.Boolean);
- }
+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) {
+ var r = (ExcelDataProvider.IRangeInfo)arg.Value;
+ if (r.GetValue(r.Address._fromRow, r.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
index 880a715..ef90818 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsErr.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Information/IsErr.cs
@@ -1,43 +1,32 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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)
- {
- var r = (ExcelDataProvider.IRangeInfo)arg;
- var e=r.GetValue(r.Address._fromRow, r.Address._fromCol) as ExcelErrorValue;
- if (e !=null && e.Type==eErrorType.NA)
- {
- return CreateResult(false, DataType.Boolean);
- }
- }
- else
- {
- if (arg is ExcelErrorValue && ((ExcelErrorValue)arg).Type==eErrorType.NA)
- {
- return CreateResult(false, DataType.Boolean);
- }
- }
- }
- return result;
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
- public override CompileResult HandleError(string errorCode)
- {
- return CreateResult(true, DataType.Boolean);
+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) {
+ var r = (ExcelDataProvider.IRangeInfo)arg;
+ var e = r.GetValue(r.Address._fromRow, r.Address._fromCol) as ExcelErrorValue;
+ if (e != null && e.Type == eErrorType.Na) {
+ return CreateResult(false, DataType.Boolean);
}
+ } else {
+ if (arg is ExcelErrorValue && ((ExcelErrorValue)arg).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
index da883f6..d9802cf 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsError.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Information/IsError.cs
@@ -7,62 +7,52 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-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)
- {
- var r = (ExcelDataProvider.IRangeInfo)argument.Value;
- if (ExcelErrorValue.Values.IsErrorValue(r.GetValue(r.Address._fromRow, r.Address._fromCol)))
- {
- return CreateResult(true, DataType.Boolean);
- }
- }
- else
- {
- if (ExcelErrorValue.Values.IsErrorValue(argument.Value))
- {
- return CreateResult(true, DataType.Boolean);
- }
- }
- }
- return CreateResult(false, DataType.Boolean);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
- public override CompileResult HandleError(string errorCode)
- {
- return CreateResult(true, DataType.Boolean);
- }
+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) {
+ var r = (ExcelDataProvider.IRangeInfo)argument.Value;
+ if (ExcelErrorValue.Values.IsErrorValue(
+ r.GetValue(r.Address._fromRow, r.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
index 883e5aa..af8bf4e 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsEven.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Information/IsEven.cs
@@ -1,24 +1,19 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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);
- }
+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
index 156669d..fbda5d6 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsLogical.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Information/IsLogical.cs
@@ -1,19 +1,16 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
-using System.Text;
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);
- }
- }
+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
index 7e83f2e..82adcfe 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsNa.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Information/IsNa.cs
@@ -7,45 +7,41 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
- var v = GetFirstValue(arguments);
-
- if (v is ExcelErrorValue && ((ExcelErrorValue)v).Type==eErrorType.NA)
- {
- return CreateResult(true, DataType.Boolean);
- }
- return CreateResult(false, DataType.Boolean);
- }
+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 && ((ExcelErrorValue)v).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
index e61eb94..c84008d 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsNonText.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Information/IsNonText.cs
@@ -7,37 +7,37 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
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);
- }
+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
index 2ddf31c..eac8fdd 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsNumber.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Information/IsNumber.cs
@@ -1,5 +1,4 @@
-using System;
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -8,35 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or 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 System.Text;
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);
- }
- }
+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
index 9b345d0..1e1af7f 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsOdd.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Information/IsOdd.cs
@@ -7,42 +7,38 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
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);
- }
+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
index dae2c3a..b2d288b 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/IsText.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Information/IsText.cs
@@ -7,39 +7,36 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
+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
index 046c7a4..18d6665 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/N.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Information/N.cs
@@ -1,39 +1,31 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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)
- {
- var val = (bool) arg ? 1d : 0d;
- return CreateResult(val, DataType.Decimal);
- }
- else if (IsNumeric(arg))
- {
- var val = ConvertUtil.GetValueDouble(arg);
- return CreateResult(val, DataType.Decimal);
- }
- else if (arg is string)
- {
- return CreateResult(0d, DataType.Decimal);
- }
- else if (arg is ExcelErrorValue)
- {
- return CreateResult(arg, DataType.ExcelError);
- }
- throw new ExcelErrorValueException(eErrorType.Value);
- }
+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) {
+ var val = (bool)arg ? 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
index 7d2fc03..93bfba2 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Information/Na.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Information/Na.cs
@@ -1,16 +1,12 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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);
- }
- }
+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
index 6ae3a09..b510d93 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/IntArgumentParser.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/IntArgumentParser.cs
@@ -7,55 +7,47 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.Utilities;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions
-{
- public class IntArgumentParser : ArgumentParser
- {
- public override object Parse(object obj)
- {
- Require.That(obj).Named("argument").IsNotNull();
- int result;
- if (obj is ExcelDataProvider.IRangeInfo)
- {
- var r = ((ExcelDataProvider.IRangeInfo)obj).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 result))
- {
- throw new ExcelErrorValueException(ExcelErrorValue.Create(eErrorType.Value));
- }
- return result;
- }
+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();
+ int result;
+ if (obj is ExcelDataProvider.IRangeInfo) {
+ var r = ((ExcelDataProvider.IRangeInfo)obj).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 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
index 363b447..c483af5 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/And.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Logical/And.cs
@@ -7,42 +7,38 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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 CompileResult(false, DataType.Boolean);
- }
- }
- return new CompileResult(true, DataType.Boolean);
- }
+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
index c568f3c..176d31a 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/False.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Logical/False.cs
@@ -7,34 +7,31 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 1dadfd3..bc55272 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/If.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Logical/If.cs
@@ -7,39 +7,37 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index a5e5802..8fe9993 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/IfError.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Logical/IfError.cs
@@ -1,18 +1,15 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
-using System.Text;
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);
- }
- }
+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
index 6c3d710..ec74404 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/IfNa.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Logical/IfNa.cs
@@ -1,18 +1,15 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
-using System.Text;
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);
- }
- }
+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
index 62cd5eb..aec7f74 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/Not.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Logical/Not.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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 CompileResult(result, DataType.Boolean);
- }
- }
+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
index 08907bd..bcf6e31 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/Or.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Logical/Or.cs
@@ -7,42 +7,38 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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 CompileResult(true, DataType.Boolean);
- }
- }
- return new CompileResult(false, DataType.Boolean);
- }
+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
index 2a85e3e..bb23a62 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Logical/True.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Logical/True.cs
@@ -7,34 +7,31 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 8f41338..ad29a14 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Abs.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Abs.cs
@@ -7,40 +7,36 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
+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
index 6a7db11..077a02e 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Acos.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Acos.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
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);
- }
- }
+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
index ac3d530..cf07e1b 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Acosh.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Acosh.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
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);
- }
- }
+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
index 4ca0a2f..288763c 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Asin.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Asin.cs
@@ -1,6 +1,6 @@
-using System;
using System.Collections.Generic;
-using System.Linq;
+using OfficeOpenXml.FormulaParsing.ExpressionGraph;
+
/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
@@ -10,33 +10,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-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);
- }
- }
+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
index e75d1f5..80ebdfa 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Asinh.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Asinh.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
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);
- }
- }
+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
index 38c6096..9cc60b0 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Atan.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Atan.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 34e4411..a490c1d 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Atan2.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Atan2.cs
@@ -7,38 +7,35 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 797ab65..302c97f 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Atanh.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Atanh.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
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);
- }
- }
+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
index c5c878d..159d9de 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Average.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Average.cs
@@ -7,102 +7,91 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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 System.Linq;
-using System.Text;
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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- 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>)
- {
- foreach (var item in (IEnumerable<FunctionArgument>)arg.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);
- }
- else if ((obj is bool) && !isInArray)
- {
- return ConvertUtil.GetValueDouble(obj);
- }
- else if (ConvertUtil.IsNumericString(obj))
- {
- return double.Parse(obj.ToString(), CultureInfo.InvariantCulture);
- }
- return default(double?);
- }
+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>) {
+ foreach (var item in (IEnumerable<FunctionArgument>)arg.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
index 8dd5bb9..00f575f 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/AverageA.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/AverageA.cs
@@ -7,118 +7,100 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
-using System.Text;
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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- 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>)
- {
- foreach (var item in (IEnumerable<FunctionArgument>)arg.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)
- {
- nValues++;
- retVal += (bool) c.Value ? 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);
- }
- else if (obj is bool)
- {
- if (isInArray) return default(double?);
- return ConvertUtil.GetValueDouble(obj);
- }
- else if (ConvertUtil.IsNumericString(obj))
- {
- return double.Parse(obj.ToString(), CultureInfo.InvariantCulture);
- }
- return default(double?);
- }
+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>) {
+ foreach (var item in (IEnumerable<FunctionArgument>)arg.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) {
+ nValues++;
+ retVal += (bool)c.Value ? 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
index 14e6b7e..3b83858 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/AverageIf.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/AverageIf.cs
@@ -7,155 +7,142 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.Exceptions;
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;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- public AverageIf()
- : this(new NumericExpressionEvaluator(), new WildCardValueMatcher())
- {
+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;
- }
+ 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);
- var retVal = 0d;
- 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);
- }
-
- private double Calculate(FunctionArgument arg, string expression)
- {
- var retVal = 0d;
- if (ShouldIgnore(arg) || !_numericExpressionEvaluator.Evaluate(arg.Value, expression))
- {
- return retVal;
- }
- if (IsNumeric(arg.Value))
- {
- retVal += ConvertUtil.GetValueDouble(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;
- }
+ 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);
+ var retVal = 0d;
+ 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);
+ }
+
+ private double Calculate(FunctionArgument arg, string expression) {
+ var retVal = 0d;
+ if (ShouldIgnore(arg) || !_numericExpressionEvaluator.Evaluate(arg.Value, expression)) {
+ return retVal;
+ }
+ if (IsNumeric(arg.Value)) {
+ retVal += ConvertUtil.GetValueDouble(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/AverageIfs.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/AverageIfs.cs
index 7333ce2..a24266c 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/AverageIfs.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/AverageIfs.cs
@@ -7,60 +7,63 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- var result = matchIndexes.Average(index => sumRange[index]);
-
- return CreateResult(result, DataType.Decimal);
- }
+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
index a441db2..2140891 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Ceiling.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Ceiling.cs
@@ -7,62 +7,54 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- else if (significance == 1)
- {
- return CreateResult(System.Math.Ceiling(number), DataType.Decimal);
- }
- else
- {
- var result = number - (number % significance) + significance;
- return CreateResult(result, DataType.Decimal);
- }
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- 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);
- }
- }
+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
index e889619..a605707 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Cos.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Cos.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index f294478..bb15381 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Cosh.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Cosh.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 21a58c1..c5c42da 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Count.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Count.cs
@@ -7,111 +7,98 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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 System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math
-{
- public class Count : HiddenValuesHandlingFunction
- {
- private enum ItemContext
- {
- InRange,
- InArray,
- SingleArg
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- 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);
- }
+public class Count : HiddenValuesHandlingFunction {
+ private enum ItemContext {
+ InRange,
+ InArray,
+ SingleArg,
+ }
- 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++;
- }
- }
- }
- }
- }
+ 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 _CheckForAndHandleExcelError(FunctionArgument arg, ParsingContext context)
- {
- //if (context.Scopes.Current.IsSubtotal)
- //{
- // CheckForAndHandleExcelError(arg);
- //}
+ 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++;
+ }
}
-
- private void _CheckForAndHandleExcelError(ExcelDataProvider.ICellInfo cell, ParsingContext context)
- {
- //if (context.Scopes.Current.IsSubtotal)
- //{
- // CheckForAndHandleExcelError(cell);
- //}
+ } 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 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.ToString());
- }
- }
+ }
}
+ }
+
+ 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
index 0f44b47..3e7fd3c 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/CountA.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/CountA.cs
@@ -7,91 +7,79 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- 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>)
- {
- Calculate((IEnumerable<FunctionArgument>)item.Value, context, ref nItems);
- }
- else
- {
- _CheckForAndHandleExcelError(item, context);
- if (!ShouldIgnore(item) && ShouldCount(item.Value))
- {
- nItems++;
- }
- }
+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++;
+ }
}
-
- private void _CheckForAndHandleExcelError(FunctionArgument arg, ParsingContext context)
- {
- if (context.Scopes.Current.IsSubtotal)
- {
- CheckForAndHandleExcelError(arg);
- }
+ } else if (item.Value is IEnumerable<FunctionArgument>) {
+ Calculate((IEnumerable<FunctionArgument>)item.Value, context, ref nItems);
+ } else {
+ _CheckForAndHandleExcelError(item, context);
+ if (!ShouldIgnore(item) && ShouldCount(item.Value)) {
+ nItems++;
}
-
- 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()));
- }
+ }
}
+ }
+
+ 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
index a5932ac..23176ae 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/CountBlank.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/CountBlank.cs
@@ -1,28 +1,25 @@
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
+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);
- }
+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
index 02f57a9..e5e7f14 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/CountIf.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/CountIf.cs
@@ -1,84 +1,66 @@
-using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
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;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- public CountIf()
- : this(new NumericExpressionEvaluator(), new WildCardValueMatcher())
- {
+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;
- }
+ 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>)
- {
- foreach (var arg in (IEnumerable<FunctionArgument>) range.Value)
- {
- if(Evaluate(arg.Value, criteria))
- {
- result++;
- }
- }
- }
- else
- {
- if (Evaluate(range.Value, criteria))
- {
- result++;
- }
- }
- return CreateResult(result, DataType.Integer);
- }
+ 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>) {
+ foreach (var arg in (IEnumerable<FunctionArgument>)range.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
index 34e7526..e4b7418 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/CountIfs.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/CountIfs.cs
@@ -7,63 +7,56 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Xml.XPath;
-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 CountIfs : MultipleRangeCriteriasFunction
- {
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- 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);
- }
+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
index 85d2979..7faae97 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Degrees.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Degrees.cs
@@ -1,19 +1,15 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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);
- }
- }
+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
index 843b179..de88305 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Exp.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Exp.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index da54301..2bb24f5 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Fact.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Fact.cs
@@ -1,24 +1,19 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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);
- }
+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
index 29d57c7..caa43c5 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Floor.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Floor.cs
@@ -7,70 +7,59 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- else if (significance == 1)
- {
- return CreateResult(System.Math.Floor(number), DataType.Decimal);
- }
- else
- {
- double result;
- if (number > 1)
- {
- result = number - (number % significance) + significance;
- }
- else
- {
- result = number - (number % significance);
- }
- return CreateResult(result, DataType.Decimal);
- }
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- 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);
- }
- }
+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
index adf4fe4..025c47f 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Large.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Large.cs
@@ -1,22 +1,19 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
-using System.Text;
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);
- }
- }
+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
index 5769eec..e93147f 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Ln.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Ln.cs
@@ -1,18 +1,14 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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);
- }
-}
+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
index 53b0007..c348ecf 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Log.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Log.cs
@@ -7,41 +7,38 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
+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
index 28c8eb3..c9f9431 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Log10.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Log10.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index e4e813a..6b9163a 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/MathHelper.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/MathHelper.cs
@@ -7,159 +7,132 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+
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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- // Cosecant
- public static double Cosec(double x)
- {
- return 1 / MathObj.Sin(x);
- }
+/// <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);
+ }
- // Cotangent
- public static double Cotan(double x)
- {
- return 1 / MathObj.Tan(x);
- }
+ // Cosecant
+ public static double Cosec(double x) {
+ return 1 / MathObj.Sin(x);
+ }
- // Inverse Sine
- public static double Arcsin(double x)
- {
- return MathObj.Atan(x / MathObj.Sqrt(-x * x + 1));
- }
+ // Cotangent
+ public static double Cotan(double x) {
+ return 1 / MathObj.Tan(x);
+ }
- // Inverse Cosine
- public static double Arccos(double x)
- {
- return MathObj.Atan(-x / MathObj.Sqrt(-x * x + 1)) + 2 * MathObj.Atan(1);
- }
+ // 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 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 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);
- }
+ // 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 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 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 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 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 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));
- }
+ // 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 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 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 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 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 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;
- }
+ // 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);
- }
- }
+ // 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
index 689c6eb..c6ddf8f 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Max.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Max.cs
@@ -7,36 +7,34 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index cd19664..1ef491a 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Maxa.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Maxa.cs
@@ -7,49 +7,45 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
using OfficeOpenXml.FormulaParsing.Utilities;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math
-{
- public class Maxa : ExcelFunction
- {
- private readonly DoubleEnumerableArgConverter _argConverter;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- public Maxa()
- : this(new DoubleEnumerableArgConverter())
- {
+public class Maxa : ExcelFunction {
+ private readonly DoubleEnumerableArgConverter _argConverter;
- }
- 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);
- }
- }
+ 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
index 80cd503..6edc020 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Median.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Median.cs
@@ -7,48 +7,44 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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 OfficeOpenXml.FormulaParsing.ExpressionGraph;
+
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
+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);
- }
+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
index edd621f..f2b5fdf 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Min.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Min.cs
@@ -7,36 +7,34 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 65ebc87..a93424f 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Mina.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Mina.cs
@@ -7,49 +7,45 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
using OfficeOpenXml.FormulaParsing.Utilities;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math
-{
- public class Mina : ExcelFunction
- {
- private readonly DoubleEnumerableArgConverter _argConverter;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- public Mina()
- : this(new DoubleEnumerableArgConverter())
- {
+public class Mina : ExcelFunction {
+ private readonly DoubleEnumerableArgConverter _argConverter;
- }
- 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);
- }
- }
+ 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
index 4025d6b..968e1c8 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Mod.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Mod.cs
@@ -7,37 +7,34 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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 CompileResult(n1 % n2, DataType.Decimal);
- }
- }
+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
index 4f29447..5efe6f0 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/MultipleRangeCriteriasFunction.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/MultipleRangeCriteriasFunction.cs
@@ -7,85 +7,72 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.ExcelUtilities;
using OfficeOpenXml.FormulaParsing.Utilities;
using OfficeOpenXml.Utils;
using Require = OfficeOpenXml.FormulaParsing.Utilities.Require;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math
-{
- public abstract class MultipleRangeCriteriasFunction : ExcelFunction
- {
+public abstract class MultipleRangeCriteriasFunction : ExcelFunction {
+ private readonly NumericExpressionEvaluator _numericExpressionEvaluator;
+ private readonly WildCardValueMatcher _wildCardValueMatcher;
- private readonly NumericExpressionEvaluator _numericExpressionEvaluator;
- private readonly WildCardValueMatcher _wildCardValueMatcher;
+ protected MultipleRangeCriteriasFunction()
+ : this(new(), new()) {}
- protected MultipleRangeCriteriasFunction()
- :this(new NumericExpressionEvaluator(), new WildCardValueMatcher())
- {
-
- }
+ protected MultipleRangeCriteriasFunction(
+ NumericExpressionEvaluator evaluator,
+ WildCardValueMatcher wildCardValueMatcher) {
+ Require.That(evaluator).Named("evaluator").IsNotNull();
+ Require.That(wildCardValueMatcher).Named("wildCardValueMatcher").IsNotNull();
+ _numericExpressionEvaluator = evaluator;
+ _wildCardValueMatcher = wildCardValueMatcher;
+ }
- 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;
- }
+ 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
index 244dce7..c606b48 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Pi.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Pi.cs
@@ -7,35 +7,32 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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((double)System.Math.PI, 14);
- return CreateResult(result, DataType.Decimal);
- }
- }
+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
index abe7e67..f0fd0a6 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Power.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Power.cs
@@ -7,38 +7,35 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index d8c8c4e..5414558 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Product.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Product.cs
@@ -7,85 +7,83 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- 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;
- }
+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
index e4f7307..866ddd9 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Quotient.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Quotient.cs
@@ -1,21 +1,17 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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);
- }
- }
+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
index e04ebf5..9beb787 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Rand.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Rand.cs
@@ -1,24 +1,17 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math
-{
- public class Rand : ExcelFunction
- {
- private static int Seed
- {
- get;
- set;
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- 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);
- }
- }
+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
index 0202085..5bb9e8a 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/RandBetween.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/RandBetween.cs
@@ -7,53 +7,47 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- private double CalulateDiff(double high, double low)
- {
- if (high > 0 && low < 0)
- {
- return high + low * - 1;
- }
- else if (high < 0 && low < 0)
- {
- return high * -1 - low * -1;
- }
- return high - low;
- }
+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/Rank.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Rank.cs
index 7087b5f..ae71b2c 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Rank.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Rank.cs
@@ -1,69 +1,66 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math
-{
- public class Rank : ExcelFunction
- {
- bool _isAvg;
- public Rank(bool isAvg=false)
- {
- _isAvg=isAvg;
- }
- public override CompileResult Execute(IEnumerable<FunctionArgument> arguments, ParsingContext context)
- {
- ValidateArguments(arguments, 2);
- var number = ArgToDecimal(arguments, 0);
- var refer = arguments.ElementAt(1);
- bool asc = false;
- if (arguments.Count() > 2)
- {
- asc = base.ArgToBool(arguments, 2);
- }
- var l = new List<double>();
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math {
+ public class Rank : ExcelFunction {
+ bool _isAvg;
- foreach (var c in refer.ValueAsRangeInfo)
- {
- var v = Utils.ConvertUtil.GetValueDouble(c.Value, false, true);
- if (!double.IsNaN(v))
- {
- l.Add(v);
- }
- }
- l.Sort();
- double ix;
- if (asc)
- {
- ix = l.IndexOf(number)+1;
- if(_isAvg)
- {
- int st = Convert.ToInt32(ix);
- while (l.Count > st && l[st] == number) st++;
- if (st > ix) ix = ix + ((st - ix) / 2D);
- }
- }
- else
- {
- ix = l.LastIndexOf(number);
- if (_isAvg)
- {
- int st = Convert.ToInt32(ix)-1;
- while (0 <= st && l[st] == number) st--;
- if (st+1 < ix) ix = ix - ((ix - st - 1) / 2D);
- }
- ix = l.Count - ix;
- }
- if (ix <= 0 || ix>l.Count)
- {
- return new CompileResult(ExcelErrorValue.Create(eErrorType.NA), DataType.ExcelError);
- }
- else
- {
- return CreateResult(ix, DataType.Decimal);
- }
- }
+ public Rank(bool isAvg = false) {
+ _isAvg = isAvg;
}
+
+ public override CompileResult Execute(
+ IEnumerable<FunctionArgument> arguments,
+ ParsingContext context) {
+ ValidateArguments(arguments, 2);
+ var number = ArgToDecimal(arguments, 0);
+ var refer = arguments.ElementAt(1);
+ bool asc = false;
+ if (arguments.Count() > 2) {
+ asc = base.ArgToBool(arguments, 2);
+ }
+ var l = new List<double>();
+
+ foreach (var c in refer.ValueAsRangeInfo) {
+ var v = Utils.ConvertUtil.GetValueDouble(c.Value, false, true);
+ if (!double.IsNaN(v)) {
+ l.Add(v);
+ }
+ }
+ l.Sort();
+ double ix;
+ if (asc) {
+ ix = l.IndexOf(number) + 1;
+ if (_isAvg) {
+ int st = Convert.ToInt32(ix);
+ while (l.Count > st && l[st] == number) {
+ st++;
+ }
+ if (st > ix) {
+ ix = ix + ((st - ix) / 2D);
+ }
+ }
+ } else {
+ ix = l.LastIndexOf(number);
+ if (_isAvg) {
+ int st = Convert.ToInt32(ix) - 1;
+ while (0 <= st && l[st] == number) {
+ st--;
+ }
+ if (st + 1 < ix) {
+ ix = ix - ((ix - st - 1) / 2D);
+ }
+ }
+ ix = l.Count - ix;
+ }
+ if (ix <= 0 || ix > l.Count) {
+ return new CompileResult(ExcelErrorValue.Create(eErrorType.NA), DataType.ExcelError);
+ } else {
+ return CreateResult(ix, DataType.Decimal);
+ }
+ }
+ }
}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Round.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Round.cs
index 78407fc..1bda92d 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Round.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Round.cs
@@ -7,42 +7,38 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
+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
index 82e9fcd..396c355 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Rounddown.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Rounddown.cs
@@ -7,61 +7,54 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
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);
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- var nFactor = number < 0 ? -1 : 1;
- number *= nFactor;
+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);
- 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);
- }
+ var nFactor = number < 0 ? -1 : 1;
+ number *= nFactor;
- 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;
- }
+ 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
index 80c00ff..d411ce6 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Roundup.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Roundup.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,40 +7,40 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
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);
- }
- }
+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
index a060685..e09a919 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Sign.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Sign.cs
@@ -7,45 +7,39 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
+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
index 0e3bc1f..5b55efa 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Sin.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Sin.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index ec1b646..5cf3d88 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Sinh.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Sinh.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 5defb12..f22e9fa 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Small.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Small.cs
@@ -1,22 +1,19 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
-using System.Text;
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);
- }
- }
+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
index ccaebf7..61dff82 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Sqrt.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Sqrt.cs
@@ -7,37 +7,34 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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((double)arg);
- return CreateResult((double)result, DataType.Decimal);
- }
- }
+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
index a87edd3..cea3e32 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/SqrtPi.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/SqrtPi.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 44bfa43..62831fb 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Stdev.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Stdev.cs
@@ -7,56 +7,53 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
using OfficeOpenXml.FormulaParsing.Exceptions;
-using MathObj = System.Math;
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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- 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;
- }
+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
index f97065d..16e7b7a 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/StdevP.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/StdevP.cs
@@ -7,42 +7,39 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using MathObj = System.Math;
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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- private static double StandardDeviation(IEnumerable<double> values)
- {
- double avg = values.Average();
- return MathObj.Sqrt(values.Average(v => MathObj.Pow(v - avg, 2)));
- }
- }
+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
index d02024e..45e11e6 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Subtotal.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Subtotal.cs
@@ -7,101 +7,92 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math
-{
- public class Subtotal : ExcelFunction
- {
- private Dictionary<int, HiddenValuesHandlingFunction> _functions = new Dictionary<int, HiddenValuesHandlingFunction>();
-
- public Subtotal()
- {
- Initialize();
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- 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();
+public class Subtotal : ExcelFunction {
+ private Dictionary<int, HiddenValuesHandlingFunction> _functions = new();
- 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);
- }
+ public Subtotal() {
+ Initialize();
+ }
- private void AddHiddenValueHandlingFunction(HiddenValuesHandlingFunction func, int funcNum)
- {
- func.IgnoreHiddenValues = true;
- _functions[funcNum] = func;
- }
+ 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();
- public override void BeforeInvoke(ParsingContext context)
- {
- base.BeforeInvoke(context);
- context.Scopes.Current.IsSubtotal = true;
- }
+ 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);
+ }
- 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);
- ExcelFunction function = null;
- function = GetFunctionByCalcType(funcNum);
- var compileResult = function.Execute(actualArgs, context);
- compileResult.IsResultOfSubtotal = true;
- return compileResult;
- }
+ private void AddHiddenValueHandlingFunction(HiddenValuesHandlingFunction func, int funcNum) {
+ func.IgnoreHiddenValues = true;
+ _functions[funcNum] = func;
+ }
- 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];
- }
+ 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);
+ ExcelFunction function = null;
+ 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
index 4cc7d24..5d3550e 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Sum.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Sum.cs
@@ -7,78 +7,61 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
using OfficeOpenXml.Utils;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
- private double Calculate(FunctionArgument arg, ParsingContext context)
- {
- var retVal = 0d;
- if (ShouldIgnore(arg))
- {
- return retVal;
- }
- if (arg.Value is IEnumerable<FunctionArgument>)
- {
- foreach (var item in (IEnumerable<FunctionArgument>)arg.Value)
- {
- retVal += Calculate(item, context);
- }
- }
- else if (arg.Value is ExcelDataProvider.IRangeInfo)
- {
- foreach (var c in (ExcelDataProvider.IRangeInfo)arg.Value)
- {
- if (ShouldIgnore(c, context) == false)
- {
- CheckForAndHandleExcelError(c);
- retVal += c.ValueDouble;
- }
- }
- }
- else
- {
- CheckForAndHandleExcelError(arg);
- retVal += ConvertUtil.GetValueDouble(arg.Value, true);
- }
- return retVal;
- }
+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>) {
+ foreach (var item in (IEnumerable<FunctionArgument>)arg.Value) {
+ retVal += Calculate(item, context);
+ }
+ } else if (arg.Value is ExcelDataProvider.IRangeInfo) {
+ foreach (var c in (ExcelDataProvider.IRangeInfo)arg.Value) {
+ 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
index 3c50d3e..1750c4e 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/SumIf.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/SumIf.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,170 +7,161 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.Utilities;
using OfficeOpenXml.FormulaParsing.Exceptions;
-using Util=OfficeOpenXml.Utils;
+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;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- public SumIf()
- : this(new NumericExpressionEvaluator())
- {
+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 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);
- var retVal = 0d;
- 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(IEnumerable<FunctionArgument> range, string criteria, IEnumerable<FunctionArgument> sumRange, ParsingContext context)
- {
- var retVal = 0d;
- var flattenedRange = ArgsToDoubleEnumerable(range, context);
- var flattenedSumRange = ArgsToDoubleEnumerable(sumRange, context);
- for (var x = 0; x < flattenedRange.Count(); x++)
- {
- var candidate = flattenedSumRange.ElementAt(x);
- if (_evaluator.Evaluate(flattenedRange.ElementAt(x), criteria))
- {
- retVal += candidate;
- }
- }
- return retVal;
- }
-
- 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)
- {
- throw (new ExcelErrorValueException((ExcelErrorValue)v));
- }
- 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;
- //}
+ 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);
+ var retVal = 0d;
+ 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(
+ IEnumerable<FunctionArgument> range,
+ string criteria,
+ IEnumerable<FunctionArgument> sumRange,
+ ParsingContext context) {
+ var retVal = 0d;
+ var flattenedRange = ArgsToDoubleEnumerable(range, context);
+ var flattenedSumRange = ArgsToDoubleEnumerable(sumRange, context);
+ for (var x = 0; x < flattenedRange.Count(); x++) {
+ var candidate = flattenedSumRange.ElementAt(x);
+ if (_evaluator.Evaluate(flattenedRange.ElementAt(x), criteria)) {
+ retVal += candidate;
+ }
+ }
+ return retVal;
+ }
+
+ 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) {
+ throw (new ExcelErrorValueException((ExcelErrorValue)v));
+ }
+ 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
index aefaea0..72ed696 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/SumIfs.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/SumIfs.cs
@@ -7,60 +7,63 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- var result = matchIndexes.Sum(index => sumRange[index]);
-
- return CreateResult(result, DataType.Decimal);
- }
+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
index 5ee6de5..6985eb7 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/SumProduct.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/SumProduct.cs
@@ -7,100 +7,80 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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 List<double>());
- var currentResult = results.Last();
- if (arg.Value is IEnumerable<FunctionArgument>)
- {
- foreach (var val in (IEnumerable<FunctionArgument>)arg.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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- private void AddValue(object convertVal, List<double> currentResult)
- {
- if (IsNumeric(convertVal))
- {
- currentResult.Add(Convert.ToDouble(convertVal));
- }
- else if (convertVal is ExcelErrorValue)
- {
- throw (new ExcelErrorValueException((ExcelErrorValue)convertVal));
- }
- else
- {
- currentResult.Add(0d);
- }
+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>) {
+ foreach (var val in (IEnumerable<FunctionArgument>)arg.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) {
+ throw (new ExcelErrorValueException((ExcelErrorValue)convertVal));
+ } else {
+ currentResult.Add(0d);
+ }
+ }
}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/Math/Sumsq.cs b/EPPlus/FormulaParsing/Excel/Functions/Math/Sumsq.cs
index 2a4a077..9bb56d3 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Sumsq.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Sumsq.cs
@@ -1,69 +1,50 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-
- private double Calculate(FunctionArgument arg, ParsingContext context, bool isInArray = false)
- {
- var retVal = 0d;
- if (ShouldIgnore(arg))
- {
- return retVal;
- }
- if (arg.Value is IEnumerable<FunctionArgument>)
- {
- foreach (var item in (IEnumerable<FunctionArgument>)arg.Value)
- {
- 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;
- }
+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>) {
+ foreach (var item in (IEnumerable<FunctionArgument>)arg.Value) {
+ 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
index b15bab6..dd85652 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Tan.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Tan.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 6b2333b..e2e4f14 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Tanh.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Tanh.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index fc21fea..3730382 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Trunc.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Trunc.cs
@@ -7,43 +7,39 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using OfficeOpenXml.FormulaParsing.Exceptions;
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);
- }
+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
index c18e7c5..b32b165 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/Var.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/Var.cs
@@ -7,37 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.Exceptions;
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 CompileResult(VarMethods.Var(args), DataType.Decimal);
- }
- }
+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
index e48dcb9..d12ddf8 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/VarMethods.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/VarMethods.cs
@@ -7,52 +7,45 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
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;
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
- 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());
- }
+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
index 159fe18..1afab92 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Math/VarP.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Math/VarP.cs
@@ -7,36 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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 CompileResult(VarMethods.VarP(args), DataType.Decimal);
- }
- }
+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
index 1e6f6af..0482de8 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Numeric/CInt.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Numeric/CInt.cs
@@ -7,37 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using System.Globalization;
-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);
- }
- }
+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
index d6fc7ba..71c5252 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/ObjectEnumerableArgConverter.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/ObjectEnumerableArgConverter.cs
@@ -7,52 +7,43 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.Utils;
-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)
- {
- foreach (var cell in (ExcelDataProvider.IRangeInfo)arg.Value)
- {
- if (!CellStateHelper.ShouldIgnore(ignoreHidden, cell, context))
- {
- argList.Add(cell.Value);
- }
- }
- }
- else
- {
- argList.Add(arg.Value);
- }
- })
- ;
+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) {
+ foreach (var cell in (ExcelDataProvider.IRangeInfo)arg.Value) {
+ 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
index a80d4a5..3d75525 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Address.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Address.cs
@@ -7,65 +7,58 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.Exceptions;
+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 && !(bool)fourthArg)
- {
- 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);
- }
+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 && !(bool)fourthArg) {
+ 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
index fd9659d..e558462 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/ArrayLookupNavigator.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/ArrayLookupNavigator.cs
@@ -1,78 +1,59 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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 = 0;
- 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();
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
- private void Initialize()
- {
- if (Arguments.LookupIndex >= _arrayData.Length)
- {
- throw new ExcelErrorValueException(eErrorType.Ref);
- }
- SetCurrentValue();
+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();
+ }
- public override int Index
- {
- get { return _index; }
- }
-
- private void SetCurrentValue()
- {
- _currentValue = _arrayData[_index];
- }
-
- private bool HasNext()
- {
- if (Direction == LookupDirection.Vertical)
- {
- return _index < (_arrayData.Length - 1);
- }
- else
- {
- return false;
- }
- }
-
- public override bool MoveNext()
- {
- if (!HasNext()) return false;
- if (Direction == LookupDirection.Vertical)
- {
- _index++;
- }
- SetCurrentValue();
- return true;
- }
-
- public override object CurrentValue
- {
- get { return _arrayData[_index].Value; }
- }
-
- public override object GetLookupValue()
- {
- return _arrayData[_index].Value;
- }
+ 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
index 491c6c6..599467b 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Choose.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Choose.cs
@@ -7,41 +7,38 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
+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
index 38e9360..c2b4366 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Column.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Column.cs
@@ -7,46 +7,43 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.Utilities;
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);
- }
+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
index d7eff8a..27864bb 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Columns.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Columns.cs
@@ -7,53 +7,45 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.Utilities;
-using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
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);
- }
- else
- {
- 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");
- }
+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
index 36a5ea5..124fb3e 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/ExcelLookupNavigator.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/ExcelLookupNavigator.cs
@@ -7,119 +7,100 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.Utilities;
+
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;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
- public ExcelLookupNavigator(LookupDirection direction, LookupArguments arguments, ParsingContext parsingContext)
- : base(direction, arguments, parsingContext)
- {
- Initialize();
- }
+public class ExcelLookupNavigator : LookupNavigator {
+ private int _currentRow;
+ private int _currentCol;
+ private object _currentValue;
+ private RangeAddress _rangeAddress;
+ private int _index;
- 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();
- }
+ public ExcelLookupNavigator(
+ LookupDirection direction,
+ LookupArguments arguments,
+ ParsingContext parsingContext)
+ : base(direction, arguments, parsingContext) {
+ Initialize();
+ }
- private void SetCurrentValue()
- {
- _currentValue = ParsingContext.ExcelDataProvider.GetCellValue(_rangeAddress.Worksheet, _currentRow, _currentCol);
- }
-
- private bool HasNext()
- {
- if (Direction == LookupDirection.Vertical)
- {
- return _currentRow < _rangeAddress.ToRow;
- }
- else
- {
- return _currentCol < _rangeAddress.ToCol;
- }
- }
-
- public override int Index
- {
- get { return _index; }
- }
-
- public override bool MoveNext()
- {
- if (!HasNext()) return false;
- if (Direction == LookupDirection.Vertical)
- {
- _currentRow++;
- }
- else
- {
- _currentCol++;
- }
- _index++;
- SetCurrentValue();
- return true;
- }
-
- public override object CurrentValue
- {
- get { return _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);
- }
+ 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
index 0dc39b8..a2ec6a3 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/HLookup.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/HLookup.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,39 +7,35 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-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);
- }
- }
+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
index 4d97611..7c8431d 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Index.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Index.cs
@@ -1,56 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.Exceptions;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.Utils;
-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();
- }
+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
index af85a06..ae80178 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Indirect.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Indirect.cs
@@ -7,49 +7,44 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
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 CompileResult(result, DataType.Enumerable);
- }
+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
index 87cf319..8fee752 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Lookup.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Lookup.cs
@@ -7,92 +7,94 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
+using OfficeOpenXml.FormulaParsing.ExcelUtilities;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
using OfficeOpenXml.FormulaParsing.Utilities;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using System.Text.RegularExpressions;
-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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
- 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);
- }
+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
index 846045f..8bed82d 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupArguments.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupArguments.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,106 +7,97 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup
-{
- public class LookupArguments
- {
- public enum LookupArgumentDataType
- {
- ExcelRange,
- DataArray
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
- public LookupArguments(IEnumerable<FunctionArgument> arguments)
- : this(arguments, new ArgumentParsers())
- {
+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; }
+ 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
index ee5a7d6..abb564c 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupDirection.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupDirection.cs
@@ -7,31 +7,25 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup
-{
- public enum LookupDirection
- {
- Vertical,
- Horizontal
- }
+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
index 800d553..84f20d8 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupFunction.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupFunction.cs
@@ -7,111 +7,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
+
using OfficeOpenXml.FormulaParsing.ExcelUtilities;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup
-{
- public abstract class LookupFunction : ExcelFunction
- {
- private readonly ValueMatcher _valueMatcher;
- private readonly CompileResultFactory _compileResultFactory;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
- public LookupFunction()
- : this(new LookupValueMatcher(), new CompileResultFactory())
- {
+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 LookupFunction(ValueMatcher valueMatcher, CompileResultFactory compileResultFactory) {
+ _valueMatcher = valueMatcher;
+ _compileResultFactory = compileResultFactory;
+ }
- public override bool IsLookupFuction
- {
- get
- {
- return true;
- }
- }
+ public override bool IsLookupFuction => true;
- protected int IsMatch(object o1, object o2)
- {
- return _valueMatcher.IsMatch(o1, o2);
- }
+ 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 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 CompileResult(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 CompileResult(ExcelErrorValue.Create(eErrorType.NA), DataType.ExcelError);
- }
+ 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
index 8ef23d5..f93cfbe 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigator.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigator.cs
@@ -7,60 +7,51 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
+
using OfficeOpenXml.FormulaParsing.Utilities;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup
-{
- public abstract class LookupNavigator
- {
- protected readonly LookupDirection Direction;
- protected readonly LookupArguments Arguments;
- protected readonly ParsingContext ParsingContext;
+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 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 int Index
- {
- get;
- }
+ public abstract bool MoveNext();
- public abstract bool MoveNext();
+ public abstract object CurrentValue { get; }
- public abstract object CurrentValue
- {
- get;
- }
-
- public abstract object GetLookupValue();
- }
+ public abstract object GetLookupValue();
}
diff --git a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigatorFactory.cs b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigatorFactory.cs
index 2a68900..d444525 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigatorFactory.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/LookupNavigatorFactory.cs
@@ -1,23 +1,18 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-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);
- }
- else if (args.ArgumentDataType == LookupArguments.LookupArgumentDataType.DataArray)
- {
- return new ArrayLookupNavigator(direction, args, parsingContext);
- }
- throw new NotSupportedException("Invalid argument datatype");
- }
+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
index a37218e..36f24fc 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Match.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Match.cs
@@ -7,99 +7,84 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
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
+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.
}
-
- public Match()
- : base(new WildCardValueMatcher(), new CompileResultFactory())
- {
-
+ 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);
+ }
- 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;
- }
+ 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
index 216f79e..8a16080 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Offset.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Offset.cs
@@ -7,74 +7,70 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
using System.Linq;
-using System.Text;
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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
- 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);
- }
+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
index 7b18ce1..5b20a5b 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Row.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Row.cs
@@ -7,46 +7,43 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.Utilities;
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);
- }
+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
index ab3d580..94f5203 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Rows.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Rows.cs
@@ -7,53 +7,45 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.Utilities;
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);
- }
- else
- {
- 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");
- }
+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
index a1f87b5..559715a 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/VLookup.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/VLookup.cs
@@ -7,51 +7,45 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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.Diagnostics;
-using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-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 Stopwatch();
- 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;
- }
+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
index b64da70..2350c6c 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/CStr.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/CStr.cs
@@ -7,35 +7,32 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index ac21f34..231479a 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/CharFunction.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/CharFunction.cs
@@ -1,19 +1,15 @@
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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);
- }
- }
+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
index 9102195..9a22422 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Concatenate.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Concatenate.cs
@@ -7,47 +7,42 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
+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
index 1cacfff..41d6a3e 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Exact.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Exact.cs
@@ -7,48 +7,48 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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;
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
- if (val1 == null && val2 == null)
- {
- return CreateResult(true, DataType.Boolean);
- }
- else if ((val1 == null && val2 != null) || (val1 != null && val2 == null))
- {
- return CreateResult(false, DataType.Boolean);
- }
+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;
- var result = string.Compare(val1.ToString(), val2.ToString(), StringComparison.InvariantCulture);
- return CreateResult(result == 0, DataType.Boolean);
- }
+ 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
index ed622d0..1a8c255 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Find.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Find.cs
@@ -7,50 +7,47 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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, System.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);
- }
+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
index c852959..4eab700 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Fixed.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Fixed.cs
@@ -1,37 +1,31 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using System.Text;
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);
- }
+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
index e2d184a..1635f43 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Hyperlink.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Hyperlink.cs
@@ -7,39 +7,36 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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 System.Text;
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);
- }
+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
index fddfe39..bdbbc74 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Left.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Left.cs
@@ -7,37 +7,34 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 357252b..d5ce785 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Len.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Len.cs
@@ -7,36 +7,35 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 244d86d..b9e51e2 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Lower.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Lower.cs
@@ -7,35 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 3f7da7a..8bbd0e6 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Mid.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Mid.cs
@@ -7,51 +7,46 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- else
- {
- var result = text.Substring(startIx - 1, startIx - 1 + length < text.Length ? length : text.Length - startIx + 1);
- return CreateResult(result, DataType.String);
- }
- }
+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
index a6044d3..a336746 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Proper.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Proper.cs
@@ -7,51 +7,45 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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 System.Linq;
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);
- }
+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
index c283c5d..37ccc2c 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Replace.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Replace.cs
@@ -7,54 +7,49 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
- private string GetFirstPart(string text, int startPos)
- {
- return text.Substring(0, startPos - 1);
- }
+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 GetLastPart(string text, int startPos, int nCharactersToReplace)
- {
- int startIx = startPos -1;
- startIx += nCharactersToReplace;
- return text.Substring(startIx, text.Length - startIx);
- }
- }
+ 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
index 2dafbd7..1f7cc5c 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Rept.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Rept.cs
@@ -7,42 +7,39 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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 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);
- }
+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
index 748e51d..f78efd9 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Right.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Right.cs
@@ -7,38 +7,35 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 05528cd..a6d38ba 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Search.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Search.cs
@@ -7,49 +7,46 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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 System.Text;
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, System.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);
- }
+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
index c0097e2..22d887e 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Substitute.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Substitute.cs
@@ -7,39 +7,36 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index 7179891..646b90b 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/T.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/T.cs
@@ -7,37 +7,37 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
+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
index 3d7ba36..00ae7fc 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Text.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Text.cs
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Jan Källman
+/* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -7,42 +7,43 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
+
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
-using System.Text;
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(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, ".");
- format = format.Replace(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator.Replace((char)160,' '), ","); //Special handling for No-Break Space
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
- var result = context.ExcelDataProvider.GetFormat(value, format);
+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
- return CreateResult(result, DataType.String);
- }
- }
+ 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
index 5328acd..c40e6f4 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Upper.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Upper.cs
@@ -7,35 +7,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any 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;
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);
- }
- }
+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
index a6b3e24..3ad4fc8 100644
--- a/EPPlus/FormulaParsing/Excel/Functions/Text/Value.cs
+++ b/EPPlus/FormulaParsing/Excel/Functions/Text/Value.cs
@@ -1,60 +1,62 @@
-using System;
using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
-using System.Text;
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 string _shortTimePattern = CultureInfo.CurrentCulture.DateTimeFormat.ShortTimePattern;
- private readonly DateValue _dateValueFunc = new DateValue();
- private readonly TimeValue _timeValueFunc = new TimeValue();
+namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
- public override CompileResult Execute(IEnumerable<FunctionArgument> arguments, ParsingContext context)
- {
- ValidateArguments(arguments, 1);
- var val = ArgToString(arguments, 0).TrimEnd(' ');
- double result = 0d;
- 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);
- }
+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 string _shortTimePattern = CultureInfo
+ .CurrentCulture
+ .DateTimeFormat
+ .ShortTimePattern;
+ 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 = 0d;
+ 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
index 63f7851..7975cc1 100644
--- a/EPPlus/FormulaParsing/Excel/Operators/IOperator.cs
+++ b/EPPlus/FormulaParsing/Excel/Operators/IOperator.cs
@@ -13,35 +13,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
+
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.Excel.Operators
-{
- public interface IOperator
- {
- Operators Operator { get; }
+namespace OfficeOpenXml.FormulaParsing.Excel.Operators;
- CompileResult Apply(CompileResult left, CompileResult right);
+public interface IOperator {
+ Operators Operator { get; }
- int Precedence { 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
index d53a4ac..9134b3c 100644
--- a/EPPlus/FormulaParsing/Excel/Operators/Operator.cs
+++ b/EPPlus/FormulaParsing/Excel/Operators/Operator.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,383 +13,386 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.Exceptions;
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 PrecedenceIntegerDivision = 8;
- private const int PrecedenceModulus = 10;
- private const int PrecedenceAddSubtract = 12;
- private const int PrecedenceConcat = 15;
- private const int PrecedenceComparison = 25;
+namespace OfficeOpenXml.FormulaParsing.Excel.Operators;
- private Operator() { }
+public class Operator : IOperator {
+ private const int _precedencePercent = 2;
+ private const int _precedenceExp = 4;
+ private const int _precedenceMultiplyDevide = 6;
+ private const int _precedenceIntegerDivision = 8;
+ private const int _precedenceModulus = 10;
+ 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 Operator() {}
- private readonly Func<CompileResult, CompileResult, CompileResult> _implementation;
- private readonly int _precedence;
- private readonly Operators _operator;
+ private Operator(
+ Operators @operator,
+ int precedence,
+ Func<CompileResult, CompileResult, CompileResult> implementation) {
+ _implementation = implementation;
+ _precedence = precedence;
+ _operator = @operator;
+ }
- int IOperator.Precedence
- {
- get { return _precedence; }
- }
+ private readonly Func<CompileResult, CompileResult, CompileResult> _implementation;
+ private readonly int _precedence;
+ private readonly Operators _operator;
- Operators IOperator.Operator
- {
- get { return _operator; }
- }
+ int IOperator.Precedence => _precedence;
- public CompileResult Apply(CompileResult left, CompileResult right)
- {
- if (left.Result is ExcelErrorValue)
- {
- return new CompileResult(left.Result, DataType.ExcelError);
- //throw(new ExcelErrorValueException((ExcelErrorValue)left.Result));
- }
- else if (right.Result is ExcelErrorValue)
- {
- return new CompileResult(right.Result, DataType.ExcelError);
- //throw(new ExcelErrorValueException((ExcelErrorValue)right.Result));
- }
- return _implementation(left, right);
- }
+ Operators IOperator.Operator {
+ get { return _operator; }
+ }
- public override string ToString()
- {
- return "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);
+ }
- 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 CompileResult(0, DataType.Integer) : l;
- r = r == null || r.Result == null ? new CompileResult(0, DataType.Integer) : r;
+ 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;
ExcelErrorValue errorVal;
- if (EitherIsError(l, r, out errorVal))
- {
- return new CompileResult(errorVal);
+ if (EitherIsError(l, r, out errorVal)) {
+ return new(errorVal);
}
- if (l.DataType == DataType.Integer && r.DataType == DataType.Integer)
- {
- return new CompileResult(l.ResultNumeric + r.ResultNumeric, DataType.Integer);
+ if (l.DataType == DataType.Integer && r.DataType == DataType.Integer) {
+ return new(l.ResultNumeric + r.ResultNumeric, DataType.Integer);
}
- else if ((l.IsNumeric || l.IsNumericString || l.Result is ExcelDataProvider.IRangeInfo) &&
- (r.IsNumeric || r.IsNumericString || r.Result is ExcelDataProvider.IRangeInfo))
- {
- return new CompileResult(l.ResultNumeric + r.ResultNumeric, DataType.Decimal);
+ 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 CompileResult(eErrorType.Value);
- }));
- }
- }
+ 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 CompileResult(0, DataType.Integer) : l;
- r = r == null || r.Result == null ? new CompileResult(0, DataType.Integer) : r;
- if (l.DataType == DataType.Integer && r.DataType == DataType.Integer)
- {
- return new CompileResult(l.ResultNumeric - r.ResultNumeric, DataType.Integer);
+ 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);
}
- else if ((l.IsNumeric || l.IsNumericString || l.Result is ExcelDataProvider.IRangeInfo) &&
- (r.IsNumeric || r.IsNumericString || r.Result is ExcelDataProvider.IRangeInfo))
- {
- return new CompileResult(l.ResultNumeric - r.ResultNumeric, DataType.Decimal);
+ 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 CompileResult(eErrorType.Value);
- }));
- }
- }
+ return new(eErrorType.Value);
+ }));
+ }
+ }
- private static IOperator _multiply;
- public static IOperator Multiply
- {
- get
- {
- return _multiply ?? (_multiply = new Operator(Operators.Multiply, PrecedenceMultiplyDevide, (l, r) =>
- {
+ 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 CompileResult(l.ResultNumeric*r.ResultNumeric, DataType.Integer);
+ if (l.DataType == DataType.Integer && r.DataType == DataType.Integer) {
+ return new(l.ResultNumeric * r.ResultNumeric, DataType.Integer);
}
- else if ((l.IsNumeric || l.IsNumericString || l.Result is ExcelDataProvider.IRangeInfo) &&
- (r.IsNumeric || r.IsNumericString || r.Result is ExcelDataProvider.IRangeInfo))
- {
- return new CompileResult(l.ResultNumeric*r.ResultNumeric, DataType.Decimal);
+ 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 CompileResult(eErrorType.Value);
- }));
- }
- }
+ 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 CompileResult(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 CompileResult(eErrorType.Div0);
+ if (Math.Abs(right - 0d) < double.Epsilon) {
+ return new(eErrorType.Div0);
}
- else if ((l.IsNumeric || l.IsNumericString || l.Result is ExcelDataProvider.IRangeInfo) &&
- (r.IsNumeric || r.IsNumericString || r.Result is ExcelDataProvider.IRangeInfo))
- {
- return new CompileResult(left/right, DataType.Decimal);
+ 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 CompileResult(eErrorType.Value);
- }));
- }
- }
-
- public static IOperator Exp
- {
- get
- {
- return new Operator(Operators.Exponentiation, PrecedenceExp, (l, r) =>
- {
- if (l == null && r == null)
- {
- return new CompileResult(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 CompileResult(Math.Pow(l.ResultNumeric, r.ResultNumeric), DataType.Decimal);
- }
- return new CompileResult(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 CompileResult(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 CompileResult(l.ResultNumeric * r.ResultNumeric, DataType.Integer);
- }
- else if ((l.IsNumeric || l.Result is ExcelDataProvider.IRangeInfo) && (r.IsNumeric || r.Result is ExcelDataProvider.IRangeInfo))
- {
- return new CompileResult(l.ResultNumeric * r.ResultNumeric, DataType.Decimal);
- }
- return new CompileResult(eErrorType.Value);
- });
- }
- return _percent;
- }
- }
-
- private static object GetObjFromOther(CompileResult obj, CompileResult other)
- {
- if (obj.Result == null)
- {
- if (other.DataType == DataType.String) return string.Empty;
- else return 0d;
- }
- return obj.ResultValue;
- }
-
- private static CompileResult Compare(CompileResult l, CompileResult r, Func<int, bool> comparison )
- {
- ExcelErrorValue errorVal;
- if (EitherIsError(l, r, out errorVal))
- {
- return new CompileResult(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 CompileResult(comparison(0), DataType.Boolean);
- }
- var comparisonResult = lnum.CompareTo(rnum);
- return new CompileResult(comparison(comparisonResult), DataType.Boolean);
- }
- else
- {
- var comparisonResult = CompareString(left, right);
- return new CompileResult(comparison(comparisonResult), DataType.Boolean);
- }
- }
-
- private static int CompareString(object l, object r)
- {
- var sl = (l ?? "").ToString();
- var sr = (r ?? "").ToString();
- return System.String.Compare(sl, sr, System.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;
- }
+ 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) {
+ ExcelErrorValue errorVal;
+ if (EitherIsError(l, r, out 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
index b5b4774..04c07e5 100644
--- a/EPPlus/FormulaParsing/Excel/Operators/Operators.cs
+++ b/EPPlus/FormulaParsing/Excel/Operators/Operators.cs
@@ -13,45 +13,39 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.Excel.Operators
-{
- public enum Operators
- {
- Undefined,
- Concat,
- Plus,
- Minus,
- Multiply,
- Divide,
- Modulus,
- Percent,
- Equals,
- GreaterThan,
- GreaterThanOrEqual,
- LessThan,
- LessThanOrEqual,
- NotEqualTo,
- IntegerDivision,
- Exponentiation
- }
+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
index 2ea34fb..2f1cf99 100644
--- a/EPPlus/FormulaParsing/Excel/Operators/OperatorsDict.cs
+++ b/EPPlus/FormulaParsing/Excel/Operators/OperatorsDict.cs
@@ -13,58 +13,50 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-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);
- }
+namespace OfficeOpenXml.FormulaParsing.Excel.Operators;
- private static IDictionary<string, IOperator> _instance;
+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);
+ }
- public static IDictionary<string, IOperator> Instance
- {
- get
- {
- if (_instance == null)
- {
- _instance = new OperatorsDict();
- }
- return _instance;
- }
- }
+ 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
index c642710..a94d5ef 100644
--- a/EPPlus/FormulaParsing/ExcelCalculationOption.cs
+++ b/EPPlus/FormulaParsing/ExcelCalculationOption.cs
@@ -1,16 +1,9 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+namespace OfficeOpenXml.FormulaParsing;
-namespace OfficeOpenXml.FormulaParsing
-{
- public class ExcelCalculationOption
- {
- public ExcelCalculationOption()
- {
- AllowCirculareReferences = false;
- }
- public bool AllowCirculareReferences { get; set; }
- }
+public class ExcelCalculationOption {
+ public ExcelCalculationOption() {
+ AllowCirculareReferences = false;
+ }
+
+ public bool AllowCirculareReferences { get; set; }
}
diff --git a/EPPlus/FormulaParsing/ExcelCell.cs b/EPPlus/FormulaParsing/ExcelCell.cs
index a560b08..aedd49c 100644
--- a/EPPlus/FormulaParsing/ExcelCell.cs
+++ b/EPPlus/FormulaParsing/ExcelCell.cs
@@ -1,26 +1,18 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+namespace OfficeOpenXml.FormulaParsing;
-namespace OfficeOpenXml.FormulaParsing
-{
- public class ExcelCell
- {
- public ExcelCell(object val, string formula, int colIndex, int rowIndex)
- {
- Value = val;
- Formula = formula;
- ColIndex = colIndex;
- RowIndex = rowIndex;
- }
+public class ExcelCell {
+ public ExcelCell(object val, string formula, int colIndex, int rowIndex) {
+ Value = val;
+ Formula = formula;
+ ColIndex = colIndex;
+ RowIndex = rowIndex;
+ }
- public int ColIndex { get; private set; }
+ public int ColIndex { get; private set; }
- public int RowIndex { get; private set; }
+ public int RowIndex { get; private set; }
- public object Value { get; private set; }
+ public object Value { get; private set; }
- public string Formula { get; private set; }
- }
+ public string Formula { get; private set; }
}
diff --git a/EPPlus/FormulaParsing/ExcelDataProvider.cs b/EPPlus/FormulaParsing/ExcelDataProvider.cs
index 17f1257..2c33ece 100644
--- a/EPPlus/FormulaParsing/ExcelDataProvider.cs
+++ b/EPPlus/FormulaParsing/ExcelDataProvider.cs
@@ -1,123 +1,153 @@
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
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);
+namespace OfficeOpenXml.FormulaParsing;
- 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);
+/// <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; }
- public abstract IEnumerable<object> GetRangeValues(string address);
+ bool IsMulti { get; }
- 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);
+ int GetNCells();
- /// <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);
+ ExcelAddressBase Address { get; }
- ///// <summary>
- ///// Sets the value on the cell
- ///// </summary>
- ///// <param name="address"></param>
- ///// <param name="value"></param>
- //public abstract void SetCellValue(string address, object value);
+ object GetValue(int row, int col);
- /// <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);
+ object GetOffset(int rowOffset, int colOffset);
- /// <summary>
- /// Max number of columns in a worksheet that the Excel data provider can handle.
- /// </summary>
- public abstract int ExcelMaxColumns { get; }
+ ExcelWorksheet Worksheet { get; }
+ }
- /// <summary>
- /// Max number of rows in a worksheet that the Excel data provider can handle
- /// </summary>
- public abstract int ExcelMaxRows { get; }
+ /// <summary>
+ /// Information and help methods about a cell
+ /// </summary>
+ public interface ICellInfo {
+ string Address { get; }
- public abstract object GetRangeValue(string worksheetName, int row, int column);
- public abstract string GetFormat(object value, string format);
+ int Row { get; }
- public abstract void Reset();
- public abstract IRangeInfo GetRange(string worksheet, int fromRow, int fromCol, int toRow, int toCol);
- }
+ 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
index 7f13379..7816854 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/AddressTranslator.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/AddressTranslator.cs
@@ -13,119 +13,104 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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.Globalization;
-using System.Linq;
-using System.Text;
using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing;
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
- }
+namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
- private readonly ExcelDataProvider _excelDataProvider;
+/// <summary>
+/// Handles translations from Spreadsheet addresses to 0-based numeric index.
+/// </summary>
+public class AddressTranslator {
+ public enum RangeCalculationBehaviour {
+ FirstPart,
+ LastPart,
+ }
- public AddressTranslator(ExcelDataProvider excelDataProvider)
- {
- Require.That(excelDataProvider).Named("excelDataProvider").IsNotNull();
- _excelDataProvider = excelDataProvider;
- }
+ private readonly 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);
- }
+ public AddressTranslator(ExcelDataProvider excelDataProvider) {
+ Require.That(excelDataProvider).Named("excelDataProvider").IsNotNull();
+ _excelDataProvider = excelDataProvider;
+ }
- /// <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);
+ /// <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);
+ }
- }
-
- private int GetRowIndexByBehaviour(RangeCalculationBehaviour behaviour)
- {
- if (behaviour == RangeCalculationBehaviour.FirstPart)
- {
- return 1;
- }
- return _excelDataProvider.ExcelMaxRows;
- }
-
- private int GetNumericAlphaValue(char c)
- {
- return (int)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;
- }
+ /// <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
index 77ca083..590d3e0 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/CellReferenceProvider.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/CellReferenceProvider.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,57 +13,51 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
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;
+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
index f8ae9fa..afba2c1 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/ExcelAddressInfo.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/ExcelAddressInfo.cs
@@ -13,82 +13,59 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
+
using OfficeOpenXml.FormulaParsing.Utilities;
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities
-{
- public class ExcelAddressInfo
- {
- private ExcelAddressInfo(string address)
- {
- var addressOnSheet = address;
- Worksheet = string.Empty;
- 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;
- }
+namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
- public static ExcelAddressInfo Parse(string address)
- {
- Require.That(address).Named("address").IsNotNullOrEmpty();
- return new ExcelAddressInfo(address);
- }
-
- public string Worksheet { get; private set; }
-
- public bool WorksheetIsSpecified
- {
- get
- {
- return !string.IsNullOrEmpty(Worksheet);
- }
- }
-
- public bool IsMultipleCells
- {
- get
- {
- return !string.IsNullOrEmpty(EndCell);
- }
- }
-
- public string StartCell { get; private set; }
-
- public string EndCell { get; private set; }
-
- public string AddressOnSheet { get; private set; }
+public class ExcelAddressInfo {
+ private ExcelAddressInfo(string address) {
+ var addressOnSheet = address;
+ Worksheet = string.Empty;
+ 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; }
+
+ 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
index 71a301f..75ad665 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/ExcelAddressUtil.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/ExcelAddressUtil.cs
@@ -13,59 +13,45 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities
-{
- public static class ExcelAddressUtil
- {
- static char[] SheetNameInvalidChars = new char[] { '?', ':', '*', '/', '\\' };
- 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 OfficeOpenXml.ExcelAddress.IsValidAddress(token);
+namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
+
+public static class ExcelAddressUtil {
+ private static 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
index eb87236..9651a35 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/ExcelReferenceType.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/ExcelReferenceType.cs
@@ -13,33 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities
-{
- public enum ExcelReferenceType
- {
- AbsoluteRowAndColumn = 1,
- AbsoluteRowRelativeColumn = 2,
- RelativeRowAbsolutColumn = 3,
- RelativeRowAndColumn = 4
- }
+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
index 92d2e61..53cf288 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/ExpressionEvaluator.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/ExpressionEvaluator.cs
@@ -13,133 +13,116 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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;
-using OfficeOpenXml.Utils;
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities
-{
- public class ExpressionEvaluator
- {
- private readonly WildCardValueMatcher _wildCardValueMatcher;
- private readonly CompileResultFactory _compileResultFactory;
+namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
- public ExpressionEvaluator()
- : this(new WildCardValueMatcher(), new CompileResultFactory())
- {
+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;
- }
+ 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;
- }
- else if (op is DateTime)
- {
- d = ((DateTime) op).ToOADate();
- return true;
- }
- else 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 != "-")
- {
- IOperator op;
- if (OperatorsDict.Instance.TryGetValue(operatorCandidate, out 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;
- }
- double leftNum, rightNum;
- DateTime date;
- bool leftIsNumeric = TryConvertToDouble(left, out leftNum);
- bool rightIsNumeric = double.TryParse(right, out rightNum);
- bool rightIsDate = DateTime.TryParse(right, out 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;
- }
+ 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) {
+ d = ((DateTime)op).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 != "-") {
+ IOperator op;
+ if (OperatorsDict.Instance.TryGetValue(operatorCandidate, out 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;
+ }
+ double leftNum,
+ rightNum;
+ DateTime date;
+ bool leftIsNumeric = TryConvertToDouble(left, out leftNum);
+ bool rightIsNumeric = double.TryParse(right, out rightNum);
+ bool rightIsDate = DateTime.TryParse(right, out 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
index 3025aa9..b5bc0cf 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependencies.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependencies.cs
@@ -13,70 +13,59 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities
-{
- public class FormulaDependencies
- {
- public FormulaDependencies()
- : this(new FormulaDependencyFactory())
- {
+namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
- }
+public class FormulaDependencies {
+ public FormulaDependencies()
+ : this(new()) {}
- public FormulaDependencies(FormulaDependencyFactory formulaDependencyFactory)
- {
- _formulaDependencyFactory = formulaDependencyFactory;
- }
+ public FormulaDependencies(FormulaDependencyFactory formulaDependencyFactory) {
+ _formulaDependencyFactory = formulaDependencyFactory;
+ }
- private readonly FormulaDependencyFactory _formulaDependencyFactory;
- private readonly Dictionary<string, FormulaDependency> _dependencies = new Dictionary<string, FormulaDependency>();
+ private readonly FormulaDependencyFactory _formulaDependencyFactory;
+ private readonly Dictionary<string, FormulaDependency> _dependencies = new();
- public IEnumerable<KeyValuePair<string, FormulaDependency>> Dependencies { get { return _dependencies; } }
+ 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 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();
- }
- }
+ public void Clear() {
+ _dependencies.Clear();
+ }
}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependency.cs b/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependency.cs
index da6fb9d..c337019 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependency.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependency.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,60 +13,55 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
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; }
+namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
- public RangeAddress Address { get; private set; }
+public class FormulaDependency {
+ public FormulaDependency(ParsingScope scope) {
+ ScopeId = scope.ScopeId;
+ Address = scope.Address;
+ }
- private List<RangeAddress> _referencedBy = new List<RangeAddress>();
+ public Guid ScopeId { get; private set; }
- private List<RangeAddress> _references = new List<RangeAddress>();
+ public RangeAddress Address { get; private set; }
- public virtual void AddReferenceFrom(RangeAddress rangeAddress)
- {
- if (Address.CollidesWith(rangeAddress) || _references.Exists(x => x.CollidesWith(rangeAddress)))
- {
- throw new CircularReferenceException("Circular reference detected at " + rangeAddress.ToString());
- }
- _referencedBy.Add(rangeAddress);
- }
+ private List<RangeAddress> _referencedBy = new();
- public virtual void AddReferenceTo(RangeAddress rangeAddress)
- {
- if (Address.CollidesWith(rangeAddress) || _referencedBy.Exists(x => x.CollidesWith(rangeAddress)))
- {
- throw new CircularReferenceException("Circular reference detected at " + rangeAddress.ToString());
- }
- _references.Add(rangeAddress);
- }
+ private 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
index a6e6205..9eb1f6d 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependencyFactory.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/FormulaDependencyFactory.cs
@@ -13,33 +13,26 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities
-{
- public class FormulaDependencyFactory
- {
- public virtual FormulaDependency Create(ParsingScope scope)
- {
- return new FormulaDependency(scope);
- }
- }
+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
index d1de754..238743a 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/IndexToAddressTranslator.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/IndexToAddressTranslator.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,90 +13,74 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-using OfficeOpenXml.FormulaParsing;
+
using OfficeOpenXml.FormulaParsing.Utilities;
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities
-{
- public class IndexToAddressTranslator
- {
- public IndexToAddressTranslator(ExcelDataProvider excelDataProvider)
- : this(excelDataProvider, ExcelReferenceType.AbsoluteRowAndColumn)
- {
+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;
- }
+ public IndexToAddressTranslator(
+ ExcelDataProvider excelDataProvider,
+ ExcelReferenceType referenceType) {
+ Require.That(excelDataProvider).Named("excelDataProvider").IsNotNull();
+ _excelDataProvider = excelDataProvider;
+ _excelReferenceType = referenceType;
+ }
- private readonly ExcelDataProvider _excelDataProvider;
- private readonly ExcelReferenceType _excelReferenceType;
+ 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;
- }
+ 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
index 41200ca..d2e0f3e 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/LookupValueMatcher.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/LookupValueMatcher.cs
@@ -1,15 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities
-{
- public class LookupValueMatcher : ValueMatcher
- {
- protected override int CompareObjectToString(object o1, string o2)
- {
- return IncompatibleOperands;
- }
- }
+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
index b5a1094..31b6f2a 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/NumericExpressionEvaluator.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/NumericExpressionEvaluator.cs
@@ -13,101 +13,87 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
using System.Text.RegularExpressions;
using OfficeOpenXml.FormulaParsing.Excel.Operators;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities
-{
- public class NumericExpressionEvaluator
- {
- private ValueMatcher _valueMatcher;
- private CompileResultFactory _compileResultFactory;
+namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
- public NumericExpressionEvaluator()
- : this(new ValueMatcher(), new CompileResultFactory())
- {
+public class NumericExpressionEvaluator {
+ private ValueMatcher _valueMatcher;
+ private CompileResultFactory _compileResultFactory;
- }
+ public NumericExpressionEvaluator()
+ : this(new(), new()) {}
- public NumericExpressionEvaluator(ValueMatcher valueMatcher, CompileResultFactory compileResultFactory)
- {
- _valueMatcher = valueMatcher;
- _compileResultFactory = compileResultFactory;
- }
+ 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)
- {
- double output;
- if (double.TryParse(op.ToString(), out 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)
- {
- IOperator op;
- if (OperatorsDict.Instance.TryGetValue(operatorCandidate, out op))
- {
- var numericCandidate = expression.Replace(operatorCandidate, string.Empty);
- double d;
- if (double.TryParse(numericCandidate, out 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;
- }
+ 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) {
+ double output;
+ if (double.TryParse(op.ToString(), out 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) {
+ IOperator op;
+ if (OperatorsDict.Instance.TryGetValue(operatorCandidate, out op)) {
+ var numericCandidate = expression.Replace(operatorCandidate, string.Empty);
+ double d;
+ if (double.TryParse(numericCandidate, out 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
index 114e80a..5a19ff9 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/RangeAddress.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/RangeAddress.cs
@@ -13,77 +13,64 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-using OfficeOpenXml.FormulaParsing.Utilities;
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities
-{
- public class RangeAddress
- {
- public RangeAddress()
- {
- Address = string.Empty;
- }
+namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
- internal string Address { get; set; }
+public class RangeAddress {
+ public RangeAddress() {
+ Address = string.Empty;
+ }
- public string Worksheet { get; internal set; }
+ internal string Address { get; set; }
- public int FromCol { get; internal set; }
+ public string Worksheet { get; internal set; }
- public int ToCol { get; internal set; }
+ public int FromCol { get; internal set; }
- public int FromRow { get; internal set; }
+ public int ToCol { get; internal set; }
- public int ToRow { get; internal set; }
+ public int FromRow { get; internal set; }
- public override string ToString()
- {
- return Address;
- }
+ public int ToRow { get; internal set; }
- private static RangeAddress _empty = new RangeAddress();
- public static RangeAddress Empty
- {
- get { return _empty; }
- }
+ public override string ToString() {
+ return Address;
+ }
- /// <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;
- }
+ private static 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
index 2e8b710..a2ae075 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/RangeAddressFactory.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/RangeAddressFactory.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,151 +13,144 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-using OfficeOpenXml.FormulaParsing;
+
using OfficeOpenXml.FormulaParsing.Utilities;
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities
-{
- public class RangeAddressFactory
- {
- private readonly ExcelDataProvider _excelDataProvider;
- private readonly AddressTranslator _addressTranslator;
- private readonly IndexToAddressTranslator _indexToAddressTranslator;
+namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
- public RangeAddressFactory(ExcelDataProvider excelDataProvider)
- : this(excelDataProvider, new AddressTranslator(excelDataProvider), new IndexToAddressTranslator(excelDataProvider, ExcelReferenceType.RelativeRowAndColumn))
- {
-
-
- }
+public class RangeAddressFactory {
+ private readonly ExcelDataProvider _excelDataProvider;
+ private readonly AddressTranslator _addressTranslator;
+ private readonly IndexToAddressTranslator _indexToAddressTranslator;
- 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;
- _addressTranslator = addressTranslator;
- _indexToAddressTranslator = indexToAddressTranslator;
- }
+ public RangeAddressFactory(ExcelDataProvider excelDataProvider)
+ : this(
+ excelDataProvider,
+ new(excelDataProvider),
+ new(excelDataProvider, ExcelReferenceType.RelativeRowAndColumn)) {}
- public RangeAddress Create(int col, int row)
- {
- return Create(string.Empty, col, row);
- }
+ 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;
+ _addressTranslator = addressTranslator;
+ _indexToAddressTranslator = indexToAddressTranslator;
+ }
- public RangeAddress Create(string worksheetName, int col, int row)
- {
- return new RangeAddress()
- {
- Address = _indexToAddressTranslator.ToAddress(col, row),
- Worksheet = worksheetName,
- FromCol = col,
- ToCol = col,
- FromRow = row,
- ToRow = row
- };
- }
+ public RangeAddress Create(int col, int row) {
+ return Create(string.Empty, col, 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
- };
+ 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,
+ };
+ }
- //if (addressInfo.IsMultipleCells)
- //{
- // HandleMultipleCellAddress(rangeAddress, addressInfo);
- //}
- //else
- //{
- // HandleSingleCellAddress(rangeAddress, addressInfo);
- //}
- return rangeAddress;
- }
+ /// <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,
+ };
- 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
- };
-
- //if (addressInfo.IsMultipleCells)
- //{
- // HandleMultipleCellAddress(rangeAddress, addressInfo);
- //}
- //else
- //{
- // HandleSingleCellAddress(rangeAddress, addressInfo);
- //}
- return rangeAddress;
- }
+ //if (addressInfo.IsMultipleCells)
+ //{
+ // HandleMultipleCellAddress(rangeAddress, addressInfo);
+ //}
+ //else
+ //{
+ // HandleSingleCellAddress(rangeAddress, addressInfo);
+ //}
+ return rangeAddress;
+ }
- private void HandleSingleCellAddress(RangeAddress rangeAddress, ExcelAddressInfo addressInfo)
- {
- int col, row;
- _addressTranslator.ToColAndRow(addressInfo.StartCell, out col, out row);
- rangeAddress.FromCol = col;
- rangeAddress.ToCol = col;
- rangeAddress.FromRow = row;
- rangeAddress.ToRow = row;
- }
+ 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,
+ };
- private void HandleMultipleCellAddress(RangeAddress rangeAddress, ExcelAddressInfo addressInfo)
- {
- int fromCol, fromRow;
- _addressTranslator.ToColAndRow(addressInfo.StartCell, out fromCol, out fromRow);
- int toCol, toRow;
- _addressTranslator.ToColAndRow(addressInfo.EndCell, out toCol, out toRow, AddressTranslator.RangeCalculationBehaviour.LastPart);
- rangeAddress.FromCol = fromCol;
- rangeAddress.ToCol = toCol;
- rangeAddress.FromRow = fromRow;
- rangeAddress.ToRow = toRow;
- }
- }
+ //if (addressInfo.IsMultipleCells)
+ //{
+ // HandleMultipleCellAddress(rangeAddress, addressInfo);
+ //}
+ //else
+ //{
+ // HandleSingleCellAddress(rangeAddress, addressInfo);
+ //}
+ return rangeAddress;
+ }
+
+ private void HandleSingleCellAddress(RangeAddress rangeAddress, ExcelAddressInfo addressInfo) {
+ int col,
+ row;
+ _addressTranslator.ToColAndRow(addressInfo.StartCell, out col, out row);
+ rangeAddress.FromCol = col;
+ rangeAddress.ToCol = col;
+ rangeAddress.FromRow = row;
+ rangeAddress.ToRow = row;
+ }
+
+ private void HandleMultipleCellAddress(RangeAddress rangeAddress, ExcelAddressInfo addressInfo) {
+ int fromCol,
+ fromRow;
+ _addressTranslator.ToColAndRow(addressInfo.StartCell, out fromCol, out fromRow);
+ int toCol,
+ toRow;
+ _addressTranslator.ToColAndRow(
+ addressInfo.EndCell,
+ out toCol,
+ out toRow,
+ AddressTranslator.RangeCalculationBehaviour.LastPart);
+ rangeAddress.FromCol = fromCol;
+ rangeAddress.ToCol = toCol;
+ rangeAddress.FromRow = fromRow;
+ rangeAddress.ToRow = toRow;
+ }
}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/ValueMatcher.cs b/EPPlus/FormulaParsing/ExcelUtilities/ValueMatcher.cs
index 2e8fd2a..aeb4a47 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/ValueMatcher.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/ValueMatcher.cs
@@ -13,98 +13,86 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExcelUtilities
-{
- public class ValueMatcher
- {
- public const int IncompatibleOperands = -2;
+namespace OfficeOpenXml.FormulaParsing.ExcelUtilities;
- 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);
+public class ValueMatcher {
+ public const int IncompatibleOperands = -2;
- if (o1 is string && o2 is string)
- {
- return CompareStringToString(o1.ToString().ToLower(), o2.ToString().ToLower());
- }
- else if( o1.GetType() == typeof(string))
- {
- return CompareStringToObject(o1.ToString(), o2);
- }
- else 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)
- {
- var r = ((ExcelDataProvider.IRangeInfo)v);
- if (r.GetNCells() > 1)
- {
- v = ExcelErrorValue.Create(eErrorType.NA);
- }
- v = r.GetOffset(0, 0);
- }
- else if (v is ExcelDataProvider.INameInfo)
- {
- var n = ((ExcelDataProvider.INameInfo)v);
- v = CheckGetRange(n);
- }
- return v;
- }
-
- protected virtual int CompareStringToString(string s1, string s2)
- {
- return s1.CompareTo(s2);
- }
-
- protected virtual int CompareStringToObject(string o1, object o2)
- {
- double d1;
- if (double.TryParse(o1, out d1))
- {
- return d1.CompareTo(Convert.ToDouble(o2));
- }
- return IncompatibleOperands;
- }
-
- protected virtual int CompareObjectToString(object o1, string o2)
- {
- double d2;
- if (double.TryParse(o2, out d2))
- {
- return Convert.ToDouble(o1).CompareTo(d2);
- }
- return IncompatibleOperands;
- }
+ 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) {
+ var r = ((ExcelDataProvider.IRangeInfo)v);
+ if (r.GetNCells() > 1) {
+ v = ExcelErrorValue.Create(eErrorType.Na);
+ }
+ v = r.GetOffset(0, 0);
+ } else if (v is ExcelDataProvider.INameInfo) {
+ var n = ((ExcelDataProvider.INameInfo)v);
+ v = CheckGetRange(n);
+ }
+ return v;
+ }
+
+ protected virtual int CompareStringToString(string s1, string s2) {
+ return s1.CompareTo(s2);
+ }
+
+ protected virtual int CompareStringToObject(string o1, object o2) {
+ double d1;
+ if (double.TryParse(o1, out d1)) {
+ return d1.CompareTo(Convert.ToDouble(o2));
+ }
+ return IncompatibleOperands;
+ }
+
+ protected virtual int CompareObjectToString(object o1, string o2) {
+ double d2;
+ if (double.TryParse(o2, out d2)) {
+ return Convert.ToDouble(o1).CompareTo(d2);
+ }
+ return IncompatibleOperands;
+ }
}
diff --git a/EPPlus/FormulaParsing/ExcelUtilities/WildCardValueMatcher.cs b/EPPlus/FormulaParsing/ExcelUtilities/WildCardValueMatcher.cs
index bfdbb51..15a1754 100644
--- a/EPPlus/FormulaParsing/ExcelUtilities/WildCardValueMatcher.cs
+++ b/EPPlus/FormulaParsing/ExcelUtilities/WildCardValueMatcher.cs
@@ -13,45 +13,37 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
+
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);
- }
+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
index 57be38f..d8fceeb 100644
--- a/EPPlus/FormulaParsing/ExcelValues.cs
+++ b/EPPlus/FormulaParsing/ExcelValues.cs
@@ -1,207 +1,206 @@
-using System;
+using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-namespace OfficeOpenXml
-{
+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 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>
- /// Represents the errortypes in excel
+ /// Returns true if the supplied <paramref name="candidate"/> is an excel error.
/// </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
+ /// <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>
- /// Represents an Excel error.
+ /// Returns true if the supplied <paramref name="candidate"/> is 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 Dictionary<string, eErrorType> _values = new Dictionary<string, eErrorType>()
- {
- {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 ExcelErrorValue(errorType);
- }
-
- internal static ExcelErrorValue Parse(string val)
- {
- if (string.IsNullOrEmpty(val)) // Google Bug G0005
- {
- val = Values.ErrorValueIsNullOrEmpty;
- }
-
- if (Values.StringIsErrorValue(val))
- {
- return new ExcelErrorValue(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)) return false;
- return ((ExcelErrorValue) obj).ToString() == this.ToString();
- }
+ /// <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)) {
+ return false;
+ }
+ return ((ExcelErrorValue)obj).ToString() == ToString();
+ }
}
diff --git a/EPPlus/FormulaParsing/Exceptions/CircularReferenceException.cs b/EPPlus/FormulaParsing/Exceptions/CircularReferenceException.cs
index 5ffc5ed..90dad5b 100644
--- a/EPPlus/FormulaParsing/Exceptions/CircularReferenceException.cs
+++ b/EPPlus/FormulaParsing/Exceptions/CircularReferenceException.cs
@@ -13,34 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.Exceptions
-{
- public class CircularReferenceException : Exception
- {
- public CircularReferenceException(string message)
- : base(message)
- {
+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
index 34333de..f182e8a 100644
--- a/EPPlus/FormulaParsing/Exceptions/ExcelErrorCodes.cs
+++ b/EPPlus/FormulaParsing/Exceptions/ExcelErrorCodes.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,94 +13,73 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.Exceptions
-{
- public class ExcelErrorCodes
- {
- private ExcelErrorCodes(string code)
- {
- Code = code;
- }
+namespace OfficeOpenXml.FormulaParsing.Exceptions;
- public string Code
- {
- get;
- private set;
- }
+public class ExcelErrorCodes {
+ private ExcelErrorCodes(string code) {
+ Code = code;
+ }
- public override int GetHashCode()
- {
- return Code.GetHashCode();
- }
+ public string Code { get; private set; }
- public override bool Equals(object obj)
- {
- if (obj is ExcelErrorCodes)
- {
- return ((ExcelErrorCodes)obj).Code.Equals(Code);
- }
- return false;
- }
+ public override int GetHashCode() {
+ return Code.GetHashCode();
+ }
- 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
- {
- get { return new ExcelErrorCodes("#VALUE!"); }
- }
-
- public static ExcelErrorCodes Name
- {
- get { return new ExcelErrorCodes("#NAME?"); }
- }
-
- public static ExcelErrorCodes NoValueAvaliable
- {
- get { return new ExcelErrorCodes("#N/A"); }
- }
+ public override bool Equals(object obj) {
+ if (obj is ExcelErrorCodes) {
+ return ((ExcelErrorCodes)obj).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
index dcc2239..4341ed0 100644
--- a/EPPlus/FormulaParsing/Exceptions/ExcelErrorValueException.cs
+++ b/EPPlus/FormulaParsing/Exceptions/ExcelErrorValueException.cs
@@ -1,40 +1,27 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-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)
- {
-
- }
+namespace OfficeOpenXml.FormulaParsing.Exceptions;
- public ExcelErrorValueException(string message, ExcelErrorValue error)
- : base(message)
- {
- ErrorValue = error;
- }
+/// <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(eErrorType errorType)
- : this(ExcelErrorValue.Create(errorType))
- {
-
- }
+ public ExcelErrorValueException(string message, ExcelErrorValue error)
+ : base(message) {
+ ErrorValue = error;
+ }
- /// <summary>
- /// The error value
- /// </summary>
- public ExcelErrorValue ErrorValue { get; private set; }
- }
+ 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
index 4c26ba8..f4852c0 100644
--- a/EPPlus/FormulaParsing/Exceptions/UnrecognizedTokenException.cs
+++ b/EPPlus/FormulaParsing/Exceptions/UnrecognizedTokenException.cs
@@ -13,35 +13,28 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-namespace OfficeOpenXml.FormulaParsing.Exceptions
-{
- public class UnrecognizedTokenException : Exception
- {
- public UnrecognizedTokenException(Token token)
- : base( "Unrecognized token: " + token.Value)
- {
+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
index 5467137..0ad249e 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/AtomicExpression.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/AtomicExpression.cs
@@ -13,39 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public abstract class AtomicExpression : Expression
- {
- public AtomicExpression(string expression)
- : base(expression)
- {
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- }
+public abstract class AtomicExpression : Expression {
+ public AtomicExpression(string expression)
+ : base(expression) {}
- public override bool IsGroupedExpression
- {
- get { return false; }
- }
- }
+ public override bool IsGroupedExpression => false;
}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/BooleanExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/BooleanExpression.cs
index 216248f..dce6b0f 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/BooleanExpression.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/BooleanExpression.cs
@@ -13,48 +13,37 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class BooleanExpression : AtomicExpression
- {
- private bool? _precompiledValue;
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- public BooleanExpression(string expression)
- : base(expression)
- {
+public class BooleanExpression : AtomicExpression {
+ private bool? _precompiledValue;
- }
+ public BooleanExpression(string expression)
+ : base(expression) {}
- public BooleanExpression(bool value)
- : base(value ? "true" : "false")
- {
- _precompiledValue = value;
- }
+ public BooleanExpression(bool value)
+ : base(value ? "true" : "false") {
+ _precompiledValue = value;
+ }
- public override CompileResult Compile()
- {
- var result = _precompiledValue ?? bool.Parse(ExpressionString);
- return new CompileResult(result, DataType.Boolean);
- }
- }
+ 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
index 7abc32e..1014610 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/CompileResult.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/CompileResult.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,147 +13,108 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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.Globalization;
using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
using OfficeOpenXml.Utils;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class CompileResult
- {
- private static CompileResult _empty = new CompileResult(null, DataType.Empty);
- public static CompileResult Empty
- {
- get { return _empty; }
- }
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- public CompileResult(object result, DataType dataType)
- {
- Result = result;
- DataType = dataType;
- }
+public class CompileResult {
+ private static CompileResult _empty = new(null, DataType.Empty);
- public CompileResult(eErrorType errorType)
- {
- Result = ExcelErrorValue.Create(errorType);
- DataType = DataType.ExcelError;
- }
+ public static CompileResult Empty => _empty;
- 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;
- }
- else
- {
- return r.GetValue(r.Address._fromRow, r.Address._fromCol);
- }
- }
- }
- public double ResultNumeric
- {
- get
- {
- if (IsNumeric)
- {
- return Result == null ? 0 : Convert.ToDouble(Result);
- }
- else if(Result is DateTime)
- {
- return ((DateTime)Result).ToOADate();
- }
- else if(Result is TimeSpan)
- {
- return new DateTime(((TimeSpan)Result).Ticks).ToOADate();
- }
- else if (IsNumericString)
- {
- try
- {
- return double.Parse(Result.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture);
- }
- catch (Exception)
- {
- return 0;
- }
- }
- else if (Result is ExcelDataProvider.IRangeInfo)
- {
- var c = ((ExcelDataProvider.IRangeInfo)Result).FirstOrDefault();
- if (c == null)
- {
- return 0;
- }
- else
- {
- return c.ValueDoubleLogical;
- }
- }
- else
- {
- return 0;
- }
- }
- }
+ public CompileResult(object result, DataType dataType) {
+ Result = result;
+ DataType = dataType;
+ }
- public DataType DataType
- {
- get;
- private set;
- }
-
- public bool IsNumeric
- {
- get
- {
- return DataType == DataType.Decimal || DataType == DataType.Integer || DataType == DataType.Empty || DataType == DataType.Boolean || DataType == DataType.Date;
- }
- }
+ public CompileResult(eErrorType errorType) {
+ Result = ExcelErrorValue.Create(errorType);
+ DataType = DataType.ExcelError;
+ }
- public bool IsNumericString
- {
- get
- {
- return DataType == DataType.String && ConvertUtil.IsNumericString(Result);
- }
- }
+ public CompileResult(ExcelErrorValue errorValue) {
+ Require.Argument(errorValue).IsNotNull("errorValue");
+ Result = errorValue;
+ DataType = DataType.ExcelError;
+ }
- public bool IsResultOfSubtotal { get; set; }
+ public object Result { get; private set; }
- public bool IsHiddenCell { get; 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) {
+ return ((DateTime)Result).ToOADate();
+ }
+ if (Result is TimeSpan) {
+ return new DateTime(((TimeSpan)Result).Ticks).ToOADate();
+ }
+ if (IsNumericString) {
+ try {
+ return double.Parse(Result.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture);
+ } catch (Exception) {
+ return 0;
+ }
+ }
+ if (Result is ExcelDataProvider.IRangeInfo) {
+ var c = ((ExcelDataProvider.IRangeInfo)Result).FirstOrDefault();
+ if (c == null) {
+ return 0;
+ }
+ return c.ValueDoubleLogical;
+ }
+ return 0;
+ }
+ }
+
+ public DataType DataType { get; private set; }
+
+ public bool IsNumeric {
+ get {
+ return DataType == DataType.Decimal
+ || DataType == DataType.Integer
+ || DataType == DataType.Empty
+ || DataType == DataType.Boolean
+ || DataType == DataType.Date;
+ }
+ }
+
+ public bool IsNumericString {
+ get { return 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
index ab313c4..af6f09f 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/CompileResultFactory.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/CompileResultFactory.cs
@@ -13,66 +13,55 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class CompileResultFactory
- {
- public virtual CompileResult Create(object obj)
- {
- if ((obj is ExcelDataProvider.INameInfo))
- {
- obj = ((ExcelDataProvider.INameInfo)obj).Value;
- }
- if (obj is ExcelDataProvider.IRangeInfo)
- {
- obj = ((ExcelDataProvider.IRangeInfo)obj).GetOffset(0, 0);
- }
- if (obj == null) return new CompileResult(null, DataType.Empty);
- if (obj.GetType().Equals(typeof(string)))
- {
- return new CompileResult(obj, DataType.String);
- }
- if (obj.GetType().Equals(typeof(double)) || obj is decimal)
- {
- return new CompileResult(obj, DataType.Decimal);
- }
- if (obj.GetType().Equals(typeof(int)) || obj is long || obj is short)
- {
- return new CompileResult(obj, DataType.Integer);
- }
- if (obj.GetType().Equals(typeof(bool)))
- {
- return new CompileResult(obj, DataType.Boolean);
- }
- if (obj.GetType().Equals(typeof (ExcelErrorValue)))
- {
- return new CompileResult(obj, DataType.ExcelError);
- }
- if (obj.GetType().Equals(typeof(System.DateTime)))
- {
- return new CompileResult(((System.DateTime)obj).ToOADate(), DataType.Date);
- }
- throw new ArgumentException("Non supported type " + obj.GetType().FullName);
- }
+using System;
+
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
+
+public class CompileResultFactory {
+ public virtual CompileResult Create(object obj) {
+ if ((obj is ExcelDataProvider.INameInfo)) {
+ obj = ((ExcelDataProvider.INameInfo)obj).Value;
}
+ if (obj is ExcelDataProvider.IRangeInfo) {
+ obj = ((ExcelDataProvider.IRangeInfo)obj).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
index 01138c0..0eab4ab 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategy.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategy.cs
@@ -13,37 +13,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.CompileStrategy
-{
- public abstract class CompileStrategy
- {
- protected readonly Expression _expression;
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.CompileStrategy;
- public CompileStrategy(Expression expression)
- {
- _expression = expression;
- }
+public abstract class CompileStrategy {
+ protected readonly Expression _expression;
- public abstract Expression Compile();
- }
+ 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
index 9d7fb1f..944a3bf 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategyFactory.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/CompileStrategyFactory.cs
@@ -13,41 +13,31 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
+
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);
- }
- else
- {
- return new DefaultCompileStrategy(expression);
- }
- }
+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
index 3fd8155..27475d1 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/DefaultCompileStrategy.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/DefaultCompileStrategy.cs
@@ -13,38 +13,29 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.CompileStrategy
-{
- public class DefaultCompileStrategy : CompileStrategy
- {
- public DefaultCompileStrategy(Expression expression)
- : base(expression)
- {
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.CompileStrategy;
- }
- public override Expression Compile()
- {
- return _expression.MergeWithNext();
- }
- }
+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
index 26a5263..16a53a4 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/ICompileStrategyFactory.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/ICompileStrategyFactory.cs
@@ -13,30 +13,24 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.CompileStrategy
-{
- public interface ICompileStrategyFactory
- {
- CompileStrategy Create(Expression expression);
- }
+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
index 9bc1134..4403ab8 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/StringConcatStrategy.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/CompileStrategy/StringConcatStrategy.cs
@@ -13,50 +13,41 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.CompileStrategy
-{
- public class StringConcatStrategy : CompileStrategy
- {
- public StringConcatStrategy(Expression expression)
- : base(expression)
- {
-
- }
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.CompileStrategy;
- 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();
- }
+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
index 17a9e0c..00fe9c6 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/ConstantExpressions.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/ConstantExpressions.cs
@@ -1,31 +1,22 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+using System;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public static class ConstantExpressions
- {
- public static Expression Percent
- {
- get { return new ConstantExpression("Percent", () => new CompileResult(0.01, DataType.Decimal)); }
- }
- }
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- public class ConstantExpression : AtomicExpression
- {
- private readonly Func<CompileResult> _factoryMethod;
+public static class ConstantExpressions {
+ public static Expression Percent {
+ get { return new ConstantExpression("Percent", () => new(0.01, DataType.Decimal)); }
+ }
+}
- public ConstantExpression(string title, Func<CompileResult> factoryMethod)
- : base(title)
- {
- _factoryMethod = factoryMethod;
- }
+public class ConstantExpression : AtomicExpression {
+ private readonly Func<CompileResult> _factoryMethod;
- public override CompileResult Compile()
- {
- return _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
index b115b08..4751df3 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/DataType.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/DataType.cs
@@ -13,40 +13,34 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public enum DataType
- {
- Integer,
- Decimal,
- String,
- Boolean,
- Date,
- Time,
- Enumerable,
- LookupArray,
- ExcelAddress,
- ExcelError,
- Empty
- }
+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
index 056efc5..12e9342 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/DateExpression.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/DateExpression.cs
@@ -13,41 +13,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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.Globalization;
-using System.Linq;
-using System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class DateExpression : AtomicExpression
- {
- public DateExpression(string expression)
- : base(expression)
- {
+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 CompileResult(DateTime.FromOADate(date), DataType.Date);
- }
- }
+ 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
index 6e3ba50..9c32645 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/DecimalExpression.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/DecimalExpression.cs
@@ -1,5 +1,5 @@
-using System;
-using System.Collections.Generic;
+using System.Globalization;
+
/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
@@ -15,61 +15,48 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-using System.Globalization;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class DecimalExpression : AtomicExpression
- {
- private readonly double? _compiledValue;
- private readonly bool _negate;
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- public DecimalExpression(string expression)
- : this(expression, false)
- {
-
- }
+public class DecimalExpression : AtomicExpression {
+ private readonly double? _compiledValue;
+ private readonly bool _negate;
- public DecimalExpression(string expression, bool negate)
- : base(expression)
- {
- _negate = negate;
- }
+ public DecimalExpression(string expression)
+ : this(expression, false) {}
- public DecimalExpression(double compiledValue)
- : base(compiledValue.ToString(CultureInfo.InvariantCulture))
- {
- _compiledValue = compiledValue;
- }
+ public DecimalExpression(string expression, bool negate)
+ : base(expression) {
+ _negate = negate;
+ }
- public override CompileResult Compile()
- {
- double result = _compiledValue.HasValue ? _compiledValue.Value : double.Parse(ExpressionString, CultureInfo.InvariantCulture);
- result = _negate ? result * -1 : result;
- return new CompileResult(result, DataType.Decimal);
- }
+ public DecimalExpression(double compiledValue)
+ : base(compiledValue.ToString(CultureInfo.InvariantCulture)) {
+ _compiledValue = compiledValue;
+ }
- public bool IsNegated
- {
- get { return _negate; }
- }
+ public override CompileResult Compile() {
+ double result = _compiledValue.HasValue
+ ? _compiledValue.Value
+ : 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
index 345c915..56b0fa8 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/EnumerableExpression.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/EnumerableExpression.cs
@@ -13,61 +13,47 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class EnumerableExpression : Expression
- {
- public EnumerableExpression()
- : this(new ExpressionCompiler())
- {
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- }
+public class EnumerableExpression : Expression {
+ public EnumerableExpression()
+ : this(new ExpressionCompiler()) {}
- public EnumerableExpression(IExpressionCompiler expressionCompiler)
- {
- _expressionCompiler = expressionCompiler;
- }
+ public EnumerableExpression(IExpressionCompiler expressionCompiler) {
+ _expressionCompiler = expressionCompiler;
+ }
- private readonly IExpressionCompiler _expressionCompiler;
+ private readonly IExpressionCompiler _expressionCompiler;
- public override bool IsGroupedExpression
- {
- get { return false; }
- }
+ public override bool IsGroupedExpression => false;
- public override Expression PrepareForNextChild()
- {
- return this;
- }
+ 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 CompileResult(result, DataType.Enumerable);
- }
+ 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
index 186c726..4f68d2c 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/ExcelAddressExpression.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/ExcelAddressExpression.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,116 +13,101 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-using OfficeOpenXml.FormulaParsing;
using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
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;
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- public ExcelAddressExpression(string expression, ExcelDataProvider excelDataProvider, ParsingContext parsingContext)
- : this(expression, excelDataProvider, parsingContext, new RangeAddressFactory(excelDataProvider), false)
- {
+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, bool negate)
- : this(expression, excelDataProvider, parsingContext, new RangeAddressFactory(excelDataProvider), 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 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
- {
- get { return false; }
- }
+ public override bool IsGroupedExpression => false;
- public override CompileResult Compile()
- {
- if (ParentIsLookupFunction)
- {
- return new CompileResult(ExpressionString, DataType.ExcelAddress);
- }
- else
- {
- return CompileRangeValues();
- }
- }
-
- private CompileResult CompileRangeValues()
- {
- var c = this._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 CompileResult(result, DataType.Enumerable);
- }
- else
- {
- 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(compileResult.ResultNumeric * -1, compileResult.DataType);
- }
- compileResult.IsHiddenCell = cell.IsHiddenRow;
- return compileResult;
- }
-
- public bool IsNegated
- {
- get { return _negate; }
- }
-
+ 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 {
+ get { return _negate; }
+ }
}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/ExcelErrorExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/ExcelErrorExpression.cs
index d25e446..fcf4ddd 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/ExcelErrorExpression.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/ExcelErrorExpression.cs
@@ -13,62 +13,46 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-using OfficeOpenXml.FormulaParsing;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.Utilities;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class ExcelErrorExpression : Expression
- {
- ExcelErrorValue _error;
- public ExcelErrorExpression(string expression, ExcelErrorValue error)
- : base(expression)
- {
- _error = error;
- }
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- public ExcelErrorExpression(ExcelErrorValue error)
- : this(error.ToString(), error)
- {
-
- }
+public class ExcelErrorExpression : Expression {
+ private ExcelErrorValue _error;
- public override bool IsGroupedExpression
- {
- get { return false; }
- }
+ public ExcelErrorExpression(string expression, ExcelErrorValue error)
+ : base(expression) {
+ _error = error;
+ }
- public override CompileResult Compile()
- {
- return new CompileResult(_error, DataType.ExcelError);
- //if (ParentIsLookupFunction)
- //{
- // return new CompileResult(ExpressionString, DataType.ExcelError);
- //}
- //else
- //{
- // return CompileRangeValues();
- //}
- }
- }
+ 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
index 277b78a..e32e3f0 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/Expression.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/Expression.cs
@@ -13,116 +13,97 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
using OfficeOpenXml.FormulaParsing.Excel.Operators;
-using OfficeOpenXml.FormulaParsing.Exceptions;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public abstract class Expression
- {
- public string ExpressionString { get; private set; }
- private readonly List<Expression> _children = new List<Expression>();
- public IEnumerable<Expression> Children { get { return _children; } }
- public Expression Next { get; set; }
- public Expression Prev { get; set; }
- public IOperator Operator { get; set; }
- public abstract bool IsGroupedExpression { get; }
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- public Expression()
- {
+public abstract class Expression {
+ public string ExpressionString { get; private set; }
- }
+ private readonly List<Expression> _children = new();
- public Expression(string expression)
- {
- ExpressionString = expression;
- Operator = null;
- }
+ public IEnumerable<Expression> Children => _children;
- public virtual bool ParentIsLookupFunction
- {
- get;
- set;
- }
+ public Expression Next { get; set; }
- public virtual bool HasChildren
- {
- get { return _children.Any(); }
- }
+ public Expression Prev { get; set; }
- public virtual Expression PrepareForNextChild()
- {
- return this;
- }
+ public IOperator Operator { get; set; }
- 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 abstract bool IsGroupedExpression { get; }
- public virtual Expression MergeWithNext()
- {
- var expression = this;
- 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 Expression() {}
- public abstract CompileResult Compile();
+ 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() {
+ var expression = this;
+ 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
index e92aa75..49a4ecf 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/ExpressionCompiler.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/ExpressionCompiler.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,145 +13,133 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-using OfficeOpenXml.FormulaParsing.Excel.Operators;
using OfficeOpenXml.FormulaParsing.ExpressionGraph.CompileStrategy;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class ExpressionCompiler : IExpressionCompiler
- {
- private IEnumerable<Expression> _expressions;
- private IExpressionConverter _expressionConverter;
- private ICompileStrategyFactory _compileStrategyFactory;
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- public ExpressionCompiler()
- : this(new ExpressionConverter(), new CompileStrategyFactory())
- {
-
- }
+public class ExpressionCompiler : IExpressionCompiler {
+ private IEnumerable<Expression> _expressions;
+ private IExpressionConverter _expressionConverter;
+ private ICompileStrategyFactory _compileStrategyFactory;
- public ExpressionCompiler(IExpressionConverter expressionConverter, ICompileStrategyFactory compileStrategyFactory)
- {
- _expressionConverter = expressionConverter;
- _compileStrategyFactory = compileStrategyFactory;
- }
+ public ExpressionCompiler()
+ : this(new ExpressionConverter(), new 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);
- }
+ public ExpressionCompiler(
+ IExpressionConverter expressionConverter,
+ ICompileStrategyFactory compileStrategyFactory) {
+ _expressionConverter = expressionConverter;
+ _compileStrategyFactory = compileStrategyFactory;
+ }
- 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;
- }
+ public CompileResult Compile(IEnumerable<Expression> expressions) {
+ _expressions = expressions;
+ return PerformCompilation();
+ }
- 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);
- }
+ public CompileResult Compile(
+ string worksheet,
+ int row,
+ int column,
+ IEnumerable<Expression> expressions) {
+ _expressions = expressions;
+ return PerformCompilation(worksheet, row, column);
+ }
- 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;
- }
+ 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
index a3a4248..339b757 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/ExpressionConverter.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/ExpressionConverter.cs
@@ -13,83 +13,73 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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.Globalization;
-using System.Linq;
-using System.Text;
-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;
- }
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- public Expression FromCompileResult(CompileResult compileResult)
- {
- switch (compileResult.DataType)
- {
- case DataType.Integer:
- return compileResult.Result is string
- ? new IntegerExpression(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 DecimalExpression(compileResult.Result.ToString())
- : new DecimalExpression(((double) compileResult.Result));
- case DataType.Boolean:
- return compileResult.Result is string
- ? new BooleanExpression(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 ExcelErrorExpression(compileResult.Result.ToString(),
- ExcelErrorValue.Parse(compileResult.Result.ToString()))
- : new ExcelErrorExpression((ExcelErrorValue) compileResult.Result);
- case DataType.Empty:
- return new IntegerExpression(0); //Added JK
+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;
+ }
- }
- return null;
- }
-
- private static IExpressionConverter _instance;
- public static IExpressionConverter Instance
- {
- get
- {
- if (_instance == null)
- {
- _instance = new ExpressionConverter();
- }
- return _instance;
- }
- }
+ 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
index 8347352..742d50c 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/ExpressionFactory.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/ExpressionFactory.cs
@@ -13,69 +13,63 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-using OfficeOpenXml.FormulaParsing;
+
using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class ExpressionFactory : IExpressionFactory
- {
- private readonly ExcelDataProvider _excelDataProvider;
- private readonly ParsingContext _parsingContext;
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- public ExpressionFactory(ExcelDataProvider excelDataProvider, ParsingContext context)
- {
- _excelDataProvider = excelDataProvider;
- _parsingContext = context;
- }
+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);
- }
- }
+ 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
index 04c6509..d9388aa 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/ExpressionGraph.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/ExpressionGraph.cs
@@ -13,59 +13,52 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class ExpressionGraph
- {
- private List<Expression> _expressions = new List<Expression>();
- public IEnumerable<Expression> Expressions { get { return _expressions; } }
- public Expression Current { get; private set; }
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- public Expression Add(Expression expression)
- {
- _expressions.Add(expression);
- if (Current != null)
- {
- Current.Next = expression;
- expression.Prev = Current;
- }
- Current = expression;
- return expression;
- }
+public class ExpressionGraph {
+ private List<Expression> _expressions = new();
- public void Reset()
- {
- _expressions.Clear();
- Current = null;
- }
+ public IEnumerable<Expression> Expressions => _expressions;
- public void Remove(Expression item)
- {
- if (item == Current)
- {
- Current = item.Prev ?? item.Next;
- }
- _expressions.Remove(item);
- }
+ 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
index 3f77158..de2f384 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/ExpressionGraphBuilder.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/ExpressionGraphBuilder.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,240 +13,185 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
using OfficeOpenXml.FormulaParsing.Excel.Operators;
using OfficeOpenXml.FormulaParsing.Exceptions;
using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-using OfficeOpenXml.FormulaParsing.Excel;
-using OfficeOpenXml.FormulaParsing;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class ExpressionGraphBuilder :IExpressionGraphBuilder
- {
- private readonly ExpressionGraph _graph = new ExpressionGraph();
- private readonly IExpressionFactory _expressionFactory;
- private readonly ParsingContext _parsingContext;
- private int _tokenIndex = 0;
- private bool _negateNextExpression;
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- public ExpressionGraphBuilder(ExcelDataProvider excelDataProvider, ParsingContext parsingContext)
- : this(new ExpressionFactory(excelDataProvider, parsingContext), parsingContext)
- {
+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];
+ IOperator op = null;
+ if (token.TokenType == TokenType.Operator
+ && OperatorsDict.Instance.TryGetValue(token.Value, out 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);
}
-
- 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];
- IOperator op = null;
- if (token.TokenType == TokenType.Operator && OperatorsDict.Instance.TryGetValue(token.Value, out 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;
- }
- }
+ } 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
index ba5aee0..0123e1d 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionArgumentExpression.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/FunctionArgumentExpression.cs
@@ -13,62 +13,45 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class FunctionArgumentExpression : GroupExpression
- {
- private readonly Expression _function;
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- public FunctionArgumentExpression(Expression function)
- : base(false)
- {
- _function = function;
- }
+public class FunctionArgumentExpression : GroupExpression {
+ private readonly Expression _function;
- public override bool ParentIsLookupFunction
- {
- get
- {
- return base.ParentIsLookupFunction;
- }
- set
- {
- base.ParentIsLookupFunction = value;
- foreach (var child in Children)
- {
- child.ParentIsLookupFunction = value;
- }
- }
- }
+ public FunctionArgumentExpression(Expression function)
+ : base(false) {
+ _function = function;
+ }
- public override bool IsGroupedExpression
- {
- get { return false; }
- }
-
- public override Expression PrepareForNextChild()
- {
- return _function.PrepareForNextChild();
- }
+ 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
index 40a8544..ebc2918 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/DefaultCompiler.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/DefaultCompiler.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,57 +13,45 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
using OfficeOpenXml.FormulaParsing.Excel;
using OfficeOpenXml.FormulaParsing.Excel.Functions;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers
-{
- public class DefaultCompiler : FunctionCompiler
- {
- public DefaultCompiler(ExcelFunction function)
- : base(function)
- {
+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);
- }
+ 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
index ffa4cac..303821a 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/ErrorHandlingFunctionCompiler.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/ErrorHandlingFunctionCompiler.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,59 +13,46 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
using OfficeOpenXml.FormulaParsing.Excel.Functions;
using OfficeOpenXml.FormulaParsing.Exceptions;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers
-{
- public class ErrorHandlingFunctionCompiler : FunctionCompiler
- {
- public ErrorHandlingFunctionCompiler(ExcelFunction function)
- : base(function)
- {
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
- }
- 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 != null ? arg.Result : null, 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);
- }
+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 != null ? arg.Result : null, 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
index 63a8b22..cb164b0 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompiler.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompiler.cs
@@ -13,63 +13,48 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using System.Collections;
using OfficeOpenXml.FormulaParsing.Utilities;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers
-{
- public abstract class FunctionCompiler
- {
- protected ExcelFunction Function
- {
- get;
- private set;
- }
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
- public FunctionCompiler(ExcelFunction function)
- {
- Require.That(function).Named("function").IsNotNull();
- Function = function;
- }
+public abstract class FunctionCompiler {
+ protected ExcelFunction Function { get; private set; }
- protected void BuildFunctionArguments(object result, List<FunctionArgument> args)
- {
- if (result is IEnumerable<object> && !(result is ExcelDataProvider.IRangeInfo))
- {
- var argList = new List<FunctionArgument>();
- var objects = result as IEnumerable<object>;
- foreach (var arg in objects)
- {
- BuildFunctionArguments(arg, argList);
- }
- args.Add(new FunctionArgument(argList));
- }
- else
- {
- args.Add(new FunctionArgument(result));
- }
- }
+ public FunctionCompiler(ExcelFunction function) {
+ Require.That(function).Named("function").IsNotNull();
+ Function = function;
+ }
- public abstract CompileResult Compile(IEnumerable<Expression> children, ParsingContext context);
+ protected void BuildFunctionArguments(object result, List<FunctionArgument> args) {
+ if (result is IEnumerable<object> && !(result is ExcelDataProvider.IRangeInfo)) {
+ var argList = new List<FunctionArgument>();
+ var objects = result as IEnumerable<object>;
+ 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
index 1bf7693..0f54dcc 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompilerFactory.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/FunctionCompilerFactory.cs
@@ -13,55 +13,55 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
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 Dictionary<Type, FunctionCompiler>();
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
- 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")));
- }
+public class FunctionCompilerFactory {
+ private readonly Dictionary<Type, FunctionCompiler> _specialCompilers = new();
- 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);
- }
+ 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
index a409632..e809ea5 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfErrorFunctionCompiler.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfErrorFunctionCompiler.cs
@@ -1,48 +1,35 @@
-using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
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();
-
- }
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
- 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 FunctionArgument(lastChild.Compile().Result));
- }
- else
- {
- args.Add(new FunctionArgument(result.Result));
- }
-
- }
- catch (ExcelErrorValueException)
- {
- args.Add(new FunctionArgument(lastChild.Compile().Result));
- }
- return Function.Execute(args, context);
- }
+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
index ffe70ad..0818ce5 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfFunctionCompiler.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfFunctionCompiler.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,102 +13,92 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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 System.Text;
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");
- }
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
- 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)
- {
- v = ((ExcelDataProvider.INameInfo)v).Value;
- }
-
- if (v is ExcelDataProvider.IRangeInfo)
- {
- var r=((ExcelDataProvider.IRangeInfo)v);
- if(r.GetNCells()>1)
- {
- throw(new ArgumentException("Logical can't be more than one cell"));
- }
- v = r.GetOffset(0, 0);
- }
- bool boolVal;
- if(v is bool)
- {
- boolVal = (bool)v;
- }
- else
- {
- if(OfficeOpenXml.Utils.ConvertUtil.IsNumeric(v))
- {
- boolVal = OfficeOpenXml.Utils.ConvertUtil.GetValueDouble(v)!=0;
- }
- else
- {
- throw (new ArgumentException("Invalid logical test"));
- }
- }
- /**** End Handle names and ranges ****/
-
- args.Add(new FunctionArgument(boolVal));
- if (boolVal)
- {
- var val = children.ElementAt(1).Compile().Result;
- args.Add(new FunctionArgument(val));
- args.Add(new FunctionArgument(null));
- }
- else
- {
- var val = children.ElementAt(2).Compile().Result;
- args.Add(new FunctionArgument(null));
- args.Add(new FunctionArgument(val));
- }
- return Function.Execute(args, context);
- }
+/// <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) {
+ v = ((ExcelDataProvider.INameInfo)v).Value;
+ }
+
+ if (v is ExcelDataProvider.IRangeInfo) {
+ var r = ((ExcelDataProvider.IRangeInfo)v);
+ if (r.GetNCells() > 1) {
+ throw (new ArgumentException("Logical can't be more than one cell"));
+ }
+ v = r.GetOffset(0, 0);
+ }
+ bool boolVal;
+ if (v is bool) {
+ boolVal = (bool)v;
+ } 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
index ecfff31..55f15b2 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfNaFunctionCompiler.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/IfNaFunctionCompiler.cs
@@ -1,46 +1,33 @@
-using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.Excel.Functions;
using OfficeOpenXml.FormulaParsing.Exceptions;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers
-{
- public class IfNaFunctionCompiler : FunctionCompiler
- {
- public IfNaFunctionCompiler(ExcelFunction function)
- :base(function)
- {
-
- }
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
- 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 FunctionArgument(lastChild.Compile().Result));
- }
- else
- {
- args.Add(new FunctionArgument(result.Result));
- }
+public class IfNaFunctionCompiler : FunctionCompiler {
+ public IfNaFunctionCompiler(ExcelFunction function)
+ : base(function) {}
- }
- catch (ExcelErrorValueException)
- {
- args.Add(new FunctionArgument(lastChild.Compile().Result));
- }
- return Function.Execute(args, context);
- }
+ 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
index 9440594..a350504 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/LookupFunctionCompiler.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/FunctionCompilers/LookupFunctionCompiler.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,56 +13,44 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
using OfficeOpenXml.FormulaParsing.Excel.Functions;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers
-{
- public class LookupFunctionCompiler : FunctionCompiler
- {
- public LookupFunctionCompiler(ExcelFunction function)
- : base(function)
- {
+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 != null ? arg.Result : null, args);
- }
- return Function.Execute(args, context);
- }
+ 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 != null ? arg.Result : null, args);
}
+ return Function.Execute(args, context);
+ }
}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/FunctionExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/FunctionExpression.cs
index 24193ca..0f39bd5 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/FunctionExpression.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/FunctionExpression.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,122 +13,98 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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.Globalization;
+
using System.Linq;
-using System.Text;
-using OfficeOpenXml.FormulaParsing.Excel;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
using OfficeOpenXml.FormulaParsing.Exceptions;
using OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers;
-using OfficeOpenXml.Utils;
-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 FunctionCompilerFactory(parsingContext.Configuration.FunctionRepository);
- _isNegated = isNegated;
- base.AddChild(new FunctionArgumentExpression(this));
+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));
}
-
- 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 CompileResult(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 CompileResult(ExcelErrorValue.Create(eErrorType.Value), DataType.ExcelError);
- }
- return new CompileResult(result.ResultNumeric * -1, result.DataType);
- }
- return result;
- }
- catch (ExcelErrorValueException e)
- {
- if (_parsingContext.Debug)
- {
- _parsingContext.Configuration.Logger.Log(_parsingContext, e);
- }
- return new CompileResult(e.ErrorValue, DataType.ExcelError);
- }
-
+ 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);
}
-
- public override Expression PrepareForNextChild()
- {
- return base.AddChild(new FunctionArgumentExpression(this));
- }
-
- public override bool HasChildren
- {
- get
- {
- return (Children.Any() && Children.First().Children.Any());
- }
- }
-
- public override Expression AddChild(Expression child)
- {
- Children.Last().AddChild(child);
- return child;
- }
+ 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
index e8dba20..54df131 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/GroupExpression.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/GroupExpression.cs
@@ -13,65 +13,45 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class GroupExpression : Expression
- {
- public GroupExpression(bool isNegated)
- : this(isNegated, new ExpressionCompiler())
- {
+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;
- }
+ public GroupExpression(bool isNegated, IExpressionCompiler expressionCompiler) {
+ _expressionCompiler = expressionCompiler;
+ _isNegated = isNegated;
+ }
- private readonly IExpressionCompiler _expressionCompiler;
- private readonly bool _isNegated;
+ private readonly IExpressionCompiler _expressionCompiler;
+ private readonly bool _isNegated;
-
- public override CompileResult Compile()
- {
- var result = _expressionCompiler.Compile(Children);
- if (result.IsNumeric && _isNegated)
- {
- return new CompileResult(result.ResultNumeric * -1, result.DataType);
- }
- return result;
- }
-
- public override bool IsGroupedExpression
- {
- get { return true; }
- }
-
- public bool IsNegated
- {
- get { return _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
index 3fb39ee..c7ef8dd 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/IExpressionCompiler.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/IExpressionCompiler.cs
@@ -13,30 +13,26 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public interface IExpressionCompiler
- {
- CompileResult Compile(IEnumerable<Expression> expressions);
- }
+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
index 660df97..0a1b901 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/IExpressionConverter.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/IExpressionConverter.cs
@@ -13,31 +13,26 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public interface IExpressionConverter
- {
- StringExpression ToStringExpression(Expression expression);
- Expression FromCompileResult(CompileResult compileResult);
- }
+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
index 944b118..2e89b2a 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/IExpressionFactory.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/IExpressionFactory.cs
@@ -13,31 +13,26 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
+
using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public interface IExpressionFactory
- {
- Expression Create(Token token);
- }
+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
index cb9e122..2fad667 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/IExpressionGraphBuilder.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/IExpressionGraphBuilder.cs
@@ -13,31 +13,27 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public interface IExpressionGraphBuilder
- {
- ExpressionGraph Build(IEnumerable<Token> tokens);
- }
+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
index 4e57168..973b523 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/IntegerExpression.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/IntegerExpression.cs
@@ -13,63 +13,51 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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.Globalization;
-using System.Linq;
-using System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class IntegerExpression : AtomicExpression
- {
- private readonly double? _compiledValue;
- private readonly bool _negate;
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- public IntegerExpression(string expression)
- : this(expression, false)
- {
+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(string expression, bool negate)
+ : base(expression) {
+ _negate = negate;
+ }
- public IntegerExpression(double val)
- : base(val.ToString(CultureInfo.InvariantCulture))
- {
- _compiledValue = Math.Floor(val);
- }
+ public IntegerExpression(double val)
+ : base(val.ToString(CultureInfo.InvariantCulture)) {
+ _compiledValue = Math.Floor(val);
+ }
- public override CompileResult Compile()
- {
- double result = _compiledValue.HasValue ? _compiledValue.Value : double.Parse(ExpressionString, CultureInfo.InvariantCulture);
- result = _negate ? result*-1 : result;
- return new CompileResult(result, DataType.Integer);
- }
+ public override CompileResult Compile() {
+ double result = _compiledValue.HasValue
+ ? _compiledValue.Value
+ : double.Parse(ExpressionString, CultureInfo.InvariantCulture);
+ result = _negate ? result * -1 : result;
+ return new(result, DataType.Integer);
+ }
- public bool IsNegated
- {
- get { return _negate; }
- }
-
- }
+ public bool IsNegated => _negate;
}
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/NamedValueExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/NamedValueExpression.cs
index 3c54bc8..080f8a0 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/NamedValueExpression.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/NamedValueExpression.cs
@@ -13,78 +13,62 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
+using OfficeOpenXml.FormulaParsing.Exceptions;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class NamedValueExpression : AtomicExpression
- {
- public NamedValueExpression(string expression, ParsingContext parsingContext)
- : base(expression)
- {
- _parsingContext = parsingContext;
- }
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- private readonly ParsingContext _parsingContext;
+public class NamedValueExpression : AtomicExpression {
+ public NamedValueExpression(string expression, ParsingContext parsingContext)
+ : base(expression) {
+ _parsingContext = parsingContext;
+ }
- public override CompileResult Compile()
- {
- var c = this._parsingContext.Scopes.Current;
- var name = _parsingContext.ExcelDataProvider.GetName(c.Address.Worksheet, ExpressionString);
- //var result = _parsingContext.Parser.Parse(value.ToString());
+ private readonly ParsingContext _parsingContext;
- if (name == null)
- {
- throw (new Exceptions.ExcelErrorValueException(ExcelErrorValue.Create(eErrorType.Name)));
- }
- if (name.Value==null)
- {
- return null;
- }
- if (name.Value is ExcelDataProvider.IRangeInfo)
- {
- var range = (ExcelDataProvider.IRangeInfo)name.Value;
- if (range.IsMulti)
- {
- return new CompileResult(name.Value, DataType.Enumerable);
- }
- else
- {
- if (range.IsEmpty)
- {
- return null;
- }
- var factory = new CompileResultFactory();
- return factory.Create(range.First().Value);
- }
- }
- else
- {
- var factory = new CompileResultFactory();
- return factory.Create(name.Value);
- }
+ 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());
-
-
- //return new CompileResultFactory().Create(result);
- }
+ if (name == null) {
+ throw (new ExcelErrorValueException(ExcelErrorValue.Create(eErrorType.Name)));
}
+ if (name.Value == null) {
+ return null;
+ }
+ if (name.Value is ExcelDataProvider.IRangeInfo) {
+ var range = (ExcelDataProvider.IRangeInfo)name.Value;
+ if (range.IsMulti) {
+ return new(name.Value, 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
index 52895cb..f3b29de 100644
--- a/EPPlus/FormulaParsing/ExpressionGraph/StringExpression.cs
+++ b/EPPlus/FormulaParsing/ExpressionGraph/StringExpression.cs
@@ -13,39 +13,29 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
-{
- public class StringExpression : AtomicExpression
- {
- public StringExpression(string expression)
- : base(expression)
- {
+namespace OfficeOpenXml.FormulaParsing.ExpressionGraph;
- }
+public class StringExpression : AtomicExpression {
+ public StringExpression(string expression)
+ : base(expression) {}
- public override CompileResult Compile()
- {
- return new CompileResult(ExpressionString, DataType.String);
- }
- }
+ public override CompileResult Compile() {
+ return new(ExpressionString, DataType.String);
+ }
}
diff --git a/EPPlus/FormulaParsing/FormulaParser.cs b/EPPlus/FormulaParsing/FormulaParser.cs
index a7ad2d8..faa0536 100644
--- a/EPPlus/FormulaParsing/FormulaParser.cs
+++ b/EPPlus/FormulaParsing/FormulaParser.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,214 +13,186 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
using OfficeOpenXml.FormulaParsing.Excel.Functions;
using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing.Utilities;
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;
+namespace OfficeOpenXml.FormulaParsing;
- public FormulaParser(ExcelDataProvider excelDataProvider)
- : this(excelDataProvider, ParsingContext.Create())
- {
-
- }
+public class FormulaParser {
+ private readonly ParsingContext _parsingContext;
+ private readonly ExcelDataProvider _excelDataProvider;
- public FormulaParser(ExcelDataProvider excelDataProvider, ParsingContext parsingContext)
- {
- parsingContext.Parser = this;
- parsingContext.ExcelDataProvider = excelDataProvider;
- parsingContext.NameValueProvider = new EpplusNameValueProvider(excelDataProvider);
- parsingContext.RangeAddressFactory = new RangeAddressFactory(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 FormulaParser(ExcelDataProvider excelDataProvider)
+ : this(excelDataProvider, ParsingContext.Create()) {}
- 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;
- }
+ 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());
+ });
+ }
- private ILexer _lexer;
- private IExpressionGraphBuilder _graphBuilder;
- private IExpressionCompiler _compiler;
+ 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;
+ }
- public ILexer Lexer { get { return _lexer; } }
- public IEnumerable<string> FunctionNames { get { return _parsingContext.Configuration.FunctionRepository.FunctionNames; } }
+ private ILexer _lexer;
+ private IExpressionGraphBuilder _graphBuilder;
+ private IExpressionCompiler _compiler;
- 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;
- }
- }
+ public ILexer Lexer => _lexer;
- 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;
- }
- else
- {
- 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 IEnumerable<string> FunctionNames {
+ get { return _parsingContext.Configuration.FunctionRepository.FunctionNames; }
+ }
- 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);
- }
- else
- {
- 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;
- }
- }
+ 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
index 51a5234..9d7dc65 100644
--- a/EPPlus/FormulaParsing/FormulaParserManager.cs
+++ b/EPPlus/FormulaParsing/FormulaParserManager.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,94 +13,85 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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.IO;
using System.Linq;
-using System.Text;
using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using OfficeOpenXml.FormulaParsing.Logging;
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;
- }
+namespace OfficeOpenXml.FormulaParsing;
- /// <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>
+/// Provides access to various functionality regarding
+/// excel formula evaluation.
+/// </summary>
+public class FormulaParserManager {
+ private readonly FormulaParser _parser;
- /// <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));
- }
+ internal FormulaParserManager(FormulaParser parser) {
+ Require.That(parser).Named("parser").IsNotNull();
+ _parser = parser;
+ }
- /// <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, System.StringComparison.Ordinal));
- return fnList;
- }
+ /// <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>
- /// 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);
- }
+ /// <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));
+ }
- // Praveen's Parser Support
- public ExpressionGraph.ExpressionGraph ParseToGraph(string formula)
- {
- return _parser.ParseToGraph(formula);
- }
- }
+ /// <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
index c93bf0d..0a227ae 100644
--- a/EPPlus/FormulaParsing/INameValueProvider.cs
+++ b/EPPlus/FormulaParsing/INameValueProvider.cs
@@ -1,16 +1,9 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+namespace OfficeOpenXml.FormulaParsing;
-namespace OfficeOpenXml.FormulaParsing
-{
- public interface INameValueProvider
- {
- bool IsNamedValue(string key, string worksheet);
+public interface INameValueProvider {
+ bool IsNamedValue(string key, string worksheet);
- object GetNamedValue(string key);
+ object GetNamedValue(string key);
- void Reload();
- }
+ void Reload();
}
diff --git a/EPPlus/FormulaParsing/IParsingLifetimeEventHandler.cs b/EPPlus/FormulaParsing/IParsingLifetimeEventHandler.cs
index 1c6d31b..52fc794 100644
--- a/EPPlus/FormulaParsing/IParsingLifetimeEventHandler.cs
+++ b/EPPlus/FormulaParsing/IParsingLifetimeEventHandler.cs
@@ -1,12 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+namespace OfficeOpenXml.FormulaParsing;
-namespace OfficeOpenXml.FormulaParsing
-{
- public interface IParsingLifetimeEventHandler
- {
- void ParsingCompleted();
- }
+public interface IParsingLifetimeEventHandler {
+ void ParsingCompleted();
}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/ILexer.cs b/EPPlus/FormulaParsing/LexicalAnalysis/ILexer.cs
index 943fab4..ec3aef5 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/ILexer.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/ILexer.cs
@@ -13,31 +13,28 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis
-{
- public interface ILexer
- {
- IEnumerable<Token> Tokenize(string input);
- IEnumerable<Token> Tokenize(string input, string worksheet);
- }
+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
index 3a6ad48..488d4aa 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/ISourceCodeTokenizer.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/ISourceCodeTokenizer.cs
@@ -13,30 +13,26 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis
-{
- public interface ISourceCodeTokenizer
- {
- IEnumerable<Token> Tokenize(string input, string worksheet);
- }
+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
index 55e1a86..9f73dba 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/ISyntacticAnalyzer.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/ISyntacticAnalyzer.cs
@@ -13,30 +13,26 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis
-{
- public interface ISyntacticAnalyzer
- {
- void Analyze(IEnumerable<Token> tokens);
- }
+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
index d330ffe..ab5b170 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/ITokenFactory.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/ITokenFactory.cs
@@ -13,32 +13,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-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);
- }
+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
index 6a7f6c4..1028a1c 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/ITokenIndexProvider.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/ITokenIndexProvider.cs
@@ -1,14 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis
-{
- public interface ITokenIndexProvider
- {
- int Index { get; }
+public interface ITokenIndexProvider {
+ int Index { get; }
- void MoveIndexPointerForward();
- }
+ void MoveIndexPointerForward();
}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/ITokenSeparatorProvider.cs b/EPPlus/FormulaParsing/LexicalAnalysis/ITokenSeparatorProvider.cs
index db3610b..91fb6b9 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/ITokenSeparatorProvider.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/ITokenSeparatorProvider.cs
@@ -13,35 +13,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis
-{
- public interface ITokenSeparatorProvider
- {
- IDictionary<string, Token> Tokens { get; }
+namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
- bool IsOperator(string item);
+public interface ITokenSeparatorProvider {
+ IDictionary<string, Token> Tokens { get; }
- bool IsPossibleLastPartOfMultipleCharOperator(string part);
+ bool IsOperator(string item);
- }
+ bool IsPossibleLastPartOfMultipleCharOperator(string part);
}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/Lexer.cs b/EPPlus/FormulaParsing/LexicalAnalysis/Lexer.cs
index bc5ea18..35f4e8f 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/Lexer.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/Lexer.cs
@@ -13,56 +13,50 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
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())
- {
+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;
- }
+ public Lexer(ISourceCodeTokenizer tokenizer, ISyntacticAnalyzer analyzer) {
+ _tokenizer = tokenizer;
+ _analyzer = analyzer;
+ }
- private readonly ISourceCodeTokenizer _tokenizer;
- private readonly ISyntacticAnalyzer _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;
- }
- }
+ 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
index b8265a1..01e9bf9 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/SourceCodeTokenizer.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/SourceCodeTokenizer.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,341 +13,286 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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.Globalization;
using System.Linq;
-using System.Text;
using System.Text.RegularExpressions;
using OfficeOpenXml.FormulaParsing.Excel.Functions;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis
-{
- public class SourceCodeTokenizer : ISourceCodeTokenizer
- {
- public static ISourceCodeTokenizer Default
- {
- get { return new SourceCodeTokenizer(FunctionNameProvider.Empty, NameValueProvider.Empty); }
- }
- public SourceCodeTokenizer(IFunctionNameProvider functionRepository, INameValueProvider nameValueProvider)
- : this(new TokenFactory(functionRepository, nameValueProvider), new TokenSeparatorProvider())
- {
+namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
- }
- public SourceCodeTokenizer(ITokenFactory tokenFactory, ITokenSeparatorProvider tokenProvider)
- {
- _tokenFactory = tokenFactory;
- _tokenProvider = tokenProvider;
- }
+public class SourceCodeTokenizer : ISourceCodeTokenizer {
+ public static ISourceCodeTokenizer Default =>
+ new SourceCodeTokenizer(FunctionNameProvider.Empty, NameValueProvider.Empty);
- private readonly ITokenSeparatorProvider _tokenProvider;
- private readonly ITokenFactory _tokenFactory;
+ public SourceCodeTokenizer(
+ IFunctionNameProvider functionRepository,
+ INameValueProvider nameValueProvider)
+ : this(
+ new TokenFactory(functionRepository, nameValueProvider),
+ new TokenSeparatorProvider()) {}
- 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);
+ public SourceCodeTokenizer(ITokenFactory tokenFactory, ITokenSeparatorProvider tokenProvider) {
+ _tokenFactory = tokenFactory;
+ _tokenProvider = tokenProvider;
+ }
- bool isSingleQuoteString = false;
- for (int i = 0; i<context.FormulaChars.Length;i++)
- {
- var c = context.FormulaChars[i];
- Token tokenSeparator;
- if (CharIsTokenSeparator(c, out 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 Token(string.Empty, TokenType.StringContent)
- : new Token(context.CurrentToken, TokenType.StringContent));
- }
- context.AddToken(new Token("\"", 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 Token("-", TokenType.Negator));
- continue;
- }
- }
- context.AddToken(tokenSeparator);
- context.NewToken();
- continue;
- }
- context.AppendToCurrentToken(c);
- }
- if (context.CurrentTokenHasValue)
- {
- context.AddToken(CreateToken(context, worksheet));
- }
+ private readonly ITokenSeparatorProvider _tokenProvider;
+ private readonly ITokenFactory _tokenFactory;
- CleanupTokens(context, _tokenProvider.Tokens);
+ public IEnumerable<Token> Tokenize(string input) {
+ return Tokenize(input, null);
+ }
- 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 Token("-", 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 Token("-", 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;
- }
+ 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];
+ Token tokenSeparator;
+ if (CharIsTokenSeparator(c, out 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
index 0666220..e771aaf 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/SyntacticAnalyzer.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/SyntacticAnalyzer.cs
@@ -13,90 +13,77 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
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);
- }
+namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
- 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");
- }
- }
+public class SyntacticAnalyzer : ISyntacticAnalyzer {
+ private class AnalyzingContext {
+ public int NumberOfOpenedParentheses { get; set; }
- private void EnsureParenthesesAreWellFormed(Token token, AnalyzingContext context)
- {
- if (token.TokenType == TokenType.OpeningParenthesis)
- {
- context.NumberOfOpenedParentheses++;
- }
- else if (token.TokenType == TokenType.ClosingParenthesis)
- {
- context.NumberOfClosedParentheses++;
- }
- }
+ public int NumberOfClosedParentheses { get; set; }
- 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++;
- }
- }
+ 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
index 1de9b99..f3faa0c 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/Token.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/Token.cs
@@ -13,63 +13,49 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis
-{
- public class Token
- {
- public Token(string token, TokenType tokenType)
- {
- Value = token;
- TokenType = tokenType;
- }
+namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
- public string Value { get; internal set; }
+public class Token {
+ public Token(string token, TokenType tokenType) {
+ Value = token;
+ TokenType = tokenType;
+ }
- public TokenType TokenType { get; internal set; }
+ public string Value { get; internal set; }
- public void Append(string stringToAppend)
- {
- Value += stringToAppend;
- }
+ public TokenType TokenType { get; internal set; }
- public bool IsNegated { get; private set; }
-
- public void Negate()
- {
+ public void Append(string stringToAppend) {
+ Value += stringToAppend;
+ }
- if (
- TokenType == TokenType.Decimal
- ||
- TokenType == TokenType.Integer
- ||
- TokenType == TokenType.ExcelAddress)
- {
- IsNegated = true;
- }
- }
- public override string ToString()
- {
- return TokenType.ToString() + ", " + Value;
- }
+ 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
index 3817df2..96c87a3 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenFactory.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/TokenFactory.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,155 +13,129 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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;
using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing;
using OfficeOpenXml.FormulaParsing.Excel.Functions;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
using OfficeOpenXml.FormulaParsing.Utilities;
-using OfficeOpenXml;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis
-{
- public class TokenFactory : ITokenFactory
- {
- public TokenFactory(IFunctionNameProvider functionRepository, INameValueProvider nameValueProvider)
- : this(new TokenSeparatorProvider(), nameValueProvider, functionRepository)
- {
+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;
- }
+ 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)
- {
- Token tokenSeparator = null;
- if (_tokenSeparatorProvider.Tokens.TryGetValue(token, out tokenSeparator))
- {
- return tokenSeparator;
- }
- var tokenList = (IList<Token>)tokens;
- //Address with worksheet-string before /JK
- if (token.StartsWith("!") && tokenList[tokenList.Count-1].TokenType == TokenType.String)
- {
- string addr = "";
- var i = tokenList.Count - 2;
- if (i > 0)
- {
- 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);
+ private readonly ITokenSeparatorProvider _tokenSeparatorProvider;
+ private readonly IFunctionNameProvider _functionNameProvider;
+ private readonly INameValueProvider _nameValueProvider;
- return new Token(addr + token, TokenType.ExcelAddress);
- }
- else
- {
- throw(new ArgumentException(string.Format("Invalid formula token sequence near {0}",token)));
- }
-
- }
+ public Token Create(IEnumerable<Token> tokens, string token) {
+ return Create(tokens, token, null);
+ }
- if (tokens.Any() && tokens.Last().TokenType == TokenType.String)
- {
- return new Token(token, TokenType.StringContent);
- }
- if (!string.IsNullOrEmpty(token))
- {
- token = token.Trim();
- }
- if (Regex.IsMatch(token, RegexConstants.Decimal))
- {
- return new Token(token, TokenType.Decimal);
- }
- if(Regex.IsMatch(token, RegexConstants.Integer))
- {
- return new Token(token, TokenType.Integer);
- }
- if (Regex.IsMatch(token, RegexConstants.Boolean, RegexOptions.IgnoreCase))
- {
- return new Token(token, TokenType.Boolean);
- }
- if (token.ToUpper(CultureInfo.InvariantCulture).Contains("#REF!"))
- {
- return new Token(token, TokenType.InvalidReference);
- }
- if (token.ToUpper(CultureInfo.InvariantCulture) == "#NUM!")
- {
- return new Token(token, TokenType.NumericError);
- }
- if (token.ToUpper(CultureInfo.InvariantCulture) == "#VALUE!")
- {
- return new Token(token, TokenType.ValueDataTypeError);
- }
- if (token.ToUpper(CultureInfo.InvariantCulture) == "#NULL!")
- {
- return new Token(token, TokenType.Null);
- }
- if (_nameValueProvider != null && _nameValueProvider.IsNamedValue(token, worksheet))
- {
- return new Token(token, TokenType.NameValue);
- }
- if (_functionNameProvider.IsFunctionName(token))
- {
- return new Token(token, TokenType.Function);
- }
- if (tokenList.Count > 0 && tokenList[tokenList.Count - 1].TokenType == TokenType.OpeningEnumerable)
- {
- return new Token(token, TokenType.Enumerable);
- }
- var at = OfficeOpenXml.ExcelAddressBase.IsValid(token);
- if (at==ExcelAddressBase.AddressType.InternalAddress)
- {
- return new Token(token.ToUpper(CultureInfo.InvariantCulture), TokenType.ExcelAddress);
- }
- return new Token(token, TokenType.Unrecognized);
-
- }
-
- public Token Create(string token, TokenType explicitTokenType)
- {
- return new Token(token, explicitTokenType);
- }
+ public Token Create(IEnumerable<Token> tokens, string token, string worksheet) {
+ Token tokenSeparator = null;
+ if (_tokenSeparatorProvider.Tokens.TryGetValue(token, out tokenSeparator)) {
+ return tokenSeparator;
}
+ var tokenList = (IList<Token>)tokens;
+ //Address with worksheet-string before /JK
+ if (token.StartsWith("!") && tokenList[tokenList.Count - 1].TokenType == TokenType.String) {
+ string addr = "";
+ var i = tokenList.Count - 2;
+ if (i > 0) {
+ 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/TokenHandler.cs b/EPPlus/FormulaParsing/LexicalAnalysis/TokenHandler.cs
index 8e86169..8c2a271 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenHandler.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/TokenHandler.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,146 +13,120 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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-12-28
*******************************************************************************/
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis.TokenSeparatorHandlers;
using System.Text.RegularExpressions;
+using OfficeOpenXml.FormulaParsing.LexicalAnalysis.TokenSeparatorHandlers;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis
-{
- public class TokenHandler : ITokenIndexProvider
- {
- public TokenHandler(TokenizerContext context, ITokenFactory tokenFactory, ITokenSeparatorProvider tokenProvider)
- {
- _context = context;
- _tokenFactory = tokenFactory;
- _tokenProvider = tokenProvider;
- }
-
- private readonly TokenizerContext _context;
- private readonly ITokenSeparatorProvider _tokenProvider;
- private readonly ITokenFactory _tokenFactory;
- private int _tokenIndex = -1;
-
- public string Worksheet { get; set; }
-
- public bool HasMore()
- {
- return _tokenIndex < (_context.FormulaChars.Length - 1);
- }
-
- public void Next()
- {
- _tokenIndex++;
- Handle();
- }
-
- private void Handle()
- {
- var c = _context.FormulaChars[_tokenIndex];
- Token tokenSeparator;
- if (CharIsTokenSeparator(c, out tokenSeparator))
- {
- if (TokenSeparatorHandler.Handle(c, tokenSeparator, _context, this))
- {
- return;
- }
-
- 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 Token("-", TokenType.Negator));
- return;
- }
- }
- _context.AddToken(tokenSeparator);
- _context.NewToken();
- return;
- }
- _context.AppendToCurrentToken(c);
- }
-
- 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;
- }
-
-
-
- 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 Token CreateToken(TokenizerContext context, string worksheet)
- {
- if (context.CurrentToken == "-")
- {
- if (context.LastToken == null && context.LastToken.TokenType == TokenType.Operator)
- {
- return new Token("-", TokenType.Negator);
- }
- }
- return _tokenFactory.Create(context.Result, context.CurrentToken, worksheet);
- }
-
- int ITokenIndexProvider.Index
- {
- get { return _tokenIndex; }
- }
-
-
- void ITokenIndexProvider.MoveIndexPointerForward()
- {
- _tokenIndex++;
- }
+namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis {
+ public class TokenHandler : ITokenIndexProvider {
+ public TokenHandler(
+ TokenizerContext context,
+ ITokenFactory tokenFactory,
+ ITokenSeparatorProvider tokenProvider) {
+ _context = context;
+ _tokenFactory = tokenFactory;
+ _tokenProvider = tokenProvider;
}
+
+ private readonly TokenizerContext _context;
+ private readonly ITokenSeparatorProvider _tokenProvider;
+ private readonly ITokenFactory _tokenFactory;
+ private int _tokenIndex = -1;
+
+ public string Worksheet { get; set; }
+
+ public bool HasMore() {
+ return _tokenIndex < (_context.FormulaChars.Length - 1);
+ }
+
+ public void Next() {
+ _tokenIndex++;
+ Handle();
+ }
+
+ private void Handle() {
+ var c = _context.FormulaChars[_tokenIndex];
+ Token tokenSeparator;
+ if (CharIsTokenSeparator(c, out tokenSeparator)) {
+ if (TokenSeparatorHandler.Handle(c, tokenSeparator, _context, this)) {
+ return;
+ }
+
+ 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 Token("-", TokenType.Negator));
+ return;
+ }
+ }
+ _context.AddToken(tokenSeparator);
+ _context.NewToken();
+ return;
+ }
+ _context.AppendToCurrentToken(c);
+ }
+
+ 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;
+ }
+
+ 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 Token CreateToken(TokenizerContext context, string worksheet) {
+ if (context.CurrentToken == "-") {
+ if (context.LastToken == null && context.LastToken.TokenType == TokenType.Operator) {
+ return new Token("-", TokenType.Negator);
+ }
+ }
+ return _tokenFactory.Create(context.Result, context.CurrentToken, worksheet);
+ }
+
+ int ITokenIndexProvider.Index {
+ get { return _tokenIndex; }
+ }
+
+ void ITokenIndexProvider.MoveIndexPointerForward() {
+ _tokenIndex++;
+ }
+ }
}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/BracketHandler.cs b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/BracketHandler.cs
index 18aceb1..ea4236a 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/BracketHandler.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/BracketHandler.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,17 +13,17 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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-12-28
@@ -33,30 +33,28 @@
using System.Linq;
using System.Text;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis.TokenSeparatorHandlers
-{
- public class BracketHandler : SeparatorHandler
- {
- public override bool Handle(char c, Token tokenSeparator, TokenizerContext context, ITokenIndexProvider tokenIndexProvider)
- {
- if (tokenSeparator.TokenType == TokenType.OpeningBracket)
- {
- context.AppendToCurrentToken(c);
- context.BracketCount++;
- return true;
- }
- if (tokenSeparator.TokenType == TokenType.ClosingBracket)
- {
- context.AppendToCurrentToken(c);
- context.BracketCount--;
- return true;
- }
- if (context.BracketCount > 0)
- {
- context.AppendToCurrentToken(c);
- return true;
- }
- return false;
- }
+namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis.TokenSeparatorHandlers {
+ public class BracketHandler : SeparatorHandler {
+ public override bool Handle(
+ char c,
+ Token tokenSeparator,
+ TokenizerContext context,
+ ITokenIndexProvider tokenIndexProvider) {
+ if (tokenSeparator.TokenType == TokenType.OpeningBracket) {
+ context.AppendToCurrentToken(c);
+ context.BracketCount++;
+ return true;
+ }
+ if (tokenSeparator.TokenType == TokenType.ClosingBracket) {
+ context.AppendToCurrentToken(c);
+ context.BracketCount--;
+ return true;
+ }
+ if (context.BracketCount > 0) {
+ context.AppendToCurrentToken(c);
+ return true;
+ }
+ return false;
}
+ }
}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/MultipleCharSeparatorHandler.cs b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/MultipleCharSeparatorHandler.cs
index 82ee081..dc02369 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/MultipleCharSeparatorHandler.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/MultipleCharSeparatorHandler.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,17 +13,17 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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-12-28
@@ -34,41 +34,39 @@
using System.Linq;
using System.Text;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis.TokenSeparatorHandlers
-{
- public class MultipleCharSeparatorHandler : SeparatorHandler
- {
- ITokenSeparatorProvider _tokenSeparatorProvider;
+namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis.TokenSeparatorHandlers {
+ public class MultipleCharSeparatorHandler : SeparatorHandler {
+ ITokenSeparatorProvider _tokenSeparatorProvider;
- public MultipleCharSeparatorHandler()
- : this(new TokenSeparatorProvider())
- {
+ public MultipleCharSeparatorHandler()
+ : this(new TokenSeparatorProvider()) {}
- }
- public MultipleCharSeparatorHandler(ITokenSeparatorProvider tokenSeparatorProvider)
- {
- _tokenSeparatorProvider = tokenSeparatorProvider;
- }
- public override bool Handle(char c, Token tokenSeparator, TokenizerContext context, ITokenIndexProvider tokenIndexProvider)
- {
- // two operators in sequence could be "<=" or ">="
- if (IsPartOfMultipleCharSeparator(context, c))
- {
- var sOp = context.LastToken.Value + c.ToString(CultureInfo.InvariantCulture);
- var op = _tokenSeparatorProvider.Tokens[sOp];
- context.ReplaceLastToken(op);
- context.NewToken();
- return true;
- }
- return false;
- }
-
- private bool IsPartOfMultipleCharSeparator(TokenizerContext context, char c)
- {
- var lastToken = context.LastToken != null ? context.LastToken.Value : string.Empty;
- return _tokenSeparatorProvider.IsOperator(lastToken)
- && _tokenSeparatorProvider.IsPossibleLastPartOfMultipleCharOperator(c.ToString(CultureInfo.InvariantCulture))
- && !context.CurrentTokenHasValue;
- }
+ public MultipleCharSeparatorHandler(ITokenSeparatorProvider tokenSeparatorProvider) {
+ _tokenSeparatorProvider = tokenSeparatorProvider;
}
+
+ public override bool Handle(
+ char c,
+ Token tokenSeparator,
+ TokenizerContext context,
+ ITokenIndexProvider tokenIndexProvider) {
+ // two operators in sequence could be "<=" or ">="
+ if (IsPartOfMultipleCharSeparator(context, c)) {
+ var sOp = context.LastToken.Value + c.ToString(CultureInfo.InvariantCulture);
+ var op = _tokenSeparatorProvider.Tokens[sOp];
+ context.ReplaceLastToken(op);
+ context.NewToken();
+ return true;
+ }
+ return false;
+ }
+
+ private bool IsPartOfMultipleCharSeparator(TokenizerContext context, char c) {
+ var lastToken = context.LastToken != null ? context.LastToken.Value : string.Empty;
+ return _tokenSeparatorProvider.IsOperator(lastToken)
+ && _tokenSeparatorProvider.IsPossibleLastPartOfMultipleCharOperator(
+ c.ToString(CultureInfo.InvariantCulture))
+ && !context.CurrentTokenHasValue;
+ }
+ }
}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/SeparatorHandler.cs b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/SeparatorHandler.cs
index b275b2b..702a12d 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/SeparatorHandler.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/SeparatorHandler.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,17 +13,17 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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-12-28
@@ -33,16 +33,21 @@
using System.Linq;
using System.Text;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis.TokenSeparatorHandlers
-{
- public abstract class SeparatorHandler
- {
- protected bool IsDoubleQuote(Token tokenSeparator, int formulaCharIndex, TokenizerContext context)
- {
- return tokenSeparator.TokenType == TokenType.String && formulaCharIndex + 1 < context.FormulaChars.Length && context.FormulaChars[formulaCharIndex + 1] == '\"';
- }
-
- public abstract bool Handle(char c, Token tokenSeparator, TokenizerContext context, ITokenIndexProvider tokenIndexProvider);
-
+namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis.TokenSeparatorHandlers {
+ public abstract class SeparatorHandler {
+ protected bool IsDoubleQuote(
+ Token tokenSeparator,
+ int formulaCharIndex,
+ TokenizerContext context) {
+ return tokenSeparator.TokenType == TokenType.String
+ && formulaCharIndex + 1 < context.FormulaChars.Length
+ && context.FormulaChars[formulaCharIndex + 1] == '\"';
}
+
+ public abstract bool Handle(
+ char c,
+ Token tokenSeparator,
+ TokenizerContext context,
+ ITokenIndexProvider tokenIndexProvider);
+ }
}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/SheetnameHandler.cs b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/SheetnameHandler.cs
index 2147f8e..f435fb3 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/SheetnameHandler.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/SheetnameHandler.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,17 +13,17 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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-12-28
@@ -33,41 +33,38 @@
using System.Linq;
using System.Text;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis.TokenSeparatorHandlers
-{
- public class SheetnameHandler : SeparatorHandler
- {
- public override bool Handle(char c, Token tokenSeparator, TokenizerContext context, ITokenIndexProvider tokenIndexProvider)
- {
- if (context.IsInSheetName)
- {
- if (IsDoubleQuote(tokenSeparator, tokenIndexProvider.Index, context))
- {
- tokenIndexProvider.MoveIndexPointerForward();
- context.AppendToCurrentToken(c);
- return true;
- }
- if (tokenSeparator.TokenType != TokenType.WorksheetName)
- {
- context.AppendToCurrentToken(c);
- return true;
- }
- }
-
- if (tokenSeparator.TokenType == TokenType.WorksheetName)
- {
- if (context.LastToken != null && context.LastToken.TokenType == TokenType.WorksheetName)
- {
- context.AddToken(!context.CurrentTokenHasValue
- ? new Token(string.Empty, TokenType.WorksheetNameContent)
- : new Token(context.CurrentToken, TokenType.WorksheetNameContent));
- }
- context.AddToken(new Token("'", TokenType.WorksheetName));
- context.ToggleIsInSheetName();
- context.NewToken();
- return true;
- }
- return false;
+namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis.TokenSeparatorHandlers {
+ public class SheetnameHandler : SeparatorHandler {
+ public override bool Handle(
+ char c,
+ Token tokenSeparator,
+ TokenizerContext context,
+ ITokenIndexProvider tokenIndexProvider) {
+ if (context.IsInSheetName) {
+ if (IsDoubleQuote(tokenSeparator, tokenIndexProvider.Index, context)) {
+ tokenIndexProvider.MoveIndexPointerForward();
+ context.AppendToCurrentToken(c);
+ return true;
}
+ if (tokenSeparator.TokenType != TokenType.WorksheetName) {
+ context.AppendToCurrentToken(c);
+ return true;
+ }
+ }
+
+ if (tokenSeparator.TokenType == TokenType.WorksheetName) {
+ if (context.LastToken != null && context.LastToken.TokenType == TokenType.WorksheetName) {
+ context.AddToken(
+ !context.CurrentTokenHasValue
+ ? new Token(string.Empty, TokenType.WorksheetNameContent)
+ : new Token(context.CurrentToken, TokenType.WorksheetNameContent));
+ }
+ context.AddToken(new Token("'", TokenType.WorksheetName));
+ context.ToggleIsInSheetName();
+ context.NewToken();
+ return true;
+ }
+ return false;
}
+ }
}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/StringHandler.cs b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/StringHandler.cs
index ec4a24b..2ef629c 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/StringHandler.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/StringHandler.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,17 +13,17 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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-12-28
@@ -33,47 +33,44 @@
using System.Linq;
using System.Text;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis.TokenSeparatorHandlers
-{
- public class StringHandler : SeparatorHandler
- {
- public override bool Handle(char c, Token tokenSeparator, TokenizerContext context, ITokenIndexProvider tokenIndexProvider)
- {
- if(context.IsInString)
- {
- if (IsDoubleQuote(tokenSeparator, tokenIndexProvider.Index, context))
- {
- tokenIndexProvider.MoveIndexPointerForward();
- context.AppendToCurrentToken(c);
- return true;
- }
- if (tokenSeparator.TokenType != TokenType.String)
- {
- context.AppendToCurrentToken(c);
- return true;
- }
- }
-
- if (tokenSeparator.TokenType == TokenType.String)
- {
- if (context.LastToken != null && context.LastToken.TokenType == TokenType.OpeningEnumerable)
- {
- context.AppendToCurrentToken(c);
- context.ToggleIsInString();
- return true;
- }
- if (context.LastToken != null && context.LastToken.TokenType == TokenType.String)
- {
- context.AddToken(!context.CurrentTokenHasValue
- ? new Token(string.Empty, TokenType.StringContent)
- : new Token(context.CurrentToken, TokenType.StringContent));
- }
- context.AddToken(new Token("\"", TokenType.String));
- context.ToggleIsInString();
- context.NewToken();
- return true;
- }
- return false;
+namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis.TokenSeparatorHandlers {
+ public class StringHandler : SeparatorHandler {
+ public override bool Handle(
+ char c,
+ Token tokenSeparator,
+ TokenizerContext context,
+ ITokenIndexProvider tokenIndexProvider) {
+ if (context.IsInString) {
+ if (IsDoubleQuote(tokenSeparator, tokenIndexProvider.Index, context)) {
+ tokenIndexProvider.MoveIndexPointerForward();
+ context.AppendToCurrentToken(c);
+ return true;
}
+ if (tokenSeparator.TokenType != TokenType.String) {
+ context.AppendToCurrentToken(c);
+ return true;
+ }
+ }
+
+ if (tokenSeparator.TokenType == TokenType.String) {
+ if (context.LastToken != null
+ && context.LastToken.TokenType == TokenType.OpeningEnumerable) {
+ context.AppendToCurrentToken(c);
+ context.ToggleIsInString();
+ return true;
+ }
+ if (context.LastToken != null && context.LastToken.TokenType == TokenType.String) {
+ context.AddToken(
+ !context.CurrentTokenHasValue
+ ? new Token(string.Empty, TokenType.StringContent)
+ : new Token(context.CurrentToken, TokenType.StringContent));
+ }
+ context.AddToken(new Token("\"", TokenType.String));
+ context.ToggleIsInString();
+ context.NewToken();
+ return true;
+ }
+ return false;
}
+ }
}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/TokenSeparatorHandler.cs b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/TokenSeparatorHandler.cs
index 4f78c94..8afb997 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/TokenSeparatorHandler.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorHandlers/TokenSeparatorHandler.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,17 +13,17 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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-12-28
@@ -33,40 +33,38 @@
using System.Linq;
using System.Text;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis.TokenSeparatorHandlers
-{
- /// <summary>
- /// This class provides access to <see cref="SeparatorHandler"/>s - classes that exposes functionatlity
- /// needed when parsing strings to tokens.
- /// </summary>
- public static class TokenSeparatorHandler
- {
- private static SeparatorHandler[] _handlers = new SeparatorHandler[]
- {
- new StringHandler(),
- new BracketHandler(),
- new SheetnameHandler(),
- new MultipleCharSeparatorHandler()
- };
+namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis.TokenSeparatorHandlers {
+ /// <summary>
+ /// This class provides access to <see cref="SeparatorHandler"/>s - classes that exposes functionatlity
+ /// needed when parsing strings to tokens.
+ /// </summary>
+ public static class TokenSeparatorHandler {
+ private static SeparatorHandler[] _handlers = new SeparatorHandler[] {
+ new StringHandler(),
+ new BracketHandler(),
+ new SheetnameHandler(),
+ new MultipleCharSeparatorHandler(),
+ };
- /// <summary>
- /// Handles a tokenseparator.
- /// </summary>
- /// <param name="c"></param>
- /// <param name="tokenSeparator"></param>
- /// <param name="context"></param>
- /// <param name="tokenIndexProvider"></param>
- /// <returns>Returns true if the tokenseparator was handled.</returns>
- public static bool Handle(char c, Token tokenSeparator, TokenizerContext context, ITokenIndexProvider tokenIndexProvider)
- {
- foreach(var handler in _handlers)
- {
- if(handler.Handle(c, tokenSeparator, context, tokenIndexProvider))
- {
- return true;
- }
- }
- return false;
+ /// <summary>
+ /// Handles a tokenseparator.
+ /// </summary>
+ /// <param name="c"></param>
+ /// <param name="tokenSeparator"></param>
+ /// <param name="context"></param>
+ /// <param name="tokenIndexProvider"></param>
+ /// <returns>Returns true if the tokenseparator was handled.</returns>
+ public static bool Handle(
+ char c,
+ Token tokenSeparator,
+ TokenizerContext context,
+ ITokenIndexProvider tokenIndexProvider) {
+ foreach (var handler in _handlers) {
+ if (handler.Handle(c, tokenSeparator, context, tokenIndexProvider)) {
+ return true;
}
+ }
+ return false;
}
+ }
}
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorProvider.cs b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorProvider.cs
index d11ccd6..cddd2f3 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorProvider.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorProvider.cs
@@ -13,82 +13,69 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-using System.Threading;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis
-{
- public class TokenSeparatorProvider : ITokenSeparatorProvider
- {
- private static readonly Dictionary<string, Token> _tokens;
+namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
- static TokenSeparatorProvider()
- {
- _tokens = new Dictionary<string, Token>();
- _tokens.Add("+", new Token("+", TokenType.Operator));
- _tokens.Add("-", new Token("-", TokenType.Operator));
- _tokens.Add("*", new Token("*", TokenType.Operator));
- _tokens.Add("/", new Token("/", TokenType.Operator));
- _tokens.Add("^", new Token("^", TokenType.Operator));
- _tokens.Add("&", new Token("&", TokenType.Operator));
- _tokens.Add(">", new Token(">", TokenType.Operator));
- _tokens.Add("<", new Token("<", TokenType.Operator));
- _tokens.Add("=", new Token("=", TokenType.Operator));
- _tokens.Add("<=", new Token("<=", TokenType.Operator));
- _tokens.Add(">=", new Token(">=", TokenType.Operator));
- _tokens.Add("<>", new Token("<>", TokenType.Operator));
- _tokens.Add("(", new Token("(", TokenType.OpeningParenthesis));
- _tokens.Add(")", new Token(")", TokenType.ClosingParenthesis));
- _tokens.Add("{", new Token("{", TokenType.OpeningEnumerable));
- _tokens.Add("}", new Token("}", TokenType.ClosingEnumerable));
- _tokens.Add("'", new Token("'", TokenType.String));
- _tokens.Add("\"", new Token("\"", TokenType.String));
- _tokens.Add(",", new Token(",", TokenType.Comma));
- _tokens.Add(";", new Token(";", TokenType.SemiColon));
- _tokens.Add("[", new Token("[", TokenType.OpeningBracket));
- _tokens.Add("]", new Token("]", TokenType.ClosingBracket));
- _tokens.Add("%", new Token("%", TokenType.Percent));
- }
+public class TokenSeparatorProvider : ITokenSeparatorProvider {
+ private static readonly Dictionary<string, Token> _tokens;
- IDictionary<string, Token> ITokenSeparatorProvider.Tokens
- {
- get { return _tokens; }
- }
+ static TokenSeparatorProvider() {
+ _tokens = new();
+ _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));
+ }
- public bool IsOperator(string item)
- {
- Token token;
- if (_tokens.TryGetValue(item, out token))
- {
- if (token.TokenType == TokenType.Operator)
- {
- return true;
- }
- }
- return false;
- }
+ IDictionary<string, Token> ITokenSeparatorProvider.Tokens => _tokens;
- public bool IsPossibleLastPartOfMultipleCharOperator(string part)
- {
- return part == "=" || part == ">";
- }
+ public bool IsOperator(string item) {
+ Token token;
+ if (_tokens.TryGetValue(item, out 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
index 5bcda9a..a698470 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenType.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/TokenType.cs
@@ -13,54 +13,48 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-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
- }
+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
index 6a28142..e87ac14 100644
--- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenizerContext.cs
+++ b/EPPlus/FormulaParsing/LexicalAnalysis/TokenizerContext.cs
@@ -13,120 +13,92 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis
-{
- public class TokenizerContext
- {
- public TokenizerContext(string formula)
- {
- if (!string.IsNullOrEmpty(formula))
- {
- _chars = formula.ToArray();
- }
- _result = new List<Token>();
- _currentToken = new StringBuilder();
- }
+namespace OfficeOpenXml.FormulaParsing.LexicalAnalysis;
- private char[] _chars;
- private List<Token> _result;
- private StringBuilder _currentToken;
-
- public char[] FormulaChars
- {
- get { return _chars; }
- }
-
- public IList<Token> Result
- {
- get { return _result; }
- }
-
- public bool IsInString
- {
- get;
- private set;
- }
-
- public void ToggleIsInString()
- {
- IsInString = !IsInString;
- }
-
- internal int BracketCount
- {
- get;
- set;
- }
-
- public string CurrentToken
- {
- get { return _currentToken.ToString(); }
- }
-
- public bool CurrentTokenHasValue
- {
- get { return !string.IsNullOrEmpty(this.IsInString ? CurrentToken : CurrentToken.Trim()); }
- }
-
- public void NewToken()
- {
- _currentToken = new StringBuilder();
- }
-
- 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
- {
- get { return _result.Count > 0 ? _result.Last() : null; }
- }
-
+public class TokenizerContext {
+ public TokenizerContext(string formula) {
+ if (!string.IsNullOrEmpty(formula)) {
+ _chars = formula.ToArray();
}
+ _result = new();
+ _currentToken = new();
+ }
+
+ private char[] _chars;
+ private List<Token> _result;
+ private StringBuilder _currentToken;
+
+ public char[] FormulaChars => _chars;
+
+ public IList<Token> Result {
+ get { return _result; }
+ }
+
+ public bool IsInString { get; private set; }
+
+ public void ToggleIsInString() {
+ IsInString = !IsInString;
+ }
+
+ internal int BracketCount { get; set; }
+
+ public string CurrentToken {
+ get { return _currentToken.ToString(); }
+ }
+
+ public bool CurrentTokenHasValue {
+ get { return !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 {
+ get { return _result.Count > 0 ? _result.Last() : null; }
+ }
}
diff --git a/EPPlus/FormulaParsing/Logging/IFormulaParserLogger.cs b/EPPlus/FormulaParsing/Logging/IFormulaParserLogger.cs
index f5a91b8..dc38d9d 100644
--- a/EPPlus/FormulaParsing/Logging/IFormulaParserLogger.cs
+++ b/EPPlus/FormulaParsing/Logging/IFormulaParserLogger.cs
@@ -1,44 +1,46 @@
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();
+namespace OfficeOpenXml.FormulaParsing.Logging;
- /// <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);
- }
+/// <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
index 5210a31..f7b0a8d 100644
--- a/EPPlus/FormulaParsing/NameValueProvider.cs
+++ b/EPPlus/FormulaParsing/NameValueProvider.cs
@@ -1,35 +1,17 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+namespace OfficeOpenXml.FormulaParsing;
-namespace OfficeOpenXml.FormulaParsing
-{
- public class NameValueProvider : INameValueProvider
- {
- private NameValueProvider()
- {
+public class NameValueProvider : INameValueProvider {
+ private NameValueProvider() {}
- }
+ public static INameValueProvider Empty => new NameValueProvider();
- public static INameValueProvider Empty
- {
- get { return new NameValueProvider(); }
- }
+ public bool IsNamedValue(string key, string worksheet) {
+ return false;
+ }
- public bool IsNamedValue(string key, string worksheet)
- {
- return false;
- }
+ public object GetNamedValue(string key) {
+ return null;
+ }
- public object GetNamedValue(string key)
- {
- return null;
- }
-
- public void Reload()
- {
-
- }
- }
+ public void Reload() {}
}
diff --git a/EPPlus/FormulaParsing/ParsedValue.cs b/EPPlus/FormulaParsing/ParsedValue.cs
index 51d7d08..43112b7 100644
--- a/EPPlus/FormulaParsing/ParsedValue.cs
+++ b/EPPlus/FormulaParsing/ParsedValue.cs
@@ -1,35 +1,15 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+namespace OfficeOpenXml.FormulaParsing;
-namespace OfficeOpenXml.FormulaParsing
-{
- public class ParsedValue
- {
- public ParsedValue(object val, int rowIndex, int colIndex)
- {
- Value = val;
- RowIndex = rowIndex;
- ColIndex = colIndex;
- }
+public class ParsedValue {
+ public ParsedValue(object val, int rowIndex, int colIndex) {
+ Value = val;
+ RowIndex = rowIndex;
+ ColIndex = colIndex;
+ }
- public object Value
- {
- get;
- private set;
- }
+ public object Value { get; private set; }
- public int RowIndex
- {
- get;
- private set;
- }
+ public int RowIndex { get; private set; }
- public int ColIndex
- {
- get;
- private set;
- }
- }
+ public int ColIndex { get; private set; }
}
diff --git a/EPPlus/FormulaParsing/ParsingConfiguration.cs b/EPPlus/FormulaParsing/ParsingConfiguration.cs
index dddf0b6..71440b3 100644
--- a/EPPlus/FormulaParsing/ParsingConfiguration.cs
+++ b/EPPlus/FormulaParsing/ParsingConfiguration.cs
@@ -1,76 +1,62 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
+using OfficeOpenXml.FormulaParsing.Excel.Functions;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.Excel.Functions;
+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; }
+namespace OfficeOpenXml.FormulaParsing;
- public IFormulaParserLogger Logger { get; private set; }
+public class ParsingConfiguration {
+ public virtual ILexer Lexer { get; private set; }
- public IExpressionGraphBuilder GraphBuilder { get; private set; }
+ public IFormulaParserLogger Logger { get; private set; }
- public IExpressionCompiler ExpressionCompiler{ get; private set; }
+ public IExpressionGraphBuilder GraphBuilder { get; private set; }
- public FunctionRepository FunctionRepository{ get; private set; }
+ public IExpressionCompiler ExpressionCompiler { get; private set; }
- private ParsingConfiguration()
- {
- FunctionRepository = FunctionRepository.Create();
- }
+ public FunctionRepository FunctionRepository { get; private set; }
- internal static ParsingConfiguration Create()
- {
- return new ParsingConfiguration();
- }
+ private ParsingConfiguration() {
+ FunctionRepository = FunctionRepository.Create();
+ }
- public ParsingConfiguration SetLexer(ILexer lexer)
- {
- Lexer = lexer;
- return this;
- }
+ internal static ParsingConfiguration Create() {
+ return new();
+ }
- public ParsingConfiguration SetGraphBuilder(IExpressionGraphBuilder graphBuilder)
- {
- GraphBuilder = graphBuilder;
- return this;
- }
+ public ParsingConfiguration SetLexer(ILexer lexer) {
+ Lexer = lexer;
+ return this;
+ }
- public ParsingConfiguration SetExpresionCompiler(IExpressionCompiler expressionCompiler)
- {
- ExpressionCompiler = expressionCompiler;
- return this;
- }
+ public ParsingConfiguration SetGraphBuilder(IExpressionGraphBuilder graphBuilder) {
+ GraphBuilder = graphBuilder;
+ 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;
- }
+ public ParsingConfiguration SetExpresionCompiler(IExpressionCompiler expressionCompiler) {
+ ExpressionCompiler = expressionCompiler;
+ return this;
+ }
- /// <summary>
- /// if a logger is attached it will be removed.
- /// </summary>
- /// <returns></returns>
- public ParsingConfiguration DetachLogger()
- {
- Logger = null;
- 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
index 641d1d6..8eee889 100644
--- a/EPPlus/FormulaParsing/ParsingContext.cs
+++ b/EPPlus/FormulaParsing/ParsingContext.cs
@@ -1,76 +1,60 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using OfficeOpenXml.FormulaParsing.ExcelUtilities;
-using OfficeOpenXml.FormulaParsing;
+using OfficeOpenXml.FormulaParsing.ExcelUtilities;
using OfficeOpenXml.FormulaParsing.Logging;
-namespace OfficeOpenXml.FormulaParsing
-{
- /// <summary>
- /// Parsing context
- /// </summary>
- public class ParsingContext : IParsingLifetimeEventHandler
- {
- private ParsingContext() { }
+namespace OfficeOpenXml.FormulaParsing;
- /// <summary>
- /// The <see cref="FormulaParser"/> of the current context.
- /// </summary>
- public FormulaParser Parser { get; set; }
+/// <summary>
+/// Parsing context
+/// </summary>
+public class ParsingContext : IParsingLifetimeEventHandler {
+ private ParsingContext() {}
- /// <summary>
- /// The <see cref="ExcelDataProvider"/> is an abstraction on top of
- /// Excel, in this case EPPlus.
- /// </summary>
- public ExcelDataProvider ExcelDataProvider { get; set; }
+ /// <summary>
+ /// The <see cref="FormulaParser"/> of the current context.
+ /// </summary>
+ public FormulaParser Parser { get; set; }
- /// <summary>
- /// Utility for handling addresses
- /// </summary>
- public RangeAddressFactory RangeAddressFactory { 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>
- /// <see cref="INameValueProvider"/> of the current context
- /// </summary>
- public INameValueProvider NameValueProvider { get; set; }
+ /// <summary>
+ /// Utility for handling addresses
+ /// </summary>
+ public RangeAddressFactory RangeAddressFactory { get; set; }
- /// <summary>
- /// Configuration
- /// </summary>
- public ParsingConfiguration Configuration { get; set; }
+ /// <summary>
+ /// <see cref="INameValueProvider"/> of the current context
+ /// </summary>
+ public INameValueProvider NameValueProvider { get; set; }
- /// <summary>
- /// Scopes, a scope represents the parsing of a cell or a value.
- /// </summary>
- public ParsingScopes Scopes { get; private set; }
+ /// <summary>
+ /// Configuration
+ /// </summary>
+ public ParsingConfiguration Configuration { get; set; }
- /// <summary>
- /// Returns true if a <see cref="IFormulaParserLogger"/> is attached to the parser.
- /// </summary>
- public bool Debug
- {
- get { return Configuration.Logger != null; }
- }
+ /// <summary>
+ /// Scopes, a scope represents the parsing of a cell or a value.
+ /// </summary>
+ public ParsingScopes Scopes { get; private set; }
- /// <summary>
- /// Factory method.
- /// </summary>
- /// <returns></returns>
- public static ParsingContext Create()
- {
- var context = new ParsingContext();
- context.Configuration = ParsingConfiguration.Create();
- context.Scopes = new ParsingScopes(context);
- return context;
- }
+ /// <summary>
+ /// Returns true if a <see cref="IFormulaParserLogger"/> is attached to the parser.
+ /// </summary>
+ public bool Debug => Configuration.Logger != null;
- void IParsingLifetimeEventHandler.ParsingCompleted()
- {
-
- }
- }
+ /// <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
index 321e693..1e861c5 100644
--- a/EPPlus/FormulaParsing/ParsingScope.cs
+++ b/EPPlus/FormulaParsing/ParsingScope.cs
@@ -1,54 +1,45 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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;
+namespace OfficeOpenXml.FormulaParsing;
- public ParsingScope(ParsingScopes parsingScopes, RangeAddress address)
- : this(parsingScopes, null, address)
- {
- }
+/// <summary>
+/// Represents a parsing of a single input or workbook addrses.
+/// </summary>
+public class ParsingScope : IDisposable {
+ private readonly ParsingScopes _parsingScopes;
- public ParsingScope(ParsingScopes parsingScopes, ParsingScope parent, RangeAddress address)
- {
- _parsingScopes = parsingScopes;
- Parent = parent;
- Address = address;
- ScopeId = Guid.NewGuid();
- }
+ public ParsingScope(ParsingScopes parsingScopes, RangeAddress address)
+ : this(parsingScopes, null, address) {}
- /// <summary>
- /// Id of the scope.
- /// </summary>
- public Guid ScopeId { get; private set; }
+ public ParsingScope(ParsingScopes parsingScopes, ParsingScope parent, RangeAddress address) {
+ _parsingScopes = parsingScopes;
+ Parent = parent;
+ Address = address;
+ ScopeId = Guid.NewGuid();
+ }
- /// <summary>
- /// The calling scope.
- /// </summary>
- public ParsingScope Parent { get; private set; }
+ /// <summary>
+ /// Id of the scope.
+ /// </summary>
+ public Guid ScopeId { get; private set; }
- /// <summary>
- /// The address of the cell currently beeing parsed.
- /// </summary>
- public RangeAddress Address { get; private set; }
+ /// <summary>
+ /// The calling scope.
+ /// </summary>
+ public ParsingScope Parent { get; private set; }
- /// <summary>
- /// True if the current scope is a Subtotal function beeing executed.
- /// </summary>
- public bool IsSubtotal { get; set; }
+ /// <summary>
+ /// The address of the cell currently beeing parsed.
+ /// </summary>
+ public RangeAddress Address { get; private set; }
- public void Dispose()
- {
- _parsingScopes.KillScope(this);
- }
- }
+ /// <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
index 978df30..51d7bad 100644
--- a/EPPlus/FormulaParsing/ParsingScopes.cs
+++ b/EPPlus/FormulaParsing/ParsingScopes.cs
@@ -1,65 +1,51 @@
-using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
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;
+namespace OfficeOpenXml.FormulaParsing;
- public ParsingScopes(IParsingLifetimeEventHandler lifetimeEventHandler)
- {
- _lifetimeEventHandler = lifetimeEventHandler;
- }
- private Stack<ParsingScope> _scopes = new Stack<ParsingScope>();
+/// <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;
- /// <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 ParsingScope(this, _scopes.Peek(), address);
- }
- else
- {
- scope = new ParsingScope(this, address);
- }
- _scopes.Push(scope);
- return scope;
- }
+ public ParsingScopes(IParsingLifetimeEventHandler lifetimeEventHandler) {
+ _lifetimeEventHandler = lifetimeEventHandler;
+ }
+ private Stack<ParsingScope> _scopes = new();
- /// <summary>
- /// The current parsing scope.
- /// </summary>
- public virtual ParsingScope Current
- {
- get { return _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();
- }
- }
+ /// <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
index 9cf0893..a0a826f 100644
--- a/EPPlus/FormulaParsing/Utilities/ArgumentInfo.cs
+++ b/EPPlus/FormulaParsing/Utilities/ArgumentInfo.cs
@@ -1,25 +1,16 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+namespace OfficeOpenXml.FormulaParsing.Utilities;
-namespace OfficeOpenXml.FormulaParsing.Utilities
-{
- public class ArgumentInfo<T>
- {
- public ArgumentInfo(T val)
- {
- Value = val;
- }
+public class ArgumentInfo<T> {
+ public ArgumentInfo(T val) {
+ Value = val;
+ }
- public T Value { get; private set; }
+ public T Value { get; private set; }
- public string Name { get; private set; }
+ public string Name { get; private set; }
- public ArgumentInfo<T> Named(string argName)
- {
- Name = argName;
- return this;
- }
- }
+ public ArgumentInfo<T> Named(string argName) {
+ Name = argName;
+ return this;
+ }
}
diff --git a/EPPlus/FormulaParsing/Utilities/ExtensionMethods.cs b/EPPlus/FormulaParsing/Utilities/ExtensionMethods.cs
index 045f793..786ec4f 100644
--- a/EPPlus/FormulaParsing/Utilities/ExtensionMethods.cs
+++ b/EPPlus/FormulaParsing/Utilities/ExtensionMethods.cs
@@ -1,33 +1,29 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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");
- }
- }
+namespace OfficeOpenXml.FormulaParsing.Utilities;
- 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 System.DateTime || obj is TimeSpan);
- }
+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
index 9dfc6ae..15e02b3 100644
--- a/EPPlus/FormulaParsing/Utilities/IdProvider.cs
+++ b/EPPlus/FormulaParsing/Utilities/IdProvider.cs
@@ -1,12 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+namespace OfficeOpenXml.FormulaParsing.Utilities;
-namespace OfficeOpenXml.FormulaParsing.Utilities
-{
- public abstract class IdProvider
- {
- public abstract object NewId();
- }
+public abstract class IdProvider {
+ public abstract object NewId();
}
diff --git a/EPPlus/FormulaParsing/Utilities/IntegerIdProvider.cs b/EPPlus/FormulaParsing/Utilities/IntegerIdProvider.cs
index 5b1b0b1..d1a39f4 100644
--- a/EPPlus/FormulaParsing/Utilities/IntegerIdProvider.cs
+++ b/EPPlus/FormulaParsing/Utilities/IntegerIdProvider.cs
@@ -1,21 +1,14 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-namespace OfficeOpenXml.FormulaParsing.Utilities
-{
- public class IntegerIdProvider : IdProvider
- {
- private int _lastId = int.MinValue;
+namespace OfficeOpenXml.FormulaParsing.Utilities;
- public override object NewId()
- {
- if (_lastId >= int.MaxValue)
- {
- throw new InvalidOperationException("IdProvider run out of id:s");
- }
- return _lastId++;
- }
+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
index 6e009aa..deba058 100644
--- a/EPPlus/FormulaParsing/Utilities/RegexConstants.cs
+++ b/EPPlus/FormulaParsing/Utilities/RegexConstants.cs
@@ -13,36 +13,34 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this 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 System.Text;
-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]+$";
- }
+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
index 443ee50..35d53cd 100644
--- a/EPPlus/FormulaParsing/Utilities/Require.cs
+++ b/EPPlus/FormulaParsing/Utilities/Require.cs
@@ -1,15 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+namespace OfficeOpenXml.FormulaParsing.Utilities;
-namespace OfficeOpenXml.FormulaParsing.Utilities
-{
- public static class Require
- {
- public static ArgumentInfo<T> That<T>(T arg)
- {
- return new ArgumentInfo<T>(arg);
- }
- }
+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
index 6c96524..8ead21d 100644
--- a/EPPlus/IRangeID.cs
+++ b/EPPlus/IRangeID.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,42 +13,33 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Text;
-namespace OfficeOpenXml
-{
- /// <summary>
- /// Id from a cell, column or row.
- /// </summary>
- 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;
- }
- }
+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
index d9e83ba..62df7e5 100644
--- a/EPPlus/OfficeProperties.cs
+++ b/EPPlus/OfficeProperties.cs
@@ -13,17 +13,17 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
@@ -31,518 +31,448 @@
* Jan K�llman License changed GPL-->LGPL 2011-12-27
* Raziq York Added Created & Modified 2014-08-20
*******************************************************************************/
+
using System;
-using System.Xml;
-using System.IO;
using System.Globalization;
+using System.IO;
+using System.Xml;
+using OfficeOpenXml.Packaging;
using OfficeOpenXml.Utils;
-namespace OfficeOpenXml
-{
- /// <summary>
- /// Provides access to the properties bag of the package
- /// </summary>
- public sealed class OfficeProperties : XmlHelper
- {
- #region Private Properties
- private XmlDocument _xmlPropertiesCore;
- private XmlDocument _xmlPropertiesExtended;
- private XmlDocument _xmlPropertiesCustom;
+namespace OfficeOpenXml;
- private Uri _uriPropertiesCore = new Uri("/docProps/core.xml", UriKind.Relative);
- private Uri _uriPropertiesExtended = new Uri("/docProps/app.xml", UriKind.Relative);
- private Uri _uriPropertiesCustom = new Uri("/docProps/custom.xml", UriKind.Relative);
+/// <summary>
+/// Provides access to the properties bag of the package
+/// </summary>
+public sealed class OfficeProperties : XmlHelper {
+ private XmlDocument _xmlPropertiesCore;
+ private XmlDocument _xmlPropertiesExtended;
+ private XmlDocument _xmlPropertiesCustom;
- XmlHelper _coreHelper;
- XmlHelper _extendedHelper;
- XmlHelper _customHelper;
- private ExcelPackage _package;
- #endregion
+ private Uri _uriPropertiesCore = new("/docProps/core.xml", UriKind.Relative);
+ private Uri _uriPropertiesExtended = new("/docProps/app.xml", UriKind.Relative);
+ private Uri _uriPropertiesCustom = new("/docProps/custom.xml", UriKind.Relative);
- #region ExcelProperties Constructor
- /// <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)
- {
- _package = package;
+ private XmlHelper _coreHelper;
+ private XmlHelper _extendedHelper;
+ private XmlHelper _customHelper;
+ private ExcelPackage _package;
- _coreHelper = XmlHelperFactory.Create(ns, CorePropertiesXml.SelectSingleNode("cp:coreProperties", NameSpaceManager));
- _extendedHelper = XmlHelperFactory.Create(ns, ExtendedPropertiesXml);
- _customHelper = XmlHelperFactory.Create(ns, CustomPropertiesXml);
+ /// <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) {
+ _package = package;
- }
- #endregion
- #region CorePropertiesXml
- /// <summary>
- /// Provides access to the XML document that holds all the code
- /// document properties.
- /// </summary>
- public XmlDocument CorePropertiesXml
- {
- get
- {
- if (_xmlPropertiesCore == null)
- {
- string xml = string.Format("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><cp:coreProperties xmlns:cp=\"{0}\" xmlns:dc=\"{1}\" xmlns:dcterms=\"{2}\" xmlns:dcmitype=\"{3}\" xmlns:xsi=\"{4}\"></cp:coreProperties>",
- ExcelPackage.schemaCore,
- ExcelPackage.schemaDc,
- ExcelPackage.schemaDcTerms,
- ExcelPackage.schemaDcmiType,
- ExcelPackage.schemaXsi);
+ _coreHelper = XmlHelperFactory.Create(
+ ns,
+ CorePropertiesXml.SelectSingleNode("cp:coreProperties", NameSpaceManager));
+ _extendedHelper = XmlHelperFactory.Create(ns, ExtendedPropertiesXml);
+ _customHelper = XmlHelperFactory.Create(ns, CustomPropertiesXml);
+ }
- _xmlPropertiesCore = GetXmlDocument(xml, _uriPropertiesCore, @"application/vnd.openxmlformats-package.core-properties+xml", @"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties");
- }
- return (_xmlPropertiesCore);
- }
- }
+ /// <summary>
+ /// Provides access to the XML document that holds all the code
+ /// document properties.
+ /// </summary>
+ public XmlDocument CorePropertiesXml {
+ get {
+ if (_xmlPropertiesCore == null) {
+ string xml = string.Format(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><cp:coreProperties xmlns:cp=\"{0}\" xmlns:dc=\"{1}\" xmlns:dcterms=\"{2}\" xmlns:dcmitype=\"{3}\" xmlns:xsi=\"{4}\"></cp:coreProperties>",
+ ExcelPackage._schemaCore,
+ ExcelPackage._schemaDc,
+ ExcelPackage._schemaDcTerms,
+ ExcelPackage._schemaDcmiType,
+ ExcelPackage._schemaXsi);
- private XmlDocument GetXmlDocument(string startXml, Uri uri, string contentType, string relationship)
- {
- XmlDocument xmlDoc;
- if (_package.Package.PartExists(uri))
- xmlDoc = _package.GetXmlFromUri(uri);
- else
- {
- xmlDoc = new XmlDocument();
- xmlDoc.LoadXml(startXml);
-
- // Create a the part and add to the package
- Packaging.ZipPackagePart part = _package.Package.CreatePart(uri, contentType);
-
- // Save it to the package
- StreamWriter stream = new StreamWriter(part.GetStream(FileMode.Create, FileAccess.Write));
- xmlDoc.Save(stream);
- //stream.Close();
-
- // create the relationship between the workbook and the new shared strings part
- _package.Package.CreateRelationship(UriHelper.GetRelativeUri(new Uri("/xl", UriKind.Relative), uri), Packaging.TargetMode.Internal, relationship);
- }
- return xmlDoc;
- }
- #endregion
- #region Core Properties
- const string TitlePath = "dc:title";
- /// <summary>
- /// Gets/sets the title property of the document (core property)
- /// </summary>
- public string Title
- {
- get { return _coreHelper.GetXmlNodeString(TitlePath); }
- set { _coreHelper.SetXmlNodeString(TitlePath, value); }
- }
-
- const string SubjectPath = "dc:subject";
- /// <summary>
- /// Gets/sets the subject property of the document (core property)
- /// </summary>
- public string Subject
- {
- get { return _coreHelper.GetXmlNodeString(SubjectPath); }
- set { _coreHelper.SetXmlNodeString(SubjectPath, value); }
- }
-
- const string AuthorPath = "dc:creator";
- /// <summary>
- /// Gets/sets the author property of the document (core property)
- /// </summary>
- public string Author
- {
- get { return _coreHelper.GetXmlNodeString(AuthorPath); }
- set { _coreHelper.SetXmlNodeString(AuthorPath, value); }
- }
-
- const string CommentsPath = "dc:description";
- /// <summary>
- /// Gets/sets the comments property of the document (core property)
- /// </summary>
- public string Comments
- {
- get { return _coreHelper.GetXmlNodeString(CommentsPath); }
- set { _coreHelper.SetXmlNodeString(CommentsPath, value); }
- }
-
- const string KeywordsPath = "cp:keywords";
- /// <summary>
- /// Gets/sets the keywords property of the document (core property)
- /// </summary>
- public string Keywords
- {
- get { return _coreHelper.GetXmlNodeString(KeywordsPath); }
- set { _coreHelper.SetXmlNodeString(KeywordsPath, value); }
- }
-
- const string LastModifiedByPath = "cp:lastModifiedBy";
- /// <summary>
- /// Gets/sets the lastModifiedBy property of the document (core property)
- /// </summary>
- public string LastModifiedBy
- {
- get { return _coreHelper.GetXmlNodeString(LastModifiedByPath); }
- set
- {
- _coreHelper.SetXmlNodeString(LastModifiedByPath, value);
- }
- }
-
- const string LastPrintedPath = "cp:lastPrinted";
- /// <summary>
- /// Gets/sets the lastPrinted property of the document (core property)
- /// </summary>
- public string LastPrinted
- {
- get { return _coreHelper.GetXmlNodeString(LastPrintedPath); }
- set { _coreHelper.SetXmlNodeString(LastPrintedPath, value); }
- }
-
- const string CreatedPath = "dcterms:created";
-
- /// <summary>
- /// Gets/sets the created property of the document (core property)
- /// </summary>
- public DateTime Created
- {
- get
- {
- DateTime date;
- return DateTime.TryParse(_coreHelper.GetXmlNodeString(CreatedPath), out 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");
- }
- }
-
- const string CategoryPath = "cp:category";
- /// <summary>
- /// Gets/sets the category property of the document (core property)
- /// </summary>
- public string Category
- {
- get { return _coreHelper.GetXmlNodeString(CategoryPath); }
- set { _coreHelper.SetXmlNodeString(CategoryPath, value); }
- }
-
- const string ContentStatusPath = "cp:contentStatus";
- /// <summary>
- /// Gets/sets the status property of the document (core property)
- /// </summary>
- public string Status
- {
- get { return _coreHelper.GetXmlNodeString(ContentStatusPath); }
- set { _coreHelper.SetXmlNodeString(ContentStatusPath, value); }
- }
- #endregion
-
- #region Extended Properties
- #region ExtendedPropertiesXml
- /// <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)
- {
- _xmlPropertiesExtended = GetXmlDocument(string.Format("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><Properties xmlns:vt=\"{0}\" xmlns=\"{1}\"></Properties>",
- ExcelPackage.schemaVt,
- ExcelPackage.schemaExtended),
- _uriPropertiesExtended,
- @"application/vnd.openxmlformats-officedocument.extended-properties+xml",
- @"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties");
- }
- return (_xmlPropertiesExtended);
- }
- }
- #endregion
-
- const string ApplicationPath = "xp:Properties/xp:Application";
- /// <summary>
- /// Gets/Set the Application property of the document (extended property)
- /// </summary>
- public string Application
- {
- get { return _extendedHelper.GetXmlNodeString(ApplicationPath); }
- set { _extendedHelper.SetXmlNodeString(ApplicationPath, value); }
- }
-
- const string HyperlinkBasePath = "xp:Properties/xp:HyperlinkBase";
- /// <summary>
- /// Gets/sets the HyperlinkBase property of the document (extended property)
- /// </summary>
- public Uri HyperlinkBase
- {
- get { return new Uri(_extendedHelper.GetXmlNodeString(HyperlinkBasePath), UriKind.Absolute); }
- set { _extendedHelper.SetXmlNodeString(HyperlinkBasePath, value.AbsoluteUri); }
- }
-
- const string AppVersionPath = "xp:Properties/xp:AppVersion";
- /// <summary>
- /// Gets/Set the AppVersion property of the document (extended property)
- /// </summary>
- public string AppVersion
- {
- get { return _extendedHelper.GetXmlNodeString(AppVersionPath); }
- set { _extendedHelper.SetXmlNodeString(AppVersionPath, value); }
- }
- const string CompanyPath = "xp:Properties/xp:Company";
-
- /// <summary>
- /// Gets/sets the Company property of the document (extended property)
- /// </summary>
- public string Company
- {
- get { return _extendedHelper.GetXmlNodeString(CompanyPath); }
- set { _extendedHelper.SetXmlNodeString(CompanyPath, value); }
- }
-
- const string ManagerPath = "xp:Properties/xp:Manager";
- /// <summary>
- /// Gets/sets the Manager property of the document (extended property)
- /// </summary>
- public string Manager
- {
- get { return _extendedHelper.GetXmlNodeString(ManagerPath); }
- set { _extendedHelper.SetXmlNodeString(ManagerPath, value); }
- }
-
- const string ModifiedPath = "dcterms:modified";
- /// <summary>
- /// Gets/sets the modified property of the document (core property)
- /// </summary>
- public DateTime Modified
- {
- get
- {
- DateTime date;
- return DateTime.TryParse(_coreHelper.GetXmlNodeString(ModifiedPath), out 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");
- }
- }
-
- #region Get and Set Extended Properties
- private string GetExtendedPropertyValue(string propertyName)
- {
- string retValue = null;
- string searchString = string.Format("xp:Properties/xp:{0}", propertyName);
- XmlNode node = ExtendedPropertiesXml.SelectSingleNode(searchString, NameSpaceManager);
- if (node != null)
- {
- retValue = node.InnerText;
- }
- return retValue;
- }
- #endregion
- #endregion
-
- #region Custom Properties
-
- #region CustomPropertiesXml
- /// <summary>
- /// Provides access to the XML document which holds the document's custom properties
- /// </summary>
- public XmlDocument CustomPropertiesXml
- {
- get
- {
- if (_xmlPropertiesCustom == null)
- {
- _xmlPropertiesCustom = GetXmlDocument(string.Format("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><Properties xmlns:vt=\"{0}\" xmlns=\"{1}\"></Properties>",
- ExcelPackage.schemaVt,
- ExcelPackage.schemaCustom),
- _uriPropertiesCustom,
- @"application/vnd.openxmlformats-officedocument.custom-properties+xml",
- @"http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties");
- }
- return (_xmlPropertiesCustom);
- }
- }
- #endregion
-
- #region Get and Set Custom Properties
- /// <summary>
- /// Gets the value of a custom property
- /// </summary>
- /// <param name="propertyName">The name of the property</param>
- /// <returns>The current value of the property</returns>
- public object GetCustomPropertyValue(string propertyName)
- {
- string searchString = string.Format("ctp:Properties/ctp:property[@name='{0}']", propertyName);
- XmlElement node = CustomPropertiesXml.SelectSingleNode(searchString, NameSpaceManager) as XmlElement;
- if (node != null)
- {
- string value = node.LastChild.InnerText;
- switch (node.LastChild.LocalName)
- {
- case "filetime":
- DateTime dt;
- if (DateTime.TryParse(value, out dt))
- {
- return dt;
- }
- else
- {
- return null;
- }
- case "i4":
- int i;
- if (int.TryParse(value, out i))
- {
- return i;
- }
- else
- {
- return null;
- }
- case "r8":
- double d;
- if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out d))
- {
- return d;
- }
- else
- {
- return null;
- }
- case "bool":
- if (value == "true")
- {
- return true;
- }
- else if (value == "false")
- {
- return false;
- }
- else
- {
- return null;
- }
- default:
- return value;
- }
- }
- else
- {
- return null;
- }
- }
-
- /// <summary>
- /// Allows you to set the value of a current custom property or create your own custom property.
- /// </summary>
- /// <param name="propertyName">The name of the property</param>
- /// <param name="value">The value of the property</param>
- public void SetCustomPropertyValue(string propertyName, object value)
- {
- XmlNode allProps = CustomPropertiesXml.SelectSingleNode(@"ctp:Properties", NameSpaceManager);
-
- var prop = string.Format("ctp:Properties/ctp:property[@name='{0}']", propertyName);
- XmlElement node = CustomPropertiesXml.SelectSingleNode(prop, NameSpaceManager) as XmlElement;
- if (node == null)
- {
- int pid;
- var MaxNode = CustomPropertiesXml.SelectSingleNode("ctp:Properties/ctp:property[not(@pid <= preceding-sibling::ctp:property/@pid) and not(@pid <= following-sibling::ctp:property/@pid)]", NameSpaceManager);
- if (MaxNode == null)
- {
- pid = 2;
- }
- else
- {
- if (!int.TryParse(MaxNode.Attributes["pid"].Value, out pid))
- {
- pid = 2;
- }
- pid++;
- }
- node = CustomPropertiesXml.CreateElement("property", ExcelPackage.schemaCustom);
- node.SetAttribute("fmtid", "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}");
- node.SetAttribute("pid", pid.ToString()); // custom property pid
- node.SetAttribute("name", propertyName);
-
- allProps.AppendChild(node);
- }
- else
- {
- while (node.ChildNodes.Count > 0) node.RemoveChild(node.ChildNodes[0]);
- }
- XmlElement valueElem;
- if (value is bool)
- {
- valueElem = CustomPropertiesXml.CreateElement("vt", "bool", ExcelPackage.schemaVt);
- valueElem.InnerText = value.ToString().ToLower(CultureInfo.InvariantCulture);
- }
- else if (value is DateTime)
- {
- valueElem = CustomPropertiesXml.CreateElement("vt", "filetime", ExcelPackage.schemaVt);
- valueElem.InnerText = ((DateTime)value).AddHours(-1).ToString("yyyy-MM-ddTHH:mm:ssZ");
- }
- else if (value is short || value is int)
- {
- valueElem = CustomPropertiesXml.CreateElement("vt", "i4", ExcelPackage.schemaVt);
- valueElem.InnerText = value.ToString();
- }
- else if (value is double || value is decimal || value is float || value is long)
- {
- valueElem = CustomPropertiesXml.CreateElement("vt", "r8", ExcelPackage.schemaVt);
- if (value is double)
- {
- valueElem.InnerText = ((double)value).ToString(CultureInfo.InvariantCulture);
- }
- else if (value is float)
- {
- valueElem.InnerText = ((float)value).ToString(CultureInfo.InvariantCulture);
- }
- else if (value is decimal)
- {
- valueElem.InnerText = ((decimal)value).ToString(CultureInfo.InvariantCulture);
- }
- else
- {
- valueElem.InnerText = value.ToString();
- }
- }
- else
- {
- valueElem = CustomPropertiesXml.CreateElement("vt", "lpwstr", ExcelPackage.schemaVt);
- valueElem.InnerText = value.ToString();
- }
- node.AppendChild(valueElem);
- }
- #endregion
- #endregion
-
- #region Save
- /// <summary>
- /// Saves the document properties back to the package.
- /// </summary>
- internal void Save()
- {
- if (_xmlPropertiesCore != null)
- {
- _package.SavePart(_uriPropertiesCore, _xmlPropertiesCore);
- }
- if (_xmlPropertiesExtended != null)
- {
- _package.SavePart(_uriPropertiesExtended, _xmlPropertiesExtended);
- }
- if (_xmlPropertiesCustom != null)
- {
- _package.SavePart(_uriPropertiesCustom, _xmlPropertiesCustom);
- }
-
- }
- #endregion
-
+ _xmlPropertiesCore = GetXmlDocument(
+ xml,
+ _uriPropertiesCore,
+ "application/vnd.openxmlformats-package.core-properties+xml",
+ "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties");
+ }
+ return (_xmlPropertiesCore);
}
+ }
+
+ private XmlDocument GetXmlDocument(
+ string startXml,
+ Uri uri,
+ string contentType,
+ string relationship) {
+ XmlDocument xmlDoc;
+ if (_package.Package.PartExists(uri)) {
+ xmlDoc = _package.GetXmlFromUri(uri);
+ } else {
+ xmlDoc = new();
+ xmlDoc.LoadXml(startXml);
+
+ // Create a the part and add to the package
+ ZipPackagePart part = _package.Package.CreatePart(uri, contentType);
+
+ // Save it to the package
+ StreamWriter stream = new StreamWriter(part.GetStream(FileMode.Create, FileAccess.Write));
+ xmlDoc.Save(stream);
+ //stream.Close();
+
+ // create the relationship between the workbook and the new shared strings part
+ _package.Package.CreateRelationship(
+ UriHelper.GetRelativeUri(new("/xl", UriKind.Relative), uri),
+ TargetMode.Internal,
+ relationship);
+ }
+ return xmlDoc;
+ }
+
+ 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 date;
+ return DateTime.TryParse(_coreHelper.GetXmlNodeString(_createdPath), out 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) {
+ _xmlPropertiesExtended = GetXmlDocument(
+ string.Format(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><Properties xmlns:vt=\"{0}\" xmlns=\"{1}\"></Properties>",
+ ExcelPackage._schemaVt,
+ ExcelPackage._schemaExtended),
+ _uriPropertiesExtended,
+ "application/vnd.openxmlformats-officedocument.extended-properties+xml",
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties");
+ }
+ 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 date;
+ return DateTime.TryParse(_coreHelper.GetXmlNodeString(_modifiedPath), out 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");
+ }
+ }
+
+ private string GetExtendedPropertyValue(string propertyName) {
+ string retValue = null;
+ string searchString = string.Format("xp:Properties/xp:{0}", propertyName);
+ XmlNode node = ExtendedPropertiesXml.SelectSingleNode(searchString, NameSpaceManager);
+ if (node != null) {
+ retValue = node.InnerText;
+ }
+ return retValue;
+ }
+
+ /// <summary>
+ /// Provides access to the XML document which holds the document's custom properties
+ /// </summary>
+ public XmlDocument CustomPropertiesXml {
+ get {
+ if (_xmlPropertiesCustom == null) {
+ _xmlPropertiesCustom = GetXmlDocument(
+ string.Format(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><Properties xmlns:vt=\"{0}\" xmlns=\"{1}\"></Properties>",
+ ExcelPackage._schemaVt,
+ ExcelPackage._schemaCustom),
+ _uriPropertiesCustom,
+ "application/vnd.openxmlformats-officedocument.custom-properties+xml",
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties");
+ }
+ return (_xmlPropertiesCustom);
+ }
+ }
+
+ /// <summary>
+ /// Gets the value of a custom property
+ /// </summary>
+ /// <param name="propertyName">The name of the property</param>
+ /// <returns>The current value of the property</returns>
+ public object GetCustomPropertyValue(string propertyName) {
+ string searchString = string.Format("ctp:Properties/ctp:property[@name='{0}']", propertyName);
+ XmlElement node =
+ CustomPropertiesXml.SelectSingleNode(searchString, NameSpaceManager) as XmlElement;
+ if (node != null) {
+ string value = node.LastChild.InnerText;
+ switch (node.LastChild.LocalName) {
+ case "filetime":
+ DateTime dt;
+ if (DateTime.TryParse(value, out dt)) {
+ return dt;
+ }
+ return null;
+ case "i4":
+ int i;
+ if (int.TryParse(value, out i)) {
+ return i;
+ }
+ return null;
+ case "r8":
+ double d;
+ if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out d)) {
+ return d;
+ }
+ return null;
+ case "bool":
+ if (value == "true") {
+ return true;
+ }
+ if (value == "false") {
+ return false;
+ }
+ return null;
+ default:
+ return value;
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Allows you to set the value of a current custom property or create your own custom property.
+ /// </summary>
+ /// <param name="propertyName">The name of the property</param>
+ /// <param name="value">The value of the property</param>
+ public void SetCustomPropertyValue(string propertyName, object value) {
+ XmlNode allProps = CustomPropertiesXml.SelectSingleNode("ctp:Properties", NameSpaceManager);
+
+ var prop = string.Format("ctp:Properties/ctp:property[@name='{0}']", propertyName);
+ XmlElement node = CustomPropertiesXml.SelectSingleNode(prop, NameSpaceManager) as XmlElement;
+ if (node == null) {
+ int pid;
+ var maxNode = CustomPropertiesXml.SelectSingleNode(
+ "ctp:Properties/ctp:property[not(@pid <= preceding-sibling::ctp:property/@pid) and not(@pid <= following-sibling::ctp:property/@pid)]",
+ NameSpaceManager);
+ if (maxNode == null) {
+ pid = 2;
+ } else {
+ if (!int.TryParse(maxNode.Attributes["pid"].Value, out pid)) {
+ pid = 2;
+ }
+ pid++;
+ }
+ node = CustomPropertiesXml.CreateElement("property", ExcelPackage._schemaCustom);
+ node.SetAttribute("fmtid", "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}");
+ node.SetAttribute("pid", pid.ToString()); // custom property pid
+ node.SetAttribute("name", propertyName);
+
+ allProps.AppendChild(node);
+ } else {
+ while (node.ChildNodes.Count > 0) {
+ node.RemoveChild(node.ChildNodes[0]);
+ }
+ }
+ XmlElement valueElem;
+ if (value is bool) {
+ valueElem = CustomPropertiesXml.CreateElement("vt", "bool", ExcelPackage._schemaVt);
+ valueElem.InnerText = value.ToString().ToLower(CultureInfo.InvariantCulture);
+ } else if (value is DateTime) {
+ valueElem = CustomPropertiesXml.CreateElement("vt", "filetime", ExcelPackage._schemaVt);
+ valueElem.InnerText = ((DateTime)value).AddHours(-1).ToString("yyyy-MM-ddTHH:mm:ssZ");
+ } else if (value is short || value is int) {
+ valueElem = CustomPropertiesXml.CreateElement("vt", "i4", ExcelPackage._schemaVt);
+ valueElem.InnerText = value.ToString();
+ } else if (value is double || value is decimal || value is float || value is long) {
+ valueElem = CustomPropertiesXml.CreateElement("vt", "r8", ExcelPackage._schemaVt);
+ if (value is double) {
+ valueElem.InnerText = ((double)value).ToString(CultureInfo.InvariantCulture);
+ } else if (value is float) {
+ valueElem.InnerText = ((float)value).ToString(CultureInfo.InvariantCulture);
+ } else if (value is decimal) {
+ valueElem.InnerText = ((decimal)value).ToString(CultureInfo.InvariantCulture);
+ } else {
+ valueElem.InnerText = value.ToString();
+ }
+ } else {
+ valueElem = CustomPropertiesXml.CreateElement("vt", "lpwstr", ExcelPackage._schemaVt);
+ valueElem.InnerText = value.ToString();
+ }
+ node.AppendChild(valueElem);
+ }
+
+ /// <summary>
+ /// Saves the document properties back to the package.
+ /// </summary>
+ internal void Save() {
+ if (_xmlPropertiesCore != null) {
+ _package.SavePart(_uriPropertiesCore, _xmlPropertiesCore);
+ }
+ if (_xmlPropertiesExtended != null) {
+ _package.SavePart(_uriPropertiesExtended, _xmlPropertiesExtended);
+ }
+ if (_xmlPropertiesCustom != null) {
+ _package.SavePart(_uriPropertiesCustom, _xmlPropertiesCustom);
+ }
+ }
}
diff --git a/EPPlus/Packaging/ZipPackage.cs b/EPPlus/Packaging/ZipPackage.cs
index 12e3431..4dbed56 100644
--- a/EPPlus/Packaging/ZipPackage.cs
+++ b/EPPlus/Packaging/ZipPackage.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,305 +13,273 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Linq;
-using System.Text;
using System.IO;
using System.IO.Compression;
+using System.Linq;
+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,
+
+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>
+public 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;
}
- /// <summary>
- /// Represent an OOXML Zip package.
- /// </summary>
- public 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;
- }
- }
- Dictionary<string, ZipPackagePart> Parts = new Dictionary<string, ZipPackagePart>(StringComparer.InvariantCultureIgnoreCase);
- internal Dictionary<string, ContentType> _contentTypes = new Dictionary<string, ContentType>(StringComparer.InvariantCultureIgnoreCase);
- internal ZipPackage()
- {
- AddNew();
- }
+ }
- private void AddNew()
- {
- _contentTypes.Add("xml", new ContentType(ExcelPackage.schemaXmlExtension, true, "xml"));
- _contentTypes.Add("rels", new ContentType(ExcelPackage.schemaRelsExtension, true, "rels"));
- }
+ private Dictionary<string, ZipPackagePart> Parts = new(StringComparer.InvariantCultureIgnoreCase);
+ internal Dictionary<string, ContentType> _contentTypes = new(
+ StringComparer.InvariantCultureIgnoreCase);
- 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
- {
- using var inputStream = e.Open();
- var part = new ZipPackagePart(this, e);
- part.Stream = new MemoryStream();
- inputStream.CopyTo(part.Stream);
- 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.");
- }
- }
- }
+ internal ZipPackage() {
+ AddNew();
+ }
- private void AddContentTypes(Stream inputStream)
- {
- var doc = new XmlDocument();
- XmlHelper.LoadXmlSafe(doc, inputStream);
+ private void AddNew() {
+ _contentTypes.Add("xml", new(ExcelPackage._schemaXmlExtension, true, "xml"));
+ _contentTypes.Add("rels", new(ExcelPackage._schemaRelsExtension, true, "rels"));
+ }
- foreach (XmlElement c in doc.DocumentElement.ChildNodes)
- {
- ContentType ct;
- if (string.IsNullOrEmpty(c.GetAttribute("Extension")))
- {
- ct = new ContentType(c.GetAttribute("ContentType"), false, c.GetAttribute("PartName"));
- }
- else
- {
- ct = new ContentType(c.GetAttribute("ContentType"), true, c.GetAttribute("Extension"));
- }
- _contentTypes.Add(GetUriKey(ct.Match), ct);
+ 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 {
+ using var inputStream = e.Open();
+ var part = new ZipPackagePart(this, e);
+ part.Stream = new();
+ inputStream.CopyTo(part.Stream);
+ Parts.Add(GetUriKey(e.FullName), part);
}
+ }
}
-
- #region Methods
- internal ZipPackagePart CreatePart(Uri partUri, string contentType)
- {
- return CreatePart(partUri, contentType, CompressionLevel.Default);
+ }
+ 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);
}
- internal ZipPackagePart CreatePart(Uri partUri, string contentType, CompressionLevel compressionLevel)
- {
- if (PartExists(partUri))
- {
- throw (new InvalidOperationException("Part already exist"));
- }
-
- var part = new ZipPackagePart(this, partUri, contentType, compressionLevel);
- _contentTypes.Add(GetUriKey(part.Uri.OriginalString), new ContentType(contentType, false, part.Uri.OriginalString));
- Parts.Add(GetUriKey(part.Uri.OriginalString), part);
- return part;
+ 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;
}
- internal ZipPackagePart GetPart(Uri partUri)
- {
- if (PartExists(partUri))
- {
- return Parts.Single(x => x.Key.Equals(GetUriKey(partUri.OriginalString),StringComparison.InvariantCultureIgnoreCase)).Value;
- }
- else
- {
- 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));
- }
- #endregion
-
- 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);
- }
- rels=null;
- _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);
- /**** ContentType****/
- 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);
- }
- //return ms;
- }
-
- 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.AppendFormat("<Default ContentType=\"{0}\" Extension=\"{1}\"/>", ct.Name, ct.Match);
- }
- else
- {
- xml.AppendFormat("<Override ContentType=\"{0}\" PartName=\"{1}\" />", ct.Name, GetUriKey(ct.Match));
- }
- }
- xml.Append("</Types>");
- return xml.ToString();
- }
- CompressionLevel _compression = CompressionLevel.Default;
- public CompressionLevel Compression
- {
- get
- {
- return _compression;
- }
- set
- {
- foreach (var part in Parts.Values)
- {
- if (part.CompressionLevel == _compression)
- {
- part.CompressionLevel = value;
- }
- }
- _compression = value;
- }
- }
+ }
+ 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 ZipPackagePart CreatePart(Uri partUri, string contentType) {
+ return CreatePart(partUri, contentType, CompressionLevel.Default);
+ }
+
+ internal ZipPackagePart CreatePart(
+ Uri partUri,
+ string contentType,
+ CompressionLevel compressionLevel) {
+ if (PartExists(partUri)) {
+ throw (new InvalidOperationException("Part already exist"));
+ }
+
+ var part = new ZipPackagePart(this, partUri, contentType, compressionLevel);
+ _contentTypes.Add(
+ GetUriKey(part.Uri.OriginalString),
+ new(contentType, false, part.Uri.OriginalString));
+ Parts.Add(GetUriKey(part.Uri.OriginalString), part);
+ return 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);
+ }
+ rels = null;
+ _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);
+ /**** ContentType****/
+ 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);
+ }
+ //return ms;
+ }
+
+ 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.AppendFormat("<Default ContentType=\"{0}\" Extension=\"{1}\"/>", ct.Name, ct.Match);
+ } else {
+ xml.AppendFormat(
+ "<Override ContentType=\"{0}\" PartName=\"{1}\" />",
+ ct.Name,
+ GetUriKey(ct.Match));
+ }
+ }
+ xml.Append("</Types>");
+ return xml.ToString();
+ }
+
+ private CompressionLevel _compression = CompressionLevel.Default;
+
+ public CompressionLevel Compression {
+ get => _compression;
+ set {
+ foreach (var part in Parts.Values) {
+ if (part.CompressionLevel == _compression) {
+ part.CompressionLevel = value;
+ }
+ }
+ _compression = value;
+ }
+ }
}
diff --git a/EPPlus/Packaging/ZipPackagePart.cs b/EPPlus/Packaging/ZipPackagePart.cs
index 06ca810..407428d 100644
--- a/EPPlus/Packaging/ZipPackagePart.cs
+++ b/EPPlus/Packaging/ZipPackagePart.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,149 +13,135 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.IO.Compression;
-namespace OfficeOpenXml.Packaging
-{
- internal class ZipPackagePart : ZipPackageRelationshipBase, IDisposable
- {
- internal delegate void SaveHandlerDelegate(StreamWriter streamWriter);
+namespace OfficeOpenXml.Packaging;
- internal ZipPackagePart(ZipPackage package, ZipArchiveEntry entry)
- {
- Package = package;
- SaveHandler = null;
- Uri = new Uri(package.GetUriKey(entry.FullName), UriKind.Relative);
- }
- internal ZipPackagePart(ZipPackage package, Uri partUri, string contentType, CompressionLevel compressionLevel)
- {
- Package = package;
- //Entry = new ZipEntry();
- //Entry.FileName = partUri.OriginalString.Replace('/','\\');
- Uri = partUri;
- ContentType = contentType;
- CompressionLevel = compressionLevel;
- }
- internal ZipPackage Package { get; set; }
- internal CompressionLevel CompressionLevel;
- MemoryStream _stream = null;
- internal MemoryStream Stream
- {
- get
- {
- return _stream;
- }
- set
- {
- _stream = value;
- }
- }
- internal override ZipPackageRelationship CreateRelationship(Uri targetUri, TargetMode targetMode, string relationshipType)
- {
+internal class ZipPackagePart : ZipPackageRelationshipBase, IDisposable {
+ internal delegate void SaveHandlerDelegate(StreamWriter streamWriter);
- var rel = base.CreateRelationship(targetUri, targetMode, relationshipType);
- rel.SourceUri = Uri;
- return rel;
- }
- internal MemoryStream GetStream()
- {
- return GetStream(FileMode.OpenOrCreate, FileAccess.ReadWrite);
- }
- internal MemoryStream GetStream(FileMode fileMode)
- {
- return GetStream(FileMode.Create, FileAccess.ReadWrite);
- }
- internal MemoryStream GetStream(FileMode fileMode, FileAccess fileAccess)
- {
- if (_stream == null || fileMode == FileMode.CreateNew || fileMode == FileMode.Create)
- {
- _stream = new MemoryStream();
- }
- else
- {
- _stream.Seek(0, SeekOrigin.Begin);
- }
- return _stream;
- }
+ internal ZipPackagePart(ZipPackage package, ZipArchiveEntry entry) {
+ Package = package;
+ SaveHandler = null;
+ Uri = new(package.GetUriKey(entry.FullName), UriKind.Relative);
+ }
- string _contentType = "";
- public string ContentType
- {
- get
- {
- return _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 ZipPackage.ContentType(value, false, Uri.OriginalString));
- }
- }
- _contentType = value;
- }
- }
- public Uri Uri { get; private set; }
- internal SaveHandlerDelegate SaveHandler
- {
- get;
- set;
- }
- internal void WriteZip(ZipArchive zipArchive)
- {
- byte[] b;
- if (SaveHandler == null)
- {
- b = GetStream().ToArray();
- if (b.Length == 0) //Make sure the file isn't empty. DotNetZip streams does not seems to handle zero sized files.
- {
- return;
- }
- var zipEntry = zipArchive.CreateEntry(Uri.OriginalString);
- using var os = zipEntry.Open();
- os.Write(b);
- }
- else
- {
- var zipEntry = zipArchive.CreateEntry(Uri.OriginalString);
- using var streamWriter = new StreamWriter(zipEntry.Open());
- SaveHandler(streamWriter);
- }
+ internal ZipPackagePart(
+ ZipPackage package,
+ Uri partUri,
+ string contentType,
+ CompressionLevel compressionLevel) {
+ Package = package;
+ //Entry = new ZipEntry();
+ //Entry.FileName = partUri.OriginalString.Replace('/','\\');
+ Uri = partUri;
+ ContentType = contentType;
+ CompressionLevel = compressionLevel;
+ }
- 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");
- }
- b = null;
- }
+ internal ZipPackage Package { get; set; }
+ internal CompressionLevel CompressionLevel;
+ private MemoryStream _stream;
- public void Dispose()
- {
- _stream.Close();
- _stream.Dispose();
- }
+ internal MemoryStream Stream {
+ get => _stream;
+ set => _stream = value;
+ }
+
+ 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 GetStream(FileMode.OpenOrCreate, FileAccess.ReadWrite);
+ }
+
+ internal MemoryStream GetStream(FileMode fileMode) {
+ return GetStream(FileMode.Create, FileAccess.ReadWrite);
+ }
+
+ internal MemoryStream GetStream(FileMode fileMode, FileAccess fileAccess) {
+ if (_stream == null || fileMode == FileMode.CreateNew || fileMode == FileMode.Create) {
+ _stream = new();
+ } else {
+ _stream.Seek(0, SeekOrigin.Begin);
}
+ return _stream;
+ }
+
+ 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; private set; }
+
+ internal SaveHandlerDelegate SaveHandler { get; set; }
+
+ internal void WriteZip(ZipArchive zipArchive) {
+ byte[] b;
+ if (SaveHandler == null) {
+ b = GetStream().ToArray();
+ if (b.Length
+ == 0) //Make sure the file isn't empty. DotNetZip streams does not seems to handle zero sized files.
+ {
+ return;
+ }
+ var zipEntry = zipArchive.CreateEntry(Uri.OriginalString);
+ using var os = zipEntry.Open();
+ os.Write(b);
+ } 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");
+ }
+ b = null;
+ }
+
+ public void Dispose() {
+ _stream.Close();
+ _stream.Dispose();
+ }
}
diff --git a/EPPlus/Packaging/ZipPackageRelationship.cs b/EPPlus/Packaging/ZipPackageRelationship.cs
index 7bb7a50..15c4539 100644
--- a/EPPlus/Packaging/ZipPackageRelationship.cs
+++ b/EPPlus/Packaging/ZipPackageRelationship.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,35 +13,34 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
-{
- public class ZipPackageRelationship
- {
- public Uri TargetUri { get; internal set; }
+namespace OfficeOpenXml.Packaging;
- public Uri SourceUri { get; internal set; }
+public class ZipPackageRelationship {
+ public Uri TargetUri { get; internal set; }
- public string RelationshipType { get; internal set; }
+ public Uri SourceUri { get; internal set; }
- public TargetMode TargetMode { get; internal set; }
+ public string RelationshipType { get; internal set; }
- public string Id { 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
index b0bd124..6c0411f 100644
--- a/EPPlus/Packaging/ZipPackageRelationshipBase.cs
+++ b/EPPlus/Packaging/ZipPackageRelationshipBase.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,113 +13,113 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
-{
- public abstract class ZipPackageRelationshipBase
- {
- protected ZipPackageRelationshipCollection _rels = new ZipPackageRelationshipCollection();
- 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"))
- {
- int num;
- if (int.TryParse(id.Substring(3), out 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++).ToString();
- _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);
+namespace OfficeOpenXml.Packaging;
- 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 Uri(c.GetAttribute("Target"), UriKind.RelativeOrAbsolute);
- }
- catch
- {
- //The URI is not a valid URI. Encode it to make i valid.
- rel.TargetUri = new Uri(Uri.EscapeUriString("Invalid:URI "+c.GetAttribute("Target")), UriKind.RelativeOrAbsolute);
- }
- if (!string.IsNullOrEmpty(source))
- {
- rel.SourceUri = new Uri(source, UriKind.Relative);
- }
- if (rel.Id.StartsWith("rid", StringComparison.InvariantCultureIgnoreCase))
- {
- int id;
- if (int.TryParse(rel.Id.Substring(3), out 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);
- }
+public 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")) {
+ int num;
+ if (int.TryParse(id.Substring(3), out num)) {
+ if (num == maxRId - 1) {
+ maxRId--;
}
+ }
}
-}
\ No newline at end of file
+ }
+
+ 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)) {
+ int id;
+ if (int.TryParse(rel.Id.Substring(3), out 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
index 0820322..dab1030 100644
--- a/EPPlus/Packaging/ZipPackageRelationshipCollection.cs
+++ b/EPPlus/Packaging/ZipPackageRelationshipCollection.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,93 +13,85 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
-{
- public class ZipPackageRelationshipCollection : IEnumerable<ZipPackageRelationship>
- {
- internal protected Dictionary<string, ZipPackageRelationship> _rels = new Dictionary<string, ZipPackageRelationship>(StringComparer.InvariantCultureIgnoreCase);
- internal void Add(ZipPackageRelationship item)
- {
- _rels.Add(item.Id, item);
- }
- public IEnumerator<ZipPackageRelationship> GetEnumerator()
- {
- return _rels.Values.GetEnumerator();
- }
+namespace OfficeOpenXml.Packaging;
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return _rels.Values.GetEnumerator();
- }
+public class ZipPackageRelationshipCollection : IEnumerable<ZipPackageRelationship> {
+ protected internal Dictionary<string, ZipPackageRelationship> _rels = new(
+ StringComparer.InvariantCultureIgnoreCase);
- internal void Remove(string id)
- {
- _rels.Remove(id);
- }
- internal bool ContainsKey(string id)
- {
- return _rels.ContainsKey(id);
- }
- internal ZipPackageRelationship this[string id]
- {
- get
- {
- return _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 Add(ZipPackageRelationship item) {
+ _rels.Add(item.Id, item);
+ }
- 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 IEnumerator<ZipPackageRelationship> GetEnumerator() {
+ return _rels.Values.GetEnumerator();
+ }
- public int Count
- {
- get
- {
- return _rels.Count;
- }
- }
+ 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 {
+ get { return _rels.Count; }
+ }
}
diff --git a/EPPlus/Properties/AssemblyInfo.cs b/EPPlus/Properties/AssemblyInfo.cs
index b4b32ad..2fc9137 100644
--- a/EPPlus/Properties/AssemblyInfo.cs
+++ b/EPPlus/Properties/AssemblyInfo.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,17 +13,17 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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-SEP-2009
@@ -34,19 +34,22 @@
using System.Runtime.InteropServices;
using System.Security;
-// General Information about an assembly is controlled through the following
+// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("EPPlus 4.0.4")]
-[assembly: AssemblyDescription("Allows Excel files(xlsx;xlsm) to be created on the server. See epplus.codeplex.com")]
+[assembly: AssemblyDescription(
+ "Allows Excel files(xlsx;xlsm) to be created on the server. See epplus.codeplex.com")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("EPPlus")]
[assembly: AssemblyProduct("EPPlus 4.0.4")]
-[assembly: AssemblyCopyright("Copyright 2009- ©Jan Källman. Parts of the Interface comes from ExcelPackage-project")]
+[assembly: AssemblyCopyright(
+ "Copyright 2009- ©Jan Källman. Parts of the Interface comes from ExcelPackage-project")]
[assembly: AssemblyTrademark("The GNU Lesser General Public License (LGPL)")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
-[assembly: InternalsVisibleTo("EPPlusTest, PublicKey=00240000048000009400000006020000002400005253413100040000010001001dd11308ec93a6ebcec727e183a8972dc6f95c23ecc34aa04f40cbfc9c17b08b4a0ea5c00dcd203bace44d15a30ce8796e38176ae88e960ceff9cc439ab938738ba0e603e3d155fc298799b391c004fc0eb4393dd254ce25db341eb43303e4c488c9500e126f1288594f0710ec7d642e9c72e76dd860649f1c48249c00e31fba")]
+[assembly: InternalsVisibleTo(
+ "EPPlusTest, PublicKey=00240000048000009400000006020000002400005253413100040000010001001dd11308ec93a6ebcec727e183a8972dc6f95c23ecc34aa04f40cbfc9c17b08b4a0ea5c00dcd203bace44d15a30ce8796e38176ae88e960ceff9cc439ab938738ba0e603e3d155fc298799b391c004fc0eb4393dd254ce25db341eb43303e4c488c9500e126f1288594f0710ec7d642e9c72e76dd860649f1c48249c00e31fba")]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("9dd43b8d-c4fe-4a8b-ad6e-47ef83bbbb01")]
@@ -54,12 +57,12 @@
// Version information for an assembly consists of the following four values:
//
// Major Version
-// Minor Version
+// Minor Version
// Build Number
// Revision
//
-// You can specify all the values or you can default the Revision and Build Numbers
+// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.0.4.0")]
[assembly: AssemblyFileVersion("4.0.4.0")]
-[assembly: AllowPartiallyTrustedCallers]
\ No newline at end of file
+[assembly: AllowPartiallyTrustedCallers]
diff --git a/EPPlus/RangeCollection.cs b/EPPlus/RangeCollection.cs
index 2e3443e..90fbfb9 100644
--- a/EPPlus/RangeCollection.cs
+++ b/EPPlus/RangeCollection.cs
@@ -1,24 +1,3 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
@@ -34,304 +13,269 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Text;
using System.Collections;
-using OfficeOpenXml.Drawing.Vml;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>
- {
- #region IComparer<IndexItem> Members
- int IComparer<IndexItem>.Compare(IndexItem x, IndexItem y)
- {
- return x.RangeID < y.RangeID ? -1 : x.RangeID > y.RangeID ? 1 : 0;
- }
+using System.Collections.Generic;
- #endregion
- }
- IndexItem[] _cellIndex;
- List<IRangeID> _cells;
- static readonly Compare _comparer=new Compare();
- /// <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 IndexItem(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]
- {
- get
- {
- return _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]
- {
- get
- {
- return _cells[_cellIndex[Index].ListPointer];
- }
- }
- internal int Count
- {
- get
- {
- return _cells.Count;
- }
- }
- internal void Add(IRangeID cell)
- {
- var ix = IndexOf(cell.RangeID);
- if (ix >= 0)
- {
- throw (new Exception("Item already exists"));
- }
- Insert(~ix, cell);
- }
- internal void Delete(ulong key)
- {
- var ix = IndexOf(key);
- if (ix < 0)
- {
- throw (new Exception("Key does not exists"));
- }
- int listPointer = _cellIndex[ix].ListPointer;
- Array.Copy(_cellIndex, ix + 1, _cellIndex, ix, _cells.Count - ix - 1);
- _cells.RemoveAt(listPointer);
+namespace OfficeOpenXml;
- //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<IndexItem>(_cellIndex, 0, _cells.Count, new IndexItem(key), _comparer);
- }
- internal bool ContainsKey(ulong key)
- {
- return IndexOf(key) < 0 ? false : true;
- }
- int _size { get; set; }
- #region "RangeID manipulation methods"
- /// <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 Exception("Working on it..."));
- }
- internal void DeleteColumn(ulong ColumnID,int columns)
- {
- throw (new Exception("Working on it..."));
- }
- #endregion
- #region "Private Methods"
- /// <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 IndexItem(cell.RangeID, _cells.Count);
- _cells.Add(cell);
- }
- #endregion
-
- #region IEnumerator<IRangeID> Members
-
- IRangeID IEnumerator<IRangeID>.Current
- {
- get { throw new NotImplementedException(); }
- }
-
- #endregion
-
- #region IDisposable for the enumerator Members
-
- void IDisposable.Dispose()
- {
- _ix = -1;
- }
-
- #endregion
-
- #region IEnumerator Members
- 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;
- }
-
- #endregion
-
- #region IEnumerable Members
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return this.MemberwiseClone() as IEnumerator;
- }
-
- #endregion
+/// <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] {
+ get { return _cells[_cellIndex[index].ListPointer]; }
+ }
+
+ internal int Count {
+ get { return _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
index bbaa6bd..7bbbcd0 100644
--- a/EPPlus/Style/Dxf/DxfStyleBase.cs
+++ b/EPPlus/Style/Dxf/DxfStyleBase.cs
@@ -1,98 +1,79 @@
-using System;
-using System.Collections.Generic;
+using System;
using System.Globalization;
-using System.Linq;
-using System.Text;
-using System.Xml;
-namespace OfficeOpenXml.Style.Dxf
-{
- public abstract class DxfStyleBase<T>
- {
- protected ExcelStyles _styles;
- internal DxfStyleBase(ExcelStyles styles)
- {
- _styles = styles;
- AllowChange = false; //Don't touch this value in the styles.xml (by default). When Dxfs is fully implemented this can be removed.
- }
- 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.Color != null)
- {
- SetValue(helper, path + "/@rgb", color.Color.Value.ToArgb().ToString("x"));
- }
- 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 internal string GetAsString(object v)
- {
- return (v ?? "").ToString();
- }
- /// <summary>
- /// Is this value allowed to be changed?
- /// </summary>
- protected internal bool AllowChange { get; set; }
+namespace OfficeOpenXml.Style.Dxf;
+
+public abstract class DxfStyleBase<T> {
+ protected ExcelStyles _styles;
+
+ internal DxfStyleBase(ExcelStyles styles) {
+ _styles = styles;
+ AllowChange = false; //Don't touch this value in the styles.xml (by default). When Dxfs is fully implemented this can be removed.
+ }
+
+ 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.Color != null) {
+ SetValue(helper, path + "/@rgb", color.Color.Value.ToArgb().ToString("x"));
+ } 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 internal string GetAsString(object v) {
+ return (v ?? "").ToString();
+ }
+
+ /// <summary>
+ /// Is this value allowed to be changed?
+ /// </summary>
+ protected internal bool AllowChange { get; set; }
}
diff --git a/EPPlus/Style/Dxf/ExcelDxfBorder.cs b/EPPlus/Style/Dxf/ExcelDxfBorder.cs
index b3fd096..12bcc84 100644
--- a/EPPlus/Style/Dxf/ExcelDxfBorder.cs
+++ b/EPPlus/Style/Dxf/ExcelDxfBorder.cs
@@ -1,106 +1,81 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml;
+namespace OfficeOpenXml.Style.Dxf;
-namespace OfficeOpenXml.Style.Dxf
-{
- public class ExcelDxfBorderBase : DxfStyleBase<ExcelDxfBorderBase>
- {
- internal ExcelDxfBorderBase(ExcelStyles styles)
- : base(styles)
- {
- Left=new ExcelDxfBorderItem(_styles);
- Right = new ExcelDxfBorderItem(_styles);
- Top = new ExcelDxfBorderItem(_styles);
- Bottom = new ExcelDxfBorderItem(_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;
- //}
+public class ExcelDxfBorderBase : DxfStyleBase<ExcelDxfBorderBase> {
+ internal ExcelDxfBorderBase(ExcelStyles styles)
+ : base(styles) {
+ Left = new(_styles);
+ Right = new(_styles);
+ Top = new(_styles);
+ Bottom = new(_styles);
+ }
- protected internal override string Id
- {
- get
- {
- return Top.Id + Bottom.Id + Left.Id + Right.Id/* + Diagonal.Id + GetAsString(DiagonalUp) + GetAsString(DiagonalDown)*/;
- }
- }
+ /// <summary>
+ /// Left border style
+ /// </summary>
+ public ExcelDxfBorderItem Left { get; internal set; }
- 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
- {
- get
- {
- return Left.HasValue ||
- Right.HasValue ||
- Top.HasValue ||
- Bottom.HasValue;
- }
- }
- protected internal override ExcelDxfBorderBase Clone()
- {
- return new ExcelDxfBorderBase(_styles) { Bottom = Bottom.Clone(), Top=Top.Clone(), Left=Left.Clone(), Right=Right.Clone() };
- }
- }
+ /// <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
index 9223bea..f068605 100644
--- a/EPPlus/Style/Dxf/ExcelDxfBorderItem.cs
+++ b/EPPlus/Style/Dxf/ExcelDxfBorderItem.cs
@@ -1,44 +1,29 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml;
+namespace OfficeOpenXml.Style.Dxf;
-namespace OfficeOpenXml.Style.Dxf
-{
- public class ExcelDxfBorderItem : DxfStyleBase<ExcelDxfBorderItem>
- {
- internal ExcelDxfBorderItem(ExcelStyles styles) :
- base(styles)
- {
- Color=new ExcelDxfColor(styles);
- }
- public ExcelBorderStyle? Style { get; set;}
- public ExcelDxfColor Color { get; internal set; }
+public class ExcelDxfBorderItem : DxfStyleBase<ExcelDxfBorderItem> {
+ internal ExcelDxfBorderItem(ExcelStyles styles)
+ : base(styles) {
+ Color = new(styles);
+ }
- protected internal override string Id
- {
- get
- {
- return GetAsString(Style) + "|" + (Color == null ? "" : Color.Id);
- }
- }
+ public ExcelBorderStyle? Style { get; set; }
- 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
- {
- get
- {
- return Style != null || Color.HasValue;
- }
- }
- protected internal override ExcelDxfBorderItem Clone()
- {
- return new ExcelDxfBorderItem(_styles) { Style = Style, Color = Color };
- }
- }
+ 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
index 0ad7ee8..4e6c4f9 100644
--- a/EPPlus/Style/Dxf/ExcelDxfColor.cs
+++ b/EPPlus/Style/Dxf/ExcelDxfColor.cs
@@ -1,46 +1,47 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+using System;
using System.Drawing;
-using System.Xml;
-namespace OfficeOpenXml.Style.Dxf
-{
- public class ExcelDxfColor : DxfStyleBase<ExcelDxfColor>
+namespace OfficeOpenXml.Style.Dxf;
- {
- public ExcelDxfColor(ExcelStyles styles) : base(styles)
- {
+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 Color? Color { get; set; }
- protected internal override string Id
- {
- get { return GetAsString(Theme) + "|" + GetAsString(Index) + "|" + GetAsString(Auto) + "|" + GetAsString(Tint) + "|" + GetAsString(Color==null ? "" : ((Color)Color.Value).ToArgb().ToString("x")); }
- }
- protected internal override ExcelDxfColor Clone()
- {
- return new ExcelDxfColor(_styles) { Theme = Theme, Index = Index, Color = Color, Auto = Auto, Tint = Tint };
- }
- protected internal override bool HasValue
- {
- get
- {
- return Theme != null ||
- Index != null ||
- Auto != null ||
- Tint != null ||
- Color != null;
- }
- }
- protected internal override void CreateNodes(XmlHelper helper, string path)
- {
- throw new NotImplementedException();
- }
- }
+ public int? Theme { get; set; }
+
+ public int? Index { get; set; }
+
+ public bool? Auto { get; set; }
+
+ public double? Tint { get; set; }
+
+ public Color? Color { get; set; }
+
+ protected internal override string Id =>
+ GetAsString(Theme)
+ + "|"
+ + GetAsString(Index)
+ + "|"
+ + GetAsString(Auto)
+ + "|"
+ + GetAsString(Tint)
+ + "|"
+ + GetAsString(Color == null ? "" : Color.Value.ToArgb().ToString("x"));
+
+ protected internal override ExcelDxfColor Clone() {
+ return new(_styles) {
+ Theme = Theme,
+ Index = Index,
+ Color = Color,
+ Auto = Auto,
+ Tint = Tint,
+ };
+ }
+
+ protected internal override bool HasValue =>
+ Theme != null || Index != null || Auto != null || Tint != null || Color != 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
index 26a8c10..f4bf1d3 100644
--- a/EPPlus/Style/Dxf/ExcelDxfFill.cs
+++ b/EPPlus/Style/Dxf/ExcelDxfFill.cs
@@ -1,57 +1,46 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
-using System.Xml;
+namespace OfficeOpenXml.Style.Dxf;
-namespace OfficeOpenXml.Style.Dxf
-{
- public class ExcelDxfFill : DxfStyleBase<ExcelDxfFill>
- {
- public ExcelDxfFill(ExcelStyles styles)
- : base(styles)
- {
- PatternColor = new ExcelDxfColor(styles);
- BackgroundColor = new ExcelDxfColor(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; }
+public class ExcelDxfFill : DxfStyleBase<ExcelDxfFill> {
+ public ExcelDxfFill(ExcelStyles styles)
+ : base(styles) {
+ PatternColor = new(styles);
+ BackgroundColor = new(styles);
+ }
- protected internal override string Id
- {
- get
- {
- return 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);
- }
+ public ExcelFillStyle? PatternType { get; set; }
- protected internal override bool HasValue
- {
- get
- {
- return PatternType != null ||
- PatternColor.HasValue ||
- BackgroundColor.HasValue;
- }
- }
- protected internal override ExcelDxfFill Clone()
- {
- return new ExcelDxfFill(_styles) {PatternType=PatternType, PatternColor=PatternColor.Clone(), BackgroundColor=BackgroundColor.Clone()};
- }
- }
+ /// <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
index c326f98..aae7d61 100644
--- a/EPPlus/Style/Dxf/ExcelDxfFontBase.cs
+++ b/EPPlus/Style/Dxf/ExcelDxfFontBase.cs
@@ -1,85 +1,72 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
-using System.Xml;
+namespace OfficeOpenXml.Style.Dxf;
-namespace OfficeOpenXml.Style.Dxf
-{
- public class ExcelDxfFontBase : DxfStyleBase<ExcelDxfFontBase>
- {
- public ExcelDxfFontBase(ExcelStyles styles)
- : base(styles)
- {
- Color = new ExcelDxfColor(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 class ExcelDxfFontBase : DxfStyleBase<ExcelDxfFontBase> {
+ public ExcelDxfFontBase(ExcelStyles styles)
+ : base(styles) {
+ Color = new(styles);
+ }
- public ExcelUnderLineType? Underline { get; set; }
+ /// <summary>
+ /// Font bold
+ /// </summary>
+ public bool? Bold { get; set; }
- protected internal override string Id
- {
- get
- {
- return GetAsString(Bold) + "|" + GetAsString(Italic) + "|" + GetAsString(Strike) + "|" + (Color ==null ? "" : Color.Id) + "|" /*+ GetAsString(VerticalAlign) + "|"*/ + GetAsString(Underline);
- }
- }
+ /// <summary>
+ /// Font Italic
+ /// </summary>
+ public bool? Italic { get; set; }
- 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
- {
- get
- {
- return Bold != null ||
- Italic != null ||
- Strike != null ||
- Underline != null ||
- Color.HasValue;
- }
- }
- protected internal override ExcelDxfFontBase Clone()
- {
- return new ExcelDxfFontBase(_styles) { Bold = Bold, Color = Color.Clone(), Italic = Italic, Strike = Strike, Underline = Underline };
- }
- }
+ /// <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
index 1d6ffd0..e00114c 100644
--- a/EPPlus/Style/Dxf/ExcelDxfNumberFormat.cs
+++ b/EPPlus/Style/Dxf/ExcelDxfNumberFormat.cs
@@ -1,105 +1,77 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml;
+namespace OfficeOpenXml.Style.Dxf;
-namespace OfficeOpenXml.Style.Dxf
-{
- public class ExcelDxfNumberFormat : DxfStyleBase<ExcelDxfNumberFormat>
- {
- public ExcelDxfNumberFormat(ExcelStyles styles) : base(styles)
- {
+public class ExcelDxfNumberFormat : DxfStyleBase<ExcelDxfNumberFormat> {
+ public ExcelDxfNumberFormat(ExcelStyles styles)
+ : base(styles) {}
- }
- 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
- {
- return _numFmtID;
- }
- internal set
- {
- _numFmtID = value;
- }
- }
- string _format="";
- public string Format
- {
- get
- {
- return _format;
- }
- set
- {
- _format = value;
- NumFmtID = ExcelNumberFormat.GetFromBuildIdFromFormat(value);
- }
- }
+ private int _numFmtID = int.MinValue;
- protected internal override string Id
- {
- get
- {
- return Format;
- }
- }
+ /// <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;
+ }
- 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
- {
- get
- {
- return !string.IsNullOrEmpty(Format);
- }
- }
- protected internal override ExcelDxfNumberFormat Clone()
- {
- return new ExcelDxfNumberFormat(_styles) { NumFmtID = NumFmtID, Format = Format };
- }
+ 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
index c2143e8..4cb8bba 100644
--- a/EPPlus/Style/Dxf/ExcelDxfStyle.cs
+++ b/EPPlus/Style/Dxf/ExcelDxfStyle.cs
@@ -1,153 +1,155 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Text;
-using System.Xml;
+using System;
using System.Drawing;
+using System.Globalization;
+using System.Xml;
-namespace OfficeOpenXml.Style.Dxf
-{
- public class ExcelDxfStyleConditionalFormatting : DxfStyleBase<ExcelDxfStyleConditionalFormatting>
- {
- XmlHelperInstance _helper;
- internal ExcelDxfStyleConditionalFormatting(XmlNamespaceManager nameSpaceManager, XmlNode topNode, ExcelStyles styles) : base(styles)
- {
- NumberFormat = new ExcelDxfNumberFormat(_styles);
- Font = new ExcelDxfFontBase(_styles);
- Border = new ExcelDxfBorderBase(_styles);
- Fill = new ExcelDxfFill(_styles);
- if (topNode != null)
- {
- _helper = new XmlHelperInstance(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);
- }
+namespace OfficeOpenXml.Style.Dxf;
- 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");
+public class ExcelDxfStyleConditionalFormatting : DxfStyleBase<ExcelDxfStyleConditionalFormatting> {
+ private XmlHelperInstance _helper;
- 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");
+ 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);
+ }
- 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 XmlHelperInstance(nameSpaceManager);
- }
- _helper.SchemaNodeOrder = new string[] { "font", "numFmt", "fill", "border" };
- }
- private ExcelDxfBorderItem GetBorderItem(XmlHelperInstance 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)
- {
- if (style == "") return ExcelBorderStyle.None;
- string sInStyle = style.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture) + style.Substring(1, style.Length - 1);
- try
- {
- return (ExcelBorderStyle)Enum.Parse(typeof(ExcelBorderStyle), sInStyle);
- }
- catch
- {
- return ExcelBorderStyle.None;
- }
+ 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");
- }
- private ExcelFillStyle GetPatternTypeEnum(string patternType)
- {
- if (patternType == "") return ExcelFillStyle.None;
- patternType = patternType.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture) + patternType.Substring(1, patternType.Length - 1);
- try
- {
- return (ExcelFillStyle)Enum.Parse(typeof(ExcelFillStyle), patternType);
- }
- catch
- {
- return ExcelFillStyle.None;
- }
- }
- private ExcelDxfColor GetColor(XmlHelperInstance helper, string path)
- {
- ExcelDxfColor ret = new ExcelDxfColor(_styles);
- ret.Theme = helper.GetXmlNodeIntNull(path + "/@theme");
- ret.Index = helper.GetXmlNodeIntNull(path + "/@indexed");
- string rgb=helper.GetXmlNodeString(path + "/@rgb");
- if(rgb!="")
- {
- ret.Color = Color.FromArgb( int.Parse(rgb.Substring(0, 2), System.Globalization.NumberStyles.AllowHexSpecifier),
- int.Parse(rgb.Substring(2, 2), System.Globalization.NumberStyles.AllowHexSpecifier),
- int.Parse(rgb.Substring(4, 2), System.Globalization.NumberStyles.AllowHexSpecifier),
- int.Parse(rgb.Substring(6, 2), System.Globalization.NumberStyles.AllowHexSpecifier));
- }
- 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
- {
- get
- {
- return 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;
- }
+ 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");
- 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
- {
- get { return Font.HasValue || NumberFormat.HasValue || Fill.HasValue || Border.HasValue; }
- }
+ 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);
}
+ _helper.SchemaNodeOrder = new[] { "font", "numFmt", "fill", "border" };
+ }
+
+ private ExcelDxfBorderItem GetBorderItem(XmlHelperInstance 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) {
+ if (style == "") {
+ return ExcelBorderStyle.None;
+ }
+ string sInStyle =
+ style.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture)
+ + style.Substring(1, style.Length - 1);
+ try {
+ return (ExcelBorderStyle)Enum.Parse(typeof(ExcelBorderStyle), sInStyle);
+ } catch {
+ return ExcelBorderStyle.None;
+ }
+ }
+
+ private ExcelFillStyle GetPatternTypeEnum(string patternType) {
+ if (patternType == "") {
+ return ExcelFillStyle.None;
+ }
+ patternType =
+ patternType.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture)
+ + patternType.Substring(1, patternType.Length - 1);
+ try {
+ return (ExcelFillStyle)Enum.Parse(typeof(ExcelFillStyle), patternType);
+ } catch {
+ return ExcelFillStyle.None;
+ }
+ }
+
+ private ExcelDxfColor GetColor(XmlHelperInstance helper, string path) {
+ ExcelDxfColor ret = new ExcelDxfColor(_styles);
+ ret.Theme = helper.GetXmlNodeIntNull(path + "/@theme");
+ ret.Index = helper.GetXmlNodeIntNull(path + "/@indexed");
+ string rgb = helper.GetXmlNodeString(path + "/@rgb");
+ if (rgb != "") {
+ ret.Color = Color.FromArgb(
+ int.Parse(rgb.Substring(0, 2), NumberStyles.AllowHexSpecifier),
+ int.Parse(rgb.Substring(2, 2), NumberStyles.AllowHexSpecifier),
+ int.Parse(rgb.Substring(4, 2), NumberStyles.AllowHexSpecifier),
+ int.Parse(rgb.Substring(6, 2), NumberStyles.AllowHexSpecifier));
+ }
+ 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
index d2db7c3..bf07432 100644
--- a/EPPlus/Style/ExcelBorder.cs
+++ b/EPPlus/Style/ExcelBorder.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,166 +13,190 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
-using OfficeOpenXml.Style.XmlAccess;
-namespace OfficeOpenXml.Style
-{
- /// <summary>
- /// Cell Border style
- /// </summary>
- public sealed class Border : StyleBase
- {
- internal Border(ExcelStyles styles, OfficeOpenXml.XmlHelper.ChangedEventHandler ChangedEvent, int PositionID, string address, int index) :
- base(styles, ChangedEvent, PositionID, address)
- {
- Index = index;
- }
- /// <summary>
- /// Left border style
- /// </summary>
- public ExcelBorderItem Left
- {
- get
- {
- return new ExcelBorderItem(_styles, _ChangedEvent, _positionID, _address, eStyleClass.BorderLeft, this);
- }
- }
- /// <summary>
- /// Right border style
- /// </summary>
- public ExcelBorderItem Right
- {
- get
- {
- return new ExcelBorderItem(_styles, _ChangedEvent, _positionID, _address, eStyleClass.BorderRight, this);
- }
- }
- /// <summary>
- /// Top border style
- /// </summary>
- public ExcelBorderItem Top
- {
- get
- {
- return new ExcelBorderItem(_styles, _ChangedEvent, _positionID, _address, eStyleClass.BorderTop, this);
- }
- }
- /// <summary>
- /// Bottom border style
- /// </summary>
- public ExcelBorderItem Bottom
- {
- get
- {
- return new ExcelBorderItem(_styles, _ChangedEvent, _positionID, _address, eStyleClass.BorderBottom, this);
- }
- }
- /// <summary>
- /// 0Diagonal border style
- /// </summary>
- public ExcelBorderItem Diagonal
- {
- get
- {
- return new ExcelBorderItem(_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;
- }
- else
- {
- return false;
- }
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Border, eStyleProperty.BorderDiagonalUp, value, _positionID, _address));
- }
- }
- /// <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;
- }
- else
- {
- return false;
- }
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Border, eStyleProperty.BorderDiagonalDown, value, _positionID, _address));
- }
- }
- internal override string Id
- {
- get { return Top.Id + Bottom.Id +Left.Id + Right.Id + Diagonal.Id + DiagonalUp + DiagonalDown; }
- }
- /// <summary>
- /// Set the border style around the range.
- /// </summary>
- /// <param name="Style">The border style</param>
- public void BorderAround(ExcelBorderStyle Style)
- {
- var addr = new ExcelAddress(_address);
- SetBorderAroundStyle(Style, addr);
- }
- /// <summary>
- /// Set the border style around the range.
- /// </summary>
- /// <param name="Style">The border style</param>
- /// <param name="Color">The color of the border</param>
- public void BorderAround(ExcelBorderStyle Style, System.Drawing.Color Color)
- {
- var addr=new ExcelAddress(_address);
- SetBorderAroundStyle(Style, addr);
+using System.Drawing;
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.BorderTop, eStyleProperty.Color, Color.ToArgb().ToString("X"), _positionID, new ExcelAddress(addr._fromRow, addr._fromCol, addr._fromRow, addr._toCol).Address));
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.BorderBottom, eStyleProperty.Color, Color.ToArgb().ToString("X"), _positionID, new ExcelAddress(addr._toRow, addr._fromCol, addr._toRow, addr._toCol).Address));
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.BorderLeft, eStyleProperty.Color, Color.ToArgb().ToString("X"), _positionID, new ExcelAddress(addr._fromRow, addr._fromCol, addr._toRow, addr._fromCol).Address));
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.BorderRight, eStyleProperty.Color, Color.ToArgb().ToString("X"), _positionID, new ExcelAddress(addr._fromRow, addr._toCol, addr._toRow, addr._toCol).Address));
- }
+namespace OfficeOpenXml.Style;
- private void SetBorderAroundStyle(ExcelBorderStyle Style, ExcelAddress addr)
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.BorderTop, eStyleProperty.Style, Style, _positionID, new ExcelAddress(addr._fromRow, addr._fromCol, addr._fromRow, addr._toCol).Address));
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.BorderBottom, eStyleProperty.Style, Style, _positionID, new ExcelAddress(addr._toRow, addr._fromCol, addr._toRow, addr._toCol).Address));
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.BorderLeft, eStyleProperty.Style, Style, _positionID, new ExcelAddress(addr._fromRow, addr._fromCol, addr._toRow, addr._fromCol).Address));
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.BorderRight, eStyleProperty.Style, Style, _positionID, new ExcelAddress(addr._fromRow, addr._toCol, addr._toRow, addr._toCol).Address));
- }
+/// <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;
}
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Border, eStyleProperty.BorderDiagonalUp, value, _positionID, _address));
+ }
+
+ /// <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;
+ }
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Border, eStyleProperty.BorderDiagonalDown, value, _positionID, _address));
+ }
+
+ internal override string Id =>
+ Top.Id + Bottom.Id + Left.Id + Right.Id + Diagonal.Id + DiagonalUp + DiagonalDown;
+
+ /// <summary>
+ /// Set the border style around the range.
+ /// </summary>
+ /// <param name="style">The border style</param>
+ public void BorderAround(ExcelBorderStyle style) {
+ var addr = new ExcelAddress(_address);
+ SetBorderAroundStyle(style, addr);
+ }
+
+ /// <summary>
+ /// Set the border style around the range.
+ /// </summary>
+ /// <param name="style">The border style</param>
+ /// <param name="color">The color of the border</param>
+ public void BorderAround(ExcelBorderStyle style, Color color) {
+ var addr = new ExcelAddress(_address);
+ SetBorderAroundStyle(style, addr);
+
+ _ChangedEvent(
+ this,
+ new(
+ eStyleClass.BorderTop,
+ eStyleProperty.Color,
+ color.ToArgb().ToString("X"),
+ _positionID,
+ new ExcelAddress(addr._fromRow, addr._fromCol, addr._fromRow, addr._toCol).Address));
+ _ChangedEvent(
+ this,
+ new(
+ eStyleClass.BorderBottom,
+ eStyleProperty.Color,
+ color.ToArgb().ToString("X"),
+ _positionID,
+ new ExcelAddress(addr._toRow, addr._fromCol, addr._toRow, addr._toCol).Address));
+ _ChangedEvent(
+ this,
+ new(
+ eStyleClass.BorderLeft,
+ eStyleProperty.Color,
+ color.ToArgb().ToString("X"),
+ _positionID,
+ new ExcelAddress(addr._fromRow, addr._fromCol, addr._toRow, addr._fromCol).Address));
+ _ChangedEvent(
+ this,
+ new(
+ eStyleClass.BorderRight,
+ eStyleProperty.Color,
+ color.ToArgb().ToString("X"),
+ _positionID,
+ new ExcelAddress(addr._fromRow, addr._toCol, addr._toRow, addr._toCol).Address));
+ }
+
+ private void SetBorderAroundStyle(ExcelBorderStyle style, ExcelAddress addr) {
+ _ChangedEvent(
+ this,
+ new(
+ eStyleClass.BorderTop,
+ eStyleProperty.Style,
+ style,
+ _positionID,
+ new ExcelAddress(addr._fromRow, addr._fromCol, addr._fromRow, addr._toCol).Address));
+ _ChangedEvent(
+ this,
+ new(
+ eStyleClass.BorderBottom,
+ eStyleProperty.Style,
+ style,
+ _positionID,
+ new ExcelAddress(addr._toRow, addr._fromCol, addr._toRow, addr._toCol).Address));
+ _ChangedEvent(
+ this,
+ new(
+ eStyleClass.BorderLeft,
+ eStyleProperty.Style,
+ style,
+ _positionID,
+ new ExcelAddress(addr._fromRow, addr._fromCol, addr._toRow, addr._fromCol).Address));
+ _ChangedEvent(
+ this,
+ new(
+ eStyleClass.BorderRight,
+ eStyleProperty.Style,
+ style,
+ _positionID,
+ new ExcelAddress(addr._fromRow, addr._toCol, addr._toRow, addr._toCol).Address));
+ }
}
diff --git a/EPPlus/Style/ExcelBorderItem.cs b/EPPlus/Style/ExcelBorderItem.cs
index 7794d9a..f46f55a 100644
--- a/EPPlus/Style/ExcelBorderItem.cs
+++ b/EPPlus/Style/ExcelBorderItem.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,100 +13,91 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
using OfficeOpenXml.Style.XmlAccess;
-namespace OfficeOpenXml.Style
-{
- /// <summary>
- /// Cell border style
- /// </summary>
- public sealed class ExcelBorderItem : StyleBase
- {
- eStyleClass _cls;
- StyleBase _parent;
- internal ExcelBorderItem (ExcelStyles styles, OfficeOpenXml.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
- {
- get
- {
- return GetSource().Style;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(_cls, eStyleProperty.Style, value, _positionID, _address));
- }
- }
- ExcelColor _color=null;
- /// <summary>
- /// The color of the border
- /// </summary>
- public ExcelColor Color
- {
- get
- {
- if (_color == null)
- {
- _color = new ExcelColor(_styles, _ChangedEvent, _positionID, _address, _cls, _parent);
- }
- return _color;
- }
- }
+namespace OfficeOpenXml.Style;
- internal override string Id
- {
- get { return Style + Color.Id; }
- }
- internal override void SetIndex(int index)
- {
- _parent.Index = index;
- }
- private ExcelBorderItemXml GetSource()
- {
- int ix = _parent.Index < 0 ? 0 : _parent.Index;
+/// <summary>
+/// Cell border style
+/// </summary>
+public sealed class ExcelBorderItem : StyleBase {
+ private eStyleClass _cls;
+ private StyleBase _parent;
- 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 Exception("Invalid class for Borderitem");
- }
+ 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 {
+ get => GetSource().Style;
+ set => _ChangedEvent(this, new(_cls, eStyleProperty.Style, value, _positionID, _address));
+ }
+
+ 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
index 33d1957..935f78e 100644
--- a/EPPlus/Style/ExcelColor.cs
+++ b/EPPlus/Style/ExcelColor.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,245 +13,213 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
-using OfficeOpenXml.Style.XmlAccess;
using System.Drawing;
+using OfficeOpenXml.Style.XmlAccess;
-namespace OfficeOpenXml.Style
-{
- /// <summary>
- /// Color for cellstyling
- /// </summary>
- public sealed class ExcelColor : StyleBase
- {
- eStyleClass _cls;
- StyleBase _parent;
- internal ExcelColor(ExcelStyles styles, OfficeOpenXml.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
- {
- get
- {
- return GetSource().Theme;
- }
- }
- /// <summary>
- /// The tint value
- /// </summary>
- public decimal Tint
- {
- get
- {
- return GetSource().Tint;
- }
- set
- {
- if (value > 1 || value < -1)
- {
- throw (new ArgumentOutOfRangeException("Value must be between -1 and 1"));
- }
- _ChangedEvent(this, new StyleChangeEventArgs(_cls, eStyleProperty.Tint, value, _positionID, _address));
- }
- }
- /// <summary>
- /// The RGB value
- /// </summary>
- public string Rgb
- {
- get
- {
- return GetSource().Rgb;
- }
- internal set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(_cls, eStyleProperty.Color, value, _positionID, _address));
- }
- }
- /// <summary>
- /// The indexed color number.
- /// </summary>
- public int Indexed
- {
- get
- {
- return GetSource().Indexed;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(_cls, eStyleProperty.IndexedColor, value, _positionID, _address));
- }
- }
- /// <summary>
- /// Set the color of the object
- /// </summary>
- /// <param name="color">The color</param>
- public void SetColor(Color color)
- {
- Rgb = color.ToArgb().ToString("X");
- }
+namespace OfficeOpenXml.Style;
+/// <summary>
+/// Color for cellstyling
+/// </summary>
+public sealed class ExcelColor : StyleBase {
+ private eStyleClass _cls;
+ private StyleBase _parent;
- internal override string Id
- {
- get
- {
- return 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 Exception("Invalid style-class for Color"));
- }
- }
- internal override void SetIndex(int index)
- {
- _parent.Index = index;
- }
- /// <summary>
- /// Return the RGB value for the color object that uses the Indexed or Tint property
- /// </summary>
- /// <param name="theColor">The color object</param>
- /// <returns>The RGB color starting with a #</returns>
- public string LookupColor(ExcelColor theColor)
- {
- //Thanks to neaves for contributing this method.
- int iTint = 0;
- string translatedRGB = "";
+ internal ExcelColor(
+ ExcelStyles styles,
+ XmlHelper.ChangedEventHandler changedEvent,
+ int worksheetId,
+ string address,
+ eStyleClass cls,
+ StyleBase parent)
+ : base(styles, changedEvent, worksheetId, address) {
+ _parent = parent;
+ _cls = cls;
+ }
- // reference extracted from ECMA-376, Part 4, Section 3.8.26
- string[] rgbLookup =
- {
- "#FF000000", // 0
- "#FFFFFFFF",
- "#FFFF0000",
- "#FF00FF00",
- "#FF0000FF",
- "#FFFFFF00",
- "#FFFF00FF",
- "#FF00FFFF",
- "#FF000000", // 8
- "#FFFFFFFF",
- "#FFFF0000",
- "#FF00FF00",
- "#FF0000FF",
- "#FFFFFF00",
- "#FFFF00FF",
- "#FF00FFFF",
- "#FF800000",
- "#FF008000",
- "#FF000080",
- "#FF808000",
- "#FF800080",
- "#FF008080",
- "#FFC0C0C0",
- "#FF808080",
- "#FF9999FF",
- "#FF993366",
- "#FFFFFFCC",
- "#FFCCFFFF",
- "#FF660066",
- "#FFFF8080",
- "#FF0066CC",
- "#FFCCCCFF",
- "#FF000080",
- "#FFFF00FF",
- "#FFFFFF00",
- "#FF00FFFF",
- "#FF800080",
- "#FF800000",
- "#FF008080",
- "#FF0000FF",
- "#FF00CCFF",
- "#FFCCFFFF",
- "#FFCCFFCC",
- "#FFFFFF99",
- "#FF99CCFF",
- "#FFFF99CC",
- "#FFCC99FF",
- "#FFFFCC99",
- "#FF3366FF",
- "#FF33CCCC",
- "#FF99CC00",
- "#FFFFCC00",
- "#FFFF9900",
- "#FFFF6600",
- "#FF666699",
- "#FF969696",
- "#FF003366",
- "#FF339966",
- "#FF003300",
- "#FF333300",
- "#FF993300",
- "#FF993366",
- "#FF333399",
- "#FF333333", // 63
- };
+ /// <summary>
+ /// The theme color
+ /// </summary>
+ public string Theme => GetSource().Theme;
- if ((0 <= theColor.Indexed) && (rgbLookup.Length > theColor.Indexed))
- {
- // coloring by pre-set color codes
- translatedRGB = rgbLookup[theColor.Indexed];
- }
- else if (null != theColor.Rgb && 0 < theColor.Rgb.Length)
- {
- // coloring by RGB value ("FFRRGGBB")
- translatedRGB = "#" + theColor.Rgb;
- }
- else
- {
- // coloring by shades of grey (-1 -> 0)
- iTint = ((int)(theColor.Tint * 160) + 0x80);
- translatedRGB = ((int)(decimal.Round(theColor.Tint * -512))).ToString("X");
- translatedRGB = "#FF" + translatedRGB + translatedRGB + translatedRGB;
- }
-
- return translatedRGB;
- }
+ /// <summary>
+ /// The tint value
+ /// </summary>
+ public decimal Tint {
+ get => GetSource().Tint;
+ set {
+ if (value > 1 || value < -1) {
+ throw (new ArgumentOutOfRangeException("Value must be between -1 and 1"));
+ }
+ _ChangedEvent(this, new(_cls, eStyleProperty.Tint, value, _positionID, _address));
}
+ }
+
+ /// <summary>
+ /// The RGB value
+ /// </summary>
+ public string Rgb {
+ get => GetSource().Rgb;
+ internal set =>
+ _ChangedEvent(this, new(_cls, eStyleProperty.Color, value, _positionID, _address));
+ }
+
+ /// <summary>
+ /// The indexed color number.
+ /// </summary>
+ public int Indexed {
+ get => GetSource().Indexed;
+ set =>
+ _ChangedEvent(this, new(_cls, eStyleProperty.IndexedColor, value, _positionID, _address));
+ }
+
+ /// <summary>
+ /// Set the color of the object
+ /// </summary>
+ /// <param name="color">The color</param>
+ public void SetColor(Color color) {
+ Rgb = color.ToArgb().ToString("X");
+ }
+
+ 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;
+ }
+
+ /// <summary>
+ /// Return the RGB value for the color object that uses the Indexed or Tint property
+ /// </summary>
+ /// <param name="theColor">The color object</param>
+ /// <returns>The RGB color starting with a #</returns>
+ public string LookupColor(ExcelColor theColor) {
+ //Thanks to neaves for contributing this method.
+ int iTint = 0;
+ string translatedRgb = "";
+
+ // reference extracted from ECMA-376, Part 4, Section 3.8.26
+ string[] rgbLookup = {
+ "#FF000000", // 0
+ "#FFFFFFFF",
+ "#FFFF0000",
+ "#FF00FF00",
+ "#FF0000FF",
+ "#FFFFFF00",
+ "#FFFF00FF",
+ "#FF00FFFF",
+ "#FF000000", // 8
+ "#FFFFFFFF",
+ "#FFFF0000",
+ "#FF00FF00",
+ "#FF0000FF",
+ "#FFFFFF00",
+ "#FFFF00FF",
+ "#FF00FFFF",
+ "#FF800000",
+ "#FF008000",
+ "#FF000080",
+ "#FF808000",
+ "#FF800080",
+ "#FF008080",
+ "#FFC0C0C0",
+ "#FF808080",
+ "#FF9999FF",
+ "#FF993366",
+ "#FFFFFFCC",
+ "#FFCCFFFF",
+ "#FF660066",
+ "#FFFF8080",
+ "#FF0066CC",
+ "#FFCCCCFF",
+ "#FF000080",
+ "#FFFF00FF",
+ "#FFFFFF00",
+ "#FF00FFFF",
+ "#FF800080",
+ "#FF800000",
+ "#FF008080",
+ "#FF0000FF",
+ "#FF00CCFF",
+ "#FFCCFFFF",
+ "#FFCCFFCC",
+ "#FFFFFF99",
+ "#FF99CCFF",
+ "#FFFF99CC",
+ "#FFCC99FF",
+ "#FFFFCC99",
+ "#FF3366FF",
+ "#FF33CCCC",
+ "#FF99CC00",
+ "#FFFFCC00",
+ "#FFFF9900",
+ "#FFFF6600",
+ "#FF666699",
+ "#FF969696",
+ "#FF003366",
+ "#FF339966",
+ "#FF003300",
+ "#FF333300",
+ "#FF993300",
+ "#FF993366",
+ "#FF333399",
+ "#FF333333", // 63
+ };
+
+ if ((0 <= theColor.Indexed) && (rgbLookup.Length > theColor.Indexed)) {
+ // coloring by pre-set color codes
+ translatedRgb = rgbLookup[theColor.Indexed];
+ } else if (null != theColor.Rgb && 0 < theColor.Rgb.Length) {
+ // coloring by RGB value ("FFRRGGBB")
+ translatedRgb = "#" + theColor.Rgb;
+ } else {
+ // coloring by shades of grey (-1 -> 0)
+ iTint = ((int)(theColor.Tint * 160) + 0x80);
+ translatedRgb = ((int)(decimal.Round(theColor.Tint * -512))).ToString("X");
+ translatedRgb = "#FF" + translatedRgb + translatedRgb + translatedRgb;
+ }
+
+ return translatedRgb;
+ }
}
diff --git a/EPPlus/Style/ExcelFill.cs b/EPPlus/Style/ExcelFill.cs
index f957154..d1a5ea6 100644
--- a/EPPlus/Style/ExcelFill.cs
+++ b/EPPlus/Style/ExcelFill.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,126 +13,127 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
-using OfficeOpenXml.Style.XmlAccess;
-using System.Globalization;
-namespace OfficeOpenXml.Style
-{
- /// <summary>
- /// The background fill of a cell
- /// </summary>
- public class ExcelFill : StyleBase
- {
- internal ExcelFill(ExcelStyles styles, OfficeOpenXml.XmlHelper.ChangedEventHandler ChangedEvent, int PositionID, string address, int index) :
- base(styles, ChangedEvent, PositionID, address)
+namespace OfficeOpenXml.Style;
- {
- Index = index;
- }
- /// <summary>
- /// The pattern for solid fills.
- /// </summary>
- public ExcelFillStyle PatternType
- {
- get
- {
- if (Index == int.MinValue)
- {
- return ExcelFillStyle.None;
- }
- else
- {
- return _styles.Fills[Index].PatternType;
- }
- }
- set
- {
- if (_gradient != null) _gradient = null;
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Fill, eStyleProperty.PatternType, value, _positionID, _address));
- }
- }
- ExcelColor _patternColor = null;
- /// <summary>
- /// The color of the pattern
- /// </summary>
- public ExcelColor PatternColor
- {
- get
- {
- if (_patternColor == null)
- {
- _patternColor = new ExcelColor(_styles, _ChangedEvent, _positionID, _address, eStyleClass.FillPatternColor, this);
- if (_gradient != null) _gradient = null;
- }
- return _patternColor;
- }
- }
- ExcelColor _backgroundColor = null;
- /// <summary>
- /// The background color
- /// </summary>
- public ExcelColor BackgroundColor
- {
- get
- {
- if (_backgroundColor == null)
- {
- _backgroundColor = new ExcelColor(_styles, _ChangedEvent, _positionID, _address, eStyleClass.FillBackgroundColor, this);
- if (_gradient != null) _gradient = null;
- }
- return _backgroundColor;
-
- }
- }
- ExcelGradientFill _gradient=null;
- /// <summary>
- /// Access to properties for gradient fill.
- /// </summary>
- public ExcelGradientFill Gradient
- {
- get
- {
- if (_gradient == null)
- {
- _gradient = new ExcelGradientFill(_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;
- }
- else
- {
- return _gradient.Id;
- }
- }
- }
+/// <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;
}
+ set {
+ if (_gradient != null) {
+ _gradient = null;
+ }
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Fill, eStyleProperty.PatternType, value, _positionID, _address));
+ }
+ }
+
+ 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
index 4702d83..36beb83 100644
--- a/EPPlus/Style/ExcelFont.cs
+++ b/EPPlus/Style/ExcelFont.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,223 +13,181 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
using System.Drawing;
-namespace OfficeOpenXml.Style
-{
- /// <summary>
- /// Cell style Font
- /// </summary>
- public sealed class ExcelFont : StyleBase
- {
- internal ExcelFont(ExcelStyles styles, OfficeOpenXml.XmlHelper.ChangedEventHandler ChangedEvent, int PositionID, string address, int index) :
- base(styles, ChangedEvent, PositionID, address)
+namespace OfficeOpenXml.Style;
- {
- Index = index;
- }
- /// <summary>
- /// The name of the font
- /// </summary>
- public string Name
- {
- get
- {
- return _styles.Fonts[Index].Name;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Font, eStyleProperty.Name, value, _positionID, _address));
- }
- }
- /// <summary>
- /// The Size of the font
- /// </summary>
- public float Size
- {
- get
- {
- return _styles.Fonts[Index].Size;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Font, eStyleProperty.Size, value, _positionID, _address));
- }
- }
- /// <summary>
- /// Font family
- /// </summary>
- public int Family
- {
- get
- {
- return _styles.Fonts[Index].Family;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Font, eStyleProperty.Family, value, _positionID, _address));
- }
- }
- /// <summary>
- /// Cell color
- /// </summary>
- public ExcelColor Color
- {
- get
- {
- return new ExcelColor(_styles, _ChangedEvent, _positionID, _address, eStyleClass.Font, this);
- }
- }
- /// <summary>
- /// Scheme
- /// </summary>
- public string Scheme
- {
- get
- {
- return _styles.Fonts[Index].Scheme;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Font, eStyleProperty.Scheme, value, _positionID, _address));
- }
- }
- /// <summary>
- /// Font-bold
- /// </summary>
- public bool Bold
- {
- get
- {
- return _styles.Fonts[Index].Bold;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Font, eStyleProperty.Bold, value, _positionID, _address));
- }
- }
- /// <summary>
- /// Font-italic
- /// </summary>
- public bool Italic
- {
- get
- {
- return _styles.Fonts[Index].Italic;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Font, eStyleProperty.Italic, value, _positionID, _address));
- }
- }
- /// <summary>
- /// Font-Strikeout
- /// </summary>
- public bool Strike
- {
- get
- {
- return _styles.Fonts[Index].Strike;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Font, eStyleProperty.Strike, value, _positionID, _address));
- }
- }
- /// <summary>
- /// Font-Underline
- /// </summary>
- public bool UnderLine
- {
- get
- {
- return _styles.Fonts[Index].UnderLine;
- }
- set
- {
- if (value)
- {
- UnderLineType = ExcelUnderLineType.Single;
- }
- else
- {
- UnderLineType = ExcelUnderLineType.None;
- }
- //_ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Font, eStyleProperty.UnderlineType, value, _positionID, _address));
- }
- }
- public ExcelUnderLineType UnderLineType
- {
- get
- {
- return _styles.Fonts[Index].UnderLineType;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Font, eStyleProperty.UnderlineType, value, _positionID, _address));
- }
- }
- /// <summary>
- /// Font-Vertical Align
- /// </summary>
- public ExcelVerticalAlignmentFont VerticalAlign
- {
- get
- {
- if (_styles.Fonts[Index].VerticalAlign == "")
- {
- return ExcelVerticalAlignmentFont.None;
- }
- else
- {
- return (ExcelVerticalAlignmentFont)Enum.Parse(typeof(ExcelVerticalAlignmentFont), _styles.Fonts[Index].VerticalAlign, true);
- }
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Font, eStyleProperty.VerticalAlign, value, _positionID, _address));
- }
- }
- /// <summary>
- /// Set the font from a Font object
- /// </summary>
- /// <param name="Font"></param>
- public void SetFromFont(Font Font)
- {
- Name = Font.Name;
- //Family=fnt.FontFamily.;
- Size = (int)Font.Size;
- Strike = Font.Strikeout;
- Bold = Font.Bold;
- UnderLine = Font.Underline;
- Italic = Font.Italic;
- }
+/// <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;
+ }
- internal override string Id
- {
- get
- {
- return Name + Size.ToString() + Family.ToString() + Scheme.ToString() + Bold.ToString()[0] + Italic.ToString()[0] + Strike.ToString()[0] + UnderLine.ToString()[0] + VerticalAlign;
- }
- }
+ /// <summary>
+ /// The name of the font
+ /// </summary>
+ public string Name {
+ get => _styles.Fonts[Index].Name;
+ set =>
+ _ChangedEvent(this, new(eStyleClass.Font, eStyleProperty.Name, value, _positionID, _address));
+ }
+
+ /// <summary>
+ /// The Size of the font
+ /// </summary>
+ public float Size {
+ get => _styles.Fonts[Index].Size;
+ set =>
+ _ChangedEvent(this, new(eStyleClass.Font, eStyleProperty.Size, value, _positionID, _address));
+ }
+
+ /// <summary>
+ /// Font family
+ /// </summary>
+ public int Family {
+ get => _styles.Fonts[Index].Family;
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Font, eStyleProperty.Family, value, _positionID, _address));
+ }
+
+ /// <summary>
+ /// Cell color
+ /// </summary>
+ public ExcelColor Color =>
+ new(_styles, _ChangedEvent, _positionID, _address, eStyleClass.Font, this);
+
+ /// <summary>
+ /// Scheme
+ /// </summary>
+ public string Scheme {
+ get => _styles.Fonts[Index].Scheme;
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Font, eStyleProperty.Scheme, value, _positionID, _address));
+ }
+
+ /// <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 {
+ get => _styles.Fonts[Index].Italic;
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Font, eStyleProperty.Italic, value, _positionID, _address));
+ }
+
+ /// <summary>
+ /// Font-Strikeout
+ /// </summary>
+ public bool Strike {
+ get => _styles.Fonts[Index].Strike;
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Font, eStyleProperty.Strike, value, _positionID, _address));
+ }
+
+ /// <summary>
+ /// Font-Underline
+ /// </summary>
+ public bool UnderLine {
+ get => _styles.Fonts[Index].UnderLine;
+ set {
+ if (value) {
+ UnderLineType = ExcelUnderLineType.Single;
+ } else {
+ UnderLineType = ExcelUnderLineType.None;
+ }
+ //_ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Font, eStyleProperty.UnderlineType, value, _positionID, _address));
}
+ }
+
+ public ExcelUnderLineType UnderLineType {
+ get => _styles.Fonts[Index].UnderLineType;
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Font, eStyleProperty.UnderlineType, value, _positionID, _address));
+ }
+
+ /// <summary>
+ /// Font-Vertical Align
+ /// </summary>
+ public ExcelVerticalAlignmentFont VerticalAlign {
+ get {
+ if (_styles.Fonts[Index].VerticalAlign == "") {
+ return ExcelVerticalAlignmentFont.None;
+ }
+ return (ExcelVerticalAlignmentFont)
+ Enum.Parse(typeof(ExcelVerticalAlignmentFont), _styles.Fonts[Index].VerticalAlign, true);
+ }
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Font, eStyleProperty.VerticalAlign, value, _positionID, _address));
+ }
+
+ /// <summary>
+ /// Set the font from a Font object
+ /// </summary>
+ /// <param name="font"></param>
+ public void SetFromFont(Font font) {
+ Name = font.Name;
+ //Family=fnt.FontFamily.;
+ Size = (int)font.Size;
+ Strike = font.Strikeout;
+ Bold = font.Bold;
+ UnderLine = font.Underline;
+ Italic = font.Italic;
+ }
+
+ 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
index 1606316..16e73c8 100644
--- a/EPPlus/Style/ExcelGradientFill.cs
+++ b/EPPlus/Style/ExcelGradientFill.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,176 +13,179 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
using OfficeOpenXml.Style.XmlAccess;
-using System.Globalization;
-namespace OfficeOpenXml.Style
-{
- /// <summary>
- /// The background fill of a cell
- /// </summary>
- public class ExcelGradientFill : StyleBase
- {
- internal ExcelGradientFill(ExcelStyles styles, OfficeOpenXml.XmlHelper.ChangedEventHandler ChangedEvent, int PositionID, string address, int index) :
- base(styles, ChangedEvent, PositionID, address)
+namespace OfficeOpenXml.Style;
- {
- Index = index;
- }
- /// <summary>
- /// Angle of the linear gradient
- /// </summary>
- public double Degree
- {
- get
- {
- return ((ExcelGradientFillXml)_styles.Fills[Index]).Degree;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.GradientFill, eStyleProperty.GradientDegree, value, _positionID, _address));
- }
- }
- /// <summary>
- /// Linear or Path gradient
- /// </summary>
- public ExcelFillGradientType Type
- {
- get
- {
- return ((ExcelGradientFillXml)_styles.Fills[Index]).Type;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.GradientFill, eStyleProperty.GradientType, value, _positionID, _address));
- }
- }
- /// <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
- {
- get
- {
- return ((ExcelGradientFillXml)_styles.Fills[Index]).Top;
- }
- set
- {
- if (value < 0 | value > 1)
- {
- throw (new ArgumentOutOfRangeException("Value must be between 0 and 1"));
- }
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.GradientFill, eStyleProperty.GradientTop, value, _positionID, _address));
- }
- }
- /// <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
- {
- get
- {
- return ((ExcelGradientFillXml)_styles.Fills[Index]).Bottom;
- }
- set
- {
- if (value < 0 | value > 1)
- {
- throw (new ArgumentOutOfRangeException("Value must be between 0 and 1"));
- }
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.GradientFill, eStyleProperty.GradientBottom, value, _positionID, _address));
- }
- }
- /// <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
- {
- get
- {
- return ((ExcelGradientFillXml)_styles.Fills[Index]).Left;
- }
- set
- {
- if (value < 0 | value > 1)
- {
- throw (new ArgumentOutOfRangeException("Value must be between 0 and 1"));
- }
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.GradientFill, eStyleProperty.GradientLeft, value, _positionID, _address));
- }
- }
- /// <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
- {
- get
- {
- return ((ExcelGradientFillXml)_styles.Fills[Index]).Right;
- }
- set
- {
- if (value < 0 | value > 1)
- {
- throw (new ArgumentOutOfRangeException("Value must be between 0 and 1"));
- }
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.GradientFill, eStyleProperty.GradientRight, value, _positionID, _address));
- }
- }
- ExcelColor _gradientColor1 = null;
- /// <summary>
- /// Gradient Color 1
- /// </summary>
- public ExcelColor Color1
- {
- get
- {
- if (_gradientColor1 == null)
- {
- _gradientColor1 = new ExcelColor(_styles, _ChangedEvent, _positionID, _address, eStyleClass.FillGradientColor1, this);
- }
- return _gradientColor1;
+/// <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;
+ }
- }
- }
- ExcelColor _gradientColor2 = null;
- /// <summary>
- /// Gradient Color 2
- /// </summary>
- public ExcelColor Color2
- {
- get
- {
- if (_gradientColor2 == null)
- {
- _gradientColor2 = new ExcelColor(_styles, _ChangedEvent, _positionID, _address, eStyleClass.FillGradientColor2, this);
- }
- return _gradientColor2;
+ /// <summary>
+ /// Angle of the linear gradient
+ /// </summary>
+ public double Degree {
+ get => ((ExcelGradientFillXml)_styles.Fills[Index]).Degree;
+ set =>
+ _ChangedEvent(
+ this,
+ new(
+ eStyleClass.GradientFill,
+ eStyleProperty.GradientDegree,
+ value,
+ _positionID,
+ _address));
+ }
- }
- }
- internal override string Id
- {
- get { return Degree.ToString() + Type + Color1.Id + Color2.Id + Top.ToString() + Bottom.ToString() + Left.ToString() + Right.ToString(); }
- }
+ /// <summary>
+ /// Linear or Path gradient
+ /// </summary>
+ public ExcelFillGradientType Type {
+ get => ((ExcelGradientFillXml)_styles.Fills[Index]).Type;
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.GradientFill, eStyleProperty.GradientType, value, _positionID, _address));
+ }
+
+ /// <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 {
+ get => ((ExcelGradientFillXml)_styles.Fills[Index]).Top;
+ set {
+ if (value < 0 | value > 1) {
+ throw (new ArgumentOutOfRangeException("Value must be between 0 and 1"));
+ }
+ _ChangedEvent(
+ this,
+ new(eStyleClass.GradientFill, eStyleProperty.GradientTop, value, _positionID, _address));
}
+ }
+
+ /// <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 {
+ get => ((ExcelGradientFillXml)_styles.Fills[Index]).Bottom;
+ set {
+ if (value < 0 | value > 1) {
+ throw (new ArgumentOutOfRangeException("Value must be between 0 and 1"));
+ }
+ _ChangedEvent(
+ this,
+ new(
+ eStyleClass.GradientFill,
+ eStyleProperty.GradientBottom,
+ value,
+ _positionID,
+ _address));
+ }
+ }
+
+ /// <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 {
+ get => ((ExcelGradientFillXml)_styles.Fills[Index]).Left;
+ set {
+ if (value < 0 | value > 1) {
+ throw (new ArgumentOutOfRangeException("Value must be between 0 and 1"));
+ }
+ _ChangedEvent(
+ this,
+ new(eStyleClass.GradientFill, eStyleProperty.GradientLeft, value, _positionID, _address));
+ }
+ }
+
+ /// <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 {
+ get => ((ExcelGradientFillXml)_styles.Fills[Index]).Right;
+ set {
+ if (value < 0 | value > 1) {
+ throw (new ArgumentOutOfRangeException("Value must be between 0 and 1"));
+ }
+ _ChangedEvent(
+ this,
+ new(
+ eStyleClass.GradientFill,
+ eStyleProperty.GradientRight,
+ value,
+ _positionID,
+ _address));
+ }
+ }
+
+ 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
index cd2fd40..d1841df 100644
--- a/EPPlus/Style/ExcelNumberFormat.cs
+++ b/EPPlus/Style/ExcelNumberFormat.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,216 +13,202 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
-using System.Text.RegularExpressions;
-using System.Globalization;
-namespace OfficeOpenXml.Style
-{
- /// <summary>
- /// The numberformat of the cell
- /// </summary>
- public sealed class ExcelNumberFormat : StyleBase
- {
- internal ExcelNumberFormat(ExcelStyles styles, OfficeOpenXml.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
- {
- get
- {
- return Index;
- }
- //set
- //{
- // _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Numberformat, "NumFmtID", value, _workSheetID, _address));
- //}
- }
- /// <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 StyleChangeEventArgs(eStyleClass.Numberformat, eStyleProperty.Format, (string.IsNullOrEmpty(value) ? "General" : value), _positionID, _address));
- }
- }
+namespace OfficeOpenXml.Style;
- internal override string Id
- {
- get
- {
- return Format;
- }
- }
- /// <summary>
- /// If the numeric format is a build-in from.
- /// </summary>
- public bool BuildIn { get; private set; }
+/// <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;
+ }
- 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;
- }
+ /// <summary>
+ /// The numeric index fror the format
+ /// </summary>
+ public int NumFmtID => Index;
+
+ //set
+ //{
+ // _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Numberformat, "NumFmtID", value, _workSheetID, _address));
+ //}
+ /// <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;
}
- 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;
- }
- }
+ }
+ 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/ExcelParagraph.cs b/EPPlus/Style/ExcelParagraph.cs
index ef745af..a758a83 100644
--- a/EPPlus/Style/ExcelParagraph.cs
+++ b/EPPlus/Style/ExcelParagraph.cs
@@ -13,55 +13,48 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
+
using System.Xml;
-namespace OfficeOpenXml.Style
-{
- /// <summary>
- /// Handels paragraph text
- /// </summary>
- public sealed class ExcelParagraph : ExcelTextFont
- {
- public ExcelParagraph(XmlNamespaceManager ns, XmlNode rootNode, string path, string[] schemaNodeOrder) :
- base(ns, rootNode, path + "a:rPr", schemaNodeOrder)
- {
+namespace OfficeOpenXml.Style;
- }
- const string TextPath = "../a:t";
- /// <summary>
- /// Text
- /// </summary>
- public string Text
- {
- get
- {
- return GetXmlNodeString(TextPath);
- }
- set
- {
- CreateTopNode();
- SetXmlNodeString(TextPath, value);
- }
+/// <summary>
+/// Handels paragraph text
+/// </summary>
+public sealed class ExcelParagraph : ExcelTextFont {
+ public ExcelParagraph(
+ XmlNamespaceManager ns,
+ XmlNode rootNode,
+ string path,
+ string[] schemaNodeOrder)
+ : base(ns, rootNode, path + "a:rPr", schemaNodeOrder) {}
- }
+ private const string _textPath = "../a:t";
+
+ /// <summary>
+ /// Text
+ /// </summary>
+ public string Text {
+ get => GetXmlNodeString(_textPath);
+ set {
+ CreateTopNode();
+ SetXmlNodeString(_textPath, value);
}
+ }
}
diff --git a/EPPlus/Style/ExcelParagraphCollection.cs b/EPPlus/Style/ExcelParagraphCollection.cs
index 7049162..8c96724 100644
--- a/EPPlus/Style/ExcelParagraphCollection.cs
+++ b/EPPlus/Style/ExcelParagraphCollection.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,165 +13,133 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
using System.Collections.Generic;
using System.Text;
using System.Xml;
-using OfficeOpenXml.Drawing;
-using System.Drawing;
-namespace OfficeOpenXml.Style
-{
- /// <summary>
- /// A collection of Paragraph objects
- /// </summary>
- public class ExcelParagraphCollection : XmlHelper, IEnumerable<ExcelParagraph>
- {
- List<ExcelParagraph> _list = new List<ExcelParagraph>();
- string _path;
- internal ExcelParagraphCollection(XmlNamespaceManager ns, XmlNode topNode, string path, string[] schemaNodeOrder) :
- base(ns, topNode)
- {
- var nl = topNode.SelectNodes(path + "/a:r", NameSpaceManager);
- SchemaNodeOrder = schemaNodeOrder;
- if (nl != null)
- {
- foreach (XmlNode n in nl)
- {
- _list.Add(new ExcelParagraph(ns, n, "",schemaNodeOrder));
- }
- }
- _path = path;
- }
- public ExcelParagraph this[int Index]
- {
- get
- {
- return _list[Index];
- }
- }
- public int Count
- {
- get
- {
- return _list.Count;
- }
- }
- /// <summary>
- /// Add a rich text string
- /// </summary>
- /// <param name="Text">The text to add</param>
- /// <returns></returns>
- public ExcelParagraph Add(string Text)
- {
- XmlDocument doc;
- if (TopNode is XmlDocument)
- {
- doc = TopNode as XmlDocument;
- }
- else
- {
- doc = TopNode.OwnerDocument;
- }
- XmlNode parentNode=TopNode.SelectSingleNode(_path, NameSpaceManager);
- if (parentNode == null)
- {
- CreateNode(_path);
- parentNode = TopNode.SelectSingleNode(_path, NameSpaceManager);
- }
-
- var node = doc.CreateElement("a", "r", ExcelPackage.schemaDrawings);
- parentNode.AppendChild(node);
- var childNode = doc.CreateElement("a", "rPr", ExcelPackage.schemaDrawings);
- node.AppendChild(childNode);
- var rt = new ExcelParagraph(NameSpaceManager, node, "", SchemaNodeOrder);
- rt.ComplexFont = "Calibri";
- rt.LatinFont = "Calibri";
- rt.Size = 11;
+namespace OfficeOpenXml.Style;
- rt.Text = Text;
- _list.Add(rt);
- return rt;
- }
- public void Clear()
- {
- _list.Clear();
- TopNode.RemoveAll();
- }
- public void RemoveAt(int Index)
- {
- var node = _list[Index].TopNode;
- while (node != null && node.Name != "a:r")
- {
- node = node.ParentNode;
- }
- node.ParentNode.RemoveChild(node);
- _list.RemoveAt(Index);
- }
- public void Remove(ExcelRichText Item)
- {
- TopNode.RemoveChild(Item.TopNode);
- }
- 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;
- int count = Count;
- for (int ix = Count-1; ix > 0; ix--)
- {
- RemoveAt(ix);
- }
- }
- }
- }
- #region IEnumerable<ExcelRichText> Members
+/// <summary>
+/// A collection of Paragraph objects
+/// </summary>
+public class ExcelParagraphCollection : XmlHelper, IEnumerable<ExcelParagraph> {
+ private List<ExcelParagraph> _list = new();
+ private string _path;
- IEnumerator<ExcelParagraph> IEnumerable<ExcelParagraph>.GetEnumerator()
- {
- return _list.GetEnumerator();
- }
-
- #endregion
-
- #region IEnumerable Members
-
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return _list.GetEnumerator();
- }
-
- #endregion
+ internal ExcelParagraphCollection(
+ XmlNamespaceManager ns,
+ XmlNode topNode,
+ string path,
+ string[] schemaNodeOrder)
+ : base(ns, topNode) {
+ var nl = topNode.SelectNodes(path + "/a:r", NameSpaceManager);
+ SchemaNodeOrder = schemaNodeOrder;
+ if (nl != null) {
+ foreach (XmlNode n in nl) {
+ _list.Add(new(ns, n, "", schemaNodeOrder));
+ }
}
+ _path = path;
+ }
+
+ public ExcelParagraph this[int index] => _list[index];
+
+ public int Count => _list.Count;
+
+ /// <summary>
+ /// Add a rich text string
+ /// </summary>
+ /// <param name="text">The text to add</param>
+ /// <returns></returns>
+ public ExcelParagraph Add(string text) {
+ XmlDocument doc;
+ if (TopNode is XmlDocument) {
+ doc = TopNode as XmlDocument;
+ } else {
+ doc = TopNode.OwnerDocument;
+ }
+ XmlNode parentNode = TopNode.SelectSingleNode(_path, NameSpaceManager);
+ if (parentNode == null) {
+ CreateNode(_path);
+ parentNode = TopNode.SelectSingleNode(_path, NameSpaceManager);
+ }
+
+ var node = doc.CreateElement("a", "r", ExcelPackage._schemaDrawings);
+ parentNode.AppendChild(node);
+ var childNode = doc.CreateElement("a", "rPr", ExcelPackage._schemaDrawings);
+ node.AppendChild(childNode);
+ var rt = new ExcelParagraph(NameSpaceManager, node, "", SchemaNodeOrder);
+ rt.ComplexFont = "Calibri";
+ rt.LatinFont = "Calibri";
+ rt.Size = 11;
+
+ rt.Text = text;
+ _list.Add(rt);
+ return rt;
+ }
+
+ public void Clear() {
+ _list.Clear();
+ TopNode.RemoveAll();
+ }
+
+ public void RemoveAt(int index) {
+ var node = _list[index].TopNode;
+ while (node != null && node.Name != "a:r") {
+ node = node.ParentNode;
+ }
+ node.ParentNode.RemoveChild(node);
+ _list.RemoveAt(index);
+ }
+
+ public void Remove(ExcelRichText item) {
+ TopNode.RemoveChild(item.TopNode);
+ }
+
+ 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;
+ int count = Count;
+ for (int ix = Count - 1; ix > 0; ix--) {
+ RemoveAt(ix);
+ }
+ }
+ }
+ }
+
+ IEnumerator<ExcelParagraph> IEnumerable<ExcelParagraph>.GetEnumerator() {
+ return _list.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _list.GetEnumerator();
+ }
}
diff --git a/EPPlus/Style/ExcelRichText.cs b/EPPlus/Style/ExcelRichText.cs
index bc74fa6..2207656 100644
--- a/EPPlus/Style/ExcelRichText.cs
+++ b/EPPlus/Style/ExcelRichText.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,17 +13,17 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
@@ -31,291 +31,277 @@
* 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.Generic;
-using System.Text;
-using System.Xml;
using System.Drawing;
using System.Globalization;
+using System.Xml;
-namespace OfficeOpenXml.Style
-{
- /// <summary>
- /// A richtext part
- /// </summary>
- public class ExcelRichText : XmlHelper
- {
- internal ExcelRichText(XmlNamespaceManager ns, XmlNode topNode, ExcelRichTextCollection collection) :
- base(ns, topNode)
- {
- SchemaNodeOrder=new string[] {"rPr", "t", "b", "i","strike", "u", "vertAlign" , "sz", "color", "rFont", "family", "scheme", "charset"};
- _collection = collection;
- }
- internal delegate void CallbackDelegate();
- CallbackDelegate _callback;
- internal void SetCallback(CallbackDelegate callback)
- {
- _callback=callback;
- }
- const string TEXT_PATH="d:t";
- /// <summary>
- /// The text
- /// </summary>
- public string Text
- {
+namespace OfficeOpenXml.Style;
- get
- {
- // Bug 15151
- if (TopNode.Name == "t")
- return TopNode.InnerText;
- else
- return GetXmlNodeString(TEXT_PATH);
- }
- 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(TEXT_PATH, value, false);
- if (PreserveSpace)
- {
- XmlElement elem = TopNode.SelectSingleNode(TEXT_PATH, 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(TEXT_PATH, NameSpaceManager) as XmlElement;
- if (elem != null)
- {
- return elem.GetAttribute("xml:space")=="preserve";
- }
- return false;
- }
- set
- {
- _collection.ConvertRichtext();
- XmlElement elem = TopNode.SelectSingleNode(TEXT_PATH, NameSpaceManager) as XmlElement;
- if (elem != null)
- {
- if (value)
- {
- elem.SetAttribute("xml:space", "preserve");
- }
- else
- {
- elem.RemoveAttribute("xml:space");
- }
- }
- if (_callback != null) _callback();
- }
- }
- const string BOLD_PATH = "d:rPr/d:b";
- /// <summary>
- /// Bold text
- /// </summary>
- public bool Bold
- {
- get
- {
- return ExistNode(BOLD_PATH);
- }
- set
- {
- _collection.ConvertRichtext();
- if (value)
- {
- CreateNode(BOLD_PATH);
- }
- else
- {
- DeleteNode(BOLD_PATH);
- }
- if(_callback!=null) _callback();
- }
- }
- const string ITALIC_PATH = "d:rPr/d:i";
- /// <summary>
- /// Italic text
- /// </summary>
- public bool Italic
- {
- get
- {
- //return GetXmlNodeBool(ITALIC_PATH, false);
- return ExistNode(ITALIC_PATH);
- }
- set
- {
- _collection.ConvertRichtext();
- if (value)
- {
- CreateNode(ITALIC_PATH);
- }
- else
- {
- DeleteNode(ITALIC_PATH);
- }
- if (_callback != null) _callback();
- }
- }
- const string STRIKE_PATH = "d:rPr/d:strike";
- /// <summary>
- /// Strike-out text
- /// </summary>
- public bool Strike
- {
- get
- {
- return ExistNode(STRIKE_PATH);
- }
- set
- {
- _collection.ConvertRichtext();
- if (value)
- {
- CreateNode(STRIKE_PATH);
- }
- else
- {
- DeleteNode(STRIKE_PATH);
- }
- if (_callback != null) _callback();
- }
- }
- const string UNDERLINE_PATH = "d:rPr/d:u";
- /// <summary>
- /// Underlined text
- /// </summary>
- public bool UnderLine
- {
- get
- {
- return ExistNode(UNDERLINE_PATH);
- }
- set
- {
- _collection.ConvertRichtext();
- if (value)
- {
- CreateNode(UNDERLINE_PATH);
- }
- else
- {
- DeleteNode(UNDERLINE_PATH);
- }
- if (_callback != null) _callback();
- }
- }
+/// <summary>
+/// A richtext part
+/// </summary>
+public class ExcelRichText : XmlHelper {
+ internal ExcelRichText(
+ XmlNamespaceManager ns,
+ XmlNode topNode,
+ ExcelRichTextCollection collection)
+ : base(ns, topNode) {
+ SchemaNodeOrder = new[] {
+ "rPr",
+ "t",
+ "b",
+ "i",
+ "strike",
+ "u",
+ "vertAlign",
+ "sz",
+ "color",
+ "rFont",
+ "family",
+ "scheme",
+ "charset",
+ };
+ _collection = collection;
+ }
- const string VERT_ALIGN_PATH = "d:rPr/d:vertAlign/@val";
- /// <summary>
- /// Vertical Alignment
- /// </summary>
- public ExcelVerticalAlignmentFont VerticalAlign
- {
- get
- {
- string v=GetXmlNodeString(VERT_ALIGN_PATH);
- if(v=="")
- {
- return ExcelVerticalAlignmentFont.None;
- }
- else
- {
- try
- {
- return (ExcelVerticalAlignmentFont)Enum.Parse(typeof(ExcelVerticalAlignmentFont), v, true);
- }
- catch
- {
- return ExcelVerticalAlignmentFont.None;
- }
- }
- }
- set
- {
- _collection.ConvertRichtext();
- if (value == ExcelVerticalAlignmentFont.None)
- {
- // If Excel 2010 encounters a vertical align value of blank, it will not load
- // the spreadsheet. So if None is specified, delete the node, it will be
- // recreated if a new value is applied later.
- DeleteNode(VERT_ALIGN_PATH);
- } else {
- SetXmlNodeString(VERT_ALIGN_PATH, value.ToString().ToLowerInvariant());
- }
- if (_callback != null) _callback();
- }
- }
- const string SIZE_PATH = "d:rPr/d:sz/@val";
- /// <summary>
- /// Font size
- /// </summary>
- public float Size
- {
- get
- {
- return Convert.ToSingle(GetXmlNodeDecimal(SIZE_PATH));
- }
- set
- {
- _collection.ConvertRichtext();
- SetXmlNodeString(SIZE_PATH, value.ToString(CultureInfo.InvariantCulture));
- if (_callback != null) _callback();
- }
- }
- const string FONT_PATH = "d:rPr/d:rFont/@val";
- /// <summary>
- /// Name of the font
- /// </summary>
- public string FontName
- {
- get
- {
- return GetXmlNodeString(FONT_PATH);
- }
- set
- {
- _collection.ConvertRichtext();
- SetXmlNodeString(FONT_PATH, value);
- if (_callback != null) _callback();
- }
- }
- const string COLOR_PATH = "d:rPr/d:color/@rgb";
- /// <summary>
- /// Text color
- /// </summary>
- public Color Color
- {
- get
- {
- string col = GetXmlNodeString(COLOR_PATH);
- if (col == "")
- {
- return Color.Empty;
- }
- else
- {
- return Color.FromArgb(int.Parse(col, System.Globalization.NumberStyles.AllowHexSpecifier));
- }
- }
- set
- {
- _collection.ConvertRichtext();
- SetXmlNodeString(COLOR_PATH, value.ToArgb().ToString("X")/*.Substring(2, 6)*/);
- if (_callback != null) _callback();
- }
- }
+ internal delegate void CallbackDelegate();
- public ExcelRichTextCollection _collection { get; set; }
+ 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 {
+ get {
+ string v = GetXmlNodeString(_vertAlignPath);
+ if (v == "") {
+ return ExcelVerticalAlignmentFont.None;
+ }
+ try {
+ return (ExcelVerticalAlignmentFont)Enum.Parse(typeof(ExcelVerticalAlignmentFont), v, true);
+ } catch {
+ return ExcelVerticalAlignmentFont.None;
+ }
+ }
+ set {
+ _collection.ConvertRichtext();
+ if (value == ExcelVerticalAlignmentFont.None) {
+ // If Excel 2010 encounters a vertical align value of blank, it will not load
+ // the spreadsheet. So if None is specified, delete the node, it will be
+ // recreated if a new value is applied later.
+ DeleteNode(_vertAlignPath);
+ } else {
+ SetXmlNodeString(_vertAlignPath, value.ToString().ToLowerInvariant());
+ }
+ if (_callback != null) {
+ _callback();
+ }
+ }
+ }
+
+ 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 Color Color {
+ get {
+ string col = GetXmlNodeString(_colorPath);
+ if (col == "") {
+ return Color.Empty;
+ }
+ return Color.FromArgb(int.Parse(col, NumberStyles.AllowHexSpecifier));
+ }
+ set {
+ _collection.ConvertRichtext();
+ SetXmlNodeString(
+ _colorPath,
+ value
+ .ToArgb()
+ .ToString(
+ "X") /*.Substring(2, 6)*/);
+ if (_callback != null) {
+ _callback();
+ }
+ }
+ }
+
+ public ExcelRichTextCollection _collection { get; set; }
}
diff --git a/EPPlus/Style/ExcelRichTextCollection.cs b/EPPlus/Style/ExcelRichTextCollection.cs
index c28bf91..496431d 100644
--- a/EPPlus/Style/ExcelRichTextCollection.cs
+++ b/EPPlus/Style/ExcelRichTextCollection.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,252 +13,245 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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;
using System.Collections.Generic;
+using System.Drawing;
+using System.Globalization;
using System.Linq;
using System.Text;
using System.Xml;
-using System.Drawing;
-using System.Globalization;
-namespace OfficeOpenXml.Style
-{
- /// <summary>
- /// Collection of Richtext objects
- /// </summary>
- public class ExcelRichTextCollection : XmlHelper, IEnumerable<ExcelRichText>
- {
- List<ExcelRichText> _list = new List<ExcelRichText>();
- ExcelRangeBase _cells=null;
- 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 ExcelRichText(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
- {
- get
- {
- return _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)
- {
- doc = TopNode as XmlDocument;
- }
- 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;
- if (prevItem.Color.IsEmpty)
- {
- rt.Color = Color.Black;
- }
- else
- {
- rt.Color = 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;
- }
+namespace OfficeOpenXml.Style;
- 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, ExcelAddressBase.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;
+/// <summary>
+/// Collection of Richtext objects
+/// </summary>
+public class ExcelRichTextCollection : XmlHelper, IEnumerable<ExcelRichText> {
+ private List<ExcelRichText> _list = new();
+ private ExcelRangeBase _cells;
- int hex;
- if (fnt.Color.Rgb != "" && int.TryParse(fnt.Color.Rgb, NumberStyles.HexNumber, null, out hex))
- {
- this[0].Color = Color.FromArgb(hex);
- }
- }
- }
- internal void UpdateCells()
- {
- _cells.SetValueRichText(TopNode.InnerXml);
- }
- /// <summary>
- /// Clear the collection
- /// </summary>
- public void Clear()
- {
- _list.Clear();
- TopNode.RemoveAll();
- UpdateCells();
- if (_cells != null) _cells.IsRichText = false;
- }
- /// <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);
- }
- }
- }
- }
- #region IEnumerable<ExcelRichText> Members
-
- IEnumerator<ExcelRichText> IEnumerable<ExcelRichText>.GetEnumerator()
- {
- return _list.Select(x => { x.SetCallback(UpdateCells); return x; }).GetEnumerator();
- }
-
- #endregion
-
- #region IEnumerable Members
-
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return _list.Select(x => { x.SetCallback(UpdateCells); return x; }).GetEnumerator();
- }
-
- #endregion
+ 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) {
+ doc = TopNode as XmlDocument;
+ } 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;
+ if (prevItem.Color.IsEmpty) {
+ rt.Color = Color.Black;
+ } else {
+ rt.Color = 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;
+
+ int hex;
+ if (fnt.Color.Rgb != ""
+ && int.TryParse(fnt.Color.Rgb, NumberStyles.HexNumber, null, out hex)) {
+ this[0].Color = Color.FromArgb(hex);
+ }
+ }
+ }
+
+ internal void UpdateCells() {
+ _cells.SetValueRichText(TopNode.InnerXml);
+ }
+
+ /// <summary>
+ /// Clear the collection
+ /// </summary>
+ public void Clear() {
+ _list.Clear();
+ TopNode.RemoveAll();
+ UpdateCells();
+ if (_cells != null) {
+ _cells.IsRichText = false;
+ }
+ }
+
+ /// <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/ExcelRichTextHtmlUtility.cs b/EPPlus/Style/ExcelRichTextHtmlUtility.cs
index 8274545..83e37c6 100644
--- a/EPPlus/Style/ExcelRichTextHtmlUtility.cs
+++ b/EPPlus/Style/ExcelRichTextHtmlUtility.cs
@@ -13,188 +13,175 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this product may cause.
*
* Code change notes:
- *
+ *
* Author Change Date
* ******************************************************************************
* Richard Tallent Initial Release 2012-08-13
*******************************************************************************/
+
using System;
-using System.Collections.Generic;
-using System.Text;
using System.Text.RegularExpressions;
+using System.Web;
-namespace OfficeOpenXml.Style
-{
- public class ExcelRichTextHtmlUtility
- {
+namespace OfficeOpenXml.Style;
- /// <summary>
- /// Provides basic HTML support by converting well-behaved HTML into appropriate RichText blocks.
- /// HTML support is limited, and does not include font colors, sizes, or typefaces at this time,
- /// and also does not support CSS style attributes. It does support line breaks using the BR tag.
- ///
- /// This routine parses the HTML into RegEx pairings of an HTML tag and the text until the NEXT
- /// tag (if any). The tag is parsed to determine the setting change to be applied to the last set
- /// of settings, and if the text is not blank, a new block is added to rich text.
- /// </summary>
- /// <param name="range"></param>
- /// <param name="html">The HTML to parse into RichText</param>
- /// <param name="defaultFontName"></param>
- /// <param name="defaultFontSize"></param>
+public class ExcelRichTextHtmlUtility {
+ /// <summary>
+ /// Provides basic HTML support by converting well-behaved HTML into appropriate RichText blocks.
+ /// HTML support is limited, and does not include font colors, sizes, or typefaces at this time,
+ /// and also does not support CSS style attributes. It does support line breaks using the BR tag.
+ ///
+ /// This routine parses the HTML into RegEx pairings of an HTML tag and the text until the NEXT
+ /// tag (if any). The tag is parsed to determine the setting change to be applied to the last set
+ /// of settings, and if the text is not blank, a new block is added to rich text.
+ /// </summary>
+ /// <param name="range"></param>
+ /// <param name="html">The HTML to parse into RichText</param>
+ /// <param name="defaultFontName"></param>
+ /// <param name="defaultFontSize"></param>
+ public static void SetRichTextFromHtml(
+ ExcelRange range,
+ string html,
+ string defaultFontName,
+ short defaultFontSize) {
+ // Reset the cell value, just in case there is an existing RichText value.
+ range.Value = "";
- public static void SetRichTextFromHtml(ExcelRange range, string html, string defaultFontName, short defaultFontSize)
- {
- // Reset the cell value, just in case there is an existing RichText value.
- range.Value = "";
+ // Sanity check for blank values, skips creating Regex objects for performance.
+ if (String.IsNullOrEmpty(html)) {
+ range.IsRichText = false;
+ return;
+ }
- // Sanity check for blank values, skips creating Regex objects for performance.
- if (String.IsNullOrEmpty(html))
- {
- range.IsRichText = false;
- return;
- }
+ // Change all BR tags to line breaks. http://epplus.codeplex.com/discussions/238692/
+ // Cells with line breaks aren't necessarily considered rich text, so this is performed
+ // before parsing the HTML tags.
+ html = Regex.Replace(
+ html,
+ "<br[^>]*>",
+ "\r\n",
+ RegexOptions.Compiled | RegexOptions.IgnoreCase);
- // Change all BR tags to line breaks. http://epplus.codeplex.com/discussions/238692/
- // Cells with line breaks aren't necessarily considered rich text, so this is performed
- // before parsing the HTML tags.
- html = System.Text.RegularExpressions.Regex.Replace(html, @"<br[^>]*>", "\r\n", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+ string tag;
+ string text;
+ ExcelRichText thisrt = null;
+ bool isFirst = true;
- string tag;
- string text;
- ExcelRichText thisrt = null;
- bool isFirst = true;
+ // Get all pairs of legitimate tags and the text between them. This loop will
+ // only execute if there is at least one start or end tag.
+ foreach (Match m in Regex.Matches(
+ html,
+ @"<(/?[a-z]+)[^<>]*>([\s\S]*?)(?=</?[a-z]+[^<>]*>|$)",
+ RegexOptions.Compiled | RegexOptions.IgnoreCase)) {
+ if (isFirst) {
+ // On the very first match, set up the initial rich text object with
+ // the defaults for the text BEFORE the match.
+ range.IsRichText = true;
+ thisrt = range.RichText.Add(CleanText(html.Substring(0, m.Index))); // May be 0-length
+ thisrt.Size = defaultFontSize; // Set the default font size
+ thisrt.FontName = defaultFontName; // Set the default font name
+ isFirst = false;
+ }
+ // Get the tag and the block of text until the NEXT tag or EOS. If there are HTML entities
+ // encoded, unencode them, they should be passed to RichText as normal characters (other
+ // than non-breaking spaces, which should be replaced with normal spaces, they break Excel.
+ tag = m.Groups[1].Captures[0].Value;
+ text = CleanText(m.Groups[2].Captures[0].Value);
- // Get all pairs of legitimate tags and the text between them. This loop will
- // only execute if there is at least one start or end tag.
- foreach (Match m in System.Text.RegularExpressions.Regex.Matches(html, @"<(/?[a-z]+)[^<>]*>([\s\S]*?)(?=</?[a-z]+[^<>]*>|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase))
- {
- if (isFirst)
- {
- // On the very first match, set up the initial rich text object with
- // the defaults for the text BEFORE the match.
- range.IsRichText = true;
- thisrt = range.RichText.Add(CleanText(html.Substring(0, m.Index))); // May be 0-length
- thisrt.Size = defaultFontSize; // Set the default font size
- thisrt.FontName = defaultFontName; // Set the default font name
- isFirst = false;
- }
- // Get the tag and the block of text until the NEXT tag or EOS. If there are HTML entities
- // encoded, unencode them, they should be passed to RichText as normal characters (other
- // than non-breaking spaces, which should be replaced with normal spaces, they break Excel.
- tag = m.Groups[1].Captures[0].Value;
- text = CleanText(m.Groups[2].Captures[0].Value);
+ if (thisrt.Text == "") {
+ // The most recent rich text block wasn't *actually* used last time around, so update
+ // the text and keep it as the "current" block. This happens with the first block if
+ // it starts with a tag, and may happen later if tags come one right after the other.
+ thisrt.Text = text;
+ } else {
+ // The current rich text block has some text, so create a new one. RichText.Add()
+ // automatically applies the settings from the previous block, other than vertical
+ // alignment.
+ thisrt = range.RichText.Add(text);
+ }
+ // Override the settings based on the current tag, keep all other settings.
+ SetStyleFromTag(tag, thisrt);
+ }
- if (thisrt.Text == "")
- {
- // The most recent rich text block wasn't *actually* used last time around, so update
- // the text and keep it as the "current" block. This happens with the first block if
- // it starts with a tag, and may happen later if tags come one right after the other.
- thisrt.Text = text;
- }
- else
- {
- // The current rich text block has some text, so create a new one. RichText.Add()
- // automatically applies the settings from the previous block, other than vertical
- // alignment.
- thisrt = range.RichText.Add(text);
- }
- // Override the settings based on the current tag, keep all other settings.
- SetStyleFromTag(tag, thisrt);
- }
+ if (thisrt == null) {
+ // No HTML tags were found, so treat this as a normal text value.
+ range.IsRichText = false;
+ range.Value = CleanText(html);
+ } else if (String.IsNullOrEmpty(thisrt.Text)) {
+ // Rich text was found, but the last node contains no text, so remove it. This can happen if,
+ // say, the end of the string is an end tag or unsupported tag (common).
+ range.RichText.Remove(thisrt);
- if (thisrt == null)
- {
- // No HTML tags were found, so treat this as a normal text value.
- range.IsRichText = false;
- range.Value = CleanText(html);
- }
- else if (String.IsNullOrEmpty(thisrt.Text))
- {
- // Rich text was found, but the last node contains no text, so remove it. This can happen if,
- // say, the end of the string is an end tag or unsupported tag (common).
- range.RichText.Remove(thisrt);
+ // Failsafe -- the HTML may be just tags, no text, in which case there may be no rich text
+ // directives that remain. If that is the case, turn off rich text and treat this like a blank
+ // cell value.
+ if (range.RichText.Count == 0) {
+ range.IsRichText = false;
+ range.Value = "";
+ }
+ }
+ }
- // Failsafe -- the HTML may be just tags, no text, in which case there may be no rich text
- // directives that remain. If that is the case, turn off rich text and treat this like a blank
- // cell value.
- if (range.RichText.Count == 0)
- {
- range.IsRichText = false;
- range.Value = "";
- }
+ private static void SetStyleFromTag(string tag, ExcelRichText settings) {
+ switch (tag.ToLower()) {
+ case "b":
+ case "strong":
+ settings.Bold = true;
+ break;
+ case "i":
+ case "em":
+ settings.Italic = true;
+ break;
+ case "u":
+ settings.UnderLine = true;
+ break;
+ case "s":
+ case "strike":
+ settings.Strike = true;
+ break;
+ case "sup":
+ settings.VerticalAlign = ExcelVerticalAlignmentFont.Superscript;
+ break;
+ case "sub":
+ settings.VerticalAlign = ExcelVerticalAlignmentFont.Subscript;
+ break;
+ case "/b":
+ case "/strong":
+ settings.Bold = false;
+ break;
+ case "/i":
+ case "/em":
+ settings.Italic = false;
+ break;
+ case "/u":
+ settings.UnderLine = false;
+ break;
+ case "/s":
+ case "/strike":
+ settings.Strike = false;
+ break;
+ case "/sup":
+ case "/sub":
+ settings.VerticalAlign = ExcelVerticalAlignmentFont.None;
+ break;
+ }
+ }
- }
-
- }
-
- private static void SetStyleFromTag(string tag, ExcelRichText settings)
- {
- switch (tag.ToLower())
- {
- case "b":
- case "strong":
- settings.Bold = true;
- break;
- case "i":
- case "em":
- settings.Italic = true;
- break;
- case "u":
- settings.UnderLine = true;
- break;
- case "s":
- case "strike":
- settings.Strike = true;
- break;
- case "sup":
- settings.VerticalAlign = ExcelVerticalAlignmentFont.Superscript;
- break;
- case "sub":
- settings.VerticalAlign = ExcelVerticalAlignmentFont.Subscript;
- break;
- case "/b":
- case "/strong":
- settings.Bold = false;
- break;
- case "/i":
- case "/em":
- settings.Italic = false;
- break;
- case "/u":
- settings.UnderLine = false;
- break;
- case "/s":
- case "/strike":
- settings.Strike = false;
- break;
- case "/sup":
- case "/sub":
- settings.VerticalAlign = ExcelVerticalAlignmentFont.None;
- break;
- default:
- // unsupported HTML, no style change
- break;
- }
- }
-
- private static string CleanText(string s)
- {
- // Need to convert HTML entities (named or numbered) into actual Unicode characters
- s = System.Web.HttpUtility.HtmlDecode(s);
- // Remove any non-breaking spaces, kills Excel
- s = s.Replace("\u00A0", " ");
- return s;
- }
-
- }
+ private static string CleanText(string s) {
+ // Need to convert HTML entities (named or numbered) into actual Unicode characters
+ s = HttpUtility.HtmlDecode(s);
+ // Remove any non-breaking spaces, kills Excel
+ s = s.Replace("\u00A0", " ");
+ return s;
+ }
}
diff --git a/EPPlus/Style/ExcelStyle.cs b/EPPlus/Style/ExcelStyle.cs
index a3edaae..f9ad943 100644
--- a/EPPlus/Style/ExcelStyle.cs
+++ b/EPPlus/Style/ExcelStyle.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,240 +13,216 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
using OfficeOpenXml.Style.XmlAccess;
-namespace OfficeOpenXml.Style
-{
- /// <summary>
- /// Toplevel class for cell styling
- /// </summary>
- public sealed class ExcelStyle : StyleBase
- {
- internal ExcelStyle(ExcelStyles styles, OfficeOpenXml.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 ExcelNumberFormat(styles, ChangedEvent, PositionID, Address, xfs.NumberFormatId);
- Font = new ExcelFont(styles, ChangedEvent, PositionID, Address, xfs.FontId);
- Fill = new ExcelFill(styles, ChangedEvent, PositionID, Address, xfs.FillId);
- Border = new Border(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
- {
- get
- {
- return _styles.CellXfs[Index].HorizontalAlignment;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Style, eStyleProperty.HorizontalAlign, value, _positionID, _address));
- }
- }
- /// <summary>
- /// The vertical alignment in the cell
- /// </summary>
- public ExcelVerticalAlignment VerticalAlignment
- {
- get
- {
- return _styles.CellXfs[Index].VerticalAlignment;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Style, eStyleProperty.VerticalAlign, value, _positionID, _address));
- }
- }
- /// <summary>
- /// Wrap the text
- /// </summary>
- public bool WrapText
- {
- get
- {
- return _styles.CellXfs[Index].WrapText;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Style, eStyleProperty.WrapText, value, _positionID, _address));
- }
- }
- /// <summary>
- /// Readingorder
- /// </summary>
- public ExcelReadingOrder ReadingOrder
- {
- get
- {
- return _styles.CellXfs[Index].ReadingOrder;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Style, eStyleProperty.ReadingOrder, value, _positionID, _address));
- }
- }
- /// <summary>
- /// Shrink the text to fit
- /// </summary>
- public bool ShrinkToFit
- {
- get
- {
- return _styles.CellXfs[Index].ShrinkToFit;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Style, eStyleProperty.ShrinkToFit, value, _positionID, _address));
- }
- }
- /// <summary>
- /// The margin between the border and the text
- /// </summary>
- public int Indent
- {
- get
- {
- return _styles.CellXfs[Index].Indent;
- }
- set
- {
- if (value <0 || value > 250)
- {
- throw(new ArgumentOutOfRangeException("Indent must be between 0 and 250"));
- }
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Style, eStyleProperty.Indent, value, _positionID, _address));
- }
- }
- /// <summary>
- /// Text orientation in degrees. Values range from 0 to 180.
- /// </summary>
- public int TextRotation
- {
- get
- {
- return _styles.CellXfs[Index].TextRotation;
- }
- set
- {
- if (value < 0 || value > 180)
- {
- throw new ArgumentOutOfRangeException("TextRotation out of range.");
- }
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Style, eStyleProperty.TextRotation, value, _positionID, _address));
- }
- }
- /// <summary>
- /// If true the cell is locked for editing when the sheet is protected
- /// <seealso cref="ExcelWorksheet.Protection"/>
- /// </summary>
- public bool Locked
- {
- get
- {
- return _styles.CellXfs[Index].Locked;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Style, eStyleProperty.Locked, value, _positionID, _address));
- }
- }
- /// <summary>
- /// If true the formula is hidden when the sheet is protected.
- /// <seealso cref="ExcelWorksheet.Protection"/>
- /// </summary>
- public bool Hidden
- {
- get
- {
- return _styles.CellXfs[Index].Hidden;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Style, eStyleProperty.Hidden, value, _positionID, _address));
- }
- }
+namespace OfficeOpenXml.Style;
-
- const string xfIdPath = "@xfId";
- /// <summary>
- /// The index in the style collection
- /// </summary>
- public int XfId
- {
- get
- {
- return _styles.CellXfs[Index].XfId;
- }
- set
- {
- _ChangedEvent(this, new StyleChangeEventArgs(eStyleClass.Style, eStyleProperty.XfId, value, _positionID, _address));
- }
- }
- internal int PositionID
- {
- get;
- set;
- }
- internal ExcelStyles Styles
- {
- get;
- set;
- }
- internal override string Id
- {
- get
- {
- return Numberformat.Id + "|" + Font.Id + "|" + Fill.Id + "|" + Border.Id + "|" + VerticalAlignment + "|" + HorizontalAlignment + "|" + WrapText.ToString() + "|" + ReadingOrder.ToString() + "|" + XfId.ToString();
- }
- }
-
+/// <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 {
+ get => _styles.CellXfs[Index].HorizontalAlignment;
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Style, eStyleProperty.HorizontalAlign, value, _positionID, _address));
+ }
+
+ /// <summary>
+ /// The vertical alignment in the cell
+ /// </summary>
+ public ExcelVerticalAlignment VerticalAlignment {
+ get => _styles.CellXfs[Index].VerticalAlignment;
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Style, eStyleProperty.VerticalAlign, value, _positionID, _address));
+ }
+
+ /// <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 {
+ get => _styles.CellXfs[Index].ReadingOrder;
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Style, eStyleProperty.ReadingOrder, value, _positionID, _address));
+ }
+
+ /// <summary>
+ /// Shrink the text to fit
+ /// </summary>
+ public bool ShrinkToFit {
+ get => _styles.CellXfs[Index].ShrinkToFit;
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Style, eStyleProperty.ShrinkToFit, value, _positionID, _address));
+ }
+
+ /// <summary>
+ /// The margin between the border and the text
+ /// </summary>
+ public int Indent {
+ get => _styles.CellXfs[Index].Indent;
+ set {
+ if (value < 0 || value > 250) {
+ throw (new ArgumentOutOfRangeException("Indent must be between 0 and 250"));
+ }
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Style, eStyleProperty.Indent, value, _positionID, _address));
+ }
+ }
+
+ /// <summary>
+ /// Text orientation in degrees. Values range from 0 to 180.
+ /// </summary>
+ public int TextRotation {
+ get => _styles.CellXfs[Index].TextRotation;
+ set {
+ if (value < 0 || value > 180) {
+ throw new ArgumentOutOfRangeException("TextRotation out of range.");
+ }
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Style, eStyleProperty.TextRotation, value, _positionID, _address));
+ }
+ }
+
+ /// <summary>
+ /// If true the cell is locked for editing when the sheet is protected
+ /// <seealso cref="ExcelWorksheet.Protection"/>
+ /// </summary>
+ public bool Locked {
+ get => _styles.CellXfs[Index].Locked;
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Style, eStyleProperty.Locked, value, _positionID, _address));
+ }
+
+ /// <summary>
+ /// If true the formula is hidden when the sheet is protected.
+ /// <seealso cref="ExcelWorksheet.Protection"/>
+ /// </summary>
+ public bool Hidden {
+ get => _styles.CellXfs[Index].Hidden;
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Style, eStyleProperty.Hidden, value, _positionID, _address));
+ }
+
+ private const string _xfIdPath = "@xfId";
+
+ /// <summary>
+ /// The index in the style collection
+ /// </summary>
+ public int XfId {
+ get => _styles.CellXfs[Index].XfId;
+ set =>
+ _ChangedEvent(
+ this,
+ new(eStyleClass.Style, eStyleProperty.XfId, value, _positionID, _address));
+ }
+
+ 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/ExcelTextFont.cs b/EPPlus/Style/ExcelTextFont.cs
index 7af62e3..13b7ae1 100644
--- a/EPPlus/Style/ExcelTextFont.cs
+++ b/EPPlus/Style/ExcelTextFont.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,295 +13,263 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Xml;
-using OfficeOpenXml.Drawing;
using System.Drawing;
+using System.Globalization;
+using System.Xml;
-namespace OfficeOpenXml.Style
-{
- /// <summary>
- /// Linestyle
- /// </summary>
- public enum eUnderLineType
- {
- Dash,
- DashHeavy,
- DashLong,
- DashLongHeavy,
- Double,
- DotDash,
- DotDashHeavy,
- DotDotDash,
- DotDotDashHeavy,
- Dotted,
- DottedHeavy,
- Heavy,
- None,
- Single,
- Wavy,
- WavyDbl,
- WavyHeavy,
- Words
- }
- /// <summary>
- /// Type of font strike
- /// </summary>
- public enum eStrikeType
- {
- Double,
- No,
- Single
- }
- /// <summary>
- /// Used by Rich-text and Paragraphs.
- /// </summary>
- public class ExcelTextFont : XmlHelper
- {
- string _path;
- XmlNode _rootNode;
- internal ExcelTextFont(XmlNamespaceManager namespaceManager, XmlNode rootNode, string path, string[] schemaNodeOrder)
- : base(namespaceManager, rootNode)
- {
- SchemaNodeOrder = schemaNodeOrder;
- _rootNode = rootNode;
- if (path != "")
- {
- XmlNode node = rootNode.SelectSingleNode(path, namespaceManager);
- if (node != null)
- {
- TopNode = node;
- }
- }
- _path = path;
- }
- string _fontLatinPath = "a:latin/@typeface";
- public string LatinFont
- {
- get
- {
- return GetXmlNodeString(_fontLatinPath);
- }
- set
- {
- CreateTopNode();
- SetXmlNodeString(_fontLatinPath, value);
- }
- }
+namespace OfficeOpenXml.Style;
- protected internal void CreateTopNode()
- {
- if (_path!="" && TopNode == _rootNode)
- {
- CreateNode(_path);
- TopNode = _rootNode.SelectSingleNode(_path, NameSpaceManager);
- }
- }
- string _fontCsPath = "a:cs/@typeface";
- public string ComplexFont
- {
- get
- {
- return GetXmlNodeString(_fontCsPath);
- }
- set
- {
- CreateTopNode();
- SetXmlNodeString(_fontCsPath, value);
- }
- }
- string _boldPath = "@b";
- public bool Bold
- {
- get
- {
- return GetXmlNodeBool(_boldPath);
- }
- set
- {
- CreateTopNode();
- SetXmlNodeString(_boldPath, value ? "1" : "0");
- }
- }
- string _underLinePath = "@u";
- public eUnderLineType UnderLine
- {
- get
- {
- return TranslateUnderline(GetXmlNodeString(_underLinePath));
- }
- set
- {
- CreateTopNode();
- SetXmlNodeString(_underLinePath, TranslateUnderlineText(value));
- }
- }
- string _underLineColorPath = "a:uFill/a:solidFill/a:srgbClr/@val";
- public Color UnderLineColor
- {
- get
- {
- string col = GetXmlNodeString(_underLineColorPath);
- if (col == "")
- {
- return Color.Empty;
- }
- else
- {
- return Color.FromArgb(int.Parse(col, System.Globalization.NumberStyles.AllowHexSpecifier));
- }
- }
- set
- {
- CreateTopNode();
- SetXmlNodeString(_underLineColorPath, value.ToArgb().ToString("X").Substring(2, 6));
- }
- }
- string _italicPath = "@i";
- public bool Italic
- {
- get
- {
- return GetXmlNodeBool(_italicPath);
- }
- set
- {
- CreateTopNode();
- SetXmlNodeString(_italicPath, value ? "1" : "0");
- }
- }
- string _strikePath = "@strike";
- public eStrikeType Strike
- {
- get
- {
- return TranslateStrike(GetXmlNodeString(_strikePath));
- }
- set
- {
- CreateTopNode();
- SetXmlNodeString(_strikePath, TranslateStrikeText(value));
- }
- }
- string _sizePath = "@sz";
- public float Size
- {
- get
- {
- return GetXmlNodeInt(_sizePath) / 100;
- }
- set
- {
- CreateTopNode();
- SetXmlNodeString(_sizePath, ((int)(value * 100)).ToString());
- }
- }
- string _colorPath = "a:solidFill/a:srgbClr/@val";
- public Color Color
- {
- get
- {
- string col = GetXmlNodeString(_colorPath);
- if (col == "")
- {
- return Color.Empty;
- }
- else
- {
- return Color.FromArgb(int.Parse(col, System.Globalization.NumberStyles.AllowHexSpecifier));
- }
- }
- set
- {
- CreateTopNode();
- SetXmlNodeString(_colorPath, value.ToArgb().ToString("X").Substring(2, 6));
- }
- }
- #region "Translate methods"
- private eUnderLineType TranslateUnderline(string text)
- {
- switch (text)
- {
- case "sng":
- return eUnderLineType.Single;
- case "dbl":
- return eUnderLineType.Double;
- case "":
- return eUnderLineType.None;
- default:
- return (eUnderLineType)Enum.Parse(typeof(eUnderLineType), text);
- }
- }
- private string TranslateUnderlineText(eUnderLineType value)
- {
- switch (value)
- {
- case eUnderLineType.Single:
- return "sng";
- case eUnderLineType.Double:
- return "dbl";
- default:
- string ret = value.ToString();
- return ret.Substring(0, 1).ToLower(CultureInfo.InvariantCulture) + ret.Substring(1, ret.Length - 1);
- }
- }
- private eStrikeType TranslateStrike(string text)
- {
- switch (text)
- {
- case "dblStrike":
- return eStrikeType.Double;
- case "sngStrike":
- return eStrikeType.Single;
- default:
- return eStrikeType.No;
- }
- }
- private string TranslateStrikeText(eStrikeType value)
- {
- switch (value)
- {
- case eStrikeType.Single:
- return "sngStrike";
- case eStrikeType.Double:
- return "dblStrike";
- default:
- return "noStrike";
- }
- }
- #endregion
- /// <summary>
- /// Set the font style from a font object
- /// </summary>
- /// <param name="Font"></param>
- public void SetFromFont(Font Font)
- {
- LatinFont = Font.Name;
- ComplexFont = Font.Name;
- Size = Font.Size;
- if (Font.Bold) Bold = Font.Bold;
- if (Font.Italic) Italic = Font.Italic;
- if (Font.Underline) UnderLine = eUnderLineType.Single;
- if (Font.Strikeout) Strike = eStrikeType.Single;
- }
+/// <summary>
+/// Linestyle
+/// </summary>
+public enum eUnderLineType {
+ Dash,
+ DashHeavy,
+ DashLong,
+ DashLongHeavy,
+ Double,
+ DotDash,
+ DotDashHeavy,
+ DotDotDash,
+ DotDotDashHeavy,
+ Dotted,
+ DottedHeavy,
+ Heavy,
+ None,
+ Single,
+ Wavy,
+ WavyDbl,
+ WavyHeavy,
+ Words,
+}
+
+/// <summary>
+/// Type of font strike
+/// </summary>
+public enum eStrikeType {
+ Double,
+ No,
+ Single,
+}
+
+/// <summary>
+/// Used by Rich-text and Paragraphs.
+/// </summary>
+public class ExcelTextFont : XmlHelper {
+ private string _path;
+ private XmlNode _rootNode;
+
+ internal ExcelTextFont(
+ XmlNamespaceManager namespaceManager,
+ XmlNode rootNode,
+ string path,
+ string[] schemaNodeOrder)
+ : base(namespaceManager, rootNode) {
+ SchemaNodeOrder = schemaNodeOrder;
+ _rootNode = rootNode;
+ if (path != "") {
+ XmlNode node = rootNode.SelectSingleNode(path, namespaceManager);
+ if (node != null) {
+ TopNode = node;
+ }
}
+ _path = path;
+ }
+
+ private string _fontLatinPath = "a:latin/@typeface";
+
+ public string LatinFont {
+ get => GetXmlNodeString(_fontLatinPath);
+ set {
+ CreateTopNode();
+ SetXmlNodeString(_fontLatinPath, value);
+ }
+ }
+
+ protected internal void CreateTopNode() {
+ if (_path != "" && TopNode == _rootNode) {
+ CreateNode(_path);
+ TopNode = _rootNode.SelectSingleNode(_path, NameSpaceManager);
+ }
+ }
+
+ private string _fontCsPath = "a:cs/@typeface";
+
+ public string ComplexFont {
+ get => GetXmlNodeString(_fontCsPath);
+ set {
+ CreateTopNode();
+ SetXmlNodeString(_fontCsPath, value);
+ }
+ }
+
+ private string _boldPath = "@b";
+
+ public bool Bold {
+ get => GetXmlNodeBool(_boldPath);
+ set {
+ CreateTopNode();
+ SetXmlNodeString(_boldPath, value ? "1" : "0");
+ }
+ }
+
+ private string _underLinePath = "@u";
+
+ public eUnderLineType UnderLine {
+ get => TranslateUnderline(GetXmlNodeString(_underLinePath));
+ set {
+ CreateTopNode();
+ SetXmlNodeString(_underLinePath, TranslateUnderlineText(value));
+ }
+ }
+
+ private string _underLineColorPath = "a:uFill/a:solidFill/a:srgbClr/@val";
+
+ public Color UnderLineColor {
+ get {
+ string col = GetXmlNodeString(_underLineColorPath);
+ if (col == "") {
+ return Color.Empty;
+ }
+ return Color.FromArgb(int.Parse(col, NumberStyles.AllowHexSpecifier));
+ }
+ set {
+ CreateTopNode();
+ SetXmlNodeString(_underLineColorPath, value.ToArgb().ToString("X").Substring(2, 6));
+ }
+ }
+
+ private string _italicPath = "@i";
+
+ public bool Italic {
+ get => GetXmlNodeBool(_italicPath);
+ set {
+ CreateTopNode();
+ SetXmlNodeString(_italicPath, value ? "1" : "0");
+ }
+ }
+
+ private string _strikePath = "@strike";
+
+ public eStrikeType Strike {
+ get => TranslateStrike(GetXmlNodeString(_strikePath));
+ set {
+ CreateTopNode();
+ SetXmlNodeString(_strikePath, TranslateStrikeText(value));
+ }
+ }
+
+ private string _sizePath = "@sz";
+
+ public float Size {
+ get => GetXmlNodeInt(_sizePath) / 100;
+ set {
+ CreateTopNode();
+ SetXmlNodeString(_sizePath, ((int)(value * 100)).ToString());
+ }
+ }
+
+ private string _colorPath = "a:solidFill/a:srgbClr/@val";
+
+ public Color Color {
+ get {
+ string col = GetXmlNodeString(_colorPath);
+ if (col == "") {
+ return Color.Empty;
+ }
+ return Color.FromArgb(int.Parse(col, NumberStyles.AllowHexSpecifier));
+ }
+ set {
+ CreateTopNode();
+ SetXmlNodeString(_colorPath, value.ToArgb().ToString("X").Substring(2, 6));
+ }
+ }
+
+ private eUnderLineType TranslateUnderline(string text) {
+ switch (text) {
+ case "sng":
+ return eUnderLineType.Single;
+ case "dbl":
+ return eUnderLineType.Double;
+ case "":
+ return eUnderLineType.None;
+ default:
+ return (eUnderLineType)Enum.Parse(typeof(eUnderLineType), text);
+ }
+ }
+
+ private string TranslateUnderlineText(eUnderLineType value) {
+ switch (value) {
+ case eUnderLineType.Single:
+ return "sng";
+ case eUnderLineType.Double:
+ return "dbl";
+ default:
+ string ret = value.ToString();
+ return ret.Substring(0, 1).ToLower(CultureInfo.InvariantCulture)
+ + ret.Substring(1, ret.Length - 1);
+ }
+ }
+
+ private eStrikeType TranslateStrike(string text) {
+ switch (text) {
+ case "dblStrike":
+ return eStrikeType.Double;
+ case "sngStrike":
+ return eStrikeType.Single;
+ default:
+ return eStrikeType.No;
+ }
+ }
+
+ private string TranslateStrikeText(eStrikeType value) {
+ switch (value) {
+ case eStrikeType.Single:
+ return "sngStrike";
+ case eStrikeType.Double:
+ return "dblStrike";
+ default:
+ return "noStrike";
+ }
+ }
+
+ /// <summary>
+ /// Set the font style from a font object
+ /// </summary>
+ /// <param name="font"></param>
+ public void SetFromFont(Font font) {
+ LatinFont = font.Name;
+ ComplexFont = font.Name;
+ Size = font.Size;
+ if (font.Bold) {
+ Bold = font.Bold;
+ }
+ if (font.Italic) {
+ Italic = font.Italic;
+ }
+ if (font.Underline) {
+ UnderLine = eUnderLineType.Single;
+ }
+ if (font.Strikeout) {
+ Strike = eStrikeType.Single;
+ }
+ }
}
diff --git a/EPPlus/Style/IStyle.cs b/EPPlus/Style/IStyle.cs
index 38235aa..f1f492e 100644
--- a/EPPlus/Style/IStyle.cs
+++ b/EPPlus/Style/IStyle.cs
@@ -13,32 +13,29 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
-using OfficeOpenXml.Style;
-namespace OfficeOpenXml.Style
-{
- internal interface IStyle
- {
- void SetNewStyleID(string value);
- ulong Id {get;}
- ExcelStyle ExcelStyle{get;}
- }
+
+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
index aedddf2..fa1b390 100644
--- a/EPPlus/Style/StyleBase.cs
+++ b/EPPlus/Style/StyleBase.cs
@@ -13,172 +13,176 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
-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 OfficeOpenXml.XmlHelper.ChangedEventHandler _ChangedEvent;
- protected int _positionID;
- protected string _address;
- internal StyleBase(ExcelStyles styles, OfficeOpenXml.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;}
+namespace OfficeOpenXml.Style;
- internal virtual void SetIndex(int index)
- {
- Index = index;
- }
- }
+/// <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
index f671df0..352dc51 100644
--- a/EPPlus/Style/StyleChangeEventArgs.cs
+++ b/EPPlus/Style/StyleChangeEventArgs.cs
@@ -13,101 +13,107 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
-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;
- }
+
+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
index e2f91b2..7e94481 100644
--- a/EPPlus/Style/XmlAccess/ExcelBorderItemXml.cs
+++ b/EPPlus/Style/XmlAccess/ExcelBorderItemXml.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,145 +13,123 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Xml;
-using OfficeOpenXml.Style;
-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 ExcelColorXml(NameSpaceManager);
- }
- internal ExcelBorderItemXml(XmlNamespaceManager nsm, XmlNode topNode) :
- base(nsm, topNode)
- {
- if (topNode != null)
- {
- _borderStyle = GetBorderStyle(GetXmlNodeString("@style"));
- _color = new ExcelColorXml(nsm, topNode.SelectSingleNode(_colorPath, nsm));
- Exists = true;
- }
- else
- {
- Exists = false;
- }
- }
- private ExcelBorderStyle GetBorderStyle(string style)
- {
- if(style=="") return ExcelBorderStyle.None;
- string sInStyle = style.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture) + style.Substring(1, style.Length - 1);
- try
- {
- return (ExcelBorderStyle)Enum.Parse(typeof(ExcelBorderStyle), sInStyle);
- }
- catch
- {
- return ExcelBorderStyle.None;
- }
+namespace OfficeOpenXml.Style.XmlAccess;
- }
- ExcelBorderStyle _borderStyle = ExcelBorderStyle.None;
- /// <summary>
- /// Cell Border style
- /// </summary>
- public ExcelBorderStyle Style
- {
- get
- {
- return _borderStyle;
- }
- set
- {
- _borderStyle = value;
- Exists = true;
- }
- }
- ExcelColorXml _color = null;
- const string _colorPath = "d:color";
- /// <summary>
- /// Border style
- /// </summary>
- public ExcelColorXml Color
- {
- get
- {
- return _color;
- }
- internal set
- {
- _color = value;
- }
- }
- internal override string Id
- {
- get
- {
- if (Exists)
- {
- return Style + Color.Id;
- }
- else
- {
- return "None";
- }
- }
- }
+/// <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 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; }
+ 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;
+ }
+ string sInStyle =
+ style.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture)
+ + style.Substring(1, style.Length - 1);
+ try {
+ return (ExcelBorderStyle)Enum.Parse(typeof(ExcelBorderStyle), sInStyle);
+ } catch {
+ return 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
index 700f319..9a7e12c 100644
--- a/EPPlus/Style/XmlAccess/ExcelBorderXml.cs
+++ b/EPPlus/Style/XmlAccess/ExcelBorderXml.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,206 +13,159 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
+
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 ExcelBorderItemXml(nsm, topNode.SelectSingleNode(leftPath, nsm));
- _right = new ExcelBorderItemXml(nsm, topNode.SelectSingleNode(rightPath, nsm));
- _top = new ExcelBorderItemXml(nsm, topNode.SelectSingleNode(topPath, nsm));
- _bottom = new ExcelBorderItemXml(nsm, topNode.SelectSingleNode(bottomPath, nsm));
- _diagonal = new ExcelBorderItemXml(nsm, topNode.SelectSingleNode(diagonalPath, nsm));
- _diagonalUp = GetBoolValue(topNode, diagonalUpPath);
- _diagonalDown = GetBoolValue(topNode, diagonalDownPath);
- }
- internal override string Id
- {
- get
- {
- return Left.Id + Right.Id + Top.Id + Bottom.Id + Diagonal.Id + DiagonalUp.ToString() + DiagonalDown.ToString();
- }
- }
- const string leftPath = "d:left";
- ExcelBorderItemXml _left = null;
- /// <summary>
- /// Left border style properties
- /// </summary>
- public ExcelBorderItemXml Left
- {
- get
- {
- return _left;
- }
- internal set
- {
- _left = value;
- }
- }
- const string rightPath = "d:right";
- ExcelBorderItemXml _right = null;
- /// <summary>
- /// Right border style properties
- /// </summary>
- public ExcelBorderItemXml Right
- {
- get
- {
- return _right;
- }
- internal set
- {
- _right = value;
- }
- }
- const string topPath = "d:top";
- ExcelBorderItemXml _top = null;
- /// <summary>
- /// Top border style properties
- /// </summary>
- public ExcelBorderItemXml Top
- {
- get
- {
- return _top;
- }
- internal set
- {
- _top = value;
- }
- }
- const string bottomPath = "d:bottom";
- ExcelBorderItemXml _bottom = null;
- /// <summary>
- /// Bottom border style properties
- /// </summary>
- public ExcelBorderItemXml Bottom
- {
- get
- {
- return _bottom;
- }
- internal set
- {
- _bottom = value;
- }
- }
- const string diagonalPath = "d:diagonal";
- ExcelBorderItemXml _diagonal = null;
- /// <summary>
- /// Diagonal border style properties
- /// </summary>
- public ExcelBorderItemXml Diagonal
- {
- get
- {
- return _diagonal;
- }
- internal set
- {
- _diagonal = value;
- }
- }
- const string diagonalUpPath = "@diagonalUp";
- bool _diagonalUp = false;
- /// <summary>
- /// Diagonal up border
- /// </summary>
- public bool DiagonalUp
- {
- get
- {
- return _diagonalUp;
- }
- internal set
- {
- _diagonalUp = value;
- }
- }
- const string diagonalDownPath = "@diagonalDown";
- bool _diagonalDown = false;
- /// <summary>
- /// Diagonal down border
- /// </summary>
- public bool DiagonalDown
- {
- get
- {
- return _diagonalDown;
- }
- internal set
- {
- _diagonalDown = value;
- }
- }
+namespace OfficeOpenXml.Style.XmlAccess;
- 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;
+/// <summary>
+/// Xml access class for border top level
+/// </summary>
+public sealed class ExcelBorderXml : StyleXmlHelper {
+ internal ExcelBorderXml(XmlNamespaceManager nameSpaceManager)
+ : base(nameSpaceManager) {}
- return newBorder;
+ 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;
- 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;
- }
+ private const string _leftPath = "d:left";
+ private ExcelBorderItemXml _left;
+
+ /// <summary>
+ /// Left border style properties
+ /// </summary>
+ public ExcelBorderItemXml Left {
+ get { return _left; }
+ internal set { _left = value; }
+ }
+
+ private const string _rightPath = "d:right";
+ private ExcelBorderItemXml _right;
+
+ /// <summary>
+ /// Right border style properties
+ /// </summary>
+ public ExcelBorderItemXml Right {
+ get { return _right; }
+ internal set { _right = value; }
+ }
+
+ private const string _topPath = "d:top";
+ private ExcelBorderItemXml _top;
+
+ /// <summary>
+ /// Top border style properties
+ /// </summary>
+ public ExcelBorderItemXml Top {
+ get { return _top; }
+ internal set { _top = value; }
+ }
+
+ private const string _bottomPath = "d:bottom";
+ private ExcelBorderItemXml _bottom;
+
+ /// <summary>
+ /// Bottom border style properties
+ /// </summary>
+ public ExcelBorderItemXml Bottom {
+ get { return _bottom; }
+ internal set { _bottom = value; }
+ }
+
+ private const string _diagonalPath = "d:diagonal";
+ private ExcelBorderItemXml _diagonal;
+
+ /// <summary>
+ /// Diagonal border style properties
+ /// </summary>
+ public ExcelBorderItemXml Diagonal {
+ get { return _diagonal; }
+ internal set { _diagonal = value; }
+ }
+
+ private const string _diagonalUpPath = "@diagonalUp";
+ private bool _diagonalUp;
+
+ /// <summary>
+ /// Diagonal up border
+ /// </summary>
+ public bool DiagonalUp {
+ get { return _diagonalUp; }
+ internal set { _diagonalUp = value; }
+ }
+
+ private const string _diagonalDownPath = "@diagonalDown";
+ private bool _diagonalDown;
+
+ /// <summary>
+ /// Diagonal down border
+ /// </summary>
+ public bool DiagonalDown {
+ get { return _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
index b636119..ba1fd11 100644
--- a/EPPlus/Style/XmlAccess/ExcelColorXml.cs
+++ b/EPPlus/Style/XmlAccess/ExcelColorXml.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,207 +13,169 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
-using System.Xml;
+using System.Drawing;
using System.Globalization;
-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
- {
- get
- {
- return _auto.ToString() + "|" + _theme + "|" + _tint + "|" + _rgb + "|" + _indexed;
- }
- }
- bool _auto;
- public bool Auto
- {
- get
- {
- return _auto;
- }
- set
- {
- _auto = value;
- _exists = true;
- Clear();
- }
- }
- string _theme;
- /// <summary>
- /// Theme color value
- /// </summary>
- public string Theme
- {
- get
- {
- return _theme;
- }
- }
- decimal _tint;
- /// <summary>
- /// Tint
- /// </summary>
- public decimal Tint
- {
- get
- {
- if (_tint == decimal.MinValue)
- {
- return 0;
- }
- else
- {
- return _tint;
- }
- }
- set
- {
- _tint = value;
- _exists = true;
- }
- }
- string _rgb;
- /// <summary>
- /// RGB value
- /// </summary>
- public string Rgb
- {
- get
- {
- return _rgb;
- }
- set
- {
- _rgb = value;
- _exists=true;
- _indexed = int.MinValue;
- _auto = false;
- }
- }
- int _indexed;
- /// <summary>
- /// Indexed color value
- /// </summary>
- public int Indexed
- {
- get
- {
- return (_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;
- }
- public void SetColor(System.Drawing.Color color)
- {
- Clear();
- _rgb = color.ToArgb().ToString("X");
- }
+using System.Xml;
- internal ExcelColorXml Copy()
- {
- return new ExcelColorXml(NameSpaceManager) {_indexed=_indexed, _tint=_tint, _rgb=_rgb, _theme=_theme, _auto=_auto, _exists=_exists };
- }
+namespace OfficeOpenXml.Style.XmlAccess;
- 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.ToString());
- }
- if (_tint != decimal.MinValue)
- {
- SetXmlNodeString("@tint", _tint.ToString(CultureInfo.InvariantCulture));
- }
- return TopNode;
- }
+/// <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;
+ }
- bool _exists;
- internal bool Exists
- {
- get
- {
- return _exists;
- }
- }
+ 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;
+ }
+
+ public void SetColor(Color color) {
+ Clear();
+ _rgb = color.ToArgb().ToString("X");
+ }
+
+ 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
index 2cea423..98b7c9d 100644
--- a/EPPlus/Style/XmlAccess/ExcelFillXml.cs
+++ b/EPPlus/Style/XmlAccess/ExcelFillXml.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,162 +13,126 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.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 ExcelColorXml(NameSpaceManager);
- _patternColor = new ExcelColorXml(NameSpaceManager);
- }
- internal ExcelFillXml(XmlNamespaceManager nsm, XmlNode topNode):
- base(nsm, topNode)
- {
- PatternType = GetPatternType(GetXmlNodeString(fillPatternTypePath));
- _backgroundColor = new ExcelColorXml(nsm, topNode.SelectSingleNode(_backgroundColorPath, nsm));
- _patternColor = new ExcelColorXml(nsm, topNode.SelectSingleNode(_patternColorPath, nsm));
- }
- private ExcelFillStyle GetPatternType(string patternType)
- {
- if (patternType == "") return ExcelFillStyle.None;
- patternType = patternType.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture) + patternType.Substring(1, patternType.Length - 1);
- try
- {
- return (ExcelFillStyle)Enum.Parse(typeof(ExcelFillStyle), patternType);
- }
- catch
- {
- return ExcelFillStyle.None;
- }
- }
- internal override string Id
- {
- get
- {
- return PatternType + PatternColor.Id + BackgroundColor.Id;
- }
- }
- #region Public Properties
- const string fillPatternTypePath = "d:patternFill/@patternType";
- protected ExcelFillStyle _fillPatternType;
- /// <summary>
- /// Cell fill pattern style
- /// </summary>
- public ExcelFillStyle PatternType
- {
- get
- {
- return _fillPatternType;
- }
- set
- {
- _fillPatternType=value;
- }
- }
- protected ExcelColorXml _patternColor = null;
- const string _patternColorPath = "d:patternFill/d:bgColor";
- /// <summary>
- /// Pattern color
- /// </summary>
- public ExcelColorXml PatternColor
- {
- get
- {
- return _patternColor;
- }
- internal set
- {
- _patternColor = value;
- }
- }
- protected ExcelColorXml _backgroundColor = null;
- const string _backgroundColorPath = "d:patternFill/d:fgColor";
- /// <summary>
- /// Cell background color
- /// </summary>
- public ExcelColorXml BackgroundColor
- {
- get
- {
- return _backgroundColor;
- }
- internal set
- {
- _backgroundColor=value;
- }
- }
- #endregion
+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 Fill Copy()
- //{
- // Fill newFill = new Fill(NameSpaceManager, TopNode.Clone());
- // return newFill;
- //}
+ 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));
+ }
- 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);
- }
+ private ExcelFillStyle GetPatternType(string patternType) {
+ if (patternType == "") {
+ return ExcelFillStyle.None;
}
+ patternType =
+ patternType.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture)
+ + patternType.Substring(1, patternType.Length - 1);
+ try {
+ return (ExcelFillStyle)Enum.Parse(typeof(ExcelFillStyle), patternType);
+ } catch {
+ return 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
index 0247591..11b6bb9 100644
--- a/EPPlus/Style/XmlAccess/ExcelFontXml.cs
+++ b/EPPlus/Style/XmlAccess/ExcelFontXml.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,321 +13,294 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Drawing;
using System.Globalization;
-using System.Text;
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 ExcelColorXml(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 ExcelColorXml(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
- {
- _underlineType = (ExcelUnderLineType)Enum.Parse(typeof(ExcelUnderLineType), ut, true);
- }
- }
- else
- {
- _underlineType = ExcelUnderLineType.None;
- }
- }
- internal override string Id
- {
- get
- {
- return Name + "|" + Size + "|" + Family + "|" + Color.Id + "|" + Scheme + "|" + Bold.ToString() + "|" + Italic.ToString() + "|" + Strike.ToString() + "|" + VerticalAlign + "|" + UnderLineType.ToString();
- }
- }
- const string namePath = "d:name/@val";
- string _name;
- /// <summary>
- /// The name of the font
- /// </summary>
- public string Name
- {
- get
- {
- return _name;
- }
- set
- {
- Scheme = ""; //Reset schema to avoid corrupt file if unsupported font is selected.
- _name = value;
- }
- }
- const string sizePath = "d:sz/@val";
- float _size;
- /// <summary>
- /// Font size
- /// </summary>
- public float Size
- {
- get
- {
- return _size;
- }
- set
- {
- _size = value;
- }
- }
- const string familyPath = "d:family/@val";
- int _family;
- /// <summary>
- /// Font family
- /// </summary>
- public int Family
- {
- get
- {
- return (_family == int.MinValue ? 0 : _family); ;
- }
- set
- {
- _family=value;
- }
- }
- ExcelColorXml _color = null;
- const string _colorPath = "d:color";
- /// <summary>
- /// Text color
- /// </summary>
- public ExcelColorXml Color
- {
- get
- {
- return _color;
- }
- internal set
- {
- _color=value;
- }
- }
- const string schemePath = "d:scheme/@val";
- string _scheme="";
- /// <summary>
- /// Font Scheme
- /// </summary>
- public string Scheme
- {
- get
- {
- return _scheme;
- }
- private set
- {
- _scheme=value;
- }
- }
- const string boldPath = "d:b";
- bool _bold;
- /// <summary>
- /// If the font is bold
- /// </summary>
- public bool Bold
- {
- get
- {
- return _bold;
- }
- set
- {
- _bold=value;
- }
- }
- const string italicPath = "d:i";
- bool _italic;
- /// <summary>
- /// If the font is italic
- /// </summary>
- public bool Italic
- {
- get
- {
- return _italic;
- }
- set
- {
- _italic=value;
- }
- }
- const string strikePath = "d:strike";
- bool _strike;
- /// <summary>
- /// If the font is striked out
- /// </summary>
- public bool Strike
- {
- get
- {
- return _strike;
- }
- set
- {
- _strike=value;
- }
- }
- 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
- {
- return UnderLineType!=ExcelUnderLineType.None;
- }
- set
- {
- _underlineType=value ? ExcelUnderLineType.Single : ExcelUnderLineType.None;
- }
- }
- ExcelUnderLineType _underlineType;
- /// <summary>
- /// If the font is underlined
- /// </summary>
- public ExcelUnderLineType UnderLineType
- {
- get
- {
- return _underlineType;
- }
- set
- {
- _underlineType = value;
- }
- }
- const string verticalAlignPath = "d:vertAlign/@val";
- string _verticalAlign;
- /// <summary>
- /// Vertical aligned
- /// </summary>
- public string VerticalAlign
- {
- get
- {
- return _verticalAlign;
- }
- set
- {
- _verticalAlign=value;
- }
- }
- public void SetFromFont(System.Drawing.Font Font)
- {
- Name=Font.Name;
- //Family=fnt.FontFamily.;
- Size=(int)Font.Size;
- Strike=Font.Strikeout;
- Bold = Font.Bold;
- UnderLine=Font.Underline;
- Italic=Font.Italic;
- }
- 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;
- }
+namespace OfficeOpenXml.Style.XmlAccess;
- internal override XmlNode CreateXmlNode(XmlNode topElement)
- {
- TopNode = topElement;
+/// <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 = "";
+ }
- 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.ToString());
- if(_size>0) SetXmlNodeString(sizePath, _size.ToString(System.Globalization.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.ToString());
-
- return TopNode;
- }
+ 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 {
+ _underlineType = (ExcelUnderLineType)Enum.Parse(typeof(ExcelUnderLineType), ut, true);
+ }
+ } 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 { return _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 { return _size; }
+ set { _size = value; }
+ }
+
+ private const string _familyPath = "d:family/@val";
+ private int _family;
+
+ /// <summary>
+ /// Font family
+ /// </summary>
+ public int Family {
+ get {
+ return (_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 { return _color; }
+ internal set { _color = value; }
+ }
+
+ private const string _schemePath = "d:scheme/@val";
+ private string _scheme = "";
+
+ /// <summary>
+ /// Font Scheme
+ /// </summary>
+ public string Scheme {
+ get { return _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 { return _bold; }
+ set { _bold = value; }
+ }
+
+ private const string _italicPath = "d:i";
+ private bool _italic;
+
+ /// <summary>
+ /// If the font is italic
+ /// </summary>
+ public bool Italic {
+ get { return _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 { return _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 { return UnderLineType != ExcelUnderLineType.None; }
+ set { _underlineType = value ? ExcelUnderLineType.Single : ExcelUnderLineType.None; }
+ }
+
+ private ExcelUnderLineType _underlineType;
+
+ /// <summary>
+ /// If the font is underlined
+ /// </summary>
+ public ExcelUnderLineType UnderLineType {
+ get { return _underlineType; }
+ set { _underlineType = value; }
+ }
+
+ private const string _verticalAlignPath = "d:vertAlign/@val";
+ private string _verticalAlign;
+
+ /// <summary>
+ /// Vertical aligned
+ /// </summary>
+ public string VerticalAlign {
+ get { return _verticalAlign; }
+ set { _verticalAlign = value; }
+ }
+
+ public void SetFromFont(Font font) {
+ Name = font.Name;
+ //Family=fnt.FontFamily.;
+ Size = (int)font.Size;
+ Strike = font.Strikeout;
+ Bold = font.Bold;
+ UnderLine = font.Underline;
+ Italic = font.Italic;
+ }
+
+ 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
index adaf0a5..00adf5e 100644
--- a/EPPlus/Style/XmlAccess/ExcelGradientFillXml.cs
+++ b/EPPlus/Style/XmlAccess/ExcelGradientFillXml.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,186 +13,172 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
-using System.Xml;
+
using System.Globalization;
-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 ExcelColorXml(nameSpaceManager);
- GradientColor2 = new ExcelColorXml(nameSpaceManager);
- }
- internal ExcelGradientFillXml(XmlNamespaceManager nsm, XmlNode topNode) :
- base(nsm, topNode)
- {
- Degree = GetXmlNodeDouble(_degreePath);
- Type = GetXmlNodeString(_typePath)=="path" ? ExcelFillGradientType.Path : ExcelFillGradientType.Linear;
- GradientColor1 = new ExcelColorXml(nsm, topNode.SelectSingleNode(_gradientColor1Path, nsm));
- GradientColor2 = new ExcelColorXml(nsm, topNode.SelectSingleNode(_gradientColor2Path, nsm));
-
- Top = GetXmlNodeDouble(_topPath);
- Bottom = GetXmlNodeDouble(_bottomPath);
- Left = GetXmlNodeDouble(_leftPath);
- Right = GetXmlNodeDouble(_rightPath);
- }
- const string _typePath = "d:gradientFill/@type";
- /// <summary>
- /// Type of gradient fill.
- /// </summary>
- public ExcelFillGradientType Type
- {
- get;
- internal set;
- }
- const string _degreePath = "d:gradientFill/@degree";
- /// <summary>
- /// Angle of the linear gradient
- /// </summary>
- public double Degree
- {
- get;
- internal set;
- }
- const string _gradientColor1Path = "d:gradientFill/d:stop[@position=\"0\"]/d:color";
- /// <summary>
- /// Gradient color 1
- /// </summary>
- public ExcelColorXml GradientColor1
- {
- get;
- private set;
- }
- const string _gradientColor2Path = "d:gradientFill/d:stop[@position=\"1\"]/d:color";
- /// <summary>
- /// Gradient color 2
- /// </summary>
- public ExcelColorXml GradientColor2
- {
- get;
- private set;
- }
- const string _bottomPath = "d:gradientFill/@bottom";
- /// <summary>
- /// Percentage format bottom
- /// </summary>
- public double Bottom
- {
- get;
- internal set;
- }
- const string _topPath = "d:gradientFill/@top";
- /// <summary>
- /// Percentage format top
- /// </summary>
- public double Top
- {
- get;
- internal set;
- }
- const string _leftPath = "d:gradientFill/@left";
- /// <summary>
- /// Percentage format left
- /// </summary>
- public double Left
- {
- get;
- internal set;
- }
- const string _rightPath = "d:gradientFill/@right";
- /// <summary>
- /// Percentage format right
- /// </summary>
- public double Right
- {
- get;
- internal set;
- }
- internal override string Id
- {
- get
- {
- return base.Id + Degree.ToString() + GradientColor1.Id + GradientColor2.Id + Type + Left.ToString() + Right.ToString() + Bottom.ToString() + Top.ToString();
- }
- }
+using System.Xml;
- #region Public Properties
- #endregion
- internal override ExcelFillXml Copy()
- {
- ExcelGradientFillXml newFill = new ExcelGradientFillXml(NameSpaceManager);
- newFill.PatternType = base._fillPatternType;
- newFill.BackgroundColor = _backgroundColor.Copy();
- newFill.PatternColor = _patternColor.Copy();
+namespace OfficeOpenXml.Style.XmlAccess;
- 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;
- }
+/// <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 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);
+ 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));
- /*** 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);
+ Top = GetXmlNodeDouble(_topPath);
+ Bottom = GetXmlNodeDouble(_bottomPath);
+ Left = GetXmlNodeDouble(_leftPath);
+ Right = GetXmlNodeDouble(_rightPath);
+ }
- 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));
+ private const string _typePath = "d:gradientFill/@type";
- return topNode;
- }
+ /// <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
index 77de394..599052c 100644
--- a/EPPlus/Style/XmlAccess/ExcelNamedStyleXml.cs
+++ b/EPPlus/Style/XmlAccess/ExcelNamedStyleXml.cs
@@ -13,133 +13,115 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
+
using System.Xml;
-namespace OfficeOpenXml.Style.XmlAccess
-{
- /// <summary>
- /// Xml access class for named styles
- /// </summary>
- public sealed class ExcelNamedStyleXml : StyleXmlHelper
- {
- 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 ExcelStyle(styles, styles.NamedStylePropertyChange, -1, Name, _styleXfId);
- }
- internal override string Id
- {
- get
- {
- return Name;
- }
- }
- int _styleXfId=0;
- const string idPath = "@xfId";
- /// <summary>
- /// Named style index
- /// </summary>
- public int StyleXfId
- {
- get
- {
- return _styleXfId;
- }
- set
- {
- _styleXfId = value;
- }
- }
- int _xfId = int.MinValue;
- /// <summary>
- /// Style index
- /// </summary>
- internal int XfId
- {
- get
- {
- return _xfId;
- }
- set
- {
- _xfId = value;
- }
- }
- const string buildInIdPath = "@builtinId";
- public int BuildInId { get; set; }
- const string customBuiltinPath = "@customBuiltin";
- public bool CustomBuildin { get; set; }
- const string namePath = "@name";
- string _name;
- /// <summary>
- /// Name of the style
- /// </summary>
- public string Name
- {
- get
- {
- return _name;
- }
- internal set
- {
- _name = value;
- }
- }
- ExcelStyle _style = null;
- /// <summary>
- /// The style object
- /// </summary>
- public ExcelStyle Style
- {
- get
- {
- return _style;
- }
- internal set
- {
- _style = value;
- }
- }
+namespace OfficeOpenXml.Style.XmlAccess;
- 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;
- }
+/// <summary>
+/// Xml access class for named styles
+/// </summary>
+public sealed class ExcelNamedStyleXml : StyleXmlHelper {
+ private 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
index 410a2dd..0d0b46f 100644
--- a/EPPlus/Style/XmlAccess/ExcelNumberFormatXml.cs
+++ b/EPPlus/Style/XmlAccess/ExcelNumberFormatXml.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,658 +13,691 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
-using System.Xml;
using System.Globalization;
+using System.Text;
using System.Text.RegularExpressions;
-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; }
- 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
- {
- return _numFmtId;
- }
- set
- {
- _numFmtId = value;
- }
- }
- internal override string Id
- {
- get
- {
- return _format;
- }
- }
- const string fmtPath = "@formatCode";
- string _format = string.Empty;
- public string Format
- {
- get
- {
- return _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();
- }
+using System.Xml;
- internal static void AddBuildIn(XmlNamespaceManager NameSpaceManager, ExcelStyleCollection<ExcelNumberFormatXml> NumberFormats)
- {
- NumberFormats.Add("General",new ExcelNumberFormatXml(NameSpaceManager,true){NumFmtId=0,Format="General"});
- NumberFormats.Add("0", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 1, Format = "0" });
- NumberFormats.Add("0.00", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 2, Format = "0.00" });
- NumberFormats.Add("#,##0", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 3, Format = "#,##0" });
- NumberFormats.Add("#,##0.00", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 4, Format = "#,##0.00" });
- NumberFormats.Add("0%", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 9, Format = "0%" });
- NumberFormats.Add("0.00%", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 10, Format = "0.00%" });
- NumberFormats.Add("0.00E+00", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 11, Format = "0.00E+00" });
- NumberFormats.Add("# ?/?", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 12, Format = "# ?/?" });
- NumberFormats.Add("# ??/??", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 13, Format = "# ??/??" });
- NumberFormats.Add("mm-dd-yy", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 14, Format = "mm-dd-yy" });
- NumberFormats.Add("d-mmm-yy", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 15, Format = "d-mmm-yy" });
- NumberFormats.Add("d-mmm", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 16, Format = "d-mmm" });
- NumberFormats.Add("mmm-yy", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 17, Format = "mmm-yy" });
- NumberFormats.Add("h:mm AM/PM", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 18, Format = "h:mm AM/PM" });
- NumberFormats.Add("h:mm:ss AM/PM", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 19, Format = "h:mm:ss AM/PM" });
- NumberFormats.Add("h:mm", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 20, Format = "h:mm" });
- NumberFormats.Add("h:mm:ss", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 21, Format = "h:mm:ss" });
- NumberFormats.Add("m/d/yy h:mm", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 22, Format = "m/d/yy h:mm" });
- NumberFormats.Add("#,##0 ;(#,##0)", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 37, Format = "#,##0 ;(#,##0)" });
- NumberFormats.Add("#,##0 ;[Red](#,##0)", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 38, Format = "#,##0 ;[Red](#,##0)" });
- NumberFormats.Add("#,##0.00;(#,##0.00)", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 39, Format = "#,##0.00;(#,##0.00)" });
- NumberFormats.Add("#,##0.00;[Red](#,##0.00)", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 40, Format = "#,##0.00;[Red](#,#)" });
- NumberFormats.Add("mm:ss", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 45, Format = "mm:ss" });
- NumberFormats.Add("[h]:mm:ss", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 46, Format = "[h]:mm:ss" });
- NumberFormats.Add("mmss.0", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 47, Format = "mmss.0" });
- NumberFormats.Add("##0.0", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 48, Format = "##0.0" });
- NumberFormats.Add("@", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 49, Format = "@" });
+namespace OfficeOpenXml.Style.XmlAccess;
- NumberFormats.NextId = 164; //Start for custom formats.
- }
+/// <summary>
+/// Xml access class for number formats
+/// </summary>
+public sealed class ExcelNumberFormatXml : StyleXmlHelper {
+ internal ExcelNumberFormatXml(XmlNamespaceManager nameSpaceManager)
+ : base(nameSpaceManager) {}
- internal override XmlNode CreateXmlNode(XmlNode topNode)
- {
- TopNode = topNode;
- SetXmlNodeString("@numFmtId", NumFmtId.ToString());
- SetXmlNodeString("@formatCode", Format);
- return TopNode;
- }
+ internal ExcelNumberFormatXml(XmlNamespaceManager nameSpaceManager, bool buildIn)
+ : base(nameSpaceManager) {
+ BuildIn = buildIn;
+ }
- internal enum eFormatType
- {
- Unknown = 0,
- Number = 1,
- DateTime = 2,
- }
- ExcelFormatTranslator _translator = null;
- internal ExcelFormatTranslator FormatTranslator
- {
- get
- {
- if (_translator == null)
- {
- _translator = new ExcelFormatTranslator(Format, NumFmtId);
- }
- return _translator;
- }
- }
- #region Excel --> .Net Format
- 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; }
- CultureInfo _ci = null;
- 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 ExcelNumberFormatXml(XmlNamespaceManager nsm, XmlNode topNode)
+ : base(nsm, topNode) {
+ _numFmtId = GetXmlNodeInt("@numFmtId");
+ _format = GetXmlNodeString("@formatCode");
+ }
- //internal string FractionFormatInteger { get; private set; }
- internal string FractionFormat { get; private set; }
- //internal string FractionFormat2 { get; private set; }
+ public bool BuildIn { 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;
- int fractionPos = -1;
- 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;
+ private int _numFmtId;
- if (containsAmPm)
- {
- ExcelFormat = Regex.Replace(ExcelFormat, "AM/PM", "");
- DataType = eFormatType.DateTime;
- }
+ // 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;
+ }
- for (int pos = 0; pos < ExcelFormat.Length; pos++)
- {
- char c = ExcelFormat[pos];
- if (c == '"')
- {
- isText = !isText;
- }
- else
- {
- if (ignoreNext)
- {
- ignoreNext = false;
- continue;
- }
- else 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 List<int>();
- format = sb.ToString();
- sb = new StringBuilder();
- }
- 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;
- }
- }
+ internal override string Id => _format;
- 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)
- {
- fractionPos = sb.Length;
- int startPos = pos - 1;
- while (startPos >= 0 &&
- (ExcelFormat[startPos] == '?' ||
- ExcelFormat[startPos] == '#' ||
- ExcelFormat[startPos] == '0'))
- {
- startPos--;
- }
+ private const string _fmtPath = "@formatCode";
+ private string _format = string.Empty;
- 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('/');
-
- int fixedDenominator;
- if (!int.TryParse(fmt[1], out fixedDenominator))
- {
- fixedDenominator = 0;
- }
-
- if (d == 0 || double.IsNaN(d))
- {
- if (fmt[0].Trim() == "" && fmt[1].Trim() == "")
- {
- return new string(' ', FractionFormat.Length);
- }
- else
- {
- 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((double)10, (double)i));
- }
-
- double divRes = 1 / ((double)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 string(' ', FractionFormat.Length));
- }
- else if (intPart == 0)
- {
- return sign + FmtInt(numerator, fmt[0]) + "/" + FmtInt(denomerator, fmt[1]);
- }
- else
- {
- 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;
- }
- }
- #endregion
+ 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 FractionFormatInteger { get; private set; }
+ internal string FractionFormat { get; private set; }
+
+ //internal string FractionFormat2 { 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;
+ int fractionPos = -1;
+ 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) {
+ fractionPos = sb.Length;
+ 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('/');
+
+ int fixedDenominator;
+ if (!int.TryParse(fmt[1], out 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
index bee3e40..3b6f823 100644
--- a/EPPlus/Style/XmlAccess/ExcelXfsXml.cs
+++ b/EPPlus/Style/XmlAccess/ExcelXfsXml.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,848 +13,736 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Xml;
using System.Drawing;
-namespace OfficeOpenXml.Style.XmlAccess
-{
- /// <summary>
- /// Xml access class xfs records. This is the top level style object.
- /// </summary>
- public sealed class ExcelXfs : StyleXmlHelper
- {
- 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);
- }
+using System.Globalization;
+using System.Xml;
- private ExcelReadingOrder GetReadingOrder(string value)
- {
- switch(value)
- {
- case "1":
- return ExcelReadingOrder.LeftToRight;
- case "2":
- return ExcelReadingOrder.RightToLeft;
- default:
- return ExcelReadingOrder.ContextDependent;
- }
- }
+namespace OfficeOpenXml.Style.XmlAccess;
- private ExcelHorizontalAlignment GetHorizontalAlign(string align)
- {
- if (align == "") return ExcelHorizontalAlignment.General;
- align = align.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture) + align.Substring(1, align.Length - 1);
- try
- {
- return (ExcelHorizontalAlignment)Enum.Parse(typeof(ExcelHorizontalAlignment), align);
- }
- catch
- {
- return ExcelHorizontalAlignment.General;
- }
- }
+/// <summary>
+/// Xml access class xfs records. This is the top level style object.
+/// </summary>
+public sealed class ExcelXfs : StyleXmlHelper {
+ private ExcelStyles _styles;
- private ExcelVerticalAlignment GetVerticalAlign(string align)
- {
- if (align == "") return ExcelVerticalAlignment.Bottom;
- align = align.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture) + align.Substring(1, align.Length - 1);
- try
- {
- return (ExcelVerticalAlignment)Enum.Parse(typeof(ExcelVerticalAlignment), align);
- }
- catch
- {
- return ExcelVerticalAlignment.Bottom;
- }
- }
- internal void Xf_ChangedEvent(object sender, EventArgs e)
- {
- //if (_cell != null)
- //{
- // if (!Styles.ChangedCells.ContainsKey(_cell.Id))
- // {
- // //_cell.Style = "";
- // _cell.SetNewStyleID(int.MinValue.ToString());
- // Styles.ChangedCells.Add(_cell.Id, _cell);
- // }
- //}
- }
- int _xfID;
- /// <summary>
- /// Style index
- /// </summary>
- public int XfId
- {
- get
- {
- return _xfID;
- }
- set
- {
- _xfID = value;
- }
- }
- #region Internal Properties
- int _numFmtId;
- internal int NumberFormatId
- {
- get
- {
- return _numFmtId;
- }
- set
- {
- _numFmtId = value;
- ApplyNumberFormat = (value>0);
- }
- }
- int _fontId;
- internal int FontId
- {
- get
- {
- return _fontId;
- }
- set
- {
- _fontId = value;
- }
- }
- int _fillId;
- internal int FillId
- {
- get
- {
- return _fillId;
- }
- set
- {
- _fillId = value;
- }
- }
- int _borderId;
- internal int BorderId
- {
- get
- {
- return _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;
- }
- #endregion
- #region Public Properties
- public ExcelStyles Styles { get; private set; }
- /// <summary>
- /// Numberformat properties
- /// </summary>
- public ExcelNumberFormatXml Numberformat
- {
- get
- {
- return _styles.NumberFormats[_numFmtId < 0 ? 0 : _numFmtId];
- }
- }
- /// <summary>
- /// Font properties
- /// </summary>
- public ExcelFontXml Font
- {
- get
- {
- return _styles.Fonts[_fontId < 0 ? 0 : _fontId];
- }
- }
- /// <summary>
- /// Fill properties
- /// </summary>
- public ExcelFillXml Fill
- {
- get
- {
- return _styles.Fills[_fillId < 0 ? 0 : _fillId];
- }
- }
- /// <summary>
- /// Border style properties
- /// </summary>
- public ExcelBorderXml Border
- {
- get
- {
- return _styles.Borders[_borderId < 0 ? 0 : _borderId];
- }
- }
- const string horizontalAlignPath = "d:alignment/@horizontal";
- ExcelHorizontalAlignment _horizontalAlignment = ExcelHorizontalAlignment.General;
- /// <summary>
- /// Horizontal alignment
- /// </summary>
- public ExcelHorizontalAlignment HorizontalAlignment
- {
- get
- {
- return _horizontalAlignment;
- }
- set
- {
- _horizontalAlignment = value;
- }
- }
- const string verticalAlignPath = "d:alignment/@vertical";
- ExcelVerticalAlignment _verticalAlignment=ExcelVerticalAlignment.Bottom;
- /// <summary>
- /// Vertical alignment
- /// </summary>
- public ExcelVerticalAlignment VerticalAlignment
- {
- get
- {
- return _verticalAlignment;
- }
- set
- {
- _verticalAlignment = value;
- }
- }
- const string wrapTextPath = "d:alignment/@wrapText";
- bool _wrapText=false;
- /// <summary>
- /// Wraped text
- /// </summary>
- public bool WrapText
- {
- get
- {
- return _wrapText;
- }
- set
- {
- _wrapText = value;
- }
- }
- string textRotationPath = "d:alignment/@textRotation";
- int _textRotation = 0;
- /// <summary>
- /// Text rotation angle
- /// </summary>
- public int TextRotation
- {
- get
- {
- return (_textRotation == int.MinValue ? 0 : _textRotation);
- }
- set
- {
- _textRotation = value;
- }
- }
- const string lockedPath = "d:protection/@locked";
- bool _locked = true;
- /// <summary>
- /// Locked when sheet is protected
- /// </summary>
- public bool Locked
- {
- get
- {
- return _locked;
- }
- set
- {
- _locked = value;
- }
- }
- const string hiddenPath = "d:protection/@hidden";
- bool _hidden = false;
- /// <summary>
- /// Hide formulas when sheet is protected
- /// </summary>
- public bool Hidden
- {
- get
- {
- return _hidden;
- }
- set
- {
- _hidden = value;
- }
- }
- const string readingOrderPath = "d:alignment/@readingOrder";
- ExcelReadingOrder _readingOrder = ExcelReadingOrder.ContextDependent;
- /// <summary>
- /// Readingorder
- /// </summary>
- public ExcelReadingOrder ReadingOrder
- {
- get
- {
- return _readingOrder;
- }
- set
- {
- _readingOrder = value;
- }
- }
- const string shrinkToFitPath = "d:alignment/@shrinkToFit";
- bool _shrinkToFit = false;
- /// <summary>
- /// Shrink to fit
- /// </summary>
- public bool ShrinkToFit
- {
- get
- {
- return _shrinkToFit;
- }
- set
- {
- _shrinkToFit = value;
- }
- }
- const string indentPath = "d:alignment/@indent";
- int _indent = 0;
- /// <summary>
- /// Indentation
- /// </summary>
- public int Indent
- {
- get
- {
- return (_indent == int.MinValue ? 0 : _indent);
- }
- set
- {
- _indent=value;
- }
- }
- #endregion
- internal void RegisterEvent(ExcelXfs xf)
- {
- // RegisterEvent(xf, xf.Xf_ChangedEvent);
- }
- internal override string Id
- {
+ internal ExcelXfs(XmlNamespaceManager nameSpaceManager, ExcelStyles styles)
+ : base(nameSpaceManager) {
+ _styles = styles;
+ isBuildIn = false;
+ }
- get
- {
- return XfId + "|" + NumberFormatId.ToString() + "|" + FontId.ToString() + "|" + FillId.ToString() + "|" + BorderId.ToString() + VerticalAlignment.ToString() + "|" + HorizontalAlignment.ToString() + "|" + WrapText.ToString() + "|" + ReadingOrder.ToString() + "|" + isBuildIn.ToString() + TextRotation.ToString() + Locked.ToString() + Hidden.ToString() + ShrinkToFit.ToString() + Indent.ToString();
- //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 = this.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 Exception("Invalid property for class style."));
-
- }
- break;
- default:
- 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 Exception("Invalid property for class Border."));
- }
- break;
- default:
- throw (new Exception("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 Exception("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 ExcelFillXml(NameSpaceManager);
- }
- fill.PatternType = (ExcelFillStyle)value;
- break;
- case eStyleProperty.Color:
- case eStyleProperty.Tint:
- case eStyleProperty.IndexedColor:
- case eStyleProperty.AutoColor:
- if (fill is ExcelGradientFillXml)
- {
- fill = new ExcelFillXml(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 ExcelGradientFillXml(Fill.NameSpaceManager);
- fill.GradientColor1.SetColor(Color.White);
- fill.GradientColor2.SetColor(Color.FromArgb(79,129,189));
- 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 ExcelNumberFormatXml(NameSpaceManager) { Format = value.ToString(), NumFmtId = _styles.NumberFormats.NextId++ };
- _styles.NumberFormats.Add(value.ToString(), item);
- }
- return item.NumFmtId;
- }
- else
- {
- throw (new Exception("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 Exception("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) this.SetXmlNodeString(horizontalAlignPath, SetAlignString(_horizontalAlignment));
- if (doSetXfId)
- {
- SetXmlNodeString("@xfId", _styles.CellStyleXfs[_xfID].newID.ToString());
- }
- if (_verticalAlignment != ExcelVerticalAlignment.Bottom) this.SetXmlNodeString(verticalAlignPath, SetAlignString(_verticalAlignment));
- if(_wrapText) this.SetXmlNodeString(wrapTextPath, "1");
- if(_readingOrder!=ExcelReadingOrder.ContextDependent) this.SetXmlNodeString(readingOrderPath, ((int)_readingOrder).ToString());
- if (_shrinkToFit) this.SetXmlNodeString(shrinkToFitPath, "1");
- if (_indent > 0) SetXmlNodeString(indentPath, _indent.ToString());
- if (_textRotation > 0) this.SetXmlNodeString(textRotationPath, _textRotation.ToString());
- if (!_locked) this.SetXmlNodeString(lockedPath, "0");
- if (_hidden) this.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);
- }
+ internal ExcelXfs(XmlNamespaceManager nsm, XmlNode topNode, ExcelStyles styles)
+ : base(nsm, topNode) {
+ _styles = styles;
+ _xfID = GetXmlNodeInt("@xfId");
+ if (_xfID == 0) {
+ isBuildIn = true; //Normal taggen
}
-}
\ No newline at end of file
+ _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) {
+ if (align == "") {
+ return ExcelHorizontalAlignment.General;
+ }
+ align =
+ align.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture)
+ + align.Substring(1, align.Length - 1);
+ try {
+ return (ExcelHorizontalAlignment)Enum.Parse(typeof(ExcelHorizontalAlignment), align);
+ } catch {
+ return ExcelHorizontalAlignment.General;
+ }
+ }
+
+ private ExcelVerticalAlignment GetVerticalAlign(string align) {
+ if (align == "") {
+ return ExcelVerticalAlignment.Bottom;
+ }
+ align =
+ align.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture)
+ + align.Substring(1, align.Length - 1);
+ try {
+ return (ExcelVerticalAlignment)Enum.Parse(typeof(ExcelVerticalAlignment), align);
+ } catch {
+ return ExcelVerticalAlignment.Bottom;
+ }
+ }
+
+ internal void Xf_ChangedEvent(object sender, EventArgs e) {
+ //if (_cell != null)
+ //{
+ // if (!Styles.ChangedCells.ContainsKey(_cell.Id))
+ // {
+ // //_cell.Style = "";
+ // _cell.SetNewStyleID(int.MinValue.ToString());
+ // Styles.ChangedCells.Add(_cell.Id, _cell);
+ // }
+ //}
+ }
+
+ 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 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.SetColor(Color.White);
+ fill.GradientColor2.SetColor(Color.FromArgb(79, 129, 189));
+ 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
index 97eaefc..f735ef3 100644
--- a/EPPlus/Style/XmlAccess/StyleXmlHelper.cs
+++ b/EPPlus/Style/XmlAccess/StyleXmlHelper.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,66 +13,54 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
+
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";
- }
- else
- {
- if (node != null && ((node.Attributes["val"] != null && node.Attributes["val"].Value != "0") || node.Attributes["val"] == null))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- }
+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
index 1d58a01..0b9144a 100644
--- a/EPPlus/Table/ExcelTable.cs
+++ b/EPPlus/Table/ExcelTable.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,627 +13,524 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Security;
using System.Text;
-using System.Xml;
using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
+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,
+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> {
+ internal ExcelTable(ZipPackageRelationship rel, ExcelWorksheet sheet)
+ : base(sheet.NameSpaceManager) {
+ WorkSheet = sheet;
+ TableUri = UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri);
+ RelationshipID = rel.Id;
+ var pck = sheet._package.Package;
+ Part = pck.GetPart(TableUri);
+
+ TableXml = new();
+ LoadXmlSafe(TableXml, Part.GetStream());
+ Init();
+ Address = new(GetXmlNodeString("@ref"));
+ }
+
+ internal ExcelTable(ExcelWorksheet sheet, ExcelAddressBase address, string name, int tblId)
+ : base(sheet.NameSpaceManager) {
+ WorkSheet = sheet;
+ Address = address;
+ TableXml = new();
+ LoadXmlSafe(TableXml, GetStartXml(name, tblId), Encoding.UTF8);
+ TopNode = TableXml.DocumentElement;
+
+ Init();
+
+ //If the table is just one row we can not have a header.
+ if (address._fromRow == address._toRow) {
+ ShowHeader = false;
}
- /// <summary>
- /// An Excel Table
- /// </summary>
- public class ExcelTable : XmlHelper, IEqualityComparer<ExcelTable>
- {
- internal ExcelTable(Packaging.ZipPackageRelationship rel, ExcelWorksheet sheet) :
- base(sheet.NameSpaceManager)
- {
- WorkSheet = sheet;
- TableUri = UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri);
- RelationshipID = rel.Id;
- var pck = sheet._package.Package;
- Part=pck.GetPart(TableUri);
+ }
- TableXml = new XmlDocument();
- LoadXmlSafe(TableXml, Part.GetStream());
- init();
- Address = new ExcelAddressBase(GetXmlNodeString("@ref"));
- }
- internal ExcelTable(ExcelWorksheet sheet, ExcelAddressBase address, string name, int tblId) :
- base(sheet.NameSpaceManager)
- {
- WorkSheet = sheet;
- Address = address;
- TableXml = new XmlDocument();
- LoadXmlSafe(TableXml, GetStartXml(name, tblId), Encoding.UTF8);
- TopNode = TableXml.DocumentElement;
+ private void Init() {
+ TopNode = TableXml.DocumentElement;
+ SchemaNodeOrder = new[] { "autoFilter", "tableColumns", "tableStyleInfo" };
+ }
- init();
+ private string GetStartXml(string name, int tblId) {
+ string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>";
+ xml += string.Format(
+ "<table xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" id=\"{0}\" name=\"{1}\" displayName=\"{2}\" ref=\"{3}\" headerRowCount=\"1\">",
+ tblId,
+ name,
+ CleanDisplayName(name),
+ Address.Address);
+ xml += string.Format("<autoFilter ref=\"{0}\" />", Address.Address);
- //If the table is just one row we can not have a header.
- if (address._fromRow == address._toRow)
- {
- ShowHeader = false;
- }
- }
-
- private void init()
- {
- TopNode = TableXml.DocumentElement;
- SchemaNodeOrder = new string[] { "autoFilter", "tableColumns", "tableStyleInfo" };
- }
- private string GetStartXml(string name, int tblId)
- {
- string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>";
- xml += string.Format("<table xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" id=\"{0}\" name=\"{1}\" displayName=\"{2}\" ref=\"{3}\" headerRowCount=\"1\">",
- tblId,
- name,
- cleanDisplayName(name),
- Address.Address);
- xml += string.Format("<autoFilter ref=\"{0}\" />", Address.Address);
-
- int cols=Address._toCol-Address._fromCol+1;
- xml += string.Format("<tableColumns count=\"{0}\">",cols);
- var names = new Dictionary<string, string>();
- for(int i=1;i<=cols;i++)
- {
- var cell = WorkSheet.Cells[Address._fromRow, Address._fromCol+i-1];
- string colName;
- if (cell.Value == null || names.ContainsKey(cell.Value.ToString()))
- {
- //Get an unique name
- int a=i;
- do
- {
- colName = string.Format("Column{0}", a++);
- }
- while (names.ContainsKey(colName));
- }
- else
- {
- colName = System.Security.SecurityElement.Escape(cell.Value.ToString());
- }
- names.Add(colName, colName);
- xml += string.Format("<tableColumn id=\"{0}\" name=\"{1}\" />", i,colName);
- }
- xml += "</tableColumns>";
- xml += "<tableStyleInfo name=\"TableStyleMedium9\" showFirstColumn=\"0\" showLastColumn=\"0\" showRowStripes=\"1\" showColumnStripes=\"0\" /> ";
- xml += "</table>";
-
- return xml;
- }
- private string cleanDisplayName(string name)
- {
- return Regex.Replace(name, @"[^\w\.-_]", "_");
- }
- internal Packaging.ZipPackagePart Part
- {
- get;
- set;
- }
- /// <summary>
- /// Provides access to the XML data representing the table in the package.
- /// </summary>
- public XmlDocument TableXml
- {
- get;
- set;
- }
- /// <summary>
- /// The package internal URI to the Table Xml Document.
- /// </summary>
- public Uri TableUri
- {
- get;
- internal set;
- }
- internal string RelationshipID
- {
- get;
- set;
- }
- const string ID_PATH = "@id";
- internal int Id
- {
- get
- {
- return GetXmlNodeInt(ID_PATH);
- }
- set
- {
- SetXmlNodeString(ID_PATH, value.ToString());
- }
- }
- const string NAME_PATH = "@name";
- const string DISPLAY_NAME_PATH = "@displayName";
- /// <summary>
- /// The name of the table object in Excel
- /// </summary>
- public string Name
- {
- get
- {
- return GetXmlNodeString(NAME_PATH);
- }
- set
- {
- if(WorkSheet.Workbook.ExistsTableName(value))
- {
- throw (new ArgumentException("Tablename 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(NAME_PATH, value);
- SetXmlNodeString(DISPLAY_NAME_PATH, cleanDisplayName(value));
- }
- }
- /// <summary>
- /// The worksheet of the table
- /// </summary>
- public ExcelWorksheet WorkSheet
- {
- get;
- set;
- }
-
- private ExcelAddressBase _address = null;
- /// <summary>
- /// The address of the table
- /// </summary>
- public ExcelAddressBase Address
- {
- get
- {
- return _address;
- }
- set
- {
- _address = value;
- SetXmlNodeString("@ref",value.Address);
- WriteAutoFilter(ShowTotal);
- }
- }
- internal ExcelTableColumnCollection _cols = null;
- /// <summary>
- /// Collection of the columns in the table
- /// </summary>
- public ExcelTableColumnCollection Columns
- {
- get
- {
- if(_cols==null)
- {
- _cols = new ExcelTableColumnCollection(this);
- }
- return _cols;
- }
- }
- 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
- {
- return _tableStyle;
- }
- set
- {
- _tableStyle=value;
- if (value != TableStyles.Custom)
- {
- SetXmlNodeString(STYLENAME_PATH, "TableStyle" + value.ToString());
- }
- }
- }
- const string HEADERROWCOUNT_PATH = "@headerRowCount";
- const string AUTOFILTER_PATH = "d:autoFilter/@ref";
- /// <summary>
- /// If the header row is visible or not
- /// </summary>
- public bool ShowHeader
- {
- get
- {
- return GetXmlNodeInt(HEADERROWCOUNT_PATH)!=0;
- }
- set
- {
- if (Address._toRow - Address._fromRow < 0 && value ||
- Address._toRow - Address._fromRow == 1 && value && ShowTotal)
- {
- throw (new Exception("Cant set ShowHeader-property. Table has too few rows"));
- }
-
- if(value)
- {
- DeleteNode(HEADERROWCOUNT_PATH);
- 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(HEADERROWCOUNT_PATH, "0");
- DeleteAllNode(AUTOFILTER_PATH);
- }
- }
- }
- internal ExcelAddressBase AutoFilterAddress
- {
- get
- {
- string a=GetXmlNodeString(AUTOFILTER_PATH);
- if (a == "")
- {
- return null;
- }
- else
- {
- return new ExcelAddressBase(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(AUTOFILTER_PATH, autofilterAddress);
- }
- }
- /// <summary>
- /// If the header row has an autofilter
- /// </summary>
- public bool ShowFilter
- {
- get
- {
- return ShowHeader && AutoFilterAddress != null;
- }
- set
- {
- if (ShowHeader)
- {
- if (value)
- {
- WriteAutoFilter(ShowTotal);
- }
- else
- {
- DeleteAllNode(AUTOFILTER_PATH);
- }
- }
- else if(value)
- {
- throw(new InvalidOperationException("Filter can only be applied when ShowHeader is set to true"));
- }
- }
- }
- const string TOTALSROWCOUNT_PATH = "@totalsRowCount";
- const string TOTALSROWSHOWN_PATH = "@totalsRowShown";
- /// <summary>
- /// If the total row is visible or not
- /// </summary>
- public bool ShowTotal
- {
- get
- {
- return GetXmlNodeInt(TOTALSROWCOUNT_PATH) == 1;
- }
- set
- {
- if (value != ShowTotal)
- {
- if (value)
- {
- Address=new ExcelAddress(WorkSheet.Name, ExcelAddressBase.GetAddress(Address.Start.Row, Address.Start.Column, Address.End.Row+1, Address.End.Column));
- }
- else
- {
- Address = new ExcelAddress(WorkSheet.Name, ExcelAddressBase.GetAddress(Address.Start.Row, Address.Start.Column, Address.End.Row - 1, Address.End.Column));
- }
- SetXmlNodeString("@ref", Address.Address);
- if (value)
- {
- SetXmlNodeString(TOTALSROWCOUNT_PATH, "1");
- }
- else
- {
- DeleteNode(TOTALSROWCOUNT_PATH);
- }
- WriteAutoFilter(value);
- }
- }
- }
- const string STYLENAME_PATH = "d:tableStyleInfo/@name";
- /// <summary>
- /// The style name for custum styles
- /// </summary>
- public string StyleName
- {
- get
- {
- return GetXmlNodeString(STYLENAME_PATH);
- }
- set
- {
- if (value.StartsWith("TableStyle"))
- {
- 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(STYLENAME_PATH,value,true);
- }
- }
- const string SHOWFIRSTCOLUMN_PATH = "d:tableStyleInfo/@showFirstColumn";
- /// <summary>
- /// Display special formatting for the first row
- /// </summary>
- public bool ShowFirstColumn
- {
- get
- {
- return GetXmlNodeBool(SHOWFIRSTCOLUMN_PATH);
- }
- set
- {
- SetXmlNodeBool(SHOWFIRSTCOLUMN_PATH, value, false);
- }
- }
- const string SHOWLASTCOLUMN_PATH = "d:tableStyleInfo/@showLastColumn";
- /// <summary>
- /// Display special formatting for the last row
- /// </summary>
- public bool ShowLastColumn
- {
- get
- {
- return GetXmlNodeBool(SHOWLASTCOLUMN_PATH);
- }
- set
- {
- SetXmlNodeBool(SHOWLASTCOLUMN_PATH, value, false);
- }
- }
- const string SHOWROWSTRIPES_PATH = "d:tableStyleInfo/@showRowStripes";
- /// <summary>
- /// Display banded rows
- /// </summary>
- public bool ShowRowStripes
- {
- get
- {
- return GetXmlNodeBool(SHOWROWSTRIPES_PATH);
- }
- set
- {
- SetXmlNodeBool(SHOWROWSTRIPES_PATH, value, false);
- }
- }
- const string SHOWCOLUMNSTRIPES_PATH = "d:tableStyleInfo/@showColumnStripes";
- /// <summary>
- /// Display banded columns
- /// </summary>
- public bool ShowColumnStripes
- {
- get
- {
- return GetXmlNodeBool(SHOWCOLUMNSTRIPES_PATH);
- }
- set
- {
- SetXmlNodeBool(SHOWCOLUMNSTRIPES_PATH, value, false);
- }
- }
-
- const string TOTALSROWCELLSTYLE_PATH = "@totalsRowCellStyle";
- /// <summary>
- /// Named style used for the total row
- /// </summary>
- public string TotalsRowCellStyle
- {
- get
- {
- return GetXmlNodeString(TOTALSROWCELLSTYLE_PATH);
- }
- set
- {
- if (WorkSheet.Workbook.Styles.NamedStyles.FindIndexByID(value) < 0)
- {
- throw (new Exception(string.Format("Named style {0} does not exist.", value)));
- }
- SetXmlNodeString(TopNode, TOTALSROWCELLSTYLE_PATH, value, true);
-
- if (ShowTotal)
- {
- WorkSheet.Cells[Address._toRow, Address._fromCol, Address._toRow, Address._toCol].StyleName = value;
- }
- }
- }
- const string DATACELLSTYLE_PATH = "@dataCellStyle";
- /// <summary>
- /// Named style used for the data cells
- /// </summary>
- public string DataCellStyleName
- {
- get
- {
- return GetXmlNodeString(DATACELLSTYLE_PATH);
- }
- set
- {
- if (WorkSheet.Workbook.Styles.NamedStyles.FindIndexByID(value) < 0)
- {
- throw (new Exception(string.Format("Named style {0} does not exist.", value)));
- }
- SetXmlNodeString(TopNode, DATACELLSTYLE_PATH, value, true);
-
- int fromRow = Address._fromRow + (ShowHeader ? 1 : 0),
- toRow = Address._toRow - (ShowTotal ? 1 : 0);
-
- if (fromRow < toRow)
- {
- WorkSheet.Cells[fromRow, Address._fromCol, toRow, Address._toCol].StyleName = value;
- }
- }
- }
- const string HEADERROWCELLSTYLE_PATH = "@headerRowCellStyle";
- /// <summary>
- /// Named style used for the header row
- /// </summary>
- public string HeaderRowCellStyle
- {
- get
- {
- return GetXmlNodeString(HEADERROWCELLSTYLE_PATH);
- }
- set
- {
- if (WorkSheet.Workbook.Styles.NamedStyles.FindIndexByID(value) < 0)
- {
- throw (new Exception(string.Format("Named style {0} does not exist.", value)));
- }
- SetXmlNodeString(TopNode, HEADERROWCELLSTYLE_PATH, value, true);
-
- if (ShowHeader)
- {
- WorkSheet.Cells[Address._fromRow, Address._fromCol, Address._fromRow, Address._toCol].StyleName = value;
- }
-
- }
- }
-
- 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();
- }
+ int cols = Address._toCol - Address._fromCol + 1;
+ xml += string.Format("<tableColumns count=\"{0}\">", cols);
+ var names = new Dictionary<string, string>();
+ for (int i = 1; i <= cols; i++) {
+ var cell = WorkSheet.Cells[Address._fromRow, Address._fromCol + i - 1];
+ string colName;
+ if (cell.Value == null || names.ContainsKey(cell.Value.ToString())) {
+ //Get an unique name
+ int a = i;
+ do {
+ colName = string.Format("Column{0}", a++);
+ } while (names.ContainsKey(colName));
+ } else {
+ colName = SecurityElement.Escape(cell.Value.ToString());
+ }
+ names.Add(colName, colName);
+ xml += string.Format("<tableColumn id=\"{0}\" name=\"{1}\" />", i, colName);
}
+ xml += "</tableColumns>";
+ xml +=
+ "<tableStyleInfo name=\"TableStyleMedium9\" showFirstColumn=\"0\" showLastColumn=\"0\" showRowStripes=\"1\" showColumnStripes=\"0\" /> ";
+ xml += "</table>";
+
+ return xml;
+ }
+
+ private string CleanDisplayName(string name) {
+ return Regex.Replace(name, @"[^\w\.-_]", "_");
+ }
+
+ internal ZipPackagePart Part { get; set; }
+
+ /// <summary>
+ /// Provides access to the XML data representing the table in the package.
+ /// </summary>
+ public XmlDocument TableXml { get; set; }
+
+ /// <summary>
+ /// The package internal URI to the Table Xml Document.
+ /// </summary>
+ public Uri TableUri { get; internal set; }
+
+ internal string RelationshipID { get; set; }
+
+ private const string _idPath = "@id";
+
+ internal int Id {
+ get => GetXmlNodeInt(_idPath);
+ set => SetXmlNodeString(_idPath, value.ToString());
+ }
+
+ private const string _namePath = "@name";
+ private const string _displayNamePath = "@displayName";
+
+ /// <summary>
+ /// The name of the table object in Excel
+ /// </summary>
+ public string Name {
+ get => GetXmlNodeString(_namePath);
+ set {
+ if (WorkSheet.Workbook.ExistsTableName(value)) {
+ throw (new ArgumentException("Tablename 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>
+ /// The worksheet of the table
+ /// </summary>
+ public ExcelWorksheet WorkSheet { get; set; }
+
+ 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 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, "TableStyle" + value);
+ }
+ }
+ }
+
+ 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 {
+ get => ShowHeader && AutoFilterAddress != null;
+ set {
+ if (ShowHeader) {
+ if (value) {
+ WriteAutoFilter(ShowTotal);
+ } else {
+ DeleteAllNode(_autofilterPath);
+ }
+ } else if (value) {
+ throw (new InvalidOperationException(
+ "Filter can only be applied when ShowHeader is set to true"));
+ }
+ }
+ }
+
+ private const string _totalsrowcountPath = "@totalsRowCount";
+ private const string _totalsrowshownPath = "@totalsRowShown";
+
+ /// <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 {
+ get => GetXmlNodeString(_stylenamePath);
+ set {
+ if (value.StartsWith("TableStyle")) {
+ 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 const string _showfirstcolumnPath = "d:tableStyleInfo/@showFirstColumn";
+
+ /// <summary>
+ /// Display special formatting for the first row
+ /// </summary>
+ public bool ShowFirstColumn {
+ get => GetXmlNodeBool(_showfirstcolumnPath);
+ set => SetXmlNodeBool(_showfirstcolumnPath, value, false);
+ }
+
+ private const string _showlastcolumnPath = "d:tableStyleInfo/@showLastColumn";
+
+ /// <summary>
+ /// Display special formatting for the last row
+ /// </summary>
+ public bool ShowLastColumn {
+ get => GetXmlNodeBool(_showlastcolumnPath);
+ set => SetXmlNodeBool(_showlastcolumnPath, value, false);
+ }
+
+ private const string _showrowstripesPath = "d:tableStyleInfo/@showRowStripes";
+
+ /// <summary>
+ /// Display banded rows
+ /// </summary>
+ public bool ShowRowStripes {
+ get => GetXmlNodeBool(_showrowstripesPath);
+ set => SetXmlNodeBool(_showrowstripesPath, value, false);
+ }
+
+ private const string _showcolumnstripesPath = "d:tableStyleInfo/@showColumnStripes";
+
+ /// <summary>
+ /// Display banded columns
+ /// </summary>
+ public bool ShowColumnStripes {
+ get => GetXmlNodeBool(_showcolumnstripesPath);
+ set => SetXmlNodeBool(_showcolumnstripesPath, value, false);
+ }
+
+ private const string _totalsrowcellstylePath = "@totalsRowCellStyle";
+
+ /// <summary>
+ /// Named style used for the total row
+ /// </summary>
+ public string TotalsRowCellStyle {
+ get => GetXmlNodeString(_totalsrowcellstylePath);
+ set {
+ if (WorkSheet.Workbook.Styles.NamedStyles.FindIndexById(value) < 0) {
+ throw (new(string.Format("Named style {0} does not exist.", value)));
+ }
+ SetXmlNodeString(TopNode, _totalsrowcellstylePath, value, true);
+
+ if (ShowTotal) {
+ WorkSheet.Cells[Address._toRow,
+ Address._fromCol,
+ Address._toRow,
+ Address._toCol].StyleName = value;
+ }
+ }
+ }
+
+ private const string _datacellstylePath = "@dataCellStyle";
+
+ /// <summary>
+ /// Named style used for the data cells
+ /// </summary>
+ public string DataCellStyleName {
+ get => GetXmlNodeString(_datacellstylePath);
+ set {
+ if (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 = Address._fromRow + (ShowHeader ? 1 : 0),
+ toRow = Address._toRow - (ShowTotal ? 1 : 0);
+
+ if (fromRow < toRow) {
+ WorkSheet.Cells[fromRow, Address._fromCol, toRow, Address._toCol].StyleName = value;
+ }
+ }
+ }
+
+ private const string _headerrowcellstylePath = "@headerRowCellStyle";
+
+ /// <summary>
+ /// Named style used for the header row
+ /// </summary>
+ public string HeaderRowCellStyle {
+ get => GetXmlNodeString(_headerrowcellstylePath);
+ set {
+ if (WorkSheet.Workbook.Styles.NamedStyles.FindIndexById(value) < 0) {
+ throw (new(string.Format("Named style {0} does not exist.", value)));
+ }
+ SetXmlNodeString(TopNode, _headerrowcellstylePath, value, true);
+
+ if (ShowHeader) {
+ WorkSheet.Cells[Address._fromRow,
+ Address._fromCol,
+ Address._fromRow,
+ Address._toCol].StyleName = value;
+ }
+ }
+ }
+
+ 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
index b0df086..08576e4 100644
--- a/EPPlus/Table/ExcelTableCollection.cs
+++ b/EPPlus/Table/ExcelTableCollection.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,236 +13,201 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Linq;
-using System.Text;
using System.Xml;
-namespace OfficeOpenXml.Table
-{
- /// <summary>
- /// A collection of table objects
- /// </summary>
- public class ExcelTableCollection : IEnumerable<ExcelTable>
- {
- List<ExcelTable> _tables = new List<ExcelTable>();
- internal Dictionary<string, int> _tableNames = new Dictionary<string, int>(StringComparer.InvariantCultureIgnoreCase);
- 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);
- }
- }
- private ExcelTable Add(ExcelTable tbl)
- {
- _tables.Add(tbl);
- _tableNames.Add(tbl.Name, _tables.Count - 1);
- if (tbl.Id >= _ws.Workbook._nextTableID)
- {
- _ws.Workbook._nextTableID = tbl.Id + 1;
- }
- return tbl;
- }
+namespace OfficeOpenXml.Table;
- /// <summary>
- /// Create a table on the supplied range
- /// </summary>
- /// <param name="Range">The range address including header and total row</param>
- /// <param name="Name">The name of the table. Must be unique </param>
- /// <returns>The table object</returns>
- public ExcelTable Add(ExcelAddressBase Range, string Name)
- {
- if (Range.WorkSheet != null && Range.WorkSheet != _ws.Name)
- {
- throw new ArgumentException("Range does not belong to worksheet", "Range");
- }
-
- if (string.IsNullOrEmpty(Name))
- {
- Name = GetNewTableName();
- }
- else if (_ws.Workbook.ExistsTableName(Name))
- {
- throw (new ArgumentException("Tablename is not unique"));
- }
+/// <summary>
+/// A collection of table objects
+/// </summary>
+public class ExcelTableCollection : IEnumerable<ExcelTable> {
+ private List<ExcelTable> _tables = new();
+ internal Dictionary<string, int> _tableNames = new(StringComparer.InvariantCultureIgnoreCase);
+ private ExcelWorksheet _ws;
- ValidateTableName(Name);
-
- foreach (var t in _tables)
- {
- if (t.Address.Collide(Range) != ExcelAddressBase.eAddressCollition.No)
- {
- throw (new ArgumentException(string.Format("Table range collides with table {0}", t.Name)));
- }
- }
- return Add(new ExcelTable(_ws, Range, Name, _ws.Workbook._nextTableID));
- }
-
- private void ValidateTableName(string Name)
- {
- if (string.IsNullOrEmpty(Name))
- {
- throw new ArgumentException("Tablename is null or empty");
- }
-
- char firstLetterOfName = Name[0];
- if (Char.IsLetter(firstLetterOfName) == false && firstLetterOfName != '_' && firstLetterOfName != '\\')
- {
- throw new ArgumentException("Tablename start with invalid character");
- }
-
- if (Name.Contains(" "))
- {
- throw new ArgumentException("Tablename has spaces");
- }
-
- }
-
- public void Delete(int Index, bool ClearRange = false)
- {
- Delete(this[Index], ClearRange);
- }
-
- public void Delete(string Name, bool ClearRange = false)
- {
- if (this[Name] == null)
- {
- throw new ArgumentOutOfRangeException(string.Format("Cannot delete non-existant table {0} in sheet {1}.", Name, _ws.Name));
- }
- Delete(this[Name], ClearRange);
- }
-
-
- public void Delete(ExcelTable Table, bool ClearRange = false)
- {
- if (!this._tables.Contains(Table))
- {
- throw new ArgumentOutOfRangeException("Table", String.Format("Table {0} does not exist in this collection", Table.Name));
- }
- lock (this)
- {
- var range = _ws.Cells[Table.Address.Address];
- _tableNames.Remove(Table.Name);
- _tables.Remove(Table);
- foreach (var sheet in Table.WorkSheet.Workbook.Worksheets)
- {
- foreach (var table in sheet.Tables)
- {
- if (table.Id > Table.Id) table.Id--;
- }
- Table.WorkSheet.Workbook._nextTableID--;
- }
- if (ClearRange)
- {
- range.Clear();
- }
- }
-
- }
-
- 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
- {
- get
- {
- return _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]];
- }
- else
- {
- return null;
- }
- }
- }
- public IEnumerator<ExcelTable> GetEnumerator()
- {
- return _tables.GetEnumerator();
- }
-
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return _tables.GetEnumerator();
- }
+ 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);
}
+ }
+
+ private ExcelTable Add(ExcelTable tbl) {
+ _tables.Add(tbl);
+ _tableNames.Add(tbl.Name, _tables.Count - 1);
+ if (tbl.Id >= _ws.Workbook._nextTableID) {
+ _ws.Workbook._nextTableID = tbl.Id + 1;
+ }
+ return tbl;
+ }
+
+ /// <summary>
+ /// Create a table on the supplied range
+ /// </summary>
+ /// <param name="range">The range address including header and total row</param>
+ /// <param name="name">The name of the table. Must be unique </param>
+ /// <returns>The table object</returns>
+ public ExcelTable Add(ExcelAddressBase range, string name) {
+ if (range.WorkSheet != null && range.WorkSheet != _ws.Name) {
+ throw new ArgumentException("Range does not belong to worksheet", "range");
+ }
+
+ if (string.IsNullOrEmpty(name)) {
+ name = GetNewTableName();
+ } else if (_ws.Workbook.ExistsTableName(name)) {
+ throw (new ArgumentException("Tablename is not unique"));
+ }
+
+ ValidateTableName(name);
+
+ foreach (var t in _tables) {
+ if (t.Address.Collide(range) != ExcelAddressBase.eAddressCollition.No) {
+ throw (new ArgumentException(string.Format("Table range collides with table {0}", t.Name)));
+ }
+ }
+ return Add(new(_ws, range, name, _ws.Workbook._nextTableID));
+ }
+
+ private void ValidateTableName(string name) {
+ if (string.IsNullOrEmpty(name)) {
+ throw new ArgumentException("Tablename is null or empty");
+ }
+
+ char firstLetterOfName = name[0];
+ if (Char.IsLetter(firstLetterOfName) == false
+ && firstLetterOfName != '_'
+ && firstLetterOfName != '\\') {
+ throw new ArgumentException("Tablename start with invalid character");
+ }
+
+ if (name.Contains(" ")) {
+ throw new ArgumentException("Tablename has spaces");
+ }
+ }
+
+ public void Delete(int index, bool clearRange = false) {
+ Delete(this[index], clearRange);
+ }
+
+ public void Delete(string name, bool clearRange = false) {
+ if (this[name] == null) {
+ throw new ArgumentOutOfRangeException(
+ string.Format("Cannot delete non-existant table {0} in sheet {1}.", name, _ws.Name));
+ }
+ Delete(this[name], clearRange);
+ }
+
+ public void Delete(ExcelTable excelTable, bool clearRange = false) {
+ if (!_tables.Contains(excelTable)) {
+ throw new ArgumentOutOfRangeException(
+ "excelTable",
+ String.Format("Table {0} does not exist in this collection", excelTable.Name));
+ }
+ lock (this) {
+ var range = _ws.Cells[excelTable.Address.Address];
+ _tableNames.Remove(excelTable.Name);
+ _tables.Remove(excelTable);
+ foreach (var sheet in excelTable.WorkSheet.Workbook.Worksheets) {
+ foreach (var table in sheet.Tables) {
+ if (table.Id > excelTable.Id) {
+ table.Id--;
+ }
+ }
+ excelTable.WorkSheet.Workbook._nextTableID--;
+ }
+ if (clearRange) {
+ range.Clear();
+ }
+ }
+ }
+
+ 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
index 0c45529..6680424 100644
--- a/EPPlus/Table/ExcelTableColumn.cs
+++ b/EPPlus/Table/ExcelTableColumn.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,228 +13,191 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Globalization;
-using System.Text;
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
+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;
}
-
- /// <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
- {
- return 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 + this.Position));
- }
- else
- {
- n = "Column" + (this.Position+1).ToString();
- }
- }
- return n;
- }
- set
- {
- var v = ConvertUtil.ExcelEncodeString(value);
- SetXmlNodeString("@name", v);
- if (_tbl.ShowHeader)
- {
- _tbl.WorkSheet.SetValue(_tbl.Address._fromRow, _tbl.Address._fromCol + this.Position, value);
- }
- _tbl.WorkSheet.SetTableTotalFunction(_tbl, this);
- }
- }
- /// <summary>
- /// A string text in the total row
- /// </summary>
- public string TotalsRowLabel
- {
- get
- {
- return 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;
- }
- else
- {
- return (RowFunctions)Enum.Parse(typeof(RowFunctions), GetXmlNodeString("@totalsRowFunction"), true);
- }
- }
- set
- {
- if (value == RowFunctions.Custom)
- {
- throw(new Exception("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);
- }
- }
- const string TOTALSROWFORMULA_PATH = "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
- {
- return GetXmlNodeString(TOTALSROWFORMULA_PATH);
- }
- set
- {
- if (value.StartsWith("=")) value = value.Substring(1, value.Length - 1);
- SetXmlNodeString("@totalsRowFunction", "custom");
- SetXmlNodeString(TOTALSROWFORMULA_PATH, value);
- _tbl.WorkSheet.SetTableTotalFunction(_tbl, this);
- }
- }
- const string DATACELLSTYLE_PATH = "@dataCellStyle";
- /// <summary>
- /// The named style for datacells in the column
- /// </summary>
- public string DataCellStyleName
- {
- get
- {
- return GetXmlNodeString(DATACELLSTYLE_PATH);
- }
- set
- {
- if(_tbl.WorkSheet.Workbook.Styles.NamedStyles.FindIndexByID(value)<0)
- {
- throw(new Exception(string.Format("Named style {0} does not exist.",value)));
- }
- SetXmlNodeString(TopNode, DATACELLSTYLE_PATH, 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;
- }
- }
- }
- const string CALCULATEDCOLUMNFORMULA_PATH = "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
- {
- return GetXmlNodeString(CALCULATEDCOLUMNFORMULA_PATH);
- }
- set
- {
- if (value.StartsWith("=")) value = value.Substring(1, value.Length - 1);
- SetXmlNodeString(CALCULATEDCOLUMNFORMULA_PATH, value);
- }
- }
-
+ 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
index 3a4d23f..864e026 100644
--- a/EPPlus/Table/ExcelTableColumnCollection.cs
+++ b/EPPlus/Table/ExcelTableColumnCollection.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,123 +13,103 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
using System.Xml;
-namespace OfficeOpenXml.Table
-{
- /// <summary>
- /// A collection of table columns
- /// </summary>
- public class ExcelTableColumnCollection : IEnumerable<ExcelTableColumn>
- {
- List<ExcelTableColumn> _cols = new List<ExcelTableColumn>();
- Dictionary<string, int> _colNames = new Dictionary<string, int>(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 ExcelTableColumn(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
- {
- get
- {
- return _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] as ExcelTableColumn;
- }
- }
- /// <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]];
- }
- else
- {
- return null;
- }
- }
- }
+namespace OfficeOpenXml.Table;
- IEnumerator<ExcelTableColumn> IEnumerable<ExcelTableColumn>.GetEnumerator()
- {
- return _cols.GetEnumerator();
- }
+/// <summary>
+/// A collection of table columns
+/// </summary>
+public class ExcelTableColumnCollection : IEnumerable<ExcelTableColumn> {
+ private List<ExcelTableColumn> _cols = new();
+ private Dictionary<string, int> _colNames = new(StringComparer.InvariantCultureIgnoreCase);
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return _cols.GetEnumerator();
- }
- internal string GetUniqueName(string name)
- {
- if (_colNames.ContainsKey(name))
- {
- var newName = name;
- var i = 2;
- do
- {
- newName = name+(i++).ToString(CultureInfo.InvariantCulture);
- }
- while (_colNames.ContainsKey(newName));
- return newName;
- }
- return name;
- }
+ 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)) {
+ var newName = name;
+ 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
index eb812ea..d25001f 100644
--- a/EPPlus/Table/PivotTable/ExcelPivotCacheDefinition.cs
+++ b/EPPlus/Table/PivotTable/ExcelPivotCacheDefinition.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,282 +13,259 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this product may cause.
*
* Code change notes:
- *
+ *
* Author Change Date
* ******************************************************************************
* Jan Källman Added 21-MAR-2011
* Jan Källman License changed GPL-->LGPL 2011-12-16
*******************************************************************************/
+
using System;
-using System.Collections.Generic;
-using System.Data.SqlClient;
+using System.Linq;
using System.Text;
using System.Xml;
-using System.Linq;
+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
+
+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;
}
- /// <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);
+ CacheDefinitionUri = UriHelper.ResolvePartUri(Relationship.SourceUri, Relationship.TargetUri);
- var pck = pivotTable.WorkSheet._package.Package;
- Part = pck.GetPart(CacheDefinitionUri);
- CacheDefinitionXml = new XmlDocument();
- LoadXmlSafe(CacheDefinitionXml, Part.GetStream());
+ var pck = pivotTable.WorkSheet._package.Package;
+ Part = pck.GetPart(CacheDefinitionUri);
+ CacheDefinitionXml = new();
+ 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)];
- }
- }
- }
- internal ExcelPivotCacheDefinition(XmlNamespaceManager ns, ExcelPivotTable pivotTable, ExcelRangeBase sourceAddress, int tblId) :
- base(ns, null)
- {
- PivotTable = pivotTable;
+ 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)];
+ }
+ }
+ }
- var pck = pivotTable.WorkSheet._package.Package;
-
- //CacheDefinition
- CacheDefinitionXml = new XmlDocument();
- LoadXmlSafe(CacheDefinitionXml, GetStartXml(sourceAddress), Encoding.UTF8);
- CacheDefinitionUri = GetNewUri(pck, "/xl/pivotCache/pivotCacheDefinition{0}.xml", tblId);
- Part = pck.CreatePart(CacheDefinitionUri, ExcelPackage.schemaPivotCacheDefinition);
- TopNode = CacheDefinitionXml.DocumentElement;
+ internal ExcelPivotCacheDefinition(
+ XmlNamespaceManager ns,
+ ExcelPivotTable pivotTable,
+ ExcelRangeBase sourceAddress,
+ int tblId)
+ : base(ns, null) {
+ PivotTable = pivotTable;
- //CacheRecord. Create an empty one.
- CacheRecordUri = GetNewUri(pck, "/xl/pivotCache/pivotCacheRecords{0}.xml", tblId);
- var cacheRecord = new XmlDocument();
- cacheRecord.LoadXml("<pivotCacheRecords xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" count=\"0\" />");
- var recPart = pck.CreatePart(CacheRecordUri, ExcelPackage.schemaPivotCacheRecords);
- cacheRecord.Save(recPart.GetStream());
+ var pck = pivotTable.WorkSheet._package.Package;
- RecordRelationship = Part.CreateRelationship(UriHelper.ResolvePartUri(CacheDefinitionUri, CacheRecordUri), Packaging.TargetMode.Internal, ExcelPackage.schemaRelationships + "/pivotCacheRecords");
- RecordRelationshipID = RecordRelationship.Id;
+ //CacheDefinition
+ CacheDefinitionXml = new();
+ LoadXmlSafe(CacheDefinitionXml, GetStartXml(sourceAddress), Encoding.UTF8);
+ CacheDefinitionUri = GetNewUri(pck, "/xl/pivotCache/pivotCacheDefinition{0}.xml", tblId);
+ Part = pck.CreatePart(CacheDefinitionUri, ExcelPackage._schemaPivotCacheDefinition);
+ TopNode = CacheDefinitionXml.DocumentElement;
- CacheDefinitionXml.Save(Part.GetStream());
- }
- /// <summary>
- /// Reference to the internal package part
- /// </summary>
- internal Packaging.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; }
- /// <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 Packaging.ZipPackageRelationship Relationship
- {
- get;
- set;
- }
- internal Packaging.ZipPackageRelationship RecordRelationship
- {
- get;
- set;
- }
- internal string RecordRelationshipID
- {
- get
- {
- return GetXmlNodeString("@r:id");
- }
- set
- {
- SetXmlNodeString("@r:id", value);
- }
- }
- /// <summary>
- /// Referece to the PivoTable object
- /// </summary>
- public ExcelPivotTable PivotTable
- {
- get;
- private set;
- }
-
- const string _sourceWorksheetPath="d:cacheSource/d:worksheetSource/@sheet";
- const string _sourceNamePath = "d:cacheSource/d:worksheetSource/@name";
- const string _sourceAddressPath = "d:cacheSource/d:worksheetSource/@ref";
- internal ExcelRangeBase _sourceRange = null;
- /// <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"));
- }
- }
+ //CacheRecord. Create an empty one.
+ CacheRecordUri = GetNewUri(pck, "/xl/pivotCache/pivotCacheRecords{0}.xml", tblId);
+ var cacheRecord = new XmlDocument();
+ cacheRecord.LoadXml(
+ "<pivotCacheRecords xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" count=\"0\" />");
+ var recPart = pck.CreatePart(CacheRecordUri, ExcelPackage._schemaPivotCacheRecords);
+ cacheRecord.Save(recPart.GetStream());
+
+ RecordRelationship = Part.CreateRelationship(
+ UriHelper.ResolvePartUri(CacheDefinitionUri, CacheRecordUri),
+ TargetMode.Internal,
+ ExcelPackage._schemaRelationships + "/pivotCacheRecords");
+ RecordRelationshipID = RecordRelationship.Id;
+
+ CacheDefinitionXml.Save(Part.GetStream());
+ }
+
+ /// <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; }
+
+ /// <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;
+ }
}
- set
- {
- if (PivotTable.WorkSheet.Workbook != value.Worksheet.Workbook)
- {
- throw (new ArgumentException("Range must be in the same package as the pivottable"));
+ 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;
}
-
- 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;
+ }
}
+ } else {
+ _sourceRange = ws.Cells[GetXmlNodeString(_sourceAddressPath)];
+ }
+ } else {
+ throw (new ArgumentException("The cachesource is not a worksheet"));
}
- /// <summary>
- /// Type of source data
- /// </summary>
- public eSourceType CacheSource
- {
- get
- {
- var s=GetXmlNodeString("d:cacheSource/@type");
- if (s == "")
- {
- return eSourceType.Worksheet;
- }
- else
- {
- 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;
- }
+ }
+ 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
index ec0990d..75c6360 100644
--- a/EPPlus/Table/PivotTable/ExcelPivotTable.cs
+++ b/EPPlus/Table/PivotTable/ExcelPivotTable.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,937 +13,701 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this product may cause.
*
* Code change notes:
- *
+ *
* Author Change Date
* ******************************************************************************
* Jan Källman Added 21-MAR-2011
* Jan Källman License changed GPL-->LGPL 2011-12-16
*******************************************************************************/
+
using System;
-using System.Collections.Generic;
using System.Text;
-using System.Xml;
using System.Text.RegularExpressions;
-using OfficeOpenXml.Table;
+using System.Xml;
+using OfficeOpenXml.Packaging;
using OfficeOpenXml.Utils;
-namespace OfficeOpenXml.Table.PivotTable
-{
- /// <summary>
- /// An Excel Pivottable
- /// </summary>
- public class ExcelPivotTable : XmlHelper
- {
- internal ExcelPivotTable(Packaging.ZipPackageRelationship rel, ExcelWorksheet sheet) :
- base(sheet.NameSpaceManager)
- {
- WorkSheet = sheet;
- PivotTableUri = UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri);
- Relationship = rel;
- var pck = sheet._package.Package;
- Part=pck.GetPart(PivotTableUri);
+namespace OfficeOpenXml.Table.PivotTable;
- PivotTableXml = new XmlDocument();
- LoadXmlSafe(PivotTableXml, Part.GetStream());
- init();
- TopNode = PivotTableXml.DocumentElement;
- Address = new ExcelAddressBase(GetXmlNodeString("d:location/@ref"));
+/// <summary>
+/// An Excel Pivottable
+/// </summary>
+public class ExcelPivotTable : XmlHelper {
+ internal ExcelPivotTable(ZipPackageRelationship rel, ExcelWorksheet sheet)
+ : base(sheet.NameSpaceManager) {
+ WorkSheet = sheet;
+ PivotTableUri = UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri);
+ Relationship = rel;
+ var pck = sheet._package.Package;
+ Part = pck.GetPart(PivotTableUri);
- _cacheDefinition = new ExcelPivotCacheDefinition(sheet.NameSpaceManager, this);
- LoadFields();
+ PivotTableXml = new();
+ LoadXmlSafe(PivotTableXml, Part.GetStream());
+ Init();
+ TopNode = PivotTableXml.DocumentElement;
+ Address = new(GetXmlNodeString("d:location/@ref"));
- //Add row fields.
- foreach (XmlElement rowElem in TopNode.SelectNodes("d:rowFields/d:field", NameSpaceManager))
- {
- int x;
- if (int.TryParse(rowElem.GetAttribute("x"), out x) && x >= 0)
- {
- RowFields.AddInternal(Fields[x]);
- }
- else
- {
- rowElem.ParentNode.RemoveChild(rowElem);
- }
- }
+ _cacheDefinition = new(sheet.NameSpaceManager, this);
+ LoadFields();
- ////Add column fields.
- foreach (XmlElement colElem in TopNode.SelectNodes("d:colFields/d:field", NameSpaceManager))
- {
- int x;
- if(int.TryParse(colElem.GetAttribute("x"),out 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))
- {
- int fld;
- if (int.TryParse(pageElem.GetAttribute("fld"), out fld) && fld >= 0)
- {
- var field = Fields[fld];
- field._pageFieldSettings = new ExcelPivotTablePageFieldSettings(NameSpaceManager, pageElem, field, fld);
- PageFields.AddInternal(field);
- }
- }
-
- //Add data elements
- //index = 0;
- foreach (XmlElement dataElem in TopNode.SelectNodes("d:dataFields/d:dataField", NameSpaceManager))
- {
- int fld;
- if (int.TryParse(dataElem.GetAttribute("fld"), out fld) && fld >= 0)
- {
- var field = Fields[fld];
- var dataField = new ExcelPivotTableDataField(NameSpaceManager, dataElem, field);
- DataFields.AddInternal(dataField);
- }
- }
- }
- /// <summary>
- /// Add a new pivottable
- /// </summary>
- /// <param name="sheet">The worksheet</param>
- /// <param name="address">the address of the pivottable</param>
- /// <param name="sourceAddress">The address of the Source data</param>
- /// <param name="name"></param>
- /// <param name="tblId"></param>
- internal ExcelPivotTable(ExcelWorksheet sheet, ExcelAddressBase address,ExcelRangeBase sourceAddress, string name, int tblId) :
- base(sheet.NameSpaceManager)
- {
- WorkSheet = sheet;
- Address = address;
- var pck = sheet._package.Package;
-
- PivotTableXml = new XmlDocument();
- LoadXmlSafe(PivotTableXml, GetStartXml(name, tblId, address, sourceAddress), Encoding.UTF8);
- TopNode = PivotTableXml.DocumentElement;
- PivotTableUri = GetNewUri(pck, "/xl/pivotTables/pivotTable{0}.xml", tblId);
- init();
-
- Part = pck.CreatePart(PivotTableUri, ExcelPackage.schemaPivotTable);
- PivotTableXml.Save(Part.GetStream());
-
- //Worksheet-Pivottable relationship
- Relationship = sheet.Part.CreateRelationship(UriHelper.ResolvePartUri(sheet.WorksheetUri, PivotTableUri), Packaging.TargetMode.Internal, ExcelPackage.schemaRelationships + "/pivotTable");
-
- _cacheDefinition = new ExcelPivotCacheDefinition(sheet.NameSpaceManager, this, sourceAddress, tblId);
- _cacheDefinition.Relationship=Part.CreateRelationship(UriHelper.ResolvePartUri(PivotTableUri, _cacheDefinition.CacheDefinitionUri), Packaging.TargetMode.Internal, ExcelPackage.schemaRelationships + "/pivotCacheDefinition");
-
- sheet.Workbook.AddPivotTable(CacheID.ToString(), _cacheDefinition.CacheDefinitionUri);
-
- LoadFields();
-
- using (var r=sheet.Cells[address.Address])
- {
- r.Clear();
- }
- }
- private void init()
- {
- SchemaNodeOrder = new string[] { "location", "pivotFields", "rowFields", "rowItems", "colFields", "colItems", "pageFields", "pageItems", "dataFields", "dataItems", "formats", "pivotTableStyleInfo" };
- }
- 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 string GetStartXml(string name, int id, ExcelAddressBase address, ExcelAddressBase sourceAddress)
- {
- string xml = string.Format("<pivotTableDefinition xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" name=\"{0}\" cacheId=\"{1}\" 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\">", name, id);
-
- xml += string.Format("<location ref=\"{0}\" firstHeaderRow=\"1\" firstDataRow=\"1\" firstDataCol=\"1\" /> ", address.FirstAddress);
- xml += string.Format("<pivotFields count=\"{0}\">", sourceAddress._toCol-sourceAddress._fromCol+1);
- for (int col = sourceAddress._fromCol; col <= sourceAddress._toCol; col++)
- {
- xml += "<pivotField showAll=\"0\" />"; //compact=\"0\" outline=\"0\" subtotalTop=\"0\" includeNewItemsInFilter=\"1\"
- }
-
- xml += "</pivotFields>";
- xml += "<pivotTableStyleInfo name=\"PivotStyleMedium9\" showRowHeaders=\"1\" showColHeaders=\"1\" showRowStripes=\"0\" showColStripes=\"0\" showLastColumn=\"1\" />";
- xml += "</pivotTableDefinition>";
- return xml;
- }
- internal Packaging.ZipPackagePart Part
- {
- get;
- set;
- }
- /// <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 Packaging.ZipPackageRelationship Relationship
- {
- get;
- set;
- }
- //const string ID_PATH = "@id";
- //internal int Id
- //{
- // get
- // {
- // return GetXmlNodeInt(ID_PATH);
- // }
- // set
- // {
- // SetXmlNodeString(ID_PATH, value.ToString());
- // }
- //}
- const string NAME_PATH = "@name";
- const string DISPLAY_NAME_PATH = "@displayName";
- /// <summary>
- /// Name of the pivottable object in Excel
- /// </summary>
- public string Name
- {
- get
- {
- return GetXmlNodeString(NAME_PATH);
- }
- 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(NAME_PATH, value);
- SetXmlNodeString(DISPLAY_NAME_PATH, cleanDisplayName(value));
- }
- }
- ExcelPivotCacheDefinition _cacheDefinition = null;
- /// <summary>
- /// Reference to the pivot table cache definition object
- /// </summary>
- public ExcelPivotCacheDefinition CacheDefinition
- {
- get
- {
- if (_cacheDefinition == null)
- {
- _cacheDefinition = new ExcelPivotCacheDefinition(NameSpaceManager, this, null, 1);
- }
- return _cacheDefinition;
- }
- }
- private string cleanDisplayName(string name)
- {
- return Regex.Replace(name, @"[^\w\.-_]", "_");
- }
- #region "Public Properties"
-
- /// <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
- {
- return GetXmlNodeBool("@dataOnRows");
- }
- set
- {
- SetXmlNodeBool("@dataOnRows",value);
- }
- }
- /// <summary>
- /// if true apply legacy table autoformat number format properties.
- /// </summary>
- public bool ApplyNumberFormats
- {
- get
- {
- return GetXmlNodeBool("@applyNumberFormats");
- }
- set
- {
- SetXmlNodeBool("@applyNumberFormats",value);
- }
- }
- /// <summary>
- /// If true apply legacy table autoformat border properties
- /// </summary>
- public bool ApplyBorderFormats
- {
- get
- {
- return GetXmlNodeBool("@applyBorderFormats");
- }
- set
- {
- SetXmlNodeBool("@applyBorderFormats",value);
- }
- }
- /// <summary>
- /// If true apply legacy table autoformat font properties
- /// </summary>
- public bool ApplyFontFormats
- {
- get
- {
- return GetXmlNodeBool("@applyFontFormats");
- }
- set
- {
- SetXmlNodeBool("@applyFontFormats",value);
- }
- }
- /// <summary>
- /// If true apply legacy table autoformat pattern properties
- /// </summary>
- public bool ApplyPatternFormats
- {
- get
- {
- return GetXmlNodeBool("@applyPatternFormats");
- }
- set
- {
- SetXmlNodeBool("@applyPatternFormats",value);
- }
- }
- /// <summary>
- /// If true apply legacy table autoformat width/height properties.
- /// </summary>
- public bool ApplyWidthHeightFormats
- {
- get
- {
- return GetXmlNodeBool("@applyWidthHeightFormats");
- }
- set
- {
- SetXmlNodeBool("@applyWidthHeightFormats",value);
- }
- }
- /// <summary>
- /// Show member property information
- /// </summary>
- public bool ShowMemberPropertyTips
- {
- get
- {
- return GetXmlNodeBool("@showMemberPropertyTips");
- }
- set
- {
- SetXmlNodeBool("@showMemberPropertyTips",value);
- }
- }
- /// <summary>
- /// Show the drill indicators
- /// </summary>
- public bool ShowCalcMember
- {
- get
- {
- return 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
- {
- return GetXmlNodeBool("@enableDrill", true);
- }
- set
- {
- SetXmlNodeBool("@enableDrill", value);
- }
- }
- /// <summary>
- /// Show the drill down buttons
- /// </summary>
- public bool ShowDrill
- {
- get
- {
- return GetXmlNodeBool("@showDrill", true);
- }
- set
- {
- SetXmlNodeBool("@showDrill", value);
- }
- }
- /// <summary>
- /// If the tooltips should be displayed for PivotTable data cells.
- /// </summary>
- public bool ShowDataTips
- {
- get
- {
- return 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
- {
- return GetXmlNodeBool("@fieldPrintTitles");
- }
- set
- {
- SetXmlNodeBool("@fieldPrintTitles", value);
- }
- }
- /// <summary>
- /// If the row and column titles from the PivotTable should be printed.
- /// </summary>
- public bool ItemPrintTitles
- {
- get
- {
- return GetXmlNodeBool("@itemPrintTitles");
- }
- set
- {
- SetXmlNodeBool("@itemPrintTitles", value);
- }
- }
- /// <summary>
- /// If the grand totals should be displayed for the PivotTable columns
- /// </summary>
- public bool ColumGrandTotals
- {
- get
- {
- return GetXmlNodeBool("@colGrandTotals");
- }
- set
- {
- SetXmlNodeBool("@colGrandTotals", value);
- }
- }
- /// <summary>
- /// If the grand totals should be displayed for the PivotTable rows
- /// </summary>
- public bool RowGrandTotals
- {
- get
- {
- return GetXmlNodeBool("@rowGrandTotals");
- }
- set
- {
- SetXmlNodeBool("@rowGrandTotals", value);
- }
- }
- /// <summary>
- /// If the drill indicators expand collapse buttons should be printed.
- /// </summary>
- public bool PrintDrill
- {
- get
- {
- return GetXmlNodeBool("@printDrill");
- }
- set
- {
- SetXmlNodeBool("@printDrill", value);
- }
- }
- /// <summary>
- /// Indicates whether to show error messages in cells.
- /// </summary>
- public bool ShowError
- {
- get
- {
- return GetXmlNodeBool("@showError");
- }
- set
- {
- SetXmlNodeBool("@showError", value);
- }
- }
- /// <summary>
- /// The string to be displayed in cells that contain errors.
- /// </summary>
- public string ErrorCaption
- {
- get
- {
- return 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
- {
- return GetXmlNodeString("@dataCaption");
- }
- set
- {
- SetXmlNodeString("@dataCaption", value);
- }
- }
- /// <summary>
- /// Show field headers
- /// </summary>
- public bool ShowHeaders
- {
- get
- {
- return 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
- {
- return GetXmlNodeInt("@pageWrap");
- }
- set
- {
- if(value<0)
- {
- throw new Exception("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
- {
- return 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
- {
- return 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
- {
- return 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
- {
- return 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
- {
- return 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
- {
- return 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
- {
- return 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
- {
- return GetXmlNodeBool("@compactData");
- }
- set
- {
- SetXmlNodeBool("@compactData",value);
- }
- }
- /// <summary>
- /// Specifies the string to be displayed for grand totals.
- /// </summary>
- public string GrandTotalCaption
- {
- get
- {
- return GetXmlNodeString("@grandTotalCaption");
- }
- set
- {
- SetXmlNodeString("@grandTotalCaption", value);
- }
- }
- /// <summary>
- /// Specifies the string to be displayed in row header in compact mode.
- /// </summary>
- public string RowHeaderCaption
- {
- get
- {
- return GetXmlNodeString("@rowHeaderCaption");
- }
- set
- {
- SetXmlNodeString("@rowHeaderCaption", value);
- }
- }
- /// <summary>
- /// Specifies the string to be displayed in cells with no value
- /// </summary>
- public string MissingCaption
- {
- get
- {
- return GetXmlNodeString("@missingCaption");
- }
- set
- {
- SetXmlNodeString("@missingCaption", value);
- }
- }
- const string FIRSTHEADERROW_PATH="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
- {
- return GetXmlNodeInt(FIRSTHEADERROW_PATH);
- }
- set
- {
- SetXmlNodeString(FIRSTHEADERROW_PATH, value.ToString());
- }
- }
- const string FIRSTDATAROW_PATH = "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
- {
- return GetXmlNodeInt(FIRSTDATAROW_PATH);
- }
- set
- {
- SetXmlNodeString(FIRSTDATAROW_PATH, value.ToString());
- }
- }
- const string FIRSTDATACOL_PATH = "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
- {
- return GetXmlNodeInt(FIRSTDATACOL_PATH);
- }
- set
- {
- SetXmlNodeString(FIRSTDATACOL_PATH, value.ToString());
- }
- }
- ExcelPivotTableFieldCollection _fields = null;
- /// <summary>
- /// The fields in the table
- /// </summary>
- public ExcelPivotTableFieldCollection Fields
- {
- get
- {
- if (_fields == null)
- {
- _fields = new ExcelPivotTableFieldCollection(this, "");
- }
- return _fields;
- }
- }
- ExcelPivotTableRowColumnFieldCollection _rowFields = null;
- /// <summary>
- /// Row label fields
- /// </summary>
- public ExcelPivotTableRowColumnFieldCollection RowFields
- {
- get
- {
- if (_rowFields == null)
- {
- _rowFields = new ExcelPivotTableRowColumnFieldCollection(this, "rowFields");
- }
- return _rowFields;
- }
- }
- ExcelPivotTableRowColumnFieldCollection _columnFields = null;
- /// <summary>
- /// Column label fields
- /// </summary>
- public ExcelPivotTableRowColumnFieldCollection ColumnFields
- {
- get
- {
- if (_columnFields == null)
- {
- _columnFields = new ExcelPivotTableRowColumnFieldCollection(this, "colFields");
- }
- return _columnFields;
- }
- }
- ExcelPivotTableDataFieldCollection _dataFields = null;
- /// <summary>
- /// Value fields
- /// </summary>
- public ExcelPivotTableDataFieldCollection DataFields
- {
- get
- {
- if (_dataFields == null)
- {
- _dataFields = new ExcelPivotTableDataFieldCollection(this);
- }
- return _dataFields;
- }
- }
- ExcelPivotTableRowColumnFieldCollection _pageFields = null;
- /// <summary>
- /// Report filter fields
- /// </summary>
- public ExcelPivotTableRowColumnFieldCollection PageFields
- {
- get
- {
- if (_pageFields == null)
- {
- _pageFields = new ExcelPivotTableRowColumnFieldCollection(this, "pageFields");
- }
- return _pageFields;
- }
- }
- const string STYLENAME_PATH = "d:pivotTableStyleInfo/@name";
- /// <summary>
- /// Pivot style name. Used for custom styles
- /// </summary>
- public string StyleName
- {
- get
- {
- return GetXmlNodeString(STYLENAME_PATH);
- }
- 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(STYLENAME_PATH, value, true);
- }
- }
- TableStyles _tableStyle = Table.TableStyles.Medium6;
- /// <summary>
- /// The table style. If this property is cusom the style from the StyleName propery is used.
- /// </summary>
- public TableStyles TableStyle
- {
- get
- {
- return _tableStyle;
- }
- set
- {
- _tableStyle=value;
- if (value != TableStyles.Custom)
- {
- SetXmlNodeString(STYLENAME_PATH, "PivotStyle" + value.ToString());
- }
- }
- }
-
- #endregion
- #region "Internal Properties"
- internal int CacheID
- {
- get
- {
- return GetXmlNodeInt("@cacheId");
- }
- set
- {
- SetXmlNodeString("@cacheId",value.ToString());
- }
- }
-
- #endregion
-
+ //Add row fields.
+ foreach (XmlElement rowElem in TopNode.SelectNodes("d:rowFields/d:field", NameSpaceManager)) {
+ int x;
+ if (int.TryParse(rowElem.GetAttribute("x"), out 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)) {
+ int x;
+ if (int.TryParse(colElem.GetAttribute("x"), out 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)) {
+ int fld;
+ if (int.TryParse(pageElem.GetAttribute("fld"), out 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)) {
+ int fld;
+ if (int.TryParse(dataElem.GetAttribute("fld"), out fld) && fld >= 0) {
+ var field = Fields[fld];
+ var dataField = new ExcelPivotTableDataField(NameSpaceManager, dataElem, field);
+ DataFields.AddInternal(dataField);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Add a new pivottable
+ /// </summary>
+ /// <param name="sheet">The worksheet</param>
+ /// <param name="address">the address of the pivottable</param>
+ /// <param name="sourceAddress">The address of the Source data</param>
+ /// <param name="name"></param>
+ /// <param name="tblId"></param>
+ internal ExcelPivotTable(
+ ExcelWorksheet sheet,
+ ExcelAddressBase address,
+ ExcelRangeBase sourceAddress,
+ string name,
+ int tblId)
+ : base(sheet.NameSpaceManager) {
+ WorkSheet = sheet;
+ Address = address;
+ var pck = sheet._package.Package;
+
+ PivotTableXml = new();
+ LoadXmlSafe(PivotTableXml, GetStartXml(name, tblId, address, sourceAddress), Encoding.UTF8);
+ TopNode = PivotTableXml.DocumentElement;
+ PivotTableUri = GetNewUri(pck, "/xl/pivotTables/pivotTable{0}.xml", tblId);
+ Init();
+
+ Part = pck.CreatePart(PivotTableUri, ExcelPackage._schemaPivotTable);
+ PivotTableXml.Save(Part.GetStream());
+
+ //Worksheet-Pivottable relationship
+ Relationship = sheet.Part.CreateRelationship(
+ UriHelper.ResolvePartUri(sheet.WorksheetUri, PivotTableUri),
+ TargetMode.Internal,
+ ExcelPackage._schemaRelationships + "/pivotTable");
+
+ _cacheDefinition = new(sheet.NameSpaceManager, this, sourceAddress, tblId);
+ _cacheDefinition.Relationship = Part.CreateRelationship(
+ UriHelper.ResolvePartUri(PivotTableUri, _cacheDefinition.CacheDefinitionUri),
+ TargetMode.Internal,
+ ExcelPackage._schemaRelationships + "/pivotCacheDefinition");
+
+ sheet.Workbook.AddPivotTable(CacheID.ToString(), _cacheDefinition.CacheDefinitionUri);
+
+ LoadFields();
+
+ using (var r = sheet.Cells[address.Address]) {
+ r.Clear();
+ }
+ }
+
+ private void Init() {
+ SchemaNodeOrder = new[] {
+ "location",
+ "pivotFields",
+ "rowFields",
+ "rowItems",
+ "colFields",
+ "colItems",
+ "pageFields",
+ "pageItems",
+ "dataFields",
+ "dataItems",
+ "formats",
+ "pivotTableStyleInfo",
+ };
+ }
+
+ 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 string GetStartXml(
+ string name,
+ int id,
+ ExcelAddressBase address,
+ ExcelAddressBase sourceAddress) {
+ string xml = string.Format(
+ "<pivotTableDefinition xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" name=\"{0}\" cacheId=\"{1}\" 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\">",
+ name,
+ id);
+
+ xml += string.Format(
+ "<location ref=\"{0}\" firstHeaderRow=\"1\" firstDataRow=\"1\" firstDataCol=\"1\" /> ",
+ address.FirstAddress);
+ xml += string.Format(
+ "<pivotFields count=\"{0}\">",
+ sourceAddress._toCol - sourceAddress._fromCol + 1);
+ for (int col = sourceAddress._fromCol; col <= sourceAddress._toCol; col++) {
+ xml += "<pivotField showAll=\"0\" />"; //compact=\"0\" outline=\"0\" subtotalTop=\"0\" includeNewItemsInFilter=\"1\"
+ }
+
+ xml += "</pivotFields>";
+ xml +=
+ "<pivotTableStyleInfo name=\"PivotStyleMedium9\" showRowHeaders=\"1\" showColHeaders=\"1\" showRowStripes=\"0\" showColStripes=\"0\" showLastColumn=\"1\" />";
+ xml += "</pivotTableDefinition>";
+ return xml;
+ }
+
+ internal ZipPackagePart Part { get; set; }
+
+ /// <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));
+ }
+ }
+
+ private ExcelPivotCacheDefinition _cacheDefinition;
+
+ /// <summary>
+ /// Reference to the pivot table cache definition object
+ /// </summary>
+ public ExcelPivotCacheDefinition CacheDefinition {
+ get {
+ if (_cacheDefinition == null) {
+ _cacheDefinition = new(NameSpaceManager, this, null, 1);
+ }
+ return _cacheDefinition;
+ }
+ }
+
+ 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
index 7bf4750..bde8c36 100644
--- a/EPPlus/Table/PivotTable/ExcelPivotTableCollection.cs
+++ b/EPPlus/Table/PivotTable/ExcelPivotTableCollection.cs
@@ -13,153 +13,127 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
-using System.Xml;
-namespace OfficeOpenXml.Table.PivotTable
-{
- /// <summary>
- /// A collection of pivottable objects
- /// </summary>
- public class ExcelPivotTableCollection : IEnumerable<ExcelPivotTable>
- {
- List<ExcelPivotTable> _pivotTables = new List<ExcelPivotTable>();
- internal Dictionary<string, int> _pivotTableNames = new Dictionary<string, int>();
- ExcelWorksheet _ws;
- internal ExcelPivotTableCollection(ExcelWorksheet ws)
- {
- var pck = ws._package.Package;
- _ws = 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);
- }
- }
- }
- private ExcelPivotTable Add(ExcelPivotTable tbl)
- {
- _pivotTables.Add(tbl);
- _pivotTableNames.Add(tbl.Name, _pivotTables.Count - 1);
- if (tbl.CacheID >= _ws.Workbook._nextPivotTableID)
- {
- _ws.Workbook._nextPivotTableID = tbl.CacheID + 1;
- }
- return tbl;
- }
+namespace OfficeOpenXml.Table.PivotTable;
- /// <summary>
- /// Create a pivottable on the supplied range
- /// </summary>
- /// <param name="Range">The range address including header and total row</param>
- /// <param name="Source">The Source data range address</param>
- /// <param name="Name">The name of the table. Must be unique </param>
- /// <returns>The pivottable object</returns>
- public ExcelPivotTable Add(ExcelAddressBase Range, ExcelRangeBase Source, string Name)
- {
- if (string.IsNullOrEmpty(Name))
- {
- Name = GetNewTableName();
- }
- if (Range.WorkSheet != _ws.Name)
- {
- throw(new Exception("The Range must be in the current worksheet"));
- }
- else if (_ws.Workbook.ExistsTableName(Name))
- {
- throw (new ArgumentException("Tablename is not unique"));
- }
- foreach (var t in _pivotTables)
- {
- if (t.Address.Collide(Range) != ExcelAddressBase.eAddressCollition.No)
- {
- throw (new ArgumentException(string.Format("Table range collides with table {0}", t.Name)));
- }
- }
- return Add(new ExcelPivotTable(_ws, Range, Source, Name, _ws.Workbook._nextPivotTableID++));
- }
+/// <summary>
+/// A collection of pivottable objects
+/// </summary>
+public class ExcelPivotTableCollection : IEnumerable<ExcelPivotTable> {
+ private List<ExcelPivotTable> _pivotTables = new();
+ internal Dictionary<string, int> _pivotTableNames = new();
+ private ExcelWorksheet _ws;
- internal string GetNewTableName()
- {
- string name = "Pivottable1";
- int i = 2;
- while (_ws.Workbook.ExistsPivotTableName(name))
- {
- name = string.Format("Pivottable{0}", i++);
- }
- return name;
- }
- public int Count
- {
- get
- {
- return _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]];
- }
- else
- {
- return null;
- }
- }
- }
- public IEnumerator<ExcelPivotTable> GetEnumerator()
- {
- return _pivotTables.GetEnumerator();
- }
-
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return _pivotTables.GetEnumerator();
- }
+ internal ExcelPivotTableCollection(ExcelWorksheet ws) {
+ var pck = ws._package.Package;
+ _ws = 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);
+ }
}
+ }
+
+ private ExcelPivotTable Add(ExcelPivotTable tbl) {
+ _pivotTables.Add(tbl);
+ _pivotTableNames.Add(tbl.Name, _pivotTables.Count - 1);
+ if (tbl.CacheID >= _ws.Workbook._nextPivotTableID) {
+ _ws.Workbook._nextPivotTableID = tbl.CacheID + 1;
+ }
+ return tbl;
+ }
+
+ /// <summary>
+ /// Create a pivottable on the supplied range
+ /// </summary>
+ /// <param name="range">The range address including header and total row</param>
+ /// <param name="source">The Source data range address</param>
+ /// <param name="name">The name of the table. Must be unique </param>
+ /// <returns>The pivottable object</returns>
+ public ExcelPivotTable Add(ExcelAddressBase range, ExcelRangeBase source, string name) {
+ if (string.IsNullOrEmpty(name)) {
+ name = GetNewTableName();
+ }
+ if (range.WorkSheet != _ws.Name) {
+ throw (new("The Range must be in the current worksheet"));
+ }
+ if (_ws.Workbook.ExistsTableName(name)) {
+ throw (new ArgumentException("Tablename is not unique"));
+ }
+ foreach (var t in _pivotTables) {
+ if (t.Address.Collide(range) != ExcelAddressBase.eAddressCollition.No) {
+ throw (new ArgumentException(string.Format("Table range collides with table {0}", t.Name)));
+ }
+ }
+ return Add(new(_ws, range, source, name, _ws.Workbook._nextPivotTableID++));
+ }
+
+ internal string GetNewTableName() {
+ string name = "Pivottable1";
+ int i = 2;
+ while (_ws.Workbook.ExistsPivotTableName(name)) {
+ name = string.Format("Pivottable{0}", i++);
+ }
+ return name;
+ }
+
+ 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
index 97a7dc4..bfe8c52 100644
--- a/EPPlus/Table/PivotTable/ExcelPivotTableDataField.cs
+++ b/EPPlus/Table/PivotTable/ExcelPivotTableDataField.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,221 +13,178 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this product may cause.
*
* Code change notes:
- *
+ *
* Author Change Date
* ******************************************************************************
* Jan Källman Added 21-MAR-2011
* Jan Källman License changed GPL-->LGPL 2011-12-16
*******************************************************************************/
+
using System;
-using System.Collections.Generic;
using System.Globalization;
-using System.Text;
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
- {
- return GetXmlNodeInt("@fld");
- }
- internal set
- {
- SetXmlNodeString("@fld",value.ToString());
- }
- }
- /// <summary>
- /// The name of the datafield
- /// </summary>
- public string Name
- {
- get
- {
- return 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
- {
- return 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
- {
- return GetXmlNodeInt("@baseItem");
- }
- set
- {
- SetXmlNodeString("@baseItem", value.ToString());
- }
- }
- /// <summary>
- /// Number format id.
- /// </summary>
- internal int NumFmtId
- {
- get
- {
- return 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;
+namespace OfficeOpenXml.Table.PivotTable;
- ExcelNumberFormatXml nf = null;
- if (!styles.NumberFormats.FindByID(value, ref nf))
- {
- nf = new ExcelNumberFormatXml(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;
- }
- else
- {
- 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);
- // }
- //}
+/// <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
index 2e897ab..654ab71 100644
--- a/EPPlus/Table/PivotTable/ExcelPivotTableField.cs
+++ b/EPPlus/Table/PivotTable/ExcelPivotTableField.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,1064 +13,1000 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this product may cause.
*
* Code change notes:
- *
+ *
* Author Change Date
* ******************************************************************************
* Jan Källman Added 21-MAR-2011
* Jan Källman License changed GPL-->LGPL 2011-12-16
*******************************************************************************/
+
using System;
using System.Collections.Generic;
-using System.Text;
-using System.Xml;
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
+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;
}
- /// <summary>
- /// Build-in table row functions
- /// </summary>
- public enum DataFieldFunctions
- {
- Average,
- Count,
- CountNums,
- Max,
- Min,
- Product,
- None,
- StdDev,
- StdDevP,
- Sum,
- Var,
- VarP
+ 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);
}
- /// <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,
+ set {
+ if (value == eSortType.None) {
+ DeleteNode("@sortType");
+ } else {
+ SetXmlNodeString("@sortType", value.ToString().ToLower(CultureInfo.InvariantCulture));
+ }
}
- /// <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>
+ /// 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;
}
- /// <summary>
- /// Sorting
- /// </summary>
- public enum eSortType
- {
- None,
- Ascending,
- Descending
+ 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>
- /// 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");
- }
- else
- {
- return v;
- }
- }
- set
- {
- SetXmlNodeString("@name", value);
- }
- }
- /// <summary>
- /// Compact mode
- /// </summary>
- public bool Compact
- {
- get
- {
- return 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
- {
- return GetXmlNodeBool("@outline");
- }
- set
- {
- SetXmlNodeBool("@outline",value);
- }
- }
- /// <summary>
- /// The custom text that is displayed for the subtotals label
- /// </summary>
- public bool SubtotalTop
- {
- get
- {
- return GetXmlNodeBool("@subtotalTop");
- }
- set
- {
- SetXmlNodeBool("@subtotalTop",value);
- }
- }
- /// <summary>
- /// A boolean that indicates whether to show all items for this field
- /// </summary>
- public bool ShowAll
- {
- get
- {
- return 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
- {
- return 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."));
- }
+ }
+ /// <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;
+ }
+ }
+ }
- // 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
- {
- return (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 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");
}
- /// <summary>
- /// If the field is a column field
- /// </summary>
- public bool IsColumnField
- {
- get
- {
- return (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);
+ rowsNode = TopNode.SelectSingleNode("../../d:rowFields", 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);
- }
- }
- }
+ AppendField(rowsNode, Index, "field", "x");
+ if (BaseIndex == Index) {
+ TopNode.InnerXml = "<items count=\"1\"><item t=\"default\" /></items>";
+ } else {
+ TopNode.InnerXml = "<items count=\"0\"></items>";
}
- /// <summary>
- /// If the field is a datafield
- /// </summary>
- public bool IsDataField
- {
- get
- {
- return GetXmlNodeBool("@dataField", false);
- }
+ } 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 page field.
- /// </summary>
- public bool IsPageField
- {
- get
- {
- return (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 ExcelPivotTablePageFieldSettings(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);
- }
- }
- }
+ /// <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");
}
- //public ExcelPivotGrouping DateGrouping
+ 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);
+ int fieldIndex;
+ if (int.TryParse(x, out 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 ExcelPivotTableFieldDateGroup SetDateGroup(
+ eDateGroupBy groupBy,
+ DateTime startDate,
+ DateTime endDate,
+ int interval) {
+ ExcelPivotTableFieldDateGroup group;
+ group = new(NameSpaceManager, _cacheFieldHelper.TopNode);
+ _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsDate", true);
+ _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsNonDate", false);
+ _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsSemiMixedTypes", false);
+
+ group.TopNode.InnerXml += string.Format(
+ "<fieldGroup base=\"{0}\"><rangePr groupBy=\"{1}\" /><groupItems /></fieldGroup>",
+ BaseIndex,
+ groupBy.ToString().ToLower(CultureInfo.InvariantCulture));
+
+ if (startDate.Year < 1900) {
+ _cacheFieldHelper.SetXmlNodeString(
+ "d:fieldGroup/d:rangePr/@startDate",
+ "1900-01-01T00:00:00");
+ } else {
+ _cacheFieldHelper.SetXmlNodeString(
+ "d:fieldGroup/d:rangePr/@startDate",
+ startDate.ToString("s", CultureInfo.InvariantCulture));
+ _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/d:rangePr/@autoStart", "0");
+ }
+
+ if (endDate == DateTime.MaxValue) {
+ _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/d:rangePr/@endDate", "9999-12-31T00:00:00");
+ } else {
+ _cacheFieldHelper.SetXmlNodeString(
+ "d:fieldGroup/d:rangePr/@endDate",
+ endDate.ToString("s", CultureInfo.InvariantCulture));
+ _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/d:rangePr/@autoEnd", "0");
+ }
+
+ int items = AddDateGroupItems(group, groupBy, startDate, endDate, interval);
+ AddFieldItems(items);
+
+ _grouping = group;
+ return group;
+ }
+
+ internal ExcelPivotTableFieldNumericGroup SetNumericGroup(
+ double start,
+ double end,
+ double interval) {
+ ExcelPivotTableFieldNumericGroup group;
+ group = new(NameSpaceManager, _cacheFieldHelper.TopNode);
+ _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsNumber", true);
+ _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsInteger", true);
+ _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsSemiMixedTypes", false);
+ _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsString", false);
+
+ group.TopNode.InnerXml += string.Format(
+ "<fieldGroup base=\"{0}\"><rangePr autoStart=\"0\" autoEnd=\"0\" startNum=\"{1}\" endNum=\"{2}\" groupInterval=\"{3}\"/><groupItems /></fieldGroup>",
+ BaseIndex,
+ start.ToString(CultureInfo.InvariantCulture),
+ end.ToString(CultureInfo.InvariantCulture),
+ interval.ToString(CultureInfo.InvariantCulture));
+ int items = AddNumericGroupItems(group, start, end, interval);
+ AddFieldItems(items);
+
+ _grouping = group;
+ return group;
+ }
+
+ private int AddNumericGroupItems(
+ ExcelPivotTableFieldNumericGroup group,
+ double start,
+ double end,
+ double interval) {
+ if (interval < 0) {
+ throw (new("The interval must be a positiv"));
+ }
+ if (start > end) {
+ throw (new("Then End number must be larger than the Start number"));
+ }
+
+ XmlElement groupItems =
+ group.TopNode.SelectSingleNode("d:fieldGroup/d:groupItems", group.NameSpaceManager)
+ as XmlElement;
+ int items = 2;
+ //First date
+ double index = start;
+ double nextIndex = start + interval;
+ AddGroupItem(groupItems, "<" + start.ToString(CultureInfo.InvariantCulture));
+
+ while (index < end) {
+ AddGroupItem(
+ groupItems,
+ string.Format(
+ "{0}-{1}",
+ index.ToString(CultureInfo.InvariantCulture),
+ nextIndex.ToString(CultureInfo.InvariantCulture)));
+ index = nextIndex;
+ nextIndex += interval;
+ items++;
+ }
+ AddGroupItem(groupItems, ">" + nextIndex.ToString(CultureInfo.InvariantCulture));
+ return items;
+ }
+
+ private void AddFieldItems(int items) {
+ XmlElement prevNode = null;
+ XmlElement itemsNode = TopNode.SelectSingleNode("d:items", NameSpaceManager) as XmlElement;
+ for (int x = 0; x < items; x++) {
+ var itemNode = itemsNode.OwnerDocument.CreateElement("item", ExcelPackage._schemaMain);
+ itemNode.SetAttribute("x", x.ToString());
+ if (prevNode == null) {
+ itemsNode.PrependChild(itemNode);
+ } else {
+ itemsNode.InsertAfter(itemNode, prevNode);
+ }
+ prevNode = itemNode;
+ }
+ itemsNode.SetAttribute("count", (items + 1).ToString());
+ }
+
+ private int AddDateGroupItems(
+ ExcelPivotTableFieldGroup group,
+ eDateGroupBy groupBy,
+ DateTime startDate,
+ DateTime endDate,
+ int interval) {
+ XmlElement groupItems =
+ group.TopNode.SelectSingleNode("d:fieldGroup/d:groupItems", group.NameSpaceManager)
+ as XmlElement;
+ int items = 2;
+ //First date
+ AddGroupItem(
+ groupItems,
+ "<" + startDate.ToString("s", CultureInfo.InvariantCulture).Substring(0, 10));
+
+ switch (groupBy) {
+ case eDateGroupBy.Seconds:
+ case eDateGroupBy.Minutes:
+ AddTimeSerie(60, groupItems);
+ items += 60;
+ break;
+ case eDateGroupBy.Hours:
+ AddTimeSerie(24, groupItems);
+ items += 24;
+ break;
+ case eDateGroupBy.Days:
+ if (interval == 1) {
+ DateTime dt = new DateTime(2008, 1, 1); //pick a year with 366 days
+ while (dt.Year == 2008) {
+ AddGroupItem(groupItems, dt.ToString("dd-MMM"));
+ dt = dt.AddDays(1);
+ }
+ items += 366;
+ } else {
+ DateTime dt = startDate;
+ items = 0;
+ while (dt < endDate) {
+ AddGroupItem(groupItems, dt.ToString("dd-MMM"));
+ dt = dt.AddDays(interval);
+ items++;
+ }
+ }
+ break;
+ case eDateGroupBy.Months:
+ AddGroupItem(groupItems, "jan");
+ AddGroupItem(groupItems, "feb");
+ AddGroupItem(groupItems, "mar");
+ AddGroupItem(groupItems, "apr");
+ AddGroupItem(groupItems, "may");
+ AddGroupItem(groupItems, "jun");
+ AddGroupItem(groupItems, "jul");
+ AddGroupItem(groupItems, "aug");
+ AddGroupItem(groupItems, "sep");
+ AddGroupItem(groupItems, "oct");
+ AddGroupItem(groupItems, "nov");
+ AddGroupItem(groupItems, "dec");
+ items += 12;
+ break;
+ case eDateGroupBy.Quarters:
+ AddGroupItem(groupItems, "Qtr1");
+ AddGroupItem(groupItems, "Qtr2");
+ AddGroupItem(groupItems, "Qtr3");
+ AddGroupItem(groupItems, "Qtr4");
+ items += 4;
+ break;
+ case eDateGroupBy.Years:
+ if (startDate.Year >= 1900 && endDate != DateTime.MaxValue) {
+ for (int year = startDate.Year; year <= endDate.Year; year++) {
+ AddGroupItem(groupItems, year.ToString());
+ }
+ items += endDate.Year - startDate.Year + 1;
+ }
+ break;
+ default:
+ throw (new("unsupported grouping"));
+ }
+
+ //Lastdate
+ AddGroupItem(
+ groupItems,
+ ">" + endDate.ToString("s", CultureInfo.InvariantCulture).Substring(0, 10));
+ return items;
+ }
+
+ private void AddTimeSerie(int count, XmlElement groupItems) {
+ for (int i = 0; i < count; i++) {
+ AddGroupItem(groupItems, string.Format("{0:00}", i));
+ }
+ }
+
+ private void AddGroupItem(XmlElement groupItems, string value) {
+ var s = groupItems.OwnerDocument.CreateElement("s", ExcelPackage._schemaMain);
+ s.SetAttribute("v", value);
+ groupItems.AppendChild(s);
+ }
+
+ 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);
+ }
+ }
+ //if (_grouping is ExcelPivotTableFieldDateGroup)
+ //{
+ // ExcelPivotTableFieldDateGroup dtgrp = ((ExcelPivotTableFieldDateGroup)_grouping);
+
+ // ExcelPivotTableFieldItem minItem=null, maxItem=null;
+ // foreach (var item in _items)
+ // {
+ // if (item.X == 0)
+ // {
+ // minItem = item;
+ // }
+ // else if (maxItem == null || maxItem.X < item.X)
+ // {
+ // maxItem = item;
+ // }
+ // }
+ // if (dtgrp.AutoStart)
+ // {
+ // _items._list.Remove(minItem);
+ // }
+ // if (dtgrp.AutoEnd)
+ // {
+ // _items._list.Remove(maxItem);
+ // }
//}
- internal ExcelPivotTablePageFieldSettings _pageFieldSettings = null;
- public ExcelPivotTablePageFieldSettings PageFieldSettings
- {
- get
- {
- return _pageFieldSettings;
- }
- }
- internal eDateGroupBy DateGrouping
- {
- get;
- set;
- }
- ExcelPivotTableFieldGroup _grouping=null;
- /// <summary>
- /// Grouping settings.
- /// Null if the field has no grouping otherwise ExcelPivotTableFieldNumericGroup or ExcelPivotTableFieldNumericGroup.
- /// </summary>
- public ExcelPivotTableFieldGroup Grouping
- {
- get
- {
- return _grouping;
- }
- }
- #region Private & internal Methods
- 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);
- int fieldIndex;
- if(int.TryParse(x, out 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 = null;
- internal void SetCacheFieldNode(XmlNode cacheField)
- {
- _cacheFieldHelper = new XmlHelperInstance(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);
- }
- }
- }
- #endregion
- #region Grouping
- internal ExcelPivotTableFieldDateGroup SetDateGroup(eDateGroupBy GroupBy, DateTime StartDate, DateTime EndDate, int interval)
- {
- ExcelPivotTableFieldDateGroup group;
- group = new ExcelPivotTableFieldDateGroup(NameSpaceManager, _cacheFieldHelper.TopNode);
- _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsDate", true);
- _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsNonDate", false);
- _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsSemiMixedTypes", false);
-
- group.TopNode.InnerXml += string.Format("<fieldGroup base=\"{0}\"><rangePr groupBy=\"{1}\" /><groupItems /></fieldGroup>", BaseIndex, GroupBy.ToString().ToLower(CultureInfo.InvariantCulture));
-
- if (StartDate.Year < 1900)
- {
- _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/d:rangePr/@startDate", "1900-01-01T00:00:00");
- }
- else
- {
- _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/d:rangePr/@startDate", StartDate.ToString("s", CultureInfo.InvariantCulture));
- _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/d:rangePr/@autoStart", "0");
- }
-
- if (EndDate==DateTime.MaxValue)
- {
- _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/d:rangePr/@endDate", "9999-12-31T00:00:00");
- }
- else
- {
- _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/d:rangePr/@endDate", EndDate.ToString("s", CultureInfo.InvariantCulture));
- _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/d:rangePr/@autoEnd", "0");
- }
-
- int items = AddDateGroupItems(group, GroupBy, StartDate, EndDate, interval);
- AddFieldItems(items);
-
- _grouping = group;
- return group;
- }
- internal ExcelPivotTableFieldNumericGroup SetNumericGroup(double start, double end, double interval)
- {
- ExcelPivotTableFieldNumericGroup group;
- group = new ExcelPivotTableFieldNumericGroup(NameSpaceManager, _cacheFieldHelper.TopNode);
- _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsNumber", true);
- _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsInteger", true);
- _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsSemiMixedTypes", false);
- _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsString", false);
-
- group.TopNode.InnerXml += string.Format("<fieldGroup base=\"{0}\"><rangePr autoStart=\"0\" autoEnd=\"0\" startNum=\"{1}\" endNum=\"{2}\" groupInterval=\"{3}\"/><groupItems /></fieldGroup>", BaseIndex, start.ToString(CultureInfo.InvariantCulture), end.ToString(CultureInfo.InvariantCulture), interval.ToString(CultureInfo.InvariantCulture));
- int items = AddNumericGroupItems(group, start, end, interval);
- AddFieldItems(items);
-
- _grouping = group;
- return group;
- }
-
- private int AddNumericGroupItems(ExcelPivotTableFieldNumericGroup group, double start, double end, double interval)
- {
- if (interval < 0)
- {
- throw (new Exception("The interval must be a positiv"));
- }
- if (start > end)
- {
- throw(new Exception("Then End number must be larger than the Start number"));
- }
-
- XmlElement groupItems = group.TopNode.SelectSingleNode("d:fieldGroup/d:groupItems", group.NameSpaceManager) as XmlElement;
- int items = 2;
- //First date
- double index=start;
- double nextIndex=start+interval;
- AddGroupItem(groupItems, "<" + start.ToString(CultureInfo.InvariantCulture));
-
- while (index < end)
- {
- AddGroupItem(groupItems, string.Format("{0}-{1}", index.ToString(CultureInfo.InvariantCulture), nextIndex.ToString(CultureInfo.InvariantCulture)));
- index=nextIndex;
- nextIndex+=interval;
- items++;
- }
- AddGroupItem(groupItems, ">" + nextIndex.ToString(CultureInfo.InvariantCulture));
- return items;
- }
-
- private void AddFieldItems(int items)
- {
- XmlElement prevNode = null;
- XmlElement itemsNode = TopNode.SelectSingleNode("d:items", NameSpaceManager) as XmlElement;
- for (int x = 0; x < items; x++)
- {
- var itemNode = itemsNode.OwnerDocument.CreateElement("item", ExcelPackage.schemaMain);
- itemNode.SetAttribute("x", x.ToString());
- if (prevNode == null)
- {
- itemsNode.PrependChild(itemNode);
- }
- else
- {
- itemsNode.InsertAfter(itemNode, prevNode);
- }
- prevNode = itemNode;
- }
- itemsNode.SetAttribute("count", (items + 1).ToString());
- }
-
- private int AddDateGroupItems(ExcelPivotTableFieldGroup group, eDateGroupBy GroupBy, DateTime StartDate, DateTime EndDate, int interval)
- {
- XmlElement groupItems = group.TopNode.SelectSingleNode("d:fieldGroup/d:groupItems", group.NameSpaceManager) as XmlElement;
- int items = 2;
- //First date
- AddGroupItem(groupItems, "<" + StartDate.ToString("s", CultureInfo.InvariantCulture).Substring(0, 10));
-
- switch (GroupBy)
- {
- case eDateGroupBy.Seconds:
- case eDateGroupBy.Minutes:
- AddTimeSerie(60, groupItems);
- items += 60;
- break;
- case eDateGroupBy.Hours:
- AddTimeSerie(24, groupItems);
- items += 24;
- break;
- case eDateGroupBy.Days:
- if (interval == 1)
- {
- DateTime dt = new DateTime(2008, 1, 1); //pick a year with 366 days
- while (dt.Year == 2008)
- {
- AddGroupItem(groupItems, dt.ToString("dd-MMM"));
- dt = dt.AddDays(1);
- }
- items += 366;
- }
- else
- {
- DateTime dt = StartDate;
- items = 0;
- while (dt < EndDate)
- {
- AddGroupItem(groupItems, dt.ToString("dd-MMM"));
- dt = dt.AddDays(interval);
- items++;
- }
- }
- break;
- case eDateGroupBy.Months:
- AddGroupItem(groupItems, "jan");
- AddGroupItem(groupItems, "feb");
- AddGroupItem(groupItems, "mar");
- AddGroupItem(groupItems, "apr");
- AddGroupItem(groupItems, "may");
- AddGroupItem(groupItems, "jun");
- AddGroupItem(groupItems, "jul");
- AddGroupItem(groupItems, "aug");
- AddGroupItem(groupItems, "sep");
- AddGroupItem(groupItems, "oct");
- AddGroupItem(groupItems, "nov");
- AddGroupItem(groupItems, "dec");
- items += 12;
- break;
- case eDateGroupBy.Quarters:
- AddGroupItem(groupItems, "Qtr1");
- AddGroupItem(groupItems, "Qtr2");
- AddGroupItem(groupItems, "Qtr3");
- AddGroupItem(groupItems, "Qtr4");
- items += 4;
- break;
- case eDateGroupBy.Years:
- if(StartDate.Year>=1900 && EndDate!=DateTime.MaxValue)
- {
- for (int year = StartDate.Year; year <= EndDate.Year; year++)
- {
- AddGroupItem(groupItems, year.ToString());
- }
- items += EndDate.Year - StartDate.Year+1;
- }
- break;
- default:
- throw (new Exception("unsupported grouping"));
- }
-
- //Lastdate
- AddGroupItem(groupItems, ">" + EndDate.ToString("s", CultureInfo.InvariantCulture).Substring(0, 10));
- return items;
- }
-
- private void AddTimeSerie(int count, XmlElement groupItems)
- {
- for (int i = 0; i < count; i++)
- {
- AddGroupItem(groupItems, string.Format("{0:00}", i));
- }
- }
-
- private void AddGroupItem(XmlElement groupItems, string value)
- {
- var s = groupItems.OwnerDocument.CreateElement("s", ExcelPackage.schemaMain);
- s.SetAttribute("v", value);
- groupItems.AppendChild(s);
- }
- #endregion
- internal ExcelPivotTableFieldCollectionBase<ExcelPivotTableFieldItem> _items=null;
- /// <summary>
- /// Pivottable field Items. Used for grouping.
- /// </summary>
- public ExcelPivotTableFieldCollectionBase<ExcelPivotTableFieldItem> Items
- {
- get
- {
- if (_items == null)
- {
- _items = new ExcelPivotTableFieldCollectionBase<ExcelPivotTableFieldItem>(_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);
- }
- }
- //if (_grouping is ExcelPivotTableFieldDateGroup)
- //{
- // ExcelPivotTableFieldDateGroup dtgrp = ((ExcelPivotTableFieldDateGroup)_grouping);
-
- // ExcelPivotTableFieldItem minItem=null, maxItem=null;
- // foreach (var item in _items)
- // {
- // if (item.X == 0)
- // {
- // minItem = item;
- // }
- // else if (maxItem == null || maxItem.X < item.X)
- // {
- // maxItem = item;
- // }
- // }
- // if (dtgrp.AutoStart)
- // {
- // _items._list.Remove(minItem);
- // }
- // if (dtgrp.AutoEnd)
- // {
- // _items._list.Remove(maxItem);
- // }
-
- //}
- }
- return _items;
- }
- }
- /// <summary>
- /// Add numberic grouping to the field
- /// </summary>
- /// <param name="Start">Start value</param>
- /// <param name="End">End value</param>
- /// <param name="Interval">Interval</param>
- public void AddNumericGrouping(double Start, double End, double Interval)
- {
- ValidateGrouping();
- SetNumericGroup(Start, End, Interval);
- }
- /// <summary>
- /// Add a date grouping on this field.
- /// </summary>
- /// <param name="groupBy">Group by</param>
- public void AddDateGrouping(eDateGroupBy groupBy)
- {
- AddDateGrouping(groupBy, DateTime.MinValue, DateTime.MaxValue,1);
- }
- /// <summary>
- /// Add a date grouping on this field.
- /// </summary>
- /// <param name="groupBy">Group by</param>
- /// <param name="startDate">Fixed start date. Use DateTime.MinValue for auto</param>
- /// <param name="endDate">Fixed end date. Use DateTime.MaxValue for auto</param>
- public void AddDateGrouping(eDateGroupBy groupBy, DateTime startDate, DateTime endDate)
- {
- AddDateGrouping(groupBy, startDate, endDate, 1);
- }
- /// <summary>
- /// Add a date grouping on this field.
- /// </summary>
- /// <param name="days">Number of days when grouping on days</param>
- /// <param name="startDate">Fixed start date. Use DateTime.MinValue for auto</param>
- /// <param name="endDate">Fixed end date. Use DateTime.MaxValue for auto</param>
- public void AddDateGrouping(int days, DateTime startDate, DateTime endDate)
- {
- AddDateGrouping(eDateGroupBy.Days, startDate, endDate, days);
- }
- private void AddDateGrouping(eDateGroupBy groupBy, DateTime startDate, DateTime endDate, int groupInterval)
- {
- if (groupInterval < 1 || groupInterval >= Int16.MaxValue)
- {
- throw (new ArgumentOutOfRangeException("Group interval is out of range"));
- }
- if (groupInterval > 1 && groupBy != eDateGroupBy.Days)
- {
- throw (new ArgumentException("Group interval is can only be used when groupBy is Days"));
- }
- ValidateGrouping();
-
- bool firstField = true;
- List<ExcelPivotTableField> fields=new List<ExcelPivotTableField>();
- //Seconds
- if ((groupBy & eDateGroupBy.Seconds) == eDateGroupBy.Seconds)
- {
- fields.Add(AddField(eDateGroupBy.Seconds, startDate, endDate, ref firstField));
- }
- //Minutes
- if ((groupBy & eDateGroupBy.Minutes) == eDateGroupBy.Minutes)
- {
- fields.Add(AddField(eDateGroupBy.Minutes, startDate, endDate, ref firstField));
- }
- //Hours
- if ((groupBy & eDateGroupBy.Hours) == eDateGroupBy.Hours)
- {
- fields.Add(AddField(eDateGroupBy.Hours, startDate, endDate, ref firstField));
- }
- //Days
- if ((groupBy & eDateGroupBy.Days) == eDateGroupBy.Days)
- {
- fields.Add(AddField(eDateGroupBy.Days, startDate, endDate, ref firstField, groupInterval));
- }
- //Month
- if ((groupBy & eDateGroupBy.Months) == eDateGroupBy.Months)
- {
- fields.Add(AddField(eDateGroupBy.Months, startDate, endDate, ref firstField));
- }
- //Quarters
- if ((groupBy & eDateGroupBy.Quarters) == eDateGroupBy.Quarters)
- {
- fields.Add(AddField(eDateGroupBy.Quarters, startDate, endDate, ref firstField));
- }
- //Years
- if ((groupBy & eDateGroupBy.Years) == eDateGroupBy.Years)
- {
- fields.Add(AddField(eDateGroupBy.Years, startDate, endDate, ref firstField));
- }
-
- if (fields.Count > 1) _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/@par", (_table.Fields.Count - 1).ToString());
- if (groupInterval != 1)
- {
- _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/d:rangePr/@groupInterval", groupInterval.ToString());
- }
- else
- {
- _cacheFieldHelper.DeleteNode("d:fieldGroup/d:rangePr/@groupInterval");
- }
- _items = null;
- }
-
- private void ValidateGrouping()
- {
- if (!(IsColumnField || IsRowField))
- {
- throw (new Exception("Field must be a row or column field"));
- }
- foreach (var field in _table.Fields)
- {
- if (field.Grouping != null)
- {
- throw (new Exception("Grouping already exists"));
- }
- }
- }
- private ExcelPivotTableField AddField(eDateGroupBy groupBy, DateTime startDate, DateTime endDate, ref bool firstField)
- {
- return AddField(groupBy, startDate, endDate, ref firstField,1);
- }
- private ExcelPivotTableField AddField(eDateGroupBy groupBy, DateTime startDate, DateTime endDate, ref bool firstField, int interval)
- {
- if (firstField == false)
- {
- //Pivot field
- var topNode = _table.PivotTableXml.SelectSingleNode("//d:pivotFields", _table.NameSpaceManager);
- var fieldNode = _table.PivotTableXml.CreateElement("pivotField", ExcelPackage.schemaMain);
- fieldNode.SetAttribute("compact", "0");
- fieldNode.SetAttribute("outline", "0");
- fieldNode.SetAttribute("showAll", "0");
- fieldNode.SetAttribute("defaultSubtotal", "0");
- topNode.AppendChild(fieldNode);
-
- var field = new ExcelPivotTableField(_table.NameSpaceManager, fieldNode, _table, _table.Fields.Count, Index);
- field.DateGrouping = groupBy;
-
- XmlNode rowColFields;
- if (IsRowField)
- {
- rowColFields=TopNode.SelectSingleNode("../../d:rowFields", NameSpaceManager);
- }
- else
- {
- rowColFields = TopNode.SelectSingleNode("../../d:colFields", NameSpaceManager);
- }
-
- int fieldIndex, index = 0;
- foreach (XmlElement rowfield in rowColFields.ChildNodes)
- {
- if (int.TryParse(rowfield.GetAttribute("x"), out fieldIndex))
- {
- if (_table.Fields[fieldIndex].BaseIndex == BaseIndex)
- {
- var newElement = rowColFields.OwnerDocument.CreateElement("field", ExcelPackage.schemaMain);
- newElement.SetAttribute("x", field.Index.ToString());
- rowColFields.InsertBefore(newElement, rowfield);
- break;
- }
- }
- index++;
- }
-
- if (IsRowField)
- {
- _table.RowFields.Insert(field, index);
- }
- else
- {
- _table.ColumnFields.Insert(field, index);
- }
-
- _table.Fields.AddInternal(field);
-
- AddCacheField(field, startDate, endDate, interval);
- return field;
- }
- else
- {
- firstField = false;
- DateGrouping = groupBy;
- Compact = false;
- SetDateGroup(groupBy, startDate, endDate, interval);
- return this;
- }
- }
- private void AddCacheField(ExcelPivotTableField field, DateTime startDate, DateTime endDate, int interval)
- {
- //Add Cache definition field.
- var cacheTopNode = _table.CacheDefinition.CacheDefinitionXml.SelectSingleNode("//d:cacheFields", _table.NameSpaceManager);
- var cacheFieldNode = _table.CacheDefinition.CacheDefinitionXml.CreateElement("cacheField", ExcelPackage.schemaMain);
-
- cacheFieldNode.SetAttribute("name", field.DateGrouping.ToString());
- cacheFieldNode.SetAttribute("databaseField", "0");
- cacheTopNode.AppendChild(cacheFieldNode);
- field.SetCacheFieldNode(cacheFieldNode);
-
- field.SetDateGroup(field.DateGrouping, startDate, endDate, interval);
- }
+ }
+ return _items;
}
+ }
+
+ /// <summary>
+ /// Add numberic grouping to the field
+ /// </summary>
+ /// <param name="start">Start value</param>
+ /// <param name="end">End value</param>
+ /// <param name="interval">Interval</param>
+ public void AddNumericGrouping(double start, double end, double interval) {
+ ValidateGrouping();
+ SetNumericGroup(start, end, interval);
+ }
+
+ /// <summary>
+ /// Add a date grouping on this field.
+ /// </summary>
+ /// <param name="groupBy">Group by</param>
+ public void AddDateGrouping(eDateGroupBy groupBy) {
+ AddDateGrouping(groupBy, DateTime.MinValue, DateTime.MaxValue, 1);
+ }
+
+ /// <summary>
+ /// Add a date grouping on this field.
+ /// </summary>
+ /// <param name="groupBy">Group by</param>
+ /// <param name="startDate">Fixed start date. Use DateTime.MinValue for auto</param>
+ /// <param name="endDate">Fixed end date. Use DateTime.MaxValue for auto</param>
+ public void AddDateGrouping(eDateGroupBy groupBy, DateTime startDate, DateTime endDate) {
+ AddDateGrouping(groupBy, startDate, endDate, 1);
+ }
+
+ /// <summary>
+ /// Add a date grouping on this field.
+ /// </summary>
+ /// <param name="days">Number of days when grouping on days</param>
+ /// <param name="startDate">Fixed start date. Use DateTime.MinValue for auto</param>
+ /// <param name="endDate">Fixed end date. Use DateTime.MaxValue for auto</param>
+ public void AddDateGrouping(int days, DateTime startDate, DateTime endDate) {
+ AddDateGrouping(eDateGroupBy.Days, startDate, endDate, days);
+ }
+
+ private void AddDateGrouping(
+ eDateGroupBy groupBy,
+ DateTime startDate,
+ DateTime endDate,
+ int groupInterval) {
+ if (groupInterval < 1 || groupInterval >= Int16.MaxValue) {
+ throw (new ArgumentOutOfRangeException("Group interval is out of range"));
+ }
+ if (groupInterval > 1 && groupBy != eDateGroupBy.Days) {
+ throw (new ArgumentException("Group interval is can only be used when groupBy is Days"));
+ }
+ ValidateGrouping();
+
+ bool firstField = true;
+ List<ExcelPivotTableField> fields = new List<ExcelPivotTableField>();
+ //Seconds
+ if ((groupBy & eDateGroupBy.Seconds) == eDateGroupBy.Seconds) {
+ fields.Add(AddField(eDateGroupBy.Seconds, startDate, endDate, ref firstField));
+ }
+ //Minutes
+ if ((groupBy & eDateGroupBy.Minutes) == eDateGroupBy.Minutes) {
+ fields.Add(AddField(eDateGroupBy.Minutes, startDate, endDate, ref firstField));
+ }
+ //Hours
+ if ((groupBy & eDateGroupBy.Hours) == eDateGroupBy.Hours) {
+ fields.Add(AddField(eDateGroupBy.Hours, startDate, endDate, ref firstField));
+ }
+ //Days
+ if ((groupBy & eDateGroupBy.Days) == eDateGroupBy.Days) {
+ fields.Add(AddField(eDateGroupBy.Days, startDate, endDate, ref firstField, groupInterval));
+ }
+ //Month
+ if ((groupBy & eDateGroupBy.Months) == eDateGroupBy.Months) {
+ fields.Add(AddField(eDateGroupBy.Months, startDate, endDate, ref firstField));
+ }
+ //Quarters
+ if ((groupBy & eDateGroupBy.Quarters) == eDateGroupBy.Quarters) {
+ fields.Add(AddField(eDateGroupBy.Quarters, startDate, endDate, ref firstField));
+ }
+ //Years
+ if ((groupBy & eDateGroupBy.Years) == eDateGroupBy.Years) {
+ fields.Add(AddField(eDateGroupBy.Years, startDate, endDate, ref firstField));
+ }
+
+ if (fields.Count > 1) {
+ _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/@par", (_table.Fields.Count - 1).ToString());
+ }
+ if (groupInterval != 1) {
+ _cacheFieldHelper.SetXmlNodeString(
+ "d:fieldGroup/d:rangePr/@groupInterval",
+ groupInterval.ToString());
+ } else {
+ _cacheFieldHelper.DeleteNode("d:fieldGroup/d:rangePr/@groupInterval");
+ }
+ _items = null;
+ }
+
+ private void ValidateGrouping() {
+ if (!(IsColumnField || IsRowField)) {
+ throw (new("Field must be a row or column field"));
+ }
+ foreach (var field in _table.Fields) {
+ if (field.Grouping != null) {
+ throw (new("Grouping already exists"));
+ }
+ }
+ }
+
+ private ExcelPivotTableField AddField(
+ eDateGroupBy groupBy,
+ DateTime startDate,
+ DateTime endDate,
+ ref bool firstField) {
+ return AddField(groupBy, startDate, endDate, ref firstField, 1);
+ }
+
+ private ExcelPivotTableField AddField(
+ eDateGroupBy groupBy,
+ DateTime startDate,
+ DateTime endDate,
+ ref bool firstField,
+ int interval) {
+ if (firstField == false) {
+ //Pivot field
+ var topNode = _table.PivotTableXml.SelectSingleNode(
+ "//d:pivotFields",
+ _table.NameSpaceManager);
+ var fieldNode = _table.PivotTableXml.CreateElement("pivotField", ExcelPackage._schemaMain);
+ fieldNode.SetAttribute("compact", "0");
+ fieldNode.SetAttribute("outline", "0");
+ fieldNode.SetAttribute("showAll", "0");
+ fieldNode.SetAttribute("defaultSubtotal", "0");
+ topNode.AppendChild(fieldNode);
+
+ var field = new ExcelPivotTableField(
+ _table.NameSpaceManager,
+ fieldNode,
+ _table,
+ _table.Fields.Count,
+ Index);
+ field.DateGrouping = groupBy;
+
+ XmlNode rowColFields;
+ if (IsRowField) {
+ rowColFields = TopNode.SelectSingleNode("../../d:rowFields", NameSpaceManager);
+ } else {
+ rowColFields = TopNode.SelectSingleNode("../../d:colFields", NameSpaceManager);
+ }
+
+ int fieldIndex,
+ index = 0;
+ foreach (XmlElement rowfield in rowColFields.ChildNodes) {
+ if (int.TryParse(rowfield.GetAttribute("x"), out fieldIndex)) {
+ if (_table.Fields[fieldIndex].BaseIndex == BaseIndex) {
+ var newElement = rowColFields.OwnerDocument.CreateElement(
+ "field",
+ ExcelPackage._schemaMain);
+ newElement.SetAttribute("x", field.Index.ToString());
+ rowColFields.InsertBefore(newElement, rowfield);
+ break;
+ }
+ }
+ index++;
+ }
+
+ if (IsRowField) {
+ _table.RowFields.Insert(field, index);
+ } else {
+ _table.ColumnFields.Insert(field, index);
+ }
+
+ _table.Fields.AddInternal(field);
+
+ AddCacheField(field, startDate, endDate, interval);
+ return field;
+ }
+ firstField = false;
+ DateGrouping = groupBy;
+ Compact = false;
+ SetDateGroup(groupBy, startDate, endDate, interval);
+ return this;
+ }
+
+ private void AddCacheField(
+ ExcelPivotTableField field,
+ DateTime startDate,
+ DateTime endDate,
+ int interval) {
+ //Add Cache definition field.
+ var cacheTopNode = _table.CacheDefinition.CacheDefinitionXml.SelectSingleNode(
+ "//d:cacheFields",
+ _table.NameSpaceManager);
+ var cacheFieldNode = _table.CacheDefinition.CacheDefinitionXml.CreateElement(
+ "cacheField",
+ ExcelPackage._schemaMain);
+
+ cacheFieldNode.SetAttribute("name", field.DateGrouping.ToString());
+ cacheFieldNode.SetAttribute("databaseField", "0");
+ cacheTopNode.AppendChild(cacheFieldNode);
+ field.SetCacheFieldNode(cacheFieldNode);
+
+ field.SetDateGroup(field.DateGrouping, startDate, endDate, interval);
+ }
}
diff --git a/EPPlus/Table/PivotTable/ExcelPivotTableFieldCollection.cs b/EPPlus/Table/PivotTable/ExcelPivotTableFieldCollection.cs
index 9b736ce..e60e735 100644
--- a/EPPlus/Table/PivotTable/ExcelPivotTableFieldCollection.cs
+++ b/EPPlus/Table/PivotTable/ExcelPivotTableFieldCollection.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,310 +13,291 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
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 List<T>();
- internal ExcelPivotTableFieldCollectionBase(ExcelPivotTable table)
- {
- _table = table;
- }
- public IEnumerator<T> GetEnumerator()
- {
- return _list.GetEnumerator();
- }
+namespace OfficeOpenXml.Table.PivotTable;
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return _list.GetEnumerator();
- }
- public int Count
- {
- get
- {
- return _list.Count;
- }
- }
- internal void AddInternal(T field)
- {
- _list.Add(field);
- }
- internal void Clear()
- {
- _list.Clear();
- }
- public T this[int Index]
- {
- get
- {
- if (Index < 0 || Index >= _list.Count)
- {
- throw (new ArgumentOutOfRangeException("Index out of range"));
- }
- return _list[Index];
- }
- }
+/// <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)
- {
+ }
+}
+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;
}
- /// <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 && (((ExcelPivotTableFieldDateGroup)fld.Grouping).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;
- }
+ }
+ 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 Exception("This field is a column or page field. Can't add it to the RowFields collection"));
- }
- field.IsRowField = value;
- field.Axis = ePivotFieldAxis.Row;
- break;
- case "colFields":
- if (field.IsRowField || field.IsPageField)
- {
- throw (new Exception("This field is a row or page field. Can't add it to the ColumnFields collection"));
- }
- field.IsColumnField = value;
- field.Axis = ePivotFieldAxis.Column;
- break;
- case "pageFields":
- if (field.IsColumnField || field.IsRowField)
- {
- throw (new Exception("Field is a column or row field. Can't add it to the PageFields collection"));
- }
- if (_table.Address._fromRow < 3)
- {
- throw(new Exception(string.Format("A pivot table with page fields must be located above row 3. Currenct location is {0}", _table.Address.Address)));
- }
- field.IsPageField = value;
- field.Axis = ePivotFieldAxis.Page;
- break;
- case "dataFields":
-
- break;
- }
- }
- /// <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>
+ /// 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
+ && (((ExcelPivotTableFieldDateGroup)fld.Grouping).GroupBy) == groupBy) {
+ return fld;
+ }
}
- /// <summary>
- /// Collection class for data fields in a Pivottable
- /// </summary>
- public class ExcelPivotTableDataFieldCollection : ExcelPivotTableFieldCollectionBase<ExcelPivotTableDataField>
- {
- internal ExcelPivotTableDataFieldCollection(ExcelPivotTable table) :
- base(table)
- {
+ return null;
+ }
- }
- /// <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++.ToString();
- }
- while (ExistsDfName(name,null));
- dataField.Name = name;
- }
- }
-
- internal bool ExistsDfName(string name, ExcelPivotTableDataField datafield)
- {
- foreach (var df in _list)
- {
- if (((!string.IsNullOrEmpty(df.Name) && df.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase) ||
- (string.IsNullOrEmpty(df.Name) && df.Field.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)))) && datafield != df)
- {
- return true;
- }
- }
- return false;
- }
- /// <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);
- }
+ /// <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;
+ }
}
-}
\ No newline at end of file
+ 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
index cac0918..ea1f9d4 100644
--- a/EPPlus/Table/PivotTable/ExcelPivotTableFieldGroup.cs
+++ b/EPPlus/Table/PivotTable/ExcelPivotTableFieldGroup.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,148 +13,107 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this product may cause.
*
* Code change notes:
- *
+ *
* Author Change Date
* ******************************************************************************
* Jan Källman Added 21-MAR-2011
* Jan Källman License changed GPL-->LGPL 2011-12-16
*******************************************************************************/
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml;
-using System.Globalization;
-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)
- {
-
- }
+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"));
}
- /// <summary>
- /// A date group
- /// </summary>
- public class ExcelPivotTableFieldDateGroup : ExcelPivotTableFieldGroup
- {
- internal ExcelPivotTableFieldDateGroup(XmlNamespaceManager ns, XmlNode topNode) :
- base(ns, topNode)
- {
- }
- 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);
- }
- else
- {
- throw (new Exception("Invalid date Groupby"));
- }
- }
- private set
- {
- SetXmlNodeString(groupByPath, value.ToString().ToLower(CultureInfo.InvariantCulture));
- }
- }
- /// <summary>
- /// Auto detect start date
- /// </summary>
- public bool AutoStart
- {
- get
- {
- return GetXmlNodeBool("@autoStart", false);
- }
- }
- /// <summary>
- /// Auto detect end date
- /// </summary>
- public bool AutoEnd
- {
- get
- {
- return GetXmlNodeBool("@autoStart", false);
- }
- }
- }
- /// <summary>
- /// A pivot table field numeric grouping
- /// </summary>
- public class ExcelPivotTableFieldNumericGroup : ExcelPivotTableFieldGroup
- {
- internal ExcelPivotTableFieldNumericGroup(XmlNamespaceManager ns, XmlNode topNode) :
- base(ns, topNode)
- {
- }
- const string startPath = "d:fieldGroup/d:rangePr/@startNum";
- /// <summary>
- /// Start value
- /// </summary>
- public double Start
- {
- get
- {
- return (double)GetXmlNodeDoubleNull(startPath);
- }
- private set
- {
- SetXmlNodeString(startPath,value.ToString(CultureInfo.InvariantCulture));
- }
- }
- const string endPath = "d:fieldGroup/d:rangePr/@endNum";
- /// <summary>
- /// End value
- /// </summary>
- public double End
- {
- get
- {
- return (double)GetXmlNodeDoubleNull(endPath);
- }
- private set
- {
- SetXmlNodeString(endPath, value.ToString(CultureInfo.InvariantCulture));
- }
- }
- const string groupIntervalPath = "d:fieldGroup/d:rangePr/@groupInterval";
- /// <summary>
- /// Interval
- /// </summary>
- public double Interval
- {
- get
- {
- return (double)GetXmlNodeDoubleNull(groupIntervalPath);
- }
- private set
- {
- SetXmlNodeString(groupIntervalPath, value.ToString(CultureInfo.InvariantCulture));
- }
- }
- }
+ 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 {
+ get => (double)GetXmlNodeDoubleNull(_startPath);
+ private set => SetXmlNodeString(_startPath, value.ToString(CultureInfo.InvariantCulture));
+ }
+
+ private const string _endPath = "d:fieldGroup/d:rangePr/@endNum";
+
+ /// <summary>
+ /// End value
+ /// </summary>
+ public double End {
+ get => (double)GetXmlNodeDoubleNull(_endPath);
+ private set => SetXmlNodeString(_endPath, value.ToString(CultureInfo.InvariantCulture));
+ }
+
+ private const string _groupIntervalPath = "d:fieldGroup/d:rangePr/@groupInterval";
+
+ /// <summary>
+ /// Interval
+ /// </summary>
+ public double Interval {
+ get => (double)GetXmlNodeDoubleNull(_groupIntervalPath);
+ private set =>
+ SetXmlNodeString(_groupIntervalPath, value.ToString(CultureInfo.InvariantCulture));
+ }
}
diff --git a/EPPlus/Table/PivotTable/ExcelPivotTableFieldItem.cs b/EPPlus/Table/PivotTable/ExcelPivotTableFieldItem.cs
index 711507e..d4dce2d 100644
--- a/EPPlus/Table/PivotTable/ExcelPivotTableFieldItem.cs
+++ b/EPPlus/Table/PivotTable/ExcelPivotTableFieldItem.cs
@@ -13,80 +13,62 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this product may cause.
*
* Code change notes:
- *
+ *
* Author Change Date
* ******************************************************************************
* Jan Källman Added 21-MAR-2011
* Jan Källman License changed GPL-->LGPL 2011-12-16
*******************************************************************************/
+
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using System.Xml;
-namespace OfficeOpenXml.Table.PivotTable
-{
- /// <summary>
- /// A field Item. Used for grouping
- /// </summary>
- public class ExcelPivotTableFieldItem : XmlHelper
- {
- ExcelPivotTableField _field;
- internal ExcelPivotTableFieldItem(XmlNamespaceManager ns, XmlNode topNode, ExcelPivotTableField field) :
- base(ns, topNode)
- {
- _field = field;
+namespace OfficeOpenXml.Table.PivotTable;
+
+/// <summary>
+/// A field Item. Used for grouping
+/// </summary>
+public class ExcelPivotTableFieldItem : XmlHelper {
+ private 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"));
}
- /// <summary>
- /// The text. Unique values only
- /// </summary>
- public string Text
- {
- get
- {
- return 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
- {
- get
- {
- return GetXmlNodeInt("@x");
- }
- }
- internal string T
- {
- get
- {
- return GetXmlNodeString("@t");
- }
- }
+ }
+ 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
index 7e5ba85..fe6f762 100644
--- a/EPPlus/Table/PivotTable/ExcelPivotTablePageFieldSettings.cs
+++ b/EPPlus/Table/PivotTable/ExcelPivotTablePageFieldSettings.cs
@@ -13,106 +13,81 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this product may cause.
*
* Code change notes:
- *
+ *
* Author Change Date
* ******************************************************************************
* Jan Källman Added 21-MAR-2011
* Jan Källman License changed GPL-->LGPL 2011-12-16
*******************************************************************************/
-using System;
-using System.Collections.Generic;
-using System.Text;
+
using System.Xml;
-namespace OfficeOpenXml.Table.PivotTable
-{
- /// <summary>
- /// A page / report filter field
- /// </summary>
- public class ExcelPivotTablePageFieldSettings : XmlHelper
- {
- 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
- {
- return GetXmlNodeInt("@fld");
- }
- set
- {
- SetXmlNodeString("@fld",value.ToString());
- }
- }
- /// <summary>
- /// The Name of the field
- /// </summary>
- public string Name
- {
- get
- {
- return 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
- {
- return GetXmlNodeInt("@numFmtId");
- }
- set
- {
- SetXmlNodeString("@numFmtId", value.ToString());
- }
- }
- internal int Hier
- {
- get
- {
- return GetXmlNodeInt("@hier");
- }
- set
- {
- SetXmlNodeString("@hier", value.ToString());
- }
- }
+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
index bc1c8fc..05fadd1 100644
--- a/EPPlus/Utils/AddressUtility.cs
+++ b/EPPlus/Utils/AddressUtility.cs
@@ -1,29 +1,20 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
+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;
- }
+namespace OfficeOpenXml.Utils;
- private static void AddRowNumbersToEntireColumnRange(ref string address, string range)
- {
- var parsedRange = string.Format("{0}{1}", range, ExcelPackage.MaxRows);
- var splitArr = parsedRange.Split(new char[] { ':' });
- address = address.Replace(range, string.Format("{0}1:{1}", splitArr[0], splitArr[1]));
- }
+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
index 90b0abe..e95c92b 100644
--- a/EPPlus/Utils/Argument.cs
+++ b/EPPlus/Utils/Argument.cs
@@ -13,41 +13,31 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
-namespace OfficeOpenXml.Utils
-{
- internal class Argument<T> : IArgument<T>
- {
- public Argument(T @value)
- {
- _value = @value;
- }
+namespace OfficeOpenXml.Utils;
- private T _value;
+internal class Argument<T> : IArgument<T> {
+ public Argument(T value) {
+ _value = value;
+ }
- T IArgument<T>.Value
- {
- get { return _value; }
- }
- }
+ private T _value;
+
+ T IArgument<T>.Value => _value;
}
diff --git a/EPPlus/Utils/ArgumentExtensions.cs b/EPPlus/Utils/ArgumentExtensions.cs
index 9fdd6c4..6bba854 100644
--- a/EPPlus/Utils/ArgumentExtensions.cs
+++ b/EPPlus/Utils/ArgumentExtensions.cs
@@ -13,17 +13,17 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
@@ -31,65 +31,53 @@
*******************************************************************************/
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-namespace OfficeOpenXml.Utils
-{
- /// <summary>
- /// Extension methods for guarding
- /// </summary>
- public static class ArgumentExtensions
- {
+namespace OfficeOpenXml.Utils;
- /// <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);
- }
- }
+/// <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
index d528426..fddf785 100644
--- a/EPPlus/Utils/ConvertUtil.cs
+++ b/EPPlus/Utils/ConvertUtil.cs
@@ -1,196 +1,171 @@
-using System;
-using System.Collections.Generic;
+using System;
using System.Globalization;
-using System.Linq;
+using System.IO;
using System.Text;
using System.Text.RegularExpressions;
-using OfficeOpenXml.FormulaParsing.ExpressionGraph;
-using System.IO;
-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);
- }
+namespace OfficeOpenXml.Utils;
- 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)
- {
- d = ((DateTime)v).ToOADate();
- }
- else if (v is TimeSpan)
- {
- d = DateTime.FromOADate(0).Add((TimeSpan)v).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();
- }
+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) {
+ d = ((DateTime)v).ToOADate();
+ } else if (v is TimeSpan) {
+ d = DateTime.FromOADate(0).Add((TimeSpan)v).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
index ac4a5aa..8c4f614 100644
--- a/EPPlus/Utils/IArgument.cs
+++ b/EPPlus/Utils/IArgument.cs
@@ -13,36 +13,29 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
+namespace OfficeOpenXml.Utils;
-namespace OfficeOpenXml.Utils
-{
- /// <summary>
- /// An argument
- /// </summary>
- /// <typeparam name="T">Argument Type</typeparam>
- public interface IArgument<T>
- {
- T Value { get; }
- }
+/// <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
index 6447951..b1087c3 100644
--- a/EPPlus/Utils/IExcelCell.cs
+++ b/EPPlus/Utils/IExcelCell.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,38 +13,39 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Text;
-namespace OfficeOpenXml.Style
-{
- internal interface IExcelCell
- {
- #region "public properties"
- 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; }
- #endregion
- }
+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
index 19b4986..61ef1c1 100644
--- a/EPPlus/Utils/IValidationResult.cs
+++ b/EPPlus/Utils/IValidationResult.cs
@@ -1,13 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+namespace OfficeOpenXml.Utils;
-namespace OfficeOpenXml.Utils
-{
- public interface IValidationResult
- {
- void IsTrue();
- void IsFalse();
- }
+public interface IValidationResult {
+ void IsTrue();
+
+ void IsFalse();
}
diff --git a/EPPlus/Utils/Require.cs b/EPPlus/Utils/Require.cs
index 6f9943f..17b98d8 100644
--- a/EPPlus/Utils/Require.cs
+++ b/EPPlus/Utils/Require.cs
@@ -13,40 +13,30 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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.Generic;
-using System.Linq;
-using System.Text;
+namespace OfficeOpenXml.Utils;
-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);
- }
-
-
- }
+/// <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
index a170486..5115bd3 100644
--- a/EPPlus/Utils/SqRefUtility.cs
+++ b/EPPlus/Utils/SqRefUtility.cs
@@ -1,39 +1,31 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
+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;
- }
+namespace OfficeOpenXml.Utils;
- /// <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;
- }
- }
+/// <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
index 84ff943..8f9c04b 100644
--- a/EPPlus/Utils/UriHelper.cs
+++ b/EPPlus/Utils/UriHelper.cs
@@ -1,91 +1,69 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+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('/');
+namespace OfficeOpenXml.Utils;
- 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;
- }
- else 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 Uri(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 Uri(dirUp+file,UriKind.Relative);
- }
+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
index cb04dab..2985491 100644
--- a/EPPlus/Utils/ValidationResult.cs
+++ b/EPPlus/Utils/ValidationResult.cs
@@ -1,50 +1,35 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-namespace OfficeOpenXml.Utils
-{
- public class ValidationResult : IValidationResult
- {
- public ValidationResult(bool result)
- : this(result, null)
- {
-
- }
+namespace OfficeOpenXml.Utils;
- public ValidationResult(bool result, string errorMessage)
- {
- _result = result;
- _errorMessage = errorMessage;
- }
+public class ValidationResult : IValidationResult {
+ public ValidationResult(bool result)
+ : this(result, null) {}
- private bool _result;
- private string _errorMessage;
+ public ValidationResult(bool result, string errorMessage) {
+ _result = result;
+ _errorMessage = errorMessage;
+ }
- private void Throw()
- {
- if(string.IsNullOrEmpty(_errorMessage))
- {
- throw new InvalidOperationException();
- }
- throw new InvalidOperationException(_errorMessage);
- }
+ private bool _result;
+ private string _errorMessage;
- void IValidationResult.IsTrue()
- {
- if (!_result)
- {
- Throw();
- }
- }
-
- void IValidationResult.IsFalse()
- {
- if (_result)
- {
- Throw();
- }
- }
+ 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
index 6915a4a..9455242 100644
--- a/EPPlus/XmlHelper.cs
+++ b/EPPlus/XmlHelper.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,17 +13,17 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The author 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
@@ -33,798 +33,658 @@
*******************************************************************************/
using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Xml;
-using OfficeOpenXml.Style;
using System.Globalization;
using System.IO;
-namespace OfficeOpenXml
-{
- /// <summary>
- /// Help class containing XML functions.
- /// Can be Inherited
- /// </summary>
- public abstract class XmlHelper
- {
- internal delegate int ChangedEventHandler(StyleBase sender, Style.StyleChangeEventArgs e);
+using System.Text;
+using System.Xml;
+using OfficeOpenXml.Packaging;
+using OfficeOpenXml.Style;
- internal XmlHelper(XmlNamespaceManager nameSpaceManager)
- {
- TopNode = null;
- NameSpaceManager = nameSpaceManager;
- }
+namespace OfficeOpenXml;
- internal XmlHelper(XmlNamespaceManager nameSpaceManager, XmlNode topNode)
- {
- TopNode = topNode;
- NameSpaceManager = nameSpaceManager;
- }
- //internal bool ChangedFlag;
- internal XmlNamespaceManager NameSpaceManager { get; set; }
- internal XmlNode TopNode { get; set; }
- string[] _schemaNodeOrder = null;
- /// <summary>
- /// Schema order list
- /// </summary>
- internal string[] SchemaNodeOrder
- {
- get
- {
- return _schemaNodeOrder;
- }
- set
- {
- _schemaNodeOrder = value;
- }
- }
- internal XmlNode CreateNode(string path)
- {
- if (path == "")
- return TopNode;
- else
- 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;
+/// <summary>
+/// Help class containing XML functions.
+/// Can be Inherited
+/// </summary>
+public abstract class XmlHelper {
+ internal delegate int ChangedEventHandler(StyleBase sender, StyleChangeEventArgs e);
- string nameSpaceURI = "";
- string[] nameSplit = subPath.Split(':');
+ internal XmlHelper(XmlNamespaceManager nameSpaceManager) {
+ TopNode = null;
+ NameSpaceManager = nameSpaceManager;
+ }
- if (SchemaNodeOrder != null && subPath[0] != '@')
- {
- insertFirst = false;
- prependNode = GetPrependNode(subPath, node);
- }
+ internal XmlHelper(XmlNamespaceManager nameSpaceManager, XmlNode topNode) {
+ TopNode = topNode;
+ NameSpaceManager = nameSpaceManager;
+ }
- 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;
- }
+ //internal bool ChangedFlag;
+ internal XmlNamespaceManager NameSpaceManager { get; set; }
- /// <summary>
- /// Options to insert a node in the XmlDocument
- /// </summary>
- internal enum eNodeInsertOrder
- {
- /// <summary>
- /// Insert as first node of "topNode"
- /// </summary>
- First,
+ internal XmlNode TopNode { get; set; }
- /// <summary>
- /// Insert as the last child of "topNode"
- /// </summary>
- Last,
+ private string[] _schemaNodeOrder;
- /// <summary>
- /// Insert after the "referenceNode"
- /// </summary>
- After,
+ /// <summary>
+ /// Schema order list
+ /// </summary>
+ internal string[] SchemaNodeOrder {
+ get => _schemaNodeOrder;
+ set => _schemaNodeOrder = value;
+ }
- /// <summary>
- /// Insert before the "referenceNode"
- /// </summary>
- Before,
+ internal XmlNode CreateNode(string path) {
+ if (path == "") {
+ return TopNode;
+ }
+ return CreateNode(path, false);
+ }
- /// <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
- }
+ 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;
- /// <summary>
- /// Create a complex node. Insert the node according to SchemaOrder
- /// using the TopNode as the parent
- /// </summary>
- /// <param name="path"></param>
- /// <returns></returns>
- internal XmlNode CreateComplexNode(
- string path)
- {
- return CreateComplexNode(
- TopNode,
- path,
- eNodeInsertOrder.SchemaOrder,
- null);
- }
+ string nameSpaceUri = "";
+ string[] nameSplit = subPath.Split(':');
- /// <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);
- }
+ if (SchemaNodeOrder != null && subPath[0] != '@') {
+ insertFirst = false;
+ prependNode = GetPrependNode(subPath, node);
+ }
- /// <summary>
- /// Creates complex XML nodes
+ 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>
- /// <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;
- }
+ First,
- XmlNode node = topNode;
- string nameSpaceURI = string.Empty;
+ /// <summary>
+ /// Insert as the last child of "topNode"
+ /// </summary>
+ Last,
- //TODO: BUG: when the "path" contains "/" in an attrribue value, it gives an error.
+ /// <summary>
+ /// Insert after the "referenceNode"
+ /// </summary>
+ After,
- // 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'
+ /// <summary>
+ /// Insert before the "referenceNode"
+ /// </summary>
+ Before,
- // 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
+ /// <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,
+ }
- // 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("\"", "");
- }
+ /// <summary>
+ /// Create a complex node. Insert the node according to SchemaOrder
+ /// using the TopNode as the parent
+ /// </summary>
+ /// <param name="path"></param>
+ /// <returns></returns>
+ internal XmlNode CreateComplexNode(string path) {
+ return CreateComplexNode(TopNode, path, eNodeInsertOrder.SchemaOrder, null);
+ }
- // Get the attribute (if exists)
- XmlAttribute attribute = (XmlAttribute)(node.Attributes.GetNamedItem(attributeName));
+ /// <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);
+ }
- // 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(':');
- nameSpaceURI = string.Empty;
-
- // 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 == null) || (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)
- {
- (node as XmlAttribute).OwnerElement.Attributes.Remove(node as XmlAttribute);
- }
- 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)
- {
- var att = (XmlAttribute)node;
- att.OwnerElement.Attributes.Remove(att);
- }
- else
- {
- node.ParentNode.RemoveChild(node);
- }
- }
- }
- internal void DeleteTopNode()
- {
- TopNode.ParentNode.RemoveChild(TopNode);
+ /// <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;
}
- 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)
- {
- SetXmlNodeString(node, path, value, false, 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)
- {
- var elem = (node as XmlAttribute).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;
- }
- else
- {
- 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;
- }
- else if (value == "")
- {
- return blankValue;
- }
- else
- {
- return false;
- }
- }
- internal int GetXmlNodeInt(string path)
- {
- int i;
- if (int.TryParse(GetXmlNodeString(path), out i))
- {
- return i;
- }
- else
- {
- return int.MinValue;
- }
- }
- internal int? GetXmlNodeIntNull(string path)
- {
- int i;
- string s = GetXmlNodeString(path);
- if (s!="" && int.TryParse(s, out i))
- {
- return i;
- }
- else
- {
- return null;
- }
- }
- internal decimal GetXmlNodeDecimal(string path)
- {
- decimal d;
- if (decimal.TryParse(GetXmlNodeString(path), NumberStyles.Any, CultureInfo.InvariantCulture, out d))
- {
- return d;
- }
- else
- {
- return 0;
- }
- }
- internal decimal? GetXmlNodeDecimalNull(string path)
- {
- decimal d;
- if (decimal.TryParse(GetXmlNodeString(path), NumberStyles.Any, CultureInfo.InvariantCulture, out d))
- {
- return d;
+ XmlNode node = topNode;
+ string nameSpaceUri = string.Empty;
+
+ //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
- {
- return null;
+ } 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(':');
+ nameSpaceUri = string.Empty;
+
+ // 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 == null) || (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;
}
- internal double? GetXmlNodeDoubleNull(string path)
- {
- string s = GetXmlNodeString(path);
- if (s == "")
- {
- return null;
- }
- else
- {
- double v;
- if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out v))
- {
- return v;
- }
- else
- {
- return null;
- }
- }
- }
- internal double GetXmlNodeDouble(string path)
- {
- string s = GetXmlNodeString(path);
- if (s == "")
- {
- return double.NaN;
- }
- else
- {
- double v;
- if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out v))
- {
- return v;
- }
- else
- {
- return double.NaN;
- }
- }
- }
- internal string GetXmlNodeString(XmlNode node, string path)
- {
- if (node == null)
- {
- return "";
}
+ }
+ // 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) {
+ (node as XmlAttribute).OwnerElement.Attributes.Remove(node as XmlAttribute);
+ } 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) {
+ var att = (XmlAttribute)node;
+ att.OwnerElement.Attributes.Remove(att);
+ } else {
+ node.ParentNode.RemoveChild(node);
+ }
+ }
+ }
+
+ internal void DeleteTopNode() {
+ TopNode.ParentNode.RemoveChild(TopNode);
+ }
+
+ 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) {
+ SetXmlNodeString(node, path, value, false, 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;
+ }
+ }
- if (nameNode != null)
- {
- if (nameNode.NodeType == XmlNodeType.Attribute)
- {
- return nameNode.Value != null ? nameNode.Value : "";
- }
- else
- {
- return nameNode.InnerText;
+ 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) {
+ var elem = (node as XmlAttribute).OwnerElement;
+ elem.ParentNode.RemoveChild(elem);
+ } else {
+ TopNode.RemoveChild(node);
}
}
- else
- {
- return "";
+ } 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) {
+ int i;
+ if (int.TryParse(GetXmlNodeString(path), out i)) {
+ return i;
+ }
+ return int.MinValue;
+ }
+
+ internal int? GetXmlNodeIntNull(string path) {
+ int i;
+ string s = GetXmlNodeString(path);
+ if (s != "" && int.TryParse(s, out i)) {
+ return i;
+ }
+ return null;
+ }
+
+ internal decimal GetXmlNodeDecimal(string path) {
+ decimal d;
+ if (decimal.TryParse(
+ GetXmlNodeString(path),
+ NumberStyles.Any,
+ CultureInfo.InvariantCulture,
+ out d)) {
+ return d;
+ }
+ return 0;
+ }
+
+ internal decimal? GetXmlNodeDecimalNull(string path) {
+ decimal d;
+ if (decimal.TryParse(
+ GetXmlNodeString(path),
+ NumberStyles.Any,
+ CultureInfo.InvariantCulture,
+ out d)) {
+ return d;
+ }
+ return null;
+ }
+
+ internal double? GetXmlNodeDoubleNull(string path) {
+ string s = GetXmlNodeString(path);
+ if (s == "") {
+ return null;
+ }
+ double v;
+ if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out v)) {
+ return v;
+ }
+ return null;
+ }
+
+ internal double GetXmlNodeDouble(string path) {
+ string s = GetXmlNodeString(path);
+ if (s == "") {
+ return double.NaN;
+ }
+ double v;
+ if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out 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 != null ? nameNode.Value : "";
+ }
+ return nameNode.InnerText;
+ }
+ return "";
+ }
+
+ internal string GetXmlNodeString(string path) {
+ return GetXmlNodeString(TopNode, path);
+ }
+
+ internal static Uri GetNewUri(ZipPackage package, string sUri) {
+ return GetNewUri(package, sUri, 1);
+ }
+
+ internal static Uri GetNewUri(ZipPackage package, string sUri, int id) {
+ Uri uri;
+ do {
+ uri = new(string.Format(sUri, id++), UriKind.Relative);
+ } while (package.PartExists(uri));
+ return uri;
+ }
+
+ /// <summary>
+ /// Insert the new node before any of the nodes in the comma separeted list
+ /// </summary>
+ /// <param name="parentNode">Parent node</param>
+ /// <param name="beforeNodes">comma separated list containing nodes to insert after. Left to right order</param>
+ /// <param name="newNode">The new node to be inserterd</param>
+ internal void InserAfter(XmlNode parentNode, string beforeNodes, XmlNode newNode) {
+ string[] nodePaths = beforeNodes.Split(',');
+
+ foreach (string nodePath in nodePaths) {
+ XmlNode node = parentNode.SelectSingleNode(nodePath, NameSpaceManager);
+ if (node != null) {
+ parentNode.InsertAfter(newNode, node);
+ return;
}
}
- internal string GetXmlNodeString(string path)
- {
- return GetXmlNodeString(TopNode, path);
- }
- internal static Uri GetNewUri(Packaging.ZipPackage package, string sUri)
- {
- return GetNewUri(package, sUri, 1);
- }
- internal static Uri GetNewUri(Packaging.ZipPackage package, string sUri, int id)
- {
- Uri uri;
- do
- {
- uri = new Uri(string.Format(sUri, id++), UriKind.Relative);
- }
- while (package.PartExists(uri));
- return uri;
- }
- /// <summary>
- /// Insert the new node before any of the nodes in the comma separeted list
- /// </summary>
- /// <param name="parentNode">Parent node</param>
- /// <param name="beforeNodes">comma separated list containing nodes to insert after. Left to right order</param>
- /// <param name="newNode">The new node to be inserterd</param>
- internal void InserAfter(XmlNode parentNode, string beforeNodes, XmlNode newNode)
- {
- string[] nodePaths = beforeNodes.Split(',');
+ parentNode.InsertAfter(newNode, null);
+ }
- foreach (string nodePath in nodePaths)
- {
- XmlNode node = parentNode.SelectSingleNode(nodePath, NameSpaceManager);
- if (node != null)
- {
- parentNode.InsertAfter(newNode, node);
- return;
- }
- }
- parentNode.InsertAfter(newNode, null);
- }
- 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);
- }
- }
+ 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
index b2106a2..0af078b 100644
--- a/EPPlus/XmlHelperFactory.cs
+++ b/EPPlus/XmlHelperFactory.cs
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
@@ -13,52 +13,41 @@
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
- * All code and executables are provided "as is" with no warranty either express or implied.
+ * All code and executables are provided "as is" with no warranty either express or implied.
* The 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;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+
using System.Xml;
-namespace OfficeOpenXml
-{
- internal class XmlHelperInstance : XmlHelper
- {
- internal XmlHelperInstance(XmlNamespaceManager namespaceManager)
- : base(namespaceManager)
- {}
+namespace OfficeOpenXml;
- internal XmlHelperInstance(XmlNamespaceManager namespaceManager, XmlNode topNode)
- : base(namespaceManager, topNode)
- {}
+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 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);
- }
- }
+ internal static XmlHelper Create(XmlNamespaceManager namespaceManager, XmlNode topNode) {
+ return new XmlHelperInstance(namespaceManager, topNode);
+ }
}
diff --git a/NetCoreTests/ExcelPackageTest.cs b/NetCoreTests/ExcelPackageTest.cs
index e59278f..975fadc 100644
--- a/NetCoreTests/ExcelPackageTest.cs
+++ b/NetCoreTests/ExcelPackageTest.cs
@@ -7,24 +7,21 @@
namespace NetCoreTests;
[TestClass]
-public class ExcelPackageTest
-{
- [TestMethod]
- public void TestGetAsByteArray()
- {
- var package = new ExcelPackage(new FileInfo(GetTestWorkbookPath("Times.xlsx")));
- var data = package.GetAsByteArray();
-
- // Verify that we can reload
- var newPackage = new ExcelPackage(new MemoryStream(data, false));
- newPackage.Workbook.Worksheets.Count.Should().Be(1);
- var worksheet = newPackage.Workbook.Worksheets.First();
- worksheet.Name.Should().Be("Times_csv");
- }
-
- private static string GetTestWorkbookPath(string filename)
- {
- var assemblyPath = Path.GetDirectoryName(typeof(ExcelPackageTest).Assembly.Location)!;
- return Path.Combine(assemblyPath, "TestWorkbooks", filename);
- }
-}
\ No newline at end of file
+public class ExcelPackageTest {
+ [TestMethod]
+ public void TestGetAsByteArray() {
+ var package = new ExcelPackage(new FileInfo(GetTestWorkbookPath("Times.xlsx")));
+ var data = package.GetAsByteArray();
+
+ // Verify that we can reload
+ var newPackage = new ExcelPackage(new MemoryStream(data, false));
+ newPackage.Workbook.Worksheets.Count.Should().Be(1);
+ var worksheet = newPackage.Workbook.Worksheets.First();
+ worksheet.Name.Should().Be("Times_csv");
+ }
+
+ private static string GetTestWorkbookPath(string filename) {
+ var assemblyPath = Path.GetDirectoryName(typeof(ExcelPackageTest).Assembly.Location)!;
+ return Path.Combine(assemblyPath, "TestWorkbooks", filename);
+ }
+}
diff --git a/NetCoreTests/NetCoreTests.csproj b/NetCoreTests/NetCoreTests.csproj
index 3f11e9f..b5e9414 100644
--- a/NetCoreTests/NetCoreTests.csproj
+++ b/NetCoreTests/NetCoreTests.csproj
@@ -4,19 +4,19 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="FluentAssertions" Version="6.6.0" />
+ <PackageReference Include="FluentAssertions" Version="6.6.0"/>
<PackageReference Include="MSTest.TestAdapter" Version="2.2.8"/>
- <PackageReference Include="MSTest.TestFramework" Version="2.2.8" />
+ <PackageReference Include="MSTest.TestFramework" Version="2.2.8"/>
<PackageReference Include="Microsoft.NET.Test.SDK" Version="17.1.0"/>
<PackageReference Include="System.Net.Http" Version="4.3.4"/>
- <PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />
+ <PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0"/>
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1"/>
- <ProjectReference Include="..\EPPlus\EPPlusSDK.csproj" />
-
+ <ProjectReference Include="..\EPPlus\EPPlusSDK.csproj"/>
+
<None Include="TestWorkbooks/**" CopyToOutputDirectory="PreserveNewest"/>
<!--Transient dependency; required to address b/230278644-->
- <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
+ <PackageReference Include="Newtonsoft.Json" Version="13.0.1"/>
</ItemGroup>
</Project>
diff --git a/NetCoreTests/TimeTest.cs b/NetCoreTests/TimeTest.cs
index b207ff0..8ce92f5 100644
--- a/NetCoreTests/TimeTest.cs
+++ b/NetCoreTests/TimeTest.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.IO;
using System.Linq;
using System.Text;
@@ -9,57 +9,52 @@
namespace NetCoreTests;
[TestClass]
-public class TimeTest
-{
- static TimeTest()
- {
- Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
- }
-
- [TestMethod]
- public void TestIncorrectDurationFromOADate()
- {
- ExcelWorksheet.IncorrectDurationFromOADate(2.75).Should().Be(new(1900, 1, 1, 18, 0, 0));
- ExcelWorksheet.IncorrectDurationFromOADate(1.75).Should().Be(new(1899, 12, 31, 18, 0, 0));
- ExcelWorksheet.IncorrectDurationFromOADate(0.75).Should().Be(new(1899, 12, 30, 18, 0, 0));
- ExcelWorksheet.IncorrectDurationFromOADate(0.5).Should().Be(new(1899, 12, 30, 12, 0, 0));
- ExcelWorksheet.IncorrectDurationFromOADate(0.25).Should().Be(new(1899, 12, 30, 6, 0, 0));
+public class TimeTest {
+ static TimeTest() {
+ Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
+ }
- ExcelWorksheet.IncorrectDurationFromOADate(0).Should().Be(new(1899, 12, 30, 0, 0, 0));
-
- ExcelWorksheet.IncorrectDurationFromOADate(-0.25).Should().Be(new(1899, 12, 29, 18, 0, 0));
- ExcelWorksheet.IncorrectDurationFromOADate(-0.5).Should().Be(new(1899, 12, 29, 12, 0, 0));
- ExcelWorksheet.IncorrectDurationFromOADate(-0.75).Should().Be(new(1899, 12, 29, 6, 0, 0));
- ExcelWorksheet.IncorrectDurationFromOADate(-1.75).Should().Be(new(1899, 12, 28, 6, 0, 0));
- ExcelWorksheet.IncorrectDurationFromOADate(-2.75).Should().Be(new(1899, 12, 27, 6, 0, 0));
- }
+ [TestMethod]
+ public void TestIncorrectDurationFromOaDate() {
+ ExcelWorksheet.IncorrectDurationFromOaDate(2.75).Should().Be(new(1900, 1, 1, 18, 0, 0));
+ ExcelWorksheet.IncorrectDurationFromOaDate(1.75).Should().Be(new(1899, 12, 31, 18, 0, 0));
+ ExcelWorksheet.IncorrectDurationFromOaDate(0.75).Should().Be(new(1899, 12, 30, 18, 0, 0));
+ ExcelWorksheet.IncorrectDurationFromOaDate(0.5).Should().Be(new(1899, 12, 30, 12, 0, 0));
+ ExcelWorksheet.IncorrectDurationFromOaDate(0.25).Should().Be(new(1899, 12, 30, 6, 0, 0));
- [TestMethod]
- public void TestDateParse()
- {
- var package = new ExcelPackage(new FileInfo(GetTestWorkbookPath("Times.xlsx")));
- var sheet = package.Workbook.Worksheets.First();
+ ExcelWorksheet.IncorrectDurationFromOaDate(0).Should().Be(new(1899, 12, 30, 0, 0, 0));
- sheet.Cells["B3"].Value.Should().Be(new DateTime(1899, 12, 30, 3, 15, 30));
- sheet.Cells["C3"].Value.Should().Be(new DateTime(1899, 12, 30, 3, 15, 0));
- sheet.Cells["D3"].Value.Should().Be(0.13541666666666666);
- sheet.Cells["E3"].Value.Should().Be(new DateTime(1899, 12, 30, 3, 15, 30));
- sheet.Cells["F3"].Value.Should().Be(0.13576388888888888);
- sheet.Cells["G3"].Value.Should().Be(0.13541666666666666);
- sheet.Cells["H3"].Value.Should().Be(new DateTime(1899, 12, 30, 3, 15, 30));
-
- sheet.Cells["B7"].Value.Should().Be(new DateTime(1899, 12, 30, 23, 59, 59));
- sheet.Cells["C7"].Value.Should().Be(new DateTime(1899, 12, 30, 23, 59, 0));
- sheet.Cells["D7"].Value.Should().Be(0.9993055555555556);
- sheet.Cells["E7"].Value.Should().Be(new DateTime(1899, 12, 30, 23, 59, 59));
- sheet.Cells["F7"].Value.Should().Be(0.999988425925926);
- sheet.Cells["G7"].Value.Should().Be(0.9993055555555556);
- sheet.Cells["H7"].Value.Should().Be(new DateTime(1899, 12, 30, 23, 59, 59));
- }
+ ExcelWorksheet.IncorrectDurationFromOaDate(-0.25).Should().Be(new(1899, 12, 29, 18, 0, 0));
+ ExcelWorksheet.IncorrectDurationFromOaDate(-0.5).Should().Be(new(1899, 12, 29, 12, 0, 0));
+ ExcelWorksheet.IncorrectDurationFromOaDate(-0.75).Should().Be(new(1899, 12, 29, 6, 0, 0));
+ ExcelWorksheet.IncorrectDurationFromOaDate(-1.75).Should().Be(new(1899, 12, 28, 6, 0, 0));
+ ExcelWorksheet.IncorrectDurationFromOaDate(-2.75).Should().Be(new(1899, 12, 27, 6, 0, 0));
+ }
- private static string GetTestWorkbookPath(string filename)
- {
- var assemblyPath = Path.GetDirectoryName(typeof(TimeTest).Assembly.Location)!;
- return Path.Combine(assemblyPath, "TestWorkbooks", filename);
- }
+ [TestMethod]
+ public void TestDateParse() {
+ var package = new ExcelPackage(new FileInfo(GetTestWorkbookPath("Times.xlsx")));
+ var sheet = package.Workbook.Worksheets.First();
+
+ sheet.Cells["B3"].Value.Should().Be(new DateTime(1899, 12, 30, 3, 15, 30));
+ sheet.Cells["C3"].Value.Should().Be(new DateTime(1899, 12, 30, 3, 15, 0));
+ sheet.Cells["D3"].Value.Should().Be(0.13541666666666666);
+ sheet.Cells["E3"].Value.Should().Be(new DateTime(1899, 12, 30, 3, 15, 30));
+ sheet.Cells["F3"].Value.Should().Be(0.13576388888888888);
+ sheet.Cells["G3"].Value.Should().Be(0.13541666666666666);
+ sheet.Cells["H3"].Value.Should().Be(new DateTime(1899, 12, 30, 3, 15, 30));
+
+ sheet.Cells["B7"].Value.Should().Be(new DateTime(1899, 12, 30, 23, 59, 59));
+ sheet.Cells["C7"].Value.Should().Be(new DateTime(1899, 12, 30, 23, 59, 0));
+ sheet.Cells["D7"].Value.Should().Be(0.9993055555555556);
+ sheet.Cells["E7"].Value.Should().Be(new DateTime(1899, 12, 30, 23, 59, 59));
+ sheet.Cells["F7"].Value.Should().Be(0.999988425925926);
+ sheet.Cells["G7"].Value.Should().Be(0.9993055555555556);
+ sheet.Cells["H7"].Value.Should().Be(new DateTime(1899, 12, 30, 23, 59, 59));
+ }
+
+ private static string GetTestWorkbookPath(string filename) {
+ var assemblyPath = Path.GetDirectoryName(typeof(TimeTest).Assembly.Location)!;
+ return Path.Combine(assemblyPath, "TestWorkbooks", filename);
+ }
}
diff --git a/dotnet-csharpier b/dotnet-csharpier
new file mode 100755
index 0000000..61b2200
--- /dev/null
+++ b/dotnet-csharpier
Binary files differ