Skip to main content

easydoc_core/metadata/
column.rs

1use crate::types::HorizontalAlignment;
2
3/// 表格中单列的描述符。
4///
5/// 由 `#[derive(DocxRow)]` 从字段注解生成。
6///
7/// 对应 Java: `com.alibaba.excel.metadata.ExcelColumn` / `ExcelProperty` 注解属性
8#[derive(Debug, Clone)]
9pub struct TableColumn {
10    /// Column header text (displayed in the table header row).
11    pub name: String,
12    /// Rust field name (used for reverse lookup).
13    pub field_name: String,
14    /// Zero-based column index in the table.
15    pub index: usize,
16    /// Order for column sorting (lower = leftmost).
17    pub order: u32,
18    /// Column width as a CSS-like string (e.g. `"2cm"`, `"80px"`, `"auto"`),
19    /// or `None` for auto-width.
20    pub width: Option<String>,
21    /// Number or date format pattern (e.g. `"#,##0.00"`, `"yyyy-mm-dd"`),
22    /// if applicable.
23    pub format: Option<String>,
24    /// Horizontal alignment override for cells in this column.
25    pub align: Option<HorizontalAlignment>,
26    /// Custom converter type path (e.g. `"StatusConverter"`),
27    /// used by `from_row_with_converters` / `to_row_with_converters`.
28    pub converter: Option<String>,
29    /// Whether text in this column should wrap.
30    pub wrap: bool,
31    /// Whether the field should be ignored during read/write.
32    pub ignored: bool,
33}
34
35impl TableColumn {
36    /// 创建新的列描述符。
37    #[must_use]
38    pub fn new(name: impl Into<String>, field_name: impl Into<String>, index: usize) -> Self {
39        Self {
40            name: name.into(),
41            field_name: field_name.into(),
42            index,
43            order: index as u32,
44            width: None,
45            format: None,
46            align: None,
47            converter: None,
48            wrap: false,
49            ignored: false,
50        }
51    }
52
53    /// 设置显示名称。
54    #[must_use]
55    pub fn name(mut self, name: impl Into<String>) -> Self {
56        self.name = name.into();
57        self
58    }
59
60    /// 设置列排序顺序。
61    #[must_use]
62    pub fn order(mut self, order: u32) -> Self {
63        self.order = order;
64        self
65    }
66
67    /// 设置列宽(CSS 风格字符串,如 `"2cm"`、`"80px"`)。
68    #[must_use]
69    pub fn width(mut self, width: impl Into<String>) -> Self {
70        self.width = Some(width.into());
71        self
72    }
73
74    /// 设置数字/日期列的格式模式。
75    #[must_use]
76    pub fn format(mut self, format: impl Into<String>) -> Self {
77        self.format = Some(format.into());
78        self
79    }
80
81    /// 设置此列的水平对齐方式。
82    #[must_use]
83    pub fn align(mut self, align: HorizontalAlignment) -> Self {
84        self.align = Some(align);
85        self
86    }
87
88    /// 设置此列的自定义转换器类型名。
89    #[must_use]
90    pub fn converter(mut self, converter: impl Into<String>) -> Self {
91        self.converter = Some(converter.into());
92        self
93    }
94
95    /// 启用此列的文本换行。
96    #[must_use]
97    pub fn wrap(mut self) -> Self {
98        self.wrap = true;
99        self
100    }
101
102    /// 标记此列在读写时被忽略。
103    ///
104    /// 对应 Java: `ExcelProperty` 的 `@ExcelIgnore` 注解
105    #[must_use]
106    pub fn ignore(mut self) -> Self {
107        self.ignored = true;
108        self
109    }
110}
111
112#[cfg(test)]
113mod tests {
114    use super::*;
115    use crate::types::HorizontalAlignment;
116
117    #[test]
118    fn column_new() {
119        let c = TableColumn::new("Name", "name", 0);
120        assert_eq!(c.name, "Name");
121        assert_eq!(c.field_name, "name");
122        assert_eq!(c.index, 0);
123        assert_eq!(c.order, 0);
124        assert!(c.width.is_none());
125        assert!(c.format.is_none());
126        assert!(c.align.is_none());
127        assert!(c.converter.is_none());
128        assert!(!c.wrap);
129        assert!(!c.ignored);
130    }
131
132    #[test]
133    fn column_builder_chain() {
134        let c = TableColumn::new("Age", "age", 1)
135            .name("User Age")
136            .order(5)
137            .width("2cm")
138            .format("%Y-%m-%d")
139            .align(HorizontalAlignment::Center)
140            .converter("AgeConverter")
141            .wrap()
142            .ignore();
143        assert_eq!(c.name, "User Age");
144        assert_eq!(c.order, 5);
145        assert_eq!(c.width.as_deref(), Some("2cm"));
146        assert_eq!(c.format.as_deref(), Some("%Y-%m-%d"));
147        assert_eq!(c.align, Some(HorizontalAlignment::Center));
148        assert_eq!(c.converter.as_deref(), Some("AgeConverter"));
149        assert!(c.wrap);
150        assert!(c.ignored);
151    }
152
153    #[test]
154    fn column_builder_width_string_variants() {
155        let c = TableColumn::new("X", "x", 0).width("80px");
156        assert_eq!(c.width.as_deref(), Some("80px"));
157
158        let c = TableColumn::new("X", "x", 0).width("auto");
159        assert_eq!(c.width.as_deref(), Some("auto"));
160    }
161}