diff --git a/.~lock.test_masque.xlsx# b/.~lock.test_masque.xlsx# new file mode 100644 index 0000000..fa82ba9 --- /dev/null +++ b/.~lock.test_masque.xlsx# @@ -0,0 +1 @@ +,sanchezn,pc-sanchezn,04.10.2025 13:10,file:///home/sanchezn/.config/libreoffice/4; \ No newline at end of file diff --git a/src/arguments.rs b/src/arguments.rs index 38417f6..776100d 100644 --- a/src/arguments.rs +++ b/src/arguments.rs @@ -2,19 +2,16 @@ use clap::Parser; #[derive(Parser, Debug)] pub struct Arguments { - /// path to the xlsx file + /// Path to the xlsx file #[arg()] pub file: String, - /// path to the output csv file + /// Separator + #[arg(short, long, default_value_t = ';')] + pub separator: char, + /// Replacement char to replace separator in cells text #[arg(short, long)] - pub output: Option, - /// worksheets to convert to xlsx (numbers, or names, or nothing to convert all worksheets) - #[arg(short, long)] - pub worksheets: Vec, - /// separator char. If many defined, use the first that is not used in cells. - #[arg(short, long, value_delimiter = ',', default_values_t = [';'])] - pub separator: Vec, - /// char to replace separator char in cells. If no replacement, error will be fired - #[arg(short, long)] - pub replacement: Option, -} \ No newline at end of file + pub replacement: Option, + /// Default hidden lines are not included to output + #[arg(short, long, default_value_t=false)] + pub include_hidden_lines: bool, +} diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..690ed11 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,18 @@ +use std::fmt; + +#[derive(Debug, Clone)] +pub struct Error { + pub msg: String +} + +impl Error { + pub fn new(msg: &str) -> Self { + Error { msg: String::from(msg)} + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Error: {}", self.msg) + } +} \ No newline at end of file diff --git a/src/extractor.rs b/src/extractor.rs deleted file mode 100644 index 5bfac11..0000000 --- a/src/extractor.rs +++ /dev/null @@ -1,83 +0,0 @@ -use umya_spreadsheet::{Spreadsheet, Worksheet}; - -#[derive(Debug)] -pub struct Extractor<'a> { - book: Spreadsheet, - sheet: Option<&'a Worksheet>, - pub separator: char, - pub replacement: Option, - pub merge_fill: MergeFill, - pub exclude_hidden: bool, -} - -impl<'a> Extractor<'a> { - pub fn new(book: Spreadsheet) -> Self { - Extractor { - book, - sheet: None, - separator: ';', - replacement: None, - merge_fill: MergeFill::None, - exclude_hidden: true, - } - } - - pub fn new_with_options( - book: Spreadsheet, - separator: char, - replacement: Option, - ) -> Self { - Extractor { - book, - sheet: None, - separator, - replacement, - merge_fill: MergeFill::None, - exclude_hidden: true, - } - } - - fn _is_row_hidden(&self, row_index: u32) -> Option { - if let Some(row) = self.sheet.unwrap().get_row_dimension(&row_index) { - if *row.get_hidden() { - return Some(false); - } else { - return Some(true); - } - } - None - } - - fn _is_column_hidden(&self, column_index: u32) -> Option { - if let Some(column) = self.sheet.unwrap().get_column_dimension_by_number(&column_index) { - if *column.get_hidden() { - return Some(false); - } else { - return Some(true); - } - } - None - } - - fn _is_cell_in_merge(&self, row_index: u32, column_index: u32) -> bool { - let merges = self.sheet.unwrap().get_merge_cells(); - for merge in merges { - if row_index >= *merge.get_coordinate_start_row().unwrap().get_num() - && row_index <= *merge.get_coordinate_end_row().unwrap().get_num() - && column_index >= *merge.get_coordinate_start_col().unwrap().get_num() - && column_index <= *merge.get_coordinate_end_col().unwrap().get_num() - { - return true; - } - } - false - } -} - -#[derive(Debug)] -pub enum MergeFill { - None, - Horizontal, - Vertical, - Both, -} diff --git a/src/main.rs b/src/main.rs index 79411ed..34f74e9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,67 @@ -use std::path::Path; use clap::Parser; +use std::path::Path; use umya_spreadsheet::reader; -pub mod extractor; -use extractor::Extractor; - pub mod arguments; use arguments::Arguments; -fn main() { - let _args = Arguments::parse(); +pub mod error; +use crate::error::Error; - let book = reader::xlsx::read(Path::new("anafi.xlsx")).unwrap(); - let _extractor = Extractor::new(book); -} +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()); + + let sheet = match book.get_sheet(&0) { + Some(sheet) => sheet, + None => return Err(Error::new("cannot open 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 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!(""); + } + + Ok(()) +} diff --git a/test_masque.csv b/test_masque.csv new file mode 100644 index 0000000..bcd028a --- /dev/null +++ b/test_masque.csv @@ -0,0 +1,4 @@ +A1;12;10 +A2;33; +A4,A4;45; +A5;90; diff --git a/test_masque.xlsx b/test_masque.xlsx new file mode 100644 index 0000000..5f6bfa7 Binary files /dev/null and b/test_masque.xlsx differ