From c8a47c9fb3adcf7b2f52ef069d26215097ead083 Mon Sep 17 00:00:00 2001 From: MarekSpodBiedry <73122968+MarekSpodBiedry@users.noreply.github.com> Date: Mon, 12 Oct 2026 08:31:44 +0200 Subject: [PATCH] Read omitted val on chart smooth and showVal as on (#518) --- crates/xlsx/src/chart.rs | 4 +-- crates/xlsx/src/tests/chart_bool_default.rs | 32 +++++++++++++++++++++ crates/xlsx/src/tests/mod.rs | 1 + 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 crates/xlsx/src/tests/chart_bool_default.rs diff --git a/crates/xlsx/src/chart.rs b/crates/xlsx/src/chart.rs index 052d620..020ce67 100644 --- a/crates/xlsx/src/chart.rs +++ b/crates/xlsx/src/chart.rs @@ -106,7 +106,7 @@ fn read_series(s: &El) -> Series { color, secondary: false, kind: None, - smooth: s.child("smooth").and_then(|e| e.attr("val")).and_then(|v| v.parse::().ok()).is_some_and(|v| v != 0), + smooth: bool_val(s, "smooth"), trendlines: s.kids("trendline").filter_map(read_trendline).collect(), } } @@ -201,7 +201,7 @@ pub fn read_chart(root: &El) -> Option { } } let kind = if groups.len() > 1 { ChartKind::Combo } else { first_kind }; - let show_val = |e: &El| e.child("dLbls").and_then(|d| d.child_val("showVal")).is_some_and(|v| v == "1" || v == "true"); + let show_val = |e: &El| e.child("dLbls").is_some_and(|d| bool_val(d, "showVal")); let data_labels = groups.iter().any(|(g, _)| show_val(g) || g.kids("ser").any(show_val)); let val_axes: Vec<&El> = plot.kids("valAx").collect(); let cat_ax = plot.child("catAx").or_else(|| plot.child("dateAx")); diff --git a/crates/xlsx/src/tests/chart_bool_default.rs b/crates/xlsx/src/tests/chart_bool_default.rs new file mode 100644 index 0000000..e9a074c --- /dev/null +++ b/crates/xlsx/src/tests/chart_bool_default.rs @@ -0,0 +1,32 @@ +//! A `CT_Boolean` chart flag with no `val` attribute is on (ECMA-376), for series smoothing and value labels. + +use crate::chart::read_chart; +use crate::xml::parse; + +/// Reads a line chart with `ser` appended to its one series and `group` inside the group's ``. +fn flags(ser: &str, group: &str) -> (bool, bool) { + let xml = format!( + "\ + \ + Data!$A$1:$A$5{ser}{group}\ + \ + " + ); + let root = parse(xml.as_bytes()).unwrap(); + let ch = read_chart(&root).unwrap(); + (ch.series[0].smooth, ch.data_labels) +} + +#[test] +fn omitted_val_means_on() { + assert_eq!(flags("", ""), (true, true)); + assert_eq!(flags("", ""), (false, true), "series-level value labels"); +} + +#[test] +fn explicit_values_are_honoured() { + assert_eq!(flags("", ""), (true, true)); + assert_eq!(flags("", ""), (true, true)); + assert_eq!(flags("", ""), (false, false)); + assert_eq!(flags("", ""), (false, false)); +} diff --git a/crates/xlsx/src/tests/mod.rs b/crates/xlsx/src/tests/mod.rs index d5d2f2f..eef5d5f 100644 --- a/crates/xlsx/src/tests/mod.rs +++ b/crates/xlsx/src/tests/mod.rs @@ -1,6 +1,7 @@ //! Integration-style tests: round trips, hand-written fixtures, hostile input and CSV. mod array_export; +mod chart_bool_default; mod csv_tests; mod encrypted_tests; mod fixtures;