blob: 02f57a91c51c37c7013a3d8f235637ecde5db959 [file] [log] [blame]
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);
}
}
}