umya_spreadsheet/structs/
writer_manager.rs1use crate::helper::const_str::*;
2use crate::structs::Spreadsheet;
3use crate::structs::XlsxError;
4use crate::writer::driver::*;
5use quick_xml::Writer;
6use std::io;
7use std::io::Cursor;
8pub struct WriterManager<'a, W: io::Seek + io::Write> {
9 files: Vec<String>,
10 arv: &'a mut zip::ZipWriter<W>,
11 is_light: bool,
12 table_no: i32,
13}
14
15impl<'a, W: io::Seek + io::Write> WriterManager<'a, W> {
16 #[inline]
17 pub fn new(arv: &'a mut zip::ZipWriter<W>) -> Self {
18 WriterManager {
19 files: Vec::new(),
20 arv,
21 is_light: false,
22 table_no: 0,
23 }
24 }
25
26 #[inline]
27 pub fn set_is_light(&mut self, value: bool) -> &mut Self {
28 self.is_light = value;
29 self
30 }
31
32 #[inline]
33 pub fn get_is_light(&self) -> &bool {
34 &self.is_light
35 }
36
37 #[inline]
38 pub fn get_num_tables(&self) -> i32 {
39 self.table_no
40 }
41
42 #[inline]
43 pub fn next_table_no(&mut self) -> i32 {
44 self.table_no += 1;
45 self.table_no
46 }
47
48 #[inline]
49 pub(crate) fn add_writer(
50 &mut self,
51 target: &str,
52 writer: Writer<Cursor<Vec<u8>>>,
53 ) -> Result<(), XlsxError> {
54 if !self.check_file_exist(target) {
55 make_file_from_writer(target, self.arv, writer, None, &self.is_light)?;
56 self.files.push(target.to_string());
57 }
58 Ok(())
59 }
60
61 #[inline]
62 pub(crate) fn add_bin(&mut self, target: &str, data: &[u8]) -> Result<(), XlsxError> {
63 if !self.check_file_exist(target) {
64 make_file_from_bin(target, &mut self.arv, data, None, &self.is_light)?;
65 self.files.push(target.to_string());
66 }
67 Ok(())
68 }
69
70 #[inline]
71 pub(crate) fn get_arv_mut(&mut self) -> &mut zip::ZipWriter<W> {
72 &mut self.arv
73 }
74
75 #[inline]
76 pub(crate) fn file_list_sort(&mut self) -> &mut Self {
77 self.files.sort();
78 self
79 }
80
81 #[inline]
82 pub(crate) fn check_file_exist(&mut self, file_path: &str) -> bool {
83 self.file_list_sort();
84 self.files.iter().any(|file| file == file_path)
85 }
86
87 pub(crate) fn add_file_at_drawing(
88 &mut self,
89 writer: Writer<Cursor<Vec<u8>>>,
90 ) -> Result<i32, XlsxError> {
91 let mut index = 0;
92 loop {
93 index += 1;
94 let file_path = format!("{}/drawing{}.xml", PKG_DRAWINGS, index);
95 if !self.check_file_exist(&file_path) {
96 self.add_writer(&file_path, writer)?;
97 return Ok(index);
98 }
99 }
100 }
101
102 pub(crate) fn add_file_at_vml_drawing(
103 &mut self,
104 writer: Writer<Cursor<Vec<u8>>>,
105 ) -> Result<i32, XlsxError> {
106 let mut index = 0;
107 loop {
108 index += 1;
109 let file_path = format!("{}/vmlDrawing{}.vml", PKG_DRAWINGS, index);
110 if !self.check_file_exist(&file_path) {
111 self.add_writer(&file_path, writer)?;
112 return Ok(index);
113 }
114 }
115 }
116
117 pub(crate) fn add_file_at_comment(
118 &mut self,
119 writer: Writer<Cursor<Vec<u8>>>,
120 ) -> Result<i32, XlsxError> {
121 let mut index = 0;
122 loop {
123 index += 1;
124 let file_path = format!("xl/comments{}.xml", index);
125 if !self.check_file_exist(&file_path) {
126 self.add_writer(&file_path, writer)?;
127 return Ok(index);
128 }
129 }
130 }
131
132 pub(crate) fn add_file_at_threaded_comment(
133 &mut self,
134 writer: Writer<Cursor<Vec<u8>>>,
135 ) -> Result<i32, XlsxError> {
136 let mut index = 0;
137 loop {
138 index += 1;
139 let file_path = format!("xl/threadedComments/threadedComment{}.xml", index);
140 if !self.check_file_exist(&file_path) {
141 self.add_writer(&file_path, writer)?;
142 return Ok(index);
143 }
144 }
145 }
146
147 pub(crate) fn add_file_at_chart(
148 &mut self,
149 writer: Writer<Cursor<Vec<u8>>>,
150 ) -> Result<i32, XlsxError> {
151 let mut index = 0;
152 loop {
153 index += 1;
154 let file_path = format!("{}/chart{}.xml", PKG_CHARTS, index);
155 if !self.check_file_exist(&file_path) {
156 self.add_writer(&file_path, writer)?;
157 return Ok(index);
158 }
159 }
160 }
161
162 pub(crate) fn add_file_at_ole_object(&mut self, writer: &[u8]) -> Result<i32, XlsxError> {
163 let mut index = 0;
164 loop {
165 index += 1;
166 let file_path = format!("{}/oleObject{}.bin", PKG_EMBEDDINGS, index);
167 if !self.check_file_exist(&file_path) {
168 self.add_bin(&file_path, writer)?;
169 return Ok(index);
170 }
171 }
172 }
173
174 pub(crate) fn add_file_at_excel(&mut self, writer: &[u8]) -> Result<i32, XlsxError> {
175 let mut index = 0;
176 loop {
177 index += 1;
178 let file_path = format!("{}/Microsoft_Excel_Worksheet{}.xlsx", PKG_EMBEDDINGS, index);
179 if !self.check_file_exist(&file_path) {
180 self.add_bin(&file_path, writer)?;
181 return Ok(index);
182 }
183 }
184 }
185
186 pub(crate) fn add_file_at_printer_settings(&mut self, writer: &[u8]) -> Result<i32, XlsxError> {
187 let mut index = 0;
188 loop {
189 index += 1;
190 let file_path = format!("{}/printerSettings{}.bin", PKG_PRNTR_SETTINGS, index);
191 if !self.check_file_exist(&file_path) {
192 self.add_bin(&file_path, writer)?;
193 return Ok(index);
194 }
195 }
196 }
197
198 #[inline]
199 pub(crate) fn add_file_at_table(
200 &mut self,
201 writer: Writer<Cursor<Vec<u8>>>,
202 table_no: i32,
203 ) -> Result<i32, XlsxError> {
204 let file_path = format!("{}/table{}.xml", PKG_TABLES, table_no);
205 self.add_writer(&file_path, writer)?;
206 return Ok(table_no);
207 }
208
209 #[inline]
210 pub(crate) fn has_extension(&self, extension: &str) -> bool {
211 let extension = format!(".{}", extension);
212 self.files.iter().any(|file| file.ends_with(&extension))
213 }
214
215 pub(crate) fn make_context_type_override(
216 &mut self,
217 spreadsheet: &Spreadsheet,
218 ) -> Vec<(String, String)> {
219 self.file_list_sort();
220
221 let mut list: Vec<(String, String)> = Vec::new();
222 for file in &self.files {
223 let file = format!("/{}", file);
224 let mut content_type = "";
225
226 if file.starts_with("/xl/workbook.xml") {
228 content_type = match spreadsheet.get_has_macros() {
229 true => WORKBOOK_MACRO_TYPE,
230 false => WORKBOOK_TYPE,
231 };
232 }
233
234 if file.starts_with("/xl/worksheets/sheet") {
236 content_type = SHEET_TYPE;
237 }
238
239 if file.starts_with("/xl/tables/table") {
241 content_type = TABLE_TYPE;
242 }
243
244 if file.starts_with("/xl/comments") {
246 content_type = COMMENTS_TYPE;
247 }
248
249 if file.starts_with("/xl/theme/theme") {
251 content_type = THEME_TYPE;
252 }
253
254 if file.starts_with("/xl/styles.xml") {
256 content_type = STYLES_TYPE;
257 }
258
259 if file.starts_with("/xl/sharedStrings.xml") {
261 content_type = SHARED_STRINGS_TYPE;
262 }
263
264 if file.starts_with("/xl/drawings/drawing") {
266 content_type = DRAWING_TYPE;
267 }
268
269 if file.starts_with("/xl/charts/chart") {
271 content_type = CHART_TYPE;
272 }
273
274 if file.starts_with("/xl/embeddings/oleObject") {
276 content_type = OLE_OBJECT_TYPE;
277 }
278
279 if file.starts_with("/xl/vbaProject.bin") {
281 content_type = VBA_TYPE;
282 }
283
284 if file.starts_with("/docProps/core.xml") {
286 content_type = CORE_PROPS_TYPE;
287 }
288
289 if file.starts_with("/docProps/app.xml") {
291 content_type = XPROPS_TYPE;
292 }
293
294 if file.starts_with("/docProps/custom.xml") {
296 content_type = CUSTOM_PROPS_TYPE;
297 }
298
299 if content_type.is_empty() {
301 for (old_part_name, old_content_type) in spreadsheet.get_backup_context_types() {
302 if &**old_part_name == &file {
303 content_type = old_content_type;
304 }
305 }
306 }
307
308 if !content_type.is_empty() {
309 list.push((file, content_type.to_string()));
310 }
311 }
312 list
313 }
314}