Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/xlwt/Style.py: 38%
291 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1from __future__ import print_function
2# -*- coding: windows-1252 -*-
4from . import Formatting
5from .BIFFRecords import NumberFormatRecord, XFRecord, StyleRecord
6from .compat import basestring, xrange
8FIRST_USER_DEFINED_NUM_FORMAT_IDX = 164
10class XFStyle(object):
12 def __init__(self):
13 self.num_format_str = 'General'
14 self.font = Formatting.Font()
15 self.alignment = Formatting.Alignment()
16 self.borders = Formatting.Borders()
17 self.pattern = Formatting.Pattern()
18 self.protection = Formatting.Protection()
20default_style = XFStyle()
22class StyleCollection(object):
23 _std_num_fmt_list = [
24 'general',
25 '0',
26 '0.00',
27 '#,##0',
28 '#,##0.00',
29 '"$"#,##0_);("$"#,##0)',
30 '"$"#,##0_);[Red]("$"#,##0)',
31 '"$"#,##0.00_);("$"#,##0.00)',
32 '"$"#,##0.00_);[Red]("$"#,##0.00)',
33 '0%',
34 '0.00%',
35 '0.00E+00',
36 '# ?/?',
37 '# ??/??',
38 'M/D/YY',
39 'D-MMM-YY',
40 'D-MMM',
41 'MMM-YY',
42 'h:mm AM/PM',
43 'h:mm:ss AM/PM',
44 'h:mm',
45 'h:mm:ss',
46 'M/D/YY h:mm',
47 '_(#,##0_);(#,##0)',
48 '_(#,##0_);[Red](#,##0)',
49 '_(#,##0.00_);(#,##0.00)',
50 '_(#,##0.00_);[Red](#,##0.00)',
51 '_("$"* #,##0_);_("$"* (#,##0);_("$"* "-"_);_(@_)',
52 '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)',
53 '_("$"* #,##0.00_);_("$"* (#,##0.00);_("$"* "-"??_);_(@_)',
54 '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)',
55 'mm:ss',
56 '[h]:mm:ss',
57 'mm:ss.0',
58 '##0.0E+0',
59 '@'
60 ]
62 def __init__(self, style_compression=0):
63 self.style_compression = style_compression
64 self.stats = [0, 0, 0, 0, 0, 0]
65 self._font_id2x = {}
66 self._font_x2id = {}
67 self._font_val2x = {}
69 for x in (0, 1, 2, 3, 5): # The font with index 4 is omitted in all BIFF versions
70 font = Formatting.Font()
71 search_key = font._search_key()
72 self._font_id2x[font] = x
73 self._font_x2id[x] = font
74 self._font_val2x[search_key] = x
76 self._xf_id2x = {}
77 self._xf_x2id = {}
78 self._xf_val2x = {}
80 self._num_formats = {}
81 for fmtidx, fmtstr in zip(range(0, 23), StyleCollection._std_num_fmt_list[0:23]):
82 self._num_formats[fmtstr] = fmtidx
83 for fmtidx, fmtstr in zip(range(37, 50), StyleCollection._std_num_fmt_list[23:]):
84 self._num_formats[fmtstr] = fmtidx
86 self.default_style = XFStyle()
87 self._default_xf = self._add_style(self.default_style)[0]
89 def add(self, style):
90 if style == None:
91 return 0x10
92 return self._add_style(style)[1]
94 def _add_style(self, style):
95 num_format_str = style.num_format_str
96 if num_format_str in self._num_formats:
97 num_format_idx = self._num_formats[num_format_str]
98 else:
99 num_format_idx = (
100 FIRST_USER_DEFINED_NUM_FORMAT_IDX
101 + len(self._num_formats)
102 - len(StyleCollection._std_num_fmt_list)
103 )
104 self._num_formats[num_format_str] = num_format_idx
106 font = style.font
107 if font in self._font_id2x:
108 font_idx = self._font_id2x[font]
109 self.stats[0] += 1
110 elif self.style_compression:
111 search_key = font._search_key()
112 font_idx = self._font_val2x.get(search_key)
113 if font_idx is not None:
114 self._font_id2x[font] = font_idx
115 self.stats[1] += 1
116 else:
117 font_idx = len(self._font_x2id) + 1 # Why plus 1? Font 4 is missing
118 self._font_id2x[font] = font_idx
119 self._font_val2x[search_key] = font_idx
120 self._font_x2id[font_idx] = font
121 self.stats[2] += 1
122 else:
123 font_idx = len(self._font_id2x) + 1
124 self._font_id2x[font] = font_idx
125 self.stats[2] += 1
127 gof = (style.alignment, style.borders, style.pattern, style.protection)
128 xf = (font_idx, num_format_idx) + gof
129 if xf in self._xf_id2x:
130 xf_index = self._xf_id2x[xf]
131 self.stats[3] += 1
132 elif self.style_compression == 2:
133 xf_key = (font_idx, num_format_idx) + tuple(obj._search_key() for obj in gof)
134 xf_index = self._xf_val2x.get(xf_key)
135 if xf_index is not None:
136 self._xf_id2x[xf] = xf_index
137 self.stats[4] += 1
138 else:
139 xf_index = 0x10 + len(self._xf_x2id)
140 self._xf_id2x[xf] = xf_index
141 self._xf_val2x[xf_key] = xf_index
142 self._xf_x2id[xf_index] = xf
143 self.stats[5] += 1
144 else:
145 xf_index = 0x10 + len(self._xf_id2x)
146 self._xf_id2x[xf] = xf_index
147 self.stats[5] += 1
149 if xf_index >= 0xFFF:
150 # 12 bits allowed, 0xFFF is a sentinel value
151 raise ValueError("More than 4094 XFs (styles)")
153 return xf, xf_index
155 def add_font(self, font):
156 return self._add_font(font)
158 def _add_font(self, font):
159 if font in self._font_id2x:
160 font_idx = self._font_id2x[font]
161 self.stats[0] += 1
162 elif self.style_compression:
163 search_key = font._search_key()
164 font_idx = self._font_val2x.get(search_key)
165 if font_idx is not None:
166 self._font_id2x[font] = font_idx
167 self.stats[1] += 1
168 else:
169 font_idx = len(self._font_x2id) + 1 # Why plus 1? Font 4 is missing
170 self._font_id2x[font] = font_idx
171 self._font_val2x[search_key] = font_idx
172 self._font_x2id[font_idx] = font
173 self.stats[2] += 1
174 else:
175 font_idx = len(self._font_id2x) + 1
176 self._font_id2x[font] = font_idx
177 self.stats[2] += 1
179 return font_idx
182 def get_biff_data(self):
183 result = b''
184 result += self._all_fonts()
185 result += self._all_num_formats()
186 result += self._all_cell_styles()
187 result += self._all_styles()
188 return result
190 def _all_fonts(self):
191 result = b''
192 if self.style_compression:
193 fonts = self._font_x2id.items()
194 else:
195 fonts = [(x, o) for o, x in self._font_id2x.items()]
196 for font_idx, font in sorted(fonts):
197 result += font.get_biff_record().get()
198 return result
200 def _all_num_formats(self):
201 result = b''
202 alist = [
203 (v, k)
204 for k, v in self._num_formats.items()
205 if v >= FIRST_USER_DEFINED_NUM_FORMAT_IDX
206 ]
207 alist.sort()
208 for fmtidx, fmtstr in alist:
209 result += NumberFormatRecord(fmtidx, fmtstr).get()
210 return result
212 def _all_cell_styles(self):
213 result = b''
214 for i in range(0, 16):
215 result += XFRecord(self._default_xf, 'style').get()
216 if self.style_compression == 2:
217 styles = self._xf_x2id.items()
218 else:
219 styles = [(x, o) for o, x in self._xf_id2x.items()]
220 for xf_idx, xf in sorted(styles):
221 result += XFRecord(xf).get()
222 return result
224 def _all_styles(self):
225 return StyleRecord().get()
227# easyxf and its supporting objects ###################################
229class EasyXFException(Exception):
230 pass
232class EasyXFCallerError(EasyXFException):
233 pass
235class EasyXFAuthorError(EasyXFException):
236 pass
238class IntULim(object):
239 # If astring represents a valid unsigned integer ('123', '0xabcd', etc)
240 # and it is <= limit, return the int value; otherwise return None.
242 def __init__(self, limit):
243 self.limit = limit
245 def __call__(self, astring):
246 try:
247 value = int(astring, 0)
248 except ValueError:
249 return None
250 if not 0 <= value <= self.limit:
251 return None
252 return value
254bool_map = {
255 # Text values for all Boolean attributes
256 '1': 1, 'yes': 1, 'true': 1, 'on': 1,
257 '0': 0, 'no': 0, 'false': 0, 'off': 0,
258 }
260border_line_map = {
261 # Text values for these borders attributes:
262 # left, right, top, bottom and diag
263 'no_line': 0x00,
264 'thin': 0x01,
265 'medium': 0x02,
266 'dashed': 0x03,
267 'dotted': 0x04,
268 'thick': 0x05,
269 'double': 0x06,
270 'hair': 0x07,
271 'medium_dashed': 0x08,
272 'thin_dash_dotted': 0x09,
273 'medium_dash_dotted': 0x0a,
274 'thin_dash_dot_dotted': 0x0b,
275 'medium_dash_dot_dotted': 0x0c,
276 'slanted_medium_dash_dotted': 0x0d,
277 }
279charset_map = {
280 # Text values for font.charset
281 'ansi_latin': 0x00,
282 'sys_default': 0x01,
283 'symbol': 0x02,
284 'apple_roman': 0x4d,
285 'ansi_jap_shift_jis': 0x80,
286 'ansi_kor_hangul': 0x81,
287 'ansi_kor_johab': 0x82,
288 'ansi_chinese_gbk': 0x86,
289 'ansi_chinese_big5': 0x88,
290 'ansi_greek': 0xa1,
291 'ansi_turkish': 0xa2,
292 'ansi_vietnamese': 0xa3,
293 'ansi_hebrew': 0xb1,
294 'ansi_arabic': 0xb2,
295 'ansi_baltic': 0xba,
296 'ansi_cyrillic': 0xcc,
297 'ansi_thai': 0xde,
298 'ansi_latin_ii': 0xee,
299 'oem_latin_i': 0xff,
300 }
303# Text values for colour indices. "grey" is a synonym of "gray".
304# The names are those given by Microsoft Excel 2003 to the colours
305# in the default palette. There is no great correspondence with
306# any W3C name-to-RGB mapping.
307_colour_map_text = """\
308aqua 0x31
309black 0x08
310blue 0x0C
311blue_gray 0x36
312bright_green 0x0B
313brown 0x3C
314coral 0x1D
315cyan_ega 0x0F
316dark_blue 0x12
317dark_blue_ega 0x12
318dark_green 0x3A
319dark_green_ega 0x11
320dark_purple 0x1C
321dark_red 0x10
322dark_red_ega 0x10
323dark_teal 0x38
324dark_yellow 0x13
325gold 0x33
326gray_ega 0x17
327gray25 0x16
328gray40 0x37
329gray50 0x17
330gray80 0x3F
331green 0x11
332ice_blue 0x1F
333indigo 0x3E
334ivory 0x1A
335lavender 0x2E
336light_blue 0x30
337light_green 0x2A
338light_orange 0x34
339light_turquoise 0x29
340light_yellow 0x2B
341lime 0x32
342magenta_ega 0x0E
343ocean_blue 0x1E
344olive_ega 0x13
345olive_green 0x3B
346orange 0x35
347pale_blue 0x2C
348periwinkle 0x18
349pink 0x0E
350plum 0x3D
351purple_ega 0x14
352red 0x0A
353rose 0x2D
354sea_green 0x39
355silver_ega 0x16
356sky_blue 0x28
357tan 0x2F
358teal 0x15
359teal_ega 0x15
360turquoise 0x0F
361violet 0x14
362white 0x09
363yellow 0x0D"""
365colour_map = {}
366for _line in _colour_map_text.splitlines():
367 _name, _num = _line.split()
368 _num = int(_num, 0)
369 colour_map[_name] = _num
370 if 'gray' in _name:
371 colour_map[_name.replace('gray', 'grey')] = _num
372del _colour_map_text, _line, _name, _num
374def add_palette_colour(colour_str, colour_index):
375 if not (8 <= colour_index <= 63):
376 raise Exception("add_palette_colour: colour_index (%d) not in range(8, 64)" %
377 (colour_index))
378 colour_map[colour_str] = colour_index
380# user-defined palette defines 56 RGB colors from entry 8 - 64
381#excel_default_palette_b8 = [ # (red, green, blue)
382# ( 0, 0, 0), (255,255,255), (255, 0, 0), ( 0,255, 0),
383# ( 0, 0,255), (255,255, 0), (255, 0,255), ( 0,255,255),
384# (128, 0, 0), ( 0,128, 0), ( 0, 0,128), (128,128, 0),
385# (128, 0,128), ( 0,128,128), (192,192,192), (128,128,128),
386# (153,153,255), (153, 51,102), (255,255,204), (204,255,255),
387# (102, 0,102), (255,128,128), ( 0,102,204), (204,204,255),
388# ( 0, 0,128), (255, 0,255), (255,255, 0), ( 0,255,255),
389# (128, 0,128), (128, 0, 0), ( 0,128,128), ( 0, 0,255),
390# ( 0,204,255), (204,255,255), (204,255,204), (255,255,153),
391# (153,204,255), (255,153,204), (204,153,255), (255,204,153),
392# ( 51,102,255), ( 51,204,204), (153,204, 0), (255,204, 0),
393# (255,153, 0), (255,102, 0), (102,102,153), (150,150,150),
394# ( 0, 51,102), ( 51,153,102), ( 0, 51, 0), ( 51, 51, 0),
395# (153, 51, 0), (153, 51,102), ( 51, 51,153), ( 51, 51, 51),
396# ]
398# Default colour table for BIFF8 copied from
399# OpenOffice.org's Documentation of the Microsoft Excel File Format, Excel Version 2003
400# Note palette has LSB padded with 2 bytes 0x00
401excel_default_palette_b8 = (
4020x00000000,
4030xFFFFFF00,
4040xFF000000,
4050x00FF0000,
4060x0000FF00,
4070xFFFF0000,
4080xFF00FF00,
4090x00FFFF00,
4100x80000000,
4110x00800000,
4120x00008000,
4130x80800000,
4140x80008000,
4150x00808000,
4160xC0C0C000,
4170x80808000,
4180x9999FF00,
4190x99336600,
4200xFFFFCC00,
4210xCCFFFF00,
4220x66006600,
4230xFF808000,
4240x0066CC00,
4250xCCCCFF00,
4260x00008000,
4270xFF00FF00,
4280xFFFF0000,
4290x00FFFF00,
4300x80008000,
4310x80000000,
4320x00808000,
4330x0000FF00,
4340x00CCFF00,
4350xCCFFFF00,
4360xCCFFCC00,
4370xFFFF9900,
4380x99CCFF00,
4390xFF99CC00,
4400xCC99FF00,
4410xFFCC9900,
4420x3366FF00,
4430x33CCCC00,
4440x99CC0000,
4450xFFCC0000,
4460xFF990000,
4470xFF660000,
4480x66669900,
4490x96969600,
4500x00336600,
4510x33996600,
4520x00330000,
4530x33330000,
4540x99330000,
4550x99336600,
4560x33339900,
4570x33333300)
459assert len(excel_default_palette_b8) == 56
461pattern_map = {
462 # Text values for pattern.pattern
463 # xlwt/doc/pattern_examples.xls showcases all of these patterns.
464 'no_fill': 0,
465 'none': 0,
466 'solid': 1,
467 'solid_fill': 1,
468 'solid_pattern': 1,
469 'fine_dots': 2,
470 'alt_bars': 3,
471 'sparse_dots': 4,
472 'thick_horz_bands': 5,
473 'thick_vert_bands': 6,
474 'thick_backward_diag': 7,
475 'thick_forward_diag': 8,
476 'big_spots': 9,
477 'bricks': 10,
478 'thin_horz_bands': 11,
479 'thin_vert_bands': 12,
480 'thin_backward_diag': 13,
481 'thin_forward_diag': 14,
482 'squares': 15,
483 'diamonds': 16,
484 }
486def any_str_func(s):
487 return s.strip()
489def colour_index_func(s, maxval=0x7F):
490 try:
491 value = int(s, 0)
492 except ValueError:
493 return None
494 if not (0 <= value <= maxval):
495 return None
496 return value
498colour_index_func_7 = colour_index_func
500def colour_index_func_15(s):
501 return colour_index_func(s, maxval=0x7FFF)
503def rotation_func(s):
504 try:
505 value = int(s, 0)
506 except ValueError:
507 return None
508 if not (-90 <= value <= 90):
509 raise EasyXFCallerError("rotation %d: should be -90 to +90 degrees" % value)
510 if value < 0:
511 value = 90 - value # encode as 91 to 180 (clockwise)
512 return value
514xf_dict = {
515 'align': 'alignment', # synonym
516 'alignment': {
517 'dire': {
518 'general': 0,
519 'lr': 1,
520 'rl': 2,
521 },
522 'direction': 'dire',
523 'horiz': 'horz',
524 'horizontal': 'horz',
525 'horz': {
526 'general': 0,
527 'left': 1,
528 'center': 2,
529 'centre': 2, # "align: horiz centre" means xf.alignment.horz is set to 2
530 'right': 3,
531 'filled': 4,
532 'justified': 5,
533 'center_across_selection': 6,
534 'centre_across_selection': 6,
535 'distributed': 7,
536 },
537 'inde': IntULim(15), # restriction: 0 <= value <= 15
538 'indent': 'inde',
539 'rota': [{'stacked': 255, 'none': 0, }, rotation_func],
540 'rotation': 'rota',
541 'shri': bool_map,
542 'shrink': 'shri',
543 'shrink_to_fit': 'shri',
544 'vert': {
545 'top': 0,
546 'center': 1,
547 'centre': 1,
548 'bottom': 2,
549 'justified': 3,
550 'distributed': 4,
551 },
552 'vertical': 'vert',
553 'wrap': bool_map,
554 },
555 'border': 'borders',
556 'borders': {
557 'left': [border_line_map, IntULim(0x0d)],
558 'right': [border_line_map, IntULim(0x0d)],
559 'top': [border_line_map, IntULim(0x0d)],
560 'bottom': [border_line_map, IntULim(0x0d)],
561 'diag': [border_line_map, IntULim(0x0d)],
562 'top_colour': [colour_map, colour_index_func_7],
563 'bottom_colour': [colour_map, colour_index_func_7],
564 'left_colour': [colour_map, colour_index_func_7],
565 'right_colour': [colour_map, colour_index_func_7],
566 'diag_colour': [colour_map, colour_index_func_7],
567 'top_color': 'top_colour',
568 'bottom_color': 'bottom_colour',
569 'left_color': 'left_colour',
570 'right_color': 'right_colour',
571 'diag_color': 'diag_colour',
572 'need_diag1': bool_map,
573 'need_diag2': bool_map,
574 },
575 'font': {
576 'bold': bool_map,
577 'charset': charset_map,
578 'color': 'colour_index',
579 'color_index': 'colour_index',
580 'colour': 'colour_index',
581 'colour_index': [colour_map, colour_index_func_15],
582 'escapement': {'none': 0, 'superscript': 1, 'subscript': 2},
583 'family': {'none': 0, 'roman': 1, 'swiss': 2, 'modern': 3, 'script': 4, 'decorative': 5, },
584 'height': IntULim(0xFFFF), # practical limits are much narrower e.g. 160 to 1440 (8pt to 72pt)
585 'italic': bool_map,
586 'name': any_str_func,
587 'outline': bool_map,
588 'shadow': bool_map,
589 'struck_out': bool_map,
590 'underline': [bool_map, {'none': 0, 'single': 1, 'single_acc': 0x21, 'double': 2, 'double_acc': 0x22, }],
591 },
592 'pattern': {
593 'back_color': 'pattern_back_colour',
594 'back_colour': 'pattern_back_colour',
595 'fore_color': 'pattern_fore_colour',
596 'fore_colour': 'pattern_fore_colour',
597 'pattern': [pattern_map, IntULim(16)],
598 'pattern_back_color': 'pattern_back_colour',
599 'pattern_back_colour': [colour_map, colour_index_func_7],
600 'pattern_fore_color': 'pattern_fore_colour',
601 'pattern_fore_colour': [colour_map, colour_index_func_7],
602 },
603 'protection': {
604 'cell_locked' : bool_map,
605 'formula_hidden': bool_map,
606 },
607 }
609def _esplit(s, split_char, esc_char="\\"):
610 escaped = False
611 olist = ['']
612 for c in s:
613 if escaped: 613 ↛ 614line 613 didn't jump to line 614, because the condition on line 613 was never true
614 olist[-1] += c
615 escaped = False
616 elif c == esc_char: 616 ↛ 617line 616 didn't jump to line 617, because the condition on line 616 was never true
617 escaped = True
618 elif c == split_char:
619 olist.append('')
620 else:
621 olist[-1] += c
622 return olist
624def _parse_strg_to_obj(strg, obj, parse_dict,
625 field_sep=",", line_sep=";", intro_sep=":", esc_char="\\", debug=False):
626 for line in _esplit(strg, line_sep, esc_char):
627 line = line.strip()
628 if not line: 628 ↛ 629line 628 didn't jump to line 629, because the condition on line 628 was never true
629 break
630 split_line = _esplit(line, intro_sep, esc_char)
631 if len(split_line) != 2: 631 ↛ 632line 631 didn't jump to line 632, because the condition on line 631 was never true
632 raise EasyXFCallerError('line %r should have exactly 1 "%c"' % (line, intro_sep))
633 section, item_str = split_line
634 section = section.strip().lower()
635 for counter in range(2): 635 ↛ 648line 635 didn't jump to line 648, because the loop on line 635 didn't complete
636 result = parse_dict.get(section)
637 if result is None: 637 ↛ 638line 637 didn't jump to line 638, because the condition on line 637 was never true
638 raise EasyXFCallerError('section %r is unknown' % section)
639 if isinstance(result, dict): 639 ↛ 641line 639 didn't jump to line 641, because the condition on line 639 was never false
640 break
641 if not isinstance(result, str):
642 raise EasyXFAuthorError(
643 'section %r should map to dict or str object; found %r' % (section, type(result)))
644 # synonym
645 old_section = section
646 section = result
647 else:
648 raise EasyXFAuthorError('Attempt to define synonym of synonym (%r: %r)' % (old_section, result))
649 section_dict = result
650 section_obj = getattr(obj, section, None)
651 if section_obj is None: 651 ↛ 652line 651 didn't jump to line 652, because the condition on line 651 was never true
652 raise EasyXFAuthorError('instance of %s class has no attribute named %s' % (obj.__class__.__name__, section))
653 for kv_str in _esplit(item_str, field_sep, esc_char):
654 guff = kv_str.split()
655 if not guff: 655 ↛ 656line 655 didn't jump to line 656, because the condition on line 655 was never true
656 continue
657 k = guff[0].lower().replace('-', '_')
658 v = ' '.join(guff[1:])
659 if not v: 659 ↛ 660line 659 didn't jump to line 660, because the condition on line 659 was never true
660 raise EasyXFCallerError("no value supplied for %s.%s" % (section, k))
661 for counter in xrange(2): 661 ↛ 671line 661 didn't jump to line 671, because the loop on line 661 didn't complete
662 result = section_dict.get(k)
663 if result is None: 663 ↛ 664line 663 didn't jump to line 664, because the condition on line 663 was never true
664 raise EasyXFCallerError('%s.%s is not a known attribute' % (section, k))
665 if not isinstance(result, basestring): 665 ↛ 668line 665 didn't jump to line 668, because the condition on line 665 was never false
666 break
667 # synonym
668 old_k = k
669 k = result
670 else:
671 raise EasyXFAuthorError('Attempt to define synonym of synonym (%r: %r)' % (old_k, result))
672 value_info = result
673 if not isinstance(value_info, list): 673 ↛ 675line 673 didn't jump to line 675, because the condition on line 673 was never false
674 value_info = [value_info]
675 for value_rule in value_info: 675 ↛ 689line 675 didn't jump to line 689, because the loop on line 675 didn't complete
676 if isinstance(value_rule, dict): 676 ↛ 682line 676 didn't jump to line 682, because the condition on line 676 was never false
677 # dict maps strings to integer field values
678 vl = v.lower().replace('-', '_')
679 if vl in value_rule: 679 ↛ 675line 679 didn't jump to line 675, because the condition on line 679 was never false
680 value = value_rule[vl]
681 break
682 elif callable(value_rule):
683 value = value_rule(v)
684 if value is not None:
685 break
686 else:
687 raise EasyXFAuthorError("unknown value rule for attribute %r: %r" % (k, value_rule))
688 else:
689 raise EasyXFCallerError("unexpected value %r for %s.%s" % (v, section, k))
690 try:
691 orig = getattr(section_obj, k)
692 except AttributeError:
693 raise EasyXFAuthorError('%s.%s in dictionary but not in supplied object' % (section, k))
694 if debug: print("+++ %s.%s = %r # %s; was %r" % (section, k, value, v, orig))
695 setattr(section_obj, k, value)
697def easyxf(strg_to_parse="", num_format_str=None,
698 field_sep=",", line_sep=";", intro_sep=":", esc_char="\\", debug=False):
699 """
700 This function is used to create and configure
701 :class:`XFStyle` objects for use with (for example) the
702 :meth:`Worksheet.write` method.
704 It takes a string to be parsed to obtain attribute values for
705 :class:`Alignment`, :class:`Borders`, :class:`Font`, :class:`Pattern` and
706 :class:`Protection` objects.
708 Refer to the examples in the file `examples/xlwt_easyxf_simple_demo.py`
709 and to the `xf_dict` dictionary in :mod:`xlwt.Style`.
711 Various synonyms including color/colour, center/centre and gray/grey are
712 allowed. Case is irrelevant (except maybe in font names). ``-`` may be used
713 instead of ``_``.
715 Example: ``font: bold on; align: wrap on, vert centre, horiz center``
717 :param num_format_str:
719 To get the "number format string" of an existing
720 cell whose format you want to reproduce, select the cell and click on
721 Format/Cells/Number/Custom. Otherwise, refer to Excel help.
723 Examples: ``"#,##0.00"``, ``"dd/mm/yyyy"``
725 :return: An :class:`XFstyle` object.
727 """
728 xfobj = XFStyle()
729 if num_format_str is not None: 729 ↛ 730line 729 didn't jump to line 730, because the condition on line 729 was never true
730 xfobj.num_format_str = num_format_str
731 if strg_to_parse: 731 ↛ 734line 731 didn't jump to line 734, because the condition on line 731 was never false
732 _parse_strg_to_obj(strg_to_parse, xfobj, xf_dict,
733 field_sep=field_sep, line_sep=line_sep, intro_sep=intro_sep, esc_char=esc_char, debug=debug)
734 return xfobj
736def easyfont(strg_to_parse="", field_sep=",", esc_char="\\", debug=False):
737 xfobj = XFStyle()
738 if strg_to_parse:
739 _parse_strg_to_obj("font: " + strg_to_parse, xfobj, xf_dict,
740 field_sep=field_sep, line_sep=";", intro_sep=":", esc_char=esc_char, debug=debug)
741 return xfobj.font