ElyTable: a filtered range keeps its rows only for a cell inside it (R2.9)

This commit is contained in:
ZacharyZhang-NY committed 2026-10-09 03:43:29 -04:00
1 parent e85884212b
commit cc67055ccc
3 files changed
+61 -12

No files matched your search

+54 -6
View File
@@ -18,6 +18,33 @@ const BLOCK: &str = r#"<?xml version="1.0" encoding="UTF-8"?>
</table:table></office:spreadsheet></office:body>
</office:document>"#;
/// Two blocks: A1:A5 as in `BLOCK`, and D1:D3.
const TWO: &str = r#"<?xml version="1.0" encoding="UTF-8"?>
<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">
<office:body><office:spreadsheet><table:table table:name="S">
<table:table-row><table:table-cell><text:p>Name</text:p></table:table-cell><table:table-cell table:number-columns-repeated="2"/><table:table-cell><text:p>Other</text:p></table:table-cell></table:table-row>
<table:table-row><table:table-cell office:value-type="float" office:value="1"><text:p>1</text:p></table:table-cell><table:table-cell table:number-columns-repeated="2"/><table:table-cell office:value-type="float" office:value="9"><text:p>9</text:p></table:table-cell></table:table-row>
<table:table-row><table:table-cell office:value-type="float" office:value="2"><text:p>2</text:p></table:table-cell><table:table-cell table:number-columns-repeated="2"/><table:table-cell office:value-type="float" office:value="10"><text:p>10</text:p></table:table-cell></table:table-row>
<table:table-row><table:table-cell office:value-type="float" office:value="3"><text:p>3</text:p></table:table-cell></table:table-row>
<table:table-row><table:table-cell office:value-type="float" office:value="6"><text:p>6</text:p></table:table-cell></table:table-row>
</table:table></office:spreadsheet></office:body>
</office:document>"#;
/// The book saved as flat XML.
fn saved(worker: &mut Worker, doc: &Doc, dir: &std::path::Path) -> String {
let out = dir.join("kept.fods");
doc.save_as(worker, &crate::file_url(&out), "fods").expect("saves");
std::fs::read_to_string(&out).expect("the saved book")
}
/// Whether the row holding `value` is hidden by a filter.
fn hidden(xml: &str, value: &str) -> bool {
let before = &xml[..xml.find(&format!("office:value=\"{value}\"")).expect("the value")];
before[before.rfind("<table:table-row").expect("its row")..].contains("table:visibility=\"filter\"")
}
/// Column A's filter entries.
fn entries(worker: &mut Worker, doc: &Doc) -> Vec<String> {
let query = sheet::cell_query(sheet::FILTER, 0, 0);
@@ -38,13 +65,9 @@ fn keep_one(worker: &mut Worker, doc: &Doc, dir: &std::path::Path) -> (String, b
worker.run(doc, "cell.goto", &["A1"]).expect("A1");
let one = r#"{"column":0,"conditions":[{"op":"values","values":["1"]}]}"#;
worker.run(doc, "data.filter", &[one]).expect("keeps 1");
let out = dir.join("kept.fods");
doc.save_as(worker, &crate::file_url(&out), "fods").expect("saves");
let xml = std::fs::read_to_string(&out).expect("the saved book");
let xml = saved(worker, doc, dir);
let range = xml.split("table:target-range-address=\"").nth(1).expect("a filter range");
let total = &xml[..xml.find("office:value=\"6\"").expect("the total")];
let row = &total[total.rfind("<table:table-row").expect("its row")..];
(range[..range.find('"').expect("closed")].to_string(), row.contains("table:visibility=\"filter\""))
(range[..range.find('"').expect("closed")].to_string(), hidden(&xml, "6"))
}
#[test]
@@ -104,3 +127,28 @@ fn a_saved_autofilter_range_keeps_its_rows_when_reopened() {
assert_eq!(keep_one(&mut worker, &doc, dir.path()), ("S.A1:S.A4".into(), false), "{format}");
}
}
#[test]
fn one_cell_in_another_block_filters_that_block() {
if install().is_none() {
eprintln!("SKIP: no pinned LOK build");
return;
}
let (dir, mut worker, doc) = open_book(TWO);
worker.run(&doc, "cell.goto", &["A1:A4"]).expect("marks the block");
worker.run(&doc, "data.autofilter", &[]).expect("filters A");
worker.run(&doc, "cell.goto", &["D1"]).expect("D1");
let nine = r#"{"conditions":[{"field":3,"op":"equals","value":"9"}]}"#;
worker.run(&doc, "data.filter", &[nine]).expect("keeps 9");
let xml = saved(&mut worker, &doc, dir.path());
assert!(hidden(&xml, "10") && !hidden(&xml, "9"), "D keeps 9 alone");
assert!(!hidden(&xml, "3") && !hidden(&xml, "6"), "A's rows past D stay");
let (_dir, mut worker, doc) = open_book(TWO);
worker.run(&doc, "cell.goto", &["A1:A4"]).expect("marks the block");
worker.run(&doc, "data.autofilter", &[]).expect("filters A");
worker.run(&doc, "cell.goto", &["D1"]).expect("D1");
worker.run(&doc, "data.autofilter", &[]).expect("filters D");
let json = worker.values(&doc, &sheet::cell_query(sheet::FILTER, 3, 0)).expect("D's entries");
let entries: Vec<String> = sheet::filter_values(&json).expect("parses").entries.into_iter().map(|e| e.text).collect();
assert_eq!(entries, ["9", "10"], "an AutoFilter from D1 is D's");
}