diff --git a/crates/engine/src/cmd/pivot/fields.rs b/crates/engine/src/cmd/pivot/fields.rs index 48c25657c..55036f541 100644 --- a/crates/engine/src/cmd/pivot/fields.rs +++ b/crates/engine/src/cmd/pivot/fields.rs @@ -507,9 +507,13 @@ pub(super) fn value_settings(s: &mut Session, p: &Json) -> Result { let mut v = cur.clone(); if let Some(f) = func { v.func = f; - // An automatic caption follows the function. - let auto = auto_name(cur.func, &cur.source_col); - if cur.name.eq_ignore_ascii_case(&auto) || cur.name.strip_prefix(auto.as_str()).is_some_and(|r| r.chars().all(|c| c.is_ascii_digit())) { + // An automatic caption follows the function. Count Numbers was captioned "Count + // Numbers of …" before it took Excel's "Count of …", and saved workbooks still carry it. + let is_auto = |base: &str| { + cur.name.eq_ignore_ascii_case(base) || cur.name.strip_prefix(base).is_some_and(|r| r.chars().all(|c| c.is_ascii_digit())) + }; + let legacy = cur.func == PivotFunc::CountNumbers && is_auto(&format!("Count Numbers of {}", cur.source_col)); + if is_auto(&auto_name(cur.func, &cur.source_col)) || legacy { v.name = unique_value_name(pt, &auto_name(f, &cur.source_col), Some(i)); } } diff --git a/crates/engine/src/cmd/pivot/tests.rs b/crates/engine/src/cmd/pivot/tests.rs index 1733a2664..308d30f4a 100644 --- a/crates/engine/src/cmd/pivot/tests.rs +++ b/crates/engine/src/cmd/pivot/tests.rs @@ -1029,3 +1029,20 @@ fn rank_ties_are_dense_and_count_numbers_is_captioned_count_of() { s.execute("pivot.valueSettings", json!({"index": 0, "showAs": "normal", "func": "countNumbers"})).unwrap(); assert_eq!(text(&s, "E3"), "Count of Val"); } + +#[test] +fn legacy_count_numbers_caption_follows_the_function() { + // Workbooks saved before Count Numbers was captioned "Count of" carry "Count Numbers of Val"; + // that is still an automatic caption, so it follows a new function. A custom name stays. + let mut s = Session::new(); + s.new_workbook(); + let rows = json!([["Key", "Val"], ["A", 5], ["B", 4]]); + s.execute("range.setValues", json!({"range": "A1", "values": rows})).unwrap(); + s.execute("insert.pivotTable", json!({"source": "Sheet1!$A$1:$B$3", "destination": "Sheet1!D3", "rows": ["Key"], "values": ["Val"]})).unwrap(); + for (legacy, after) in [("Count Numbers of Val", "Sum of Val"), ("Count Numbers of Val2", "Sum of Val"), ("Numbers counted", "Numbers counted")] { + s.execute("pivot.valueSettings", json!({"index": 0, "func": "countNumbers", "name": legacy})).unwrap(); + assert_eq!(text(&s, "E3"), legacy); + s.execute("pivot.valueSettings", json!({"index": 0, "func": "sum"})).unwrap(); + assert_eq!(text(&s, "E3"), after, "{legacy}"); + } +}