#[cfg(test)]
mod tests;
use crate::workbook::DocProperties;
use crate::{Result, XmlWritable, XmlWriter};
use indexmap::{indexmap, IndexMap, IndexSet};
pub(crate) struct App<'a> {
pub heading_pairs: IndexMap<String, String>,
pub part_names: IndexSet<String>,
pub properties: &'a DocProperties,
}
impl XmlWritable for App<'_> {
fn write_xml<W: XmlWriter>(&self, w: &mut W) -> Result<()> {
let attrs = indexmap! {
"xmlns" => "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties",
"xmlns:vt" => "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes",
};
let tag = "Properties";
w.start_tag_with_attrs(tag, attrs)?;
self.write_application(w)?;
self.write_doc_security(w)?;
self.write_scale_crop(w)?;
self.write_heading_pairs(w)?;
self.write_titles_of_parts(w)?;
self.write_manager(w)?;
self.write_company(w)?;
self.write_links_up_to_date(w)?;
self.write_shared_doc(w)?;
self.write_hyperlink_base(w)?;
self.write_hyperlinks_changed(w)?;
self.write_app_version(w)?;
w.end_tag(tag)?;
Ok(())
}
}
impl App<'_> {
fn write_application<W: XmlWriter>(&self, w: &mut W) -> Result<()> {
w.tag_with_text("Application", "Microsoft Excel")
}
fn write_doc_security<W: XmlWriter>(&self, w: &mut W) -> Result<()> {
w.tag_with_text("DocSecurity", "0")
}
fn write_scale_crop<W: XmlWriter>(&self, w: &mut W) -> Result<()> {
w.tag_with_text("ScaleCrop", "false")
}
fn write_heading_pairs<W: XmlWriter>(&self, w: &mut W) -> Result<()> {
let tag = "HeadingPairs";
w.start_tag(tag)?;
self.write_vt_vector_heading_pairs(w)?;
w.end_tag(tag)?;
Ok(())
}
fn write_vt_vector_heading_pairs<W: XmlWriter>(
&self,
w: &mut W,
) -> Result<()> {
let tag = "vt:vector";
let attrs = indexmap! {
"size" => format!("{}", self.heading_pairs.len() * 2),
"baseType" => "variant".to_string(),
};
w.start_tag_with_attrs(tag, attrs)?;
for (key, value) in self.heading_pairs.iter() {
self.write_vt_variant(w, key, value)?;
}
w.end_tag(tag)?;
Ok(())
}
fn write_vt_variant<W: XmlWriter>(
&self,
w: &mut W,
key: &str,
value: &str,
) -> Result<()> {
let tag = "vt:variant";
{
w.start_tag(tag)?;
self.write_vt_lpstr(w, key)?;
w.end_tag(tag)?;
}
{
w.start_tag(tag)?;
self.write_vt_i4(w, value)?;
w.end_tag(tag)?;
}
Ok(())
}
fn write_vt_lpstr<W: XmlWriter>(
&self,
w: &mut W,
string: &str,
) -> Result<()> {
w.tag_with_text("vt:lpstr", string)
}
fn write_vt_i4<W: XmlWriter>(
&self,
w: &mut W,
string: &str,
) -> Result<()> {
w.tag_with_text("vt:i4", string)
}
fn write_titles_of_parts<W: XmlWriter>(
&self,
w: &mut W,
) -> Result<()> {
let tag = "TitlesOfParts";
w.start_tag(tag)?;
self.write_vt_vector_lpstr_named_parts(w)?;
w.end_tag(tag)?;
Ok(())
}
fn write_vt_vector_lpstr_named_parts<W: XmlWriter>(
&self,
w: &mut W,
) -> Result<()> {
let attrs = indexmap! {
"size" => format!("{}", self.part_names.len()),
"baseType" => "lpstr".to_string(),
};
let tag = "vt:vector";
w.start_tag_with_attrs(tag, attrs)?;
for name in self.part_names.iter() {
self.write_vt_lpstr(w, name)?;
}
w.end_tag(tag)?;
Ok(())
}
fn write_manager<W: XmlWriter>(&self, w: &mut W) -> Result<()> {
if !self.properties.manager.is_empty() {
w.tag_with_text("manager", &self.properties.manager)?;
}
Ok(())
}
fn write_company<W: XmlWriter>(&self, w: &mut W) -> Result<()> {
w.tag_with_text("Company", &self.properties.company)
}
fn write_links_up_to_date<W: XmlWriter>(
&self,
w: &mut W,
) -> Result<()> {
w.tag_with_text("LinksUpToDate", "false")
}
fn write_shared_doc<W: XmlWriter>(&self, w: &mut W) -> Result<()> {
w.tag_with_text("SharedDoc", "false")
}
fn write_hyperlink_base<W: XmlWriter>(&self, w: &mut W) -> Result<()> {
if !self.properties.hyperlink_base.is_empty() {
w.tag_with_text(
"HyperlinkBase",
&self.properties.hyperlink_base,
)?;
}
Ok(())
}
fn write_hyperlinks_changed<W: XmlWriter>(
&self,
w: &mut W,
) -> Result<()> {
w.tag_with_text("HyperlinksChanged", "false")
}
fn write_app_version<W: XmlWriter>(&self, w: &mut W) -> Result<()> {
w.tag_with_text("AppVersion", "12.0000")
}
}