mirror of
https://github.com/storytold/gridcraft.git
synced 2026-11-02 16:30:50 -06:00
Sort: case-sensitive order puts lowercase before uppercase
With Case sensitive checked, Sort compared text by code point, so every uppercase word came before every lowercase one (A, B, a, b). Excel compares ignoring case first and only then puts lowercase before uppercase: a, A, b, B.
This commit is contained in:
@@ -248,7 +248,7 @@ fn do_sort(s: &mut Session, r: RangeRef, header: bool, keys: Vec<SortKey>, by_co
|
||||
let pos = |v: &Value| v.as_text().and_then(|t| list.iter().position(|x| x.eq_ignore_ascii_case(t))).unwrap_or(usize::MAX);
|
||||
pos(va).cmp(&pos(vb))
|
||||
} else if case && va.is_text() && vb.is_text() {
|
||||
va.as_text().unwrap_or("").cmp(vb.as_text().unwrap_or(""))
|
||||
sort_compare(va, vb).then_with(|| case_order(va.as_text().unwrap_or(""), vb.as_text().unwrap_or("")))
|
||||
} else {
|
||||
sort_compare(va, vb)
|
||||
};
|
||||
@@ -653,6 +653,12 @@ pub fn filter_values(wb: &Workbook, sheet: usize, col: u32) -> Vec<(String, bool
|
||||
seen.into_iter().map(|((_, t), on)| (t, on)).collect()
|
||||
}
|
||||
|
||||
/// Case-sensitive tie-break for text that is equal ignoring case: as in Excel, lowercase sorts
|
||||
/// before uppercase at the first letter that differs in case.
|
||||
fn case_order(a: &str, b: &str) -> Ordering {
|
||||
a.chars().zip(b.chars()).find(|(x, y)| x != y).map_or(Ordering::Equal, |(x, y)| y.is_lowercase().cmp(&x.is_lowercase()))
|
||||
}
|
||||
|
||||
fn sort_key(v: &Value) -> (u8, i64, String) {
|
||||
match v {
|
||||
Value::Number(n) => (0, (n * 1e6) as i64, String::new()),
|
||||
|
||||
@@ -606,6 +606,15 @@ fn hidden_formulas_stay_hidden_on_protected_sheets() {
|
||||
assert_eq!(r["results"][0]["value"], "7");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn case_sensitive_sort_puts_lowercase_first() {
|
||||
let mut s = s();
|
||||
s.execute("range.setValues", json!({"range": "A1", "values": [["b"], ["B"], ["Ab"], ["a"], ["aB"], ["A"]]})).unwrap();
|
||||
s.execute("data.sort", json!({"range": "A1:A6", "header": false, "matchCase": true, "keys": [{"column": "A"}]})).unwrap();
|
||||
let col: Vec<Value> = (1..=6).map(|r| v(&s, &format!("A{r}"))).collect();
|
||||
assert_eq!(col, ["a", "A", "aB", "Ab", "b", "B"].map(Value::from));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formatting_and_styles() {
|
||||
let mut s = s();
|
||||
|
||||
Reference in New Issue
Block a user