umya_spreadsheet/structs/
spreadsheet.rs

1use crate::helper::address::*;
2use crate::helper::coordinate::*;
3use crate::reader::xlsx::*;
4use crate::structs::drawing::Theme;
5use crate::structs::Address;
6use crate::structs::CellValue;
7use crate::structs::Cells;
8use crate::structs::DefinedName;
9use crate::structs::Properties;
10use crate::structs::SharedStringTable;
11use crate::structs::Stylesheet;
12use crate::structs::WorkbookProtection;
13use crate::structs::WorkbookView;
14use crate::structs::Worksheet;
15use crate::traits::AdjustmentCoordinate;
16use crate::traits::AdjustmentCoordinateWithSheet;
17use crate::StringValue;
18use std::sync::Arc;
19use std::sync::RwLock;
20use thin_vec::ThinVec;
21
22/// A Spreadsheet Object.
23/// The starting point of all struct.
24#[derive(Clone, Default, Debug)]
25pub struct Spreadsheet {
26    properties: Properties,
27    work_sheet_collection: ThinVec<Worksheet>,
28    macros_code: Option<ThinVec<u8>>,
29    jsa_macros_code: Option<ThinVec<u8>>,
30    code_name: StringValue,
31    ribbon_xml_data: StringValue,
32    theme: Theme,
33    stylesheet: Stylesheet,
34    shared_string_table: Arc<RwLock<SharedStringTable>>,
35    workbook_view: WorkbookView,
36    backup_context_types: ThinVec<(Box<str>, Box<str>)>,
37    pivot_caches: ThinVec<(Box<str>, Box<str>, Box<str>)>,
38    workbook_protection: Option<Box<WorkbookProtection>>,
39    defined_names: ThinVec<DefinedName>,
40}
41
42impl Spreadsheet {
43    // ************************
44    // update Coordinate
45    // ************************
46    /// Insert new rows.
47    /// # Arguments
48    /// * `sheet_name` - Specify the sheet name. ex) "Sheet1"
49    /// * `row_index` - Specify point of insert. ex) 1
50    /// * `num_rows` - Specify number to insert. ex) 2
51    /// # Examples
52    /// ```
53    /// let mut book = umya_spreadsheet::new_file();
54    /// book.insert_new_row("Sheet1", &2, &3);
55    /// ```
56    #[inline]
57    pub fn insert_new_row(&mut self, sheet_name: &str, row_index: &u32, num_rows: &u32) {
58        self.adjustment_insert_coordinate_with_sheet(sheet_name, &0, &0, row_index, num_rows);
59    }
60
61    /// Insert new columns.
62    /// # Arguments
63    /// * `sheet_name` - Specify the sheet name. ex) "Sheet1"
64    /// * `column` - Specify point of insert. ex) "B"
65    /// * `num_columns` - Specify number to insert. ex) 3
66    /// # Examples
67    /// ```
68    /// let mut book = umya_spreadsheet::new_file();
69    /// book.insert_new_column("Sheet1", "B", &3);
70    /// ```
71    #[inline]
72    pub fn insert_new_column(&mut self, sheet_name: &str, column: &str, num_columns: &u32) {
73        self.insert_new_column_by_index(sheet_name, &column_index_from_string(column), num_columns);
74    }
75
76    /// Insert new columns.
77    /// # Arguments
78    /// * `sheet_name` - Specify the sheet name. ex) "Sheet1"
79    /// * `column_index` - Specify point of insert. ex) 2
80    /// * `num_columns` - Specify number to insert. ex) 3
81    /// # Examples
82    /// ```
83    /// let mut book = umya_spreadsheet::new_file();
84    /// book.insert_new_column_by_index("Sheet1", &2, &3);
85    /// ```
86    #[inline]
87    pub fn insert_new_column_by_index(
88        &mut self,
89        sheet_name: &str,
90        column_index: &u32,
91        num_columns: &u32,
92    ) {
93        self.adjustment_insert_coordinate_with_sheet(sheet_name, column_index, num_columns, &0, &0);
94    }
95
96    /// Remove rows.
97    /// # Arguments
98    /// * `sheet_name` - Specify the sheet name. ex) "Sheet1"
99    /// * `row_index` - Specify point of remove. ex) &1
100    /// * `num_rows` - Specify number to remove. ex) &2
101    /// # Examples
102    /// ```
103    /// let mut book = umya_spreadsheet::new_file();
104    /// book.remove_row("Sheet1", &2, &3);
105    /// ```
106    #[inline]
107    pub fn remove_row(&mut self, sheet_name: &str, row_index: &u32, num_rows: &u32) {
108        self.adjustment_remove_coordinate_with_sheet(sheet_name, &0, &0, row_index, num_rows);
109    }
110
111    /// Remove columns.
112    /// # Arguments
113    /// * `sheet_name` - Specify the sheet name. ex) "Sheet1"
114    /// * `column` - Specify point of remove. ex) "B"
115    /// * `num_columns` - Specify number to remove. ex) 3
116    /// # Examples
117    /// ```
118    /// let mut book = umya_spreadsheet::new_file();
119    /// book.remove_column("Sheet1", "B", &3);
120    /// ```
121    #[inline]
122    pub fn remove_column(&mut self, sheet_name: &str, column: &str, num_columns: &u32) {
123        self.remove_column_by_index(sheet_name, &column_index_from_string(column), num_columns);
124    }
125
126    /// Remove columns.
127    /// # Arguments
128    /// * `sheet_name` - Specify the sheet name. ex) "Sheet1"
129    /// * `column_index` - Specify point of remove. ex) 2
130    /// * `num_columns` - Specify number to remove. ex) 3
131    /// # Examples
132    /// ```
133    /// let mut book = umya_spreadsheet::new_file();
134    /// book.remove_column_by_index("Sheet1", &2, &3);
135    /// ```
136    #[inline]
137    pub fn remove_column_by_index(
138        &mut self,
139        sheet_name: &str,
140        column_index: &u32,
141        num_columns: &u32,
142    ) {
143        self.adjustment_remove_coordinate_with_sheet(sheet_name, column_index, num_columns, &0, &0);
144    }
145
146    /// Gets the cell value by specifying an address.
147    /// # Arguments
148    /// * `address` - address. ex) "Sheet1!A1:C5"
149    /// # Return value
150    /// *`Vec<&CellValue>` - CellValue List.
151    /// # Examples
152    /// ```
153    /// let mut book = umya_spreadsheet::new_file();
154    /// let mut cell_value_List = book.get_cell_value_by_address("Sheet1!A1:C5");
155    /// ```
156    #[inline]
157    pub fn get_cell_value_by_address(&self, address: &str) -> Vec<&CellValue> {
158        let (sheet_name, range) = split_address(address);
159        self.get_sheet_by_name(&sheet_name)
160            .unwrap()
161            .get_cell_value_by_range(&range)
162    }
163
164    /// (This method is crate only.)
165    /// Gets the cell value by specifying an Address Object.
166    /// # Arguments
167    /// * `address` - Address Object
168    /// # Return value
169    /// *`Vec<&CellValue>` - CellValue List.
170    #[inline]
171    pub(crate) fn get_cell_value_by_address_crate(&self, address: &Address) -> Vec<&CellValue> {
172        self.get_sheet_by_name(address.get_sheet_name())
173            .unwrap()
174            .get_cell_value_by_range(&address.get_range().get_range())
175    }
176
177    /// Get Theme.
178    #[inline]
179    pub fn get_theme(&self) -> &Theme {
180        &self.theme
181    }
182
183    /// Get Theme in mutable.
184    #[inline]
185    pub fn get_theme_mut(&mut self) -> &mut Theme {
186        &mut self.theme
187    }
188
189    /// Set Theme.
190    /// # Arguments
191    /// * `value` - Theme
192    #[inline]
193    pub fn set_theme(&mut self, value: Theme) -> &mut Self {
194        self.theme = value;
195        self
196    }
197
198    /// Get Properties.
199    #[inline]
200    pub fn get_properties(&self) -> &Properties {
201        &self.properties
202    }
203
204    /// Get Properties in mutable.
205    #[inline]
206    pub fn get_properties_mut(&mut self) -> &mut Properties {
207        &mut self.properties
208    }
209
210    /// Set Properties.
211    /// # Arguments
212    /// * `value` - Properties
213    #[inline]
214    pub fn set_properties(&mut self, value: Properties) -> &mut Self {
215        self.properties = value;
216        self
217    }
218
219    /// Get Macros Code.
220    /// # Return value
221    /// * `Option<&Vec<u8>>` - Macros Code Raw Data.
222    #[inline]
223    pub fn get_macros_code(&self) -> Option<&[u8]> {
224        self.macros_code.as_deref()
225    }
226
227    /// Set Macros Code.
228    /// # Arguments
229    /// * `value` - Macros Code Raw Data.
230    #[inline]
231    pub fn set_macros_code(&mut self, value: impl Into<ThinVec<u8>>) -> &mut Self {
232        self.macros_code = Some(value.into());
233        self
234    }
235
236    /// Remove Macros Code
237    #[inline]
238    pub fn remove_macros_code(&mut self) -> &mut Self {
239        self.macros_code = None;
240        self
241    }
242
243    /// Has Macros Code
244    #[inline]
245    pub fn get_has_macros(&self) -> bool {
246        self.macros_code.is_some()
247    }
248
249    /// Get Macros Code.
250    /// # Return value
251    /// * `Option<&Vec<u8>>` - Macros Code Raw Data.
252    #[inline]
253    pub fn get_jsa_macros_code(&self) -> Option<&[u8]> {
254        self.jsa_macros_code.as_deref()
255    }
256
257    /// Set Macros Code.
258    /// # Arguments
259    /// * `value` - Macros Code Raw Data.
260    #[inline]
261    pub fn set_jsa_macros_code(&mut self, value: impl Into<ThinVec<u8>>) -> &mut Self {
262        self.jsa_macros_code = Some(value.into());
263        self
264    }
265
266    /// Remove Macros Code
267    #[inline]
268    pub fn remove_jsa_macros_code(&mut self) -> &mut Self {
269        self.jsa_macros_code = None;
270        self
271    }
272
273    /// Has Macros Code
274    #[inline]
275    pub fn get_has_jsa_macros(&self) -> bool {
276        self.jsa_macros_code.is_some()
277    }
278
279    /// Set codeName property of workbook
280    ///
281    /// May be useful when importing VBA/macros code from another workbook
282    /// and only used when writing book with macros code
283    ///
284    /// Default one is `ThisWorkbook`.
285    ///
286    /// Excel often uses `Workbook________` (8 underscores).
287    #[inline]
288    pub fn set_code_name<S: Into<String>>(&mut self, codename: S) -> &mut Self {
289        self.code_name.set_value(codename);
290        self
291    }
292
293    /// Get codeName property of workbook
294    ///
295    /// Must to be the same in workbook with VBA/macros code from this workbook
296    /// for that code in Workbook object to work out of the box without adjustments
297    #[inline]
298    pub fn get_code_name(&self) -> Option<&str> {
299        self.code_name.get_value()
300    }
301
302    /// (This method is crate only.)
303    /// Get Stylesheet.
304    #[inline]
305    pub(crate) fn get_stylesheet(&self) -> &Stylesheet {
306        &self.stylesheet
307    }
308
309    /// (This method is crate only.)
310    /// Set Stylesheet.
311    /// # Arguments
312    /// * `value` - Stylesheet
313    #[inline]
314    pub(crate) fn set_stylesheet(&mut self, value: Stylesheet) -> &mut Self {
315        self.stylesheet = value;
316        self
317    }
318
319    /// (This method is crate only.)
320    /// Set Default Value Stylesheet.
321    #[inline]
322    pub(crate) fn set_stylesheet_defalut_value(&mut self) -> &mut Self {
323        self.stylesheet.set_defalut_value();
324        self
325    }
326
327    /// (This method is crate only.)
328    /// Get Shared String Table.
329    #[inline]
330    pub(crate) fn get_shared_string_table(&self) -> Arc<RwLock<SharedStringTable>> {
331        self.shared_string_table.clone()
332    }
333
334    /// (This method is crate only.)
335    /// Set Shared String Table.
336    /// # Arguments
337    /// * `value` - Shared String Table
338    #[inline]
339    pub(crate) fn set_shared_string_table(&mut self, value: SharedStringTable) -> &mut Self {
340        self.shared_string_table = Arc::new(RwLock::new(value));
341        self
342    }
343
344    /// Get Work Sheet List.
345    pub fn get_sheet_collection(&self) -> &[Worksheet] {
346        for worksheet in &self.work_sheet_collection {
347            assert!(worksheet.is_deserialized(),"This Worksheet is Not Deserialized. Please exec to read_sheet(&mut self, index: usize);");
348        }
349        &self.work_sheet_collection
350    }
351
352    /// Get Work Sheet List.
353    /// No check deserialized.
354    #[inline]
355    pub fn get_sheet_collection_no_check(&self) -> &[Worksheet] {
356        &self.work_sheet_collection
357    }
358
359    /// Get Work Sheet List in mutable.
360    #[inline]
361    pub fn get_sheet_collection_mut(&mut self) -> &mut ThinVec<Worksheet> {
362        self.read_sheet_collection();
363        &mut self.work_sheet_collection
364    }
365
366    /// Get Work Sheet Count.
367    /// # Return value
368    /// * `usize` - Work Sheet Count.
369    #[inline]
370    pub fn get_sheet_count(&self) -> usize {
371        self.work_sheet_collection.len()
372    }
373
374    /// deserialize by all worksheet.
375    #[inline]
376    pub fn read_sheet_collection(&mut self) -> &mut Self {
377        let shared_string_table = self.get_shared_string_table();
378        let stylesheet = self.get_stylesheet().clone();
379        for worksheet in &mut self.work_sheet_collection {
380            raw_to_deserialize_by_worksheet(worksheet, &shared_string_table, &stylesheet);
381        }
382        self
383    }
384
385    /// deserialize a worksheet.
386    #[inline]
387    pub fn read_sheet(&mut self, index: usize) -> &mut Self {
388        let shared_string_table = self.get_shared_string_table();
389        let stylesheet = self.get_stylesheet().clone();
390        let worksheet = self.work_sheet_collection.get_mut(index).unwrap();
391        raw_to_deserialize_by_worksheet(worksheet, &shared_string_table, &stylesheet);
392        self
393    }
394
395    /// deserialize a worksheet.
396    #[inline]
397    pub fn read_sheet_by_name(&mut self, sheet_name: &str) -> &mut Self {
398        let index = self.find_sheet_index_by_name(sheet_name).unwrap();
399        self.read_sheet(index)
400    }
401
402    #[inline]
403    pub(crate) fn find_sheet_index_by_name(&self, sheet_name: &str) -> Option<usize> {
404        self.work_sheet_collection
405            .iter()
406            .position(|sheet| sheet.get_name() == sheet_name)
407    }
408
409    /// Get Work Sheet.
410    /// # Arguments
411    /// * `index` - sheet index
412    /// # Return value
413    /// * `Option<&Worksheet>`.
414    #[inline]
415    pub fn get_sheet(&self, index: &usize) -> Option<&Worksheet> {
416        self.work_sheet_collection
417            .get(*index)
418            .map(|v| {
419                assert!(v.is_deserialized(),"This Worksheet is Not Deserialized. Please exec to read_sheet(&mut self, index: usize);");
420                v
421            })
422    }
423
424    /// Get Work Sheet.
425    /// # Arguments
426    /// * `sheet_name` - sheet name
427    /// # Return value
428    /// * `Option<&Worksheet>.
429    #[inline]
430    pub fn get_sheet_by_name(&self, sheet_name: &str) -> Option<&Worksheet> {
431        self.find_sheet_index_by_name(sheet_name)
432            .and_then(|index| self.get_sheet(&index))
433    }
434
435    pub fn get_lazy_read_sheet_cells(&self, index: &usize) -> Result<Cells, &'static str> {
436        let shared_string_table = self.get_shared_string_table();
437        self.work_sheet_collection
438            .get(*index)
439            .map(|v| {
440                v.get_cell_collection_stream(
441                    &shared_string_table.read().unwrap(),
442                    self.get_stylesheet(),
443                )
444            })
445            .ok_or("Not found.")
446    }
447
448    /// Get Work Sheet in mutable.
449    /// # Arguments
450    /// * `index` - sheet index
451    /// # Return value
452    /// * `Option<&mut Worksheet>`.
453    pub fn get_sheet_mut(&mut self, index: &usize) -> Option<&mut Worksheet> {
454        let shared_string_table = self.get_shared_string_table();
455        let stylesheet = self.get_stylesheet().clone();
456        self.work_sheet_collection.get_mut(*index).map(|v| {
457            raw_to_deserialize_by_worksheet(v, &shared_string_table, &stylesheet);
458            v
459        })
460    }
461
462    /// Get Work Sheet in mutable.
463    /// # Arguments
464    /// * `sheet_name` - sheet name
465    /// # Return value
466    /// * `Option<&mut Worksheet>`.
467    #[inline]
468    pub fn get_sheet_by_name_mut(&mut self, sheet_name: &str) -> Option<&mut Worksheet> {
469        self.find_sheet_index_by_name(sheet_name)
470            .and_then(move |index| self.get_sheet_mut(&index))
471    }
472
473    #[inline]
474    pub fn set_active_sheet(&mut self, index: u32) -> &mut Self {
475        self.get_workbook_view_mut().set_active_tab(index);
476        self
477    }
478
479    /// Get Active Work Sheet.
480    /// # Return value
481    /// * `&Worksheet` - Work sheet.
482    #[inline]
483    pub fn get_active_sheet(&self) -> &Worksheet {
484        let index = *self.get_workbook_view().get_active_tab();
485        self.get_sheet(&(index as usize)).unwrap()
486    }
487
488    /// Get Active Work Sheet in mutable.
489    /// # Return value
490    /// * `&mut Worksheet` - Work sheet.
491    #[inline]
492    pub fn get_active_sheet_mut(&mut self) -> &mut Worksheet {
493        let index = *self.get_workbook_view().get_active_tab();
494        self.get_sheet_mut(&(index as usize)).unwrap()
495    }
496
497    /// Add Work Sheet.
498    /// # Arguments
499    /// * `value` - Work Sheet
500    /// # Return value
501    /// * `Result<&mut Worksheet, &'static str>` - OK:added work sheet. Err:Error.
502    #[inline]
503    pub fn add_sheet(&mut self, value: Worksheet) -> Result<&mut Worksheet, &'static str> {
504        let title = value.get_name();
505        Spreadsheet::check_sheet_name(self, title)?;
506        self.work_sheet_collection.push(value);
507        Ok(self.work_sheet_collection.last_mut().unwrap())
508    }
509
510    /// Remove Work Sheet.
511    /// # Arguments
512    /// * `index` - sheet index
513    /// # Return value
514    /// * `Result<(), &'static str>` - OK:removed worksheet. Err:Error.
515    #[inline]
516    pub fn remove_sheet(&mut self, index: usize) -> Result<(), &'static str> {
517        if self.work_sheet_collection.len() <= index {
518            return Err("out of index.");
519        }
520        self.work_sheet_collection.remove(index);
521        Ok(())
522    }
523
524    /// Remove Work Sheet.
525    /// # Arguments
526    /// * `sheet_name` - sheet name
527    /// # Return value
528    /// * `Result<(), &'static str>` - OK:removed worksheet. Err:Error.
529    pub fn remove_sheet_by_name(&mut self, sheet_name: &str) -> Result<(), &'static str> {
530        let cnt_before = self.work_sheet_collection.len();
531        self.work_sheet_collection
532            .retain(|x| x.get_name() != sheet_name);
533        let cnt_after = self.work_sheet_collection.len();
534        if cnt_before == cnt_after {
535            return Err("out of index.");
536        }
537        Ok(())
538    }
539
540    /// Add New Work Sheet.
541    /// # Arguments
542    /// * `sheet_title` - sheet title
543    /// # Return value
544    /// * `Result<&mut Worksheet, &'static str>` - OK:added work sheet. Err:Error.
545    #[inline]
546    pub fn new_sheet<S: Into<String>>(
547        &mut self,
548        sheet_title: S,
549    ) -> Result<&mut Worksheet, &'static str> {
550        let v = sheet_title.into();
551        Spreadsheet::check_sheet_name(self, &v)?;
552        let sheet_id = (self.work_sheet_collection.len() + 1).to_string();
553        Ok(Spreadsheet::add_new_sheet_crate(
554            self,
555            sheet_id,
556            v.to_string(),
557        ))
558    }
559
560    /// (This method is crate only.)
561    /// Add New Work Sheet.
562    /// # Arguments
563    /// * `index` - sheet index
564    /// * `sheet_title` - sheet title
565    /// # Return value
566    /// * `&mut Worksheet` - added work sheet.
567    pub(crate) fn add_new_sheet_crate<S: Into<String>>(
568        &mut self,
569        sheet_id: S,
570        sheet_title: S,
571    ) -> &mut Worksheet {
572        let mut worksheet = Worksheet::default();
573        worksheet.set_sheet_id(sheet_id);
574        worksheet.set_name(sheet_title.into());
575        worksheet
576            .get_sheet_format_properties_mut()
577            .set_defalut_value();
578        self.work_sheet_collection.push(worksheet);
579        self.work_sheet_collection.last_mut().unwrap()
580    }
581
582    /// Set Sheet Name.
583    /// # Arguments
584    /// * `index` - target sheet index
585    /// * `sheet_name` - sheet name
586    /// # Return value
587    /// * `Result<(), &'static str>` - OK:Success  Err:Error.
588    pub fn set_sheet_name<S: Into<String>>(
589        &mut self,
590        index: usize,
591        sheet_name: S,
592    ) -> Result<(), &'static str> {
593        let sheet_name_str = sheet_name.into();
594        Spreadsheet::check_sheet_name(self, sheet_name_str.as_ref())?;
595        self.work_sheet_collection
596            .get_mut(index)
597            .map(|sheet| {
598                sheet.set_name(sheet_name_str);
599            })
600            .ok_or("sheet not found.")
601    }
602
603    /// (This method is crate only.)
604    /// Check for duplicate sheet name.
605    pub(crate) fn check_sheet_name(&self, value: &str) -> Result<(), &'static str> {
606        match self
607            .work_sheet_collection
608            .iter()
609            .any(|work_sheet| value == work_sheet.get_name())
610        {
611            true => Err("name duplicate."),
612            false => Ok(()),
613        }
614    }
615
616    /// (This method is crate only.)
617    /// Has Ribbon XML Data.
618    #[inline]
619    pub(crate) fn has_ribbon(&self) -> bool {
620        self.ribbon_xml_data.has_value()
621    }
622
623    /// Get Workbook View.
624    #[inline]
625    pub fn get_workbook_view(&self) -> &WorkbookView {
626        &self.workbook_view
627    }
628
629    /// Get Workbook View in mutable.
630    #[inline]
631    pub fn get_workbook_view_mut(&mut self) -> &mut WorkbookView {
632        &mut self.workbook_view
633    }
634
635    /// Set Workbook View.
636    /// # Arguments
637    /// * `value` - WorkbookView
638    #[inline]
639    pub fn set_workbook_view(&mut self, value: WorkbookView) -> &mut Self {
640        self.workbook_view = value;
641        self
642    }
643
644    /// (This method is crate only.)
645    /// Has Defined Names.
646    #[inline]
647    pub(crate) fn has_defined_names(&self) -> bool {
648        if !self.defined_names.is_empty() {
649            return true;
650        }
651        self.get_sheet_collection_no_check()
652            .iter()
653            .any(|sheet| sheet.has_defined_names())
654    }
655
656    #[inline]
657    pub(crate) fn get_backup_context_types(&self) -> &[(Box<str>, Box<str>)] {
658        &self.backup_context_types
659    }
660
661    #[inline]
662    pub(crate) fn set_backup_context_types(
663        &mut self,
664        value: impl Into<ThinVec<(String, String)>>,
665    ) -> &mut Self {
666        self.backup_context_types = value
667            .into()
668            .into_iter()
669            .map(|(a, b)| (a.into_boxed_str(), b.into_boxed_str()))
670            .collect();
671        self
672    }
673
674    pub(crate) fn get_pivot_caches(&self) -> Vec<(String, String, String)> {
675        let mut result: Vec<(String, String, String)> = Vec::new();
676        for (val1, val2, val3) in &self.pivot_caches {
677            let val3_up = format!("xl/{}", &val3);
678            for worksheet in self.get_sheet_collection_no_check() {
679                for pivot_cache_definition in worksheet.get_pivot_cache_definition_collection() {
680                    if &val3_up == pivot_cache_definition
681                        && !result.iter().any(|(_, _, r_val3)| r_val3 == &**val3)
682                    {
683                        result.push((val1.to_string(), val2.to_string(), val3.to_string()));
684                    }
685                }
686            }
687        }
688        result
689    }
690
691    #[inline]
692    pub(crate) fn add_pivot_caches(&mut self, value: (String, String, String)) -> &mut Self {
693        self.pivot_caches.push((
694            value.0.into_boxed_str(),
695            value.1.into_boxed_str(),
696            value.2.into_boxed_str(),
697        ));
698        self
699    }
700
701    #[inline]
702    pub(crate) fn update_pivot_caches(&mut self, key: String, value: String) -> &mut Self {
703        self.pivot_caches.iter_mut().for_each(|(val1, _, val3)| {
704            if &**val1 == &key {
705                *val3 = value.clone().into_boxed_str()
706            };
707        });
708        self
709    }
710
711    #[inline]
712    pub fn get_workbook_protection(&self) -> Option<&WorkbookProtection> {
713        self.workbook_protection.as_deref()
714    }
715
716    #[inline]
717    pub fn get_workbook_protection_mut(&mut self) -> &mut WorkbookProtection {
718        self.workbook_protection
719            .get_or_insert(Box::new(WorkbookProtection::default()))
720    }
721
722    #[inline]
723    pub fn set_workbook_protection(&mut self, value: WorkbookProtection) -> &mut Self {
724        self.workbook_protection = Some(Box::new(value));
725        self
726    }
727
728    #[inline]
729    pub fn remove_workbook_protection(&mut self) -> &mut Self {
730        self.workbook_protection = None;
731        self
732    }
733
734    /// Get Defined Name (Vec).
735    #[inline]
736    pub fn get_defined_names(&self) -> &[DefinedName] {
737        &self.defined_names
738    }
739
740    /// Get Defined Name (Vec) in mutable.
741    #[inline]
742    pub fn get_defined_names_mut(&mut self) -> &mut ThinVec<DefinedName> {
743        &mut self.defined_names
744    }
745
746    /// Set Defined Name (Vec).
747    /// # Arguments
748    /// * `value` - Vec<DefinedName>.
749    #[inline]
750    pub fn set_defined_names(&mut self, value: impl Into<ThinVec<DefinedName>>) {
751        self.defined_names = value.into();
752    }
753
754    /// Add Defined Name.
755    /// # Arguments
756    /// * `value` - DefinedName.
757    #[inline]
758    pub fn add_defined_names(&mut self, value: DefinedName) {
759        self.defined_names.push(value);
760    }
761
762    /// Has ThreadedComments.
763    #[inline]
764    pub fn has_threaded_comments(&self) -> bool {
765        for worksheet in &self.work_sheet_collection {
766            if worksheet.has_threaded_comments() {
767                return true;
768            }
769        }
770        return false;
771    }
772}
773impl AdjustmentCoordinateWithSheet for Spreadsheet {
774    fn adjustment_insert_coordinate_with_sheet(
775        &mut self,
776        sheet_name: &str,
777        root_col_num: &u32,
778        offset_col_num: &u32,
779        root_row_num: &u32,
780        offset_row_num: &u32,
781    ) {
782        self.read_sheet_collection();
783        for worksheet in &mut self.work_sheet_collection {
784            worksheet.adjustment_insert_coordinate(
785                root_col_num,
786                offset_col_num,
787                root_row_num,
788                offset_row_num,
789            );
790            worksheet.adjustment_insert_coordinate_with_sheet(
791                sheet_name,
792                root_col_num,
793                offset_col_num,
794                root_row_num,
795                offset_row_num,
796            );
797        }
798    }
799
800    fn adjustment_remove_coordinate_with_sheet(
801        &mut self,
802        sheet_name: &str,
803        root_col_num: &u32,
804        offset_col_num: &u32,
805        root_row_num: &u32,
806        offset_row_num: &u32,
807    ) {
808        self.read_sheet_collection();
809        for worksheet in &mut self.work_sheet_collection {
810            worksheet.adjustment_remove_coordinate(
811                root_col_num,
812                offset_col_num,
813                root_row_num,
814                offset_row_num,
815            );
816            worksheet.adjustment_remove_coordinate_with_sheet(
817                sheet_name,
818                root_col_num,
819                offset_col_num,
820                root_row_num,
821                offset_row_num,
822            );
823        }
824    }
825}