diff options
Diffstat (limited to 'kspread/kspread_functions_reference.cpp')
| -rw-r--r-- | kspread/kspread_functions_reference.cpp | 71 | 
1 files changed, 70 insertions, 1 deletions
| diff --git a/kspread/kspread_functions_reference.cpp b/kspread/kspread_functions_reference.cpp index 7dacb0548..1c9c5216f 100644 --- a/kspread/kspread_functions_reference.cpp +++ b/kspread/kspread_functions_reference.cpp @@ -38,11 +38,13 @@ Value func_areas (valVector args, ValueCalc *calc, FuncExtra *);  Value func_choose (valVector args, ValueCalc *calc, FuncExtra *);  Value func_column (valVector args, ValueCalc *calc, FuncExtra *);  Value func_columns (valVector args, ValueCalc *calc, FuncExtra *); +Value func_hlookup (valVector args, ValueCalc *calc, FuncExtra *);  Value func_index (valVector args, ValueCalc *calc, FuncExtra *);  Value func_indirect (valVector args, ValueCalc *calc, FuncExtra *);  Value func_lookup (valVector args, ValueCalc *calc, FuncExtra *);  Value func_row (valVector args, ValueCalc *calc, FuncExtra *);  Value func_rows (valVector args, ValueCalc *calc, FuncExtra *); +Value func_vlookup (valVector args, ValueCalc *calc, FuncExtra *);  // registers all reference functions  void RegisterReferenceFunctions() @@ -69,6 +71,10 @@ void RegisterReferenceFunctions()    f->setAcceptArray ();    f->setNeedsExtra (true);    repo->add (f); +  f = new Function ("HLOOKUP",  func_hlookup); +  f->setParamCount (3, 4); +  f->setAcceptArray (); +  repo->add (f);    f = new Function ("INDEX",   func_index);    f->setParamCount (3);    f->setAcceptArray (); @@ -89,6 +95,10 @@ void RegisterReferenceFunctions()    f->setAcceptArray ();    f->setNeedsExtra (true);    repo->add (f); +  f = new Function ("VLOOKUP",  func_vlookup); +  f->setParamCount (3, 4); +  f->setAcceptArray (); +  repo->add (f);  }  // Function: ADDRESS @@ -225,6 +235,36 @@ Value func_choose (valVector args, ValueCalc *calc, FuncExtra *)    return args[num];  } +// Function: HLOOKUP +Value func_hlookup (valVector args, ValueCalc *calc, FuncExtra *) +{ +  const Value key = args[0]; +  const Value data = args[1]; +  const int row = calc->conv()->asInteger( args[2] ).asInteger(); +  const int cols = data.columns(); +  const int rows = data.rows(); +  if ( row < 1 || row > rows ) +      return Value::errorVALUE(); +  const bool rangeLookup = ( args.count() > 3 ) ? calc->conv()->asBoolean( args[3] ).asBoolean() : true; + +  // now traverse the array and perform comparison +  Value r; +  Value v = Value::errorNA(); +  for (int col = 0; col < cols; ++col) { +    // search in the first row +    const Value le = data.element(col, 0); +    if (calc->naturalEqual(key, le)) { +      return data.element(col, row - 1); +    } +    // optionally look for the next largest value that is less than key +    if (rangeLookup && calc->naturalLower(le, key) && calc->naturalLower(r, le)) { +      r = le; +      v = data.element(col, row - 1); +    } +  } +  return v; +} +  // Function: INDEX  Value func_index (valVector args, ValueCalc *calc, FuncExtra *)  { @@ -232,7 +272,7 @@ Value func_index (valVector args, ValueCalc *calc, FuncExtra *)    // value, or a single cell containing an array - then we return the array    // element. In any case, this function can assume that the given value    // is the same. Because it is. -   +    Value val = args[0];    unsigned row = calc->conv()->asInteger (args[1]).asInteger() - 1;    unsigned col = calc->conv()->asInteger (args[2]).asInteger() - 1; @@ -340,3 +380,32 @@ Value func_indirect (valVector args, ValueCalc *calc, FuncExtra *e)    return Value::errorVALUE();  } +// Function: VLOOKUP +Value func_vlookup (valVector args, ValueCalc *calc, FuncExtra *) +{ +  const Value key = args[0]; +  const Value data = args[1]; +  const int col = calc->conv()->asInteger(args[2]).asInteger(); +  const int cols = data.columns(); +  const int rows = data.rows(); +  if (col < 1 || col > cols) +    return Value::errorVALUE(); +  const bool rangeLookup = (args.count() > 3) ? calc->conv()->asBoolean(args[3]).asBoolean() : true; + +  // now traverse the array and perform comparison +  Value r; +  Value v = Value::errorNA(); +  for (int row = 0; row < rows; ++row) { +    // search in the first column +    const Value le = data.element(0, row); +    if (calc->naturalEqual(key, le)) { +      return data.element(col - 1, row); +    } +    // optionally look for the next largest value that is less than key +    if (rangeLookup && calc->naturalLower(le, key) && calc->naturalLower(r, le)) { +      r = le; +      v = data.element(col - 1, row); +    } +  } +  return v; +} | 
