You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
4.2 KiB

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 (horiz, vert) = match args.fill_merged_cells {
crate::arguments::FillMergedCells::None => (false, false),
crate::arguments::FillMergedCells::Horizontal => (true, false),
crate::arguments::FillMergedCells::Vertical => (false, true),
crate::arguments::FillMergedCells::Both => (true, true),
};
let merged_cells = MergedCells::new(sheet, horiz, vert);
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<Range>,
fill_horizontal: bool,
fill_vertical: bool,
}
impl MergedCells {
pub fn new(sheet: &Worksheet, fill_horizontal: bool, fill_vertical: bool) -> Self {
let merged = sheet.get_merge_cells();
let mut merged_cells: Vec<Range> = vec![];
for cell in merged {
merged_cells.push(cell.clone());
}
MergedCells {
merged_cells,
fill_horizontal,
fill_vertical,
}
}
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()
{
let col_start = range.get_coordinate_start_col().unwrap().get_num().clone();
let row_start = range.get_coordinate_start_row().unwrap().get_num().clone();
if self.fill_horizontal && self.fill_vertical
|| self.fill_horizontal && row == row_start
|| self.fill_vertical && col == col_start
|| col == col_start && row == row_start
{
return Some((col_start, row_start));
}
}
}
None
}
}