Skip to main content

easydoc_writer/builder/
table_builder.rs

1//! 快速表格写入器 -- 一行代码 `Vec<Struct>` -> DOCX 表格。
2//!
3//! 对应 Java: `EasyExcel.write(path).head(RowClass.class).sheet().doWrite(data)`
4
5use std::path::PathBuf;
6
7use easydoc_core::DocxRow;
8use easydoc_core::Result;
9use easydoc_core::style::TableStyle;
10
11use crate::executor::table_executor::TableWriteExecutor;
12
13/// 将类型化 `Vec<T>` 写入 DOCX 表格的 Fluent 构建器。
14///
15/// 通过门面 `EasyDoc::write_table()` 方法创建。
16///
17/// 对应 Java: `EasyExcel.write(path).head(RowClass.class).sheet().doWrite(data)`
18///
19/// # 示例
20///
21/// ```ignore
22/// EasyDoc::write_table("users.docx", &users)
23///     .title("User List")
24///     .header_style(TableStyle::header())
25///     .do_write()?;
26/// ```
27pub struct TableWriteBuilder<'a, T: DocxRow> {
28    path: PathBuf,
29    data: &'a [T],
30    title: Option<String>,
31    style: TableStyle,
32    need_header: bool,
33}
34
35impl<'a, T: DocxRow> TableWriteBuilder<'a, T> {
36    /// Creates a new table write builder.
37    #[must_use]
38    pub fn new(path: impl Into<PathBuf>, data: &'a [T]) -> Self {
39        Self {
40            path: path.into(),
41            data,
42            title: None,
43            style: TableStyle::default(),
44            need_header: true,
45        }
46    }
47
48    /// Sets a document title (heading above the table).
49    #[must_use]
50    pub fn title(mut self, title: impl Into<String>) -> Self {
51        self.title = Some(title.into());
52        self
53    }
54
55    /// Controls whether the header row is emitted.
56    #[must_use]
57    pub fn need_header(mut self, need: bool) -> Self {
58        self.need_header = need;
59        self
60    }
61
62    /// Sets the table style.
63    #[must_use]
64    pub fn header_style(mut self, style: TableStyle) -> Self {
65        self.style = style;
66        self
67    }
68
69    /// Enables zebra striping on the table.
70    #[must_use]
71    pub fn banded_rows(mut self, enabled: bool) -> Self {
72        self.style.banded_rows = enabled;
73        self
74    }
75
76    /// Executes the write and saves the document to disk.
77    ///
78    /// # Errors
79    ///
80    /// Returns I/O or conversion errors.
81    pub fn do_write(self) -> Result<()> {
82        let executor = TableWriteExecutor::new(
83            self.path,
84            self.data,
85            self.title,
86            self.style,
87            self.need_header,
88        );
89        executor.execute()
90    }
91
92    /// Executes the write and returns the document as bytes.
93    ///
94    /// Useful for in-memory generation without touching the filesystem.
95    /// Corresponds to Hutool's pattern of writing to a `ByteArrayOutputStream`.
96    ///
97    /// # Errors
98    ///
99    /// Returns ZIP or conversion errors.
100    pub fn do_write_to_bytes(self) -> Result<Vec<u8>> {
101        let executor = TableWriteExecutor::new(
102            self.path,
103            self.data,
104            self.title,
105            self.style,
106            self.need_header,
107        );
108        executor.execute_to_bytes()
109    }
110
111    /// Executes the write to a generic writer implementing `Write + Seek`.
112    ///
113    /// Corresponds to Hutool's `flush(OutputStream)`.
114    ///
115    /// # Errors
116    ///
117    /// Returns I/O, ZIP, or conversion errors.
118    pub fn do_write_to_writer<W: std::io::Write + std::io::Seek>(self, writer: W) -> Result<()> {
119        let executor = TableWriteExecutor::new(
120            self.path,
121            self.data,
122            self.title,
123            self.style,
124            self.need_header,
125        );
126        executor.execute_to_writer(writer)
127    }
128}