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}