umya_spreadsheet/structs/custom_properties/
custom_document_property.rs

1use crate::reader::driver::*;
2use crate::structs::custom_properties::CustomDocumentPropertyValue;
3use crate::structs::StringValue;
4use crate::writer::driver::*;
5use quick_xml::events::BytesStart;
6use quick_xml::events::Event;
7use quick_xml::Reader;
8use quick_xml::Writer;
9use std::borrow::Cow;
10use std::io::Cursor;
11
12#[derive(Default, Debug, Clone)]
13pub struct CustomDocumentProperty {
14    name: StringValue,
15    link_target: StringValue,
16    custom_document_property_value: CustomDocumentPropertyValue,
17}
18
19impl CustomDocumentProperty {
20    #[inline]
21    pub fn get_name(&self) -> &str {
22        self.name.get_value_str()
23    }
24
25    #[inline]
26    pub fn set_name<S: Into<String>>(&mut self, value: S) -> &mut Self {
27        self.name.set_value(value);
28        self
29    }
30
31    #[inline]
32    pub fn get_link_target(&self) -> &str {
33        self.link_target.get_value_str()
34    }
35
36    #[inline]
37    pub fn set_link_target<S: Into<String>>(&mut self, value: S) -> &mut Self {
38        self.link_target.set_value(value);
39        self
40    }
41
42    #[inline]
43    pub fn get_value(&self) -> Cow<'static, str> {
44        self.custom_document_property_value.to_string().into()
45    }
46
47    #[inline]
48    pub fn get_value_number(&self) -> Option<i32> {
49        self.custom_document_property_value.get_number()
50    }
51
52    #[inline]
53    pub fn get_value_bool(&self) -> Option<bool> {
54        self.custom_document_property_value.get_bool()
55    }
56
57    #[inline]
58    pub fn set_value_string<S: Into<String>>(&mut self, value: S) -> &mut Self {
59        self.custom_document_property_value =
60            CustomDocumentPropertyValue::String(value.into().into_boxed_str());
61        self
62    }
63
64    #[inline]
65    pub fn set_value_number<T>(&mut self, value: T) -> &mut Self
66    where
67        T: Into<i32>,
68    {
69        self.custom_document_property_value = CustomDocumentPropertyValue::Numeric(value.into());
70        self
71    }
72
73    #[inline]
74    pub fn set_value_date(&mut self, year: i32, month: i32, day: i32) -> &mut Self {
75        let value = format!("{:>04}-{:>02}-{:>02}T10:00:00Z", year, month, day);
76        self.custom_document_property_value =
77            CustomDocumentPropertyValue::Date(value.into_boxed_str());
78        self
79    }
80
81    #[inline]
82    pub fn set_value_date_manual<S: Into<String>>(&mut self, value: S) -> &mut Self {
83        self.custom_document_property_value =
84            CustomDocumentPropertyValue::Date(value.into().into_boxed_str());
85        self
86    }
87
88    #[inline]
89    pub fn set_value_bool(&mut self, value: bool) -> &mut Self {
90        self.custom_document_property_value = CustomDocumentPropertyValue::Bool(value);
91        self
92    }
93
94    pub(crate) fn set_attributes<R: std::io::BufRead>(
95        &mut self,
96        reader: &mut Reader<R>,
97        e: &BytesStart,
98        empty_flag: bool,
99    ) {
100        set_string_from_xml!(self, e, name, "name");
101        set_string_from_xml!(self, e, link_target, "linkTarget");
102
103        if empty_flag {
104            return;
105        }
106
107        let mut value: String = String::new();
108        xml_read_loop!(
109            reader,
110            Event::Text(e) => {
111                value = e.unescape().unwrap().to_string();
112            },
113            Event::End(ref e) => {
114                match e.name().into_inner(){
115                    b"vt:lpwstr" =>{self.set_value_string(&value);}
116                    b"vt:filetime" =>{self.set_value_date_manual(&value);}
117                    b"vt:i4"=> {self.set_value_number(value.parse::<i32>().unwrap());}
118                    b"vt:bool"=> {self.set_value_bool(matches!(value.as_str(), "true" | "1"));}
119                    b"property"=> {return}
120                    _=>{}
121                }
122            },
123            Event::Eof => panic!("Error: Could not find {} end element", "property")
124        );
125    }
126
127    pub(crate) fn write_to(&self, writer: &mut Writer<Cursor<Vec<u8>>>, pid: &i32) {
128        let is_inner = self.custom_document_property_value.get_tag().is_some();
129
130        // property
131        let mut attributes: Vec<(&str, &str)> = Vec::new();
132
133        attributes.push(("fmtid", r#"{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"#));
134
135        let pid_str = pid.to_string();
136        attributes.push(("pid", &pid_str));
137
138        if self.name.has_value() {
139            attributes.push(("name", self.name.get_value_str()));
140        }
141
142        if self.link_target.has_value() {
143            attributes.push(("linkTarget", self.link_target.get_value_str()));
144        }
145
146        write_start_tag(writer, "property", attributes, !is_inner);
147
148        if is_inner {
149            let tag = self.custom_document_property_value.get_tag().unwrap();
150            let value_str = self.custom_document_property_value.to_string();
151            write_start_tag(writer, tag, vec![], !is_inner);
152            write_text_node(writer, &value_str);
153            write_end_tag(writer, tag);
154
155            write_end_tag(writer, "property");
156        }
157    }
158}