Merge pull request #749 from marcoarnulfo:fix/structured-ref-column-spaces
This commit is contained in:
commit
773bd6c1ae
|
|
@ -1059,6 +1059,33 @@ fn tables_and_structured_refs() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn structured_refs_to_columns_with_edge_spaces() {
|
||||
let mut s = s();
|
||||
s.execute("range.setValues", json!({"range": "A1", "values": [["Item", "Qty "], ["a", 2], ["b", 3]]})).unwrap();
|
||||
s.execute("insert.table", json!({"range": "A1:B3", "hasHeaders": true})).unwrap();
|
||||
s.execute("table.totalRow", json!({"on": true, "table": "Table1"})).unwrap();
|
||||
assert_eq!(v(&s, "B4"), Value::Number(5.0));
|
||||
for (cell, input) in [
|
||||
("F1", "=SUM(Table1[Qty ])"),
|
||||
("F2", "=Table1[[#Totals],[Qty ]]"),
|
||||
("F3", "=SUBTOTAL(109,Table1[Qty ])"),
|
||||
("F4", "=SUM(Table1[[Qty ]])"),
|
||||
("F5", "=SUM(Table1[Qty])"),
|
||||
("C2", "=Table1[@[Qty ]]*10"),
|
||||
] {
|
||||
s.execute("cell.set", json!({"cell": cell, "input": input})).unwrap();
|
||||
}
|
||||
let n = Value::Number;
|
||||
assert_eq!([v(&s, "F1"), v(&s, "F2"), v(&s, "F3"), v(&s, "F4")], [n(5.0), n(5.0), n(5.0), n(5.0)]);
|
||||
assert_eq!(v(&s, "F5"), Value::Error(gridcraft_core::CellError::Ref));
|
||||
assert_eq!(v(&s, "C2"), n(20.0));
|
||||
assert_eq!(s.execute("cell.get", json!({"cell": "F3"})).unwrap()["formula"], "=SUBTOTAL(109,Table1[[Qty ]])");
|
||||
|
||||
let r = s.execute("file.saveBytes", json!({"format": "xlsx"})).unwrap();
|
||||
let b64 = r["base64"].as_str().unwrap().to_string();
|
||||
s.execute("file.open", json!({"name": "x.xlsx", "base64": b64})).unwrap();
|
||||
assert_eq!(s.execute("cell.get", json!({"cell": "F3"})).unwrap()["formula"], "=SUBTOTAL(109,Table1[[Qty ]])");
|
||||
assert_eq!([v(&s, "F1"), v(&s, "F2"), v(&s, "F3")], [n(5.0), n(5.0), n(5.0)]);
|
||||
fn table_rename_keeps_a_defined_name_with_the_same_name() {
|
||||
let mut s = s();
|
||||
s.execute("range.setValues", json!({"range": "A1", "values": [["Qty"], [7]]})).unwrap();
|
||||
|
|
|
|||
|
|
@ -426,6 +426,9 @@ fn combine(op: BinOp, lhs: Expr, rhs: Expr) -> Expr {
|
|||
pub fn parse_struct(table: &str, body: &str) -> Result<StructRef, String> {
|
||||
let mut specifiers = Vec::new();
|
||||
let mut cols: Vec<String> = Vec::new();
|
||||
// Spaces at the edges of a column name are part of it (`Table1[Qty ]` names `Qty `), so the
|
||||
// untrimmed body is what a lone column is read from.
|
||||
let raw = body;
|
||||
let body = body.trim();
|
||||
let unescape = |s: &str| {
|
||||
let mut out = String::new();
|
||||
|
|
@ -477,7 +480,7 @@ pub fn parse_struct(table: &str, body: &str) -> Result<StructRef, String> {
|
|||
} else if let Some(i) = item(body) {
|
||||
specifiers.push(i);
|
||||
} else if !body.is_empty() {
|
||||
cols.push(column(body)?);
|
||||
cols.push(column(raw)?);
|
||||
}
|
||||
} else {
|
||||
// [[#Headers],[Col1]:[Col3]], [[#This Row],[Col 1]] or [[#This Row],Col1]
|
||||
|
|
|
|||
|
|
@ -119,7 +119,12 @@ fn write_struct_ref(s: &StructRef, at_shorthand: bool) -> String {
|
|||
let _ = write!(out, "[{}]", s.specifiers.first().map(item).unwrap_or(""));
|
||||
}
|
||||
(Some(c), None) if s.specifiers.is_empty() => {
|
||||
let _ = write!(out, "[{}]", esc(c));
|
||||
// Excel writes a name with spaces at its edges in the double-bracket form.
|
||||
if c.trim() == c {
|
||||
let _ = write!(out, "[{}]", esc(c));
|
||||
} else {
|
||||
let _ = write!(out, "[[{}]]", esc(c));
|
||||
}
|
||||
}
|
||||
(Some(c), None) if this_row => {
|
||||
if simple_col(c) {
|
||||
|
|
|
|||
|
|
@ -274,6 +274,20 @@ fn unbracketed_this_row_column() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn struct_column_keeps_edge_spaces() {
|
||||
// The spaces are part of the column name: `Table1[Qty ]` names `Qty `, never `Qty`.
|
||||
let Expr::Struct(s) = parse("Table1[Qty ]").unwrap() else { panic!() };
|
||||
assert_eq!(s.col_start.as_deref(), Some("Qty "));
|
||||
let Expr::Struct(s) = parse("Table1[ Qty]").unwrap() else { panic!() };
|
||||
assert_eq!(s.col_start.as_deref(), Some(" Qty"));
|
||||
// Excel writes such a column in the double-bracket form.
|
||||
assert_eq!(rt("Table1[Qty ]"), "Table1[[Qty ]]");
|
||||
for f in ["Table1[[Qty ]]", "Table1[[ Sum for Q2 ]]", "Table1[[#Totals],[Qty ]]", "Table1[@[Qty ]]", "Table1[Unit Price]"] {
|
||||
assert_eq!(rt(f), f);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trim_references() {
|
||||
for f in [
|
||||
|
|
|
|||
Loading…
Reference in New Issue