diff options
Diffstat (limited to '.venv/lib/python3.12/site-packages/xlsxwriter/format.py')
-rw-r--r-- | .venv/lib/python3.12/site-packages/xlsxwriter/format.py | 1217 |
1 files changed, 1217 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/xlsxwriter/format.py b/.venv/lib/python3.12/site-packages/xlsxwriter/format.py new file mode 100644 index 00000000..22996fed --- /dev/null +++ b/.venv/lib/python3.12/site-packages/xlsxwriter/format.py @@ -0,0 +1,1217 @@ +############################################################################### +# +# Format - 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 warnings import warn + +from . import xmlwriter + + +class Format(xmlwriter.XMLwriter): + """ + A class for writing the Excel XLSX Format file. + + + """ + + ########################################################################### + # + # Public API. + # + ########################################################################### + + def __init__(self, properties=None, xf_indices=None, dxf_indices=None): + """ + Constructor. + + """ + if properties is None: + properties = {} + + super().__init__() + + self.xf_format_indices = xf_indices + self.dxf_format_indices = dxf_indices + self.xf_index = None + self.dxf_index = None + + self.num_format = "General" + self.num_format_index = 0 + self.font_index = 0 + self.has_font = 0 + self.has_dxf_font = 0 + + self.bold = 0 + self.underline = 0 + self.italic = 0 + self.font_name = "Calibri" + self.font_size = 11 + self.font_color = 0x0 + self.font_strikeout = 0 + self.font_outline = 0 + self.font_shadow = 0 + self.font_script = 0 + self.font_family = 2 + self.font_charset = 0 + self.font_scheme = "minor" + self.font_condense = 0 + self.font_extend = 0 + self.theme = 0 + self.hyperlink = False + self.xf_id = 0 + + self.hidden = 0 + self.locked = 1 + + self.text_h_align = 0 + self.text_wrap = 0 + self.text_v_align = 0 + self.text_justlast = 0 + self.rotation = 0 + + self.fg_color = 0 + self.bg_color = 0 + self.pattern = 0 + self.has_fill = 0 + self.has_dxf_fill = 0 + self.fill_index = 0 + self.fill_count = 0 + + self.border_index = 0 + self.has_border = 0 + self.has_dxf_border = 0 + self.border_count = 0 + + self.bottom = 0 + self.bottom_color = 0 + self.diag_border = 0 + self.diag_color = 0 + self.diag_type = 0 + self.left = 0 + self.left_color = 0 + self.right = 0 + self.right_color = 0 + self.top = 0 + self.top_color = 0 + + self.indent = 0 + self.shrink = 0 + self.merge_range = 0 + self.reading_order = 0 + self.just_distrib = 0 + self.color_indexed = 0 + self.font_only = 0 + + self.quote_prefix = False + self.checkbox = False + + # Convert properties in the constructor to method calls. + for key, value in properties.items(): + getattr(self, "set_" + key)(value) + + self._format_key = None + + ########################################################################### + # + # Format properties. + # + ########################################################################### + + def set_font_name(self, font_name): + """ + Set the Format font_name property such as 'Time New Roman'. The + default Excel font is 'Calibri'. + + Args: + font_name: String with the font name. No default. + + Returns: + Nothing. + + """ + self.font_name = font_name + + def set_font_size(self, font_size=11): + """ + Set the Format font_size property. The default Excel font size is 11. + + Args: + font_size: Int with font size. No default. + + Returns: + Nothing. + + """ + self.font_size = font_size + + def set_font_color(self, font_color): + """ + Set the Format font_color property. The Excel default is black. + + Args: + font_color: String with the font color. No default. + + Returns: + Nothing. + + """ + self.font_color = self._get_color(font_color) + + def set_bold(self, bold=True): + """ + Set the Format bold property. + + Args: + bold: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.bold = bold + + def set_italic(self, italic=True): + """ + Set the Format italic property. + + Args: + italic: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.italic = italic + + def set_underline(self, underline=1): + """ + Set the Format underline property. + + Args: + underline: Default is 1, single underline. + + Returns: + Nothing. + + """ + self.underline = underline + + def set_font_strikeout(self, font_strikeout=True): + """ + Set the Format font_strikeout property. + + Args: + font_strikeout: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.font_strikeout = font_strikeout + + def set_font_script(self, font_script=1): + """ + Set the Format font_script property. + + Args: + font_script: Default is 1, superscript. + + Returns: + Nothing. + + """ + self.font_script = font_script + + def set_font_outline(self, font_outline=True): + """ + Set the Format font_outline property. + + Args: + font_outline: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.font_outline = font_outline + + def set_font_shadow(self, font_shadow=True): + """ + Set the Format font_shadow property. + + Args: + font_shadow: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.font_shadow = font_shadow + + def set_num_format(self, num_format): + """ + Set the Format num_format property such as '#,##0'. + + Args: + num_format: String representing the number format. No default. + + Returns: + Nothing. + + """ + self.num_format = num_format + + def set_locked(self, locked=True): + """ + Set the Format locked property. + + Args: + locked: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.locked = locked + + def set_hidden(self, hidden=True): + """ + Set the Format hidden property. + + Args: + hidden: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.hidden = hidden + + def set_align(self, alignment): + """ + Set the Format cell alignment. + + Args: + alignment: String representing alignment. No default. + + Returns: + Nothing. + """ + alignment = alignment.lower() + + # Set horizontal alignment properties. + if alignment == "left": + self.set_text_h_align(1) + if alignment == "centre": + self.set_text_h_align(2) + if alignment == "center": + self.set_text_h_align(2) + if alignment == "right": + self.set_text_h_align(3) + if alignment == "fill": + self.set_text_h_align(4) + if alignment == "justify": + self.set_text_h_align(5) + if alignment == "center_across": + self.set_text_h_align(6) + if alignment == "centre_across": + self.set_text_h_align(6) + if alignment == "distributed": + self.set_text_h_align(7) + if alignment == "justify_distributed": + self.set_text_h_align(7) + + if alignment == "justify_distributed": + self.just_distrib = 1 + + # Set vertical alignment properties. + if alignment == "top": + self.set_text_v_align(1) + if alignment == "vcentre": + self.set_text_v_align(2) + if alignment == "vcenter": + self.set_text_v_align(2) + if alignment == "bottom": + self.set_text_v_align(3) + if alignment == "vjustify": + self.set_text_v_align(4) + if alignment == "vdistributed": + self.set_text_v_align(5) + + def set_center_across(self, align_type=None): + # pylint: disable=unused-argument + """ + Set the Format center_across property. + + Returns: + Nothing. + + """ + self.set_text_h_align(6) + + def set_text_wrap(self, text_wrap=True): + """ + Set the Format text_wrap property. + + Args: + text_wrap: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.text_wrap = text_wrap + + def set_rotation(self, rotation): + """ + Set the Format rotation property. + + Args: + rotation: Rotation angle. No default. + + Returns: + Nothing. + + """ + rotation = int(rotation) + + # Map user angle to Excel angle. + if rotation == 270: + rotation = 255 + elif -90 <= rotation <= 90: + if rotation < 0: + rotation = -rotation + 90 + else: + warn("Rotation rotation outside range: -90 <= angle <= 90") + return + + self.rotation = rotation + + def set_indent(self, indent=1): + """ + Set the Format indent property. + + Args: + indent: Default is 1, first indentation level. + + Returns: + Nothing. + + """ + self.indent = indent + + def set_shrink(self, shrink=True): + """ + Set the Format shrink property. + + Args: + shrink: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.shrink = shrink + + def set_text_justlast(self, text_justlast=True): + """ + Set the Format text_justlast property. + + Args: + text_justlast: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.text_justlast = text_justlast + + def set_pattern(self, pattern=1): + """ + Set the Format pattern property. + + Args: + pattern: Default is 1, solid fill. + + Returns: + Nothing. + + """ + self.pattern = pattern + + def set_bg_color(self, bg_color): + """ + Set the Format bg_color property. + + Args: + bg_color: Background color. No default. + + Returns: + Nothing. + + """ + self.bg_color = self._get_color(bg_color) + + def set_fg_color(self, fg_color): + """ + Set the Format fg_color property. + + Args: + fg_color: Foreground color. No default. + + Returns: + Nothing. + + """ + self.fg_color = self._get_color(fg_color) + + # set_border(style) Set cells borders to the same style + def set_border(self, style=1): + """ + Set the Format bottom property. + + Args: + bottom: Default is 1, border type 1. + + Returns: + Nothing. + + """ + self.set_bottom(style) + self.set_top(style) + self.set_left(style) + self.set_right(style) + + # set_border_color(color) Set cells border to the same color + def set_border_color(self, color): + """ + Set the Format bottom property. + + Args: + color: Color string. No default. + + Returns: + Nothing. + + """ + self.set_bottom_color(color) + self.set_top_color(color) + self.set_left_color(color) + self.set_right_color(color) + + def set_bottom(self, bottom=1): + """ + Set the Format bottom property. + + Args: + bottom: Default is 1, border type 1. + + Returns: + Nothing. + + """ + self.bottom = bottom + + def set_bottom_color(self, bottom_color): + """ + Set the Format bottom_color property. + + Args: + bottom_color: Color string. No default. + + Returns: + Nothing. + + """ + self.bottom_color = self._get_color(bottom_color) + + def set_diag_type(self, diag_type=1): + """ + Set the Format diag_type property. + + Args: + diag_type: Default is 1, border type 1. + + Returns: + Nothing. + + """ + self.diag_type = diag_type + + def set_left(self, left=1): + """ + Set the Format left property. + + Args: + left: Default is 1, border type 1. + + Returns: + Nothing. + + """ + self.left = left + + def set_left_color(self, left_color): + """ + Set the Format left_color property. + + Args: + left_color: Color string. No default. + + Returns: + Nothing. + + """ + self.left_color = self._get_color(left_color) + + def set_right(self, right=1): + """ + Set the Format right property. + + Args: + right: Default is 1, border type 1. + + Returns: + Nothing. + + """ + self.right = right + + def set_right_color(self, right_color): + """ + Set the Format right_color property. + + Args: + right_color: Color string. No default. + + Returns: + Nothing. + + """ + self.right_color = self._get_color(right_color) + + def set_top(self, top=1): + """ + Set the Format top property. + + Args: + top: Default is 1, border type 1. + + Returns: + Nothing. + + """ + self.top = top + + def set_top_color(self, top_color): + """ + Set the Format top_color property. + + Args: + top_color: Color string. No default. + + Returns: + Nothing. + + """ + self.top_color = self._get_color(top_color) + + def set_diag_color(self, diag_color): + """ + Set the Format diag_color property. + + Args: + diag_color: Color string. No default. + + Returns: + Nothing. + + """ + self.diag_color = self._get_color(diag_color) + + def set_diag_border(self, diag_border=1): + """ + Set the Format diag_border property. + + Args: + diag_border: Default is 1, border type 1. + + Returns: + Nothing. + + """ + self.diag_border = diag_border + + def set_quote_prefix(self, quote_prefix=True): + """ + Set the Format quote prefix property. + + Args: + quote_prefix: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.quote_prefix = quote_prefix + + def set_checkbox(self, checkbox=True): + """ + Set the Format property to show a checkbox in a cell. + + This format property can be used with a cell that contains a boolean + value to display it as a checkbox. This property isn't required very + often and it is generally easier to create a checkbox using the + ``worksheet.insert_checkbox()`` method. + + Args: + checkbox: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.checkbox = checkbox + + ########################################################################### + # + # Internal Format properties. These aren't documented since they are + # either only used internally or else are unlikely to be set by the user. + # + ########################################################################### + + def set_has_font(self, has_font=True): + """ + Set the property to indicate the format has a font. + + Args: + has_font: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.has_font = has_font + + def set_has_fill(self, has_fill=True): + """ + Set the property to indicate the format has a fill. + + Args: + has_fill: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.has_fill = has_fill + + def set_font_index(self, font_index): + """ + Set the unique font index property. + + Args: + font_index: The unique font index. + + Returns: + Nothing. + + """ + self.font_index = font_index + + def set_xf_index(self, xf_index): + """ + Set the unique format index property. + + Args: + xf_index: The unique Excel format index. + + Returns: + Nothing. + + """ + self.xf_index = xf_index + + def set_dxf_index(self, dxf_index): + """ + Set the unique conditional format index property. + + Args: + dxf_index: The unique Excel conditional format index. + + Returns: + Nothing. + + """ + self.dxf_index = dxf_index + + def set_num_format_index(self, num_format_index): + """ + Set the number format_index property. + + Args: + num_format_index: The unique number format index. + + Returns: + Nothing. + + """ + self.num_format_index = num_format_index + + def set_text_h_align(self, text_h_align): + """ + Set the horizontal text alignment property. + + Args: + text_h_align: Horizontal text alignment. + + Returns: + Nothing. + + """ + self.text_h_align = text_h_align + + def set_text_v_align(self, text_v_align): + """ + Set the vertical text alignment property. + + Args: + text_h_align: Vertical text alignment. + + Returns: + Nothing. + + """ + self.text_v_align = text_v_align + + def set_reading_order(self, direction=0): + # Set the reading_order property. + """ + Set the reading order property. + + Args: + direction: Default is 0, left to right. + + Returns: + Nothing. + + """ + self.reading_order = direction + + def set_valign(self, align): + # Set vertical cell alignment. This is required by the constructor + # properties dict to differentiate between the vertical and horizontal + # properties. + """ + Set vertical cell alignment property. + + This is required by the constructor properties dict to differentiate + between the vertical and horizontal properties. + + Args: + align: Alignment property. + + Returns: + Nothing. + + """ + self.set_align(align) + + def set_font_family(self, font_family): + """ + Set the font family property. + + Args: + font_family: Font family number. + + Returns: + Nothing. + + """ + self.font_family = font_family + + def set_font_charset(self, font_charset): + """ + Set the font character set property. + + Args: + font_charset: The font character set number. + + Returns: + Nothing. + + """ + self.font_charset = font_charset + + def set_font_scheme(self, font_scheme): + """ + Set the font scheme property. + + Args: + font_scheme: The font scheme. + + Returns: + Nothing. + + """ + self.font_scheme = font_scheme + + def set_font_condense(self, font_condense): + """ + Set the font condense property. + + Args: + font_condense: The font condense property. + + Returns: + Nothing. + + """ + self.font_condense = font_condense + + def set_font_extend(self, font_extend): + """ + Set the font extend property. + + Args: + font_extend: The font extend property. + + Returns: + Nothing. + + """ + self.font_extend = font_extend + + def set_theme(self, theme): + """ + Set the theme property. + + Args: + theme: Format theme. + + Returns: + Nothing. + + """ + self.theme = theme + + def set_hyperlink(self, hyperlink=True): + """ + Set the properties for the hyperlink style. + + Args: + hyperlink: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.xf_id = 1 + self.set_underline(1) + self.set_theme(10) + self.hyperlink = hyperlink + + def set_color_indexed(self, color_index): + """ + Set the color index property. Some fundamental format properties use an + indexed color instead of a rbg or theme color. + + Args: + color_index: Generally 0 or 1. + + Returns: + Nothing. + + """ + self.color_indexed = color_index + + def set_font_only(self, font_only=True): + """ + Set property to indicate that the format is used for fonts only. + + Args: + font_only: Default is True, turns property on. + + Returns: + Nothing. + + """ + self.font_only = font_only + + ########################################################################### + # + # Private API. + # + ########################################################################### + + def _get_align_properties(self): + # pylint: disable=too-many-boolean-expressions + # Return properties for an Style xf <alignment> sub-element. + changed = 0 + align = [] + + # Check if any alignment options in the format have been changed. + if ( + self.text_h_align + or self.text_v_align + or self.indent + or self.rotation + or self.text_wrap + or self.shrink + or self.reading_order + ): + changed = 1 + else: + return changed, align + + # Indent is only allowed for some alignment properties. If it is + # defined for any other alignment or no alignment has been set then + # default to left alignment. + if ( + self.indent + and self.text_h_align != 1 + and self.text_h_align != 3 + and self.text_h_align != 7 + and self.text_v_align != 1 + and self.text_v_align != 3 + and self.text_v_align != 5 + ): + self.text_h_align = 1 + + # Check for properties that are mutually exclusive. + if self.text_wrap: + self.shrink = 0 + if self.text_h_align == 4: + self.shrink = 0 + if self.text_h_align == 5: + self.shrink = 0 + if self.text_h_align == 7: + self.shrink = 0 + if self.text_h_align != 7: + self.just_distrib = 0 + if self.indent: + self.just_distrib = 0 + + continuous = "centerContinuous" + + if self.text_h_align == 1: + align.append(("horizontal", "left")) + if self.text_h_align == 2: + align.append(("horizontal", "center")) + if self.text_h_align == 3: + align.append(("horizontal", "right")) + if self.text_h_align == 4: + align.append(("horizontal", "fill")) + if self.text_h_align == 5: + align.append(("horizontal", "justify")) + if self.text_h_align == 6: + align.append(("horizontal", continuous)) + if self.text_h_align == 7: + align.append(("horizontal", "distributed")) + + if self.just_distrib: + align.append(("justifyLastLine", 1)) + + # Property 'vertical' => 'bottom' is a default. It sets applyAlignment + # without an alignment sub-element. + if self.text_v_align == 1: + align.append(("vertical", "top")) + if self.text_v_align == 2: + align.append(("vertical", "center")) + if self.text_v_align == 4: + align.append(("vertical", "justify")) + if self.text_v_align == 5: + align.append(("vertical", "distributed")) + + if self.rotation: + align.append(("textRotation", self.rotation)) + if self.indent: + align.append(("indent", self.indent)) + + if self.text_wrap: + align.append(("wrapText", 1)) + if self.shrink: + align.append(("shrinkToFit", 1)) + + if self.reading_order == 1: + align.append(("readingOrder", 1)) + if self.reading_order == 2: + align.append(("readingOrder", 2)) + + return changed, align + + def _get_protection_properties(self): + # Return properties for an Excel XML <Protection> element. + attributes = [] + + if not self.locked: + attributes.append(("locked", 0)) + if self.hidden: + attributes.append(("hidden", 1)) + + return attributes + + def _get_format_key(self): + # Returns a unique hash key for a format. Used by Workbook. + if self._format_key is None: + self._format_key = ":".join( + str(x) + for x in ( + self._get_font_key(), + self._get_border_key(), + self._get_fill_key(), + self._get_alignment_key(), + self.num_format, + self.locked, + self.checkbox, + self.quote_prefix, + self.hidden, + ) + ) + + return self._format_key + + def _get_font_key(self): + # Returns a unique hash key for a font. Used by Workbook. + key = ":".join( + str(x) + for x in ( + self.bold, + self.font_color, + self.font_charset, + self.font_family, + self.font_outline, + self.font_script, + self.font_shadow, + self.font_strikeout, + self.font_name, + self.italic, + self.font_size, + self.underline, + self.theme, + ) + ) + + return key + + def _get_border_key(self): + # Returns a unique hash key for a border style. Used by Workbook. + key = ":".join( + str(x) + for x in ( + self.bottom, + self.bottom_color, + self.diag_border, + self.diag_color, + self.diag_type, + self.left, + self.left_color, + self.right, + self.right_color, + self.top, + self.top_color, + ) + ) + + return key + + def _get_fill_key(self): + # Returns a unique hash key for a fill style. Used by Workbook. + key = ":".join(str(x) for x in (self.pattern, self.bg_color, self.fg_color)) + + return key + + def _get_alignment_key(self): + # Returns a unique hash key for alignment formats. + + key = ":".join( + str(x) + for x in ( + self.text_h_align, + self.text_v_align, + self.indent, + self.rotation, + self.text_wrap, + self.shrink, + self.reading_order, + ) + ) + + return key + + def _get_xf_index(self): + # Returns the XF index number used by Excel to identify a format. + if self.xf_index is not None: + # Format already has an index number so return it. + return self.xf_index + + # Format doesn't have an index number so assign one. + key = self._get_format_key() + + if key in self.xf_format_indices: + # Format matches existing format with an index. + return self.xf_format_indices[key] + + # New format requiring an index. Note. +1 since Excel + # has an implicit "General" format at index 0. + index = 1 + len(self.xf_format_indices) + self.xf_format_indices[key] = index + self.xf_index = index + return index + + def _get_dxf_index(self): + # Returns the DXF index number used by Excel to identify a format. + if self.dxf_index is not None: + # Format already has an index number so return it. + return self.dxf_index + + # Format doesn't have an index number so assign one. + key = self._get_format_key() + + if key in self.dxf_format_indices: + # Format matches existing format with an index. + return self.dxf_format_indices[key] + + # New format requiring an index. + index = len(self.dxf_format_indices) + self.dxf_format_indices[key] = index + self.dxf_index = index + return index + + def _get_color(self, color): + # Used in conjunction with the set_xxx_color methods to convert a + # color name into an RGB formatted string. These colors are for + # backward compatibility with older versions of Excel. + named_colors = { + "black": "#000000", + "blue": "#0000FF", + "brown": "#800000", + "cyan": "#00FFFF", + "gray": "#808080", + "green": "#008000", + "lime": "#00FF00", + "magenta": "#FF00FF", + "navy": "#000080", + "orange": "#FF6600", + "pink": "#FF00FF", + "purple": "#800080", + "red": "#FF0000", + "silver": "#C0C0C0", + "white": "#FFFFFF", + "yellow": "#FFFF00", + "automatic": "Automatic", + } + + return named_colors.get(color, color) + + ########################################################################### + # + # XML methods. + # + ########################################################################### |