Commit 88d90f6e authored by Michael Meeks's avatar Michael Meeks

Fix warning in func.h,

Excel Array support re-enabled.
'LOOKUP' implemented.
parent 4ffb0319
1999-05-13 Michael Meeks <michael@imaginator.com>
* src/expr.c (value_area_get_at_x_y): Added warning
in safety case.
* src/fn-lookup.c (gnumeric_lookup): Implemented.
* src/func.h: Updated critera_test_fun_t: returns int,
should really be gboolean ?
* src/expr.h: Added prototype & indentation beautified.
* src/expr.c (value_array_set): Helper function added.
1999-05-13 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-math.c: Added GCD().
......
1999-05-13 Michael Meeks <michael@imaginator.com>
* src/expr.c (value_area_get_at_x_y): Added warning
in safety case.
* src/fn-lookup.c (gnumeric_lookup): Implemented.
* src/func.h: Updated critera_test_fun_t: returns int,
should really be gboolean ?
* src/expr.h: Added prototype & indentation beautified.
* src/expr.c (value_array_set): Helper function added.
1999-05-13 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-math.c: Added GCD().
......
1999-05-13 Michael Meeks <michael@imaginator.com>
* src/expr.c (value_area_get_at_x_y): Added warning
in safety case.
* src/fn-lookup.c (gnumeric_lookup): Implemented.
* src/func.h: Updated critera_test_fun_t: returns int,
should really be gboolean ?
* src/expr.h: Added prototype & indentation beautified.
* src/expr.c (value_array_set): Helper function added.
1999-05-13 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-math.c: Added GCD().
......
1999-05-13 Michael Meeks <michael@imaginator.com>
* src/expr.c (value_area_get_at_x_y): Added warning
in safety case.
* src/fn-lookup.c (gnumeric_lookup): Implemented.
* src/func.h: Updated critera_test_fun_t: returns int,
should really be gboolean ?
* src/expr.h: Added prototype & indentation beautified.
* src/expr.c (value_array_set): Helper function added.
1999-05-13 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-math.c: Added GCD().
......
1999-05-13 Michael Meeks <michael@imaginator.com>
* ms-formula.c (ms_excel_parse_formula): Updated Array support.
* ms-excel.c (ms_excel_set_cell_colors): Kills colors where
backgnd & foregnd are same, needs pattern stuff to work
before it can be fixed.
......
......@@ -824,37 +824,36 @@ ms_excel_parse_formula (MS_EXCEL_SHEET *sheet, guint8 *mem,
guint16 lpx,lpy;
guint8 *data=cur+3;
if (cols==0) cols=256;
v = value_array_new (cols, rows);
ptg_length = 3;
printf ("An Array how interesting: (%d,%d)\n", cols, rows);
dump (mem, length);
#ifdef 0
for (lpy=0;lpy<rows;lpy++) {
for (lpx=0;lpx<cols;lpx++) {
guint8 opts=BIFF_GETBYTE(data);
if (opts == 1) {
g_string_sprintfa (ans, MS_EXCEL_DOUBLE_FORMAT,
BIFF_GETDOUBLE(data+1));
value_array_set (v, lpx, lpy,
value_float (BIFF_GETDOUBLE(data+1)));
data+=9;
ptg_length+=9;
} else if (opts == 2) {
guint32 len;
g_string_append (ans, biff_get_text (data+2,
BIFF_GETBYTE(data+1),
&len));
g_string_append (ans, ",");
char *str = biff_get_text (data+2,
BIFF_GETBYTE(data+1),
&len);
value_array_set (v, lpx, lpy, value_str(str));
g_free (str);
data+=len+2;
ptg_length+=2+len;
} else {
printf ("Duff type\n");
break;
}
g_string_append (ans, ";");
}
}
#endif
ptg_length+=7;
parse_list_push_raw (&stack, v);
break;
}
......
......@@ -824,37 +824,36 @@ ms_excel_parse_formula (MS_EXCEL_SHEET *sheet, guint8 *mem,
guint16 lpx,lpy;
guint8 *data=cur+3;
if (cols==0) cols=256;
v = value_array_new (cols, rows);
ptg_length = 3;
printf ("An Array how interesting: (%d,%d)\n", cols, rows);
dump (mem, length);
#ifdef 0
for (lpy=0;lpy<rows;lpy++) {
for (lpx=0;lpx<cols;lpx++) {
guint8 opts=BIFF_GETBYTE(data);
if (opts == 1) {
g_string_sprintfa (ans, MS_EXCEL_DOUBLE_FORMAT,
BIFF_GETDOUBLE(data+1));
value_array_set (v, lpx, lpy,
value_float (BIFF_GETDOUBLE(data+1)));
data+=9;
ptg_length+=9;
} else if (opts == 2) {
guint32 len;
g_string_append (ans, biff_get_text (data+2,
BIFF_GETBYTE(data+1),
&len));
g_string_append (ans, ",");
char *str = biff_get_text (data+2,
BIFF_GETBYTE(data+1),
&len);
value_array_set (v, lpx, lpy, value_str(str));
g_free (str);
data+=len+2;
ptg_length+=2+len;
} else {
printf ("Duff type\n");
break;
}
g_string_append (ans, ";");
}
}
#endif
ptg_length+=7;
parse_list_push_raw (&stack, v);
break;
}
......
......@@ -295,6 +295,104 @@ gnumeric_hlookup (struct FunctionDefinition *i, Value *argv [], char **error_str
return NULL;
}
static char *help_lookup = {
N_("@FUNCTION=LOOKUP\n"
"@SYNTAX=LOOKUP(value,vector1,vector2)\n"
"@DESCRIPTION="
"The LOOKUP function finds the row index of 'value' in vector1 and returns "
"the contents of value2 at that row index."
"If the area is longer than it is wide then the sense of the search is rotated. "
"Alternatively a single array can be used."
"\n"
"If LOOKUP can't find value it uses the next largest value less than value."
"The data must be sorted"
"\n"
"If value is smaller than the first value it returns #N/A"
"\n"
"@SEEALSO=VLOOKUP,HLOOKUP")
};
/* Not very efficient ! */
static Value *
gnumeric_lookup (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
Value *v1, *ans;
int height, width;
const Value *next_largest = NULL;
int next_largest_x = 0;
int next_largest_y = 0;
height = value_area_get_height (argv[1]);
width = value_area_get_width (argv[1]);
if ((argv[1]->type == VALUE_ARRAY)) {
if (argv[2]) {
*error_string = _("Type Mismatch");
return NULL;
}
} else if (argv[1]->type == VALUE_CELLRANGE) {
if (!argv[2]) {
*error_string = _("Invalid number of arguments");
return NULL;
}
} else {
*error_string = _("Type Mismatch");
return NULL;
}
{
Value *src, *dest;
int x_offset=0, y_offset=0, lpx, lpy, maxx, maxy;
int tmp, compare, touched;
if (argv[1]->type == VALUE_ARRAY) {
src = dest = argv[1];
if (width>height)
y_offset = 1;
else
x_offset = 1;
} else {
src = argv[1];
dest = argv[2];
}
maxy = value_area_get_height (src);
maxx = value_area_get_width (dest);
if ((tmp=value_area_get_height (src))<maxy)
maxy=tmp;
if ((tmp=value_area_get_width (src))<maxx)
maxx=tmp;
touched = 0;
for (lpx=0,lpy=0;lpx<maxx && lpy<maxy;) {
const Value *v = value_area_get_at_x_y (src, lpx, lpy);
compare = lookup_similar (v, argv[0], next_largest, 1);
if (compare == 1)
return value_duplicate (value_area_get_at_x_y (dest, next_largest_x+x_offset,
next_largest_y+y_offset));
if (compare < 0) {
next_largest = v;
next_largest_x = lpx;
next_largest_y = lpy;
} else
break;
if (width>height)
lpx++;
else
lpy++;
}
if (!next_largest) {
*error_string = _("#N/A");
return NULL;
}
return value_duplicate (value_area_get_at_x_y (dest, next_largest_x+x_offset,
next_largest_y+y_offset));
}
}
static char *help_column = {
N_("@FUNCTION=COLUMN\n"
"@SYNTAX=COLUMN([reference])\n"
......@@ -463,6 +561,7 @@ FunctionDefinition lookup_functions [] = {
{ "column", "?", "ref", &help_column, gnumeric_column, NULL },
{ "columns", "A", "ref", &help_column, NULL, gnumeric_columns },
{ "hlookup", "?Af|b","val,range,col_idx,approx", &help_hlookup, NULL, gnumeric_hlookup },
{ "lookup", "?A|r", "val,range,range", &help_lookup, NULL, gnumeric_lookup },
{ "offset", "rffff","ref,row,col,hight,width", &help_offset, NULL, gnumeric_offset },
{ "row", "?", "ref", &help_row, gnumeric_row, NULL },
{ "rows", "A", "ref", &help_rows, NULL, gnumeric_rows },
......
......@@ -393,6 +393,7 @@ value_get_as_int (const Value *v)
g_warning ("value_get_as_int unknown type\n");
break;
}
return 0.0;
}
Value *
......@@ -417,6 +418,19 @@ value_array_new (guint width, guint height)
return v;
}
void
value_array_set (Value *array, guint col, guint row, Value *v)
{
g_return_if_fail (v);
g_return_if_fail (v->type == VALUE_ARRAY);
g_return_if_fail (col>=0);
g_return_if_fail (row>=0);
g_return_if_fail (v->v.array.y <= row);
g_return_if_fail (v->v.array.x <= col);
memcpy (&array->v.array.vals[col][row], v, sizeof (Value));
}
void
value_array_resize (Value *v, guint width, guint height)
{
......@@ -533,9 +547,9 @@ value_area_get_at_x_y (Value *v, guint x, guint y)
if (cell && cell->value)
return cell->value;
else
return value_int (0);
}
g_warning ("Leaked on array\n");
return value_int (0);
}
......
......@@ -179,12 +179,12 @@ Value *eval_expr (Sheet *sheet, ExprTree *tree,
int col, int row,
char **error_string);
void value_release (Value *value);
Value *value_cast_to_float (Value *v);
int value_get_bool (const Value *v, int *err);
float_t value_get_as_double (const Value *v);
int value_get_as_int (const Value *v);
void value_copy_to (Value *dest, const Value *source);
void value_release (Value *value);
Value *value_cast_to_float (Value *v);
int value_get_bool (const Value *v, int *err);
float_t value_get_as_double (const Value *v);
int value_get_as_int (const Value *v);
void value_copy_to (Value *dest, const Value *source);
/* Area functions ( works on VALUE_RANGE or VALUE_ARRAY */
guint value_area_get_width (Value *v);
......@@ -192,21 +192,22 @@ guint value_area_get_height (Value *v);
const Value *value_area_get_at_x_y (Value *v, guint x, guint y);
Value *value_array_new (guint width, guint height);
void value_array_set (Value *array, guint col, guint row, Value *v);
void value_array_resize (Value *v, guint width, guint height);
void value_array_copy_to (Value *dest, const Value *src);
Value *value_cellrange (const CellRef *a, const CellRef *b);
void value_dump (Value *value);
char *value_string (const Value *value);
Value *value_duplicate (const Value *value);
void value_dump (Value *value);
char *value_string (const Value *value);
Value *value_duplicate (const Value *value);
Value *value_float (float_t f);
Value *value_int (int i);
Value *value_str (const char *str);
Value *value_float (float_t f);
Value *value_int (int i);
Value *value_str (const char *str);
/* Setup of the symbol table */
void functions_init (void);
void constants_init (void);
void functions_init (void);
void constants_init (void);
#endif /* GNUMERIC_EXPR_H */
......@@ -295,6 +295,104 @@ gnumeric_hlookup (struct FunctionDefinition *i, Value *argv [], char **error_str
return NULL;
}
static char *help_lookup = {
N_("@FUNCTION=LOOKUP\n"
"@SYNTAX=LOOKUP(value,vector1,vector2)\n"
"@DESCRIPTION="
"The LOOKUP function finds the row index of 'value' in vector1 and returns "
"the contents of value2 at that row index."
"If the area is longer than it is wide then the sense of the search is rotated. "
"Alternatively a single array can be used."
"\n"
"If LOOKUP can't find value it uses the next largest value less than value."
"The data must be sorted"
"\n"
"If value is smaller than the first value it returns #N/A"
"\n"
"@SEEALSO=VLOOKUP,HLOOKUP")
};
/* Not very efficient ! */
static Value *
gnumeric_lookup (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
Value *v1, *ans;
int height, width;
const Value *next_largest = NULL;
int next_largest_x = 0;
int next_largest_y = 0;
height = value_area_get_height (argv[1]);
width = value_area_get_width (argv[1]);
if ((argv[1]->type == VALUE_ARRAY)) {
if (argv[2]) {
*error_string = _("Type Mismatch");
return NULL;
}
} else if (argv[1]->type == VALUE_CELLRANGE) {
if (!argv[2]) {
*error_string = _("Invalid number of arguments");
return NULL;
}
} else {
*error_string = _("Type Mismatch");
return NULL;
}
{
Value *src, *dest;
int x_offset=0, y_offset=0, lpx, lpy, maxx, maxy;
int tmp, compare, touched;
if (argv[1]->type == VALUE_ARRAY) {
src = dest = argv[1];
if (width>height)
y_offset = 1;
else
x_offset = 1;
} else {
src = argv[1];
dest = argv[2];
}
maxy = value_area_get_height (src);
maxx = value_area_get_width (dest);
if ((tmp=value_area_get_height (src))<maxy)
maxy=tmp;
if ((tmp=value_area_get_width (src))<maxx)
maxx=tmp;
touched = 0;
for (lpx=0,lpy=0;lpx<maxx && lpy<maxy;) {
const Value *v = value_area_get_at_x_y (src, lpx, lpy);
compare = lookup_similar (v, argv[0], next_largest, 1);
if (compare == 1)
return value_duplicate (value_area_get_at_x_y (dest, next_largest_x+x_offset,
next_largest_y+y_offset));
if (compare < 0) {
next_largest = v;
next_largest_x = lpx;
next_largest_y = lpy;
} else
break;
if (width>height)
lpx++;
else
lpy++;
}
if (!next_largest) {
*error_string = _("#N/A");
return NULL;
}
return value_duplicate (value_area_get_at_x_y (dest, next_largest_x+x_offset,
next_largest_y+y_offset));
}
}
static char *help_column = {
N_("@FUNCTION=COLUMN\n"
"@SYNTAX=COLUMN([reference])\n"
......@@ -463,6 +561,7 @@ FunctionDefinition lookup_functions [] = {
{ "column", "?", "ref", &help_column, gnumeric_column, NULL },
{ "columns", "A", "ref", &help_column, NULL, gnumeric_columns },
{ "hlookup", "?Af|b","val,range,col_idx,approx", &help_hlookup, NULL, gnumeric_hlookup },
{ "lookup", "?A|r", "val,range,range", &help_lookup, NULL, gnumeric_lookup },
{ "offset", "rffff","ref,row,col,hight,width", &help_offset, NULL, gnumeric_offset },
{ "row", "?", "ref", &help_row, gnumeric_row, NULL },
{ "rows", "A", "ref", &help_rows, NULL, gnumeric_rows },
......
......@@ -114,7 +114,7 @@ Value *gnumeric_sum (Sheet *sheet, GList *expr_node_list,
* This includes the database functions and some mathematical functions
* like COUNTIF, SUMIF...
*/
typedef (*criteria_test_fun_t) (Value *x, Value *y);
typedef int (*criteria_test_fun_t) (Value *x, Value *y);
typedef struct {
criteria_test_fun_t fun;
......
......@@ -295,6 +295,104 @@ gnumeric_hlookup (struct FunctionDefinition *i, Value *argv [], char **error_str
return NULL;
}
static char *help_lookup = {
N_("@FUNCTION=LOOKUP\n"
"@SYNTAX=LOOKUP(value,vector1,vector2)\n"
"@DESCRIPTION="
"The LOOKUP function finds the row index of 'value' in vector1 and returns "
"the contents of value2 at that row index."
"If the area is longer than it is wide then the sense of the search is rotated. "
"Alternatively a single array can be used."
"\n"
"If LOOKUP can't find value it uses the next largest value less than value."
"The data must be sorted"
"\n"
"If value is smaller than the first value it returns #N/A"
"\n"
"@SEEALSO=VLOOKUP,HLOOKUP")
};
/* Not very efficient ! */
static Value *
gnumeric_lookup (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
Value *v1, *ans;
int height, width;
const Value *next_largest = NULL;
int next_largest_x = 0;
int next_largest_y = 0;
height = value_area_get_height (argv[1]);
width = value_area_get_width (argv[1]);
if ((argv[1]->type == VALUE_ARRAY)) {
if (argv[2]) {
*error_string = _("Type Mismatch");
return NULL;
}
} else if (argv[1]->type == VALUE_CELLRANGE) {
if (!argv[2]) {
*error_string = _("Invalid number of arguments");
return NULL;
}
} else {
*error_string = _("Type Mismatch");
return NULL;
}
{
Value *src, *dest;
int x_offset=0, y_offset=0, lpx, lpy, maxx, maxy;
int tmp, compare, touched;
if (argv[1]->type == VALUE_ARRAY) {
src = dest = argv[1];
if (width>height)
y_offset = 1;
else
x_offset = 1;
} else {
src = argv[1];
dest = argv[2];
}
maxy = value_area_get_height (src);
maxx = value_area_get_width (dest);
if ((tmp=value_area_get_height (src))<maxy)
maxy=tmp;
if ((tmp=value_area_get_width (src))<maxx)
maxx=tmp;
touched = 0;
for (lpx=0,lpy=0;lpx<maxx && lpy<maxy;) {
const Value *v = value_area_get_at_x_y (src, lpx, lpy);
compare = lookup_similar (v, argv[0], next_largest, 1);
if (compare == 1)
return value_duplicate (value_area_get_at_x_y (dest, next_largest_x+x_offset,
next_largest_y+y_offset));
if (compare < 0) {
next_largest = v;
next_largest_x = lpx;
next_largest_y = lpy;
} else
break;
if (width>height)
lpx++;
else
lpy++;
}
if (!next_largest) {
*error_string = _("#N/A");
return NULL;
}
return value_duplicate (value_area_get_at_x_y (dest, next_largest_x+x_offset,
next_largest_y+y_offset));
}
}
static char *help_column = {
N_("@FUNCTION=COLUMN\n"
"@SYNTAX=COLUMN([reference])\n"
......@@ -463,6 +561,7 @@ FunctionDefinition lookup_functions [] = {
{ "column", "?", "ref", &help_column, gnumeric_column, NULL },
{ "columns", "A", "ref", &help_column, NULL, gnumeric_columns },
{ "hlookup", "?Af|b","val,range,col_idx,approx", &help_hlookup, NULL, gnumeric_hlookup },
{ "lookup", "?A|r", "val,range,range", &help_lookup, NULL, gnumeric_lookup },
{ "offset", "rffff","ref,row,col,hight,width", &help_offset, NULL, gnumeric_offset },
{ "row", "?", "ref", &help_row, gnumeric_row, NULL },
{ "rows", "A", "ref", &help_rows, NULL, gnumeric_rows },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment