use std::io::{Read, Seek, Write};
use std::path::Path;
use crate::Result;
use crate::format::DocumentFormat;
pub struct EditableDocument {
inner: EditableInner,
}
enum EditableInner {
Docx(crate::docx::edit::EditableDocx),
Xlsx(crate::xlsx::edit::EditableXlsx),
Pptx(crate::pptx::edit::EditablePptx),
}
impl EditableDocument {
pub fn open(path: impl AsRef<Path>) -> Result<Self> {
let path = path.as_ref();
let format = DocumentFormat::from_path(path).ok_or_else(|| {
crate::OfficeError::UnsupportedFormat(
path.extension()
.and_then(|e| e.to_str())
.unwrap_or("(none)")
.to_string(),
)
})?;
match format {
DocumentFormat::Docx => {
let doc = crate::docx::edit::EditableDocx::open(path)?;
Ok(Self {
inner: EditableInner::Docx(doc),
})
},
DocumentFormat::Xlsx => {
let doc = crate::xlsx::edit::EditableXlsx::open(path)?;
Ok(Self {
inner: EditableInner::Xlsx(doc),
})
},
DocumentFormat::Pptx => {
let doc = crate::pptx::edit::EditablePptx::open(path)?;
Ok(Self {
inner: EditableInner::Pptx(doc),
})
},
_ => Err(crate::OfficeError::UnsupportedFormat(format!("{format:?}"))),
}
}
pub fn from_reader<R: Read + Seek>(reader: R, format: DocumentFormat) -> Result<Self> {
match format {
DocumentFormat::Docx => {
let doc = crate::docx::edit::EditableDocx::from_reader(reader)?;
Ok(Self {
inner: EditableInner::Docx(doc),
})
},
DocumentFormat::Xlsx => {
let doc = crate::xlsx::edit::EditableXlsx::from_reader(reader)?;
Ok(Self {
inner: EditableInner::Xlsx(doc),
})
},
DocumentFormat::Pptx => {
let doc = crate::pptx::edit::EditablePptx::from_reader(reader)?;
Ok(Self {
inner: EditableInner::Pptx(doc),
})
},
_ => Err(crate::OfficeError::UnsupportedFormat(format!("{format:?}"))),
}
}
pub fn replace_text(&mut self, find: &str, replace: &str) -> usize {
match &mut self.inner {
EditableInner::Docx(doc) => doc.replace_text(find, replace),
EditableInner::Pptx(doc) => doc.replace_text(find, replace),
EditableInner::Xlsx(_) => 0,
}
}
pub fn set_cell(
&mut self,
sheet_index: usize,
cell_ref: &str,
value: crate::xlsx::edit::CellValue,
) -> Result<()> {
match &mut self.inner {
EditableInner::Xlsx(doc) => {
doc.set_cell(sheet_index, cell_ref, value)?;
Ok(())
},
_ => Err(crate::OfficeError::UnsupportedFormat(
"set_cell is only supported for XLSX".to_string(),
)),
}
}
pub fn save(&self, path: impl AsRef<Path>) -> Result<()> {
match &self.inner {
EditableInner::Docx(doc) => doc.save(path)?,
EditableInner::Xlsx(doc) => doc.save(path)?,
EditableInner::Pptx(doc) => doc.save(path)?,
}
Ok(())
}
pub fn write_to<W: Write + Seek>(&self, writer: W) -> Result<()> {
match &self.inner {
EditableInner::Docx(doc) => doc.write_to(writer)?,
EditableInner::Xlsx(doc) => doc.write_to(writer)?,
EditableInner::Pptx(doc) => doc.write_to(writer)?,
}
Ok(())
}
}