From afe9a6301f062315ede862e34a38f46d5199b450 Mon Sep 17 00:00:00 2001 From: MarekSpodBiedry <73122968+MarekSpodBiedry@users.noreply.github.com> Date: Mon, 12 Oct 2026 08:28:53 +0200 Subject: [PATCH] SUBTOTAL 109-111 leave out nested subtotals like 1-11 (#556) --- crates/calc/src/eval.rs | 3 ++- crates/calc/src/tests.rs | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/crates/calc/src/eval.rs b/crates/calc/src/eval.rs index 92a0a39..b76ab66 100644 --- a/crates/calc/src/eval.rs +++ b/crates/calc/src/eval.rs @@ -1315,7 +1315,8 @@ impl<'h> Evaluator<'h> { // SUBTOTAL documentation); 101-111 also leave out rows hidden by hand. let skip_filtered = name == "SUBTOTAL"; let skip_errors = matches!(options, 2 | 3 | 6 | 7); - let skip_nested = options <= 3; + // SUBTOTAL always leaves out nested SUBTOTAL/AGGREGATE cells (101-111 too); AGGREGATE does so for options 0-3. + let skip_nested = name == "SUBTOTAL" || options <= 3; let mut values = Vec::new(); let mut k = None; let refs = if name == "AGGREGATE" && func >= 14 { &rest[..1.min(rest.len())] } else { rest }; diff --git a/crates/calc/src/tests.rs b/crates/calc/src/tests.rs index 5133409..29d2292 100644 --- a/crates/calc/src/tests.rs +++ b/crates/calc/src/tests.rs @@ -562,6 +562,29 @@ fn subtotal_skips_hidden() { assert_eq!(t.num("B2"), 6.0); } +#[test] +fn subtotal_109_skips_nested_subtotal() { + let mut t = T::new(); + t.set("A1", "2"); + t.set("A2", "=SUBTOTAL(9,A1)"); + t.set("C1", "=SUBTOTAL(109,A1:A2)"); + t.set("C2", "=SUBTOTAL(9,A1:A2)"); + t.set("C3", "=SUBTOTAL(109,A1)"); + assert_eq!(t.num("C1"), 2.0); + assert_eq!(t.num("C2"), 2.0); + assert_eq!(t.num("C3"), 2.0); + // Manually hidden rows are still left out by 109 only. + let mut t = T::new(); + t.set("A1", "1"); + t.set("A2", "2"); + t.set("A3", "=SUBTOTAL(9,A1:A2)"); + t.wb.sheet_mut(0).unwrap().rows.insert(1, gridcraft_model::LineInfo { hidden: true, ..Default::default() }); + t.set("B1", "=SUBTOTAL(109,A1:A3)"); + t.set("B2", "=SUBTOTAL(9,A1:A3)"); + assert_eq!(t.num("B1"), 1.0); + assert_eq!(t.num("B2"), 3.0); +} + /// SUBTOTAL leaves out rows a filter hides for every function number, while 1-11 keep rows /// hidden by hand (as in ConditionalFormattingSamples.xlsx, where `SUBTOTAL(9,Table69[Sales])` /// under a filtered table adds only the visible rows).