| 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; |
| |
| public CountIf() |
| : this(new NumericExpressionEvaluator(), new 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); |
| } |
| } |
| } |