|  | /******************************************************************************* | 
|  | * You may amend and distribute as you like, but don't remove this header! | 
|  | * | 
|  | * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets. | 
|  | * See http://www.codeplex.com/EPPlus for details. | 
|  | * | 
|  | * Copyright (C) 2011  Jan Källman | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  |  | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 
|  | * See the GNU Lesser General Public License for more details. | 
|  | * | 
|  | * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php | 
|  | * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html | 
|  | * | 
|  | * All code and executables are provided "as is" with no warranty either express or implied. | 
|  | * The author accepts no liability for any damage or loss of business that this product may cause. | 
|  | * | 
|  | * Code change notes: | 
|  | * | 
|  | * Author					Change						                Date | 
|  | * ****************************************************************************** | 
|  | * Eyal Seagull		Conditional Formatting            2012-04-03 | 
|  | *******************************************************************************/ | 
|  |  | 
|  | using System; | 
|  | using System.Collections; | 
|  | using System.Collections.Generic; | 
|  | using System.Collections.Immutable; | 
|  | using System.Xml; | 
|  |  | 
|  | namespace AppsheetEpplus; | 
|  |  | 
|  | /// <summary> | 
|  | /// Collection of <see cref="ExcelConditionalFormattingRule"/>. | 
|  | /// This class is providing the API for EPPlus conditional formatting. | 
|  | /// </summary> | 
|  | /// <remarks> | 
|  | /// <para> | 
|  | /// The public methods of this class (Add[...]ConditionalFormatting) will create a ConditionalFormatting/CfRule entry in the worksheet. When this | 
|  | /// Conditional Formatting has been created changes to the properties will affect the workbook immediately. | 
|  | /// </para> | 
|  | /// <para> | 
|  | /// Each type of Conditional Formatting Rule has diferente set of properties. | 
|  | /// </para> | 
|  | /// <code> | 
|  | /// // Add a Three Color Scale conditional formatting | 
|  | /// var cf = worksheet.ConditionalFormatting.AddThreeColorScale(new ExcelAddress("A1:C10")); | 
|  | /// // Set the conditional formatting properties | 
|  | /// cf.LowValue.Type = ExcelConditionalFormattingValueObjectType.Min; | 
|  | /// cf.LowValue.Color = Color.White; | 
|  | /// cf.MiddleValue.Type = ExcelConditionalFormattingValueObjectType.Percent; | 
|  | /// cf.MiddleValue.Value = 50; | 
|  | /// cf.MiddleValue.Color = Color.Blue; | 
|  | /// cf.HighValue.Type = ExcelConditionalFormattingValueObjectType.Max; | 
|  | /// cf.HighValue.Color = Color.Black; | 
|  | /// </code> | 
|  | /// </remarks> | 
|  | public class ExcelConditionalFormattingCollection | 
|  | : XmlHelper, | 
|  | IEnumerable<IExcelConditionalFormattingRule> { | 
|  | private readonly List<IExcelConditionalFormattingRule> _rules = new(); | 
|  | private readonly ExcelWorksheet _worksheet; | 
|  |  | 
|  | protected override ImmutableArray<string> SchemaNodeOrder => | 
|  | ExcelWorksheet.WorksheetSchemaNodeOrder; | 
|  |  | 
|  | /// <summary> | 
|  | /// Initialize the <see cref="ExcelConditionalFormattingCollection"/> | 
|  | /// </summary> | 
|  | /// <param name="worksheet"></param> | 
|  | internal ExcelConditionalFormattingCollection(ExcelWorksheet worksheet) | 
|  | : base(worksheet.NameSpaceManager, worksheet.WorksheetXml.DocumentElement) { | 
|  | ArgumentNullException.ThrowIfNull(worksheet); | 
|  |  | 
|  | _worksheet = worksheet; | 
|  |  | 
|  | // Look for all the <conditionalFormatting> | 
|  | var conditionalFormattingNodes = TopNode.SelectNodes( | 
|  | "//" + ExcelConditionalFormattingConstants.Paths._conditionalFormatting, | 
|  | _worksheet.NameSpaceManager); | 
|  |  | 
|  | // Check if we found at least 1 node | 
|  | if ((conditionalFormattingNodes != null) && (conditionalFormattingNodes.Count > 0)) { | 
|  | // Foreach <conditionalFormatting> | 
|  | foreach (XmlNode conditionalFormattingNode in conditionalFormattingNodes) { | 
|  | // Check if @sqref attribute exists | 
|  | if (conditionalFormattingNode.Attributes[ExcelConditionalFormattingConstants | 
|  | .Attributes | 
|  | ._sqref] == null) { | 
|  | throw new(ExcelConditionalFormattingConstants.Errors._missingSqrefAttribute); | 
|  | } | 
|  |  | 
|  | // Get the @sqref attribute | 
|  | ExcelAddress address = new ExcelAddress( | 
|  | conditionalFormattingNode.Attributes[ExcelConditionalFormattingConstants | 
|  | .Attributes | 
|  | ._sqref].Value); | 
|  |  | 
|  | // Check for all the <cfRules> nodes and load them | 
|  | var cfRuleNodes = conditionalFormattingNode.SelectNodes( | 
|  | ExcelConditionalFormattingConstants.Paths._cfRule, | 
|  | _worksheet.NameSpaceManager); | 
|  |  | 
|  | // Foreach <cfRule> inside the current <conditionalFormatting> | 
|  | foreach (XmlNode cfRuleNode in cfRuleNodes) { | 
|  | // Check if @type attribute exists | 
|  | if (cfRuleNode.Attributes[ExcelConditionalFormattingConstants.Attributes._type] == null) { | 
|  | throw new(ExcelConditionalFormattingConstants.Errors._missingTypeAttribute); | 
|  | } | 
|  |  | 
|  | // Check if @priority attribute exists | 
|  | if (cfRuleNode.Attributes[ExcelConditionalFormattingConstants.Attributes._priority] | 
|  | == null) { | 
|  | throw new(ExcelConditionalFormattingConstants.Errors._missingPriorityAttribute); | 
|  | } | 
|  |  | 
|  | // Get the <cfRule> main attributes | 
|  | string typeAttribute = ExcelConditionalFormattingHelper.GetAttributeString( | 
|  | cfRuleNode, | 
|  | ExcelConditionalFormattingConstants.Attributes._type); | 
|  |  | 
|  | int priority = ExcelConditionalFormattingHelper.GetAttributeInt( | 
|  | cfRuleNode, | 
|  | ExcelConditionalFormattingConstants.Attributes._priority); | 
|  |  | 
|  | // Transform the @type attribute to EPPlus Rule Type (slighty diferente) | 
|  | var type = ExcelConditionalFormattingRuleType.GetTypeByAttrbiute( | 
|  | typeAttribute, | 
|  | cfRuleNode, | 
|  | _worksheet.NameSpaceManager); | 
|  |  | 
|  | // Create the Rule according to the correct type, address and priority | 
|  | var cfRule = ExcelConditionalFormattingRuleFactory.Create( | 
|  | type, | 
|  | address, | 
|  | priority, | 
|  | _worksheet, | 
|  | cfRuleNode); | 
|  |  | 
|  | // Add the new rule to the list | 
|  | if (cfRule != null) { | 
|  | _rules.Add(cfRule); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | private void EnsureRootElementExists() { | 
|  | // Find the <worksheet> node | 
|  | if (_worksheet.WorksheetXml.DocumentElement == null) { | 
|  | throw new(ExcelConditionalFormattingConstants.Errors._missingWorksheetNode); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Validates address - not empty (collisions are allowded) | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | private ExcelAddress ValidateAddress(ExcelAddress address) { | 
|  | ArgumentNullException.ThrowIfNull(address); | 
|  |  | 
|  | //TODO: Are there any other validation we need to do? | 
|  | return address; | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Get the next priority sequencial number | 
|  | /// </summary> | 
|  | /// <returns></returns> | 
|  | private int GetNextPriority() { | 
|  | // Consider zero as the last priority when we have no CF rules | 
|  | int lastPriority = 0; | 
|  |  | 
|  | // Search for the last priority | 
|  | foreach (var cfRule in _rules) { | 
|  | if (cfRule.Priority > lastPriority) { | 
|  | lastPriority = cfRule.Priority; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Our next priority is the last plus one | 
|  | return lastPriority + 1; | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Number of validations | 
|  | /// </summary> | 
|  | public int Count => _rules.Count; | 
|  |  | 
|  | /// <summary> | 
|  | /// Index operator, returns by 0-based index | 
|  | /// </summary> | 
|  | /// <param name="index"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingRule this[int index] { | 
|  | get => _rules[index]; | 
|  | set => _rules[index] = value; | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Get the 'cfRule' enumerator | 
|  | /// </summary> | 
|  | /// <returns></returns> | 
|  | IEnumerator<IExcelConditionalFormattingRule> IEnumerable<IExcelConditionalFormattingRule>.GetEnumerator() { | 
|  | return _rules.GetEnumerator(); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Get the 'cfRule' enumerator | 
|  | /// </summary> | 
|  | /// <returns></returns> | 
|  | IEnumerator IEnumerable.GetEnumerator() { | 
|  | return _rules.GetEnumerator(); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Removes all 'cfRule' from the collection and from the XML. | 
|  | /// <remarks> | 
|  | /// This is the same as removing all the 'conditionalFormatting' nodes. | 
|  | /// </remarks> | 
|  | /// </summary> | 
|  | public void RemoveAll() { | 
|  | // Look for all the <conditionalFormatting> nodes | 
|  | var conditionalFormattingNodes = TopNode.SelectNodes( | 
|  | "//" + ExcelConditionalFormattingConstants.Paths._conditionalFormatting, | 
|  | _worksheet.NameSpaceManager); | 
|  |  | 
|  | // Remove all the <conditionalFormatting> nodes one by one | 
|  | foreach (XmlNode conditionalFormattingNode in conditionalFormattingNodes) { | 
|  | conditionalFormattingNode.ParentNode.RemoveChild(conditionalFormattingNode); | 
|  | } | 
|  |  | 
|  | // Clear the <cfRule> item list | 
|  | _rules.Clear(); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Remove a Conditional Formatting Rule by its object | 
|  | /// </summary> | 
|  | /// <param name="item"></param> | 
|  | public void Remove(IExcelConditionalFormattingRule item) { | 
|  | ArgumentNullException.ThrowIfNull(item); | 
|  |  | 
|  | try { | 
|  | // Point to the parent node | 
|  | var oldParentNode = item.Node.ParentNode; | 
|  |  | 
|  | // Remove the <cfRule> from the old <conditionalFormatting> parent node | 
|  | oldParentNode.RemoveChild(item.Node); | 
|  |  | 
|  | // Check if the old <conditionalFormatting> parent node has <cfRule> node inside it | 
|  | if (!oldParentNode.HasChildNodes) { | 
|  | // Remove the old parent node | 
|  | oldParentNode.ParentNode.RemoveChild(oldParentNode); | 
|  | } | 
|  |  | 
|  | _rules.Remove(item); | 
|  | } catch { | 
|  | throw new(ExcelConditionalFormattingConstants.Errors._invalidRemoveRuleOperation); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Remove a Conditional Formatting Rule by its priority | 
|  | /// </summary> | 
|  | /// <param name="priority"></param> | 
|  | public void RemoveByPriority(int priority) { | 
|  | try { | 
|  | Remove(RulesByPriority(priority)); | 
|  | } catch {} | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Get a rule by its priority | 
|  | /// </summary> | 
|  | /// <param name="priority"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingRule RulesByPriority(int priority) { | 
|  | return _rules.Find(x => x.Priority == priority); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add rule (internal) | 
|  | /// </summary> | 
|  | /// <param name="type"></param> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns>F | 
|  | internal IExcelConditionalFormattingRule AddRule( | 
|  | eExcelConditionalFormattingRuleType type, | 
|  | ExcelAddress address) { | 
|  | ArgumentNullException.ThrowIfNull(address); | 
|  |  | 
|  | address = ValidateAddress(address); | 
|  | EnsureRootElementExists(); | 
|  |  | 
|  | // Create the Rule according to the correct type, address and priority | 
|  | IExcelConditionalFormattingRule cfRule = ExcelConditionalFormattingRuleFactory.Create( | 
|  | type, | 
|  | address, | 
|  | GetNextPriority(), | 
|  | _worksheet, | 
|  | null); | 
|  |  | 
|  | // Add the newly created rule to the list | 
|  | _rules.Add(cfRule); | 
|  |  | 
|  | // Return the newly created rule | 
|  | return cfRule; | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add AboveAverage Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingAverageGroup AddAboveAverage(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingAverageGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.AboveAverage, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add AboveOrEqualAverage Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingAverageGroup AddAboveOrEqualAverage(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingAverageGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.AboveOrEqualAverage, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add BelowAverage Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingAverageGroup AddBelowAverage(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingAverageGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.BelowAverage, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add BelowOrEqualAverage Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingAverageGroup AddBelowOrEqualAverage(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingAverageGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.BelowOrEqualAverage, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add AboveStdDev Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingStdDevGroup AddAboveStdDev(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingStdDevGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.AboveStdDev, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add BelowStdDev Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingStdDevGroup AddBelowStdDev(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingStdDevGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.BelowStdDev, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add Bottom Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingTopBottomGroup AddBottom(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingTopBottomGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.Bottom, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add BottomPercent Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingTopBottomGroup AddBottomPercent(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingTopBottomGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.BottomPercent, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add Top Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingTopBottomGroup AddTop(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingTopBottomGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.Top, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add TopPercent Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingTopBottomGroup AddTopPercent(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingTopBottomGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.TopPercent, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add Last7Days Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingTimePeriodGroup AddLast7Days(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingTimePeriodGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.Last7Days, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add LastMonth Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingTimePeriodGroup AddLastMonth(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingTimePeriodGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.LastMonth, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add LastWeek Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingTimePeriodGroup AddLastWeek(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingTimePeriodGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.LastWeek, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add NextMonth Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingTimePeriodGroup AddNextMonth(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingTimePeriodGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.NextMonth, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add NextWeek Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingTimePeriodGroup AddNextWeek(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingTimePeriodGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.NextWeek, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add ThisMonth Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingTimePeriodGroup AddThisMonth(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingTimePeriodGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.ThisMonth, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add ThisWeek Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingTimePeriodGroup AddThisWeek(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingTimePeriodGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.ThisWeek, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add Today Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingTimePeriodGroup AddToday(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingTimePeriodGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.Today, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add Tomorrow Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingTimePeriodGroup AddTomorrow(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingTimePeriodGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.Tomorrow, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add Yesterday Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingTimePeriodGroup AddYesterday(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingTimePeriodGroup)AddRule( | 
|  | eExcelConditionalFormattingRuleType.Yesterday, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add BeginsWith Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingBeginsWith AddBeginsWith(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingBeginsWith)AddRule( | 
|  | eExcelConditionalFormattingRuleType.BeginsWith, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add Between Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingBetween AddBetween(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingBetween)AddRule( | 
|  | eExcelConditionalFormattingRuleType.Between, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add ContainsBlanks Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingContainsBlanks AddContainsBlanks(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingContainsBlanks)AddRule( | 
|  | eExcelConditionalFormattingRuleType.ContainsBlanks, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add ContainsErrors Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingContainsErrors AddContainsErrors(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingContainsErrors)AddRule( | 
|  | eExcelConditionalFormattingRuleType.ContainsErrors, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add ContainsText Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingContainsText AddContainsText(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingContainsText)AddRule( | 
|  | eExcelConditionalFormattingRuleType.ContainsText, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add DuplicateValues Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingDuplicateValues AddDuplicateValues(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingDuplicateValues)AddRule( | 
|  | eExcelConditionalFormattingRuleType.DuplicateValues, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add EndsWith Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingEndsWith AddEndsWith(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingEndsWith)AddRule( | 
|  | eExcelConditionalFormattingRuleType.EndsWith, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add Equal Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingEqual AddEqual(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingEqual)AddRule( | 
|  | eExcelConditionalFormattingRuleType.Equal, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add Expression Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingExpression AddExpression(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingExpression)AddRule( | 
|  | eExcelConditionalFormattingRuleType.Expression, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add GreaterThan Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingGreaterThan AddGreaterThan(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingGreaterThan)AddRule( | 
|  | eExcelConditionalFormattingRuleType.GreaterThan, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add GreaterThanOrEqual Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingGreaterThanOrEqual AddGreaterThanOrEqual(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingGreaterThanOrEqual)AddRule( | 
|  | eExcelConditionalFormattingRuleType.GreaterThanOrEqual, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add LessThan Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingLessThan AddLessThan(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingLessThan)AddRule( | 
|  | eExcelConditionalFormattingRuleType.LessThan, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add LessThanOrEqual Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingLessThanOrEqual AddLessThanOrEqual(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingLessThanOrEqual)AddRule( | 
|  | eExcelConditionalFormattingRuleType.LessThanOrEqual, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add NotBetween Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingNotBetween AddNotBetween(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingNotBetween)AddRule( | 
|  | eExcelConditionalFormattingRuleType.NotBetween, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add NotContainsBlanks Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingNotContainsBlanks AddNotContainsBlanks(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingNotContainsBlanks)AddRule( | 
|  | eExcelConditionalFormattingRuleType.NotContainsBlanks, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add NotContainsErrors Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingNotContainsErrors AddNotContainsErrors(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingNotContainsErrors)AddRule( | 
|  | eExcelConditionalFormattingRuleType.NotContainsErrors, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add NotContainsText Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingNotContainsText AddNotContainsText(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingNotContainsText)AddRule( | 
|  | eExcelConditionalFormattingRuleType.NotContainsText, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add NotEqual Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingNotEqual AddNotEqual(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingNotEqual)AddRule( | 
|  | eExcelConditionalFormattingRuleType.NotEqual, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add Unique Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingUniqueValues AddUniqueValues(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingUniqueValues)AddRule( | 
|  | eExcelConditionalFormattingRuleType.UniqueValues, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add ThreeColorScale Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingThreeColorScale AddThreeColorScale(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingThreeColorScale)AddRule( | 
|  | eExcelConditionalFormattingRuleType.ThreeColorScale, | 
|  | address); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Add TwoColorScale Rule | 
|  | /// </summary> | 
|  | /// <param name="address"></param> | 
|  | /// <returns></returns> | 
|  | public IExcelConditionalFormattingTwoColorScale AddTwoColorScale(ExcelAddress address) { | 
|  | return (IExcelConditionalFormattingTwoColorScale)AddRule( | 
|  | eExcelConditionalFormattingRuleType.TwoColorScale, | 
|  | address); | 
|  | } | 
|  | } |