diff --git a/.~lock.test_masque.xlsx# b/.~lock.test_masque.xlsx# index fa82ba9..76cea7e 100644 --- a/.~lock.test_masque.xlsx# +++ b/.~lock.test_masque.xlsx# @@ -1 +1 @@ -,sanchezn,pc-sanchezn,04.10.2025 13:10,file:///home/sanchezn/.config/libreoffice/4; \ No newline at end of file +,sanchezn,pc-sanchezn,04.10.2025 18:38,file:///home/sanchezn/.config/libreoffice/4; \ No newline at end of file diff --git a/src/arguments.rs b/src/arguments.rs index 776100d..8ae9188 100644 --- a/src/arguments.rs +++ b/src/arguments.rs @@ -11,7 +11,7 @@ pub struct Arguments { /// Replacement char to replace separator in cells text #[arg(short, long)] pub replacement: Option, - /// Default hidden lines are not included to output + /// include hidden lines to output #[arg(short, long, default_value_t=false)] pub include_hidden_lines: bool, } diff --git a/src/main.rs b/src/main.rs index 34f74e9..c3f3559 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,67 +1,16 @@ -use clap::Parser; -use std::path::Path; -use umya_spreadsheet::reader; - -pub mod arguments; -use arguments::Arguments; - pub mod error; -use crate::error::Error; - -fn main() -> Result<(), Error> { - let args = Arguments::parse(); - let book = reader::xlsx::read(Path::new(&args.file)) - .expect(format!("Can't open {}", args.file).as_str()); +pub mod arguments; +pub mod xlsxtocsv; - let sheet = match book.get_sheet(&0) { - Some(sheet) => sheet, - None => return Err(Error::new("cannot open sheet")), - }; +use clap::Parser; +use arguments::Arguments; +use xlsxtocsv::xlsxtocsv; - let (num_cols, num_rows) = sheet.get_highest_column_and_row(); - for i in 1..=num_rows { - if ! args.include_hidden_lines { - match sheet.get_row_dimension(&i) { - Some(dim) => { - if *dim.get_hidden() { - continue; - } - } - None => continue, - } - } - let row = sheet.get_collection_by_row(&i); - let row_len = row.len(); - let mut first = true; - for cell in row { - if first { - first = false; - } else { - print!("{}", args.separator); - } - let mut value = cell.get_formatted_value(); - if let Some(ref replacement) = args.replacement { - value = value.replace(args.separator, replacement); - } else { - if value.contains(args.separator) { - return Err(Error::new( - format!( - "Cell {} contains separator char", - cell.get_coordinate().get_coordinate() - ) - .as_str(), - )); - } - } - print!("{}", value); - } - for _ in row_len..num_cols as usize { - print!("{}", args.separator); - } - println!(""); +fn main() { + let args = Arguments::parse(); + if let Err(error) = xlsxtocsv(&args) { + eprintln!("{}", error); } - - Ok(()) -} +} \ No newline at end of file diff --git a/src/xlsxtocsv.rs b/src/xlsxtocsv.rs new file mode 100644 index 0000000..88fb8f6 --- /dev/null +++ b/src/xlsxtocsv.rs @@ -0,0 +1,104 @@ +use std::path::Path; +use umya_spreadsheet::{Range, Worksheet, reader}; + +use crate::arguments::Arguments; +use crate::error::Error; + +pub fn xlsxtocsv(args: &Arguments) -> Result<(), Error> { + let book = reader::xlsx::read(Path::new(&args.file)) + .expect(format!("Can't open {}", args.file).as_str()); + + let sheet = match book.get_sheet(&0) { + Some(sheet) => sheet, + None => return Err(Error::new("cannot open sheet")), + }; + + let merged_cells = MergedCells::new(sheet); + + let (num_cols, num_rows) = sheet.get_highest_column_and_row(); + + for i in 1..=num_rows { + if !args.include_hidden_lines { + match sheet.get_row_dimension(&i) { + Some(dim) => { + if *dim.get_hidden() { + continue; + } + } + None => continue, + } + } + let row = sheet.get_collection_by_row(&i); + let row_len = row.len(); + let mut first = true; + for cell in row { + if first { + first = false; + } else { + print!("{}", args.separator); + } + + let cell_coordinate = cell.get_coordinate(); + let mut value; + if let Some((col, row)) = merged_cells.in_merged_cell(*cell_coordinate.get_col_num(), *cell_coordinate.get_row_num()) { + value = match sheet.get_cell((col,row)) { + Some(merged_cell) => merged_cell.get_formatted_value(), + None => String::from(""), + } + } else { + value = cell.get_formatted_value(); + } + + if let Some(ref replacement) = args.replacement { + value = value.replace(args.separator, replacement); + } else { + if value.contains(args.separator) { + return Err(Error::new( + format!( + "Cell {} contains separator char, use -r to choose a replacement char", + cell.get_coordinate().get_coordinate() + ) + .as_str(), + )); + } + } + print!("{}", value); + } + for _ in row_len..num_cols as usize { + print!("{}", args.separator); + } + println!(""); + } + + Ok(()) +} + +struct MergedCells { + merged_cells: Vec, +} + +impl MergedCells { + + pub fn new(sheet: &Worksheet) -> Self { + let merged = sheet.get_merge_cells(); + let mut merged_cells: Vec = vec![]; + + for cell in merged { + merged_cells.push(cell.clone()); + } + + MergedCells { merged_cells } + } + + pub fn in_merged_cell(&self, col: u32, row: u32) -> Option<(u32, u32)> { + for range in &self.merged_cells { + if col >= *range.get_coordinate_start_col().unwrap().get_num() && col <= *range.get_coordinate_end_col().unwrap().get_num() && + row >= *range.get_coordinate_start_row().unwrap().get_num() && row <= *range.get_coordinate_end_row().unwrap().get_num() { + return Some((range.get_coordinate_start_col().unwrap().get_num().clone(), (range.get_coordinate_start_row().unwrap().get_num().clone()))); + } + + } + None + } + +} diff --git a/test_masque.csv b/test_masque.csv index bcd028a..71f7a5d 100644 --- a/test_masque.csv +++ b/test_masque.csv @@ -1,4 +1,2 @@ A1;12;10 A2;33; -A4,A4;45; -A5;90; diff --git a/test_masque.xlsx b/test_masque.xlsx index 5f6bfa7..cd7043e 100644 Binary files a/test_masque.xlsx and b/test_masque.xlsx differ