mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-24 10:46:50 -06:00
Names: refuse R1C1-style names
valid_name refused R and C but took R1C1, R2, C3 and RC, which Excel refuses because they read as R1C1 references.
This commit is contained in:
@@ -218,15 +218,26 @@ fn valid_name(n: &str) -> bool {
|
||||
if !(first.is_alphabetic() || first == '_' || first == '\\') {
|
||||
return false;
|
||||
}
|
||||
if n.len() > 255 || n.eq_ignore_ascii_case("R") || n.eq_ignore_ascii_case("C") {
|
||||
return false;
|
||||
}
|
||||
if CellRef::parse(n).is_some() {
|
||||
if n.len() > 255 || CellRef::parse(n).is_some() || is_r1c1(n) {
|
||||
return false;
|
||||
}
|
||||
n.chars().all(|c| c.is_alphanumeric() || matches!(c, '_' | '.' | '\\' | '?'))
|
||||
}
|
||||
|
||||
/// Looks like an R1C1 reference (`R`, `C`, `RC`, `R2`, `C3`, `R1C1`), which Excel doesn't
|
||||
/// accept as a name.
|
||||
fn is_r1c1(n: &str) -> bool {
|
||||
let digits = |s: &str| s.bytes().take_while(u8::is_ascii_digit).count();
|
||||
let mut rest = n;
|
||||
if let Some(r) = rest.strip_prefix(['R', 'r']) {
|
||||
rest = r.get(digits(r)..).unwrap_or("");
|
||||
}
|
||||
if let Some(c) = rest.strip_prefix(['C', 'c']) {
|
||||
rest = c.get(digits(c)..).unwrap_or("");
|
||||
}
|
||||
rest.is_empty() && !n.is_empty()
|
||||
}
|
||||
|
||||
fn define_name(s: &mut Session, p: &Json) -> Result<Json> {
|
||||
let Some(name) = str_param(p, "name").map(str::to_string) else {
|
||||
s.ui_requests.push(crate::UiRequest::Dialog("defineName".into(), json!({})));
|
||||
|
||||
@@ -121,6 +121,17 @@ fn tables_and_structured_refs() {
|
||||
assert_eq!(v(&s, "B4"), Value::Number(7.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn names_that_look_like_references_are_refused() {
|
||||
let mut s = s();
|
||||
for bad in ["R1C1", "r2", "C3", "RC", "R", "c", "rc12", "A1", "XFD1048576", "1st"] {
|
||||
assert!(s.execute("formulas.defineName", json!({"name": bad, "refersTo": "=1"})).is_err(), "{bad}");
|
||||
}
|
||||
for good in ["R1C1X", "Rate", "RCx", "Rx", "_R1", "Cost"] {
|
||||
s.execute("formulas.defineName", json!({"name": good, "refersTo": "=1"})).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sheets() {
|
||||
let mut s = s();
|
||||
|
||||
Reference in New Issue
Block a user