use std::io::Cursor;
use crate::xmlwriter::{
xml_declaration, xml_empty_tag, xml_end_tag, xml_start_tag, xml_start_tag_only,
};
pub struct Metadata {
pub(crate) writer: Cursor<Vec<u8>>,
pub(crate) has_dynamic_functions: bool,
pub(crate) has_embedded_images: bool,
pub(crate) num_embedded_images: u32,
}
impl Metadata {
pub fn new() -> Metadata {
let writer = Cursor::new(Vec::with_capacity(2048));
Metadata {
writer,
has_dynamic_functions: false,
has_embedded_images: false,
num_embedded_images: 0,
}
}
pub fn assemble_xml_file(&mut self) {
xml_declaration(&mut self.writer);
self.write_metadata();
self.write_metadata_types();
if self.has_dynamic_functions {
self.write_cell_future_metadata();
}
if self.has_embedded_images {
self.write_value_future_metadata();
}
if self.has_dynamic_functions {
self.write_cell_metadata();
}
if self.has_embedded_images {
self.write_value_metadata();
}
xml_end_tag(&mut self.writer, "metadata");
}
fn write_metadata(&mut self) {
let mut attributes = vec![(
"xmlns",
"http://schemas.openxmlformats.org/spreadsheetml/2006/main",
)];
if self.has_embedded_images {
attributes.push((
"xmlns:xlrd",
"http://schemas.microsoft.com/office/spreadsheetml/2017/richdata",
));
}
if self.has_dynamic_functions {
attributes.push((
"xmlns:xda",
"http://schemas.microsoft.com/office/spreadsheetml/2017/dynamicarray",
));
}
xml_start_tag(&mut self.writer, "metadata", &attributes);
}
fn write_metadata_types(&mut self) {
let mut count = 0;
if self.has_dynamic_functions {
count += 1;
}
if self.has_embedded_images {
count += 1;
}
let attributes = [("count", count.to_string())];
xml_start_tag(&mut self.writer, "metadataTypes", &attributes);
if self.has_dynamic_functions {
self.write_cell_metadata_type();
}
if self.has_embedded_images {
self.write_value_metadata_type();
}
xml_end_tag(&mut self.writer, "metadataTypes");
}
fn write_cell_metadata_type(&mut self) {
let attributes = [
("name", "XLDAPR"),
("minSupportedVersion", "120000"),
("copy", "1"),
("pasteAll", "1"),
("pasteValues", "1"),
("merge", "1"),
("splitFirst", "1"),
("rowColShift", "1"),
("clearFormats", "1"),
("clearComments", "1"),
("assign", "1"),
("coerce", "1"),
("cellMeta", "1"),
];
xml_empty_tag(&mut self.writer, "metadataType", &attributes);
}
fn write_value_metadata_type(&mut self) {
let attributes = [
("name", "XLRICHVALUE"),
("minSupportedVersion", "120000"),
("copy", "1"),
("pasteAll", "1"),
("pasteValues", "1"),
("merge", "1"),
("splitFirst", "1"),
("rowColShift", "1"),
("clearFormats", "1"),
("clearComments", "1"),
("assign", "1"),
("coerce", "1"),
];
xml_empty_tag(&mut self.writer, "metadataType", &attributes);
}
fn write_cell_future_metadata(&mut self) {
let attributes = [("name", "XLDAPR"), ("count", "1")];
xml_start_tag(&mut self.writer, "futureMetadata", &attributes);
xml_start_tag_only(&mut self.writer, "bk");
xml_start_tag_only(&mut self.writer, "extLst");
self.write_cell_ext();
xml_end_tag(&mut self.writer, "extLst");
xml_end_tag(&mut self.writer, "bk");
xml_end_tag(&mut self.writer, "futureMetadata");
}
fn write_value_future_metadata(&mut self) {
let attributes = [
("name", "XLRICHVALUE".to_string()),
("count", self.num_embedded_images.to_string()),
];
xml_start_tag(&mut self.writer, "futureMetadata", &attributes);
for index in 0..self.num_embedded_images {
xml_start_tag_only(&mut self.writer, "bk");
xml_start_tag_only(&mut self.writer, "extLst");
self.write_value_ext(index);
xml_end_tag(&mut self.writer, "extLst");
xml_end_tag(&mut self.writer, "bk");
}
xml_end_tag(&mut self.writer, "futureMetadata");
}
fn write_cell_ext(&mut self) {
let attributes = [("uri", "{bdbb8cdc-fa1e-496e-a857-3c3f30c029c3}")];
xml_start_tag(&mut self.writer, "ext", &attributes);
self.write_xda_dynamic_array_properties();
xml_end_tag(&mut self.writer, "ext");
}
fn write_value_ext(&mut self, index: u32) {
let attributes = [("uri", "{3e2802c4-a4d2-4d8b-9148-e3be6c30e623}")];
xml_start_tag(&mut self.writer, "ext", &attributes);
self.write_xlrd_rvb(index);
xml_end_tag(&mut self.writer, "ext");
}
fn write_xlrd_rvb(&mut self, index: u32) {
let attributes = [("i", index.to_string())];
xml_empty_tag(&mut self.writer, "xlrd:rvb", &attributes);
}
fn write_xda_dynamic_array_properties(&mut self) {
let attributes = [("fDynamic", "1"), ("fCollapsed", "0")];
xml_empty_tag(&mut self.writer, "xda:dynamicArrayProperties", &attributes);
}
fn write_cell_metadata(&mut self) {
let attributes = [("count", "1")];
xml_start_tag(&mut self.writer, "cellMetadata", &attributes);
xml_start_tag_only(&mut self.writer, "bk");
self.write_rc(1, 0);
xml_end_tag(&mut self.writer, "bk");
xml_end_tag(&mut self.writer, "cellMetadata");
}
fn write_value_metadata(&mut self) {
let attributes = [("count", self.num_embedded_images.to_string())];
let rc_type = if self.has_dynamic_functions { 2 } else { 1 };
xml_start_tag(&mut self.writer, "valueMetadata", &attributes);
for index in 0..self.num_embedded_images {
xml_start_tag_only(&mut self.writer, "bk");
self.write_rc(rc_type, index);
xml_end_tag(&mut self.writer, "bk");
}
xml_end_tag(&mut self.writer, "valueMetadata");
}
fn write_rc(&mut self, rc_type: u32, value: u32) {
let attributes = [("t", rc_type.to_string()), ("v", value.to_string())];
xml_empty_tag(&mut self.writer, "rc", &attributes);
}
}