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-2025, 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 "justify_distributed",
341 "top",
342 "vcentre",
343 "vcenter",
344 "bottom",
345 "vjustify",
346 "vdistributed",
347 ],
348 ) -> None:
349 """
350 Set the Format cell alignment.
352 Args:
353 alignment: String representing alignment. No default.
355 Returns:
356 Nothing.
357 """
358 alignment = alignment.lower()
360 # Set horizontal alignment properties.
361 if alignment == "left":
362 self.set_text_h_align(1)
363 if alignment == "centre":
364 self.set_text_h_align(2)
365 if alignment == "center":
366 self.set_text_h_align(2)
367 if alignment == "right":
368 self.set_text_h_align(3)
369 if alignment == "fill":
370 self.set_text_h_align(4)
371 if alignment == "justify":
372 self.set_text_h_align(5)
373 if alignment == "center_across":
374 self.set_text_h_align(6)
375 if alignment == "centre_across":
376 self.set_text_h_align(6)
377 if alignment == "distributed":
378 self.set_text_h_align(7)
379 if alignment == "justify_distributed":
380 self.set_text_h_align(7)
382 if alignment == "justify_distributed":
383 self.just_distrib = 1
385 # Set vertical alignment properties.
386 if alignment == "top":
387 self.set_text_v_align(1)
388 if alignment == "vcentre":
389 self.set_text_v_align(2)
390 if alignment == "vcenter":
391 self.set_text_v_align(2)
392 if alignment == "bottom":
393 self.set_text_v_align(3)
394 if alignment == "vjustify":
395 self.set_text_v_align(4)
396 if alignment == "vdistributed":
397 self.set_text_v_align(5)
399 def set_center_across(self, align_type: None = None) -> None:
400 # pylint: disable=unused-argument
401 """
402 Set the Format center_across property.
404 Returns:
405 Nothing.
407 """
408 self.set_text_h_align(6)
410 def set_text_wrap(self, text_wrap: bool = True) -> None:
411 """
412 Set the Format text_wrap property.
414 Args:
415 text_wrap: Default is True, turns property on.
417 Returns:
418 Nothing.
420 """
421 self.text_wrap = text_wrap
423 def set_rotation(self, rotation: int) -> None:
424 """
425 Set the Format rotation property.
427 Args:
428 rotation: Rotation angle. No default.
430 Returns:
431 Nothing.
433 """
434 rotation = int(rotation)
436 # Map user angle to Excel angle.
437 if rotation == 270:
438 rotation = 255
439 elif -90 <= rotation <= 90:
440 if rotation < 0:
441 rotation = -rotation + 90
442 else:
443 warn("Rotation rotation outside range: -90 <= angle <= 90")
444 return
446 self.rotation = rotation
448 def set_indent(self, indent: int = 1) -> None:
449 """
450 Set the Format indent property.
452 Args:
453 indent: Default is 1, first indentation level.
455 Returns:
456 Nothing.
458 """
459 self.indent = indent
461 def set_shrink(self, shrink: bool = True) -> None:
462 """
463 Set the Format shrink property.
465 Args:
466 shrink: Default is True, turns property on.
468 Returns:
469 Nothing.
471 """
472 self.shrink = shrink
474 def set_text_justlast(self, text_justlast: bool = True) -> None:
475 """
476 Set the Format text_justlast property.
478 Args:
479 text_justlast: Default is True, turns property on.
481 Returns:
482 Nothing.
484 """
485 self.text_justlast = text_justlast
487 def set_pattern(self, pattern: int = 1) -> None:
488 """
489 Set the Format pattern property.
491 Args:
492 pattern: Default is 1, solid fill.
494 Returns:
495 Nothing.
497 """
498 self.pattern = pattern
500 def set_bg_color(self, bg_color: Union[str, Color]) -> None:
501 """
502 Set the Format bg_color property.
504 Args:
505 bg_color: Background color. No default.
507 Returns:
508 Nothing.
510 """
511 self.bg_color = Color._from_value(bg_color)
513 def set_fg_color(self, fg_color: Union[str, Color]) -> None:
514 """
515 Set the Format fg_color property.
517 Args:
518 fg_color: Foreground color. No default.
520 Returns:
521 Nothing.
523 """
524 self.fg_color = Color._from_value(fg_color)
526 # set_border(style) Set cells borders to the same style
527 def set_border(self, style: int = 1) -> None:
528 """
529 Set the Format bottom property.
531 Args:
532 bottom: Default is 1, border type 1.
534 Returns:
535 Nothing.
537 """
538 self.set_bottom(style)
539 self.set_top(style)
540 self.set_left(style)
541 self.set_right(style)
543 # set_border_color(color) Set cells border to the same color
544 def set_border_color(self, color: Union[str, Color]) -> None:
545 """
546 Set the Format bottom property.
548 Args:
549 color: Color string. No default.
551 Returns:
552 Nothing.
554 """
555 self.set_bottom_color(color)
556 self.set_top_color(color)
557 self.set_left_color(color)
558 self.set_right_color(color)
560 def set_bottom(self, bottom: int = 1) -> None:
561 """
562 Set the Format bottom property.
564 Args:
565 bottom: Default is 1, border type 1.
567 Returns:
568 Nothing.
570 """
571 self.bottom = bottom
573 def set_bottom_color(self, bottom_color: Union[str, Color]) -> None:
574 """
575 Set the Format bottom_color property.
577 Args:
578 bottom_color: Color string. No default.
580 Returns:
581 Nothing.
583 """
584 self.bottom_color = Color._from_value(bottom_color)
586 def set_diag_type(self, diag_type: Literal[1, 2, 3] = 1) -> None:
587 """
588 Set the Format diag_type property.
590 Args:
591 diag_type: Default is 1, border type 1.
593 Returns:
594 Nothing.
596 """
597 self.diag_type = diag_type
599 def set_left(self, left: int = 1) -> None:
600 """
601 Set the Format left property.
603 Args:
604 left: Default is 1, border type 1.
606 Returns:
607 Nothing.
609 """
610 self.left = left
612 def set_left_color(self, left_color: Union[str, Color]) -> None:
613 """
614 Set the Format left_color property.
616 Args:
617 left_color: Color string. No default.
619 Returns:
620 Nothing.
622 """
623 self.left_color = Color._from_value(left_color)
625 def set_right(self, right: int = 1) -> None:
626 """
627 Set the Format right property.
629 Args:
630 right: Default is 1, border type 1.
632 Returns:
633 Nothing.
635 """
636 self.right = right
638 def set_right_color(self, right_color: Union[str, Color]) -> None:
639 """
640 Set the Format right_color property.
642 Args:
643 right_color: Color string. No default.
645 Returns:
646 Nothing.
648 """
649 self.right_color = Color._from_value(right_color)
651 def set_top(self, top: int = 1) -> None:
652 """
653 Set the Format top property.
655 Args:
656 top: Default is 1, border type 1.
658 Returns:
659 Nothing.
661 """
662 self.top = top
664 def set_top_color(self, top_color: Union[str, Color]) -> None:
665 """
666 Set the Format top_color property.
668 Args:
669 top_color: Color string. No default.
671 Returns:
672 Nothing.
674 """
675 self.top_color = Color._from_value(top_color)
677 def set_diag_color(self, diag_color: Union[str, Color]) -> None:
678 """
679 Set the Format diag_color property.
681 Args:
682 diag_color: Color string. No default.
684 Returns:
685 Nothing.
687 """
688 self.diag_color = Color._from_value(diag_color)
690 def set_diag_border(self, diag_border: int = 1) -> None:
691 """
692 Set the Format diag_border property.
694 Args:
695 diag_border: Default is 1, border type 1.
697 Returns:
698 Nothing.
700 """
701 self.diag_border = diag_border
703 def set_quote_prefix(self, quote_prefix: bool = True) -> None:
704 """
705 Set the Format quote prefix property.
707 Args:
708 quote_prefix: Default is True, turns property on.
710 Returns:
711 Nothing.
713 """
714 self.quote_prefix = quote_prefix
716 def set_checkbox(self, checkbox: bool = True) -> None:
717 """
718 Set the Format property to show a checkbox in a cell.
720 This format property can be used with a cell that contains a boolean
721 value to display it as a checkbox. This property isn't required very
722 often and it is generally easier to create a checkbox using the
723 ``worksheet.insert_checkbox()`` method.
725 Args:
726 checkbox: Default is True, turns property on.
728 Returns:
729 Nothing.
731 """
732 self.checkbox = checkbox
734 ###########################################################################
735 #
736 # Internal Format properties. These aren't documented since they are
737 # either only used internally or else are unlikely to be set by the user.
738 #
739 ###########################################################################
741 def set_has_font(self, has_font: bool = True) -> None:
742 """
743 Set the property to indicate the format has a font.
745 Args:
746 has_font: Default is True, turns property on.
748 Returns:
749 Nothing.
751 """
752 self.has_font = has_font
754 def set_has_fill(self, has_fill: bool = True) -> None:
755 """
756 Set the property to indicate the format has a fill.
758 Args:
759 has_fill: Default is True, turns property on.
761 Returns:
762 Nothing.
764 """
765 self.has_fill = has_fill
767 def set_font_index(self, font_index: int) -> None:
768 """
769 Set the unique font index property.
771 Args:
772 font_index: The unique font index.
774 Returns:
775 Nothing.
777 """
778 self.font_index = font_index
780 def set_xf_index(self, xf_index: int) -> None:
781 """
782 Set the unique format index property.
784 Args:
785 xf_index: The unique Excel format index.
787 Returns:
788 Nothing.
790 """
791 self.xf_index = xf_index
793 def set_dxf_index(self, dxf_index: int) -> None:
794 """
795 Set the unique conditional format index property.
797 Args:
798 dxf_index: The unique Excel conditional format index.
800 Returns:
801 Nothing.
803 """
804 self.dxf_index = dxf_index
806 def set_num_format_index(self, num_format_index: int) -> None:
807 """
808 Set the number format_index property.
810 Args:
811 num_format_index: The unique number format index.
813 Returns:
814 Nothing.
816 """
817 self.num_format_index = num_format_index
819 def set_text_h_align(self, text_h_align: int) -> None:
820 """
821 Set the horizontal text alignment property.
823 Args:
824 text_h_align: Horizontal text alignment.
826 Returns:
827 Nothing.
829 """
830 self.text_h_align = text_h_align
832 def set_text_v_align(self, text_v_align: int) -> None:
833 """
834 Set the vertical text alignment property.
836 Args:
837 text_h_align: Vertical text alignment.
839 Returns:
840 Nothing.
842 """
843 self.text_v_align = text_v_align
845 def set_reading_order(self, direction: int = 0) -> None:
846 # Set the reading_order property.
847 """
848 Set the reading order property.
850 Args:
851 direction: Default is 0, left to right.
853 Returns:
854 Nothing.
856 """
857 self.reading_order = direction
859 def set_valign(
860 self,
861 align: Literal[
862 "left",
863 "centre",
864 "center",
865 "right",
866 "fill",
867 "justify",
868 "center_across",
869 "centre_across",
870 "distributed",
871 "justify_distributed",
872 "justify_distributed",
873 "top",
874 "vcentre",
875 "vcenter",
876 "bottom",
877 "vjustify",
878 "vdistributed",
879 ],
880 ) -> None:
881 # Set vertical cell alignment. This is required by the constructor
882 # properties dict to differentiate between the vertical and horizontal
883 # properties.
884 """
885 Set vertical cell alignment property.
887 This is required by the constructor properties dict to differentiate
888 between the vertical and horizontal properties.
890 Args:
891 align: Alignment property.
893 Returns:
894 Nothing.
896 """
897 self.set_align(align)
899 def set_font_family(self, font_family: int) -> None:
900 """
901 Set the font family property.
903 Args:
904 font_family: Font family number.
906 Returns:
907 Nothing.
909 """
910 self.font_family = font_family
912 def set_font_charset(self, font_charset: int) -> None:
913 """
914 Set the font character set property.
916 Args:
917 font_charset: The font character set number.
919 Returns:
920 Nothing.
922 """
923 self.font_charset = font_charset
925 def set_font_scheme(self, font_scheme: str) -> None:
926 """
927 Set the font scheme property to indicate if the font is tied to the
928 workbook theme
930 This method can be used to indicate that a font is part of a theme. The
931 theme must also contain the appropriate font for this to work.
933 This method can also be used to indicate that a font is not part of a
934 theme, for example, if you wished to use a "Calibri" font that is not
935 connected to the theme and which will not change if the theme is
936 changed.
939 The allowed values are:
941 - "minor": This is used to indicate a theme font that is used for body
942 text.
943 - "major": This is used to indicate a theme font that is used for
944 headings.
945 - "none": This is used to indicate a font that is not part of the theme.
947 Args:
948 font_scheme: The font scheme.
950 Returns:
951 Nothing.
953 """
954 self.font_scheme = font_scheme
956 def set_font_condense(self, font_condense: int) -> None:
957 """
958 Set the font condense property.
960 Args:
961 font_condense: The font condense property.
963 Returns:
964 Nothing.
966 """
967 self.font_condense = font_condense
969 def set_font_extend(self, font_extend: int) -> None:
970 """
971 Set the font extend property.
973 Args:
974 font_extend: The font extend property.
976 Returns:
977 Nothing.
979 """
980 self.font_extend = font_extend
982 def set_theme(self, theme: int) -> None:
983 """
984 Set the theme property.
986 Args:
987 theme: Format theme.
989 Returns:
990 Nothing.
992 """
993 self.theme = theme
995 def set_hyperlink(self, hyperlink: bool = True) -> None:
996 """
997 Set the properties for the hyperlink style.
999 Args:
1000 hyperlink: Default is True, turns property on.
1002 Returns:
1003 Nothing.
1005 """
1006 self.xf_id = 1
1007 self.set_underline(1)
1008 self.set_theme(10)
1009 self.hyperlink = hyperlink
1010 self.font_scheme = "none"
1012 def set_color_indexed(self, color_index: Literal[0, 1]) -> None:
1013 """
1014 Set the color index property. Some fundamental format properties use an
1015 indexed color instead of a rbg or theme color.
1017 Args:
1018 color_index: Generally 0 or 1.
1020 Returns:
1021 Nothing.
1023 """
1024 self.color_indexed = color_index
1026 def set_font_only(self, font_only: bool = True) -> None:
1027 """
1028 Set property to indicate that the format is used for fonts only.
1030 Args:
1031 font_only: Default is True, turns property on.
1033 Returns:
1034 Nothing.
1036 """
1037 self.font_only = font_only
1039 def set_theme_font_name(self, font_name) -> None:
1040 """
1041 Set the Format font name use for the theme.
1043 Args:
1044 font_name: String with the font name. No default.
1046 Returns:
1047 Nothing.
1049 """
1050 self.theme_font_name = font_name
1052 # Compatibility methods. These versions of the method names were added in an
1053 # initial version for compatibility testing with Excel::Writer::XLSX and
1054 # leaked out into production code. They are deprecated and will be removed
1055 # in a future after a suitable deprecation period.
1056 def set_font(self, font_name: str) -> None:
1057 """Deprecated: Use set_font_name() instead."""
1058 self.set_font_name(font_name)
1060 def set_size(self, font_size: int) -> None:
1061 """Deprecated: Use set_font_size() instead."""
1062 self.set_font_size(font_size)
1064 def set_color(self, font_color: Union[Color, str]) -> None:
1065 """Deprecated: Use set_font_color() instead."""
1066 self.set_font_color(font_color)
1068 ###########################################################################
1069 #
1070 # Private API.
1071 #
1072 ###########################################################################
1074 def _get_align_properties(self):
1075 # pylint: disable=too-many-boolean-expressions
1076 # Return properties for an Style xf <alignment> sub-element.
1077 changed = 0
1078 align = []
1080 # Check if any alignment options in the format have been changed.
1081 if (
1082 self.text_h_align
1083 or self.text_v_align
1084 or self.indent
1085 or self.rotation
1086 or self.text_wrap
1087 or self.shrink
1088 or self.reading_order
1089 ):
1090 changed = 1
1091 else:
1092 return changed, align
1094 # Indent is only allowed for some alignment properties. If it is
1095 # defined for any other alignment or no alignment has been set then
1096 # default to left alignment.
1097 if (
1098 self.indent
1099 and self.text_h_align != 1
1100 and self.text_h_align != 3
1101 and self.text_h_align != 7
1102 and self.text_v_align != 1
1103 and self.text_v_align != 3
1104 and self.text_v_align != 5
1105 ):
1106 self.text_h_align = 1
1108 # Check for properties that are mutually exclusive.
1109 if self.text_wrap:
1110 self.shrink = 0
1111 if self.text_h_align == 4:
1112 self.shrink = 0
1113 if self.text_h_align == 5:
1114 self.shrink = 0
1115 if self.text_h_align == 7:
1116 self.shrink = 0
1117 if self.text_h_align != 7:
1118 self.just_distrib = 0
1119 if self.indent:
1120 self.just_distrib = 0
1122 continuous = "centerContinuous"
1124 if self.text_h_align == 1:
1125 align.append(("horizontal", "left"))
1126 if self.text_h_align == 2:
1127 align.append(("horizontal", "center"))
1128 if self.text_h_align == 3:
1129 align.append(("horizontal", "right"))
1130 if self.text_h_align == 4:
1131 align.append(("horizontal", "fill"))
1132 if self.text_h_align == 5:
1133 align.append(("horizontal", "justify"))
1134 if self.text_h_align == 6:
1135 align.append(("horizontal", continuous))
1136 if self.text_h_align == 7:
1137 align.append(("horizontal", "distributed"))
1139 if self.just_distrib:
1140 align.append(("justifyLastLine", 1))
1142 # Property 'vertical' => 'bottom' is a default. It sets applyAlignment
1143 # without an alignment sub-element.
1144 if self.text_v_align == 1:
1145 align.append(("vertical", "top"))
1146 if self.text_v_align == 2:
1147 align.append(("vertical", "center"))
1148 if self.text_v_align == 4:
1149 align.append(("vertical", "justify"))
1150 if self.text_v_align == 5:
1151 align.append(("vertical", "distributed"))
1153 if self.rotation:
1154 align.append(("textRotation", self.rotation))
1155 if self.indent:
1156 align.append(("indent", self.indent))
1158 if self.text_wrap:
1159 align.append(("wrapText", 1))
1160 if self.shrink:
1161 align.append(("shrinkToFit", 1))
1163 if self.reading_order == 1:
1164 align.append(("readingOrder", 1))
1165 if self.reading_order == 2:
1166 align.append(("readingOrder", 2))
1168 return changed, align
1170 def _get_protection_properties(self):
1171 # Return properties for an Excel XML <Protection> element.
1172 attributes = []
1174 if not self.locked:
1175 attributes.append(("locked", 0))
1176 if self.hidden:
1177 attributes.append(("hidden", 1))
1179 return attributes
1181 def _get_format_key(self):
1182 # Returns a unique hash key for a format. Used by Workbook.
1183 if self._format_key is None:
1184 self._format_key = ":".join(
1185 str(x)
1186 for x in (
1187 self._get_font_key(),
1188 self._get_border_key(),
1189 self._get_fill_key(),
1190 self._get_alignment_key(),
1191 self.num_format,
1192 self.locked,
1193 self.checkbox,
1194 self.quote_prefix,
1195 self.hidden,
1196 )
1197 )
1199 return self._format_key
1201 def _get_font_key(self):
1202 # Returns a unique hash key for a font. Used by Workbook.
1203 key = ":".join(
1204 str(x)
1205 for x in (
1206 self.bold,
1207 self.font_color,
1208 self.font_charset,
1209 self.font_family,
1210 self.font_outline,
1211 self.font_script,
1212 self.font_shadow,
1213 self.font_strikeout,
1214 self.font_name,
1215 self.italic,
1216 self.font_size,
1217 self.underline,
1218 self.theme,
1219 )
1220 )
1222 return key
1224 def _get_border_key(self):
1225 # Returns a unique hash key for a border style. Used by Workbook.
1226 key = ":".join(
1227 str(x)
1228 for x in (
1229 self.bottom,
1230 self.bottom_color,
1231 self.diag_border,
1232 self.diag_color,
1233 self.diag_type,
1234 self.left,
1235 self.left_color,
1236 self.right,
1237 self.right_color,
1238 self.top,
1239 self.top_color,
1240 )
1241 )
1243 return key
1245 def _get_fill_key(self):
1246 # Returns a unique hash key for a fill style. Used by Workbook.
1247 key = ":".join(str(x) for x in (self.pattern, self.bg_color, self.fg_color))
1249 return key
1251 def _get_alignment_key(self):
1252 # Returns a unique hash key for alignment formats.
1254 key = ":".join(
1255 str(x)
1256 for x in (
1257 self.text_h_align,
1258 self.text_v_align,
1259 self.indent,
1260 self.rotation,
1261 self.text_wrap,
1262 self.shrink,
1263 self.reading_order,
1264 )
1265 )
1267 return key
1269 def _get_xf_index(self):
1270 # Returns the XF index number used by Excel to identify a format.
1271 if self.xf_index is not None:
1272 # Format already has an index number so return it.
1273 return self.xf_index
1275 # Format doesn't have an index number so assign one.
1276 key = self._get_format_key()
1278 if key in self.xf_format_indices:
1279 # Format matches existing format with an index.
1280 return self.xf_format_indices[key]
1282 # New format requiring an index. Note. +1 since Excel
1283 # has an implicit "General" format at index 0.
1284 index = 1 + len(self.xf_format_indices)
1285 self.xf_format_indices[key] = index
1286 self.xf_index = index
1287 return index
1289 def _get_dxf_index(self):
1290 # Returns the DXF index number used by Excel to identify a format.
1291 if self.dxf_index is not None:
1292 # Format already has an index number so return it.
1293 return self.dxf_index
1295 # Format doesn't have an index number so assign one.
1296 key = self._get_format_key()
1298 if key in self.dxf_format_indices:
1299 # Format matches existing format with an index.
1300 return self.dxf_format_indices[key]
1302 # New format requiring an index.
1303 index = len(self.dxf_format_indices)
1304 self.dxf_format_indices[key] = index
1305 self.dxf_index = index
1306 return index
1308 ###########################################################################
1309 #
1310 # XML methods.
1311 #
1312 ###########################################################################