Integration: #1531 fold the sheet filter into a table only when both start at the same column

A sheet AutoFilter that starts right of the table's first column is not folded
(its colId offsets would hit the wrong column); the sheet autoFilter stays
suppressed for any table it intersects, as before. Test added.
This commit is contained in:
aiongg
2026-10-22 02:35:41 +00:00
parent 8991b7d090
commit 7a016c2de9
2 changed files with 55 additions and 2 deletions
+7 -2
View File
@@ -88,7 +88,12 @@ pub fn write_sheet(wb: &Workbook, si: usize, selected: bool, out: &mut Out) -> (
.iter()
.cloned()
.map(|mut t| {
if t.header_row && t.filter_button && t.filter.is_empty() && t.range.contains_range(&af.range) {
if t.header_row
&& t.filter_button
&& t.filter.is_empty()
&& t.range.contains_range(&af.range)
&& t.range.start.col == af.range.start.col
{
t.filter = af.criteria.clone();
}
t
@@ -360,7 +365,7 @@ pub fn write_sheet(wb: &Workbook, si: usize, selected: bool, out: &mut Out) -> (
s.push_str(&protected_ranges_xml(sheet));
// autoFilter (a sheet filter overlapping a table would be invalid).
if let Some(af) = &sheet.autofilter
&& !folded.iter().any(|t| t.range.contains_range(&af.range) && t.header_row && t.filter_button)
&& !sheet.tables.iter().any(|t| t.range.intersects(&af.range))
{
s.push_str(&autofilter_xml(af.range, &af.criteria, out));
}
+48
View File
@@ -1222,3 +1222,51 @@ fn a_table_filter_criteria_survive_a_round_trip() {
assert!(b.is_row_hidden(1), "the row the filter hid is still hidden");
assert!(b.autofilter.is_none(), "a table's filter belongs to the table part, not the sheet");
}
/// Stored `colId` offsets are relative to the filter range's first column, so criteria of a filter
/// that starts right of the table's first column must not be folded into the table part, where
/// they would apply to the wrong column.
#[test]
fn a_partial_sheet_filter_is_not_folded_into_a_table() {
let mut wb = Workbook::new();
let s = wb.sheet_mut(0).unwrap();
for (a, v) in [("A1", "Id"), ("B1", "Region"), ("A2", "1"), ("B2", "East"), ("A3", "2"), ("B3", "West")] {
s.set_value(at(a), Value::text(v));
}
let column = |name: &str| TableColumn {
name: name.into(),
totals: TotalsFn::None,
totals_label: None,
formula: None,
unique_name: None,
xml: None,
};
s.tables.push(Table {
id: 1,
name: "Sales".into(),
range: rr("A1:B3"),
header_row: true,
totals_row: false,
columns: vec![column("Id"), column("Region")],
style: "TableStyleMedium2".into(),
banded_rows: true,
banded_cols: false,
first_col: false,
last_col: false,
filter_button: true,
filter: vec![],
table_type: None,
connection_id: None,
});
s.autofilter = Some(AutoFilter {
range: rr("B1:B3"),
criteria: vec![(0, FilterCriterion::Values { values: vec!["East".into()], blanks: false })],
});
let (back, rep) = read_xlsx(&write_xlsx(&wb).unwrap()).unwrap();
assert!(rep.warnings.is_empty(), "{:?}", rep.warnings);
let b = back.sheet(0).unwrap();
let t = b.tables.first().expect("the table survived");
assert!(t.filter.is_empty(), "the criteria landed on the wrong table column: {:?}", t.filter);
assert!(b.autofilter.is_none(), "a sheet filter inside a table would be invalid");
}