rs-xsheet2txt 0.1.0

Converts the sheet to verbose txt lines.
Documentation
use std::io;
use std::path::Path;

use io::BufWriter;
use io::Write;

use calamine::CellType;
use calamine::Data;
use calamine::Range;
use calamine::Reader;
use calamine::Rows;
use calamine::Xlsx;

pub struct XlRange<T>(pub Range<T>);

impl<T> XlRange<T>
where
    T: CellType,
{
    pub fn cell_pos_end(&self) -> Option<(u32, u32)> {
        self.0.end()
    }

    pub fn cell_pos_start(&self) -> Option<(u32, u32)> {
        self.0.start()
    }
}

impl<T> XlRange<T>
where
    T: CellType,
{
    pub fn rows(&self) -> Rows<'_, T> {
        self.0.rows()
    }
}

impl XlRange<Data> {
    pub fn rows2writer<W>(&self, wtr: &mut W) -> Result<(), io::Error>
    where
        W: FnMut(usize, usize, &Data) -> Result<(), io::Error>,
    {
        let irow = self.rows();
        for (rno, row) in irow.enumerate() {
            for (cno, cell) in row.iter().enumerate() {
                wtr(rno, cno, cell)?;
            }
        }
        Ok(())
    }
}

impl XlRange<Data> {
    pub fn rows2io_writer<W>(&self, mut wtr: W) -> Result<(), io::Error>
    where
        W: Write,
    {
        self.rows2writer(&mut |rno: usize, cno: usize, dat: &Data| match dat {
            Data::Int(i) => write_int(&mut wtr, rno, cno, *i),
            Data::Float(f) => write_float(&mut wtr, rno, cno, *f),
            Data::String(s) => write_str(&mut wtr, rno, cno, s),
            Data::Bool(b) => write_bool(&mut wtr, rno, cno, *b),
            Data::DateTime(e) => write_datetime(&mut wtr, rno, cno, *e),
            Data::DateTimeIso(t) => write_datetime_iso(&mut wtr, rno, cno, t),
            Data::DurationIso(d) => write_duration_iso(&mut wtr, rno, cno, d),
            Data::Error(e) => write_error(&mut wtr, rno, cno, e),
            Data::Empty => write_empty(&mut wtr, rno, cno),
        })?;
        wtr.flush()
    }
}

pub fn write_int<W: Write>(w: &mut W, rno: usize, cno: usize, val: i64) -> io::Result<()> {
    writeln!(w, "row:{rno}\tcol:{cno}\ttyp:int\tval:{val}")
}

pub fn write_float<W: Write>(w: &mut W, rno: usize, cno: usize, val: f64) -> io::Result<()> {
    writeln!(w, "row:{rno}\tcol:{cno}\ttyp:float\tval:{val}")
}

pub fn write_str<W: Write>(w: &mut W, rno: usize, cno: usize, val: &str) -> io::Result<()> {
    writeln!(w, "row:{rno}\tcol:{cno}\ttyp:str\tval:{val}")
}

pub fn write_bool<W: Write>(w: &mut W, rno: usize, cno: usize, val: bool) -> io::Result<()> {
    writeln!(w, "row:{rno}\tcol:{cno}\ttyp:bool\tval:{val}")
}

pub fn write_datetime<W: Write>(
    w: &mut W,
    rno: usize,
    cno: usize,
    val: calamine::ExcelDateTime,
) -> io::Result<()> {
    if let Some(ndt) = val.as_datetime() {
        writeln!(w, "row:{rno}\tcol:{cno}\ttyp:date\tval:{ndt}")
    } else {
        writeln!(w, "row:{rno}\tcol:{cno}\ttyp:edate\tval:{val}")
    }
}

pub fn write_datetime_iso<W: Write>(
    w: &mut W,
    rno: usize,
    cno: usize,
    val: &str,
) -> io::Result<()> {
    writeln!(w, "row:{rno}\tcol:{cno}\ttyp:date_iso\tval:{val}")
}

pub fn write_duration_iso<W: Write>(
    w: &mut W,
    rno: usize,
    cno: usize,
    val: &str,
) -> io::Result<()> {
    writeln!(w, "row:{rno}\tcol:{cno}\ttyp:dur_iso\tval:{val}")
}

pub fn write_error<W: Write>(
    w: &mut W,
    rno: usize,
    cno: usize,
    val: &calamine::CellErrorType,
) -> io::Result<()> {
    writeln!(w, "row:{rno}\tcol:{cno}\ttyp:err\terr:{val}")
}

pub fn write_empty<W: Write>(w: &mut W, rno: usize, cno: usize) -> io::Result<()> {
    writeln!(w, "row:{rno}\tcol:{cno}\ttyp:empty\t")
}

pub fn xpath2sheet2rows2writer<P, W>(xpath: P, sheet: &str, wtr: W) -> Result<(), io::Error>
where
    W: Write,
    P: AsRef<Path>,
{
    let mut wkbk: Xlsx<_> = calamine::open_workbook(xpath).map_err(io::Error::other)?;
    let rng: Range<Data> = wkbk.worksheet_range(sheet).map_err(io::Error::other)?;
    XlRange(rng).rows2io_writer(wtr)?;
    Ok(())
}

pub fn xpath2sheet2rows2stdout<P>(xpath: P, sheet: &str) -> Result<(), io::Error>
where
    P: AsRef<Path>,
{
    let o = io::stdout();
    let mut ol = o.lock();
    xpath2sheet2rows2writer(xpath, sheet, BufWriter::new(&mut ol))?;
    ol.flush()
}