mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-24 10:46:50 -06:00
AutoFilter: grow the range when a value is entered in the row below it (#2342)
This commit is contained in:
@@ -652,6 +652,24 @@ fn filter_blank(v: &Value) -> bool {
|
||||
v.is_empty() || matches!(v, Value::Text(t) if t.is_empty())
|
||||
}
|
||||
|
||||
/// Excel grows an AutoFilter range when a value is entered in the row right below it, in one of its columns (#2342).
|
||||
/// A table's own filter is left to the table, and a row typed after a blank row does not count.
|
||||
/// A formula counts before it is calculated: this runs inside the edit, ahead of the recalc.
|
||||
pub(crate) fn grow_autofilter(sh: &mut Sheet, at: CellRef) {
|
||||
if !sh.cells.get(at).is_some_and(|c| !c.value.is_empty() || c.formula.is_some()) {
|
||||
return;
|
||||
}
|
||||
let Some(af) = sh.autofilter.as_ref() else { return };
|
||||
let r = af.range;
|
||||
if r.end.row.checked_add(1) != Some(at.row) || at.col < r.start.col || at.col > r.end.col || sh.tables.iter().any(|t| t.range == r) {
|
||||
return;
|
||||
}
|
||||
let grown = RangeRef::new(r.start, CellRef::new(at.row, r.end.col));
|
||||
if let Some(af) = sh.autofilter.as_mut() {
|
||||
af.range = grown;
|
||||
}
|
||||
}
|
||||
|
||||
/// Hides rows of the autofilter range that fail any criterion.
|
||||
pub(crate) fn apply_filter(wb: &mut Workbook, sheet: usize) {
|
||||
let Some(sh) = wb.sheet(sheet) else { return };
|
||||
@@ -1554,6 +1572,30 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn autofilter_range_grows_when_a_value_is_entered_in_the_row_below() {
|
||||
let mut s = Session::new();
|
||||
s.new_workbook();
|
||||
s.execute("range.setValues", json!({"range": "A1", "values": [["Name", "Qty"], ["d", 4], ["b", 2]]})).unwrap();
|
||||
s.execute("data.filter", json!({"range": "A1:B3"})).unwrap();
|
||||
let range = |s: &Session| s.doc().unwrap().wb.active().unwrap().autofilter.as_ref().map(|a| a.range.a1());
|
||||
s.execute("cell.set", json!({"cell": "A4", "input": "e"})).unwrap();
|
||||
assert_eq!(range(&s), Some("A1:B4".to_string()));
|
||||
s.execute("range.setValues", json!({"range": "A5", "values": [["f", 6]]})).unwrap();
|
||||
assert_eq!(range(&s), Some("A1:B5".to_string()));
|
||||
// A row typed after a blank row does not grow it.
|
||||
s.execute("cell.set", json!({"cell": "A7", "input": "x"})).unwrap();
|
||||
assert_eq!(range(&s), Some("A1:B5".to_string()));
|
||||
// A cell outside the filter's columns does not either.
|
||||
s.execute("cell.set", json!({"cell": "C6", "input": "x"})).unwrap();
|
||||
assert_eq!(range(&s), Some("A1:B5".to_string()));
|
||||
// A formula and Ctrl+Enter (range.fill) are entries too.
|
||||
s.execute("cell.set", json!({"cell": "B6", "input": "=1+1"})).unwrap();
|
||||
assert_eq!(range(&s), Some("A1:B6".to_string()));
|
||||
s.execute("range.fill", json!({"range": "A7:B7", "input": "g"})).unwrap();
|
||||
assert_eq!(range(&s), Some("A1:B7".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_validation_without_formula1_is_an_error() {
|
||||
let mut s = Session::new();
|
||||
|
||||
@@ -272,6 +272,7 @@ fn cell_set(s: &mut Session, p: &Json) -> Result<Json> {
|
||||
sh.remove_cell(at);
|
||||
}
|
||||
}
|
||||
super::data::grow_autofilter(sh, at);
|
||||
cx.touch(sheet, at);
|
||||
Ok(Json::Null)
|
||||
})?;
|
||||
@@ -350,6 +351,7 @@ fn range_set_values(s: &mut Session, p: &Json) -> Result<Json> {
|
||||
sh.remove_cell(at);
|
||||
}
|
||||
}
|
||||
super::data::grow_autofilter(sh, at);
|
||||
cx.touch(sheet, at);
|
||||
count += 1;
|
||||
}
|
||||
@@ -390,7 +392,9 @@ fn range_fill(s: &mut Session, p: &Json) -> Result<Json> {
|
||||
let shifted = gridcraft_formula::adjust::shift_relative(e, at.row as i64 - origin.row as i64, at.col as i64 - origin.col as i64);
|
||||
cell.formula = Some(std::sync::Arc::new(Formula::from_expr(shifted)));
|
||||
}
|
||||
cx.sheet_mut(sheet)?.set_cell(at, cell);
|
||||
let sh = cx.sheet_mut(sheet)?;
|
||||
sh.set_cell(at, cell);
|
||||
super::data::grow_autofilter(sh, at);
|
||||
cx.touch(sheet, at);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user