Commit c871a37b authored by Jody Goldberg's avatar Jody Goldberg Committed by Jody Goldberg

finish TABLE importer. finish TABLE exporter.


2005-09-06  Jody Goldberg <jody@gnome.org>

	* ms-excel-read.c (excel_formula_shared) : finish TABLE importer.
	* ms-excel-write.c (excel_write_FORMULA) : finish TABLE exporter.

2005-09-05  Jody Goldberg <jody@gnome.org>

	* src/expr.c (gnm_expr_is_data_table) : move this out of the xls
	  plugin.
parent 429a6295
......@@ -6,6 +6,8 @@ Jody:
* Check all format tuples for a match [#85950]
* Escape cancels object drag. [#314866]
* F2 while editing jumps focus to entry. [#314869]
* XLS in/out for Data -> Table
* 2d Data -> Table support
Morten:
* Fix tooltip problem. [#314865]
......
2005-09-06 Jody Goldberg <jody@gnome.org>
* ms-excel-read.c (excel_formula_shared) : finish TABLE importer.
* ms-excel-write.c (excel_write_FORMULA) : finish TABLE exporter.
2005-09-04 Jody Goldberg <jody@gnome.org>
* ms-excel-write.c (excel_write_ClientTextbox) : property is called
......
......@@ -2287,15 +2287,35 @@ excel_formula_shared (BiffQuery *q, ExcelReadSheet *esheet, GnmCell *cell)
if (opcode == BIFF_TABLE_v0 || opcode == BIFF_TABLE_v2) {
XLDataTable *dt = g_new0 (XLDataTable, 1);
GnmExprList *args = NULL;
GnmCellRef ref;
guint16 const flags = GSF_LE_GET_GUINT16 (q->data + 6);
d (-2, range_dump (&r, " <-- contains data table\n"););
gsf_mem_dump (q->data, q->length);
d (2, { range_dump (&r, " <-- contains data table\n");
gsf_mem_dump (q->data, q->length); });
dt->table = r;
dt->c_in.row = GSF_LE_GET_GUINT16 (q->data + 8);
dt->c_in.col = GSF_LE_GET_GUINT16 (q->data + 10);
dt->r_in.row = GSF_LE_GET_GUINT16 (q->data + 12);
dt->r_in.col = GSF_LE_GET_GUINT16 (q->data + 14);
g_hash_table_insert (esheet->tables, &dt->table.start, dt);
expr = gnm_expr_new_funcall (gnm_func_lookup ("table", NULL), NULL);
args = gnm_expr_list_append (args, gnm_expr_new_cellref (
cellref_init (&ref, NULL,
dt->c_in.col - r.start.col,
dt->c_in.row - r.start.row, TRUE)));
if (flags & 0x8) {
args = gnm_expr_list_append (args, gnm_expr_new_cellref (
cellref_init (&ref, NULL,
dt->r_in.col - r.start.col,
dt->r_in.row - r.start.row, TRUE)));
} else {
GnmExpr const *missing = gnm_expr_new_constant (value_new_empty ());
args = (flags & 4) ? gnm_expr_list_append (args, missing)
: gnm_expr_list_prepend (args, missing);
}
expr = gnm_expr_new_funcall (gnm_func_lookup ("table", NULL), args);
cell_set_array_formula (esheet->sheet,
r.start.col, r.start.row,
r.end.col, r.end.row, expr);
......
......@@ -2938,16 +2938,39 @@ excel_write_FORMULA (ExcelWriteState *ewb, ExcelWriteSheet *esheet, GnmCell cons
if (expr->any.oper == GNM_EXPR_OP_ARRAY &&
expr->array.x == 0 && expr->array.y == 0) {
GnmCellPos r_input, c_input;
if (gnm_expr_is_data_table (expr, &r_input, &c_input)) {
GnmCellPos c_in, r_in;
if (gnm_expr_is_data_table (expr->array.corner.expr, &c_in, &r_in)) {
guint16 flags = 0;
guint8 *data = ms_biff_put_len_next (ewb->bp, BIFF_TABLE_v2, 16);
GSF_LE_SET_GUINT16 (data+0, cell->pos.row);
GSF_LE_SET_GUINT16 (data+2, cell->pos.row + expr->array.rows-1);
GSF_LE_SET_GUINT16 (data+4, cell->pos.col);
GSF_LE_SET_GUINT16 (data+5, cell->pos.col + expr->array.cols-1);
GSF_LE_SET_GUINT16 (data+6, flags);
#warning FINISH THIS
GSF_LE_SET_GUINT16 (data + 0, cell->pos.row);
GSF_LE_SET_GUINT16 (data + 2, cell->pos.row + expr->array.rows-1);
GSF_LE_SET_GUINT16 (data + 4, cell->pos.col);
GSF_LE_SET_GUINT16 (data + 5, cell->pos.col + expr->array.cols-1);
if ((c_in.col != 0 || c_in.row != 0) &&
(r_in.col != 0 || r_in.row != 0)) {
GSF_LE_SET_GUINT16 (data + 8, r_in.row + cell->pos.row);
GSF_LE_SET_GUINT16 (data +10, r_in.col + cell->pos.col);
GSF_LE_SET_GUINT16 (data +12, c_in.row + cell->pos.row);
GSF_LE_SET_GUINT16 (data +14, c_in.col + cell->pos.col);
flags |= 0xC;
} else {
if (c_in.col != 0 || c_in.row != 0) {
GSF_LE_SET_GUINT16 (data + 8, c_in.row + cell->pos.row);
GSF_LE_SET_GUINT16 (data +10, c_in.col + cell->pos.col);
/* it seems arbitrary, but this is what XL generates */
GSF_LE_SET_GUINT16 (data +12, 0x401c);
/* flags |= 0; */
} else {
GSF_LE_SET_GUINT16 (data + 8, r_in.row + cell->pos.row);
GSF_LE_SET_GUINT16 (data +10, r_in.col + cell->pos.col);
/* it seems arbitrary, but this is what XL generates */
GSF_LE_SET_GUINT16 (data +12, 0x4037);
flags |= 4;
}
GSF_LE_SET_GUINT16 (data +14, 0);
}
GSF_LE_SET_GUINT16 (data + 6, flags);
ms_biff_put_commit (ewb->bp);
} else {
ms_biff_put_var_next (ewb->bp, BIFF_ARRAY_v2);
......
......@@ -25,6 +25,7 @@
#include <workbook-priv.h>
#include <func.h>
#include <value.h>
#include <cell.h>
#include <expr.h>
#include <expr-impl.h>
#include <expr-name.h>
......@@ -812,11 +813,17 @@ write_node (PolishData *pd, GnmExpr const *expr, int paren_level,
case GNM_EXPR_OP_ARRAY : {
GnmExprArray const *array = &expr->array;
guint8 data[5];
if (gnm_expr_is_data_table (expr, NULL, NULL))
GSF_LE_SET_GUINT8 (data, FORMULA_PTG_TBL);
else
GSF_LE_SET_GUINT8 (data, FORMULA_PTG_EXPR);
guint8 data[5], ptg = FORMULA_PTG_EXPR;
if (pd->sheet != NULL) {
GnmExprArray const *corner = cell_is_array (sheet_cell_get (
pd->sheet, pd->col - array->x, pd->row - array->y));
if (NULL != corner &&
gnm_expr_is_data_table (corner->corner.expr, NULL, NULL))
ptg = FORMULA_PTG_TBL;
}
GSF_LE_SET_GUINT8 (data, ptg);
GSF_LE_SET_GUINT16 (data+1, pd->row - array->y);
GSF_LE_SET_GUINT16 (data+3, pd->col - array->x);
ms_biff_put_var_write (pd->ewb->bp, data, 5);
......
2005-09-06 Jody Goldberg <jody@gnome.org>
* dialog-function-select.c
(cb_dialog_function_select_cat_selection_changed) : filter out
internal functions (eg TABLE)
2005-09-05 Jody Goldberg <jody@gnome.org>
* dialog-cell-format.c : Move the rotation code into goffice's
......
......@@ -356,12 +356,13 @@ cb_dialog_function_select_fun_selection_changed (GtkTreeSelection *the_selection
static void
cb_dialog_function_select_cat_selection_changed (GtkTreeSelection *the_selection,
FunctionSelectState *state)
FunctionSelectState *state)
{
GtkTreeIter iter;
GtkTreeModel *model;
GnmFuncGroup const * cat;
GSList *funcs, *this_func;
GSList *funcs, *ptr;
GnmFunc const *func;
gtk_list_store_clear (state->model_f);
......@@ -378,31 +379,31 @@ cb_dialog_function_select_cat_selection_changed (GtkTreeSelection *the_selection
funcs = g_slist_concat (funcs,
g_slist_copy (cat->functions));
funcs = g_slist_sort (funcs, dialog_function_select_by_name);
funcs = g_slist_sort (funcs,
dialog_function_select_by_name);
} else
funcs = g_slist_sort (g_slist_copy (cat->functions),
dialog_function_select_by_name);
dialog_function_select_by_name);
for (this_func = funcs; this_func; this_func = this_func->next) {
GnmFunc const *a_func = this_func->data;
gtk_list_store_append (state->model_f, &iter);
gtk_list_store_set (state->model_f, &iter,
FUN_NAME, gnm_func_get_name (a_func),
FUNCTION, a_func,
-1);
for (ptr = funcs; ptr; ptr = ptr->next) {
func = ptr->data;
if (!(func->flags & GNM_FUNC_INTERNAL)) {
gtk_list_store_append (state->model_f, &iter);
gtk_list_store_set (state->model_f, &iter,
FUN_NAME, gnm_func_get_name (func),
FUNCTION, func,
-1);
}
}
g_slist_free (funcs);
} else if (cat == NULL) {
GSList *rec_funcs;
for (rec_funcs = state->recent_funcs; rec_funcs;
rec_funcs = rec_funcs->next) {
GnmFunc const *a_func = rec_funcs->data;
for (ptr = state->recent_funcs; ptr != NULL; ptr = ptr->next) {
func = ptr->data;
gtk_list_store_append (state->model_f, &iter);
gtk_list_store_set (state->model_f, &iter,
FUN_NAME, gnm_func_get_name (a_func),
FUNCTION, a_func,
-1);
FUN_NAME, gnm_func_get_name (func),
FUNCTION, func,
-1);
}
} else {
int i = 0;
......
......@@ -117,7 +117,7 @@ gnm_expr_function_eq (GnmExprFunction const *a,
#endif
GnmExpr const *
gnm_expr_new_funcall (GnmFunc *func, GnmExprList *args)
gnm_expr_new_funcall (GnmFunc *func, GnmExprList *arg_list)
{
GnmExprFunction *ans;
g_return_val_if_fail (func, NULL);
......@@ -129,8 +129,8 @@ gnm_expr_new_funcall (GnmFunc *func, GnmExprList *args)
ans->ref_count = 1;
ans->oper = GNM_EXPR_OP_FUNCALL;
gnm_func_ref (func);
ans->func = func;;
ans->arg_list = args;
ans->func = func;
ans->arg_list = arg_list;
return (GnmExpr *)ans;
}
......@@ -2473,6 +2473,22 @@ gnm_expr_is_data_table (GnmExpr const *expr, GnmCellPos *c_in, GnmCellPos *r_in)
if (expr->any.oper == GNM_EXPR_OP_FUNCALL) {
char const *name = gnm_func_get_name (expr->func.func);
if (name && 0 == strcmp (name, "table")) {
if (NULL != r_in) {
GnmExpr const *r = gnm_expr_list_nth (expr->func.arg_list, 0);
if (r != NULL && r->any.oper == GNM_EXPR_OP_CELLREF) {
r_in->col = r->cellref.ref.col;
r_in->row = r->cellref.ref.row;
} else
r_in->col = r_in->row = 0; /* impossible */
}
if (NULL != c_in) {
GnmExpr const *c = gnm_expr_list_nth (expr->func.arg_list, 1);
if (c != NULL && c->any.oper == GNM_EXPR_OP_CELLREF) {
c_in->col = c->cellref.ref.col;
c_in->row = c->cellref.ref.row;
} else
c_in->col = c_in->row = 0; /* impossible */
}
return TRUE;
}
}
......
......@@ -122,10 +122,10 @@ GnmValue *gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
/*****************************************************************************/
#define gnm_expr_list_nth(l,n) (GnmExpr const *)g_slist_nth_data ((l), n)
#define gnm_expr_list_append(l,e) g_slist_append ((l), (gpointer)(e))
#define gnm_expr_list_prepend(l,e) g_slist_prepend ((l), (gpointer)(e))
#define gnm_expr_list_length(l) g_slist_length((GSList *)(l)) /* const cast */
#define gnm_expr_list_nth(l,n) (GnmExpr const *)g_slist_nth_data ((GSList *)(l), n) /* const cast */
#define gnm_expr_list_free g_slist_free
void gnm_expr_list_unref (GnmExprList *list);
gboolean gnm_expr_list_equal (GnmExprList const *a, GnmExprList const *b);
......
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* func-builtin.c: Built in functions.
*
* Authors:
* Morten Welinder (terra@gnome.org)
* Jody Goldberg (jody@gnome.org)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -27,6 +29,10 @@
#include <collect.h>
#include <value.h>
#include <selection.h>
#include <expr.h>
#include <expr-impl.h>
#include <sheet.h>
#include <cell.h>
/***************************************************************************/
......@@ -126,10 +132,83 @@ gnumeric_version (FunctionEvalInfo *ei, GnmValue const * const *argv)
/***************************************************************************/
GnmValue *
gnumeric_table (FunctionEvalInfo *ei, GnmExprList const *nodes)
static GnmValue *
gnumeric_table (FunctionEvalInfo *ei, GnmExprList const *args)
{
return value_new_error_REF (ei->pos);
GnmExpr const *arg;
GnmCell *in[3], *x_iter, *y_iter;
GnmValue *val[3], *res;
GnmCellPos pos;
int x, y;
if (gnm_expr_list_length (args) != 2 &&
ei->pos->eval.col > 0 && ei->pos->eval.row > 0)
return value_new_error_REF (ei->pos);
for (x = 0; x < 2 ; x++) {
arg = gnm_expr_list_nth (args, x);
val[x] = NULL;
if (NULL != arg && arg->any.oper == GNM_EXPR_OP_CELLREF) {
cellref_get_abs_pos (&arg->cellref.ref, &ei->pos->eval, &pos);
in[x] = sheet_cell_get (ei->pos->sheet, pos.col, pos.row);
if (NULL == in[x])
in[x] = sheet_cell_fetch (ei->pos->sheet, pos.col, pos.row);
else
val[x] = in[x]->value;
} else
in[x] = NULL;
}
val[2] = NULL;
if (NULL != in[0] && NULL != in[1]) {
in[2] = sheet_cell_get (ei->pos->sheet,
ei->pos->eval.col - 1, ei->pos->eval.row - 1);
if (NULL == in[2])
in[2] = sheet_cell_fetch (ei->pos->sheet,
ei->pos->eval.col - 1, ei->pos->eval.row - 1);
else
val[2] = value_dup (in[2]->value);
}
res = value_new_array (ei->pos->cols, ei->pos->rows);
for (x = ei->pos->cols ; x-- > 0 ; ) {
x_iter = sheet_cell_get (ei->pos->sheet,
x + ei->pos->eval.col, ei->pos->eval.row-1);
if (NULL == x_iter)
continue;
cell_eval (x_iter);
in[0]->value = value_dup (x_iter->value);
dependent_queue_recalc (&in[0]->base);
for (y = ei->pos->rows ; y-- > 0 ; ) {
y_iter = sheet_cell_get (ei->pos->sheet,
ei->pos->eval.col-1, y + ei->pos->eval.row);
if (NULL == y_iter)
continue;
cell_eval (y_iter);
in[1]->value = value_dup (y_iter->value);
dependent_queue_recalc (&in[1]->base);
cell_eval (in[2]);
value_array_set (res, x, y, value_dup (in[2]->value));
value_release (in[1]->value);
}
value_release (in[0]->value);
}
value_release (in[2]->value);
for (x = 0 ; x < 3 ; x++)
if (in[x]) {
if (val[x])
in[x]->value = val[x];
else
sheet_cell_remove (ei->pos->sheet, in[x], FALSE, FALSE);
dependent_queue_recalc (&in[x]->base);
}
for (x = 0 ; x < 3 ; x++)
if (in[x])
cell_eval (in[x]);
return res;
}
/***************************************************************************/
......
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