mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-24 10:46:50 -06:00
Tables: Format as Table inside a table restyles it
Home > Format as Table on a cell or range inside an existing table failed with "A table can't overlap another table." Excel applies the picked style to that table instead. The command now returns that table and its range, as it does for a new table. A range crossing a table's edge is still rejected. Without a range, the active area of the selection decides, as it does for Insert > Table. The native Format menu's Format as Table now runs home.formatAsTable instead of insert.table.
This commit is contained in:
@@ -125,7 +125,7 @@ fn tree() -> Vec<(&'static str, Vec<Entry>)> {
|
||||
("Unhide Sheet…", "sheet.unhide", None),
|
||||
("-", "", None),
|
||||
("Conditional Formatting…", "dialog:manageRules", None),
|
||||
("Format as Table", "insert.table", None),
|
||||
("Format as Table", "home.formatAsTable", None),
|
||||
],
|
||||
),
|
||||
(
|
||||
|
||||
@@ -26,9 +26,9 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Format as Table",
|
||||
["Home", "Styles"],
|
||||
None,
|
||||
"{range?, style: \"TableStyleMedium2\", header?}",
|
||||
"{range?, style: \"TableStyleMedium2\", header?} (inside a table: restyles it)",
|
||||
has_doc,
|
||||
insert_table
|
||||
format_as_table
|
||||
),
|
||||
cmd!("table.totalRow", "Total Row", ["Table", "Table Style Options"], None, "{table?, on?: bool}", has_doc, |s, p| table_flag(
|
||||
s, p, "totals"
|
||||
@@ -351,6 +351,21 @@ fn insert_table(s: &mut Session, p: &Json) -> Result<Json> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Format as Table inside a table restyles that table, as in Excel; elsewhere it makes a new one.
|
||||
fn format_as_table(s: &mut Session, p: &Json) -> Result<Json> {
|
||||
// Without a range, the active area decides (as in insert_table), not the first one.
|
||||
let r = if p.get("range").is_some() { target_range(s, p)? } else { s.doc()?.selection.current() };
|
||||
let sheet = target_sheet(s, p)?;
|
||||
let inside = s.doc()?.wb.sheet(sheet).and_then(|sh| sh.tables.iter().find(|t| t.range.contains_range(&r))).map(|t| (t.name.clone(), t.range));
|
||||
match inside {
|
||||
Some((table, range)) => {
|
||||
table_style(s, &with(p, "table", json!(table)))?;
|
||||
Ok(json!({"table": table, "range": range.a1()}))
|
||||
}
|
||||
None => insert_table(s, p),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_table(s: &Session, p: &Json) -> Result<(usize, usize)> {
|
||||
let d = s.doc()?;
|
||||
if let Some(n) = str_param(p, "table") {
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
use gridcraft_engine::Session;
|
||||
use serde_json::json;
|
||||
|
||||
fn table() -> Session {
|
||||
let mut s = Session::new();
|
||||
s.new_workbook();
|
||||
s.execute("range.setValues", json!({"range":"A1", "values":[["Item", "Qty"], ["x", "7"], ["y", "8"]]})).unwrap();
|
||||
s.execute("insert.table", json!({"range":"A1:B3", "header":true, "name":"T"})).unwrap();
|
||||
s
|
||||
}
|
||||
|
||||
fn styles(s: &Session) -> Vec<String> {
|
||||
s.doc().unwrap().wb.active().unwrap().tables.iter().map(|t| t.style.clone()).collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_as_table_inside_a_table_restyles_it() {
|
||||
let mut s = table();
|
||||
s.execute("selection.set", json!({"range":"B2"})).unwrap();
|
||||
s.execute("home.formatAsTable", json!({"style":"TableStyleLight9"})).unwrap();
|
||||
assert_eq!(styles(&s), ["TableStyleLight9"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_as_table_on_a_range_inside_a_table_restyles_it() {
|
||||
let mut s = table();
|
||||
s.execute("home.formatAsTable", json!({"range":"A2:B3", "style":"TableStyleDark3"})).unwrap();
|
||||
assert_eq!(styles(&s), ["TableStyleDark3"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_as_table_across_a_table_edge_is_rejected() {
|
||||
let mut s = table();
|
||||
let e = s.execute("home.formatAsTable", json!({"range":"A1:C3", "style":"TableStyleLight9"})).unwrap_err();
|
||||
assert!(e.to_string().contains("overlap"), "{e}");
|
||||
assert_eq!(styles(&s), ["TableStyleMedium2"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_as_table_inside_a_table_returns_that_table() {
|
||||
let mut s = table();
|
||||
let r = s.execute("home.formatAsTable", json!({"range":"B2", "style":"TableStyleLight9"})).unwrap();
|
||||
assert_eq!(r, json!({"table":"T", "range":"A1:B3"}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_as_table_uses_the_active_area_of_a_multi_area_selection() {
|
||||
let mut s = table();
|
||||
s.execute("selection.set", json!({"range":"D10:E11,B2"})).unwrap();
|
||||
s.execute("home.formatAsTable", json!({"style":"TableStyleLight9"})).unwrap();
|
||||
assert_eq!(styles(&s), ["TableStyleLight9"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_as_table_inside_a_table_with_data_beside_it_restyles_it() {
|
||||
let mut s = table();
|
||||
s.execute("range.setValues", json!({"range":"C1", "values":[["Note"], ["a"], ["b"]]})).unwrap();
|
||||
s.execute("selection.set", json!({"range":"B2"})).unwrap();
|
||||
s.execute("home.formatAsTable", json!({"style":"TableStyleLight9"})).unwrap();
|
||||
assert_eq!(styles(&s), ["TableStyleLight9"]);
|
||||
}
|
||||
Reference in New Issue
Block a user