edit_xlsx/api/worksheet/
write.rs

1use std::slice::Iter;
2use crate::api::cell::Cell;
3use crate::api::cell::formula::Formula;
4use crate::api::cell::values::{CellDisplay, CellType, CellValue};
5use crate::api::cell::location::{Location, LocationRange};
6use crate::api::cell::rich_text::RichText;
7use crate::api::worksheet::format::_Format;
8use crate::api::worksheet::hyperlink::_Hyperlink;
9use crate::Format;
10use crate::api::worksheet::WorkSheet;
11use crate::result::WorkSheetResult;
12use crate::xml::extension::{AddExtension, ExtensionType};
13
14pub trait Write: _Write {
15    fn write_cell<L: Location, T: Clone + CellDisplay + CellValue>(&mut self, loc: L, cell: &Cell<T>) -> WorkSheetResult<()> {
16        self.write_by_api_cell(&loc, &cell)?;
17        Ok(())
18    }
19
20    fn write<L: Location, T: Default + Clone + CellDisplay + CellValue>(&mut self, loc: L, data: T) -> WorkSheetResult<()> {
21        let mut cell = Cell::default();
22        cell.cell_type = Some(data.to_cell_type());
23        cell.text = Some(data);
24        self.write_by_api_cell(&loc, &cell)
25    }
26    fn write_string<L: Location>(&mut self, loc: L, data: String) -> WorkSheetResult<()> {
27        let mut cell = Cell::default();
28        cell.text = Some(data);
29        self.write_by_api_cell(&loc, &cell)
30    }
31    fn write_rich_string<L: Location>(&mut self, loc: L, data: &RichText) -> WorkSheetResult<()> {
32        let mut cell: Cell<String> = Cell::default();
33        cell.rich_text = Some(data.clone());
34        self.write_by_api_cell(&loc, &cell)
35    }
36    fn write_number<L: Location>(&mut self, loc: L, data: i32) -> WorkSheetResult<()> {
37        let mut cell = Cell::default();
38        cell.text = Some(data);
39        self.write_by_api_cell(&loc, &cell)
40    }
41    fn write_double<L: Location>(&mut self, loc: L, data: f64) -> WorkSheetResult<()> {
42        let mut cell = Cell::default();
43        cell.text = Some(data);
44        self.write_by_api_cell(&loc, &cell)
45    }
46    fn write_boolean<L: Location>(&mut self, loc: L, data: bool) -> WorkSheetResult<()> {
47        let mut cell = Cell::default();
48        cell.text = Some(data);
49        self.write_by_api_cell(&loc, &cell)
50    }
51    fn write_row<L: Location, T: CellDisplay + CellValue>(&mut self, loc: L, data: &[T]) -> WorkSheetResult<()> {
52        let (row, mut col) = loc.to_location();
53        for data in data {
54            self.write_display_all(&(row, col), data, None)?;
55            col += 1;
56        }
57        Ok(())
58    }
59
60    fn write_row_cells<L: Location, T: CellDisplay + CellValue + Clone>(&mut self, loc: L, cells: &[Cell<T>]) -> WorkSheetResult<()> {
61        let (row, mut col) = loc.to_location();
62        for cell in cells {
63            self.write_by_api_cell(&(row, col), cell)?;
64            col += 1;
65        }
66        Ok(())
67    }
68
69    fn write_column<L: Location, T: CellDisplay + CellValue>(&mut self, loc: L, data: &[T]) -> WorkSheetResult<()> {
70        let (mut row, col) = loc.to_location();
71        for data in data {
72            self.write_display_all(&(row, col), data, None)?;
73            row += 1;
74        }
75        Ok(())
76    }
77
78    fn write_column_cells<L: Location, T: CellDisplay + CellValue + Clone>(&mut self, loc: L, cells: &[Cell<T>]) -> WorkSheetResult<()> {
79        let (mut row, col) = loc.to_location();
80        for cell in cells {
81            self.write_by_api_cell(&(row, col), cell)?;
82            row += 1;
83        }
84        Ok(())
85    }
86
87    fn write_url<L: Location>(&mut self, loc: L, url: &str) -> WorkSheetResult<()> {
88        let mut cell = Cell::default();
89        cell.text = Some(url);
90        cell.hyperlink = Some(url.to_string());
91        self.write_by_api_cell(&loc, &cell)
92    }
93
94    fn write_url_text<L: Location, T: CellDisplay + CellValue>(&mut self, loc: L, url: &str, data: &str) -> WorkSheetResult<()> {
95        let mut cell = Cell::default();
96        cell.text = Some(data);
97        cell.hyperlink = Some(url.to_string());
98        self.write_by_api_cell(&loc, &cell)
99    }
100
101    fn merge_range<L: LocationRange, T: CellDisplay + CellValue>(&mut self, loc: L, data: T) -> WorkSheetResult<()> {
102        self.merge_range_all(loc, data, None)
103    }
104
105    fn write_formula<L: Location>(&mut self, loc: L, data: &str) -> WorkSheetResult<()> {
106        let mut cell: Cell<&str> = Cell::default();
107        // cell.formula = Some(data.to_string());
108        // cell.formula_type = Some("array".to_string());
109        // cell.formula_ref = Some(loc.to_ref());
110        cell.formula = Some(Formula::new_array_formula(data, &loc));
111        // Some(FormulaType::Formula(loc.to_ref()).to_formula_ref());
112        self.write_by_api_cell(&loc, &cell)
113        // self.write_formula_all(&loc, data, FormulaType::Formula(loc.to_ref()), None)
114    }
115
116    fn write_old_formula<L: Location>(&mut self, loc: L, data: &str) -> WorkSheetResult<()> {
117        let mut cell: Cell<&str> = Cell::default();
118        cell.formula = Some(Formula::new(data));
119        self.write_by_api_cell(&loc, &cell)
120    }
121    fn write_array_formula<L: Location>(&mut self, loc: L, data: &str) -> WorkSheetResult<()> {
122        let mut cell: Cell<&str> = Cell::default();
123        cell.formula = Some(Formula::new_array_formula(data, &loc));
124        // cell.formula_type = Some(FormulaType::ArrayFormula(loc.to_ref()));
125        self.write_by_api_cell(&loc, &cell)
126    }
127    fn write_dynamic_array_formula<L: Location>(&mut self, loc: L, data: &str) -> WorkSheetResult<()> {
128        let mut cell: Cell<&str> = Cell::default();
129        cell.formula = Some(Formula::new_array_formula(data, &loc));
130        // cell.formula_type = Some(FormulaType::DynamicArrayFormula(loc.to_ref()));
131        self.write_by_api_cell(&loc, &cell)
132    }
133    fn write_with_format<L: Location, T: Default + Clone + CellDisplay + CellValue>(&mut self, loc: L, data: T, format: &Format) -> WorkSheetResult<()> {
134        let mut cell = Cell::default();
135        cell.cell_type = Some(data.to_cell_type());
136        cell.text = Some(data);
137        cell.format = Some(format.clone());
138        self.write_by_api_cell(&loc, &cell)
139    }
140
141    fn write_string_with_format<L: Location>(&mut self, loc: L, data: String, format: &Format) -> WorkSheetResult<()> {
142        let mut cell = Cell::default();
143        cell.text = Some(data);
144        cell.format = Some(format.clone());
145        self.write_by_api_cell(&loc, &cell)
146    }
147
148    fn write_number_with_format<L: Location>(&mut self, loc: L, data: i32, format: &Format) -> WorkSheetResult<()> {
149        let mut cell = Cell::default();
150        cell.text = Some(data);
151        cell.format = Some(format.clone());
152        self.write_by_api_cell(&loc, &cell)
153    }
154    fn write_double_with_format<L: Location>(&mut self, loc: L, data: f64, format: &Format) -> WorkSheetResult<()> {
155        let mut cell = Cell::default();
156        cell.text = Some(data);
157        cell.format = Some(format.clone());
158        self.write_by_api_cell(&loc, &cell)
159    }
160    fn write_boolean_with_format<L: Location>(&mut self, loc: L, data: bool, format: &Format) -> WorkSheetResult<()> {
161        let mut cell = Cell::default();
162        cell.text = Some(data);
163        cell.format = Some(format.clone());
164        self.write_by_api_cell(&loc, &cell)
165    }
166    fn write_row_with_format<L: Location, T: CellDisplay + CellValue>(&mut self, loc: L, data: Iter<'_, T>, format: &Format) -> WorkSheetResult<()> {
167        let (row, mut col) = loc.to_location();
168        for data in data {
169            self.write_display_all(&(row, col), data, Some(format))?;
170            col += 1;
171        }
172        Ok(())
173    }
174    fn write_column_with_format<L: Location, T: CellDisplay + CellValue>(&mut self, loc: L, data: Iter<'_, T>, format: &Format) -> WorkSheetResult<()> {
175        let (mut row, col) = loc.to_location();
176        for data in data {
177            self.write_display_all(&(row, col), data, Some(format))?;
178            row += 1;
179        }
180        Ok(())
181    }
182    fn write_url_with_format<L: Location>(&mut self, loc: L, url: &str, format: &Format) -> WorkSheetResult<()> {
183        let mut cell = Cell::default();
184        cell.text = Some(url);
185        cell.hyperlink = Some(url.to_string());
186        cell.format = Some(format.clone());
187        self.write_by_api_cell(&loc, &cell)
188    }
189    fn write_url_text_with_format<L: Location>(&mut self, loc: L, url: &str, data: &str, format: &Format) -> WorkSheetResult<()> {
190        let mut cell = Cell::default();
191        cell.text = Some(data);
192        cell.hyperlink = Some(url.to_string());
193        cell.format = Some(format.clone());
194        self.write_by_api_cell(&loc, &cell)
195    }
196    fn write_formula_with_format<L: Location>(&mut self, loc: L, data: &str, format: &Format) -> WorkSheetResult<()> {
197        let mut cell: Cell<&str> = Cell::default();
198        cell.formula = Some(Formula::new_array_formula(data, &loc));
199        // cell.formula_type = Some(FormulaType::Formula(loc.to_ref()));
200        cell.format = Some(format.clone());
201        self.write_by_api_cell(&loc, &cell)
202    }
203    fn write_array_formula_with_format<L: Location>(&mut self, loc: L, data: &str, format: &Format) -> WorkSheetResult<()> {
204        let mut cell: Cell<&str> = Cell::default();
205        cell.formula = Some(Formula::new_array_formula(data, &loc));
206        cell.format = Some(format.clone());
207        self.write_by_api_cell(&loc, &cell)
208    }
209    fn write_dynamic_array_formula_with_format<L: LocationRange>(&mut self, loc_range: L, data: &str, format: &Format) -> WorkSheetResult<()> {
210        let loc = loc_range.to_range();
211        let mut cell: Cell<&str> = Cell::default();
212        cell.formula = Some(Formula::new_array_formula_by_range(data, &loc));
213        cell.format = Some(format.clone());
214        // cell.formula_type = Some(FormulaType::DynamicArrayFormula(loc_range.to_range_ref()));
215        self.write_by_api_cell(&(loc.0, loc.1), &cell)
216    }
217    fn merge_range_with_format<L: LocationRange, T: CellDisplay + CellValue>(&mut self, loc: L, data: T, format:&Format) -> WorkSheetResult<()> {
218        self.merge_range_all(loc, data, Some(format))
219    }
220}
221
222trait _Write: _Format + _Hyperlink {
223    fn write_by_api_cell<L: Location, T: CellDisplay + CellValue + Clone>(&mut self, loc: &L, cell: &Cell<T>) -> WorkSheetResult<()>;
224    fn write_display_all<L: Location, T: CellDisplay + CellValue>(&mut self, loc: &L, data: &T, format: Option<&Format>) -> WorkSheetResult<()>;
225    // fn write_formula_all<L: Location>(&mut self, loc: &L, formula: &str, formula_type: FormulaType, format: Option<&Format>) -> WorkSheetResult<()>;
226    // fn write_hyperlink<L: Location>(&mut self, loc: &L, url: &str, data: &str, format: Option<&Format>) -> WorkSheetResult<()>;
227    fn merge_range_all<L: LocationRange, T: CellDisplay + CellValue>(&mut self, loc: L, data: T, format: Option<&Format>) -> WorkSheetResult<()>;
228}
229
230impl _Write for WorkSheet {
231    fn write_by_api_cell<L: Location, T: CellDisplay + CellValue + Clone>(&mut self, loc: &L, cell: &Cell<T>) -> WorkSheetResult<()> {
232        let mut cell = cell.clone();
233        if let Some(_) = &cell.formula {
234            self.worksheet.xmlns_attrs.add_xr();
235            self.worksheet.xmlns_attrs.add_xr_2();
236            self.worksheet.xmlns_attrs.add_xr_3();
237        }
238        if let Some(CellType::SharedString) = &cell.cell_type {
239            if cell.rich_text.is_some() {
240                cell.cell_type = Some(CellType::InlineString);
241            } else {
242                cell.cell_type = Some(CellType::String);
243            }
244        }
245        if let Some(format) = &cell.format {
246            let style = self.add_format(format);
247            cell.style = Some(style);
248        }
249        if let Some(url) = &cell.hyperlink {
250            let url_r_id = self.worksheet_rel.add_hyperlink(url);
251            self.worksheet.add_hyperlink(loc, url_r_id);
252        }
253        if let Some(_) = &cell.formula {
254            self.metadata.borrow_mut().add_extension(ExtensionType::XdaDynamicArrayProperties);
255            self.workbook_rel.borrow_mut().get_or_add_metadata();
256            self.content_types.borrow_mut().add_metadata();
257        }
258        self.worksheet.sheet_data.write_by_api_cell(loc, &cell)?;
259        Ok(())
260    }
261
262    fn write_display_all<L: Location, T: CellDisplay + CellValue>(&mut self, loc: &L, data: &T, format: Option<&Format>) -> WorkSheetResult<()> {
263        let mut style = self.worksheet.get_default_style(loc);
264        if let Some(format) = format {
265            style = Some(self.add_format(format));
266        }
267        let worksheet = &mut self.worksheet;
268        let sheet_data = &mut worksheet.sheet_data;
269        sheet_data.write_display(loc, data, style)?;
270        Ok(())
271    }
272
273    // fn write_formula_all<L: Location>(&mut self, loc: &L, formula: &str, formula_type: FormulaType, format: Option<&Format>) -> WorkSheetResult<()> {
274    //     let mut style = None;
275    //     if let Some(format) = format {
276    //         style = Some(self.add_format(format));
277    //     }
278    //     let worksheet = &mut self.worksheet;
279    //     let sheet_data = &mut worksheet.sheet_data;
280    //     // self.workbook_rel.borrow_mut().get_or_add_metadata();
281    //     self.workbook_rel.borrow_mut().get_or_add_metadata();
282    //     self.content_types.borrow_mut().add_metadata();
283    //     if FormulaType::OldFormula(loc.to_ref()) != formula_type {
284    //         self.metadata.borrow_mut().add_extension(ExtensionType::XdaDynamicArrayProperties);
285    //     }
286    //     sheet_data.write_formula(loc, formula, formula_type, style)?;
287    //     Ok(())
288    // }
289
290    // fn write_hyperlink<L: Location>(&mut self, loc: &L, url: &str, data: &str, format: Option<&Format>) -> WorkSheetResult<()> {
291    //     self.write_display_all(loc, &data, format)?;
292    //     let r_id = self.worksheet_rel.add_hyperlink(url);
293    //     self.worksheet.add_hyperlink(loc, r_id);
294    //     Ok(())
295    // }
296
297    fn merge_range_all<L: LocationRange, T: CellDisplay + CellValue>(&mut self, loc: L, data: T, format: Option<&Format>) -> WorkSheetResult<()> {
298        let (first_row, first_col, last_row, last_col) = loc.to_range();
299        let worksheet = &mut self.worksheet;
300        worksheet.add_merge_cell(first_row, first_col, last_row, last_col);
301        for row in first_row..=last_row {
302            for col in first_col..=last_col {
303                self.write_display_all(&(row, col), &data, format)?;
304            }
305        }
306        Ok(())
307    }
308}