umya_spreadsheet/reader/
xlsx.rs

1use std::fmt;
2use std::fs::File;
3use std::io;
4use std::path::Path;
5use std::string::FromUtf8Error;
6use std::sync::Arc;
7use std::sync::RwLock;
8
9use super::driver;
10use crate::helper::const_str::*;
11use crate::structs::drawing::Theme;
12use crate::structs::raw::RawWorksheet;
13use crate::structs::SharedStringTable;
14use crate::structs::Spreadsheet;
15use crate::structs::Stylesheet;
16use crate::structs::Worksheet;
17use crate::XlsxError;
18
19pub(crate) mod chart;
20pub(crate) mod comment;
21mod content_types;
22mod doc_props_app;
23mod doc_props_core;
24mod doc_props_custom;
25pub(crate) mod drawing;
26mod jsa_project_bin;
27mod pivot_table;
28mod rels;
29mod shared_strings;
30mod styles;
31pub(crate) mod table;
32mod theme;
33pub(crate) mod threaded_comment;
34mod vba_project_bin;
35pub(crate) mod vml_drawing;
36mod workbook;
37mod workbook_rels;
38pub(crate) mod worksheet;
39
40/// read spreadsheet from arbitrary reader.
41/// # Arguments
42/// * `reader` - reader to read from.
43/// # Return value
44/// * `Result` - OK is Spreadsheet. Err is error message.
45pub fn read_reader<R: io::Read + io::Seek>(
46    reader: R,
47    with_sheet_read: bool,
48) -> Result<Spreadsheet, XlsxError> {
49    let mut arv = zip::read::ZipArchive::new(reader)?;
50
51    let mut book = workbook::read(&mut arv)?;
52    doc_props_app::read(&mut arv, &mut book)?;
53    doc_props_core::read(&mut arv, &mut book)?;
54    doc_props_custom::read(&mut arv, &mut book)?;
55    vba_project_bin::read(&mut arv, &mut book)?;
56    jsa_project_bin::read(&mut arv, &mut book)?;
57    content_types::read(&mut arv, &mut book)?;
58    let workbook_rel = workbook_rels::read(&mut arv, &mut book)?;
59
60    book.set_theme(Theme::get_default_value());
61    for (_, type_value, rel_target) in &workbook_rel {
62        if type_value == THEME_NS {
63            let theme = theme::read(&mut arv, rel_target)?;
64            book.set_theme(theme);
65        }
66    }
67
68    shared_strings::read(&mut arv, &mut book)?;
69    styles::read(&mut arv, &mut book)?;
70
71    for sheet in book.get_sheet_collection_mut() {
72        for (rel_id, _, rel_target) in &workbook_rel {
73            if sheet.get_r_id() != rel_id {
74                continue;
75            }
76            let mut raw_worksheet = RawWorksheet::default();
77            raw_worksheet.read(&mut arv, rel_target);
78            sheet.set_raw_data_of_worksheet(raw_worksheet);
79        }
80    }
81
82    if with_sheet_read {
83        book.read_sheet_collection();
84    }
85
86    Ok(book)
87}
88
89/// read spreadsheet file.
90/// # Arguments
91/// * `path` - file path to read.
92/// # Return value
93/// * `Result` - OK is Spreadsheet. Err is error message.
94/// # Examples
95/// ```
96/// let path = std::path::Path::new("./tests/test_files/aaa.xlsx");
97/// let mut book = umya_spreadsheet::reader::xlsx::read(path).unwrap();
98/// ```
99#[inline]
100pub fn read<P: AsRef<Path>>(path: P) -> Result<Spreadsheet, XlsxError> {
101    let file = File::open(path)?;
102    read_reader(file, true)
103}
104
105/// lazy read spreadsheet file.
106/// Delays the loading of the worksheet until it is needed.
107/// When loading a file with a large amount of data, response improvement can be expected.
108/// # Arguments
109/// * `path` - file path to read.
110/// # Return value
111/// * `Result` - OK is Spreadsheet. Err is error message.
112/// # Examples
113/// ```
114/// let path = std::path::Path::new("./tests/test_files/aaa.xlsx");
115/// let mut book = umya_spreadsheet::reader::xlsx::lazy_read(path).unwrap();
116/// ```
117#[inline]
118pub fn lazy_read(path: &Path) -> Result<Spreadsheet, XlsxError> {
119    let file = File::open(path)?;
120    read_reader(file, false)
121}
122
123pub(crate) fn raw_to_deserialize_by_worksheet(
124    worksheet: &mut Worksheet,
125    shared_string_table: &RwLock<SharedStringTable>,
126    stylesheet: &Stylesheet,
127) {
128    if worksheet.is_deserialized() {
129        return;
130    }
131
132    let raw_data_of_worksheet = worksheet.get_raw_data_of_worksheet().clone();
133    let shared_string_table = &*shared_string_table.read().unwrap();
134    worksheet::read(
135        worksheet,
136        &raw_data_of_worksheet,
137        shared_string_table,
138        stylesheet,
139    )
140    .unwrap();
141
142    if let Some(v) = raw_data_of_worksheet.get_worksheet_relationships() {
143        for relationship in v.get_relationship_list() {
144            match relationship.get_type() {
145                // drawing, chart
146                DRAWINGS_NS => {
147                    drawing::read(
148                        worksheet,
149                        relationship.get_raw_file(),
150                        raw_data_of_worksheet.get_drawing_relationships(),
151                    )
152                    .unwrap();
153                }
154                // comment
155                COMMENTS_NS => {
156                    comment::read(worksheet, relationship.get_raw_file()).unwrap();
157                }
158                // threaded_comment
159                THREADED_COMMENT_NS => {
160                    threaded_comment::read(worksheet, relationship.get_raw_file()).unwrap();
161                }
162                // table
163                TABLE_NS => {
164                    table::read(worksheet, relationship.get_raw_file()).unwrap();
165                }
166                _ => {}
167            }
168        }
169        for relationship in v.get_relationship_list() {
170            // vmlDrawing
171            if relationship.get_type() == VML_DRAWING_NS {
172                vml_drawing::read(
173                    worksheet,
174                    relationship.get_raw_file(),
175                    raw_data_of_worksheet.get_vml_drawing_relationships(),
176                )
177                .unwrap();
178            }
179        }
180    }
181
182    worksheet.remove_raw_data_of_worksheet();
183}