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