Skip to main content

sheetkit_core/
table.rs

1//! Table and auto-filter management utilities.
2//!
3//! Provides functions for setting and removing auto-filters on worksheets.
4
5use crate::error::Result;
6use sheetkit_xml::worksheet::{AutoFilter, WorksheetXml};
7
8/// Configuration for a table.
9#[derive(Debug, Clone)]
10pub struct TableConfig {
11    /// The table name (used internally).
12    pub name: String,
13    /// The display name shown in the UI.
14    pub display_name: String,
15    /// The cell range (e.g. "A1:D10").
16    pub range: String,
17    /// Column definitions.
18    pub columns: Vec<TableColumn>,
19    /// Whether to show the header row.
20    pub show_header_row: bool,
21    /// The table style name (e.g. "TableStyleMedium2").
22    pub style_name: Option<String>,
23    /// Whether to enable auto-filter on the table.
24    pub auto_filter: bool,
25}
26
27/// A column within a table.
28#[derive(Debug, Clone)]
29pub struct TableColumn {
30    /// The column header name.
31    pub name: String,
32}
33
34/// Set an auto-filter on a worksheet for the given cell range.
35pub fn set_auto_filter(ws: &mut WorksheetXml, range: &str) -> Result<()> {
36    ws.auto_filter = Some(AutoFilter {
37        reference: range.to_string(),
38    });
39    Ok(())
40}
41
42/// Remove any auto-filter from a worksheet.
43pub fn remove_auto_filter(ws: &mut WorksheetXml) {
44    ws.auto_filter = None;
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50
51    #[test]
52    fn test_set_auto_filter() {
53        let mut ws = WorksheetXml::default();
54        set_auto_filter(&mut ws, "A1:D10").unwrap();
55
56        assert!(ws.auto_filter.is_some());
57        assert_eq!(ws.auto_filter.as_ref().unwrap().reference, "A1:D10");
58    }
59
60    #[test]
61    fn test_remove_auto_filter() {
62        let mut ws = WorksheetXml::default();
63        set_auto_filter(&mut ws, "A1:D10").unwrap();
64        remove_auto_filter(&mut ws);
65
66        assert!(ws.auto_filter.is_none());
67    }
68
69    #[test]
70    fn test_auto_filter_xml_roundtrip() {
71        let mut ws = WorksheetXml::default();
72        set_auto_filter(&mut ws, "A1:C100").unwrap();
73
74        let xml = quick_xml::se::to_string(&ws).unwrap();
75        assert!(xml.contains("autoFilter"));
76        assert!(xml.contains("A1:C100"));
77
78        let parsed: WorksheetXml = quick_xml::de::from_str(&xml).unwrap();
79        assert!(parsed.auto_filter.is_some());
80        assert_eq!(parsed.auto_filter.as_ref().unwrap().reference, "A1:C100");
81    }
82
83    #[test]
84    fn test_remove_auto_filter_when_none() {
85        let mut ws = WorksheetXml::default();
86        // Should not panic when removing a non-existent filter.
87        remove_auto_filter(&mut ws);
88        assert!(ws.auto_filter.is_none());
89    }
90
91    #[test]
92    fn test_overwrite_auto_filter() {
93        let mut ws = WorksheetXml::default();
94        set_auto_filter(&mut ws, "A1:B10").unwrap();
95        set_auto_filter(&mut ws, "A1:D20").unwrap();
96
97        assert_eq!(ws.auto_filter.as_ref().unwrap().reference, "A1:D20");
98    }
99
100    #[test]
101    fn test_table_config_creation() {
102        let config = TableConfig {
103            name: "Table1".to_string(),
104            display_name: "Table1".to_string(),
105            range: "A1:D10".to_string(),
106            columns: vec![
107                TableColumn {
108                    name: "Name".to_string(),
109                },
110                TableColumn {
111                    name: "Age".to_string(),
112                },
113                TableColumn {
114                    name: "City".to_string(),
115                },
116                TableColumn {
117                    name: "Score".to_string(),
118                },
119            ],
120            show_header_row: true,
121            style_name: Some("TableStyleMedium2".to_string()),
122            auto_filter: true,
123        };
124
125        assert_eq!(config.name, "Table1");
126        assert_eq!(config.columns.len(), 4);
127        assert!(config.auto_filter);
128    }
129}