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.merge_range = 0
109 self.reading_order = 0
110 self.just_distrib = 0
111 self.color_indexed = 0
112 self.font_only = 0
114 self.quote_prefix = False
115 self.checkbox = False
117 # Set the property first.
118 if properties.get("theme_font_name"):
119 self.theme_font_name = properties["theme_font_name"]
121 # Convert properties in the constructor to method calls.
122 for key, value in properties.items():
123 getattr(self, "set_" + key)(value)
125 self._format_key = None
127 def __repr__(self) -> str:
128 """
129 Return a string representation of the Format instance.
130 """
131 return (
132 f"Format("
133 f"font_name={self.font_name!r}, "
134 f"font_size={self.font_size}, "
135 f"bold={self.bold}, "
136 f"italic={self.italic}, "
137 f"underline={self.underline}, "
138 f"font_color={self.font_color}, "
139 f"num_format={self.num_format!r}, "
140 f"text_h_align={self.text_h_align}, "
141 f"text_v_align={self.text_v_align}, "
142 f"fg_color={self.fg_color}, "
143 f"bg_color={self.bg_color}, "
144 f"pattern={self.pattern}, "
145 f"locked={self.locked}, "
146 f"hidden={self.hidden})"
147 )
149 ###########################################################################
150 #
151 # Format properties.
152 #
153 ###########################################################################
155 def set_font_name(self, font_name) -> None:
156 """
157 Set the Format font_name property such as 'Time New Roman'. The
158 default Excel font is 'Calibri'.
160 Args:
161 font_name: String with the font name. No default.
163 Returns:
164 Nothing.
166 """
167 self.font_name = font_name
169 if font_name != self.theme_font_name:
170 self.font_scheme = "none"
172 def set_font_size(self, font_size: int = 11) -> None:
173 """
174 Set the Format font_size property. The default Excel font size is 11.
176 Args:
177 font_size: Int with font size. No default.
179 Returns:
180 Nothing.
182 """
183 self.font_size = font_size
185 def set_font_color(self, font_color: Union[str, Color]) -> None:
186 """
187 Set the Format font_color property. The Excel default is black.
189 Args:
190 font_color: String with the font color. No default.
192 Returns:
193 Nothing.
195 """
196 self.font_color = Color._from_value(font_color)
198 def set_bold(self, bold: bool = True) -> None:
199 """
200 Set the Format bold property.
202 Args:
203 bold: Default is True, turns property on.
205 Returns:
206 Nothing.
208 """
209 self.bold = bold
211 def set_italic(self, italic: bool = True) -> None:
212 """
213 Set the Format italic property.
215 Args:
216 italic: Default is True, turns property on.
218 Returns:
219 Nothing.
221 """
222 self.italic = italic
224 def set_underline(self, underline: Literal[1, 2, 33, 34] = 1) -> None:
225 """
226 Set the Format underline property.
228 Args:
229 underline: Default is 1, single underline.
231 Returns:
232 Nothing.
234 """
235 self.underline = underline
237 def set_font_strikeout(self, font_strikeout: bool = True) -> None:
238 """
239 Set the Format font_strikeout property.
241 Args:
242 font_strikeout: Default is True, turns property on.
244 Returns:
245 Nothing.
247 """
248 self.font_strikeout = font_strikeout
250 def set_font_script(self, font_script: Literal[1, 2] = 1) -> None:
251 """
252 Set the Format font_script property.
254 Args:
255 font_script: Default is 1, superscript.
257 Returns:
258 Nothing.
260 """
261 self.font_script = font_script
263 def set_font_outline(self, font_outline: bool = True) -> None:
264 """
265 Set the Format font_outline property.
267 Args:
268 font_outline: Default is True, turns property on.
270 Returns:
271 Nothing.
273 """
274 self.font_outline = font_outline
276 def set_font_shadow(self, font_shadow: bool = True) -> None:
277 """
278 Set the Format font_shadow property.
280 Args:
281 font_shadow: Default is True, turns property on.
283 Returns:
284 Nothing.
286 """
287 self.font_shadow = font_shadow
289 def set_num_format(self, num_format: str) -> None:
290 """
291 Set the Format num_format property such as '#,##0'.
293 Args:
294 num_format: String representing the number format. No default.
296 Returns:
297 Nothing.
299 """
300 self.num_format = num_format
302 def set_locked(self, locked: bool = True) -> None:
303 """
304 Set the Format locked property.
306 Args:
307 locked: Default is True, turns property on.
309 Returns:
310 Nothing.
312 """
313 self.locked = locked
315 def set_hidden(self, hidden: bool = True) -> None:
316 """
317 Set the Format hidden property.
319 Args:
320 hidden: Default is True, turns property on.
322 Returns:
323 Nothing.
325 """
326 self.hidden = hidden
328 def set_align(
329 self,
330 alignment: Literal[
331 "left",
332 "centre",
333 "center",
334 "right",
335 "fill",
336 "justify",
337 "center_across",
338 "centre_across",
339 "distributed",
340 "justify_distributed",
341 "justify_distributed",
342 "top",
343 "vcentre",
344 "vcenter",
345 "bottom",
346 "vjustify",
347 "vdistributed",
348 ],
349 ) -> None:
350 """
351 Set the Format cell alignment.
353 Args:
354 alignment: String representing alignment. No default.
356 Returns:
357 Nothing.
358 """
359 alignment = alignment.lower()
361 # Set horizontal alignment properties.
362 if alignment == "left":
363 self.set_text_h_align(1)
364 if alignment == "centre":
365 self.set_text_h_align(2)
366 if alignment == "center":
367 self.set_text_h_align(2)
368 if alignment == "right":
369 self.set_text_h_align(3)
370 if alignment == "fill":
371 self.set_text_h_align(4)
372 if alignment == "justify":
373 self.set_text_h_align(5)
374 if alignment == "center_across":
375 self.set_text_h_align(6)
376 if alignment == "centre_across":
377 self.set_text_h_align(6)
378 if alignment == "distributed":
379 self.set_text_h_align(7)
380 if alignment == "justify_distributed":
381 self.set_text_h_align(7)
383 if alignment == "justify_distributed":
384 self.just_distrib = 1
386 # Set vertical alignment properties.
387 if alignment == "top":
388 self.set_text_v_align(1)
389 if alignment == "vcentre":
390 self.set_text_v_align(2)
391 if alignment == "vcenter":
392 self.set_text_v_align(2)
393 if alignment == "bottom":
394 self.set_text_v_align(3)
395 if alignment == "vjustify":
396 self.set_text_v_align(4)
397 if alignment == "vdistributed":
398 self.set_text_v_align(5)
400 def set_center_across(self, align_type: None = None) -> None:
401 # pylint: disable=unused-argument
402 """
403 Set the Format center_across property.
405 Returns:
406 Nothing.
408 """
409 self.set_text_h_align(6)
411 def set_text_wrap(self, text_wrap: bool = True) -> None:
412 """
413 Set the Format text_wrap property.
415 Args:
416 text_wrap: Default is True, turns property on.
418 Returns:
419 Nothing.
421 """
422 self.text_wrap = text_wrap
424 def set_rotation(self, rotation: int) -> None:
425 """
426 Set the Format rotation property.
428 Args:
429 rotation: Rotation angle. No default.
431 Returns:
432 Nothing.
434 """
435 rotation = int(rotation)
437 # Map user angle to Excel angle.
438 if rotation == 270:
439 rotation = 255
440 elif -90 <= rotation <= 90:
441 if rotation < 0:
442 rotation = -rotation + 90
443 else:
444 warn("Rotation rotation outside range: -90 <= angle <= 90")
445 return
447 self.rotation = rotation
449 def set_indent(self, indent: int = 1) -> None:
450 """
451 Set the Format indent property.
453 Args:
454 indent: Default is 1, first indentation level.
456 Returns:
457 Nothing.
459 """
460 self.indent = indent
462 def set_shrink(self, shrink: bool = True) -> None:
463 """
464 Set the Format shrink property.
466 Args:
467 shrink: Default is True, turns property on.
469 Returns:
470 Nothing.
472 """
473 self.shrink = shrink
475 def set_text_justlast(self, text_justlast: bool = True) -> None:
476 """
477 Set the Format text_justlast property.
479 Args:
480 text_justlast: Default is True, turns property on.
482 Returns:
483 Nothing.
485 """
486 self.text_justlast = text_justlast
488 def set_pattern(self, pattern: int = 1) -> None:
489 """
490 Set the Format pattern property.
492 Args:
493 pattern: Default is 1, solid fill.
495 Returns:
496 Nothing.
498 """
499 self.pattern = pattern
501 def set_bg_color(self, bg_color: Union[str, Color]) -> None:
502 """
503 Set the Format bg_color property.
505 Args:
506 bg_color: Background color. No default.
508 Returns:
509 Nothing.
511 """
512 self.bg_color = Color._from_value(bg_color)
514 def set_fg_color(self, fg_color: Union[str, Color]) -> None:
515 """
516 Set the Format fg_color property.
518 Args:
519 fg_color: Foreground color. No default.
521 Returns:
522 Nothing.
524 """
525 self.fg_color = Color._from_value(fg_color)
527 # set_border(style) Set cells borders to the same style
528 def set_border(self, style: int = 1) -> None:
529 """
530 Set the Format bottom property.
532 Args:
533 bottom: Default is 1, border type 1.
535 Returns:
536 Nothing.
538 """
539 self.set_bottom(style)
540 self.set_top(style)
541 self.set_left(style)
542 self.set_right(style)
544 # set_border_color(color) Set cells border to the same color
545 def set_border_color(self, color: Union[str, Color]) -> None:
546 """
547 Set the Format bottom property.
549 Args:
550 color: Color string. No default.
552 Returns:
553 Nothing.
555 """
556 self.set_bottom_color(color)
557 self.set_top_color(color)
558 self.set_left_color(color)
559 self.set_right_color(color)
561 def set_bottom(self, bottom: int = 1) -> None:
562 """
563 Set the Format bottom property.
565 Args:
566 bottom: Default is 1, border type 1.
568 Returns:
569 Nothing.
571 """
572 self.bottom = bottom
574 def set_bottom_color(self, bottom_color: Union[str, Color]) -> None:
575 """
576 Set the Format bottom_color property.
578 Args:
579 bottom_color: Color string. No default.
581 Returns:
582 Nothing.
584 """
585 self.bottom_color = Color._from_value(bottom_color)
587 def set_diag_type(self, diag_type: Literal[1, 2, 3] = 1) -> None:
588 """
589 Set the Format diag_type property.
591 Args:
592 diag_type: Default is 1, border type 1.
594 Returns:
595 Nothing.
597 """
598 self.diag_type = diag_type
600 def set_left(self, left: int = 1) -> None:
601 """
602 Set the Format left property.
604 Args:
605 left: Default is 1, border type 1.
607 Returns:
608 Nothing.
610 """
611 self.left = left
613 def set_left_color(self, left_color: Union[str, Color]) -> None:
614 """
615 Set the Format left_color property.
617 Args:
618 left_color: Color string. No default.
620 Returns:
621 Nothing.
623 """
624 self.left_color = Color._from_value(left_color)
626 def set_right(self, right: int = 1) -> None:
627 """
628 Set the Format right property.
630 Args:
631 right: Default is 1, border type 1.
633 Returns:
634 Nothing.
636 """
637 self.right = right
639 def set_right_color(self, right_color: Union[str, Color]) -> None:
640 """
641 Set the Format right_color property.
643 Args:
644 right_color: Color string. No default.
646 Returns:
647 Nothing.
649 """
650 self.right_color = Color._from_value(right_color)
652 def set_top(self, top: int = 1) -> None:
653 """
654 Set the Format top property.
656 Args:
657 top: Default is 1, border type 1.
659 Returns:
660 Nothing.
662 """
663 self.top = top
665 def set_top_color(self, top_color: Union[str, Color]) -> None:
666 """
667 Set the Format top_color property.
669 Args:
670 top_color: Color string. No default.
672 Returns:
673 Nothing.
675 """
676 self.top_color = Color._from_value(top_color)
678 def set_diag_color(self, diag_color: Union[str, Color]) -> None:
679 """
680 Set the Format diag_color property.
682 Args:
683 diag_color: Color string. No default.
685 Returns:
686 Nothing.
688 """
689 self.diag_color = Color._from_value(diag_color)
691 def set_diag_border(self, diag_border: int = 1) -> None:
692 """
693 Set the Format diag_border property.
695 Args:
696 diag_border: Default is 1, border type 1.
698 Returns:
699 Nothing.
701 """
702 self.diag_border = diag_border
704 def set_quote_prefix(self, quote_prefix: bool = True) -> None:
705 """
706 Set the Format quote prefix property.
708 Args:
709 quote_prefix: Default is True, turns property on.
711 Returns:
712 Nothing.
714 """
715 self.quote_prefix = quote_prefix
717 def set_checkbox(self, checkbox: bool = True) -> None:
718 """
719 Set the Format property to show a checkbox in a cell.
721 This format property can be used with a cell that contains a boolean
722 value to display it as a checkbox. This property isn't required very
723 often and it is generally easier to create a checkbox using the
724 ``worksheet.insert_checkbox()`` method.
726 Args:
727 checkbox: Default is True, turns property on.
729 Returns:
730 Nothing.
732 """
733 self.checkbox = checkbox
735 ###########################################################################
736 #
737 # Internal Format properties. These aren't documented since they are
738 # either only used internally or else are unlikely to be set by the user.
739 #
740 ###########################################################################
742 def set_has_font(self, has_font: bool = True) -> None:
743 """
744 Set the property to indicate the format has a font.
746 Args:
747 has_font: Default is True, turns property on.
749 Returns:
750 Nothing.
752 """
753 self.has_font = has_font
755 def set_has_fill(self, has_fill: bool = True) -> None:
756 """
757 Set the property to indicate the format has a fill.
759 Args:
760 has_fill: Default is True, turns property on.
762 Returns:
763 Nothing.
765 """
766 self.has_fill = has_fill
768 def set_font_index(self, font_index: int) -> None:
769 """
770 Set the unique font index property.
772 Args:
773 font_index: The unique font index.
775 Returns:
776 Nothing.
778 """
779 self.font_index = font_index
781 def set_xf_index(self, xf_index: int) -> None:
782 """
783 Set the unique format index property.
785 Args:
786 xf_index: The unique Excel format index.
788 Returns:
789 Nothing.
791 """
792 self.xf_index = xf_index
794 def set_dxf_index(self, dxf_index: int) -> None:
795 """
796 Set the unique conditional format index property.
798 Args:
799 dxf_index: The unique Excel conditional format index.
801 Returns:
802 Nothing.
804 """
805 self.dxf_index = dxf_index
807 def set_num_format_index(self, num_format_index: int) -> None:
808 """
809 Set the number format_index property.
811 Args:
812 num_format_index: The unique number format index.
814 Returns:
815 Nothing.
817 """
818 self.num_format_index = num_format_index
820 def set_text_h_align(self, text_h_align: int) -> None:
821 """
822 Set the horizontal text alignment property.
824 Args:
825 text_h_align: Horizontal text alignment.
827 Returns:
828 Nothing.
830 """
831 self.text_h_align = text_h_align
833 def set_text_v_align(self, text_v_align: int) -> None:
834 """
835 Set the vertical text alignment property.
837 Args:
838 text_h_align: Vertical text alignment.
840 Returns:
841 Nothing.
843 """
844 self.text_v_align = text_v_align
846 def set_reading_order(self, direction: int = 0) -> None:
847 # Set the reading_order property.
848 """
849 Set the reading order property.
851 Args:
852 direction: Default is 0, left to right.
854 Returns:
855 Nothing.
857 """
858 self.reading_order = direction
860 def set_valign(
861 self,
862 align: Literal[
863 "left",
864 "centre",
865 "center",
866 "right",
867 "fill",
868 "justify",
869 "center_across",
870 "centre_across",
871 "distributed",
872 "justify_distributed",
873 "justify_distributed",
874 "top",
875 "vcentre",
876 "vcenter",
877 "bottom",
878 "vjustify",
879 "vdistributed",
880 ],
881 ) -> None:
882 # Set vertical cell alignment. This is required by the constructor
883 # properties dict to differentiate between the vertical and horizontal
884 # properties.
885 """
886 Set vertical cell alignment property.
888 This is required by the constructor properties dict to differentiate
889 between the vertical and horizontal properties.
891 Args:
892 align: Alignment property.
894 Returns:
895 Nothing.
897 """
898 self.set_align(align)
900 def set_font_family(self, font_family: int) -> None:
901 """
902 Set the font family property.
904 Args:
905 font_family: Font family number.
907 Returns:
908 Nothing.
910 """
911 self.font_family = font_family
913 def set_font_charset(self, font_charset: int) -> None:
914 """
915 Set the font character set property.
917 Args:
918 font_charset: The font character set number.
920 Returns:
921 Nothing.
923 """
924 self.font_charset = font_charset
926 def set_font_scheme(self, font_scheme: str) -> None:
927 """
928 Set the font scheme property to indicate if the font is tied to the
929 workbook theme
931 This method can be used to indicate that a font is part of a themeThe
932 theme must also contain the appropriate font for this to work.
934 This method can also be used to indicate that a font is not part of a
935 theme, for example, if you wished to use a "Calibri" font that is not
936 connected to the theme and which will not change if the theme is
937 changed.
940 The allowed values are:
942 - "minor": This is used to indicate a theme font that is used for body
943 text.
944 - "major": This is used to indicate a theme font that is used for
945 headings.
946 - "none": This is used to indicate a font that is not part of the theme.
948 Args:
949 font_scheme: The font scheme.
951 Returns:
952 Nothing.
954 """
955 self.font_scheme = font_scheme
957 def set_font_condense(self, font_condense: int) -> None:
958 """
959 Set the font condense property.
961 Args:
962 font_condense: The font condense property.
964 Returns:
965 Nothing.
967 """
968 self.font_condense = font_condense
970 def set_font_extend(self, font_extend: int) -> None:
971 """
972 Set the font extend property.
974 Args:
975 font_extend: The font extend property.
977 Returns:
978 Nothing.
980 """
981 self.font_extend = font_extend
983 def set_theme(self, theme: int) -> None:
984 """
985 Set the theme property.
987 Args:
988 theme: Format theme.
990 Returns:
991 Nothing.
993 """
994 self.theme = theme
996 def set_hyperlink(self, hyperlink: bool = True) -> None:
997 """
998 Set the properties for the hyperlink style.
1000 Args:
1001 hyperlink: Default is True, turns property on.
1003 Returns:
1004 Nothing.
1006 """
1007 self.xf_id = 1
1008 self.set_underline(1)
1009 self.set_theme(10)
1010 self.hyperlink = hyperlink
1011 self.font_scheme = "none"
1013 def set_color_indexed(self, color_index: Literal[0, 1]) -> None:
1014 """
1015 Set the color index property. Some fundamental format properties use an
1016 indexed color instead of a rbg or theme color.
1018 Args:
1019 color_index: Generally 0 or 1.
1021 Returns:
1022 Nothing.
1024 """
1025 self.color_indexed = color_index
1027 def set_font_only(self, font_only: bool = True) -> None:
1028 """
1029 Set property to indicate that the format is used for fonts only.
1031 Args:
1032 font_only: Default is True, turns property on.
1034 Returns:
1035 Nothing.
1037 """
1038 self.font_only = font_only
1040 def set_theme_font_name(self, font_name) -> None:
1041 """
1042 Set the Format font name use for the theme.
1044 Args:
1045 font_name: String with the font name. No default.
1047 Returns:
1048 Nothing.
1050 """
1051 self.theme_font_name = font_name
1053 # Compatibility methods. These versions of the method names were added in an
1054 # initial version for compatibility testing with Excel::Writer::XLSX and
1055 # leaked out into production code. They are deprecated and will be removed
1056 # in a future after a suitable deprecation period.
1057 def set_font(self, font_name: str) -> None:
1058 """Deprecated: Use set_font_name() instead."""
1059 self.set_font_name(font_name)
1061 def set_size(self, font_size: int) -> None:
1062 """Deprecated: Use set_font_size() instead."""
1063 self.set_font_size(font_size)
1065 def set_color(self, font_color: Union[Color, str]) -> None:
1066 """Deprecated: Use set_font_color() instead."""
1067 self.set_font_color(font_color)
1069 ###########################################################################
1070 #
1071 # Private API.
1072 #
1073 ###########################################################################
1075 def _get_align_properties(self):
1076 # pylint: disable=too-many-boolean-expressions
1077 # Return properties for an Style xf <alignment> sub-element.
1078 changed = 0
1079 align = []
1081 # Check if any alignment options in the format have been changed.
1082 if (
1083 self.text_h_align
1084 or self.text_v_align
1085 or self.indent
1086 or self.rotation
1087 or self.text_wrap
1088 or self.shrink
1089 or self.reading_order
1090 ):
1091 changed = 1
1092 else:
1093 return changed, align
1095 # Indent is only allowed for some alignment properties. If it is
1096 # defined for any other alignment or no alignment has been set then
1097 # default to left alignment.
1098 if (
1099 self.indent
1100 and self.text_h_align != 1
1101 and self.text_h_align != 3
1102 and self.text_h_align != 7
1103 and self.text_v_align != 1
1104 and self.text_v_align != 3
1105 and self.text_v_align != 5
1106 ):
1107 self.text_h_align = 1
1109 # Check for properties that are mutually exclusive.
1110 if self.text_wrap:
1111 self.shrink = 0
1112 if self.text_h_align == 4:
1113 self.shrink = 0
1114 if self.text_h_align == 5:
1115 self.shrink = 0
1116 if self.text_h_align == 7:
1117 self.shrink = 0
1118 if self.text_h_align != 7:
1119 self.just_distrib = 0
1120 if self.indent:
1121 self.just_distrib = 0
1123 continuous = "centerContinuous"
1125 if self.text_h_align == 1:
1126 align.append(("horizontal", "left"))
1127 if self.text_h_align == 2:
1128 align.append(("horizontal", "center"))
1129 if self.text_h_align == 3:
1130 align.append(("horizontal", "right"))
1131 if self.text_h_align == 4:
1132 align.append(("horizontal", "fill"))
1133 if self.text_h_align == 5:
1134 align.append(("horizontal", "justify"))
1135 if self.text_h_align == 6:
1136 align.append(("horizontal", continuous))
1137 if self.text_h_align == 7:
1138 align.append(("horizontal", "distributed"))
1140 if self.just_distrib:
1141 align.append(("justifyLastLine", 1))
1143 # Property 'vertical' => 'bottom' is a default. It sets applyAlignment
1144 # without an alignment sub-element.
1145 if self.text_v_align == 1:
1146 align.append(("vertical", "top"))
1147 if self.text_v_align == 2:
1148 align.append(("vertical", "center"))
1149 if self.text_v_align == 4:
1150 align.append(("vertical", "justify"))
1151 if self.text_v_align == 5:
1152 align.append(("vertical", "distributed"))
1154 if self.rotation:
1155 align.append(("textRotation", self.rotation))
1156 if self.indent:
1157 align.append(("indent", self.indent))
1159 if self.text_wrap:
1160 align.append(("wrapText", 1))
1161 if self.shrink:
1162 align.append(("shrinkToFit", 1))
1164 if self.reading_order == 1:
1165 align.append(("readingOrder", 1))
1166 if self.reading_order == 2:
1167 align.append(("readingOrder", 2))
1169 return changed, align
1171 def _get_protection_properties(self):
1172 # Return properties for an Excel XML <Protection> element.
1173 attributes = []
1175 if not self.locked:
1176 attributes.append(("locked", 0))
1177 if self.hidden:
1178 attributes.append(("hidden", 1))
1180 return attributes
1182 def _get_format_key(self):
1183 # Returns a unique hash key for a format. Used by Workbook.
1184 if self._format_key is None:
1185 self._format_key = ":".join(
1186 str(x)
1187 for x in (
1188 self._get_font_key(),
1189 self._get_border_key(),
1190 self._get_fill_key(),
1191 self._get_alignment_key(),
1192 self.num_format,
1193 self.locked,
1194 self.checkbox,
1195 self.quote_prefix,
1196 self.hidden,
1197 )
1198 )
1200 return self._format_key
1202 def _get_font_key(self):
1203 # Returns a unique hash key for a font. Used by Workbook.
1204 key = ":".join(
1205 str(x)
1206 for x in (
1207 self.bold,
1208 self.font_color,
1209 self.font_charset,
1210 self.font_family,
1211 self.font_outline,
1212 self.font_script,
1213 self.font_shadow,
1214 self.font_strikeout,
1215 self.font_name,
1216 self.italic,
1217 self.font_size,
1218 self.underline,
1219 self.theme,
1220 )
1221 )
1223 return key
1225 def _get_border_key(self):
1226 # Returns a unique hash key for a border style. Used by Workbook.
1227 key = ":".join(
1228 str(x)
1229 for x in (
1230 self.bottom,
1231 self.bottom_color,
1232 self.diag_border,
1233 self.diag_color,
1234 self.diag_type,
1235 self.left,
1236 self.left_color,
1237 self.right,
1238 self.right_color,
1239 self.top,
1240 self.top_color,
1241 )
1242 )
1244 return key
1246 def _get_fill_key(self):
1247 # Returns a unique hash key for a fill style. Used by Workbook.
1248 key = ":".join(str(x) for x in (self.pattern, self.bg_color, self.fg_color))
1250 return key
1252 def _get_alignment_key(self):
1253 # Returns a unique hash key for alignment formats.
1255 key = ":".join(
1256 str(x)
1257 for x in (
1258 self.text_h_align,
1259 self.text_v_align,
1260 self.indent,
1261 self.rotation,
1262 self.text_wrap,
1263 self.shrink,
1264 self.reading_order,
1265 )
1266 )
1268 return key
1270 def _get_xf_index(self):
1271 # Returns the XF index number used by Excel to identify a format.
1272 if self.xf_index is not None:
1273 # Format already has an index number so return it.
1274 return self.xf_index
1276 # Format doesn't have an index number so assign one.
1277 key = self._get_format_key()
1279 if key in self.xf_format_indices:
1280 # Format matches existing format with an index.
1281 return self.xf_format_indices[key]
1283 # New format requiring an index. Note. +1 since Excel
1284 # has an implicit "General" format at index 0.
1285 index = 1 + len(self.xf_format_indices)
1286 self.xf_format_indices[key] = index
1287 self.xf_index = index
1288 return index
1290 def _get_dxf_index(self):
1291 # Returns the DXF index number used by Excel to identify a format.
1292 if self.dxf_index is not None:
1293 # Format already has an index number so return it.
1294 return self.dxf_index
1296 # Format doesn't have an index number so assign one.
1297 key = self._get_format_key()
1299 if key in self.dxf_format_indices:
1300 # Format matches existing format with an index.
1301 return self.dxf_format_indices[key]
1303 # New format requiring an index.
1304 index = len(self.dxf_format_indices)
1305 self.dxf_format_indices[key] = index
1306 self.dxf_index = index
1307 return index
1309 ###########################################################################
1310 #
1311 # XML methods.
1312 #
1313 ###########################################################################