umya_spreadsheet/structs/
properties.rs

1use crate::helper::const_str::*;
2use crate::reader::driver::*;
3use crate::structs::custom_properties::Properties as CustomProperties;
4use crate::structs::StringValue;
5use crate::structs::Worksheet;
6use crate::writer::driver::*;
7use quick_xml::events::BytesStart;
8use quick_xml::events::Event;
9use quick_xml::Reader;
10use quick_xml::Writer;
11use std::borrow::Cow;
12use std::io::Cursor;
13
14#[derive(Clone, Debug)]
15pub struct Properties {
16    creator: StringValue,
17    last_modified_by: StringValue,
18    created: StringValue,
19    modified: StringValue,
20    title: StringValue,
21    description: StringValue,
22    subject: StringValue,
23    keywords: StringValue,
24    category: StringValue,
25    manager: StringValue,
26    company: StringValue,
27    revision: StringValue,
28    version: StringValue,
29    custom_properties: CustomProperties,
30}
31impl Default for Properties {
32    #[inline]
33    fn default() -> Self {
34        let mut created = StringValue::default();
35        let mut modified = StringValue::default();
36        created.set_value("2006-09-16T00:00:00Z");
37        modified.set_value("2006-09-16T00:00:00Z");
38        Self {
39            creator: StringValue::default(),
40            last_modified_by: StringValue::default(),
41            created,
42            modified,
43            title: StringValue::default(),
44            description: StringValue::default(),
45            subject: StringValue::default(),
46            keywords: StringValue::default(),
47            category: StringValue::default(),
48            manager: StringValue::default(),
49            company: StringValue::default(),
50            revision: StringValue::default(),
51            version: StringValue::default(),
52            custom_properties: CustomProperties::default(),
53        }
54    }
55}
56impl Properties {
57    #[inline]
58    pub fn get_creator(&self) -> &str {
59        &self.creator.get_value_str()
60    }
61
62    #[inline]
63    pub fn set_creator<S: Into<String>>(&mut self, value: S) -> &mut Self {
64        self.creator.set_value(value);
65        self
66    }
67
68    #[inline]
69    pub fn get_last_modified_by(&self) -> &str {
70        &self.last_modified_by.get_value_str()
71    }
72
73    #[inline]
74    pub fn set_last_modified_by<S: Into<String>>(&mut self, value: S) -> &mut Self {
75        self.last_modified_by.set_value(value);
76        self
77    }
78
79    #[inline]
80    pub fn get_created(&self) -> &str {
81        &self.created.get_value_str()
82    }
83
84    #[inline]
85    pub fn set_created<S: Into<String>>(&mut self, value: S) -> &mut Self {
86        self.created.set_value(value);
87        self
88    }
89
90    #[inline]
91    pub fn get_modified(&self) -> &str {
92        &self.modified.get_value_str()
93    }
94
95    #[inline]
96    pub fn set_modified<S: Into<String>>(&mut self, value: S) -> &mut Self {
97        self.modified.set_value(value);
98        self
99    }
100
101    #[inline]
102    pub fn get_title(&self) -> &str {
103        &self.title.get_value_str()
104    }
105
106    #[inline]
107    pub fn set_title<S: Into<String>>(&mut self, value: S) -> &mut Self {
108        self.title.set_value(value);
109        self
110    }
111
112    #[inline]
113    pub fn get_description(&self) -> &str {
114        &self.description.get_value_str()
115    }
116
117    #[inline]
118    pub fn set_description<S: Into<String>>(&mut self, value: S) -> &mut Self {
119        self.description.set_value(value);
120        self
121    }
122
123    #[inline]
124    pub fn get_subject(&self) -> &str {
125        &self.subject.get_value_str()
126    }
127
128    #[inline]
129    pub fn set_subject<S: Into<String>>(&mut self, value: S) -> &mut Self {
130        self.subject.set_value(value);
131        self
132    }
133
134    #[inline]
135    pub fn get_keywords(&self) -> &str {
136        &self.keywords.get_value_str()
137    }
138
139    #[inline]
140    pub fn set_keywords<S: Into<String>>(&mut self, value: S) -> &mut Self {
141        self.keywords.set_value(value);
142        self
143    }
144
145    #[inline]
146    pub fn get_revision(&self) -> &str {
147        &self.revision.get_value_str()
148    }
149
150    #[inline]
151    pub fn set_revision<S: Into<String>>(&mut self, value: S) -> &mut Self {
152        self.revision.set_value(value);
153        self
154    }
155
156    #[inline]
157    pub fn get_category(&self) -> &str {
158        &self.category.get_value_str()
159    }
160
161    #[inline]
162    pub fn set_category<S: Into<String>>(&mut self, value: S) -> &mut Self {
163        self.category.set_value(value);
164        self
165    }
166
167    #[inline]
168    pub fn get_version(&self) -> &str {
169        &self.version.get_value_str()
170    }
171
172    #[inline]
173    pub fn set_version<S: Into<String>>(&mut self, value: S) -> &mut Self {
174        self.version.set_value(value);
175        self
176    }
177
178    #[inline]
179    pub fn get_manager(&self) -> &str {
180        &self.manager.get_value_str()
181    }
182
183    #[inline]
184    pub fn set_manager<S: Into<String>>(&mut self, value: S) -> &mut Self {
185        self.manager.set_value(value);
186        self
187    }
188
189    #[inline]
190    pub fn get_company(&self) -> &str {
191        &self.company.get_value_str()
192    }
193
194    #[inline]
195    pub fn set_company<S: Into<String>>(&mut self, value: S) -> &mut Self {
196        self.company.set_value(value);
197        self
198    }
199
200    #[inline]
201    pub fn get_custom_properties(&self) -> &CustomProperties {
202        &self.custom_properties
203    }
204
205    #[inline]
206    pub fn get_custom_properties_mut(&mut self) -> &mut CustomProperties {
207        &mut self.custom_properties
208    }
209
210    #[inline]
211    pub fn set_custom_properties(&mut self, value: CustomProperties) -> &mut Self {
212        self.custom_properties = value;
213        self
214    }
215
216    pub(crate) fn set_attributes_core<R: std::io::BufRead>(
217        &mut self,
218        reader: &mut Reader<R>,
219        _e: &BytesStart,
220    ) {
221        let mut value: String = String::new();
222        xml_read_loop!(
223            reader,
224            Event::Text(e) => {
225                value = e.unescape().unwrap().to_string();
226            },
227            Event::End(ref e) => match e.name().into_inner() {
228                b"dc:title" => {self.set_title(std::mem::take(&mut value));},
229                b"dc:subject" => {self.set_subject(std::mem::take(&mut value));},
230                b"dc:creator" => {self.set_creator(std::mem::take(&mut value));},
231                b"cp:keywords" => {self.set_keywords(std::mem::take(&mut value));},
232                b"dc:description" => {self.set_description(std::mem::take(&mut value));},
233                b"cp:lastModifiedBy" => {self.set_last_modified_by(std::mem::take(&mut value));},
234                b"cp:revision" => {self.set_revision(std::mem::take(&mut value));},
235                b"dcterms:created" => {self.set_created(std::mem::take(&mut value));},
236                b"dcterms:modified" => {self.set_modified(std::mem::take(&mut value));},
237                b"cp:category" => {self.set_category(std::mem::take(&mut value));},
238                b"cp:version" => {self.set_version(std::mem::take(&mut value));},
239                b"Manager" => {self.set_manager(std::mem::take(&mut value));},
240                b"Company" => {self.set_company(std::mem::take(&mut value));},
241                _ => {}
242            },
243            Event::Eof => return,
244        );
245    }
246
247    pub(crate) fn set_attributes_app<R: std::io::BufRead>(
248        &mut self,
249        reader: &mut Reader<R>,
250        _e: &BytesStart,
251    ) {
252        let mut value: String = String::new();
253        xml_read_loop!(
254            reader,
255            Event::Start(ref e) => {
256                match e.name().into_inner(){
257                    b"Manager" => {value = String::new();},
258                    b"Company" => {value = String::new();},
259                    _ => {}
260                }
261            },
262            Event::Text(e) => {
263                value = e.unescape().unwrap().to_string();
264            },
265            Event::End(ref e) => match e.name().into_inner() {
266                b"Manager" => {self.set_manager(std::mem::take(&mut value));}
267                b"Company" => {self.set_company(std::mem::take(&mut value));}
268                _ =>{}
269            },
270            Event::Eof => return,
271        );
272    }
273
274    #[inline]
275    pub(crate) fn set_attributes_custom<R: std::io::BufRead>(
276        &mut self,
277        reader: &mut Reader<R>,
278        e: &BytesStart,
279    ) {
280        let mut obj = CustomProperties::default();
281        obj.set_attributes(reader, e);
282        self.set_custom_properties(obj);
283    }
284
285    pub(crate) fn write_to_core(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
286        // cp:coreProperties
287        write_start_tag(
288            writer,
289            "cp:coreProperties",
290            vec![
291                ("xmlns:cp", COREPROPS_NS),
292                ("xmlns:dc", DCORE_NS),
293                ("xmlns:dcterms", DCTERMS_NS),
294                ("xmlns:dcmitype", DCMITYPE_NS),
295                ("xmlns:xsi", XSI_NS),
296            ],
297            false,
298        );
299
300        // dc:title
301        if self.title.has_value() {
302            write_start_tag(writer, "dc:title", vec![], false);
303            write_text_node(writer, self.title.get_value_str());
304            write_end_tag(writer, "dc:title");
305        }
306
307        // dc:subject
308        if self.subject.has_value() {
309            write_start_tag(writer, "dc:subject", vec![], false);
310            write_text_node(writer, self.subject.get_value_str());
311            write_end_tag(writer, "dc:subject");
312        }
313
314        // dc:creator
315        if self.creator.has_value() {
316            write_start_tag(writer, "dc:creator", vec![], false);
317            write_text_node(writer, self.creator.get_value_str());
318            write_end_tag(writer, "dc:creator");
319        }
320
321        // cp:keywords
322        if self.keywords.has_value() {
323            write_start_tag(writer, "cp:keywords", vec![], false);
324            write_text_node(writer, self.keywords.get_value_str());
325            write_end_tag(writer, "cp:keywords");
326        }
327
328        // dc:description
329        if self.description.has_value() {
330            write_start_tag(writer, "dc:description", vec![], false);
331            write_text_node(writer, self.description.get_value_str());
332            write_end_tag(writer, "dc:description");
333        }
334
335        // cp:lastModifiedBy
336        if self.last_modified_by.has_value() {
337            write_start_tag(writer, "cp:lastModifiedBy", vec![], false);
338            write_text_node(writer, self.last_modified_by.get_value_str());
339            write_end_tag(writer, "cp:lastModifiedBy");
340        }
341
342        // cp:revision
343        if self.revision.has_value() {
344            write_start_tag(writer, "cp:revision", vec![], false);
345            write_text_node(writer, self.revision.get_value_str());
346            write_end_tag(writer, "cp:revision");
347        }
348
349        // dcterms:created
350        if self.created.has_value() {
351            write_start_tag(
352                writer,
353                "dcterms:created",
354                vec![("xsi:type", "dcterms:W3CDTF")],
355                false,
356            );
357            write_text_node(writer, self.created.get_value_str());
358            write_end_tag(writer, "dcterms:created");
359        }
360
361        // dcterms:modified
362        if self.modified.has_value() {
363            write_start_tag(
364                writer,
365                "dcterms:modified",
366                vec![("xsi:type", "dcterms:W3CDTF")],
367                false,
368            );
369            write_text_node(writer, self.modified.get_value_str());
370            write_end_tag(writer, "dcterms:modified");
371        }
372
373        // cp:category
374        if self.category.has_value() {
375            write_start_tag(writer, "cp:category", vec![], false);
376            write_text_node(writer, self.category.get_value_str());
377            write_end_tag(writer, "cp:category");
378        }
379
380        // cp:version
381        if self.version.has_value() {
382            write_start_tag(writer, "cp:version", vec![], false);
383            write_text_node(writer, self.version.get_value_str());
384            write_end_tag(writer, "cp:version");
385        }
386
387        write_end_tag(writer, "cp:coreProperties");
388    }
389
390    pub(crate) fn write_to_app(
391        &self,
392        writer: &mut Writer<Cursor<Vec<u8>>>,
393        work_sheet_collection: &[Worksheet],
394    ) {
395        let sheet_count_str = work_sheet_collection.len().to_string();
396
397        // Properties
398        write_start_tag(
399            writer,
400            "Properties",
401            vec![("xmlns", XPROPS_NS), ("xmlns:vt", VTYPES_NS)],
402            false,
403        );
404
405        // Application
406        write_start_tag(writer, "Application", vec![], false);
407        write_text_node(writer, "Microsoft Excel");
408        write_end_tag(writer, "Application");
409
410        // DocSecurity
411        write_start_tag(writer, "DocSecurity", vec![], false);
412        write_text_node(writer, "0");
413        write_end_tag(writer, "DocSecurity");
414
415        // ScaleCrop
416        write_start_tag(writer, "ScaleCrop", vec![], false);
417        write_text_node(writer, "false");
418        write_end_tag(writer, "ScaleCrop");
419
420        // HeadingPairs
421        write_start_tag(writer, "HeadingPairs", vec![], false);
422
423        // vt:vector
424        write_start_tag(
425            writer,
426            "vt:vector",
427            vec![("size", "2"), ("baseType", "variant")],
428            false,
429        );
430
431        // vt:variant
432        write_start_tag(writer, "vt:variant", vec![], false);
433
434        // vt:i4
435        write_start_tag(writer, "vt:lpstr", vec![], false);
436        write_text_node(writer, "Worksheets");
437        write_end_tag(writer, "vt:lpstr");
438
439        write_end_tag(writer, "vt:variant");
440
441        // vt:variant
442        write_start_tag(writer, "vt:variant", vec![], false);
443
444        // vt:i4
445        write_start_tag(writer, "vt:i4", vec![], false);
446        write_text_node(writer, &sheet_count_str);
447        write_end_tag(writer, "vt:i4");
448
449        write_end_tag(writer, "vt:variant");
450
451        write_end_tag(writer, "vt:vector");
452
453        write_end_tag(writer, "HeadingPairs");
454
455        // TitlesOfParts
456        write_start_tag(writer, "TitlesOfParts", vec![], false);
457
458        // vt:vector
459        write_start_tag(
460            writer,
461            "vt:vector",
462            vec![("size", &sheet_count_str), ("baseType", "lpstr")],
463            false,
464        );
465
466        for workseet in work_sheet_collection {
467            // vt:lpstr
468            write_start_tag(writer, "vt:lpstr", vec![], false);
469            write_text_node(writer, workseet.get_name());
470            write_end_tag(writer, "vt:lpstr");
471        }
472
473        write_end_tag(writer, "vt:vector");
474
475        write_end_tag(writer, "TitlesOfParts");
476
477        // Manager
478        write_start_tag(writer, "Manager", vec![], false);
479        write_text_node(writer, self.get_manager());
480        write_end_tag(writer, "Manager");
481
482        // Company
483        write_start_tag(writer, "Company", vec![], false);
484        write_text_node(writer, self.get_company());
485        write_end_tag(writer, "Company");
486
487        // LinksUpToDate
488        write_start_tag(writer, "LinksUpToDate", vec![], false);
489        write_text_node(writer, "false");
490        write_end_tag(writer, "LinksUpToDate");
491
492        // SharedDoc
493        write_start_tag(writer, "SharedDoc", vec![], false);
494        write_text_node(writer, "false");
495        write_end_tag(writer, "SharedDoc");
496
497        // HyperlinksChanged
498        write_start_tag(writer, "HyperlinksChanged", vec![], false);
499        write_text_node(writer, "false");
500        write_end_tag(writer, "HyperlinksChanged");
501
502        // AppVersion
503        write_start_tag(writer, "AppVersion", vec![], false);
504        write_text_node(writer, "14.0300");
505        write_end_tag(writer, "AppVersion");
506
507        write_end_tag(writer, "Properties");
508    }
509
510    #[inline]
511    pub(crate) fn write_to_custom(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
512        self.custom_properties.write_to(writer);
513    }
514}