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
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
|
|
}
|
|
}
|