diff --git a/crates/calc/src/eval.rs b/crates/calc/src/eval.rs index 063043a..fcc38c3 100644 --- a/crates/calc/src/eval.rs +++ b/crates/calc/src/eval.rs @@ -1320,7 +1320,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 e2f4a3a..bfe697e 100644 --- a/crates/calc/src/tests.rs +++ b/crates/calc/src/tests.rs @@ -594,6 +594,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).