///|
fn write_workbook_xml(
workbook : Workbook,
chartsheet_rel_start : Int,
pivot_cache_rel_entries : ArrayView[(Int, String)],
slicer_cache_rel_ids_x14 : ArrayView[String],
slicer_cache_rel_ids_x15 : ArrayView[String],
budget? : WritePartBudget,
) -> String raise XlsxError {
fn write_pivot_caches_xml(
pivot_cache_rel_entries : ArrayView[(Int, String)],
budget : WritePartBudget?,
) -> String? raise XlsxError {
if pivot_cache_rel_entries.length() == 0 {
return None
}
let sb = LimitedXmlBuilder::new(budget)
sb.write_view(" \n")
for entry in pivot_cache_rel_entries {
let (cache_id, rel_id) = entry
sb.write_view(" \n")
}
sb.write_view(" \n")
Some(sb.to_string())
}
fn write_workbook_ext_lst_xml(
slicer_cache_rel_ids_x14 : ArrayView[String],
slicer_cache_rel_ids_x15 : ArrayView[String],
budget : WritePartBudget?,
) -> String? raise XlsxError {
if slicer_cache_rel_ids_x14.length() == 0 &&
slicer_cache_rel_ids_x15.length() == 0 {
return None
}
let sb = LimitedXmlBuilder::new(budget)
sb.write_view(" \n")
if slicer_cache_rel_ids_x14.length() > 0 {
sb.write_view(
" \n",
)
sb.write_view(
" \n",
)
for id in slicer_cache_rel_ids_x14 {
sb.write_view(" \n")
}
sb.write_view(" \n")
sb.write_view(" \n")
}
if slicer_cache_rel_ids_x15.length() > 0 {
sb.write_view(
" \n",
)
sb.write_view(
" \n",
)
for id in slicer_cache_rel_ids_x15 {
sb.write_view(" \n")
}
sb.write_view(" \n")
sb.write_view(" \n")
}
sb.write_view(" \n")
Some(sb.to_string())
}
let sheets = workbook.sheet_order
let worksheet_count = workbook.sheets().length()
let sb = LimitedXmlBuilder::new(budget)
let sheet_index : Map[String, Int] = Map([])
for i, entry in sheets {
sheet_index.set(normalize_sheet_name(workbook.sheet_entry_name(entry)), i)
}
sb.write_view("\n")
sb.write_view(
"\n",
)
match
write_workbook_pr_xml(
workbook.workbook_props(),
budget?=sb.remaining_budget(),
) {
Some(value) => sb.write_view(value)
None => ()
}
if sheets.length() > 0 {
let active_index = workbook.active_sheet_index()
let safe_active = if active_index < 0 || active_index >= sheets.length() {
0
} else {
active_index
}
sb.write_view(" \n")
sb.write_view(" \n")
sb.write_view(" \n")
}
sb.write_view(" \n")
for _i, entry in sheets {
let sheet_id = match entry {
Worksheet(idx) => idx + 1
ChartSheet(idx) => worksheet_count + idx + 1
}
let rel_id = match entry {
Worksheet(idx) => idx + 1
ChartSheet(idx) => chartsheet_rel_start + idx
}
sb.write_view(" ()
Hidden => sb.write_view(" state=\"hidden\"")
VeryHidden => sb.write_view(" state=\"veryHidden\"")
}
sb.write_view("/>\n")
}
sb.write_view(" \n")
if workbook.defined_names.length() > 0 {
let mut wrote = false
for defined in workbook.defined_names {
if defined.name == "" || defined.refers_to == "" {
continue
}
if !wrote {
sb.write_view(" \n")
wrote = true
}
sb.write_view(" sb.write_view(" localSheetId=\"\{local_id}\"")
None => ()
}
}
sb.write_view(">")
sb.write_xml_text(defined.refers_to)
sb.write_view("\n")
}
if wrote {
sb.write_view(" \n")
}
}
match workbook.workbook_protection {
Some(value) =>
sb.write_view(
write_workbook_protection_xml(value, budget?=sb.remaining_budget()),
)
None => ()
}
match
write_calc_pr_xml(workbook.calc_props(), budget?=sb.remaining_budget()) {
Some(value) => sb.write_view(value)
None => ()
}
match write_pivot_caches_xml(pivot_cache_rel_entries, sb.remaining_budget()) {
Some(value) => sb.write_view(value)
None => ()
}
match
write_workbook_ext_lst_xml(
slicer_cache_rel_ids_x14,
slicer_cache_rel_ids_x15,
sb.remaining_budget(),
) {
Some(xml) => sb.write_view(xml)
None => ()
}
sb.write_view("")
sb.to_string()
}
///|
fn write_workbook_pr_xml(
options : WorkbookPropsOptions,
budget? : WritePartBudget,
) -> String? raise XlsxError {
if workbook_props_is_empty(options) {
return None
}
let sb = LimitedXmlBuilder::new(budget)
sb.write_view(" sb.write_view(" date1904=\"\{bool_attr(value)}\"")
None => ()
}
match options.filter_privacy {
Some(value) => sb.write_view(" filterPrivacy=\"\{bool_attr(value)}\"")
None => ()
}
match options.code_name {
Some(value) => {
sb.write_view(" codeName=\"")
sb.write_xml_attr(value)
sb.write_view("\"")
}
None => ()
}
sb.write_view("/>\n")
Some(sb.to_string())
}
///|
fn write_calc_pr_xml(
options : CalcPropsOptions,
budget? : WritePartBudget,
) -> String? raise XlsxError {
if calc_props_is_empty(options) {
return None
}
let sb = LimitedXmlBuilder::new(budget)
sb.write_view(" sb.write_view(" calcId=\"\{value}\"")
None => ()
}
match options.calc_mode {
Some(value) => sb.write_view(" calcMode=\"\{value}\"")
None => ()
}
match options.full_calc_on_load {
Some(value) => sb.write_view(" fullCalcOnLoad=\"\{bool_attr(value)}\"")
None => ()
}
match options.ref_mode {
Some(value) => sb.write_view(" refMode=\"\{value}\"")
None => ()
}
match options.iterate {
Some(value) => sb.write_view(" iterate=\"\{bool_attr(value)}\"")
None => ()
}
match options.iterate_count {
Some(value) => sb.write_view(" iterateCount=\"\{value}\"")
None => ()
}
match options.iterate_delta {
Some(value) => sb.write_view(" iterateDelta=\"\{value}\"")
None => ()
}
match options.full_precision {
Some(value) => sb.write_view(" fullPrecision=\"\{bool_attr(value)}\"")
None => ()
}
match options.calc_completed {
Some(value) => sb.write_view(" calcCompleted=\"\{bool_attr(value)}\"")
None => ()
}
match options.calc_on_save {
Some(value) => sb.write_view(" calcOnSave=\"\{bool_attr(value)}\"")
None => ()
}
match options.concurrent_calc {
Some(value) => sb.write_view(" concurrentCalc=\"\{bool_attr(value)}\"")
None => ()
}
match options.concurrent_manual_count {
Some(value) => sb.write_view(" concurrentManualCount=\"\{value}\"")
None => ()
}
match options.force_full_calc {
Some(value) => sb.write_view(" forceFullCalc=\"\{bool_attr(value)}\"")
None => ()
}
sb.write_view("/>\n")
Some(sb.to_string())
}
///|
test "write workbook xml wb: covers active-tab fallback and defined-name guards" {
let workbook = Workbook::new()
ignore(workbook.add_sheet("Sheet1"))
ignore(workbook.add_sheet("Sheet2"))
workbook.set_sheet_visible("Sheet1", false, very_hidden=true)
workbook.active_sheet_index = -1
workbook.defined_names.push({
name: "",
refers_to: "Sheet1!$A$1",
scope: "Workbook",
comment: "",
})
workbook.defined_names.push({
name: "SkipRef",
refers_to: "",
scope: "Workbook",
comment: "",
})
workbook.defined_names.push({
name: "ScopedMissing",
refers_to: "Sheet1!$A$1",
scope: "Ghost",
comment: "note",
})
let xml = write_workbook_xml(workbook, 100, [], [], [])
inspect(xml.contains(""), content="true")
inspect(xml.contains("state=\"veryHidden\""), content="true")
inspect(xml.contains("name=\"SkipRef\""), content="false")
inspect(
xml.contains(""),
content="true",
)
inspect(xml.contains("localSheetId="), content="false")
}
///|
test "write workbook xml wb: write_workbook_pr_xml handles sparse options" {
let date_xml = match
write_workbook_pr_xml(WorkbookPropsOptions::with_values(date_1904=true)) {
Some(value) => value
None => fail("expected workbookPr xml for date_1904")
}
inspect(date_xml.contains("date1904=\"1\""), content="true")
inspect(date_xml.contains("filterPrivacy="), content="false")
inspect(date_xml.contains("codeName="), content="false")
let filter_xml = match
write_workbook_pr_xml(
WorkbookPropsOptions::with_values(filter_privacy=true),
) {
Some(value) => value
None => fail("expected workbookPr xml for filter_privacy")
}
inspect(filter_xml.contains("date1904="), content="false")
inspect(filter_xml.contains("filterPrivacy=\"1\""), content="true")
inspect(filter_xml.contains("codeName="), content="false")
}