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