1use indexmap::IndexMap;
2
3use crate::CellReference;
4
5#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
6pub enum HeaderMode {
7 #[default]
8 Auto,
9 None,
10 FirstRow,
11}
12
13#[derive(Clone, Debug, Eq, PartialEq)]
14pub struct ReadOptions {
15 sheet_name: Option<String>,
16 start_cell: CellReference,
17 end_cell: Option<CellReference>,
18 header_mode: HeaderMode,
19 ignore_empty_rows: bool,
20 trim_headers: bool,
21}
22
23impl ReadOptions {
24 #[must_use]
25 pub fn new() -> Self {
26 Self::default()
27 }
28
29 #[must_use]
30 pub fn with_sheet_name(mut self, sheet_name: impl Into<String>) -> Self {
31 self.sheet_name = Some(sheet_name.into());
32 self
33 }
34
35 #[must_use]
36 pub const fn with_start_cell(mut self, start_cell: CellReference) -> Self {
37 self.start_cell = start_cell;
38 self
39 }
40
41 #[must_use]
42 pub const fn with_end_cell(mut self, end_cell: CellReference) -> Self {
43 self.end_cell = Some(end_cell);
44 self
45 }
46
47 #[must_use]
48 pub const fn with_header_mode(mut self, header_mode: HeaderMode) -> Self {
49 self.header_mode = header_mode;
50 self
51 }
52
53 #[must_use]
54 pub const fn with_ignore_empty_rows(mut self, ignore_empty_rows: bool) -> Self {
55 self.ignore_empty_rows = ignore_empty_rows;
56 self
57 }
58
59 #[must_use]
60 pub const fn with_trim_headers(mut self, trim_headers: bool) -> Self {
61 self.trim_headers = trim_headers;
62 self
63 }
64
65 #[must_use]
66 pub(crate) fn sheet_name(&self) -> Option<&str> {
67 self.sheet_name.as_deref()
68 }
69
70 #[must_use]
71 pub(crate) const fn start_cell(&self) -> CellReference {
72 self.start_cell
73 }
74
75 #[must_use]
76 pub(crate) const fn end_cell(&self) -> Option<CellReference> {
77 self.end_cell
78 }
79
80 #[must_use]
81 pub(crate) const fn ignore_empty_rows(&self) -> bool {
82 self.ignore_empty_rows
83 }
84
85 #[must_use]
86 pub(crate) const fn trim_headers(&self) -> bool {
87 self.trim_headers
88 }
89
90 pub(crate) const fn uses_headers(&self, typed: bool) -> bool {
91 match self.header_mode {
92 HeaderMode::Auto => typed,
93 HeaderMode::None => false,
94 HeaderMode::FirstRow => true,
95 }
96 }
97}
98
99impl Default for ReadOptions {
100 fn default() -> Self {
101 Self {
102 sheet_name: None,
103 start_cell: CellReference::A1,
104 end_cell: None,
105 header_mode: HeaderMode::Auto,
106 ignore_empty_rows: false,
107 trim_headers: true,
108 }
109 }
110}
111
112#[derive(Clone, Debug, Eq, PartialEq)]
113pub struct WriteOptions {
114 sheet_name: String,
115 print_header: bool,
116 date_format: String,
117 time_format: String,
118 datetime_format: String,
119 duration_format: String,
120 column_formats: IndexMap<String, String>,
121}
122
123impl WriteOptions {
124 #[must_use]
125 pub fn new() -> Self {
126 Self::default()
127 }
128
129 #[must_use]
130 pub fn with_sheet_name(mut self, sheet_name: impl Into<String>) -> Self {
131 self.sheet_name = sheet_name.into();
132 self
133 }
134
135 #[must_use]
136 pub const fn with_print_header(mut self, print_header: bool) -> Self {
137 self.print_header = print_header;
138 self
139 }
140
141 #[must_use]
142 pub fn with_date_format(mut self, format: impl Into<String>) -> Self {
143 self.date_format = format.into();
144 self
145 }
146
147 #[must_use]
148 pub fn with_time_format(mut self, format: impl Into<String>) -> Self {
149 self.time_format = format.into();
150 self
151 }
152
153 #[must_use]
154 pub fn with_datetime_format(mut self, format: impl Into<String>) -> Self {
155 self.datetime_format = format.into();
156 self
157 }
158
159 #[must_use]
160 pub fn with_duration_format(mut self, format: impl Into<String>) -> Self {
161 self.duration_format = format.into();
162 self
163 }
164
165 #[must_use]
166 pub fn with_column_format(
167 mut self,
168 field_name: impl Into<String>,
169 format: impl Into<String>,
170 ) -> Self {
171 self.column_formats.insert(field_name.into(), format.into());
172 self
173 }
174
175 #[must_use]
176 pub(crate) fn sheet_name(&self) -> &str {
177 &self.sheet_name
178 }
179
180 #[must_use]
181 pub(crate) const fn print_header(&self) -> bool {
182 self.print_header
183 }
184
185 #[must_use]
186 pub(crate) fn date_format(&self) -> &str {
187 &self.date_format
188 }
189
190 #[must_use]
191 pub(crate) fn time_format(&self) -> &str {
192 &self.time_format
193 }
194
195 #[must_use]
196 pub(crate) fn datetime_format(&self) -> &str {
197 &self.datetime_format
198 }
199
200 #[must_use]
201 pub(crate) fn duration_format(&self) -> &str {
202 &self.duration_format
203 }
204
205 #[must_use]
206 pub(crate) fn column_formats(&self) -> &IndexMap<String, String> {
207 &self.column_formats
208 }
209}
210
211impl Default for WriteOptions {
212 fn default() -> Self {
213 Self {
214 sheet_name: "Sheet1".to_owned(),
215 print_header: true,
216 date_format: "yyyy-mm-dd".to_owned(),
217 time_format: "hh:mm:ss".to_owned(),
218 datetime_format: "yyyy-mm-dd hh:mm:ss".to_owned(),
219 duration_format: "[h]:mm:ss".to_owned(),
220 column_formats: IndexMap::new(),
221 }
222 }
223}