public ValueEval Evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) { ValueEval arg3 = null; switch (args.Length) { case 4: arg3 = args[3]; // important: assumed array element Is never null break; case 3: break; default: // wrong number of arguments return(ErrorEval.VALUE_INVALID); } try { // Evaluation order: // arg0 lookup_value, arg1 table_array, arg3 range_lookup, Find lookup value, arg2 row_index, fetch result ValueEval lookupValue = OperandResolver.GetSingleValue(args[0], srcCellRow, srcCellCol); AreaEval tableArray = LookupUtils.ResolveTableArrayArg(args[1]); bool IsRangeLookup = LookupUtils.ResolveRangeLookupArg(arg3, srcCellRow, srcCellCol); int colIndex = LookupUtils.LookupIndexOfValue(lookupValue, LookupUtils.CreateRowVector(tableArray, 0), IsRangeLookup); int rowIndex = LookupUtils.ResolveRowOrColIndexArg(args[2], srcCellRow, srcCellCol); ValueVector resultCol = CreateResultColumnVector(tableArray, rowIndex); return(resultCol.GetItem(colIndex)); } catch (EvaluationException e) { return(e.GetErrorEval()); } }
/** * Returns one column from an <c>AreaEval</c> * * @(#VALUE!) if colIndex Is negative, (#REF!) if colIndex Is too high */ private ValueVector CreateResultColumnVector(AreaEval tableArray, int rowIndex) { if (rowIndex >= tableArray.Height) { throw EvaluationException.InvalidRef(); } return(LookupUtils.CreateRowVector(tableArray, rowIndex)); }
/** * Returns one column from an <c>AreaEval</c> * * @(#VALUE!) if colIndex Is negative, (#REF!) if colIndex Is too high */ private ValueVector CreateResultColumnVector(TwoDEval tableArray, int colIndex) { if (colIndex >= tableArray.Width) { throw EvaluationException.InvalidRef(); } return(LookupUtils.CreateColumnVector(tableArray, colIndex)); }
private static ValueVector CreateVector(AreaEval ae) { ValueVector result = LookupUtils.CreateVector(ae); if (result != null) { return(result); } // extra complexity required to emulate the way LOOKUP can handles these abnormal cases. throw new InvalidOperationException("non-vector lookup or result areas not supported yet"); }
private static LookupValueComparer CreateLookupComparer(ValueEval lookupValue, bool matchExact) { if (matchExact && lookupValue is StringEval) { String stringValue = ((StringEval)lookupValue).StringValue; if (IsLookupValueWild(stringValue)) { throw new Exception("Wildcard lookup values '" + stringValue + "' not supported yet"); } } return(LookupUtils.CreateLookupComparer(lookupValue)); }
public override ValueEval Evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, ValueEval arg2, ValueEval arg3) { try { // Evaluation order: // arg0 lookup_value, arg1 table_array, arg3 range_lookup, find lookup value, arg2 col_index, fetch result ValueEval lookupValue = OperandResolver.GetSingleValue(arg0, srcRowIndex, srcColumnIndex); TwoDEval tableArray = LookupUtils.ResolveTableArrayArg(arg1); bool isRangeLookup = LookupUtils.ResolveRangeLookupArg(arg3, srcRowIndex, srcColumnIndex); int rowIndex = LookupUtils.LookupIndexOfValue(lookupValue, LookupUtils.CreateColumnVector(tableArray, 0), isRangeLookup); int colIndex = LookupUtils.ResolveRowOrColIndexArg(arg2, srcRowIndex, srcColumnIndex); ValueVector resultCol = CreateResultColumnVector(tableArray, colIndex); return(resultCol.GetItem(rowIndex)); } catch (EvaluationException e) { return(e.GetErrorEval()); } }
public ValueEval Evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) { switch (args.Length) { case 3: break; case 2: // complex rules to choose lookupVector and resultVector from the single area ref throw new Exception("Two arg version of LOOKUP not supported yet"); default: return(ErrorEval.VALUE_INVALID); } try { ValueEval lookupValue = OperandResolver.GetSingleValue(args[0], srcCellRow, srcCellCol); AreaEval aeLookupVector = LookupUtils.ResolveTableArrayArg(args[1]); AreaEval aeResultVector = LookupUtils.ResolveTableArrayArg(args[2]); ValueVector lookupVector = CreateVector(aeLookupVector); ValueVector resultVector = CreateVector(aeResultVector); if (lookupVector.Size > resultVector.Size) { // Excel seems to handle this by accessing past the end of the result vector. throw new Exception("Lookup vector and result vector of differing sizes not supported yet"); } int index = LookupUtils.LookupIndexOfValue(lookupValue, lookupVector, true); return(resultVector.GetItem(index)); } catch (EvaluationException e) { return(e.GetErrorEval()); } }
private static ValueVector EvaluateLookupRange(ValueEval eval) { if (eval is RefEval) { RefEval re = (RefEval)eval; return(new SingleValueVector(re.InnerValueEval)); } if (eval is TwoDEval) { ValueVector result = LookupUtils.CreateVector((TwoDEval)eval); if (result == null) { throw new EvaluationException(ErrorEval.NA); } return(result); } // Error handling for lookup_range arg Is also Unusual if (eval is NumericValueEval) { throw new EvaluationException(ErrorEval.NA); } if (eval is StringEval) { StringEval se = (StringEval)eval; double d = OperandResolver.ParseDouble(se.StringValue); if (double.IsNaN(d)) { // plain string throw new EvaluationException(ErrorEval.VALUE_INVALID); } // else looks like a number throw new EvaluationException(ErrorEval.NA); } throw new Exception("Unexpected eval type (" + eval.GetType().Name + ")"); }