Skip to main content

xlsbye_xml/
shared_strings.rs

1use crate::writer::{Result, XmlWriter};
2use std::io::Write;
3use xlsbye_core::types::SharedStringTable;
4use xlsbye_core::xml_names::SPREADSHEET_NS;
5
6pub fn write_shared_strings(
7    writer: impl Write,
8    sst: &SharedStringTable,
9    count: u32,
10    unique_count: u32,
11) -> Result<()> {
12    let mut writer = XmlWriter::new(writer);
13    writer.write_xml_declaration()?;
14    writer.write_start_element_with_ns(
15        "sst",
16        [("", SPREADSHEET_NS)],
17        [
18            ("count", count.to_string()),
19            ("uniqueCount", unique_count.to_string()),
20        ],
21    )?;
22
23    for entry in sst {
24        writer.write_start_element("si", std::iter::empty::<(&str, &str)>())?;
25        match entry {
26            xlsbye_core::types::SharedStringEntry::Plain(text) => {
27                write_text_node(&mut writer, "t", text)?;
28            }
29            xlsbye_core::types::SharedStringEntry::Rich(runs) => {
30                for run in runs {
31                    writer.write_start_element("r", std::iter::empty::<(&str, &str)>())?;
32                    if let Some(font_index) = run.font_index {
33                        writer.write_start_element("rPr", std::iter::empty::<(&str, &str)>())?;
34                        writer.write_empty_element("rFont", [("val", format!("font{}", font_index))])?;
35                        writer.write_end_element("rPr")?;
36                    }
37                    write_text_node(&mut writer, "t", &run.text)?;
38                    writer.write_end_element("r")?;
39                }
40            }
41        }
42        writer.write_end_element("si")?;
43    }
44
45    writer.write_end_element("sst")?;
46    Ok(())
47}
48
49pub(crate) fn write_text_node<W: Write>(
50    writer: &mut XmlWriter<W>,
51    tag_name: &str,
52    text: &str,
53) -> Result<()> {
54    if needs_space_preserve(text) {
55        writer.write_text_element(tag_name, [("xml:space", "preserve")], text)
56    } else {
57        writer.write_text_element(tag_name, std::iter::empty::<(&str, &str)>(), text)
58    }
59}
60
61fn needs_space_preserve(text: &str) -> bool {
62    text.chars().next().is_some_and(char::is_whitespace)
63        || text.chars().last().is_some_and(char::is_whitespace)
64}