1use super::driver;
2use crate::helper::crypt::*;
3use crate::structs::Spreadsheet;
4use crate::structs::WriterManager;
5use crate::XlsxError;
6use std::fmt;
7use std::fs;
8use std::fs::File;
9use std::io;
10use std::io::Read;
11use std::io::Write;
12use std::path::Path;
13use std::string::FromUtf8Error;
14
15mod chart;
16mod comment;
17mod content_types;
18mod doc_props_app;
19mod doc_props_core;
20mod doc_props_custom;
21mod drawing;
22mod drawing_rels;
23mod embeddings;
24mod jsa_project_bin;
25mod media;
26mod person;
27mod printer_settings;
28mod rels;
29mod shared_strings;
30mod styles;
31mod table;
32mod theme;
33mod threaded_comment;
34mod vba_project_bin;
35mod vml_drawing;
36mod vml_drawing_rels;
37mod workbook;
38mod workbook_rels;
39mod worksheet;
40mod worksheet_rels;
41
42fn make_buffer(spreadsheet: &Spreadsheet, is_light: bool) -> Result<std::vec::Vec<u8>, XlsxError> {
43 let mut arv = zip::ZipWriter::new(std::io::Cursor::new(Vec::new()));
44 let mut writer_manager = WriterManager::new(&mut arv);
45 writer_manager.set_is_light(is_light);
46
47 doc_props_app::write(spreadsheet, &mut writer_manager)?;
49
50 doc_props_core::write(spreadsheet, &mut writer_manager)?;
52
53 doc_props_custom::write(spreadsheet, &mut writer_manager)?;
55
56 vba_project_bin::write(spreadsheet, &mut writer_manager)?;
58
59 jsa_project_bin::write(spreadsheet, &mut writer_manager)?;
61
62 rels::write(spreadsheet, &mut writer_manager)?;
64
65 theme::write(spreadsheet.get_theme(), &mut writer_manager)?;
67
68 person::write(spreadsheet, &mut writer_manager)?;
70
71 let shared_string_table = spreadsheet.get_shared_string_table();
73 let mut stylesheet = spreadsheet.get_stylesheet().clone();
74 let mut worksheet_no = 1;
75 for worksheet in spreadsheet.get_sheet_collection_no_check() {
76 if worksheet.is_deserialized() {
77 worksheet::write(
79 &worksheet_no,
80 worksheet,
81 &shared_string_table,
82 &mut stylesheet,
83 spreadsheet.get_has_macros(),
84 &mut writer_manager,
85 )?;
86 } else {
87 worksheet
89 .get_raw_data_of_worksheet()
90 .write(&worksheet_no, &mut writer_manager)?;
91 }
92 worksheet_no += 1;
93 }
94
95 let mut worksheet_no = 0;
97 for worksheet in spreadsheet.get_sheet_collection_no_check() {
98 worksheet_no += 1;
99 if !worksheet.is_deserialized() {
100 continue;
101 }
102
103 let mut chart_no_list: Vec<String> = Vec::new();
106 for chart in worksheet.get_worksheet_drawing().get_chart_collection() {
107 let chart_space = chart.get_chart_space();
108 let chart_no = chart::write(chart_space, spreadsheet, &mut writer_manager)?;
109 chart_no_list.push(chart_no);
110 }
111
112 let (drawing_no, rel_list) = drawing::write(worksheet, &mut writer_manager)?;
114
115 drawing_rels::write(
117 worksheet,
118 &drawing_no,
119 &chart_no_list,
120 &rel_list,
121 &mut writer_manager,
122 )?;
123
124 let (vml_drawing_no, rel_list) = vml_drawing::write(worksheet, &mut writer_manager)?;
126
127 vml_drawing_rels::write(worksheet, &vml_drawing_no, &rel_list, &mut writer_manager)?;
129
130 let comment_no = comment::write(worksheet, &mut writer_manager)?;
132
133 let threaded_comment_no = threaded_comment::write(worksheet, &mut writer_manager)?;
135
136 let (ole_object_no_list, excel_no_list) =
138 embeddings::write(worksheet, &mut writer_manager)?;
139
140 media::write(worksheet, &mut writer_manager)?;
142
143 let printer_settings_no = match worksheet.get_page_setup().get_object_data() {
145 Some(_) => printer_settings::write(worksheet, &mut writer_manager)?,
146 None => String::new(),
147 };
148
149 let table_no_list = table::write(worksheet, &mut writer_manager)?;
151
152 worksheet_rels::write(
154 worksheet,
155 &worksheet_no.to_string(),
156 &drawing_no,
157 &vml_drawing_no,
158 &comment_no,
159 &threaded_comment_no,
160 &ole_object_no_list,
161 &excel_no_list,
162 &printer_settings_no,
163 &table_no_list,
164 &mut writer_manager,
165 )?;
166 }
167
168 writer_manager.file_list_sort();
170
171 shared_strings::write(&shared_string_table, &mut writer_manager)?;
173
174 styles::write(&stylesheet, &mut writer_manager)?;
176
177 workbook::write(spreadsheet, &mut writer_manager)?;
179
180 let has_shared_string_table = shared_string_table.read().unwrap().has_value();
182 workbook_rels::write(spreadsheet, has_shared_string_table, &mut writer_manager)?;
183
184 content_types::write(spreadsheet, &mut writer_manager)?;
186
187 Ok(arv.finish()?.into_inner())
188}
189
190#[inline]
197pub fn write_writer<W: io::Write>(
198 spreadsheet: &Spreadsheet,
199 mut writer: W,
200) -> Result<(), XlsxError> {
201 let buffer = make_buffer(spreadsheet, false)?;
202 writer.write_all(&buffer)?;
203 Ok(())
204}
205
206#[inline]
213pub fn write_writer_light<W: io::Write>(
214 spreadsheet: &Spreadsheet,
215 mut writer: W,
216) -> Result<(), XlsxError> {
217 let buffer = make_buffer(spreadsheet, true)?;
218 writer.write_all(&buffer)?;
219 Ok(())
220}
221
222pub fn write<P: AsRef<Path>>(spreadsheet: &Spreadsheet, path: P) -> Result<(), XlsxError> {
235 let extension = path.as_ref().extension().unwrap().to_str().unwrap();
236 let path_tmp = path
237 .as_ref()
238 .with_extension(format!("{}{}", extension, "tmp"));
239 if let Err(v) = write_writer(
240 spreadsheet,
241 &mut io::BufWriter::new(fs::File::create(&path_tmp)?),
242 ) {
243 fs::remove_file(path_tmp)?;
244 return Err(v);
245 }
246 fs::rename(path_tmp, path)?;
247 Ok(())
248}
249
250pub fn write_light<P: AsRef<Path>>(spreadsheet: &Spreadsheet, path: P) -> Result<(), XlsxError> {
263 let extension = path.as_ref().extension().unwrap().to_str().unwrap();
264 let path_tmp = path
265 .as_ref()
266 .with_extension(format!("{}{}", extension, "tmp"));
267 if let Err(v) = write_writer_light(
268 spreadsheet,
269 &mut io::BufWriter::new(fs::File::create(&path_tmp)?),
270 ) {
271 fs::remove_file(path_tmp)?;
272 return Err(v);
273 }
274 fs::rename(path_tmp, path)?;
275 Ok(())
276}
277
278pub fn write_with_password<P: AsRef<Path>>(
292 spreadsheet: &Spreadsheet,
293 path: P,
294 password: &str,
295) -> Result<(), XlsxError> {
296 let extension = path.as_ref().extension().unwrap().to_str().unwrap();
297 let path_tmp = path
298 .as_ref()
299 .with_extension(format!("{}{}", extension, "tmp"));
300 let buffer = match make_buffer(spreadsheet, false) {
301 Ok(v) => v,
302 Err(v) => {
303 fs::remove_file(path_tmp)?;
304 return Err(v);
305 }
306 };
307
308 encrypt(&path_tmp, &buffer, password);
310
311 fs::rename(path_tmp, path)?;
312 Ok(())
313}
314
315pub fn write_with_password_light<P: AsRef<Path>>(
329 spreadsheet: &Spreadsheet,
330 path: P,
331 password: &str,
332) -> Result<(), XlsxError> {
333 let extension = path.as_ref().extension().unwrap().to_str().unwrap();
334 let path_tmp = path
335 .as_ref()
336 .with_extension(format!("{}{}", extension, "tmp"));
337 let buffer = match make_buffer(spreadsheet, true) {
338 Ok(v) => v,
339 Err(v) => {
340 fs::remove_file(path_tmp)?;
341 return Err(v);
342 }
343 };
344
345 encrypt(&path_tmp, &buffer, password);
347
348 fs::rename(path_tmp, path)?;
349 Ok(())
350}
351
352pub fn set_password<P: AsRef<Path>>(
366 from_path: P,
367 to_path: P,
368 password: &str,
369) -> Result<(), XlsxError> {
370 let mut file = File::open(from_path).unwrap();
371 let mut buffer = Vec::new();
372 file.read_to_end(&mut buffer).unwrap();
373
374 encrypt(&to_path, &buffer, password);
376
377 Ok(())
378}