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}