diff --git a/crates/engine/src/cmd/insert.rs b/crates/engine/src/cmd/insert.rs index 0d58b0da5..985bb2a8a 100644 --- a/crates/engine/src/cmd/insert.rs +++ b/crates/engine/src/cmd/insert.rs @@ -1274,8 +1274,8 @@ fn is_string_literal(v: &str) -> bool { /// A conditional format's `style` as the model's `Style` JSON (`font`, `fill`, `borders`, `align`, /// `num_fmt`, `protection`, merged over the default by the caller), where a colour may also be /// written as `format_range` takes it (`"#RRGGBB"`, `{theme, tint}`, `"auto"`) and `fill` may be a -/// colour alone (a solid fill). An unknown key is an error rather than dropped: dropped, it left a -/// rule with an empty format that matches and shows nothing. +/// colour alone (a solid fill) or `"none"` (no fill). An unknown key is an error rather than +/// dropped: dropped, it left a rule with an empty format that matches and shows nothing. fn cf_style_json(st: &Json) -> Result { const KEYS: [&str; 6] = ["font", "fill", "borders", "align", "num_fmt", "protection"]; let err = |m: String| bad("home.conditionalFormat", m); @@ -1299,7 +1299,10 @@ fn cf_style_json(st: &Json) -> Result { color(c, "font.color")?; } if let Some(fill) = st.get_mut("fill") { - if fill.is_string() || fill.get("theme").is_some() { + // `"none"` (or `"auto"`) is no fill, as `home.fillColor` reads it, not a solid automatic one. + if fill.is_string() && super::format::color_param(Some(fill)) == Some(Color::Auto) { + *fill = serde_json::to_value(Fill::default()).map_err(|e| EngineError::Other(e.to_string()))?; + } else if fill.is_string() || fill.get("theme").is_some() { *fill = json!({"pattern": "Solid", "fg": fill.clone()}); } if let Some(f) = fill.as_object_mut() { diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 7b3fff840..1af74e67e 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -2643,6 +2643,14 @@ fn conditional_format_styles_take_hex_colours_and_quoted_values() { s.execute("home.conditionalFormat", json!({"range": "A1", "rule": {"type": "expression", "formula": "=TRUE", "style": internal}})).unwrap(); let st = style(&rule(&s, 0)); assert_eq!((st.fill.fg, st.borders.left.color), (Color::Rgb(0xFFF2CC), Color::Rgb(0xC00000))); + // `"none"` is no fill (the format only sets the font), as `home.fillColor` reads it. + s.execute( + "home.conditionalFormat", + json!({"range": "A1", "rule": {"type": "expression", "formula": "=TRUE", "style": {"fill": "none", "font": {"bold": true}}}}), + ) + .unwrap(); + let st = style(&rule(&s, 0)); + assert_eq!((st.fill, st.font.bold), (Fill::default(), true)); // Keys that would be dropped, leaving a rule that shows nothing, are refused. let n = s.doc().unwrap().wb.active().unwrap().cond_formats.len(); for bad in [json!({"preset": "greenFill"}), json!({"fillColor": "#FFF2CC"}), json!({"fill": "#nothex"}), json!("bold")] {