| 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); | |
| } | |
| } | |
| } | |
| } |