edit_xlsx/api/worksheet/row.rs
1//!
2//! Manages the Row settings that are modified,
3//! only the parts that are not None are applied to the [`Row`]'s modifications.
4//!
5//! This module contains the [`Row`] type, the [`WorkSheetRow`] trait for
6//! [`WorkSheet`]s working with [`Row`]s.
7//!
8//! # Examples
9//!
10//! There are multiple ways to create a new [`Row`]
11//!
12//! ```
13//! use edit_xlsx::Row;
14//! let row = Row::new(15.0, 2, 1, 0);
15//! assert_eq!(row.height, Some(15.0));
16//! assert_eq!(row.outline_level, Some(2));
17//! assert_eq!(row.hidden, Some(1));
18//! assert_eq!(row.collapsed, Some(0));
19//! ```
20//! Since the [`Row`] records the fields you want to update to worksheets, all their fields are optional
21//! If you create a new [`Row`] by default, the fields in it will be filled with None.
22//! ```
23//! use edit_xlsx::Row;
24//! let row = Row::default();
25//! assert_eq!(row.height, None);
26//! assert_eq!(row.outline_level, None);
27//! assert_eq!(row.hidden, None);
28//! assert_eq!(row.collapsed, None);
29//! ```
30//!
31//! You can update Worksheet rows by using the methods in WorkSheetRow
32//! ```
33//! use edit_xlsx::{Row, Workbook, WorkSheetRow};
34//! let mut workbook = Workbook::new();
35//! let worksheet = workbook.get_worksheet_mut(1).unwrap();
36//! let row = Row::new(15.0, 2, 1, 0);
37//! worksheet.set_row(1, &row).unwrap();
38//! workbook.save_as("./examples/row_update_row.xlsx").unwrap()
39//! ```
40
41use crate::{Format, Column, Cell};
42use crate::api::worksheet::format::_Format;
43use crate::api::worksheet::WorkSheet;
44use crate::result::RowError::RowNotFound;
45use crate::result::WorkSheetError::RowError;
46use crate::result::WorkSheetResult;
47
48/// [`Row`] records the fields you want to update to worksheets.
49///
50/// # Fields:
51/// | field | type |meaning|
52/// | ---- | ---- |----|
53/// | `height` | [`Option<f64>`] |The custom height you want to update with.|
54/// | `outline_level` | [`Option<u8>`] |The outline level of a row, learn more from [official documentation](https://support.microsoft.com/en-us/office/outline-group-data-in-a-worksheet-08ce98c4-0063-4d42-8ac7-8278c49e9aff).|
55/// | `hidden` | [`Option<u8>`] |Whether the row is hidden or not.|
56/// | `collapsed` | [`Option<u8>`] |collapse rows to group them.|
57#[derive(Copy, Debug, Clone, Default)]
58pub struct Row {
59 pub height: Option<f64>,
60 pub(crate) style: Option<u32>,
61 pub outline_level: Option<u8>,
62 pub hidden: Option<u8>,
63 pub collapsed: Option<u8>,
64}
65
66impl Row {
67 //
68 // constructors
69 //
70 /// If you need to customize each field, you can use the [`Row::new()`] method to create a [`Row`]
71 /// ```
72 /// use edit_xlsx::Row;
73 /// let row = Row::new(15.0, 2, 1, 0);
74 /// assert_eq!(row.height, Some(15.0));
75 /// assert_eq!(row.outline_level, Some(2));
76 /// assert_eq!(row.hidden, Some(1));
77 /// assert_eq!(row.collapsed, Some(0));
78 /// ```
79 pub fn new(height: f64, outline_level: u8, hidden: u8, collapsed: u8) -> Row {
80 Row {
81 height: Some(height),
82 style: None,
83 outline_level: Some(outline_level),
84 hidden: Some(hidden),
85 collapsed: Some(collapsed),
86 }
87 }
88
89 /// If you want to custom the format of row, you can use [`Row::new_by_worksheet()`] method.
90 /// **NOTICE**: A [`Row`] created using the [`Row::new_by_worksheet()`] method can only be used in incoming worksheets.
91 /// ```
92 /// use edit_xlsx::{Workbook, WorkSheetRow, Row, Format, FormatColor};
93 /// let red = Format::default().set_background_color(FormatColor::RGB(255, 0, 0));
94 /// let mut workbook = Workbook::new();
95 /// let worksheet = workbook.get_worksheet_mut(1).unwrap();
96 /// let row = Row::new_by_worksheet(15.0, 2, 1, 0, &red, worksheet);
97 /// worksheet.set_row(1, &row).unwrap();
98 /// workbook.save_as("./examples/row_new_by_worksheet.xlsx").unwrap()
99 /// ```
100 pub fn new_by_worksheet(height: f64, outline_level: u8
101 , hidden: u8, collapsed: u8
102 , format: &Format, work_sheet: &mut WorkSheet) -> Row {
103 let mut row = Row::new(height, outline_level, hidden, collapsed);
104 row.style = Some(work_sheet.add_format(format));
105 row
106 }
107}
108
109/// [`WorkSheetRow`] is a trait for [`WorkSheet`]s that allowing them working with [`Row`]s.
110///
111/// Not only does it support reading and updating rows directly,
112/// but it also provides a set of suggested methods for reading and updating rows swiftly.
113pub trait WorkSheetRow: _Row {
114 //
115 // get methods
116 //
117
118 /// Get the [`Row`] of a row based on the row number,
119 /// note that the row number starts with 1.
120 /// # Example
121 /// ```
122 /// use edit_xlsx::{Workbook, WorkSheetRow};
123 /// let workbook = Workbook::from_path("./examples/xlsx/accounting.xlsx").unwrap();
124 /// let worksheet = workbook.get_worksheet_by_name("worksheet").unwrap();
125 /// let first_row = worksheet.get_row(1).unwrap();
126 /// // Convert to u32 to reduce error
127 /// assert_eq!(first_row.height.unwrap() as u32, 28);
128 /// ```
129 fn get_row(&self, row: u32) -> WorkSheetResult<Row> {
130 self.get_by_row_number(row)
131 }
132
133 /// Get the [`Row`] and [`Format`] of a row based on the row number,
134 /// note that the row number starts with 1.
135 /// # Example
136 /// ```
137 /// use edit_xlsx::{Workbook, WorkSheetRow};
138 /// let workbook = Workbook::from_path("./examples/xlsx/accounting.xlsx").unwrap();
139 /// let worksheet = workbook.get_worksheet_by_name("worksheet").unwrap();
140 /// let (_, third_row_format) = worksheet.get_row_with_format(3).unwrap();
141 /// assert_eq!(third_row_format.unwrap().font.bold, true);
142 /// ```
143 fn get_row_with_format(&self, row: u32) -> WorkSheetResult<(Row, Option<Format>)> {
144 let row = self.get_by_row_number(row);
145 match row {
146 Ok(row) => {
147 match row.style {
148 None => Ok((row, None)),
149 Some(style_id) => Ok((row, Some(self.get_format(style_id))))
150 }
151 }
152 Err(_) => Err(RowError(RowNotFound))
153 }
154 }
155
156 /// Get the custom height of a row based on the row number,
157 /// note that the row number starts with 1.
158 /// Only rows have custom height can return their height.
159 /// # Example
160 /// ```
161 /// use edit_xlsx::{Workbook, WorkSheetRow};
162 /// let workbook = Workbook::from_path("./examples/xlsx/accounting.xlsx").unwrap();
163 /// let worksheet = workbook.get_worksheet_by_name("worksheet").unwrap();
164 /// let first_height = worksheet.get_row_height(1).unwrap();
165 /// let forth_height = worksheet.get_row_height(4).unwrap();
166 /// assert_eq!(first_height, Some(28.2));
167 /// assert_eq!(forth_height, None);
168 /// ```
169 fn get_row_height(&self, row: u32) -> WorkSheetResult<Option<f64>> {
170 let row = self.get_by_row_number(row)?;
171 Ok(row.height)
172 }
173
174 //
175 // set methods
176 //
177
178 ///
179 /// update a row by [`Row`], note that the row number starts with 1.
180 ///
181 /// Only not none fields will be updated.
182 ///
183 /// # Example
184 /// ```
185 /// use edit_xlsx::{Row, Workbook, WorkSheetRow};
186 /// let mut workbook = Workbook::from_path("./examples/xlsx/accounting.xlsx").unwrap();
187 /// let mut worksheet = workbook.get_worksheet_mut_by_name("worksheet").unwrap();
188 /// let mut row = Row::default();
189 /// row.outline_level = Some(1);
190 /// row.hidden = Some(1);
191 /// worksheet.set_row(1, &row).unwrap();
192 /// worksheet.set_row(2, &row).unwrap();
193 /// worksheet.set_row(3, &row).unwrap();
194 /// workbook.save_as("./examples/row_set_row.xlsx").unwrap()
195 fn set_row(&mut self, row_number: u32, row: &Row) -> WorkSheetResult<()> {
196 self.set_by_row(row_number, row)?;
197 Ok(())
198 }
199
200 /// update a row by [`Row`], note that the row number starts with 1.
201 ///
202 /// Only not none fields will be updated.
203 ///
204 /// **NOTICE**: Changing the [`Row`]'s [`Format`] does not mean that the effect can be seen directly in Excel,
205 /// because the style priority is [`Cell`]>[`Row`]>[`Column`].
206 /// # Example
207 /// ```
208 /// use edit_xlsx::{Format, FormatColor, Row, Workbook, WorkSheetRow};
209 /// let mut workbook = Workbook::from_path("./examples/xlsx/accounting.xlsx").unwrap();
210 /// let mut worksheet = workbook.get_worksheet_mut_by_name("worksheet").unwrap();
211 /// let mut row = Row::default();
212 /// row.height = Some(10.0);
213 /// let red_font = Format::default().set_background_color(FormatColor::Index(4)).set_color(FormatColor::RGB(255, 0, 0));
214 /// worksheet.set_row_with_format(6, &row, &red_font).unwrap();
215 /// worksheet.set_row_with_format(7, &row, &red_font).unwrap();
216 /// worksheet.set_row_with_format(8, &row, &red_font).unwrap();
217 /// workbook.save_as("./examples/row_set_row_with_format.xlsx").unwrap()
218 fn set_row_with_format(&mut self, row_number: u32, row: &Row, format: &Format) -> WorkSheetResult<()> {
219 let mut row = row.clone();
220 row.style = Some(self.add_format(format));
221 self.set_by_row(row_number, &row)?;
222 Ok(())
223 }
224
225 /// set the height of a row by row number,
226 /// The effect is the same as
227 /// # Basic Example
228 /// ```
229 /// use edit_xlsx::Row;
230 /// let mut row = Row::default();
231 /// row.height = Some(15.0);
232 /// // worksheet.set_row(1, &row);
233 /// ```
234 fn set_row_height(&mut self, row: u32, height: f64) -> WorkSheetResult<()> {
235 let mut row_set = Row::default();
236 row_set.height = Some(height);
237 self.set_by_row(row, &row_set)?;
238 Ok(())
239 }
240 fn set_row_height_pixels(&mut self, row: u32, height: f64) -> WorkSheetResult<()> {
241 let mut row_set = Row::default();
242 row_set.height = Some(0.5 * height);
243 self.set_by_row(row, &row_set)?;
244 Ok(())
245 }
246
247 /// set the height and format of a row by row number,
248 /// The effect is the same as
249 /// # Basic Example
250 /// ```
251 /// use edit_xlsx::{Format, Row};
252 /// let mut row = Row::default();
253 /// row.height = Some(15.0);
254 /// let format = Format::default();
255 /// // worksheet.set_row_with_format(1, &row, &format);
256 /// ```
257 fn set_row_height_with_format(&mut self, row: u32, height: f64, format: &Format) -> WorkSheetResult<()> {
258 let mut row_set = Row::default();
259 row_set.height = Some(height);
260 row_set.style = Some(self.add_format(format));
261 self.set_by_row(row, &row_set)?;
262 Ok(())
263 }
264 fn set_row_height_pixels_with_format(&mut self, row: u32, height: f64, format: &Format) -> WorkSheetResult<()> {
265 let mut row_set = Row::default();
266 row_set.height = Some(0.5 * height);
267 row_set.style = Some(self.add_format(format));
268 self.set_by_row(row, &row_set)?;
269 Ok(())
270 }
271
272 /// hide a row by row number,
273 /// The effect is the same as
274 /// # Basic Example
275 /// ```
276 /// use edit_xlsx::Row;
277 /// let mut row = Row::default();
278 /// row.hidden = Some(1);
279 /// // worksheet.set_row(1, &row);
280 /// ```
281 fn hide_row(&mut self, row: u32) -> WorkSheetResult<()> {
282 let mut row_set = Row::default();
283 row_set.hidden = Some(1);
284 self.set_by_row(row, &row_set)?;
285 Ok(())
286 }
287
288 /// set the outline of a row by row number,
289 /// The effect is the same as
290 /// # Basic Example
291 /// ```
292 /// use edit_xlsx::Row;
293 /// let mut row = Row::default();
294 /// row.outline_level = Some(1);
295 /// // worksheet.set_row(1, &row);
296 /// ```
297 fn set_row_level(&mut self, row: u32, level: u8) -> WorkSheetResult<()> {
298 let mut row_set = Row::default();
299 row_set.outline_level = Some(level);
300 self.set_by_row(row, &row_set)?;
301 Ok(())
302 }
303
304 /// collapse a row by row number,
305 /// The effect is the same as
306 /// # Basic Example
307 /// ```
308 /// use edit_xlsx::Row;
309 /// let mut row = Row::default();
310 /// row.collapsed = Some(1);
311 /// // worksheet.set_row(1, &row);
312 /// ```
313 fn collapse_row(&mut self, row: u32) -> WorkSheetResult<()> {
314 let mut row_set = Row::default();
315 row_set.collapsed = Some(1);
316 self.set_by_row(row, &row_set)?;
317 Ok(())
318 }
319}
320
321pub(crate) trait _Row: _Format {
322 fn set_by_row(&mut self, row: u32, row_set: &Row) -> WorkSheetResult<()>;
323 fn get_by_row_number(&self, row_number: u32) -> WorkSheetResult<Row>;
324 // fn get_custom_row_height(&self, row: u32) -> WorkSheetResult<f64>;
325}
326
327impl _Row for WorkSheet {
328 fn set_by_row(&mut self, row: u32, row_set: &Row) -> WorkSheetResult<()> {
329 self.worksheet.sheet_data.set_by_row(row, row_set);
330 Ok(())
331 }
332
333 fn get_by_row_number(&self, row_number: u32) -> WorkSheetResult<Row> {
334 let row = self.worksheet.sheet_data.get_api_row(row_number)?;
335 Ok(row)
336 }
337}