From 4f3853d4a95e50b9adf7733f9cd14d16b394fb97 Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Sun, 18 Oct 2026 20:25:07 +0200 Subject: [PATCH] Hide blank and text rows for numeric ordering custom filters Found while testing crates/engine/src/cmd/data.rs:550 (custom_ok, used from apply_filter at :623) Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/engine/src/cmd/data.rs | 2 ++ crates/engine/tests/custom_filter_blanks.rs | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 crates/engine/tests/custom_filter_blanks.rs diff --git a/crates/engine/src/cmd/data.rs b/crates/engine/src/cmd/data.rs index 383624b70..09d781f84 100644 --- a/crates/engine/src/cmd/data.rs +++ b/crates/engine/src/cmd/data.rs @@ -551,6 +551,8 @@ fn custom_ok(v: &Value, text: &str, op: &str, crit: &str) -> bool { let num = gridcraft_core::parse::parse_number_text(crit); let cmp = match (v.as_f64(), num) { (Some(a), Some(b)) => a.partial_cmp(&b), + // A numeric ordering comparison only matches numbers; blanks and text never do. + (None, Some(_)) if matches!(op, "<" | "<=" | ">" | ">=") => None, _ => Some(gridcraft_core::compare_text(text, crit)), }; let wild = || super::edit::wildcard(&text.to_lowercase(), &crit.to_lowercase()); diff --git a/crates/engine/tests/custom_filter_blanks.rs b/crates/engine/tests/custom_filter_blanks.rs new file mode 100644 index 000000000..9bfd395d2 --- /dev/null +++ b/crates/engine/tests/custom_filter_blanks.rs @@ -0,0 +1,20 @@ +use gridcraft_engine::Session; +use serde_json::json; + +fn visible_rows(op: &str) -> Vec { + let mut s = Session::new(); + s.new_workbook(); + s.execute("range.setValues", json!({"range":"A1", "values":[["n"], ["3"], ["10"], [""], ["abc1"], ["20"]]})).unwrap(); + s.execute("selection.set", json!({"range":"A1:A6"})).unwrap(); + s.execute("data.filter", json!({})).unwrap(); + s.execute("data.filterBy", json!({"column":0, "custom":{"op":op, "value":"5"}})).unwrap(); + let doc = s.doc().unwrap(); + let sh = doc.wb.active().unwrap(); + (1..6u32).filter(|r| !sh.rows.get(r).is_some_and(|i| i.hidden)).collect() +} + +#[test] +fn less_than_numeric_criterion_hides_blank_and_text_rows() { + assert_eq!(visible_rows("<"), vec![1]); + assert_eq!(visible_rows("<="), vec![1]); +}