Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/xlsxwriter/format.py: 49%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1###############################################################################
2#
3# Format - A class for writing the Excel XLSX Worksheet file.
4#
5# SPDX-License-Identifier: BSD-2-Clause
6#
7# Copyright (c) 2013-2026, John McNamara, jmcnamara@cpan.org
8#
10# Package imports.
11from typing import Literal, Union
12from warnings import warn
14from xlsxwriter import xmlwriter
15from xlsxwriter.color import Color
18class Format(xmlwriter.XMLwriter):
19 """
20 A class for writing the Excel XLSX Format file.
23 """
25 ###########################################################################
26 #
27 # Public API.
28 #
29 ###########################################################################
31 def __init__(self, properties=None, xf_indices=None, dxf_indices=None) -> None:
32 """
33 Constructor.
35 """
36 if properties is None:
37 properties = {}
39 super().__init__()
41 self.xf_format_indices = xf_indices
42 self.dxf_format_indices = dxf_indices
43 self.xf_index = None
44 self.dxf_index = None
46 self.num_format = "General"
47 self.num_format_index = 0
48 self.font_index = 0
49 self.has_font = False
50 self.has_dxf_font = False
52 self.bold = 0
53 self.underline = 0
54 self.italic = 0
55 self.font_name = "Calibri"
56 self.theme_font_name = "Calibri"
57 self.font_size = 11
58 self.font_color = None
59 self.font_strikeout = 0
60 self.font_outline = 0
61 self.font_shadow = 0
62 self.font_script = 0
63 self.font_family = 2
64 self.font_charset = 0
65 self.font_scheme = "minor"
66 self.font_condense = 0
67 self.font_extend = 0
68 self.theme = 0
69 self.hyperlink = False
70 self.xf_id = 0
72 self.hidden = 0
73 self.locked = 1
75 self.text_h_align = 0
76 self.text_wrap = 0
77 self.text_v_align = 0
78 self.text_justlast = 0
79 self.rotation = 0
81 self.fg_color = None
82 self.bg_color = None
83 self.pattern = 0
84 self.has_fill = False
85 self.has_dxf_fill = False
86 self.fill_index = 0
87 self.fill_count = 0
89 self.border_index = 0
90 self.has_border = False
91 self.has_dxf_border = False
92 self.border_count = 0
94 self.bottom = 0
95 self.bottom_color = None
96 self.diag_border = 0
97 self.diag_color = None
98 self.diag_type = 0
99 self.left = 0
100 self.left_color = None
101 self.right = 0
102 self.right_color = None
103 self.top = 0
104 self.top_color = None
106 self.indent = 0
107 self.shrink = 0
108 self.reading_order = 0
109 self.just_distrib = 0
110 self.color_indexed = 0
111 self.font_only = 0
113 self.quote_prefix = False
114 self.checkbox = False
116 # Set the property first.
117 if properties.get("theme_font_name"):
118 self.theme_font_name = properties["theme_font_name"]
120 # Convert properties in the constructor to method calls.
121 for key, value in properties.items():
122 getattr(self, "set_" + key)(value)
124 self._format_key = None
126 def __repr__(self) -> str:
127 """
128 Return a string representation of the Format instance.
129 """
130 return (
131 f"Format("
132 f"font_name={self.font_name!r}, "
133 f"font_size={self.font_size}, "
134 f"bold={self.bold}, "
135 f"italic={self.italic}, "
136 f"underline={self.underline}, "
137 f"font_color={self.font_color}, "
138 f"num_format={self.num_format!r}, "
139 f"text_h_align={self.text_h_align}, "
140 f"text_v_align={self.text_v_align}, "
141 f"fg_color={self.fg_color}, "
142 f"bg_color={self.bg_color}, "
143 f"pattern={self.pattern}, "
144 f"locked={self.locked}, "
145 f"hidden={self.hidden})"
146 )
148 ###########################################################################
149 #
150 # Format properties.
151 #
152 ###########################################################################
154 def set_font_name(self, font_name) -> None:
155 """
156 Set the Format font_name property such as 'Time New Roman'. The
157 default Excel font is 'Calibri'.
159 Args:
160 font_name: String with the font name. No default.
162 Returns:
163 Nothing.
165 """
166 self.font_name = font_name
168 if font_name != self.theme_font_name:
169 self.font_scheme = "none"
171 def set_font_size(self, font_size: int = 11) -> None:
172 """
173 Set the Format font_size property. The default Excel font size is 11.
175 Args:
176 font_size: Int with font size. No default.
178 Returns:
179 Nothing.
181 """
182 self.font_size = font_size
184 def set_font_color(self, font_color: Union[str, Color]) -> None:
185 """
186 Set the Format font_color property. The Excel default is black.
188 Args:
189 font_color: String with the font color. No default.
191 Returns:
192 Nothing.
194 """
195 self.font_color = Color._from_value(font_color)
197 def set_bold(self, bold: bool = True) -> None:
198 """
199 Set the Format bold property.
201 Args:
202 bold: Default is True, turns property on.
204 Returns:
205 Nothing.
207 """
208 self.bold = bold
210 def set_italic(self, italic: bool = True) -> None:
211 """
212 Set the Format italic property.
214 Args:
215 italic: Default is True, turns property on.
217 Returns:
218 Nothing.
220 """
221 self.italic = italic
223 def set_underline(self, underline: Literal[1, 2, 33, 34] = 1) -> None:
224 """
225 Set the Format underline property.
227 Args:
228 underline: Default is 1, single underline.
230 Returns:
231 Nothing.
233 """
234 self.underline = underline
236 def set_font_strikeout(self, font_strikeout: bool = True) -> None:
237 """
238 Set the Format font_strikeout property.
240 Args:
241 font_strikeout: Default is True, turns property on.
243 Returns:
244 Nothing.
246 """
247 self.font_strikeout = font_strikeout
249 def set_font_script(self, font_script: Literal[1, 2] = 1) -> None:
250 """
251 Set the Format font_script property.
253 Args:
254 font_script: Default is 1, superscript.
256 Returns:
257 Nothing.
259 """
260 self.font_script = font_script
262 def set_font_outline(self, font_outline: bool = True) -> None:
263 """
264 Set the Format font_outline property.
266 Args:
267 font_outline: Default is True, turns property on.
269 Returns:
270 Nothing.
272 """
273 self.font_outline = font_outline
275 def set_font_shadow(self, font_shadow: bool = True) -> None:
276 """
277 Set the Format font_shadow property.
279 Args:
280 font_shadow: Default is True, turns property on.
282 Returns:
283 Nothing.
285 """
286 self.font_shadow = font_shadow
288 def set_num_format(self, num_format: str) -> None:
289 """
290 Set the Format num_format property such as '#,##0'.
292 Args:
293 num_format: String representing the number format. No default.
295 Returns:
296 Nothing.
298 """
299 self.num_format = num_format
301 def set_locked(self, locked: bool = True) -> None:
302 """
303 Set the Format locked property.
305 Args:
306 locked: Default is True, turns property on.
308 Returns:
309 Nothing.
311 """
312 self.locked = locked
314 def set_hidden(self, hidden: bool = True) -> None:
315 """
316 Set the Format hidden property.
318 Args:
319 hidden: Default is True, turns property on.
321 Returns:
322 Nothing.
324 """
325 self.hidden = hidden
327 def set_align(
328 self,
329 alignment: Literal[
330 "left",
331 "centre",
332 "center",
333 "right",
334 "fill",
335 "justify",
336 "center_across",
337 "centre_across",
338 "distributed",
339 "justify_distributed",
340 "top",
341 "vcentre",
342 "vcenter",
343 "bottom",
344 "vjustify",
345 "vdistributed",
346 ],
347 ) -> None:
348 """
349 Set the Format cell alignment.
351 Args:
352 alignment: String representing alignment. No default.
354 Returns:
355 Nothing.
356 """
357 alignment = alignment.lower()
359 # Set horizontal alignment properties.
360 if alignment == "left":
361 self.set_text_h_align(1)
362 if alignment == "centre":
363 self.set_text_h_align(2)
364 if alignment == "center":
365 self.set_text_h_align(2)
366 if alignment == "right":
367 self.set_text_h_align(3)
368 if alignment == "fill":
369 self.set_text_h_align(4)
370 if alignment == "justify":
371 self.set_text_h_align(5)
372 if alignment == "center_across":
373 self.set_text_h_align(6)
374 if alignment == "centre_across":
375 self.set_text_h_align(6)
376 if alignment == "distributed":
377 self.set_text_h_align(7)
378 if alignment == "justify_distributed":
379 self.set_text_h_align(7)
381 if alignment == "justify_distributed":
382 self.just_distrib = 1
384 # Set vertical alignment properties.
385 if alignment == "top":
386 self.set_text_v_align(1)
387 if alignment == "vcentre":
388 self.set_text_v_align(2)
389 if alignment == "vcenter":
390 self.set_text_v_align(2)
391 if alignment == "bottom":
392 self.set_text_v_align(3)
393 if alignment == "vjustify":
394 self.set_text_v_align(4)
395 if alignment == "vdistributed":
396 self.set_text_v_align(5)
398 def set_center_across(self, align_type: None = None) -> None:
399 # pylint: disable=unused-argument
400 """
401 Set the Format center_across property.
403 Returns:
404 Nothing.
406 """
407 self.set_text_h_align(6)
409 def set_text_wrap(self, text_wrap: bool = True) -> None:
410 """
411 Set the Format text_wrap property.
413 Args:
414 text_wrap: Default is True, turns property on.
416 Returns:
417 Nothing.
419 """
420 self.text_wrap = text_wrap
422 def set_rotation(self, rotation: int) -> None:
423 """
424 Set the Format rotation property.
426 Args:
427 rotation: Rotation angle. No default.
429 Returns:
430 Nothing.
432 """
433 rotation = int(rotation)
435 # Map user angle to Excel angle.
436 if rotation == 270:
437 rotation = 255
438 elif -90 <= rotation <= 90:
439 if rotation < 0:
440 rotation = -rotation + 90
441 else:
442 warn("Rotation rotation outside range: -90 <= angle <= 90")
443 return
445 self.rotation = rotation
447 def set_indent(self, indent: int = 1) -> None:
448 """
449 Set the Format indent property.
451 Args:
452 indent: Default is 1, first indentation level.
454 Returns:
455 Nothing.
457 """
458 self.indent = indent
460 def set_shrink(self, shrink: bool = True) -> None:
461 """
462 Set the Format shrink property.
464 Args:
465 shrink: Default is True, turns property on.
467 Returns:
468 Nothing.
470 """
471 self.shrink = shrink
473 def set_text_justlast(self, text_justlast: bool = True) -> None:
474 """
475 Set the Format text_justlast property.
477 Args:
478 text_justlast: Default is True, turns property on.
480 Returns:
481 Nothing.
483 """
484 self.text_justlast = text_justlast
486 def set_pattern(self, pattern: int = 1) -> None:
487 """
488 Set the Format pattern property.
490 Args:
491 pattern: Default is 1, solid fill.
493 Returns:
494 Nothing.
496 """
497 self.pattern = pattern
499 def set_bg_color(self, bg_color: Union[str, Color]) -> None:
500 """
501 Set the Format bg_color property.
503 Args:
504 bg_color: Background color. No default.
506 Returns:
507 Nothing.
509 """
510 self.bg_color = Color._from_value(bg_color)
512 def set_fg_color(self, fg_color: Union[str, Color]) -> None:
513 """
514 Set the Format fg_color property.
516 Args:
517 fg_color: Foreground color. No default.
519 Returns:
520 Nothing.
522 """
523 self.fg_color = Color._from_value(fg_color)
525 # set_border(style) Set cells borders to the same style
526 def set_border(self, style: int = 1) -> None:
527 """
528 Set the Format bottom property.
530 Args:
531 bottom: Default is 1, border type 1.
533 Returns:
534 Nothing.
536 """
537 self.set_bottom(style)
538 self.set_top(style)
539 self.set_left(style)
540 self.set_right(style)
542 # set_border_color(color) Set cells border to the same color
543 def set_border_color(self, color: Union[str, Color]) -> None:
544 """
545 Set the Format bottom property.
547 Args:
548 color: Color string. No default.
550 Returns:
551 Nothing.
553 """
554 self.set_bottom_color(color)
555 self.set_top_color(color)
556 self.set_left_color(color)
557 self.set_right_color(color)
559 def set_bottom(self, bottom: int = 1) -> None:
560 """
561 Set the Format bottom property.
563 Args:
564 bottom: Default is 1, border type 1.
566 Returns:
567 Nothing.
569 """
570 self.bottom = bottom
572 def set_bottom_color(self, bottom_color: Union[str, Color]) -> None:
573 """
574 Set the Format bottom_color property.
576 Args:
577 bottom_color: Color string. No default.
579 Returns:
580 Nothing.
582 """
583 self.bottom_color = Color._from_value(bottom_color)
585 def set_diag_type(self, diag_type: Literal[1, 2, 3] = 1) -> None:
586 """
587 Set the Format diag_type property.
589 Args:
590 diag_type: Default is 1, border type 1.
592 Returns:
593 Nothing.
595 """
596 self.diag_type = diag_type
598 def set_left(self, left: int = 1) -> None:
599 """
600 Set the Format left property.
602 Args:
603 left: Default is 1, border type 1.
605 Returns:
606 Nothing.
608 """
609 self.left = left
611 def set_left_color(self, left_color: Union[str, Color]) -> None:
612 """
613 Set the Format left_color property.
615 Args:
616 left_color: Color string. No default.
618 Returns:
619 Nothing.
621 """
622 self.left_color = Color._from_value(left_color)
624 def set_right(self, right: int = 1) -> None:
625 """
626 Set the Format right property.
628 Args:
629 right: Default is 1, border type 1.
631 Returns:
632 Nothing.
634 """
635 self.right = right
637 def set_right_color(self, right_color: Union[str, Color]) -> None:
638 """
639 Set the Format right_color property.
641 Args:
642 right_color: Color string. No default.
644 Returns:
645 Nothing.
647 """
648 self.right_color = Color._from_value(right_color)
650 def set_top(self, top: int = 1) -> None:
651 """
652 Set the Format top property.
654 Args:
655 top: Default is 1, border type 1.
657 Returns:
658 Nothing.
660 """
661 self.top = top
663 def set_top_color(self, top_color: Union[str, Color]) -> None:
664 """
665 Set the Format top_color property.
667 Args:
668 top_color: Color string. No default.
670 Returns:
671 Nothing.
673 """
674 self.top_color = Color._from_value(top_color)
676 def set_diag_color(self, diag_color: Union[str, Color]) -> None:
677 """
678 Set the Format diag_color property.
680 Args:
681 diag_color: Color string. No default.
683 Returns:
684 Nothing.
686 """
687 self.diag_color = Color._from_value(diag_color)
689 def set_diag_border(self, diag_border: int = 1) -> None:
690 """
691 Set the Format diag_border property.
693 Args:
694 diag_border: Default is 1, border type 1.
696 Returns:
697 Nothing.
699 """
700 self.diag_border = diag_border
702 def set_quote_prefix(self, quote_prefix: bool = True) -> None:
703 """
704 Set the Format quote prefix property.
706 Args:
707 quote_prefix: Default is True, turns property on.
709 Returns:
710 Nothing.
712 """
713 self.quote_prefix = quote_prefix
715 def set_checkbox(self, checkbox: bool = True) -> None:
716 """
717 Set the Format property to show a checkbox in a cell.
719 This format property can be used with a cell that contains a boolean
720 value to display it as a checkbox. This property isn't required very
721 often and it is generally easier to create a checkbox using the
722 ``worksheet.insert_checkbox()`` method.
724 Args:
725 checkbox: Default is True, turns property on.
727 Returns:
728 Nothing.
730 """
731 self.checkbox = checkbox
733 ###########################################################################
734 #
735 # Internal Format properties. These aren't documented since they are
736 # either only used internally or else are unlikely to be set by the user.
737 #
738 ###########################################################################
740 def set_has_font(self, has_font: bool = True) -> None:
741 """
742 Set the property to indicate the format has a font.
744 Args:
745 has_font: Default is True, turns property on.
747 Returns:
748 Nothing.
750 """
751 self.has_font = has_font
753 def set_has_fill(self, has_fill: bool = True) -> None:
754 """
755 Set the property to indicate the format has a fill.
757 Args:
758 has_fill: Default is True, turns property on.
760 Returns:
761 Nothing.
763 """
764 self.has_fill = has_fill
766 def set_font_index(self, font_index: int) -> None:
767 """
768 Set the unique font index property.
770 Args:
771 font_index: The unique font index.
773 Returns:
774 Nothing.
776 """
777 self.font_index = font_index
779 def set_xf_index(self, xf_index: int) -> None:
780 """
781 Set the unique format index property.
783 Args:
784 xf_index: The unique Excel format index.
786 Returns:
787 Nothing.
789 """
790 self.xf_index = xf_index
792 def set_dxf_index(self, dxf_index: int) -> None:
793 """
794 Set the unique conditional format index property.
796 Args:
797 dxf_index: The unique Excel conditional format index.
799 Returns:
800 Nothing.
802 """
803 self.dxf_index = dxf_index
805 def set_num_format_index(self, num_format_index: int) -> None:
806 """
807 Set the number format_index property.
809 Args:
810 num_format_index: The unique number format index.
812 Returns:
813 Nothing.
815 """
816 self.num_format_index = num_format_index
818 def set_text_h_align(self, text_h_align: int) -> None:
819 """
820 Set the horizontal text alignment property.
822 Args:
823 text_h_align: Horizontal text alignment.
825 Returns:
826 Nothing.
828 """
829 self.text_h_align = text_h_align
831 def set_text_v_align(self, text_v_align: int) -> None:
832 """
833 Set the vertical text alignment property.
835 Args:
836 text_h_align: Vertical text alignment.
838 Returns:
839 Nothing.
841 """
842 self.text_v_align = text_v_align
844 def set_reading_order(self, direction: int = 0) -> None:
845 # Set the reading_order property.
846 """
847 Set the reading order property.
849 Args:
850 direction: Default is 0, left to right.
852 Returns:
853 Nothing.
855 """
856 self.reading_order = direction
858 def set_valign(
859 self,
860 align: Literal[
861 "left",
862 "centre",
863 "center",
864 "right",
865 "fill",
866 "justify",
867 "center_across",
868 "centre_across",
869 "distributed",
870 "justify_distributed",
871 "top",
872 "vcentre",
873 "vcenter",
874 "bottom",
875 "vjustify",
876 "vdistributed",
877 ],
878 ) -> None:
879 # Set vertical cell alignment. This is required by the constructor
880 # properties dict to differentiate between the vertical and horizontal
881 # properties.
882 """
883 Set vertical cell alignment property.
885 This is required by the constructor properties dict to differentiate
886 between the vertical and horizontal properties.
888 Args:
889 align: Alignment property.
891 Returns:
892 Nothing.
894 """
895 self.set_align(align)
897 def set_font_family(self, font_family: int) -> None:
898 """
899 Set the font family property.
901 Args:
902 font_family: Font family number.
904 Returns:
905 Nothing.
907 """
908 self.font_family = font_family
910 def set_font_charset(self, font_charset: int) -> None:
911 """
912 Set the font character set property.
914 Args:
915 font_charset: The font character set number.
917 Returns:
918 Nothing.
920 """
921 self.font_charset = font_charset
923 def set_font_scheme(self, font_scheme: str) -> None:
924 """
925 Set the font scheme property to indicate if the font is tied to the
926 workbook theme
928 This method can be used to indicate that a font is part of a theme. The
929 theme must also contain the appropriate font for this to work.
931 This method can also be used to indicate that a font is not part of a
932 theme, for example, if you wished to use a "Calibri" font that is not
933 connected to the theme and which will not change if the theme is
934 changed.
937 The allowed values are:
939 - "minor": This is used to indicate a theme font that is used for body
940 text.
941 - "major": This is used to indicate a theme font that is used for
942 headings.
943 - "none": This is used to indicate a font that is not part of the theme.
945 Args:
946 font_scheme: The font scheme.
948 Returns:
949 Nothing.
951 """
952 self.font_scheme = font_scheme
954 def set_font_condense(self, font_condense: int) -> None:
955 """
956 Set the font condense property.
958 Args:
959 font_condense: The font condense property.
961 Returns:
962 Nothing.
964 """
965 self.font_condense = font_condense
967 def set_font_extend(self, font_extend: int) -> None:
968 """
969 Set the font extend property.
971 Args:
972 font_extend: The font extend property.
974 Returns:
975 Nothing.
977 """
978 self.font_extend = font_extend
980 def set_theme(self, theme: int) -> None:
981 """
982 Set the theme property.
984 Args:
985 theme: Format theme.
987 Returns:
988 Nothing.
990 """
991 self.theme = theme
993 def set_hyperlink(self, hyperlink: bool = True) -> None:
994 """
995 Set the properties for the hyperlink style.
997 Args:
998 hyperlink: Default is True, turns property on.
1000 Returns:
1001 Nothing.
1003 """
1004 self.xf_id = 1
1005 self.set_underline(1)
1006 self.set_theme(10)
1007 self.hyperlink = hyperlink
1008 self.font_scheme = "none"
1010 def set_color_indexed(self, color_index: Literal[0, 1]) -> None:
1011 """
1012 Set the color index property. Some fundamental format properties use an
1013 indexed color instead of a rbg or theme color.
1015 Args:
1016 color_index: Generally 0 or 1.
1018 Returns:
1019 Nothing.
1021 """
1022 self.color_indexed = color_index
1024 def set_font_only(self, font_only: bool = True) -> None:
1025 """
1026 Set property to indicate that the format is used for fonts only.
1028 Args:
1029 font_only: Default is True, turns property on.
1031 Returns:
1032 Nothing.
1034 """
1035 self.font_only = font_only
1037 def set_theme_font_name(self, font_name) -> None:
1038 """
1039 Set the Format font name use for the theme.
1041 Args:
1042 font_name: String with the font name. No default.
1044 Returns:
1045 Nothing.
1047 """
1048 self.theme_font_name = font_name
1050 # Compatibility methods. These versions of the method names were added in an
1051 # initial version for compatibility testing with Excel::Writer::XLSX and
1052 # leaked out into production code. They are deprecated and will be removed
1053 # in a future after a suitable deprecation period.
1054 def set_font(self, font_name: str) -> None:
1055 """Deprecated: Use set_font_name() instead."""
1056 self.set_font_name(font_name)
1058 def set_size(self, font_size: int) -> None:
1059 """Deprecated: Use set_font_size() instead."""
1060 self.set_font_size(font_size)
1062 def set_color(self, font_color: Union[Color, str]) -> None:
1063 """Deprecated: Use set_font_color() instead."""
1064 self.set_font_color(font_color)
1066 ###########################################################################
1067 #
1068 # Private API.
1069 #
1070 ###########################################################################
1072 def _get_align_properties(self):
1073 # pylint: disable=too-many-boolean-expressions
1074 # Return properties for an Style xf <alignment> sub-element.
1075 changed = 0
1076 align = []
1078 # Check if any alignment options in the format have been changed.
1079 if (
1080 self.text_h_align
1081 or self.text_v_align
1082 or self.indent
1083 or self.rotation
1084 or self.text_wrap
1085 or self.shrink
1086 or self.reading_order
1087 ):
1088 changed = 1
1089 else:
1090 return changed, align
1092 # Indent is only allowed for some alignment properties. If it is
1093 # defined for any other alignment or no alignment has been set then
1094 # default to left alignment.
1095 if (
1096 self.indent
1097 and self.text_h_align != 1
1098 and self.text_h_align != 3
1099 and self.text_h_align != 7
1100 and self.text_v_align != 1
1101 and self.text_v_align != 3
1102 and self.text_v_align != 5
1103 ):
1104 self.text_h_align = 1
1106 # Check for properties that are mutually exclusive.
1107 if self.text_wrap:
1108 self.shrink = 0
1109 if self.text_h_align == 4:
1110 self.shrink = 0
1111 if self.text_h_align == 5:
1112 self.shrink = 0
1113 if self.text_h_align == 7:
1114 self.shrink = 0
1115 if self.text_h_align != 7:
1116 self.just_distrib = 0
1117 if self.indent:
1118 self.just_distrib = 0
1120 continuous = "centerContinuous"
1122 if self.text_h_align == 1:
1123 align.append(("horizontal", "left"))
1124 if self.text_h_align == 2:
1125 align.append(("horizontal", "center"))
1126 if self.text_h_align == 3:
1127 align.append(("horizontal", "right"))
1128 if self.text_h_align == 4:
1129 align.append(("horizontal", "fill"))
1130 if self.text_h_align == 5:
1131 align.append(("horizontal", "justify"))
1132 if self.text_h_align == 6:
1133 align.append(("horizontal", continuous))
1134 if self.text_h_align == 7:
1135 align.append(("horizontal", "distributed"))
1137 if self.just_distrib:
1138 align.append(("justifyLastLine", 1))
1140 # Property 'vertical' => 'bottom' is a default. It sets applyAlignment
1141 # without an alignment sub-element.
1142 if self.text_v_align == 1:
1143 align.append(("vertical", "top"))
1144 if self.text_v_align == 2:
1145 align.append(("vertical", "center"))
1146 if self.text_v_align == 4:
1147 align.append(("vertical", "justify"))
1148 if self.text_v_align == 5:
1149 align.append(("vertical", "distributed"))
1151 if self.rotation:
1152 align.append(("textRotation", self.rotation))
1153 if self.indent:
1154 align.append(("indent", self.indent))
1156 if self.text_wrap:
1157 align.append(("wrapText", 1))
1158 if self.shrink:
1159 align.append(("shrinkToFit", 1))
1161 if self.reading_order == 1:
1162 align.append(("readingOrder", 1))
1163 if self.reading_order == 2:
1164 align.append(("readingOrder", 2))
1166 return changed, align
1168 def _get_protection_properties(self):
1169 # Return properties for an Excel XML <Protection> element.
1170 attributes = []
1172 if not self.locked:
1173 attributes.append(("locked", 0))
1174 if self.hidden:
1175 attributes.append(("hidden", 1))
1177 return attributes
1179 def _get_format_key(self):
1180 # Returns a unique hash key for a format. Used by Workbook.
1181 if self._format_key is None:
1182 self._format_key = ":".join(
1183 str(x)
1184 for x in (
1185 self._get_font_key(),
1186 self._get_border_key(),
1187 self._get_fill_key(),
1188 self._get_alignment_key(),
1189 self.num_format,
1190 self.locked,
1191 self.checkbox,
1192 self.quote_prefix,
1193 self.hidden,
1194 )
1195 )
1197 return self._format_key
1199 def _get_font_key(self):
1200 # Returns a unique hash key for a font. Used by Workbook.
1201 key = ":".join(
1202 str(x)
1203 for x in (
1204 self.bold,
1205 self.font_color,
1206 self.font_charset,
1207 self.font_family,
1208 self.font_outline,
1209 self.font_script,
1210 self.font_shadow,
1211 self.font_strikeout,
1212 self.font_name,
1213 self.italic,
1214 self.font_size,
1215 self.underline,
1216 self.theme,
1217 )
1218 )
1220 return key
1222 def _get_border_key(self):
1223 # Returns a unique hash key for a border style. Used by Workbook.
1224 key = ":".join(
1225 str(x)
1226 for x in (
1227 self.bottom,
1228 self.bottom_color,
1229 self.diag_border,
1230 self.diag_color,
1231 self.diag_type,
1232 self.left,
1233 self.left_color,
1234 self.right,
1235 self.right_color,
1236 self.top,
1237 self.top_color,
1238 )
1239 )
1241 return key
1243 def _get_fill_key(self):
1244 # Returns a unique hash key for a fill style. Used by Workbook.
1245 key = ":".join(str(x) for x in (self.pattern, self.bg_color, self.fg_color))
1247 return key
1249 def _get_alignment_key(self):
1250 # Returns a unique hash key for alignment formats.
1252 key = ":".join(
1253 str(x)
1254 for x in (
1255 self.text_h_align,
1256 self.text_v_align,
1257 self.indent,
1258 self.rotation,
1259 self.text_wrap,
1260 self.shrink,
1261 self.reading_order,
1262 )
1263 )
1265 return key
1267 def _get_xf_index(self):
1268 # Returns the XF index number used by Excel to identify a format.
1269 if self.xf_index is not None:
1270 # Format already has an index number so return it.
1271 return self.xf_index
1273 # Format doesn't have an index number so assign one.
1274 key = self._get_format_key()
1276 if key in self.xf_format_indices:
1277 # Format matches existing format with an index.
1278 return self.xf_format_indices[key]
1280 # New format requiring an index. Note. +1 since Excel
1281 # has an implicit "General" format at index 0.
1282 index = 1 + len(self.xf_format_indices)
1283 self.xf_format_indices[key] = index
1284 self.xf_index = index
1285 return index
1287 def _get_dxf_index(self):
1288 # Returns the DXF index number used by Excel to identify a format.
1289 if self.dxf_index is not None:
1290 # Format already has an index number so return it.
1291 return self.dxf_index
1293 # Format doesn't have an index number so assign one.
1294 key = self._get_format_key()
1296 if key in self.dxf_format_indices:
1297 # Format matches existing format with an index.
1298 return self.dxf_format_indices[key]
1300 # New format requiring an index.
1301 index = len(self.dxf_format_indices)
1302 self.dxf_format_indices[key] = index
1303 self.dxf_index = index
1304 return index
1306 ###########################################################################
1307 #
1308 # XML methods.
1309 #
1310 ###########################################################################