umya_spreadsheet/structs/
ole_object.rs1use super::EmbeddedObjectProperties;
2use super::StringValue;
3use crate::helper::const_str::MC_NS;
4use crate::reader::driver::*;
5use crate::structs::drawing::spreadsheet::TwoCellAnchor;
6use crate::structs::raw::RawRelationships;
7use crate::structs::vml::Shape;
8use crate::writer::driver::*;
9use quick_xml::events::{BytesStart, Event};
10use quick_xml::Reader;
11use quick_xml::Writer;
12use std::io::Cursor;
13use thin_vec::ThinVec;
14
15#[derive(Clone, Default, Debug)]
16pub struct OleObject {
17 requires: StringValue,
18 prog_id: StringValue,
19 object_extension: Box<str>,
20 object_data: Option<ThinVec<u8>>,
21 embedded_object_properties: EmbeddedObjectProperties,
22 two_cell_anchor: TwoCellAnchor,
23 shape: Shape,
24}
25
26impl OleObject {
27 #[inline]
28 pub fn get_requires(&self) -> &str {
29 self.requires.get_value_str()
30 }
31
32 #[inline]
33 pub fn set_requires<S: Into<String>>(&mut self, value: S) -> &mut Self {
34 self.requires.set_value(value);
35 self
36 }
37
38 #[inline]
39 pub fn get_prog_id(&self) -> &str {
40 self.prog_id.get_value_str()
41 }
42
43 #[inline]
44 pub fn set_prog_id<S: Into<String>>(&mut self, value: S) -> &mut Self {
45 self.prog_id.set_value(value);
46 self
47 }
48
49 #[inline]
50 pub fn get_object_extension(&self) -> &str {
51 &self.object_extension
52 }
53
54 #[inline]
55 pub fn set_object_extension<S: Into<String>>(&mut self, value: S) {
56 self.object_extension = value.into().into_boxed_str();
57 }
58
59 #[inline]
60 pub fn get_object_data(&self) -> Option<&[u8]> {
61 self.object_data.as_deref()
62 }
63
64 #[inline]
65 pub fn get_object_data_mut(&mut self) -> Option<&mut ThinVec<u8>> {
66 self.object_data.as_mut()
67 }
68
69 #[inline]
70 pub fn set_object_data(&mut self, value: impl Into<ThinVec<u8>>) -> &mut Self {
71 self.object_data = Some(value.into());
72 self
73 }
74
75 #[inline]
76 pub fn get_embedded_object_properties(&self) -> &EmbeddedObjectProperties {
77 &self.embedded_object_properties
78 }
79
80 #[inline]
81 pub fn get_embedded_object_properties_mut(&mut self) -> &mut EmbeddedObjectProperties {
82 &mut self.embedded_object_properties
83 }
84
85 #[inline]
86 pub fn set_embedded_object_properties(&mut self, value: EmbeddedObjectProperties) -> &mut Self {
87 self.embedded_object_properties = value;
88 self
89 }
90
91 #[inline]
92 pub fn get_two_cell_anchor(&self) -> &TwoCellAnchor {
93 &self.two_cell_anchor
94 }
95
96 #[inline]
97 pub fn get_two_cell_anchor_mut(&mut self) -> &mut TwoCellAnchor {
98 &mut self.two_cell_anchor
99 }
100
101 #[inline]
102 pub fn set_two_cell_anchor(&mut self, value: TwoCellAnchor) -> &mut Self {
103 self.two_cell_anchor = value;
104 self
105 }
106
107 #[inline]
108 pub fn get_shape(&self) -> &Shape {
109 &self.shape
110 }
111
112 #[inline]
113 pub fn get_shape_mut(&mut self) -> &mut Shape {
114 &mut self.shape
115 }
116
117 #[inline]
118 pub fn set_shape(&mut self, value: Shape) -> &mut Self {
119 self.shape = value;
120 self
121 }
122
123 #[inline]
124 pub(crate) fn is_bin(&self) -> bool {
125 &*self.object_extension == "bin"
126 }
127
128 #[inline]
129 pub(crate) fn is_xlsx(&self) -> bool {
130 &*self.object_extension == "xlsx"
131 }
132
133 pub(crate) fn set_attributes<R: std::io::BufRead>(
134 &mut self,
135 reader: &mut Reader<R>,
136 _e: &BytesStart,
137 relationships: &RawRelationships,
138 ) {
139 let mut alternate_content: &str = "";
140
141 xml_read_loop!(
142 reader,
143 Event::Start(ref e) => {
144 match e.name().into_inner() {
145 b"mc:Choice" => {
146 alternate_content = "Choice";
147 set_string_from_xml!(self, e, requires, "Requires");
148 }
149 b"mc:Fallback" => {
150 alternate_content = "Fallback";
151 }
152 b"oleObject" => {
153 if alternate_content == "Choice" {
154 self.prog_id
155 .set_value_string(get_attribute(e, b"progId").unwrap());
156
157 let r_id = get_attribute(e, b"r:id").unwrap();
158 let attached_file =
159 relationships.get_relationship_by_rid(&r_id).get_raw_file();
160 self.set_object_extension(attached_file.get_extension());
161 self.set_object_data(attached_file.get_file_data().clone());
162 }
163 }
164 b"objectPr" => {
165 let mut obj = EmbeddedObjectProperties::default();
166 obj.set_attributes(reader, e, relationships);
167 self.set_embedded_object_properties(obj);
168 }
169 _ => (),
170 }
171 },
172 Event::End(ref e) => {
173 if e.name().into_inner() == b"mc:AlternateContent" {
174 return
175 }
176 },
177 Event::Eof => panic!("Error: Could not find {} end element", "mc:AlternateContent")
178 );
179 }
180
181 pub(crate) fn write_to(
182 &self,
183 writer: &mut Writer<Cursor<Vec<u8>>>,
184 r_id: &usize,
185 ole_id: &usize,
186 ) {
187 write_start_tag(
189 writer,
190 "mc:AlternateContent",
191 vec![("xmlns:mc", MC_NS)],
192 false,
193 );
194
195 write_start_tag(
197 writer,
198 "mc:Choice",
199 vec![("Requires", self.requires.get_value_str())],
200 false,
201 );
202
203 let r_id_str = format!("rId{}", r_id);
205 let shape_id_str = format!("{}", ole_id);
206 let attributes = vec![
207 ("progId", self.prog_id.get_value_str()),
208 ("shapeId", &shape_id_str),
209 ("r:id", &r_id_str),
210 ];
211 write_start_tag(writer, "oleObject", attributes, false);
212
213 self.embedded_object_properties
215 .write_to(writer, &(r_id + 1));
216
217 write_end_tag(writer, "oleObject");
218
219 write_end_tag(writer, "mc:Choice");
220
221 write_start_tag(writer, "mc:Fallback", vec![], false);
223
224 let r_id_str = format!("rId{}", r_id);
226 let attributes = vec![
227 ("progId", self.prog_id.get_value_str()),
228 ("shapeId", &shape_id_str),
229 ("r:id", &r_id_str),
230 ];
231 write_start_tag(writer, "oleObject", attributes, true);
232
233 write_end_tag(writer, "mc:Fallback");
234
235 write_end_tag(writer, "mc:AlternateContent");
236 }
237}