[gnumeric] Write custom properties in xlsx export
- From: Andreas J. Guelzow <guelzow src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] Write custom properties in xlsx export
- Date: Sun, 26 Jun 2011 18:23:03 +0000 (UTC)
commit 19f0979fb9d0aee71202e62a8309515d18b322bc
Author: Andreas J Guelzow <aguelzow pyrshep ca>
Date: Sun Jun 26 12:21:07 2011 -0600
Write custom properties in xlsx export
2011-06-26 Andreas J. Guelzow <aguelzow pyrshep ca>
* xlsx-write.c: new includes (for xlsx-write-docprops.c)
* xlsx-write-docprops.c (xlsx_map_time_to_int): new
(xlsx_map_to_int): new
(xlsx_map_to_bool): new
(xlsx_map_to_date_core): new
(xlsx_map_prop_name_to_output_fun): new
(xlsx_meta_write_props_extended): use xlsx_map_prop_name_to_output_fun
(xlsx_map_prop_type): replaced by xlsx_map_prop_name_to_output_fun
(xlsx_meta_write_props): use xlsx_map_prop_name_to_output_fun
(xlsx_map_to_pid): new
(xlsx_meta_write_props_custom): new
(xlsx_write_docprops_custom): call xlsx_meta_write_props_custom
plugins/excel/ChangeLog | 15 ++
plugins/excel/xlsx-write-docprops.c | 268 +++++++++++++++++++++++++++++------
plugins/excel/xlsx-write.c | 2 +
3 files changed, 243 insertions(+), 42 deletions(-)
---
diff --git a/plugins/excel/ChangeLog b/plugins/excel/ChangeLog
index e7f0033..4618128 100644
--- a/plugins/excel/ChangeLog
+++ b/plugins/excel/ChangeLog
@@ -1,3 +1,18 @@
+2011-06-26 Andreas J. Guelzow <aguelzow pyrshep ca>
+
+ * xlsx-write.c: new includes (for xlsx-write-docprops.c)
+ * xlsx-write-docprops.c (xlsx_map_time_to_int): new
+ (xlsx_map_to_int): new
+ (xlsx_map_to_bool): new
+ (xlsx_map_to_date_core): new
+ (xlsx_map_prop_name_to_output_fun): new
+ (xlsx_meta_write_props_extended): use xlsx_map_prop_name_to_output_fun
+ (xlsx_map_prop_type): replaced by xlsx_map_prop_name_to_output_fun
+ (xlsx_meta_write_props): use xlsx_map_prop_name_to_output_fun
+ (xlsx_map_to_pid): new
+ (xlsx_meta_write_props_custom): new
+ (xlsx_write_docprops_custom): call xlsx_meta_write_props_custom
+
2011-06-25 Andreas J. Guelzow <aguelzow pyrshep ca>
* xlsx-write-docprops.c (xlsx_write_docprops_custom):
diff --git a/plugins/excel/xlsx-write-docprops.c b/plugins/excel/xlsx-write-docprops.c
index d801bca..383b977 100644
--- a/plugins/excel/xlsx-write-docprops.c
+++ b/plugins/excel/xlsx-write-docprops.c
@@ -30,6 +30,133 @@
* included via xlsx-write.c
**/
+typedef void (*output_function) (GsfXMLOut *output, GValue const *val);
+
+static void
+xlsx_map_time_to_int (GsfXMLOut *output, GValue const *val)
+{
+ switch (G_VALUE_TYPE(val)) {
+ case G_TYPE_INT:
+ gsf_xml_out_add_gvalue (output, NULL, val);
+ break;
+ case G_TYPE_STRING: {
+ char const *str = g_value_get_string (val);
+ int minutes = 0, seconds = 0;
+ if ( 1 < sscanf (str, "PT%dM%dS", &minutes, &seconds)) {
+ if (seconds > 29)
+ minutes++;
+ gsf_xml_out_add_int (output, NULL, minutes);
+ break;
+ }
+ /* no break */
+ }
+ default:
+ gsf_xml_out_add_int (output, NULL, 0);
+ break;
+ }
+}
+
+static void
+xlsx_map_to_int (GsfXMLOut *output, GValue const *val)
+{
+ if (G_TYPE_INT == G_VALUE_TYPE (val))
+ gsf_xml_out_add_gvalue (output, NULL, val);
+ else
+ gsf_xml_out_add_int (output, NULL, 0);
+}
+
+static void
+xlsx_map_to_bool (GsfXMLOut *output, GValue const *val)
+{
+ switch (G_VALUE_TYPE(val)) {
+ case G_TYPE_BOOLEAN:
+ xlsx_add_bool (output, NULL, g_value_get_boolean (val));
+ break;
+ case G_TYPE_INT:
+ xlsx_add_bool (output, NULL, g_value_get_int (val) != 0);
+ break;
+ case G_TYPE_STRING:
+ xlsx_add_bool (output, NULL,
+ 0 == g_ascii_strcasecmp (g_value_get_string (val), "true")
+ || 0 == g_ascii_strcasecmp (g_value_get_string (val), "yes"));
+ break;
+ default:
+ xlsx_add_bool (output, NULL, FALSE);
+ break;
+ }
+}
+
+static void
+xlsx_map_to_date_core (GsfXMLOut *output, GValue const *val)
+{
+ gsf_xml_out_add_cstr_unchecked (output, "xsi:type", "dcterms:W3CDTF");
+ if (VAL_IS_GSF_TIMESTAMP(val))
+ gsf_xml_out_add_gvalue (output, NULL, val);
+ else if (G_TYPE_INT == G_VALUE_TYPE (val)) {
+ GsfTimestamp * ts = gsf_timestamp_new ();
+ char *str;
+ gsf_timestamp_set_time (ts, g_value_get_int (val));
+ str = gsf_timestamp_as_string (ts);
+ gsf_xml_out_add_cstr (output, NULL, str);
+ g_free (str);
+ } else {
+ GsfTimestamp * ts = gsf_timestamp_new ();
+ char *str;
+ GTimeVal tm;
+ g_get_current_time (&tm);
+ tm.tv_usec = 0L;
+ gsf_timestamp_set_time (ts, tm.tv_sec);
+ str = gsf_timestamp_as_string (ts);
+ gsf_xml_out_add_cstr (output, NULL, str);
+ g_free (str);
+ }
+}
+
+static output_function
+xlsx_map_prop_name_to_output_fun (char const *name)
+{
+ /* shared by all instances and never freed */
+ static GHashTable *xlsx_prop_name_map_output_fun_extended = NULL;
+
+ if (NULL == xlsx_prop_name_map_output_fun_extended)
+ {
+ static struct {
+ char const *gsf_key;
+ output_function xlsx_output_fun;
+ } const map [] = {
+ { GSF_META_NAME_DATE_CREATED, xlsx_map_to_date_core},
+ { GSF_META_NAME_DATE_MODIFIED, xlsx_map_to_date_core},
+ { GSF_META_NAME_EDITING_DURATION, xlsx_map_time_to_int},
+ { GSF_META_NAME_CHARACTER_COUNT, xlsx_map_to_int},
+ { GSF_META_NAME_BYTE_COUNT, xlsx_map_to_int},
+ { GSF_META_NAME_SECURITY, xlsx_map_to_int},
+ { GSF_META_NAME_HIDDEN_SLIDE_COUNT, xlsx_map_to_int},
+ { "xlsx:HyperlinksChanged", xlsx_map_to_bool},
+ { GSF_META_NAME_LINE_COUNT, xlsx_map_to_int},
+ { GSF_META_NAME_LINKS_DIRTY, xlsx_map_to_bool},
+ { "xlsx:MMClips", xlsx_map_to_int},
+ { GSF_META_NAME_NOTE_COUNT, xlsx_map_to_int},
+ { GSF_META_NAME_PAGE_COUNT, xlsx_map_to_int},
+ { GSF_META_NAME_PARAGRAPH_COUNT, xlsx_map_to_int},
+ { "xlsx:SharedDoc", xlsx_map_to_bool},
+ { GSF_META_NAME_SCALE, xlsx_map_to_bool},
+ { GSF_META_NAME_SLIDE_COUNT, xlsx_map_to_int},
+ { GSF_META_NAME_WORD_COUNT, xlsx_map_to_int}
+ };
+
+ int i = G_N_ELEMENTS (map);
+
+ xlsx_prop_name_map_output_fun_extended = g_hash_table_new (g_str_hash, g_str_equal);
+ while (i-- > 0)
+ g_hash_table_insert (xlsx_prop_name_map_output_fun_extended,
+ (gpointer)map[i].gsf_key,
+ (gpointer)map[i].xlsx_output_fun);
+ }
+
+ return g_hash_table_lookup (xlsx_prop_name_map_output_fun_extended, name);
+}
+
+
static char const *
xlsx_map_prop_name_extended (char const *name)
{
@@ -109,8 +236,14 @@ xlsx_meta_write_props_extended (char const *prop_name, GsfDocProp *prop, GsfXMLO
if (NULL != (mapped_name = xlsx_map_prop_name_extended (prop_name))) {
gsf_xml_out_start_element (output, mapped_name);
- if (NULL != val)
- gsf_xml_out_add_gvalue (output, NULL, val);
+ if (NULL != val) {
+ output_function of = xlsx_map_prop_name_to_output_fun
+ (prop_name);
+ if (of != NULL)
+ of (output, val);
+ else
+ gsf_xml_out_add_gvalue (output, NULL, val);
+ }
gsf_xml_out_end_element (output);
}
}
@@ -149,36 +282,6 @@ xlsx_write_docprops_app (XLSXWriteState *state, GsfOutfile *root_part, GsfOutfil
}
static char const *
-xlsx_map_prop_type (char const *name)
-{
- /* shared by all instances and never freed */
- static GHashTable *xlsx_prop_type_map = NULL;
-
- if (NULL == xlsx_prop_type_map)
- {
- static struct {
- char const *gsf_key;
- char const *xlsx_type;
- } const map [] = {
- /* Note that in ECMA-376 edition 1 these are the only 2 props */
- /* permitted to have types attached to them and they must be as */
- /* as given here. */
- { GSF_META_NAME_DATE_CREATED, "dcterms:W3CDTF" },
- { GSF_META_NAME_DATE_MODIFIED, "dcterms:W3CDTF" }/* , */
- };
- int i = G_N_ELEMENTS (map);
-
- xlsx_prop_type_map = g_hash_table_new (g_str_hash, g_str_equal);
- while (i-- > 0)
- g_hash_table_insert (xlsx_prop_type_map,
- (gpointer)map[i].gsf_key,
- (gpointer)map[i].xlsx_type);
- }
-
- return g_hash_table_lookup (xlsx_prop_type_map, name);
-}
-
-static char const *
xlsx_map_prop_name (char const *name)
{
/* shared by all instances and never freed */
@@ -257,14 +360,15 @@ xlsx_meta_write_props (char const *prop_name, GsfDocProp *prop, GsfXMLOut *outpu
}
if (NULL != (mapped_name = xlsx_map_prop_name (prop_name))) {
- char const *mapped_type = xlsx_map_prop_type (prop_name);
-
- gsf_xml_out_start_element (output, mapped_name);
- if (mapped_type != NULL)
- gsf_xml_out_add_cstr_unchecked (output, "xsi:type", mapped_type);
-
- if (NULL != val)
- gsf_xml_out_add_gvalue (output, NULL, val);
+ gsf_xml_out_start_element (output, mapped_name);
+ if (NULL != val) {
+ output_function of = xlsx_map_prop_name_to_output_fun
+ (prop_name);
+ if (of != NULL)
+ of (output, val);
+ else
+ gsf_xml_out_add_gvalue (output, NULL, val);
+ }
gsf_xml_out_end_element (output);
}
}
@@ -297,6 +401,86 @@ xlsx_write_docprops_core (XLSXWriteState *state, GsfOutfile *root_part, GsfOutfi
g_object_unref (part);
}
+static int
+xlsx_map_to_pid (char const *name)
+{
+ /* shared by all instances and never freed */
+ static GHashTable *xlsx_pid_map = NULL;
+
+ if (NULL == xlsx_pid_map)
+ {
+ static struct {
+ char const *name_key;
+ int pid_key;
+ } const map [] = {
+ { "Editor", 2}
+ };
+
+ int i = G_N_ELEMENTS (map);
+
+ xlsx_pid_map = g_hash_table_new (g_str_hash, g_str_equal);
+ while (i-- > 0)
+ g_hash_table_insert (xlsx_pid_map,
+ (gpointer)map[i].name_key,
+ GINT_TO_POINTER (map[i].pid_key));
+ }
+
+ return GPOINTER_TO_INT (g_hash_table_lookup (xlsx_pid_map, name));
+}
+
+static void
+xlsx_meta_write_props_custom_type (char const *prop_name, GValue const *val, GsfXMLOut *xml, char const *type,
+ int *custom_pid)
+{
+ int pid = xlsx_map_to_pid (prop_name);
+
+
+ gsf_xml_out_start_element (xml, "property");
+ gsf_xml_out_add_cstr_unchecked (xml, "fmtid", "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}");
+ if (pid != 0)
+ gsf_xml_out_add_int (xml, "pid", pid);
+ else {
+ gsf_xml_out_add_int (xml, "pid", *custom_pid);
+ *custom_pid += 1;
+ }
+ gsf_xml_out_add_cstr (xml, "name", prop_name);
+ gsf_xml_out_start_element (xml, type);
+ if (NULL != val)
+ gsf_xml_out_add_gvalue (xml, NULL, val);
+ gsf_xml_out_end_element (xml);
+ gsf_xml_out_end_element (xml); /* </property> */
+}
+
+static void
+xlsx_meta_write_props_custom (char const *prop_name, GsfDocProp *prop, GsfXMLOut *output)
+{
+ int custom_pid = 29;
+ if ((0 != strcmp (GSF_META_NAME_GENERATOR, prop_name)) && (NULL == xlsx_map_prop_name (prop_name))
+ && (NULL == xlsx_map_prop_name_extended (prop_name))) {
+ GValue const *val = gsf_doc_prop_get_val (prop);
+ if (VAL_IS_GSF_TIMESTAMP(val))
+ xlsx_meta_write_props_custom_type (prop_name, val, output, "vt:date", &custom_pid);
+ else switch (G_VALUE_TYPE(val)) {
+ case G_TYPE_BOOLEAN:
+ xlsx_meta_write_props_custom_type (prop_name, val, output, "vt:bool", &custom_pid);
+ break;
+ case G_TYPE_INT:
+ case G_TYPE_LONG:
+ xlsx_meta_write_props_custom_type (prop_name, val, output, "vt:i4", &custom_pid);
+ break;
+ case G_TYPE_FLOAT:
+ case G_TYPE_DOUBLE:
+ xlsx_meta_write_props_custom_type (prop_name, val, output, "vt:decimal", &custom_pid);
+ break;
+ case G_TYPE_STRING:
+ xlsx_meta_write_props_custom_type (prop_name, val, output, "vt:lpwstr", &custom_pid);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
static void
xlsx_write_docprops_custom (XLSXWriteState *state, GsfOutfile *root_part, GsfOutfile *docprops_dir)
{
@@ -306,13 +490,13 @@ xlsx_write_docprops_custom (XLSXWriteState *state, GsfOutfile *root_part, GsfOut
root_part,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties");
GsfXMLOut *xml = gsf_xml_out_new (part);
- /* GsfDocMetaData *meta = go_doc_get_meta_data (GO_DOC (state->base.wb)); */
+ GsfDocMetaData *meta = go_doc_get_meta_data (GO_DOC (state->base.wb));
gsf_xml_out_start_element (xml, "Properties");
gsf_xml_out_add_cstr_unchecked (xml, "xmlns", ns_docprops_custom);
gsf_xml_out_add_cstr_unchecked (xml, "xmlns:vt", ns_docprops_extended_vt);
- /* gsf_doc_meta_data_foreach (meta, (GHFunc) xlsx_meta_write_props_custom, xml); */
+ gsf_doc_meta_data_foreach (meta, (GHFunc) xlsx_meta_write_props_custom, xml);
gsf_xml_out_end_element (xml); /* </Properties> */
diff --git a/plugins/excel/xlsx-write.c b/plugins/excel/xlsx-write.c
index 03c48f5..45e9b66 100644
--- a/plugins/excel/xlsx-write.c
+++ b/plugins/excel/xlsx-write.c
@@ -50,6 +50,7 @@
#include "sheet-object-graph.h"
#include "graph.h"
#include "style-border.h"
+#include "gutils.h"
#include "go-val.h"
@@ -65,6 +66,7 @@
#include <gsf/gsf-meta-names.h>
#include <gsf/gsf-doc-meta-data.h>
#include <gsf/gsf-docprop-vector.h>
+#include <gsf/gsf-timestamp.h>
#include <gmodule.h>
#include <string.h>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]