[gnumeric] xlsx: first stab at writing conditional formatting.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] xlsx: first stab at writing conditional formatting.
- Date: Thu, 20 Mar 2014 01:08:47 +0000 (UTC)
commit 337cec7d6fe31ac71d09e9942b555abd86a4d1da
Author: Morten Welinder <terra gnome org>
Date: Wed Mar 19 21:08:09 2014 -0400
xlsx: first stab at writing conditional formatting.
Almost there. Borders don't work yet.
plugins/excel/ChangeLog | 2 +
plugins/excel/xlsx-write.c | 495 +++++++++++++++++++++++++++++++-------------
2 files changed, 351 insertions(+), 146 deletions(-)
---
diff --git a/plugins/excel/ChangeLog b/plugins/excel/ChangeLog
index bf34770..cb519c7 100644
--- a/plugins/excel/ChangeLog
+++ b/plugins/excel/ChangeLog
@@ -1,5 +1,7 @@
2014-03-19 Morten Welinder <terra gnome org>
+ * xlsx-write.c (xlsx_write_dxfs): New function.
+
* xlsx-read.c (xlsx_CT_CustomFilter): Avoid mixing enums.
(xlsx_cond_fmt_formula_end): Parse expressions in the right parse
position.
diff --git a/plugins/excel/xlsx-write.c b/plugins/excel/xlsx-write.c
index 9ee0e36..3059eaa 100644
--- a/plugins/excel/xlsx-write.c
+++ b/plugins/excel/xlsx-write.c
@@ -53,6 +53,7 @@
#include "sheet-object-graph.h"
#include "graph.h"
#include "style-border.h"
+#include "style-conditions.h"
#include "gutils.h"
#include "expr-name.h"
@@ -106,6 +107,8 @@ typedef struct {
GPtrArray *shared_string_array;
GHashTable *styles_hash;
GPtrArray *styles_array;
+ GHashTable *dxfs_hash;
+ GPtrArray *dxfs_array;
GnmConventions *convs;
GOIOContext *io_context;
@@ -351,6 +354,16 @@ xlsx_load_buildin_num_formats (GHashTable *hash)
g_hash_table_insert (hash, g_strdup (std_builtins[i]), GUINT_TO_POINTER (i));
}
+static void
+xlsx_write_num_format (XLSXWriteState *state, GsfXMLOut *xml,
+ GOFormat const *format, int id)
+{
+ gsf_xml_out_start_element (xml, "numFmt");
+ gsf_xml_out_add_cstr (xml, "formatCode", go_format_as_XL (format));
+ gsf_xml_out_add_int (xml, "numFmtId", id);
+ gsf_xml_out_end_element (xml);
+}
+
static GHashTable *
xlsx_write_num_formats (XLSXWriteState *state, GsfXMLOut *xml)
{
@@ -358,7 +371,6 @@ xlsx_write_num_formats (XLSXWriteState *state, GsfXMLOut *xml)
(g_str_hash, g_str_equal, g_free, NULL);
GHashTable *num_format_hash = g_hash_table_new
(g_direct_hash, g_direct_equal);
- unsigned int n = NUM_FORMAT_BASE;
unsigned int i, count;
GPtrArray *num_format_array = g_ptr_array_new ();
@@ -372,16 +384,15 @@ xlsx_write_num_formats (XLSXWriteState *state, GsfXMLOut *xml)
if (!gnm_style_is_element_set (style, MSTYLE_FORMAT))
continue;
- format = gnm_style_get_format (style);
+ format = gnm_style_get_format (style);
if (go_format_is_general (format))
continue;
xl = go_format_as_XL (format);
tmp = g_hash_table_lookup (hash, xl);
if (tmp == NULL) {
- char *xl_c = g_strdup (xl);
- tmp = GUINT_TO_POINTER (n++);
- g_hash_table_insert (hash, xl_c, tmp);
- g_ptr_array_add (num_format_array, xl_c);
+ tmp = GUINT_TO_POINTER (num_format_array->len + NUM_FORMAT_BASE);
+ g_hash_table_insert (hash, g_strdup (xl), tmp);
+ g_ptr_array_add (num_format_array, (gpointer)format);
}
g_hash_table_insert (num_format_hash, (gpointer) style, tmp);
}
@@ -390,13 +401,11 @@ xlsx_write_num_formats (XLSXWriteState *state, GsfXMLOut *xml)
if (count != 0) {
gsf_xml_out_start_element (xml, "numFmts");
gsf_xml_out_add_int (xml, "count", count);
- for (i = 0 , n = NUM_FORMAT_BASE; i < count ; i++, n++) {
- gsf_xml_out_start_element (xml, "numFmt");
- gsf_xml_out_add_cstr
- (xml, "formatCode",
- g_ptr_array_index (num_format_array, i));
- gsf_xml_out_add_int (xml, "numFmtId", n);
- gsf_xml_out_end_element (xml);
+ for (i = 0; i < count; i++) {
+ GOFormat const *format =
+ g_ptr_array_index (num_format_array, i);
+ xlsx_write_num_format (state, xml, format,
+ i + NUM_FORMAT_BASE);
}
gsf_xml_out_end_element (xml);
}
@@ -454,23 +463,97 @@ xlsx_find_font (GnmStyle const *style, GPtrArray *styles)
return -1;
}
+static gboolean
+xlsx_has_font_style (GnmStyle const *style)
+{
+ return (gnm_style_is_element_set (style, MSTYLE_FONT_BOLD) ||
+ gnm_style_is_element_set (style, MSTYLE_FONT_ITALIC) ||
+ gnm_style_is_element_set (style, MSTYLE_FONT_UNDERLINE) ||
+ gnm_style_is_element_set (style, MSTYLE_FONT_COLOR) ||
+ gnm_style_is_element_set (style, MSTYLE_FONT_NAME) ||
+ gnm_style_is_element_set (style, MSTYLE_FONT_SCRIPT) ||
+ gnm_style_is_element_set (style, MSTYLE_FONT_SIZE) ||
+ gnm_style_is_element_set (style, MSTYLE_FONT_STRIKETHROUGH));
+}
+
+static void
+xlsx_write_font (XLSXWriteState *state, GsfXMLOut *xml, GnmStyle const *style)
+{
+ gsf_xml_out_start_element (xml, "font");
+ if (gnm_style_is_element_set (style, MSTYLE_FONT_BOLD)) {
+ gsf_xml_out_start_element (xml, "b");
+ xlsx_add_bool (xml, "val", gnm_style_get_font_bold (style));
+ gsf_xml_out_end_element (xml);
+ }
+ if (gnm_style_is_element_set (style, MSTYLE_FONT_ITALIC)) {
+ gsf_xml_out_start_element (xml, "i");
+ xlsx_add_bool (xml, "val", gnm_style_get_font_italic (style));
+ gsf_xml_out_end_element (xml);
+ }
+ if (gnm_style_is_element_set (style, MSTYLE_FONT_UNDERLINE)) {
+ static const char * const types[] = {
+ "none",
+ "single",
+ "double",
+ "singleAccounting",
+ "doubleAccounting"
+ };
+
+ gsf_xml_out_start_element (xml, "u");
+ gsf_xml_out_add_cstr
+ (xml, "val", types[gnm_style_get_font_uline (style)]);
+ gsf_xml_out_end_element (xml);
+ }
+ if (gnm_style_is_element_set (style, MSTYLE_FONT_COLOR))
+ xlsx_write_color_element
+ (xml, "color",
+ gnm_style_get_font_color (style)->go_color);
+ if (gnm_style_is_element_set (style, MSTYLE_FONT_NAME)) {
+ gsf_xml_out_start_element (xml, "name");
+ gsf_xml_out_add_cstr
+ (xml, "val", gnm_style_get_font_name (style));
+ gsf_xml_out_end_element (xml);
+ }
+ if (gnm_style_is_element_set (style, MSTYLE_FONT_SCRIPT)) {
+ GOFontScript scr = gnm_style_get_font_script (style);
+ const char *val;
+
+ switch (scr) {
+ case GO_FONT_SCRIPT_SUB: val = "subscript"; break;
+ case GO_FONT_SCRIPT_SUPER: val = "superscript"; break;
+ default:
+ case GO_FONT_SCRIPT_STANDARD: val = "baseline"; break;
+ }
+ gsf_xml_out_start_element (xml, "vertAlign");
+ gsf_xml_out_add_cstr (xml, "val", val);
+ gsf_xml_out_end_element (xml);
+ }
+ if (gnm_style_is_element_set (style, MSTYLE_FONT_SIZE)) {
+ gsf_xml_out_start_element (xml, "sz");
+ gsf_xml_out_add_float
+ (xml, "val", gnm_style_get_font_size (style),
+ 2);
+ gsf_xml_out_end_element (xml);
+
+ }
+ if (gnm_style_is_element_set (style, MSTYLE_FONT_STRIKETHROUGH)) {
+ gsf_xml_out_start_element (xml, "strike");
+ xlsx_add_bool (xml, "val", gnm_style_get_font_strike (style));
+ gsf_xml_out_end_element (xml);
+ }
+ gsf_xml_out_end_element (xml); /* font */
+}
+
static GHashTable *
xlsx_write_fonts (XLSXWriteState *state, GsfXMLOut *xml)
{
- GHashTable *fonts_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
- GPtrArray *styles_w_fonts = g_ptr_array_new ();
+ GHashTable *fonts_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+ GPtrArray *styles_w_fonts = g_ptr_array_new ();
unsigned int i;
for (i = 0 ; i < state->styles_array->len ; i++) {
GnmStyle const *style = g_ptr_array_index (state->styles_array, i);
- if (gnm_style_is_element_set (style, MSTYLE_FONT_BOLD) ||
- gnm_style_is_element_set (style, MSTYLE_FONT_ITALIC) ||
- gnm_style_is_element_set (style, MSTYLE_FONT_UNDERLINE) ||
- gnm_style_is_element_set (style, MSTYLE_FONT_COLOR) ||
- gnm_style_is_element_set (style, MSTYLE_FONT_NAME) ||
- gnm_style_is_element_set (style, MSTYLE_FONT_SCRIPT) ||
- gnm_style_is_element_set (style, MSTYLE_FONT_SIZE) ||
- gnm_style_is_element_set (style, MSTYLE_FONT_STRIKETHROUGH)) {
+ if (xlsx_has_font_style (style)) {
gint font_n = xlsx_find_font (style, styles_w_fonts);
if (font_n < 0) {
g_ptr_array_add (styles_w_fonts, (gpointer)style);
@@ -487,70 +570,7 @@ xlsx_write_fonts (XLSXWriteState *state, GsfXMLOut *xml)
gsf_xml_out_add_int (xml, "count", styles_w_fonts->len);
for (i = 0 ; i < styles_w_fonts->len ; i++) {
GnmStyle const *style = g_ptr_array_index (styles_w_fonts, i);
- gsf_xml_out_start_element (xml, "font");
- if (gnm_style_is_element_set (style, MSTYLE_FONT_BOLD)) {
- gsf_xml_out_start_element (xml, "b");
- xlsx_add_bool (xml, "val", gnm_style_get_font_bold (style));
- gsf_xml_out_end_element (xml);
- }
- if (gnm_style_is_element_set (style, MSTYLE_FONT_ITALIC)) {
- gsf_xml_out_start_element (xml, "i");
- xlsx_add_bool (xml, "val", gnm_style_get_font_italic (style));
- gsf_xml_out_end_element (xml);
- }
- if (gnm_style_is_element_set (style, MSTYLE_FONT_UNDERLINE)) {
- static const char * const types[] = {
- "none",
- "single",
- "double",
- "singleAccounting",
- "doubleAccounting"
- };
-
- gsf_xml_out_start_element (xml, "u");
- gsf_xml_out_add_cstr
- (xml, "val", types[gnm_style_get_font_uline (style)]);
- gsf_xml_out_end_element (xml);
- }
- if (gnm_style_is_element_set (style, MSTYLE_FONT_COLOR))
- xlsx_write_color_element
- (xml, "color",
- gnm_style_get_font_color (style)->go_color);
- if (gnm_style_is_element_set (style, MSTYLE_FONT_NAME)) {
- gsf_xml_out_start_element (xml, "name");
- gsf_xml_out_add_cstr
- (xml, "val", gnm_style_get_font_name (style));
- gsf_xml_out_end_element (xml);
- }
- if (gnm_style_is_element_set (style, MSTYLE_FONT_SCRIPT)) {
- GOFontScript scr = gnm_style_get_font_script (style);
- const char *val;
-
- switch (scr) {
- case GO_FONT_SCRIPT_SUB: val = "subscript"; break;
- case GO_FONT_SCRIPT_SUPER: val = "superscript"; break;
- default: val = NULL;
- }
- if (val) {
- gsf_xml_out_start_element (xml, "vertAlign");
- gsf_xml_out_add_cstr (xml, "val", val);
- gsf_xml_out_end_element (xml);
- }
- }
- if (gnm_style_is_element_set (style, MSTYLE_FONT_SIZE)) {
- gsf_xml_out_start_element (xml, "sz");
- gsf_xml_out_add_float
- (xml, "val", gnm_style_get_font_size (style),
- 2);
- gsf_xml_out_end_element (xml);
-
- }
- if (gnm_style_is_element_set (style, MSTYLE_FONT_STRIKETHROUGH)) {
- gsf_xml_out_start_element (xml, "strike");
- xlsx_add_bool (xml, "val", gnm_style_get_font_strike (style));
- gsf_xml_out_end_element (xml);
- }
- gsf_xml_out_end_element (xml); /* font */
+ xlsx_write_font (state, xml, style);
}
gsf_xml_out_end_element (xml);
}
@@ -591,6 +611,49 @@ xlsx_find_fill (GnmStyle const *style, GPtrArray *styles)
return -1;
}
+static gboolean
+xlsx_has_background_style (GnmStyle const *style)
+{
+ return (gnm_style_is_element_set (style, MSTYLE_COLOR_BACK) ||
+ gnm_style_is_element_set (style, MSTYLE_COLOR_PATTERN) ||
+ gnm_style_is_element_set (style, MSTYLE_PATTERN));
+}
+
+static void
+xlsx_write_background (XLSXWriteState *state, GsfXMLOut *xml,
+ GnmStyle const *style, gboolean invert_solid)
+{
+ /* MAGIC :
+ * Looks like pattern background and forground colours are inverted for
+ * dxfs with solid fills for no apparent reason. */
+
+ gsf_xml_out_start_element (xml, "fill");
+ gsf_xml_out_start_element (xml, "patternFill");
+ if (gnm_style_is_element_set (style, MSTYLE_PATTERN)) {
+ gint pattern = gnm_style_get_pattern (style);
+ if (pattern <= 0 || pattern > (gint)G_N_ELEMENTS (pats)) {
+ gsf_xml_out_add_cstr_unchecked (xml, "patternType",
+ "none");
+ } else {
+ gboolean invert = (pattern == 1 && invert_solid);
+ gsf_xml_out_add_cstr_unchecked (xml, "patternType",
+ pats[pattern - 1]);
+ if (gnm_style_is_element_set (style, MSTYLE_COLOR_BACK))
+ xlsx_write_color_element
+ (xml,
+ invert ? "bgColor" : "fgColor",
+ gnm_style_get_back_color (style)->go_color);
+ if (gnm_style_is_element_set (style, MSTYLE_COLOR_PATTERN))
+ xlsx_write_color_element
+ (xml,
+ invert ? "fgColor" : "bgColor",
+ gnm_style_get_pattern_color (style)->go_color);
+ }
+ }
+ gsf_xml_out_end_element (xml);
+ gsf_xml_out_end_element (xml);
+}
+
static GHashTable *
xlsx_write_fills (XLSXWriteState *state, GsfXMLOut *xml)
{
@@ -600,9 +663,7 @@ xlsx_write_fills (XLSXWriteState *state, GsfXMLOut *xml)
for (i = 0 ; i < state->styles_array->len ; i++) {
GnmStyle const *style = g_ptr_array_index (state->styles_array, i);
- if (gnm_style_is_element_set (style, MSTYLE_COLOR_BACK) ||
- gnm_style_is_element_set (style, MSTYLE_COLOR_PATTERN) ||
- gnm_style_is_element_set (style, MSTYLE_PATTERN)) {
+ if (xlsx_has_background_style (style)) {
gint fill_n = xlsx_find_fill (style, styles_w_fills);
if (fill_n < 0) {
g_ptr_array_add (styles_w_fills, (gpointer)style);
@@ -626,46 +687,7 @@ xlsx_write_fills (XLSXWriteState *state, GsfXMLOut *xml)
xlsx_write_predefined_fills (xml);
for (i = 0 ; i < styles_w_fills->len ; i++) {
GnmStyle const *style = g_ptr_array_index (styles_w_fills, i);
- gsf_xml_out_start_element (xml, "fill");
- gsf_xml_out_start_element (xml, "patternFill");
- if (gnm_style_is_element_set (style, MSTYLE_PATTERN)) {
- gint pattern = gnm_style_get_pattern (style);
- switch (pattern) {
- case 0:
- gsf_xml_out_add_cstr_unchecked (xml, "patternType",
- "none");
- break;
- case 1:
- gsf_xml_out_add_cstr_unchecked (xml, "patternType",
- "solid");
- if (gnm_style_is_element_set (style, MSTYLE_COLOR_BACK)) {
- xlsx_write_color_element
- (xml, "fgColor",
- gnm_style_get_back_color (style)->go_color);
- }
- break;
- default:
- if (pattern < 2 || pattern > (gint)G_N_ELEMENTS (pats))
- gsf_xml_out_add_cstr_unchecked (xml, "patternType",
- "none");
- else
- gsf_xml_out_add_cstr_unchecked (xml, "patternType",
- pats[pattern - 1]);
- break;
- }
- if (pattern > 1) {
- if (gnm_style_is_element_set (style, MSTYLE_COLOR_BACK))
- xlsx_write_color_element
- (xml, "fgColor",
- gnm_style_get_back_color (style)->go_color);
- if (gnm_style_is_element_set (style, MSTYLE_COLOR_PATTERN))
- xlsx_write_color_element
- (xml, "bgColor",
- gnm_style_get_pattern_color (style)->go_color);
- }
- }
- gsf_xml_out_end_element (xml);
- gsf_xml_out_end_element (xml);
+ xlsx_write_background (state, xml, style, FALSE);
}
gsf_xml_out_end_element (xml);
@@ -887,7 +909,7 @@ xlsx_write_borders (XLSXWriteState *state, GsfXMLOut *xml)
}
static gboolean
-xlsx_write_style_want_alignment (GnmStyle const *style)
+xlsx_has_alignment_style (GnmStyle const *style)
{
return gnm_style_is_element_set (style, MSTYLE_ALIGN_H)
|| gnm_style_is_element_set (style, MSTYLE_ALIGN_V)
@@ -990,7 +1012,7 @@ xlsx_write_style (XLSXWriteState *state, GsfXMLOut *xml,
GHashTable *num_format_hash, GHashTable *fonts_hash,
GHashTable *border_hash, gint id)
{
- gboolean alignment = xlsx_write_style_want_alignment (style);
+ gboolean alignment = xlsx_has_alignment_style (style);
gpointer tmp_fill, tmp_font, tmp_border;
gboolean fill = (NULL != (tmp_fill = g_hash_table_lookup (fills_hash, style)));
gboolean font = (NULL != (tmp_font = g_hash_table_lookup (fonts_hash, style)));
@@ -1019,7 +1041,6 @@ xlsx_write_style (XLSXWriteState *state, GsfXMLOut *xml,
if (alignment)
xlsx_write_style_write_alignment (state, xml, style);
-
}
static void
@@ -1044,21 +1065,56 @@ xlsx_write_cellXfs (XLSXWriteState *state, GsfXMLOut *xml,
GHashTable *fills_hash, GHashTable *num_format_hash,
GHashTable *fonts_hash, GHashTable *border_hash)
{
- if (state->styles_array->len > 0) {
- unsigned i;
- gsf_xml_out_start_element (xml, "cellXfs");
- gsf_xml_out_add_int (xml, "count", state->styles_array->len);
- for (i = 0 ; i < state->styles_array->len ; i++) {
- gsf_xml_out_start_element (xml, "xf");
- xlsx_write_style
- (state, xml,
- g_ptr_array_index (state->styles_array, i),
- fills_hash, num_format_hash, fonts_hash,
- border_hash, 0);
- gsf_xml_out_end_element (xml);
+ unsigned i, N = state->styles_array->len;
+
+ if (N == 0)
+ return;
+
+ gsf_xml_out_start_element (xml, "cellXfs");
+ gsf_xml_out_add_int (xml, "count", N);
+ for (i = 0; i < N; i++) {
+ GnmStyle const *style =
+ g_ptr_array_index (state->styles_array, i);
+ gsf_xml_out_start_element (xml, "xf");
+ xlsx_write_style
+ (state, xml, style,
+ fills_hash, num_format_hash, fonts_hash,
+ border_hash, 0);
+ gsf_xml_out_end_element (xml);
+ }
+ gsf_xml_out_end_element (xml);
+}
+
+static void
+xlsx_write_dxfs (XLSXWriteState *state, GsfXMLOut *xml,
+ GHashTable *num_format_hash)
+{
+ unsigned i, N = state->dxfs_array->len;
+ int id = NUM_FORMAT_BASE + g_hash_table_size (num_format_hash);
+
+ if (N == 0)
+ return;
+
+ gsf_xml_out_start_element (xml, "dxfs");
+ gsf_xml_out_add_int (xml, "count", N);
+ for (i = 0; i < N; i++) {
+ GnmStyle *style =
+ g_ptr_array_index (state->dxfs_array, i);
+ gsf_xml_out_start_element (xml, "dxf");
+ if (xlsx_has_font_style (style))
+ xlsx_write_font (state, xml, style);
+ if (xlsx_has_alignment_style (style))
+ xlsx_write_style_write_alignment (state, xml, style);
+ if (xlsx_has_background_style (style))
+ xlsx_write_background (state, xml, style, TRUE);
+ if (gnm_style_is_element_set (style, MSTYLE_FORMAT)) {
+ GOFormat const *format = gnm_style_get_format (style);
+ xlsx_write_num_format (state, xml, format, id++);
}
+
gsf_xml_out_end_element (xml);
}
+ gsf_xml_out_end_element (xml);
}
static void
@@ -1083,7 +1139,7 @@ xlsx_write_styles (XLSXWriteState *state, GsfOutfile *wb_part)
xlsx_write_cellStyleXfs (state, xml, fills_hash, num_format_hash, fonts_hash, border_hash);
xlsx_write_cellXfs (state, xml, fills_hash, num_format_hash, fonts_hash, border_hash);
/* <xsd:element name="cellStyles" type="CT_CellStyles" minOccurs="0" maxOccurs="1"/> */
- /* <xsd:element name="dxfs" type="CT_Dxfs" minOccurs="0" maxOccurs="1"/> */
+ xlsx_write_dxfs (state, xml, num_format_hash);
/* <xsd:element name="tableStyles" type="CT_TableStyles" minOccurs="0" maxOccurs="1"/> */
/* <xsd:element name="colors" type="CT_Colors" minOccurs="0" maxOccurs="1"/> */
/* <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> */
@@ -1227,6 +1283,21 @@ xlsx_get_style_id (XLSXWriteState *state, GnmStyle const *style)
return GPOINTER_TO_INT (tmp) - 1;
}
+static gint
+xlsx_get_cond_style_id (XLSXWriteState *state, GnmStyle const *style)
+{
+ gpointer tmp;
+
+ g_return_val_if_fail (style != NULL, 0);
+
+ if (NULL == (tmp = g_hash_table_lookup (state->dxfs_hash, style))) {
+ g_ptr_array_add (state->dxfs_array, (gpointer)style);
+ tmp = GINT_TO_POINTER (state->dxfs_array->len);
+ g_hash_table_insert (state->dxfs_hash, (gpointer)style, tmp);
+ }
+ return GPOINTER_TO_INT (tmp) - 1;
+}
+
static gboolean
row_boring (Sheet *sheet, int r)
{
@@ -1448,6 +1519,133 @@ xlsx_write_merges (XLSXWriteState *state, GsfXMLOut *xml)
}
static void
+xlsx_write_cond_rule (XLSXWriteState *state, GsfXMLOut *xml,
+ GnmStyleCond *cond, GnmParsePos const *pp)
+{
+ int i, n;
+ const char *type = NULL;
+ const char *operator = NULL;
+ GnmExprTop const *alt_texpr = NULL;
+
+ gsf_xml_out_start_element (xml, "cfRule");
+ switch (cond->op) {
+ case GNM_STYLE_COND_BETWEEN:
+ n = 2; operator = "between";
+ break;
+ case GNM_STYLE_COND_NOT_BETWEEN:
+ n = 2; operator = "notBetween";
+ break;
+ case GNM_STYLE_COND_EQUAL:
+ n = 1; operator = "equal";
+ break;
+ case GNM_STYLE_COND_NOT_EQUAL:
+ n = 1; operator = "notEqual";
+ break;
+ case GNM_STYLE_COND_GT:
+ n = 1; operator = "greaterThan";
+ break;
+ case GNM_STYLE_COND_LT:
+ n = 1; operator = "lessThan";
+ break;
+ case GNM_STYLE_COND_GTE:
+ n = 1; operator = "greaterThanOrEqual";
+ break;
+ case GNM_STYLE_COND_LTE:
+ n = 1; operator = "lessThanOrEqual";
+ break;
+ case GNM_STYLE_COND_CONTAINS_BLANKS:
+ n = 0; type = "containsBlanks";
+ break;
+ case GNM_STYLE_COND_NOT_CONTAINS_BLANKS:
+ n = 0; type = "containsNoBlanks";
+ break;
+ case GNM_STYLE_COND_CONTAINS_ERR:
+ n = 0; type = "containsErrors";
+ break;
+ case GNM_STYLE_COND_NOT_CONTAINS_ERR:
+ n = 0; type = "containsNoErrors";
+ break;
+ case GNM_STYLE_COND_CUSTOM:
+ n = 1; type = "expression";
+ break;
+ case GNM_STYLE_COND_CONTAINS_STR:
+ n = 1; type = "containsText";
+ break;
+ case GNM_STYLE_COND_NOT_CONTAINS_STR:
+ n = 1; type = "doesNotContainText";
+ break;
+ case GNM_STYLE_COND_BEGINS_WITH_STR:
+ n = 1; type = "beginsWith";
+ break;
+ case GNM_STYLE_COND_ENDS_WITH_STR:
+ n = 1; type = "endsWith";
+ break;
+
+ case GNM_STYLE_COND_NOT_BEGINS_WITH_STR:
+ case GNM_STYLE_COND_NOT_ENDS_WITH_STR:
+ alt_texpr = gnm_style_cond_get_alternate_expr (cond);
+ n = 1; type = "expression";
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+ gsf_xml_out_add_cstr_unchecked (xml, "type", type ? type : "cellIs");
+ gsf_xml_out_add_int (xml, "dxfId",
+ xlsx_get_cond_style_id (state, cond->overlay));
+ gsf_xml_out_add_int (xml, "priority", 1) ;
+ gsf_xml_out_add_int (xml, "stopIfTrue", 1) ;
+ if (operator)
+ gsf_xml_out_add_cstr_unchecked (xml, "operator", operator);
+ for (i = 0; i < n; i++) {
+ GnmExprTop const *texpr = alt_texpr
+ ? alt_texpr
+ : gnm_style_cond_get_expr (cond, i);
+ char *str = gnm_expr_top_as_string (texpr, pp, state->convs);
+ gsf_xml_out_simple_element (xml, "formula", str);
+ g_free (str);
+ }
+ if (alt_texpr)
+ gnm_expr_top_unref (alt_texpr);
+ gsf_xml_out_end_element (xml); /* </cfRule> */
+}
+
+
+static void
+xlsx_write_conditional_formatting (XLSXWriteState *state, GsfXMLOut *xml)
+{
+ GnmStyleList *cond_styles =
+ sheet_style_collect_conditions (state->sheet, NULL);
+ GnmStyleList *l;
+ if (!cond_styles)
+ return;
+
+ for (l = cond_styles; l; l = l->next) {
+ GnmStyleRegion const *sr = l->data;
+ GnmStyleConditions *sc = gnm_style_get_conditions (sr->style);
+ GPtrArray const *conds = gnm_style_conditions_details (sc);
+ unsigned ui;
+ GnmParsePos pp;
+
+ if (!conds)
+ continue;
+
+ parse_pos_init (&pp, NULL, state->sheet,
+ sr->range.start.col, sr->range.start.row);
+ gsf_xml_out_start_element (xml, "conditionalFormatting");
+ xlsx_add_range (xml, "sqref", &sr->range);
+ for (ui = 0; ui < conds->len; ui++) {
+ GnmStyleCond *cond = g_ptr_array_index (conds, ui);
+ xlsx_write_cond_rule (state, xml, cond, &pp);
+ }
+ gsf_xml_out_end_element (xml); /* </conditionalFormatting> */
+ }
+
+ style_list_free (cond_styles);
+}
+
+
+static void
xlsx_write_validation_expr (XLSXClosure *info, GnmCellPos const *pos,
char const *elem, GnmExprTop const *texpr)
{
@@ -2449,6 +2647,7 @@ xlsx_write_sheet (XLSXWriteState *state, GsfOutfile *dir, GsfOutfile *wb_part, u
xlsx_write_merges (state, xml);
/* element phoneticPr { CT_PhoneticPr }?, */
/* element conditionalFormatting { CT_ConditionalFormatting }*, */
+ xlsx_write_conditional_formatting (state, xml);
/* element dataValidations { CT_DataValidations }?, */
xlsx_write_validations (state, xml, &extent);
/* element hyperlinks { CT_Hyperlinks }?, */
@@ -2580,6 +2779,8 @@ xlsx_write_workbook (XLSXWriteState *state, GsfOutfile *root_part)
state->shared_string_array = g_ptr_array_new ();
state->styles_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
state->styles_array = g_ptr_array_new ();
+ state->dxfs_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+ state->dxfs_array = g_ptr_array_new ();
xlsx_get_style_id (state, style);
gnm_style_unref (style);
@@ -2675,6 +2876,8 @@ xlsx_write_workbook (XLSXWriteState *state, GsfOutfile *root_part)
g_ptr_array_free (state->shared_string_array, TRUE);
g_hash_table_destroy (state->styles_hash);
g_ptr_array_free (state->styles_array, TRUE);
+ g_hash_table_destroy (state->dxfs_hash);
+ g_ptr_array_free (state->dxfs_array, TRUE);
if (NULL != state->chart.dir)
gsf_output_close (GSF_OUTPUT (state->chart.dir));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]