edit_xlsx/api/format/border.rs
1//!
2//! This module contains the [`FormatBorder`] struct,
3//! which used to edit the border style of the [`Cell`] in each direction.
4//!
5//! # Examples
6//!
7//! Wrap cells
8//! ```
9//! use std::cell;
10//! use edit_xlsx::{Cell, Format, FormatBorder, FormatBorderElement, FormatBorderType, FormatColor, Workbook, Write};
11//! let format = Format::default().set_border(FormatBorderType::Thin);
12//! // Or use
13//! // let mut format = Format::default();
14//! // let mut format_border = FormatBorder::default();
15//! // let format_border_element = FormatBorderElement::from_border_type(&FormatBorderType::Thin);
16//! // format_border.left = format_border_element;
17//! // format_border.right = format_border_element;
18//! // format_border.top = format_border_element;
19//! // format_border.bottom = format_border_element;
20//! // format.border = format_border;
21//! let mut workbook = Workbook::from_path("./examples/xlsx/accounting.xlsx").unwrap();
22//! let worksheet = workbook.get_worksheet_mut_by_name("worksheet").unwrap();
23//! let mut cell: Cell<String> = Cell::default();
24//! cell.format = Some(format);
25//! for row in 6..=15 {
26//! for col in 3..=12 {
27//! worksheet.write_cell((row, col), &cell).unwrap()
28//! }
29//! }
30//! workbook.save_as("./examples/border_wrap_cells.xlsx").unwrap();
31//! ```
32//!
33//! Use diagonal to creat a table
34//! ```
35//! use std::cell;
36//! use edit_xlsx::{Cell, Format, FormatBorder, FormatBorderElement, FormatBorderType, FormatColor, Read, Workbook, Write};
37//! let mut workbook = Workbook::new();
38//! let worksheet = workbook.get_worksheet_mut(1).unwrap();
39//! let mut cell: Cell<String> = Cell::default();
40//! let mut format = Format::default();
41//! format.border.diagonal = FormatBorderElement::from_border_type(&FormatBorderType::Thin);
42//! cell.format = Some(format);
43//! worksheet.write_cell("A1", &cell).unwrap();
44//! // todo bug fix
45//! worksheet.write_column("A2", &[1, 2, 3]).unwrap();
46//! worksheet.write_column("B1", &["Region", "East", "West", "North"]).unwrap();
47//! worksheet.write_column("C1", &["Sales Rep", "Tom", "Fred", "Amy"]).unwrap();
48//! worksheet.write_column("C1", &["Product", "Apple", "Grape", "Pear"]).unwrap();
49//! workbook.save_as("./examples/border_diagonal_cell.xlsx").unwrap();
50//! ```
51//!
52//! Wrap merged cells
53//! ```
54//! use std::cell;
55//! use edit_xlsx::{Cell, Format, FormatBorder, FormatBorderElement, FormatBorderType, FormatColor, Read, Workbook, Write};
56//! let mut workbook = Workbook::from_path("./examples/xlsx/accounting.xlsx").unwrap();
57//! let worksheet = workbook.get_worksheet_mut_by_name("worksheet").unwrap();
58//! for row in 18..=21 {
59//! for col in 2..=11 {
60//! let mut cell: Cell<String> = worksheet.read_cell((row, col)).unwrap();
61//! cell.format = match cell.format.take() {
62//! None => None,
63//! Some(mut format) => Some(format.set_border(FormatBorderType::Double)),
64//! };
65//! worksheet.write_cell((row, col), &cell).unwrap()
66//! }
67//! }
68//! workbook.save_as("./examples/border_wrap_merged_cells.xlsx").unwrap();
69//! ```
70//!
71
72use std::fmt::{Display, Formatter};
73use crate::{Cell, FormatColor};
74use crate::xml::common::FromFormat;
75use crate::xml::style::border::{Border, BorderElement};
76use crate::xml::style::color::Color;
77
78///
79/// [`FormatBorder`] is used to edit the border style of the [`Cell`] in each direction.
80/// # Fields
81/// | field | type | meaning |
82/// | ------------ | ----------- | ------------------------------------------------------------ |
83/// | `left` | [`FormatBorderElement`] | The [`Cell`]'s left border style |
84/// | `right` | [`FormatBorderElement`] | The [`Cell`]'s right border style |
85/// | `top` | [`FormatBorderElement`] | The [`Cell`]'s top border style |
86/// | `bottom` | [`FormatBorderElement`] | The [`Cell`]'s bottom border style |
87/// | `diagonal` | [`FormatBorderElement`] | The [`Cell`]'s diagonal border style |
88///
89#[derive(Clone, Debug, PartialEq, Default)]
90pub struct FormatBorder {
91 pub left: FormatBorderElement,
92 pub right: FormatBorderElement,
93 pub top: FormatBorderElement,
94 pub bottom: FormatBorderElement,
95 pub diagonal: FormatBorderElement,
96}
97
98///
99/// [`FormatBorderElement`] is used to edit one of the direction of the [`Cell`]'s border style.
100/// # Fields
101/// | field | type | meaning |
102/// | ------------ | ----------- | ------------------------------------------------------------ |
103/// | `border_type` | [`FormatBorderType`] | Type of the border |
104/// | `color` | [`FormatColor`] | Color of the border |
105///
106#[derive(Clone, Debug, PartialEq, Copy, Default)]
107pub struct FormatBorderElement {
108 pub border_type: FormatBorderType,
109 pub color: FormatColor,
110}
111
112impl FormatBorderElement {
113 pub fn new(border_type: &FormatBorderType, color: &FormatColor) -> FormatBorderElement {
114 FormatBorderElement {
115 border_type: *border_type,
116 color: *color,
117 }
118 }
119
120 ///
121 /// Create a new [`FormatBorderElement`] based on the border color,
122 /// the border type defaults to [`FormatBorderType::Thin`]
123 ///
124 pub fn from_color(color: &FormatColor) -> FormatBorderElement {
125 FormatBorderElement {
126 border_type: FormatBorderType::Thin,
127 color: *color,
128 }
129 }
130
131 ///
132 /// Create a new [`FormatBorderElement`] based on the border type,
133 /// the border color defaults to [`FormatColor::Default`]
134 ///
135 pub fn from_border_type(border_type: &FormatBorderType) -> FormatBorderElement {
136 FormatBorderElement {
137 border_type: *border_type,
138 color: FormatColor::default(),
139 }
140 }
141}
142
143///
144/// Enumeration of different border type
145///
146/// # Fields:
147/// | unit | meaning |
148/// | ---- | ---- |
149/// | `None` | Default, No border |
150/// | `Thin` | Thin line |
151/// | `Medium` | Medium line |
152/// | `Dashed` | Dashed line |
153/// | `Dotted` | Dotted line |
154/// | `Thick` | Thick line |
155/// | `Double` | Double line |
156/// | `Hair` | Hairline |
157/// | `MediumDashed` | Medium dashed line |
158/// | `DashDot` | Dash-dot line |
159/// | `MediumDashDot` | Medium dash-dot line |
160/// | `DashDotDot` | Dash-dot-dot line |
161/// | `MediumDashDotDot` | Medium dash-dot-dot line |
162/// | `SlantDashDot` | Slanted dash-dot-dot line |
163///
164#[derive(Copy, Clone, Debug, PartialEq)]
165pub enum FormatBorderType {
166 /// Default, No border
167 None,
168 /// Thin line
169 Thin,
170 /// Medium line
171 Medium,
172 /// Dashed line
173 Dashed,
174 /// Dotted line
175 Dotted,
176 /// Thick line
177 Thick,
178 /// Double line
179 Double,
180 /// Hairline
181 Hair,
182 /// Medium dashed line
183 MediumDashed,
184 /// Dash-dot line
185 DashDot,
186 /// Medium dash-dot line
187 MediumDashDot,
188 /// Dash-dot-dot line
189 DashDotDot,
190 /// Medium dash-dot-dot line
191 MediumDashDotDot,
192 /// Slanted dash-dot-dot line
193 SlantDashDot,
194}
195
196impl Display for FormatBorderType {
197 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
198 f.write_str(self.to_str())
199 }
200}
201
202impl Default for FormatBorderType {
203 fn default() -> FormatBorderType {
204 FormatBorderType::None
205 }
206}
207
208impl FormatBorderType {
209 pub(crate) fn to_str(&self) -> &str {
210 match self {
211 FormatBorderType::None => "none",
212 FormatBorderType::Thin => "thin",
213 FormatBorderType::Medium => "medium",
214 FormatBorderType::Dashed => "dashed",
215 FormatBorderType::Dotted => "dotted",
216 FormatBorderType::Thick => "thick",
217 FormatBorderType::Double => "double",
218 FormatBorderType::Hair => "hair",
219 FormatBorderType::MediumDashed => "mediumDashed",
220 FormatBorderType::DashDot => "dashDot",
221 FormatBorderType::MediumDashDot => "mediumDashDot",
222 FormatBorderType::DashDotDot => "dashDotDot",
223 FormatBorderType::MediumDashDotDot => "mediumDashDotDot",
224 FormatBorderType::SlantDashDot => "slantDashDot",
225 }
226 }
227
228 pub(crate) fn from_str(border_str: &str) -> Self {
229 match border_str {
230 "thin" => FormatBorderType::Thin,
231 "medium" => FormatBorderType::Medium,
232 "dashed" => FormatBorderType::Dashed,
233 "dotted" => FormatBorderType::Dotted,
234 "thick" => FormatBorderType::Thick,
235 "double" => FormatBorderType::Double,
236 "hair" => FormatBorderType::Hair,
237 "mediumDashed" => FormatBorderType::MediumDashed,
238 "dashDot" => FormatBorderType::DashDot,
239 "mediumDashDot" => FormatBorderType::MediumDashDot,
240 "dashDotDot" => FormatBorderType::DashDotDot,
241 "mediumDashDotDot" => FormatBorderType::MediumDashDotDot,
242 "slantDashDot" => FormatBorderType::SlantDashDot,
243 _ => FormatBorderType::None,
244 }
245 }
246}
247
248impl FromFormat<FormatBorder> for Border {
249 fn set_attrs_by_format(&mut self, format: &FormatBorder) {
250 self.left = Some(BorderElement::from_format(&format.left));
251 self.right = Some(BorderElement::from_format(&format.right));
252 self.top = Some(BorderElement::from_format(&format.top));
253 self.bottom = Some(BorderElement::from_format(&format.bottom));
254 self.diagonal = Some(BorderElement::from_format(&format.diagonal));
255 }
256
257 fn set_format(&self, format: &mut FormatBorder) {
258 format.left = {
259 if let Some(left) = &self.left {
260 left.get_format()
261 } else {
262 FormatBorderElement::default()
263 }
264 };
265 format.right = {
266 if let Some(right) = &self.right {
267 right.get_format()
268 } else {
269 FormatBorderElement::default()
270 }
271 };
272 format.top = {
273 if let Some(top) = &self.top {
274 top.get_format()
275 } else {
276 FormatBorderElement::default()
277 }
278 };
279 format.bottom = {
280 if let Some(bottom) = &self.bottom {
281 bottom.get_format()
282 } else {
283 FormatBorderElement::default()
284 }
285 };
286 format.diagonal = {
287 if let Some(diagonal) = &self.diagonal {
288 diagonal.get_format()
289 } else {
290 FormatBorderElement::default()
291 }
292 }
293 }
294}
295
296impl FromFormat<FormatBorderElement> for BorderElement {
297 fn set_attrs_by_format(&mut self, format: &FormatBorderElement) {
298 self.style = Some(String::from(format.border_type.to_str()));
299 self.color = Some(Color::from_format(&format.color));
300 }
301
302 fn set_format(&self, format: &mut FormatBorderElement) {
303 // format.color = self.color.unwrap_or_default();
304 match &self.style {
305 None => format.border_type = FormatBorderType::default(),
306 Some(style) => format.border_type = FormatBorderType::from_str(style)
307 }
308 }
309}