[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="&quot;&lt;&gt;">
-//  <x:formula>LEFT(A3,LEN("""&lt;&gt;"))="""&lt;&gt;"</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))&gt;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)&lt;=6,FLOOR(A1,1)&lt;=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)&gt;=(WEEKDAY(TODAY())),TODAY()-ROUNDDOWN(A1,0)&lt;(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()&gt;(7-WEEKDAY(TODAY())),ROUNDDOWN(A1,0)-TODAY()&lt;(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)&lt;=WEEKDAY(TODAY())-1,ROUNDDOWN(A1,0)-TODAY()&lt;=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&lt;eExcelconditionalFormatting3IconsSetType&gt;"/> to the range
-    /// </summary>
-    /// <param name="IconSet"></param>
-    /// <returns></returns>
-    IExcelConditionalFormattingThreeIconSet<eExcelconditionalFormatting3IconsSetType> AddThreeIconSet(eExcelconditionalFormatting3IconsSetType IconSet);
-    /// <summary>
-    /// Adds a <see cref="IExcelConditionalFormattingFourIconSet&lt;eExcelconditionalFormatting4IconsSetType&gt;"/> 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&lt;eExcelconditionalFormatting3IconsSetType&gt;"/> to the range
+  /// </summary>
+  /// <param name="iconSet"></param>
+  /// <returns></returns>
+  IExcelConditionalFormattingThreeIconSet<eExcelconditionalFormatting3IconsSetType> AddThreeIconSet(
+      eExcelconditionalFormatting3IconsSetType iconSet);
+
+  /// <summary>
+  /// Adds a <see cref="IExcelConditionalFormattingFourIconSet&lt;eExcelconditionalFormatting4IconsSetType&gt;"/> 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: &apos; &quot; &gt; &lt; &amp;)
-    /// </summary>
-    /// <param name="s"></param>
-    /// <returns></returns>
-    public static string EncodeXML(
-      this string s)
-    {
-      return s.Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;").Replace("\"", "&quot;").Replace("'", "&apos;");
-    }
-
-    /// <summary>
-    /// Decode from XML (special characteres: &apos; &quot; &gt; &lt; &amp;)
-    /// </summary>
-    /// <param name="s"></param>
-    /// <returns></returns>
-    public static string DecodeXML(
-      this string s)
-    {
-      return s.Replace("'", "&apos;").Replace("\"", "&quot;").Replace(">", "&gt;").Replace("<", "&lt;").Replace("&", "&amp;");
+  /// <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: &apos; &quot; &gt; &lt; &amp;)
+  /// </summary>
+  /// <param name="s"></param>
+  /// <returns></returns>
+  public static string EncodeXml(this string s) {
+    return s.Replace("&", "&amp;")
+        .Replace("<", "&lt;")
+        .Replace(">", "&gt;")
+        .Replace("\"", "&quot;")
+        .Replace("'", "&apos;");
+  }
+
+  /// <summary>
+  /// Decode from XML (special characteres: &apos; &quot; &gt; &lt; &amp;)
+  /// </summary>
+  /// <param name="s"></param>
+  /// <returns></returns>
+  public static string DecodeXml(this string s) {
+    return s.Replace("'", "&apos;")
+        .Replace("\"", "&quot;")
+        .Replace(">", "&gt;")
+        .Replace("<", "&lt;")
+        .Replace("&", "&amp;");
+  }
+}
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 &lt;cfRule&gt; 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 &lt;conditionalFormatting&gt; 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 &lt;cfRule&gt; 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 &lt;conditionalFormatting&gt; 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&lt;ExcelNamedRange&gt; 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&lt;ExcelNamedRange&gt; 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 = "&amp;24&amp;U&amp;\"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 = "&amp;24&amp;U&amp;\"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>&amp;U</term><description>Underlined</description></item>
+  /// <item><term>&amp;E</term><description>Double Underline</description></item>
+  /// <item><term>&amp;K:xxxxxx</term><description>Color. ex &amp;K:FF0000 for red</description></item>
+  /// <item><term>&amp;"Font,Regular Bold Italic"</term><description>Changes the font. Regular or Bold or Italic or Bold Italic can be used. ex &amp;"Arial,Bold Italic"</description></item>
+  /// <item><term>&amp;nn</term><description>Change font size. nn is an integer. ex &amp;24</description></item>
+  /// <item><term>&amp;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>&amp;U</term><description>Underlined</description></item>
-        /// <item><term>&amp;E</term><description>Double Underline</description></item>
-        /// <item><term>&amp;K:xxxxxx</term><description>Color. ex &amp;K:FF0000 for red</description></item>
-        /// <item><term>&amp;"Font,Regular Bold Italic"</term><description>Changes the font. Regular or Bold or Italic or Bold Italic can be used. ex &amp;"Arial,Bold Italic"</description></item>
-        /// <item><term>&amp;nn</term><description>Change font size. nn is an integer. ex &amp;24</description></item>
-        /// <item><term>&amp;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 &amp; 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  &apos; and &quot;, 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("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;");
-        }
-
-        /// <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 &amp; 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  &apos; and &quot;, 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("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;");
+  }
+
+  /// <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