[gnumeric] [xlsx] Basic external ref support
- From: Jody Goldberg <jody src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnumeric] [xlsx] Basic external ref support
- Date: Tue, 28 Apr 2009 18:46:27 -0400 (EDT)
commit 13420953c3093609f862fb88baf84becf55181f5
Author: Jody Goldberg <jody gnome org>
Date: Tue Apr 28 17:27:35 2009 -0400
[xlsx] Basic external ref support
Still requires
1) storing the values
2) names
3) re-organize parser to handle sheetnames with spaces.
4) proper life cycle support for the extern workbook.
5) Use (4) for xls
---
NEWS | 3 ++
plugins/excel/ChangeLog | 7 ++++
plugins/excel/xlsx-read.c | 66 +++++++++++++++++++++++++++++++++++++++++++-
plugins/excel/xlsx-utils.c | 42 ++++++++++++++++++++++++----
plugins/excel/xlsx-utils.h | 6 ++-
src/parse-util.c | 27 +++++++++++------
src/parse-util.h | 6 ++--
src/parser.y | 8 ++++-
8 files changed, 141 insertions(+), 24 deletions(-)
diff --git a/NEWS b/NEWS
index d0a9e15..0c15c8b 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,9 @@ Andreas:
* Fix some divergence between character weight in the label properties
dialog and the label itself.
+Jody:
+ * XLSX start reading external refs.
+
Morten:
* Fix xls save problem with sheets that are too big for the format.
* Fix global-name .gnumeric warning. [#580227]
diff --git a/plugins/excel/ChangeLog b/plugins/excel/ChangeLog
index 533827f..f62e571 100644
--- a/plugins/excel/ChangeLog
+++ b/plugins/excel/ChangeLog
@@ -1,3 +1,10 @@
+2009-04-28 Jody Goldberg <jody gnome org>
+
+ * xlsx-read.c : initial work on reading external refs. Still broken
+ for refs to sheets with spaces in their names '[1]A Space!A1' thanks
+ to massively silly quoting conventions. This will take a parser
+ re-org to handle.
+
2009-04-26 Morten Welinder <terra gnome org>
* ms-excel-write.c (excel_sheet_extent): Fix off-by-one when we
diff --git a/plugins/excel/xlsx-read.c b/plugins/excel/xlsx-read.c
index 7dc8514..175257f 100644
--- a/plugins/excel/xlsx-read.c
+++ b/plugins/excel/xlsx-read.c
@@ -198,6 +198,10 @@ typedef struct {
GHashTable *by_obj;
XLSXAxisInfo *info;
} axis;
+
+ /* external refs */
+ Workbook *external_ref;
+ Sheet *external_ref_sheet;
} XLSXReadState;
typedef struct {
GnmString *str;
@@ -3986,6 +3990,66 @@ xlsx_sheet_begin (GsfXMLIn *xin, xmlChar const **attrs)
(GDestroyNotify) g_free);
}
+/**************************************************************************************************/
+
+static void
+xlsx_read_external_book (GsfXMLIn *xin, xmlChar const **attrs)
+{
+ XLSXReadState *state = (XLSXReadState *)xin->user_state;
+ GsfOpenPkgRel const *rel = gsf_open_pkg_lookup_rel_by_type (
+ gsf_xml_in_get_input (xin),
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath");
+ if (NULL != rel && gsf_open_pkg_rel_is_extern (rel))
+ state->external_ref = xlsx_conventions_add_extern_ref (
+ state->convs, gsf_open_pkg_rel_get_target (rel));
+}
+static void
+xlsx_read_external_book_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
+{
+ XLSXReadState *state = (XLSXReadState *)xin->user_state;
+ state->external_ref = NULL;
+}
+static void
+xlsx_read_external_sheetname (GsfXMLIn *xin, xmlChar const **attrs)
+{
+ XLSXReadState *state = (XLSXReadState *)xin->user_state;
+ for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
+ if (0 == strcmp (attrs[0], "val"))
+ workbook_sheet_attach (state->external_ref,
+ state->external_ref_sheet = sheet_new (state->external_ref, attrs[1], 256, 65536));
+}
+static void
+xlsx_read_external_sheetname_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
+{
+ XLSXReadState *state = (XLSXReadState *)xin->user_state;
+ state->external_ref_sheet = NULL;
+}
+
+static GsfXMLInNode const xlsx_extern_dtd[] = {
+GSF_XML_IN_NODE_FULL (START, START, -1, NULL, GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
+GSF_XML_IN_NODE_FULL (START, LINK, XL_NS_SS, "externalLink", GSF_XML_NO_CONTENT, TRUE, TRUE, xlsx_read_external_book, xlsx_read_external_book_end, 0),
+ GSF_XML_IN_NODE (LINK, BOOK, XL_NS_SS, "externalBook", GSF_XML_NO_CONTENT, NULL, NULL),
+ GSF_XML_IN_NODE (BOOK, SHEET_NAMES, XL_NS_SS, "sheetNames", GSF_XML_NO_CONTENT, NULL, NULL),
+ GSF_XML_IN_NODE (SHEET_NAMES, SHEET_NAME, XL_NS_SS, "sheetName", GSF_XML_NO_CONTENT, xlsx_read_external_sheetname, xlsx_read_external_sheetname_end),
+ GSF_XML_IN_NODE (BOOK, SHEET_DATASET, XL_NS_SS, "sheetDataSet", GSF_XML_NO_CONTENT, NULL, NULL),
+ GSF_XML_IN_NODE (SHEET_DATASET, SHEET_DATA, XL_NS_SS, "sheetData", GSF_XML_NO_CONTENT, NULL, NULL),
+ GSF_XML_IN_NODE (SHEET_DATA, ROW, XL_NS_SS, "row", GSF_XML_NO_CONTENT, NULL, NULL),
+ GSF_XML_IN_NODE (ROW, CELL, XL_NS_SS, "cell", GSF_XML_NO_CONTENT, NULL, NULL),
+ GSF_XML_IN_NODE (CELL, VAL, XL_NS_SS, "v", GSF_XML_NO_CONTENT, NULL, NULL),
+
+GSF_XML_IN_NODE_END
+};
+
+static void
+xlsx_wb_external_ref (GsfXMLIn *xin, xmlChar const **attrs)
+{
+ for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
+ if (gsf_xml_in_namecmp (xin, attrs[0], XL_NS_DOC_REL, "id"))
+ xlsx_parse_rel_by_id (xin, attrs[1], xlsx_extern_dtd, xlsx_ns);
+}
+
+/**************************************************************************************************/
+
static void
xlsx_wb_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
{
@@ -4039,7 +4103,7 @@ GSF_XML_IN_NODE_FULL (START, WORKBOOK, XL_NS_SS, "workbook", GSF_XML_NO_CONTENT,
GSF_XML_IN_NODE (FGROUPS, FGROUP, XL_NS_SS, "functionGroup", GSF_XML_NO_CONTENT, NULL, NULL),
GSF_XML_IN_NODE (WORKBOOK, WEB_PUB, XL_NS_SS, "webPublishing", GSF_XML_NO_CONTENT, NULL, NULL),
GSF_XML_IN_NODE (WORKBOOK, EXTERNS, XL_NS_SS, "externalReferences", GSF_XML_NO_CONTENT, NULL, NULL),
- GSF_XML_IN_NODE (EXTERNS, EXTERN, XL_NS_SS, "externalReference", GSF_XML_NO_CONTENT, NULL, NULL),
+ GSF_XML_IN_NODE (EXTERNS, EXTERN, XL_NS_SS, "externalReference", GSF_XML_NO_CONTENT, xlsx_wb_external_ref, NULL),
GSF_XML_IN_NODE (WORKBOOK, NAMES, XL_NS_SS, "definedNames", GSF_XML_NO_CONTENT, NULL, NULL),
GSF_XML_IN_NODE (NAMES, NAME, XL_NS_SS, "definedName", GSF_XML_NO_CONTENT, NULL, NULL),
GSF_XML_IN_NODE (WORKBOOK, PIVOTCACHES, XL_NS_SS, "pivotCaches", GSF_XML_NO_CONTENT, NULL, NULL),
diff --git a/plugins/excel/xlsx-utils.c b/plugins/excel/xlsx-utils.c
index 3ce0397..a8894eb 100644
--- a/plugins/excel/xlsx-utils.c
+++ b/plugins/excel/xlsx-utils.c
@@ -28,13 +28,16 @@
#include "parse-util.h"
#include "position.h"
+#include "workbook.h"
#include "sheet.h"
#include "func.h"
+#include <goffice/app/go-doc.h>
#include <glib-object.h>
typedef struct {
GnmConventions base;
- GHashTable *extern_ids;
+ GHashTable *extern_id_by_wb;
+ GHashTable *extern_wb_by_id;
} XLSXExprConventions;
static void
@@ -42,17 +45,27 @@ xlsx_add_extern_id (GnmConventionsOut *out, Workbook *wb)
{
if (wb != out->pp->wb) {
XLSXExprConventions const *xconv = (XLSXExprConventions const *)out->convs;
- char *id = g_hash_table_lookup (xconv->extern_ids, wb);
+ char *id = g_hash_table_lookup (xconv->extern_id_by_wb, wb);
if (NULL == id) {
id = g_strdup_printf ("[%u]",
- g_hash_table_size (xconv->extern_ids));
+ g_hash_table_size (xconv->extern_id_by_wb));
g_object_ref (wb);
- g_hash_table_insert (xconv->extern_ids, wb, id);
+ g_hash_table_insert (xconv->extern_id_by_wb, wb, id);
}
g_string_append (out->accum, id);
}
}
+static Workbook *
+xlsx_lookup_external_wb (GnmConventions const *convs,
+ G_GNUC_UNUSED Workbook *ref_wb,
+ char const *name)
+{
+ XLSXExprConventions const *xconv = (XLSXExprConventions const *)convs;
+ g_print ("lookup '%s'\n", name);
+ return g_hash_table_lookup (xconv->extern_wb_by_id, name);
+}
+
static void
xlsx_cellref_as_string (GnmConventionsOut *out,
GnmCellRef const *cell_ref,
@@ -90,6 +103,19 @@ xlsx_rangeref_as_string (GnmConventionsOut *out, GnmRangeRef const *ref)
rangeref_as_string (out, ref);
}
+Workbook *
+xlsx_conventions_add_extern_ref (GnmConventions *convs, char const *path)
+{
+ XLSXExprConventions *xconv = (XLSXExprConventions *)convs;
+ Workbook *res = g_object_new (WORKBOOK_TYPE, NULL);
+ (void) go_doc_set_uri (GO_DOC (res), path);
+ g_hash_table_insert (xconv->extern_wb_by_id,
+ g_strdup_printf ("%d", g_hash_table_size (xconv->extern_wb_by_id) + 1),
+ res);
+ g_print ("add %d = '%s'\n", g_hash_table_size (xconv->extern_wb_by_id), path);
+ return res;
+}
+
GnmConventions *
xlsx_conventions_new (void)
{
@@ -99,6 +125,7 @@ xlsx_conventions_new (void)
convs->decimal_sep_dot = TRUE;
convs->input.range_ref = rangeref_parse;
+ convs->input.external_wb = xlsx_lookup_external_wb;
convs->output.cell_ref = xlsx_cellref_as_string;
convs->output.range_ref = xlsx_rangeref_as_string;
convs->range_sep_colon = TRUE;
@@ -107,8 +134,10 @@ xlsx_conventions_new (void)
convs->array_col_sep = ',';
convs->array_row_sep = ';';
convs->output.translated = FALSE;
- xconv->extern_ids = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ xconv->extern_id_by_wb = g_hash_table_new_full (g_direct_hash, g_direct_equal,
(GDestroyNotify) g_object_unref, g_free);
+ xconv->extern_wb_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) g_object_unref);
return convs;
}
@@ -117,6 +146,7 @@ void
xlsx_conventions_free (GnmConventions *convs)
{
XLSXExprConventions *xconv = (XLSXExprConventions *)convs;
- g_hash_table_destroy (xconv->extern_ids);
+ g_hash_table_destroy (xconv->extern_id_by_wb);
+ g_hash_table_destroy (xconv->extern_wb_by_id);
gnm_conventions_free (convs);
}
diff --git a/plugins/excel/xlsx-utils.h b/plugins/excel/xlsx-utils.h
index 226cf52..13c6387 100644
--- a/plugins/excel/xlsx-utils.h
+++ b/plugins/excel/xlsx-utils.h
@@ -35,7 +35,9 @@ enum {
XL_NS_PKG_REL
};
-GnmConventions *xlsx_conventions_new (void);
-void xlsx_conventions_free (GnmConventions *conv);
+GnmConventions *xlsx_conventions_new (void);
+void xlsx_conventions_free (GnmConventions *conv);
+Workbook *xlsx_conventions_add_extern_ref (GnmConventions *conv,
+ char const *path);
#endif /* GNM_XLSX_UTILS_H */
diff --git a/src/parse-util.c b/src/parse-util.c
index 867e6b4..6507f89 100644
--- a/src/parse-util.c
+++ b/src/parse-util.c
@@ -808,6 +808,7 @@ unquote (char *dst, char const *src, int n)
/**
* wbref_parse :
+ * @convs : #GnmConventions const
* @start :
* @wb :
*
@@ -815,9 +816,10 @@ unquote (char *dst, char const *src, int n)
* If the string is a valid workbook known name it returns a pointer
* the end of the name.
* Otherwise returns @start and does not modify @wb.
- * **/
+ **/
static char const *
-wbref_parse (char const *start, Workbook **wb, Workbook *ref_wb)
+wbref_parse (GnmConventions const *convs,
+ char const *start, Workbook **wb, Workbook *ref_wb)
{
/* Is this an external reference ? */
if (*start == '[') {
@@ -843,9 +845,11 @@ wbref_parse (char const *start, Workbook **wb, Workbook *ref_wb)
} else
unquote (name, start+2, end-start-2);
- tmp_wb = gnm_app_workbook_get_by_name
- (name,
- ref_wb ? go_doc_get_uri ((GODoc *)ref_wb) : NULL);
+ if (convs->input.external_wb)
+ tmp_wb = (*convs->input.external_wb) (convs, ref_wb, name);
+ else
+ tmp_wb = gnm_app_workbook_get_by_name (name,
+ ref_wb ? go_doc_get_uri ((GODoc *)ref_wb) : NULL);
if (tmp_wb == NULL)
return NULL;
*wb = tmp_wb;
@@ -857,6 +861,7 @@ wbref_parse (char const *start, Workbook **wb, Workbook *ref_wb)
/**
* sheetref_parse :
+ * @convs :
* @start :
* @sheet :
* @wb :
@@ -867,8 +872,9 @@ wbref_parse (char const *start, Workbook **wb, Workbook *ref_wb)
* the end of the name.
* Otherwise returns @start and does not modify @sheet.
**/
-char const *
-sheetref_parse (char const *start, Sheet **sheet, Workbook const *wb,
+static char const *
+sheetref_parse (GnmConventions const *convs,
+ char const *start, Sheet **sheet, Workbook const *wb,
gboolean allow_3d)
{
GString *sheet_name;
@@ -1031,15 +1037,15 @@ rangeref_parse (GnmRangeRef *res, char const *start, GnmParsePos const *pp,
wb = pp->wb;
ref_wb = wb ? wb : pp->sheet->workbook;
start_wb = start;
- start_sheet = wbref_parse (start, &wb, ref_wb);
+ start_sheet = wbref_parse (convs, start, &wb, ref_wb);
if (start_sheet == NULL)
return start; /* TODO error unknown workbook */
- ptr = sheetref_parse (start_sheet, &res->a.sheet, wb, TRUE);
+ ptr = sheetref_parse (convs, start_sheet, &res->a.sheet, wb, TRUE);
if (ptr == NULL)
return start; /* TODO error unknown sheet */
if (ptr != start_sheet) {
if (*ptr == ':') { /* 3d ref */
- ptr = sheetref_parse (ptr+1, &res->b.sheet, wb, FALSE);
+ ptr = sheetref_parse (convs, ptr+1, &res->b.sheet, wb, FALSE);
if (ptr == NULL)
return start; /* TODO error unknown sheet */
} else
@@ -1318,6 +1324,7 @@ gnm_conventions_new_full (unsigned size)
convs->input.range_ref = rangeref_parse;
convs->input.name = std_name_parser;
convs->input.func = std_func_map;
+ convs->input.external_wb = NULL;
convs->output.decimal_digits = GNM_DIG;
convs->output.translated = TRUE;
diff --git a/src/parse-util.h b/src/parse-util.h
index f9bad48..1c07c95 100644
--- a/src/parse-util.h
+++ b/src/parse-util.h
@@ -33,9 +33,6 @@ char const *rangeref_parse (GnmRangeRef *res, char const *in,
GnmConventions const *convs);
/* GError **err); */
-char const *sheetref_parse (char const *start, Sheet **sheet,
- Workbook const *wb, gboolean allow_3d);
-
char const *cell_coord_name (int col, int row);
char const *cell_name (GnmCell const *cell);
@@ -156,6 +153,9 @@ struct _GnmConventions {
Workbook *scope,
char const *name,
GnmExprList *args);
+ Workbook *(*external_wb) (GnmConventions const *convs,
+ Workbook *ref_wb,
+ char const *unquoted_name);
} input;
/* Export specific functions ----------------------------------- */
diff --git a/src/parser.y b/src/parser.y
index 518790b..e1fdc1c 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -726,6 +726,7 @@ string_opt_quote : STRING
| QUOTED_STRING
;
+/* only used for names */
workbookref : '[' string_opt_quote ']' {
char const *wb_name = value_peek_string ($2->constant.value);
Workbook *ref_wb = state->pos
@@ -735,8 +736,11 @@ workbookref : '[' string_opt_quote ']' {
? state->pos->sheet->workbook
: NULL))
: NULL;
- Workbook *wb = gnm_app_workbook_get_by_name
- (wb_name,
+ Workbook *wb;
+ if (state->convs->input.external_wb)
+ wb = (*state->convs->input.external_wb) (state->convs, ref_wb, wb_name);
+ else
+ wb = gnm_app_workbook_get_by_name (wb_name,
ref_wb ? go_doc_get_uri ((GODoc *)ref_wb) : NULL);
if (wb != NULL) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]