@ -38,11 +38,13 @@ Value func_areas (valVector args, ValueCalc *calc, FuncExtra *);
Value func_choose ( valVector args , ValueCalc * calc , FuncExtra * ) ;
Value func_choose ( valVector args , ValueCalc * calc , FuncExtra * ) ;
Value func_column ( valVector args , ValueCalc * calc , FuncExtra * ) ;
Value func_column ( valVector args , ValueCalc * calc , FuncExtra * ) ;
Value func_columns ( 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_index ( valVector args , ValueCalc * calc , FuncExtra * ) ;
Value func_indirect ( valVector args , ValueCalc * calc , FuncExtra * ) ;
Value func_indirect ( valVector args , ValueCalc * calc , FuncExtra * ) ;
Value func_lookup ( valVector args , ValueCalc * calc , FuncExtra * ) ;
Value func_lookup ( valVector args , ValueCalc * calc , FuncExtra * ) ;
Value func_row ( valVector args , ValueCalc * calc , FuncExtra * ) ;
Value func_row ( valVector args , ValueCalc * calc , FuncExtra * ) ;
Value func_rows ( 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
// registers all reference functions
void RegisterReferenceFunctions ( )
void RegisterReferenceFunctions ( )
@ -69,6 +71,10 @@ void RegisterReferenceFunctions()
f - > setAcceptArray ( ) ;
f - > setAcceptArray ( ) ;
f - > setNeedsExtra ( true ) ;
f - > setNeedsExtra ( true ) ;
repo - > add ( f ) ;
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 = new Function ( " INDEX " , func_index ) ;
f - > setParamCount ( 3 ) ;
f - > setParamCount ( 3 ) ;
f - > setAcceptArray ( ) ;
f - > setAcceptArray ( ) ;
@ -89,6 +95,10 @@ void RegisterReferenceFunctions()
f - > setAcceptArray ( ) ;
f - > setAcceptArray ( ) ;
f - > setNeedsExtra ( true ) ;
f - > setNeedsExtra ( true ) ;
repo - > add ( f ) ;
repo - > add ( f ) ;
f = new Function ( " VLOOKUP " , func_vlookup ) ;
f - > setParamCount ( 3 , 4 ) ;
f - > setAcceptArray ( ) ;
repo - > add ( f ) ;
}
}
// Function: ADDRESS
// Function: ADDRESS
@ -225,6 +235,36 @@ Value func_choose (valVector args, ValueCalc *calc, FuncExtra *)
return args [ num ] ;
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
// Function: INDEX
Value func_index ( valVector args , ValueCalc * calc , FuncExtra * )
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
// 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
// element. In any case, this function can assume that the given value
// is the same. Because it is.
// is the same. Because it is.
Value val = args [ 0 ] ;
Value val = args [ 0 ] ;
unsigned row = calc - > conv ( ) - > asInteger ( args [ 1 ] ) . asInteger ( ) - 1 ;
unsigned row = calc - > conv ( ) - > asInteger ( args [ 1 ] ) . asInteger ( ) - 1 ;
unsigned col = calc - > conv ( ) - > asInteger ( args [ 2 ] ) . 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 ( ) ;
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 ;
}