diff --git a/xlsx/src/import/worksheets.rs b/xlsx/src/import/worksheets.rs index f3e0bd9..cb946f0 100644 --- a/xlsx/src/import/worksheets.rs +++ b/xlsx/src/import/worksheets.rs @@ -336,6 +336,7 @@ fn get_cell_from_excel( sheet_name: &str, cell_ref: &str, shared_strings: &mut Vec, + rich_text_inline: Option, ) -> Cell { // Possible cell types: // 18.18.11 ST_CellType (Cell Type) @@ -397,12 +398,15 @@ fn get_cell_from_excel( } } "inlineStr" => { - // Not implemented - println!("Invalid type (inlineStr) in {sheet_name}!{cell_ref}"); - Cell::ErrorCell { - ei: Error::NIMPL, - s: cell_style, - } + let s = rich_text_inline.unwrap_or_default(); + let si = if let Some(i) = shared_strings.iter().position(|r| r == &s) { + i + } else { + shared_strings.push(s.to_string()); + shared_strings.len() - 1 + } as i32; + + Cell::SharedString { si, s: cell_style } } "empty" => Cell::EmptyCell { s: cell_style }, _ => { @@ -480,16 +484,11 @@ fn get_cell_from_excel( } } "inlineStr" => { - // Not implemented - let o = format!("{sheet_name}!{cell_ref}"); - let m = Error::NIMPL.to_string(); - println!("Invalid type (inlineStr) in {sheet_name}!{cell_ref}"); - Cell::CellFormulaError { + // NB: This is untested, I don't know of any engine that uses inline strings in formulas + Cell::CellFormulaString { f: formula_index, - ei: Error::NIMPL, + v: rich_text_inline.unwrap_or("".to_string()), s: cell_style, - o, - m, } } _ => { @@ -796,7 +795,7 @@ pub(super) fn load_sheet( // 18.3.1.4 c (Cell) // Child Elements: // * v: Cell value - // * is: Rich Text Inline (not used in IronCalc) + // * is: Rich Text Inline // * f: Formula // Attributes: // r: reference. A1 style @@ -820,6 +819,26 @@ pub(super) fn load_sheet( None }; + // + // + // Hello, World! + // + // + let cell_rich_text_nodes: Vec = + cell.children().filter(|n| n.has_tag_name("is")).collect(); + let cell_rich_text = if cell_rich_text_nodes.is_empty() { + None + } else { + let texts: Vec = cell_rich_text_nodes[0] + .descendants() + .filter(|n| n.has_tag_name("t")) + .filter_map(|n| n.text()) + .map(|s| s.to_string()) + .collect(); + + Some(texts.join("")) + }; + let cell_metadata = cell.attribute("cm"); // type, the default type being "n" for number @@ -976,6 +995,7 @@ pub(super) fn load_sheet( sheet_name, cell_ref, shared_strings, + cell_rich_text, ); data_row.insert(column, cell); } diff --git a/xlsx/tests/openpyxl_example.xlsx b/xlsx/tests/openpyxl_example.xlsx new file mode 100644 index 0000000..aa1609e Binary files /dev/null and b/xlsx/tests/openpyxl_example.xlsx differ diff --git a/xlsx/tests/test.rs b/xlsx/tests/test.rs index f86ec91..da4bdaa 100644 --- a/xlsx/tests/test.rs +++ b/xlsx/tests/test.rs @@ -531,3 +531,33 @@ fn test_user_model() { // we can still use the model afterwards model.set_rows_height(0, 1, 1, 100.0).unwrap(); } + +// This is produced with: +// from openpyxl import Workbook + +// # Create new workbook +// wb = Workbook() +// ws = wb.active + +// # Write text and formula +// ws['A1'] = 'Hello, World!' +// ws['A2'] = '=1+1' + +// ws['B1'] = '=CONCAT("It is", " what it is")' + +// # Save +// wb.save('openpyxl_example.xlsx') +#[test] +fn test_pyopenxl_example() { + let mut model = load_from_xlsx("tests/openpyxl_example.xlsx", "en", "UTC").unwrap(); + model.evaluate(); + + let a1 = model.get_formatted_cell_value(0, 1, 1).unwrap(); + assert_eq!(a1, "Hello, World!"); + + let a2 = model.get_formatted_cell_value(0, 2, 1).unwrap(); + assert_eq!(a2, "2"); + + let b1 = model.get_formatted_cell_value(0, 1, 2).unwrap(); + assert_eq!(b1, "It is what it is"); +}