← Files Public Equity InvestingARCHIVED FILE
skills/dcf-model-builder/scripts/xlsx_writer.py
10.5 KB · Oct 2, 2026 · 00:03 UTC
"""Minimal XLSX writer for dcf-model-builder deterministic exports."""
from __future__ import annotations
import os
import zipfile
from datetime import datetime
from pathlib import Path
from typing import Any
from xml.sax.saxutils import escape
def _is_number(value: Any) -> bool:
return isinstance(value, (int, float)) and not isinstance(value, bool)
def _col_letter(idx: int) -> str:
result = ""
n = idx
while n:
n, rem = divmod(n - 1, 26)
result = chr(65 + rem) + result
return result
def _cell_ref(row_idx: int, col_idx: int) -> str:
return f"{_col_letter(col_idx)}{row_idx}"
def _xml_text(value: Any) -> str:
return escape(str(value), {'"': """})
def _sheet_name(name: str, used: set[str]) -> str:
invalid = set("[]:*?/\\")
clean = "".join("_" if char in invalid else char for char in name).strip() or "Sheet"
clean = clean[:31]
original = clean
i = 2
while clean in used:
suffix = f"_{i}"
clean = (original[: 31 - len(suffix)] + suffix)[:31]
i += 1
used.add(clean)
return clean
def _sheet_xml(rows: list[list[Any]]) -> str:
xml_rows: list[str] = []
for r_idx, row in enumerate(rows, start=1):
cells: list[str] = []
for c_idx, value in enumerate(row, start=1):
if value is None:
continue
ref = _cell_ref(r_idx, c_idx)
if isinstance(value, bool):
cells.append(f'<c r="{ref}" t="b"><v>{1 if value else 0}</v></c>')
elif _is_number(value):
cells.append(f'<c r="{ref}"><v>{float(value):.12g}</v></c>')
else:
cells.append(f'<c r="{ref}" t="inlineStr"><is><t>{_xml_text(value)}</t></is></c>')
xml_rows.append(f'<row r="{r_idx}">{"".join(cells)}</row>')
dimension = "A1"
if rows:
max_cols = max((len(row) for row in rows), default=1)
dimension = f"A1:{_cell_ref(len(rows), max_cols)}"
cols = "".join(
f'<col min="{idx}" max="{idx}" width="18" customWidth="1"/>'
for idx in range(1, max((len(row) for row in rows), default=1) + 1)
)
return "".join(
[
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
'<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" ',
'xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">',
f'<dimension ref="{dimension}"/>',
'<sheetViews><sheetView showGridLines="0" workbookViewId="0">',
'<pane ySplit="1" topLeftCell="A2" activePane="bottomLeft" state="frozen"/>',
"</sheetView></sheetViews>",
f"<cols>{cols}</cols>",
"<sheetData>",
"".join(xml_rows),
"</sheetData>",
"</worksheet>",
]
)
def _content_types(sheet_count: int) -> str:
overrides = [
(
'<Override PartName="/xl/workbook.xml" '
'ContentType="application/vnd.openxmlformats-officedocument.'
'spreadsheetml.sheet.main+xml"/>'
),
(
'<Override PartName="/xl/styles.xml" '
'ContentType="application/vnd.openxmlformats-officedocument.'
'spreadsheetml.styles+xml"/>'
),
(
'<Override PartName="/docProps/core.xml" '
'ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>'
),
(
'<Override PartName="/docProps/app.xml" '
'ContentType="application/vnd.openxmlformats-officedocument.'
'extended-properties+xml"/>'
),
]
for idx in range(1, sheet_count + 1):
overrides.append(
f'<Override PartName="/xl/worksheets/sheet{idx}.xml" '
'ContentType="application/vnd.openxmlformats-officedocument.'
'spreadsheetml.worksheet+xml"/>'
)
return "".join(
[
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
'<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">',
'<Default Extension="rels" '
'ContentType="application/vnd.openxmlformats-package.relationships+xml"/>',
'<Default Extension="xml" ContentType="application/xml"/>',
"".join(overrides),
"</Types>",
]
)
def _root_rels() -> str:
return "".join(
[
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
'<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">',
'<Relationship Id="rId1" '
'Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" '
'Target="xl/workbook.xml"/>',
'<Relationship Id="rId2" '
'Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" '
'Target="docProps/core.xml"/>',
'<Relationship Id="rId3" '
'Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" '
'Target="docProps/app.xml"/>',
"</Relationships>",
]
)
def _workbook_xml(sheet_names: list[str]) -> str:
sheets = [
f'<sheet name="{_xml_text(name)}" sheetId="{idx}" r:id="rId{idx}"/>'
for idx, name in enumerate(sheet_names, start=1)
]
return "".join(
[
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
'<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" ',
'xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">',
"<bookViews><workbookView/></bookViews>",
f"<sheets>{''.join(sheets)}</sheets>",
"</workbook>",
]
)
def _workbook_rels(sheet_count: int) -> str:
rels = []
for idx in range(1, sheet_count + 1):
rels.append(
f'<Relationship Id="rId{idx}" '
'Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" '
f'Target="worksheets/sheet{idx}.xml"/>'
)
rels.append(
f'<Relationship Id="rId{sheet_count + 1}" '
'Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" '
'Target="styles.xml"/>'
)
return "".join(
[
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
'<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">',
"".join(rels),
"</Relationships>",
]
)
def _styles_xml() -> str:
return "".join(
[
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
'<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">',
'<fonts count="1"><font><sz val="11"/><color theme="1"/>',
'<name val="Calibri"/><family val="2"/></font></fonts>',
'<fills count="2"><fill><patternFill patternType="none"/></fill>',
'<fill><patternFill patternType="gray125"/></fill></fills>',
'<borders count="1"><border><left/><right/><top/><bottom/>',
"<diagonal/></border></borders>",
'<cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" ',
'borderId="0"/></cellStyleXfs>',
'<cellXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" ',
'borderId="0" xfId="0"/></cellXfs>',
'<cellStyles count="1"><cellStyle name="Normal" xfId="0" ',
'builtinId="0"/></cellStyles>',
"</styleSheet>",
]
)
def _core_xml() -> str:
now = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
return "".join(
[
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
'<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" ',
'xmlns:dc="http://purl.org/dc/elements/1.1/" ',
'xmlns:dcterms="http://purl.org/dc/terms/" ',
'xmlns:dcmitype="http://purl.org/dc/dcmitype/" ',
'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">',
"<dc:title>DCF Model Export</dc:title>",
"<dc:creator>dcf-model-builder</dc:creator>",
f'<dcterms:created xsi:type="dcterms:W3CDTF">{now}</dcterms:created>',
f'<dcterms:modified xsi:type="dcterms:W3CDTF">{now}</dcterms:modified>',
"</cp:coreProperties>",
]
)
def _app_xml(sheet_names: list[str]) -> str:
names = "".join(f"<vt:lpstr>{_xml_text(name)}</vt:lpstr>" for name in sheet_names)
return "".join(
[
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
'<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" ',
'xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">',
"<Application>dcf-model-builder</Application>",
'<HeadingPairs><vt:vector size="2" baseType="variant">',
"<vt:variant><vt:lpstr>Worksheets</vt:lpstr></vt:variant>",
f"<vt:variant><vt:i4>{len(sheet_names)}</vt:i4></vt:variant>",
"</vt:vector></HeadingPairs>",
f'<TitlesOfParts><vt:vector size="{len(sheet_names)}" baseType="lpstr">',
names,
"</vt:vector></TitlesOfParts>",
"</Properties>",
]
)
def write_xlsx(path: str | os.PathLike[str], rows: Any, sheet_name: str = "Model") -> None:
"""Write a minimal valid XLSX. `rows` may be a table or dict of sheet tables."""
sheets_input = rows if isinstance(rows, dict) else {sheet_name: rows}
used: set[str] = set()
sheet_names = []
sheet_tables = []
for raw_name, table in sheets_input.items():
name = _sheet_name(str(raw_name), used)
sheet_names.append(name)
sheet_tables.append(table)
Path(path).parent.mkdir(parents=True, exist_ok=True)
with zipfile.ZipFile(path, "w", compression=zipfile.ZIP_DEFLATED) as zf:
zf.writestr("[Content_Types].xml", _content_types(len(sheet_names)))
zf.writestr("_rels/.rels", _root_rels())
zf.writestr("xl/workbook.xml", _workbook_xml(sheet_names))
zf.writestr("xl/_rels/workbook.xml.rels", _workbook_rels(len(sheet_names)))
zf.writestr("xl/styles.xml", _styles_xml())
zf.writestr("docProps/core.xml", _core_xml())
zf.writestr("docProps/app.xml", _app_xml(sheet_names))
for idx, table in enumerate(sheet_tables, start=1):
zf.writestr(f"xl/worksheets/sheet{idx}.xml", _sheet_xml(table))
SHA-256: c2388e917a91eb3038b3947ca94094939503b442dbf9abe94a040f1dd1283756