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