Add xlsxwriter-based Excel generation scripts with openpyxl implementation
- Created create_excel_xlsxwriter.py and update_excel_xlsxwriter.py - Uses openpyxl exclusively to preserve Excel formatting and formulas - Updated server.js to use new xlsxwriter scripts for form submissions - Maintains all original functionality while ensuring proper Excel file handling 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
788
venv/lib/python3.12/site-packages/xlsxwriter/styles.py
Normal file
788
venv/lib/python3.12/site-packages/xlsxwriter/styles.py
Normal file
@@ -0,0 +1,788 @@
|
||||
###############################################################################
|
||||
#
|
||||
# Styles - A class for writing the Excel XLSX Worksheet file.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
# Copyright (c) 2013-2025, John McNamara, jmcnamara@cpan.org
|
||||
#
|
||||
|
||||
# Package imports.
|
||||
from . import xmlwriter
|
||||
|
||||
|
||||
class Styles(xmlwriter.XMLwriter):
|
||||
"""
|
||||
A class for writing the Excel XLSX Styles file.
|
||||
|
||||
|
||||
"""
|
||||
|
||||
###########################################################################
|
||||
#
|
||||
# Public API.
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""
|
||||
Constructor.
|
||||
|
||||
"""
|
||||
|
||||
super().__init__()
|
||||
|
||||
self.xf_formats = []
|
||||
self.palette = []
|
||||
self.font_count = 0
|
||||
self.num_formats = []
|
||||
self.border_count = 0
|
||||
self.fill_count = 0
|
||||
self.custom_colors = []
|
||||
self.dxf_formats = []
|
||||
self.has_hyperlink = False
|
||||
self.hyperlink_font_id = 0
|
||||
self.has_comments = False
|
||||
|
||||
###########################################################################
|
||||
#
|
||||
# Private API.
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
def _assemble_xml_file(self) -> None:
|
||||
# Assemble and write the XML file.
|
||||
|
||||
# Write the XML declaration.
|
||||
self._xml_declaration()
|
||||
|
||||
# Add the style sheet.
|
||||
self._write_style_sheet()
|
||||
|
||||
# Write the number formats.
|
||||
self._write_num_fmts()
|
||||
|
||||
# Write the fonts.
|
||||
self._write_fonts()
|
||||
|
||||
# Write the fills.
|
||||
self._write_fills()
|
||||
|
||||
# Write the borders element.
|
||||
self._write_borders()
|
||||
|
||||
# Write the cellStyleXfs element.
|
||||
self._write_cell_style_xfs()
|
||||
|
||||
# Write the cellXfs element.
|
||||
self._write_cell_xfs()
|
||||
|
||||
# Write the cellStyles element.
|
||||
self._write_cell_styles()
|
||||
|
||||
# Write the dxfs element.
|
||||
self._write_dxfs()
|
||||
|
||||
# Write the tableStyles element.
|
||||
self._write_table_styles()
|
||||
|
||||
# Write the colors element.
|
||||
self._write_colors()
|
||||
|
||||
# Close the style sheet tag.
|
||||
self._xml_end_tag("styleSheet")
|
||||
|
||||
# Close the file.
|
||||
self._xml_close()
|
||||
|
||||
def _set_style_properties(self, properties) -> None:
|
||||
# Pass in the Format objects and other properties used in the styles.
|
||||
|
||||
self.xf_formats = properties[0]
|
||||
self.palette = properties[1]
|
||||
self.font_count = properties[2]
|
||||
self.num_formats = properties[3]
|
||||
self.border_count = properties[4]
|
||||
self.fill_count = properties[5]
|
||||
self.custom_colors = properties[6]
|
||||
self.dxf_formats = properties[7]
|
||||
self.has_comments = properties[8]
|
||||
|
||||
###########################################################################
|
||||
#
|
||||
# XML methods.
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
def _write_style_sheet(self) -> None:
|
||||
# Write the <styleSheet> element.
|
||||
xmlns = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
||||
|
||||
attributes = [("xmlns", xmlns)]
|
||||
self._xml_start_tag("styleSheet", attributes)
|
||||
|
||||
def _write_num_fmts(self) -> None:
|
||||
# Write the <numFmts> element.
|
||||
if not self.num_formats:
|
||||
return
|
||||
|
||||
attributes = [("count", len(self.num_formats))]
|
||||
self._xml_start_tag("numFmts", attributes)
|
||||
|
||||
# Write the numFmts elements.
|
||||
for index, num_format in enumerate(self.num_formats, 164):
|
||||
self._write_num_fmt(index, num_format)
|
||||
|
||||
self._xml_end_tag("numFmts")
|
||||
|
||||
def _write_num_fmt(self, num_fmt_id, format_code) -> None:
|
||||
# Write the <numFmt> element.
|
||||
format_codes = {
|
||||
0: "General",
|
||||
1: "0",
|
||||
2: "0.00",
|
||||
3: "#,##0",
|
||||
4: "#,##0.00",
|
||||
5: "($#,##0_);($#,##0)",
|
||||
6: "($#,##0_);[Red]($#,##0)",
|
||||
7: "($#,##0.00_);($#,##0.00)",
|
||||
8: "($#,##0.00_);[Red]($#,##0.00)",
|
||||
9: "0%",
|
||||
10: "0.00%",
|
||||
11: "0.00E+00",
|
||||
12: "# ?/?",
|
||||
13: "# ??/??",
|
||||
14: "m/d/yy",
|
||||
15: "d-mmm-yy",
|
||||
16: "d-mmm",
|
||||
17: "mmm-yy",
|
||||
18: "h:mm AM/PM",
|
||||
19: "h:mm:ss AM/PM",
|
||||
20: "h:mm",
|
||||
21: "h:mm:ss",
|
||||
22: "m/d/yy h:mm",
|
||||
37: "(#,##0_);(#,##0)",
|
||||
38: "(#,##0_);[Red](#,##0)",
|
||||
39: "(#,##0.00_);(#,##0.00)",
|
||||
40: "(#,##0.00_);[Red](#,##0.00)",
|
||||
41: '_(* #,##0_);_(* (#,##0);_(* "-"_);_(_)',
|
||||
42: '_($* #,##0_);_($* (#,##0);_($* "-"_);_(_)',
|
||||
43: '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(_)',
|
||||
44: '_($* #,##0.00_);_($* (#,##0.00);_($* "-"??_);_(_)',
|
||||
45: "mm:ss",
|
||||
46: "[h]:mm:ss",
|
||||
47: "mm:ss.0",
|
||||
48: "##0.0E+0",
|
||||
49: "@",
|
||||
}
|
||||
|
||||
# Set the format code for built-in number formats.
|
||||
if num_fmt_id < 164:
|
||||
format_code = format_codes.get(num_fmt_id, "General")
|
||||
|
||||
attributes = [
|
||||
("numFmtId", num_fmt_id),
|
||||
("formatCode", format_code),
|
||||
]
|
||||
|
||||
self._xml_empty_tag("numFmt", attributes)
|
||||
|
||||
def _write_fonts(self) -> None:
|
||||
# Write the <fonts> element.
|
||||
if self.has_comments:
|
||||
# Add extra font for comments.
|
||||
attributes = [("count", self.font_count + 1)]
|
||||
else:
|
||||
attributes = [("count", self.font_count)]
|
||||
|
||||
self._xml_start_tag("fonts", attributes)
|
||||
|
||||
# Write the font elements for xf_format objects that have them.
|
||||
for xf_format in self.xf_formats:
|
||||
if xf_format.has_font:
|
||||
self._write_font(xf_format)
|
||||
|
||||
if self.has_comments:
|
||||
self._write_comment_font()
|
||||
|
||||
self._xml_end_tag("fonts")
|
||||
|
||||
def _write_font(self, xf_format, is_dxf_format=False) -> None:
|
||||
# Write the <font> element.
|
||||
self._xml_start_tag("font")
|
||||
|
||||
# The condense and extend elements are mainly used in dxf formats.
|
||||
if xf_format.font_condense:
|
||||
self._write_condense()
|
||||
|
||||
if xf_format.font_extend:
|
||||
self._write_extend()
|
||||
|
||||
if xf_format.bold:
|
||||
self._xml_empty_tag("b")
|
||||
|
||||
if xf_format.italic:
|
||||
self._xml_empty_tag("i")
|
||||
|
||||
if xf_format.font_strikeout:
|
||||
self._xml_empty_tag("strike")
|
||||
|
||||
if xf_format.font_outline:
|
||||
self._xml_empty_tag("outline")
|
||||
|
||||
if xf_format.font_shadow:
|
||||
self._xml_empty_tag("shadow")
|
||||
|
||||
# Handle the underline variants.
|
||||
if xf_format.underline:
|
||||
self._write_underline(xf_format.underline)
|
||||
|
||||
if xf_format.font_script == 1:
|
||||
self._write_vert_align("superscript")
|
||||
|
||||
if xf_format.font_script == 2:
|
||||
self._write_vert_align("subscript")
|
||||
|
||||
if not is_dxf_format:
|
||||
self._xml_empty_tag("sz", [("val", xf_format.font_size)])
|
||||
|
||||
if xf_format.theme == -1:
|
||||
# Ignore for excel2003_style.
|
||||
pass
|
||||
elif xf_format.theme:
|
||||
self._write_color([("theme", xf_format.theme)])
|
||||
elif xf_format.color_indexed:
|
||||
self._write_color([("indexed", xf_format.color_indexed)])
|
||||
elif xf_format.font_color:
|
||||
color = xf_format.font_color
|
||||
if not color._is_automatic:
|
||||
self._write_color(color._attributes())
|
||||
elif not is_dxf_format:
|
||||
self._write_color([("theme", 1)])
|
||||
|
||||
if not is_dxf_format:
|
||||
self._xml_empty_tag("name", [("val", xf_format.font_name)])
|
||||
|
||||
if xf_format.font_family:
|
||||
self._xml_empty_tag("family", [("val", xf_format.font_family)])
|
||||
|
||||
if xf_format.font_charset:
|
||||
self._xml_empty_tag("charset", [("val", xf_format.font_charset)])
|
||||
|
||||
if xf_format.font_name == "Calibri" and not xf_format.hyperlink:
|
||||
self._xml_empty_tag("scheme", [("val", xf_format.font_scheme)])
|
||||
|
||||
if xf_format.hyperlink:
|
||||
self.has_hyperlink = True
|
||||
if self.hyperlink_font_id == 0:
|
||||
self.hyperlink_font_id = xf_format.font_index
|
||||
|
||||
self._xml_end_tag("font")
|
||||
|
||||
def _write_comment_font(self) -> None:
|
||||
# Write the <font> element for comments.
|
||||
self._xml_start_tag("font")
|
||||
|
||||
self._xml_empty_tag("sz", [("val", 8)])
|
||||
self._write_color([("indexed", 81)])
|
||||
self._xml_empty_tag("name", [("val", "Tahoma")])
|
||||
self._xml_empty_tag("family", [("val", 2)])
|
||||
|
||||
self._xml_end_tag("font")
|
||||
|
||||
def _write_underline(self, underline) -> None:
|
||||
# Write the underline font element.
|
||||
|
||||
if underline == 2:
|
||||
attributes = [("val", "double")]
|
||||
elif underline == 33:
|
||||
attributes = [("val", "singleAccounting")]
|
||||
elif underline == 34:
|
||||
attributes = [("val", "doubleAccounting")]
|
||||
else:
|
||||
# Default to single underline.
|
||||
attributes = []
|
||||
|
||||
self._xml_empty_tag("u", attributes)
|
||||
|
||||
def _write_vert_align(self, val) -> None:
|
||||
# Write the <vertAlign> font sub-element.
|
||||
attributes = [("val", val)]
|
||||
|
||||
self._xml_empty_tag("vertAlign", attributes)
|
||||
|
||||
def _write_color(self, attributes) -> None:
|
||||
# Write the <color> element.
|
||||
self._xml_empty_tag("color", attributes)
|
||||
|
||||
def _write_fills(self) -> None:
|
||||
# Write the <fills> element.
|
||||
attributes = [("count", self.fill_count)]
|
||||
|
||||
self._xml_start_tag("fills", attributes)
|
||||
|
||||
# Write the default fill element.
|
||||
self._write_default_fill("none")
|
||||
self._write_default_fill("gray125")
|
||||
|
||||
# Write the fill elements for xf_format objects that have them.
|
||||
for xf_format in self.xf_formats:
|
||||
if xf_format.has_fill:
|
||||
self._write_fill(xf_format)
|
||||
|
||||
self._xml_end_tag("fills")
|
||||
|
||||
def _write_default_fill(self, pattern_type) -> None:
|
||||
# Write the <fill> element for the default fills.
|
||||
self._xml_start_tag("fill")
|
||||
self._xml_empty_tag("patternFill", [("patternType", pattern_type)])
|
||||
self._xml_end_tag("fill")
|
||||
|
||||
def _write_fill(self, xf_format, is_dxf_format=False) -> None:
|
||||
# Write the <fill> element.
|
||||
pattern = xf_format.pattern
|
||||
bg_color = xf_format.bg_color
|
||||
fg_color = xf_format.fg_color
|
||||
|
||||
# Colors for dxf formats are handled differently from normal formats
|
||||
# since the normal xf_format reverses the meaning of BG and FG for
|
||||
# solid fills.
|
||||
if is_dxf_format:
|
||||
bg_color = xf_format.dxf_bg_color
|
||||
fg_color = xf_format.dxf_fg_color
|
||||
|
||||
patterns = (
|
||||
"none",
|
||||
"solid",
|
||||
"mediumGray",
|
||||
"darkGray",
|
||||
"lightGray",
|
||||
"darkHorizontal",
|
||||
"darkVertical",
|
||||
"darkDown",
|
||||
"darkUp",
|
||||
"darkGrid",
|
||||
"darkTrellis",
|
||||
"lightHorizontal",
|
||||
"lightVertical",
|
||||
"lightDown",
|
||||
"lightUp",
|
||||
"lightGrid",
|
||||
"lightTrellis",
|
||||
"gray125",
|
||||
"gray0625",
|
||||
)
|
||||
|
||||
# Special handling for pattern only case.
|
||||
if not fg_color and not bg_color and patterns[pattern]:
|
||||
self._write_default_fill(patterns[pattern])
|
||||
return
|
||||
|
||||
self._xml_start_tag("fill")
|
||||
|
||||
# The "none" pattern is handled differently for dxf formats.
|
||||
if is_dxf_format and pattern <= 1:
|
||||
self._xml_start_tag("patternFill")
|
||||
else:
|
||||
self._xml_start_tag("patternFill", [("patternType", patterns[pattern])])
|
||||
|
||||
if fg_color:
|
||||
if not fg_color._is_automatic:
|
||||
self._xml_empty_tag("fgColor", fg_color._attributes())
|
||||
|
||||
if bg_color:
|
||||
if not bg_color._is_automatic:
|
||||
self._xml_empty_tag("bgColor", bg_color._attributes())
|
||||
else:
|
||||
if not is_dxf_format and pattern <= 1:
|
||||
self._xml_empty_tag("bgColor", [("indexed", 64)])
|
||||
|
||||
self._xml_end_tag("patternFill")
|
||||
self._xml_end_tag("fill")
|
||||
|
||||
def _write_borders(self) -> None:
|
||||
# Write the <borders> element.
|
||||
attributes = [("count", self.border_count)]
|
||||
|
||||
self._xml_start_tag("borders", attributes)
|
||||
|
||||
# Write the border elements for xf_format objects that have them.
|
||||
for xf_format in self.xf_formats:
|
||||
if xf_format.has_border:
|
||||
self._write_border(xf_format)
|
||||
|
||||
self._xml_end_tag("borders")
|
||||
|
||||
def _write_border(self, xf_format, is_dxf_format=False) -> None:
|
||||
# Write the <border> element.
|
||||
attributes = []
|
||||
|
||||
# Diagonal borders add attributes to the <border> element.
|
||||
if xf_format.diag_type == 1:
|
||||
attributes.append(("diagonalUp", 1))
|
||||
elif xf_format.diag_type == 2:
|
||||
attributes.append(("diagonalDown", 1))
|
||||
elif xf_format.diag_type == 3:
|
||||
attributes.append(("diagonalUp", 1))
|
||||
attributes.append(("diagonalDown", 1))
|
||||
|
||||
# Ensure that a default diag border is set if the diag type is set.
|
||||
if xf_format.diag_type and not xf_format.diag_border:
|
||||
xf_format.diag_border = 1
|
||||
|
||||
# Write the start border tag.
|
||||
self._xml_start_tag("border", attributes)
|
||||
|
||||
# Write the <border> sub elements.
|
||||
self._write_sub_border("left", xf_format.left, xf_format.left_color)
|
||||
|
||||
self._write_sub_border("right", xf_format.right, xf_format.right_color)
|
||||
|
||||
self._write_sub_border("top", xf_format.top, xf_format.top_color)
|
||||
|
||||
self._write_sub_border("bottom", xf_format.bottom, xf_format.bottom_color)
|
||||
|
||||
# Condition DXF formats don't allow diagonal borders.
|
||||
if not is_dxf_format:
|
||||
self._write_sub_border(
|
||||
"diagonal", xf_format.diag_border, xf_format.diag_color
|
||||
)
|
||||
|
||||
if is_dxf_format:
|
||||
self._write_sub_border("vertical", None, None)
|
||||
self._write_sub_border("horizontal", None, None)
|
||||
|
||||
self._xml_end_tag("border")
|
||||
|
||||
def _write_sub_border(self, border_type, style, color) -> None:
|
||||
# Write the <border> sub elements such as <right>, <top>, etc.
|
||||
attributes = []
|
||||
|
||||
if not style:
|
||||
self._xml_empty_tag(border_type)
|
||||
return
|
||||
|
||||
border_styles = (
|
||||
"none",
|
||||
"thin",
|
||||
"medium",
|
||||
"dashed",
|
||||
"dotted",
|
||||
"thick",
|
||||
"double",
|
||||
"hair",
|
||||
"mediumDashed",
|
||||
"dashDot",
|
||||
"mediumDashDot",
|
||||
"dashDotDot",
|
||||
"mediumDashDotDot",
|
||||
"slantDashDot",
|
||||
)
|
||||
|
||||
attributes.append(("style", border_styles[style]))
|
||||
|
||||
self._xml_start_tag(border_type, attributes)
|
||||
|
||||
if color and not color._is_automatic:
|
||||
self._xml_empty_tag("color", color._attributes())
|
||||
else:
|
||||
self._xml_empty_tag("color", [("auto", 1)])
|
||||
|
||||
self._xml_end_tag(border_type)
|
||||
|
||||
def _write_cell_style_xfs(self) -> None:
|
||||
# Write the <cellStyleXfs> element.
|
||||
count = 1
|
||||
|
||||
if self.has_hyperlink:
|
||||
count = 2
|
||||
|
||||
attributes = [("count", count)]
|
||||
|
||||
self._xml_start_tag("cellStyleXfs", attributes)
|
||||
self._write_style_xf()
|
||||
|
||||
if self.has_hyperlink:
|
||||
self._write_style_xf(True, self.hyperlink_font_id)
|
||||
|
||||
self._xml_end_tag("cellStyleXfs")
|
||||
|
||||
def _write_cell_xfs(self) -> None:
|
||||
# Write the <cellXfs> element.
|
||||
formats = self.xf_formats
|
||||
|
||||
# Workaround for when the last xf_format is used for the comment font
|
||||
# and shouldn't be used for cellXfs.
|
||||
last_format = formats[-1]
|
||||
if last_format.font_only:
|
||||
formats.pop()
|
||||
|
||||
attributes = [("count", len(formats))]
|
||||
self._xml_start_tag("cellXfs", attributes)
|
||||
|
||||
# Write the xf elements.
|
||||
for xf_format in formats:
|
||||
self._write_xf(xf_format)
|
||||
|
||||
self._xml_end_tag("cellXfs")
|
||||
|
||||
def _write_style_xf(self, has_hyperlink=False, font_id=0) -> None:
|
||||
# Write the style <xf> element.
|
||||
num_fmt_id = 0
|
||||
fill_id = 0
|
||||
border_id = 0
|
||||
|
||||
attributes = [
|
||||
("numFmtId", num_fmt_id),
|
||||
("fontId", font_id),
|
||||
("fillId", fill_id),
|
||||
("borderId", border_id),
|
||||
]
|
||||
|
||||
if has_hyperlink:
|
||||
attributes.append(("applyNumberFormat", 0))
|
||||
attributes.append(("applyFill", 0))
|
||||
attributes.append(("applyBorder", 0))
|
||||
attributes.append(("applyAlignment", 0))
|
||||
attributes.append(("applyProtection", 0))
|
||||
|
||||
self._xml_start_tag("xf", attributes)
|
||||
self._xml_empty_tag("alignment", [("vertical", "top")])
|
||||
self._xml_empty_tag("protection", [("locked", 0)])
|
||||
self._xml_end_tag("xf")
|
||||
|
||||
else:
|
||||
self._xml_empty_tag("xf", attributes)
|
||||
|
||||
def _write_xf(self, xf_format) -> None:
|
||||
# Write the <xf> element.
|
||||
xf_id = xf_format.xf_id
|
||||
font_id = xf_format.font_index
|
||||
fill_id = xf_format.fill_index
|
||||
border_id = xf_format.border_index
|
||||
num_fmt_id = xf_format.num_format_index
|
||||
|
||||
has_checkbox = xf_format.checkbox
|
||||
has_alignment = False
|
||||
has_protection = False
|
||||
|
||||
attributes = [
|
||||
("numFmtId", num_fmt_id),
|
||||
("fontId", font_id),
|
||||
("fillId", fill_id),
|
||||
("borderId", border_id),
|
||||
("xfId", xf_id),
|
||||
]
|
||||
|
||||
if xf_format.quote_prefix:
|
||||
attributes.append(("quotePrefix", 1))
|
||||
|
||||
if xf_format.num_format_index > 0:
|
||||
attributes.append(("applyNumberFormat", 1))
|
||||
|
||||
# Add applyFont attribute if XF format uses a font element.
|
||||
if xf_format.font_index > 0 and not xf_format.hyperlink:
|
||||
attributes.append(("applyFont", 1))
|
||||
|
||||
# Add applyFill attribute if XF format uses a fill element.
|
||||
if xf_format.fill_index > 0:
|
||||
attributes.append(("applyFill", 1))
|
||||
|
||||
# Add applyBorder attribute if XF format uses a border element.
|
||||
if xf_format.border_index > 0:
|
||||
attributes.append(("applyBorder", 1))
|
||||
|
||||
# Check if XF format has alignment properties set.
|
||||
(apply_align, align) = xf_format._get_align_properties()
|
||||
|
||||
# Check if an alignment sub-element should be written.
|
||||
if apply_align and align:
|
||||
has_alignment = True
|
||||
|
||||
# We can also have applyAlignment without a sub-element.
|
||||
if apply_align or xf_format.hyperlink:
|
||||
attributes.append(("applyAlignment", 1))
|
||||
|
||||
# Check for cell protection properties.
|
||||
protection = xf_format._get_protection_properties()
|
||||
|
||||
if protection or xf_format.hyperlink:
|
||||
attributes.append(("applyProtection", 1))
|
||||
|
||||
if not xf_format.hyperlink:
|
||||
has_protection = True
|
||||
|
||||
# Write XF with sub-elements if required.
|
||||
if has_alignment or has_protection or has_checkbox:
|
||||
self._xml_start_tag("xf", attributes)
|
||||
|
||||
if has_alignment:
|
||||
self._xml_empty_tag("alignment", align)
|
||||
|
||||
if has_protection:
|
||||
self._xml_empty_tag("protection", protection)
|
||||
|
||||
if has_checkbox:
|
||||
self._write_xf_format_extensions()
|
||||
|
||||
self._xml_end_tag("xf")
|
||||
else:
|
||||
self._xml_empty_tag("xf", attributes)
|
||||
|
||||
def _write_cell_styles(self) -> None:
|
||||
# Write the <cellStyles> element.
|
||||
count = 1
|
||||
|
||||
if self.has_hyperlink:
|
||||
count = 2
|
||||
|
||||
attributes = [("count", count)]
|
||||
|
||||
self._xml_start_tag("cellStyles", attributes)
|
||||
|
||||
if self.has_hyperlink:
|
||||
self._write_cell_style("Hyperlink", 1, 8)
|
||||
|
||||
self._write_cell_style()
|
||||
|
||||
self._xml_end_tag("cellStyles")
|
||||
|
||||
def _write_cell_style(self, name="Normal", xf_id=0, builtin_id=0) -> None:
|
||||
# Write the <cellStyle> element.
|
||||
attributes = [
|
||||
("name", name),
|
||||
("xfId", xf_id),
|
||||
("builtinId", builtin_id),
|
||||
]
|
||||
|
||||
self._xml_empty_tag("cellStyle", attributes)
|
||||
|
||||
def _write_dxfs(self) -> None:
|
||||
# Write the <dxfs> element.
|
||||
formats = self.dxf_formats
|
||||
count = len(formats)
|
||||
|
||||
attributes = [("count", len(formats))]
|
||||
|
||||
if count:
|
||||
self._xml_start_tag("dxfs", attributes)
|
||||
|
||||
# Write the font elements for xf_format objects that have them.
|
||||
for dxf_format in self.dxf_formats:
|
||||
self._xml_start_tag("dxf")
|
||||
if dxf_format.has_dxf_font:
|
||||
self._write_font(dxf_format, True)
|
||||
|
||||
if dxf_format.num_format_index:
|
||||
self._write_num_fmt(
|
||||
dxf_format.num_format_index, dxf_format.num_format
|
||||
)
|
||||
|
||||
if dxf_format.has_dxf_fill:
|
||||
self._write_fill(dxf_format, True)
|
||||
|
||||
if dxf_format.has_dxf_border:
|
||||
self._write_border(dxf_format, True)
|
||||
|
||||
if dxf_format.checkbox:
|
||||
self._write_dxf_format_extensions()
|
||||
|
||||
self._xml_end_tag("dxf")
|
||||
|
||||
self._xml_end_tag("dxfs")
|
||||
else:
|
||||
self._xml_empty_tag("dxfs", attributes)
|
||||
|
||||
def _write_table_styles(self) -> None:
|
||||
# Write the <tableStyles> element.
|
||||
count = 0
|
||||
default_table_style = "TableStyleMedium9"
|
||||
default_pivot_style = "PivotStyleLight16"
|
||||
|
||||
attributes = [
|
||||
("count", count),
|
||||
("defaultTableStyle", default_table_style),
|
||||
("defaultPivotStyle", default_pivot_style),
|
||||
]
|
||||
|
||||
self._xml_empty_tag("tableStyles", attributes)
|
||||
|
||||
def _write_colors(self) -> None:
|
||||
# Write the <colors> element.
|
||||
custom_colors = self.custom_colors
|
||||
|
||||
if not custom_colors:
|
||||
return
|
||||
|
||||
self._xml_start_tag("colors")
|
||||
self._write_mru_colors(custom_colors)
|
||||
self._xml_end_tag("colors")
|
||||
|
||||
def _write_mru_colors(self, custom_colors) -> None:
|
||||
# Write the <mruColors> element for the most recently used colors.
|
||||
|
||||
# Write the custom custom_colors in reverse order.
|
||||
custom_colors.reverse()
|
||||
|
||||
# Limit the mruColors to the last 10.
|
||||
if len(custom_colors) > 10:
|
||||
custom_colors = custom_colors[0:10]
|
||||
|
||||
self._xml_start_tag("mruColors")
|
||||
|
||||
# Write the custom custom_colors in reverse order.
|
||||
for color in custom_colors:
|
||||
# For backwards compatibility convert possible
|
||||
self._write_color(color._attributes())
|
||||
|
||||
self._xml_end_tag("mruColors")
|
||||
|
||||
def _write_condense(self) -> None:
|
||||
# Write the <condense> element.
|
||||
attributes = [("val", 0)]
|
||||
|
||||
self._xml_empty_tag("condense", attributes)
|
||||
|
||||
def _write_extend(self) -> None:
|
||||
# Write the <extend> element.
|
||||
attributes = [("val", 0)]
|
||||
|
||||
self._xml_empty_tag("extend", attributes)
|
||||
|
||||
def _write_xf_format_extensions(self) -> None:
|
||||
# Write the xfComplement <extLst> elements.
|
||||
schema = "http://schemas.microsoft.com/office/spreadsheetml"
|
||||
attributes = [
|
||||
("uri", "{C7286773-470A-42A8-94C5-96B5CB345126}"),
|
||||
(
|
||||
"xmlns:xfpb",
|
||||
schema + "/2022/featurepropertybag",
|
||||
),
|
||||
]
|
||||
|
||||
self._xml_start_tag("extLst")
|
||||
self._xml_start_tag("ext", attributes)
|
||||
|
||||
self._xml_empty_tag("xfpb:xfComplement", [("i", "0")])
|
||||
|
||||
self._xml_end_tag("ext")
|
||||
self._xml_end_tag("extLst")
|
||||
|
||||
def _write_dxf_format_extensions(self) -> None:
|
||||
# Write the DXFComplement <extLst> elements.
|
||||
schema = "http://schemas.microsoft.com/office/spreadsheetml"
|
||||
attributes = [
|
||||
("uri", "{0417FA29-78FA-4A13-93AC-8FF0FAFDF519}"),
|
||||
(
|
||||
"xmlns:xfpb",
|
||||
schema + "/2022/featurepropertybag",
|
||||
),
|
||||
]
|
||||
|
||||
self._xml_start_tag("extLst")
|
||||
self._xml_start_tag("ext", attributes)
|
||||
|
||||
self._xml_empty_tag("xfpb:DXFComplement", [("i", "0")])
|
||||
|
||||
self._xml_end_tag("ext")
|
||||
self._xml_end_tag("extLst")
|
||||
Reference in New Issue
Block a user