diff --git a/crates/calc/src/eval.rs b/crates/calc/src/eval.rs index 8216f5d..d31a997 100644 --- a/crates/calc/src/eval.rs +++ b/crates/calc/src/eval.rs @@ -1200,9 +1200,18 @@ impl<'h> Evaluator<'h> { let same_len = if vertical { r.range.height() == l.range.height() } else { r.range.width() == l.range.width() }; if !matches!(key, Value::Array(_)) && (vertical || horizontal) && same_len { let mut xargs = vec![Arg { value: key, from_ref: false }, Arg { value: self.area_value(&l), from_ref: true }]; - for i in [4, 5] { + // An empty match_mode before a given search_mode is the default (0), not the end. + let given = |i: usize| args.get(i).is_some_and(|e| !matches!(e, Expr::Missing)); + let last = if given(5) { + 5 + } else if given(4) { + 4 + } else { + 3 + }; + for i in 4..=last { match args.get(i) { - Some(Expr::Missing) | None => break, + Some(Expr::Missing) | None => xargs.push(Arg { value: Value::Number(0.0), from_ref: false }), Some(e) => { let value = self.value(e); xargs.push(Arg { value, from_ref: false }); diff --git a/crates/calc/src/tests.rs b/crates/calc/src/tests.rs index 8b33f93..791da35 100644 --- a/crates/calc/src/tests.rs +++ b/crates/calc/src/tests.rs @@ -118,6 +118,13 @@ fn xlookup_returns_a_reference() { assert_eq!(t.get("D6"), Value::Bool(true)); t.set("D7", "=\"x\"&XLOOKUP(\"e\",A1:A5,B1:B5)&\"y\""); assert_eq!(t.get("D7"), Value::from("xy")); + // An empty match_mode keeps the search_mode after it: search last to first. + t.set("A6", "b"); + t.set("B6", "20"); + t.set("D8", "=XLOOKUP(\"b\",A1:A6,B1:B6,,,-1)"); + assert_eq!(t.num("D8"), 20.0); + t.set("D9", "=XLOOKUP(\"b\",A1:A6,B1:B6)"); + assert_eq!(t.num("D9"), 2.0); } #[test]