Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/xlwt/Workbook.py: 24%
413 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
1# -*- coding: windows-1252 -*-
2# Record Order in BIFF8
3# Workbook Globals Substream
4# BOF Type = workbook globals
5# Interface Header
6# MMS
7# Interface End
8# WRITEACCESS
9# CODEPAGE
10# DSF
11# TABID
12# FNGROUPCOUNT
13# Workbook Protection Block
14# WINDOWPROTECT
15# PROTECT
16# PASSWORD
17# PROT4REV
18# PROT4REVPASS
19# BACKUP
20# HIDEOBJ
21# WINDOW1
22# DATEMODE
23# PRECISION
24# REFRESHALL
25# BOOKBOOL
26# FONT +
27# FORMAT *
28# XF +
29# STYLE +
30# ? PALETTE
31# USESELFS
32#
33# BOUNDSHEET +
34#
35# COUNTRY
36# ? Link Table
37# SST
38# ExtSST
39# EOF
41from . import BIFFRecords
42from . import Style
43from .compat import unicode_type, int_types, basestring
45class Workbook(object):
46 """
47 This is a class representing a workbook and all its contents. When creating
48 Excel files with xlwt, you will normally start by instantiating an
49 object of this class.
50 """
52 #################################################################
53 ## Constructor
54 #################################################################
55 def __init__(self, encoding='ascii', style_compression=0):
56 self.encoding = encoding
57 self.__owner = 'None'
58 self.__country_code = None # 0x07 is Russia :-)
59 self.__wnd_protect = 0
60 self.__obj_protect = 0
61 self.__protect = 0
62 self.__backup_on_save = 0
63 # for WINDOW1 record
64 self.__hpos_twips = 0x01E0
65 self.__vpos_twips = 0x005A
66 self.__width_twips = 0x3FCF
67 self.__height_twips = 0x2A4E
68 self.__custom_palette_b8 = None
70 self.__active_sheet = 0
71 self.__first_tab_index = 0
72 self.__selected_tabs = 0x01
73 self.__tab_width_twips = 0x0258
75 self.__wnd_hidden = 0
76 self.__wnd_mini = 0
77 self.__hscroll_visible = 1
78 self.__vscroll_visible = 1
79 self.__tabs_visible = 1
81 self.__styles = Style.StyleCollection(style_compression)
83 self.__dates_1904 = 0
84 self.__use_cell_values = 1
86 self.__sst = BIFFRecords.SharedStringTable(self.encoding)
88 self.__worksheets = []
89 self.__worksheet_idx_from_name = {}
90 self.__sheet_refs = {}
91 self._supbook_xref = {}
92 self._xcall_xref = {}
93 self._ownbook_supbookx = None
94 self._ownbook_supbook_ref = None
95 self._xcall_supbookx = None
96 self._xcall_supbook_ref = None
100 #################################################################
101 ## Properties, "getters", "setters"
102 #################################################################
104 def get_style_stats(self):
105 return self.__styles.stats[:]
107 def set_owner(self, value):
108 self.__owner = value
110 def get_owner(self):
111 return self.__owner
113 owner = property(get_owner, set_owner)
115 #################################################################
117 def set_country_code(self, value):
118 self.__country_code = value
120 def get_country_code(self):
121 return self.__country_code
123 country_code = property(get_country_code, set_country_code)
125 #################################################################
127 def set_wnd_protect(self, value):
128 self.__wnd_protect = int(value)
130 def get_wnd_protect(self):
131 return bool(self.__wnd_protect)
133 wnd_protect = property(get_wnd_protect, set_wnd_protect)
135 #################################################################
137 def set_obj_protect(self, value):
138 self.__obj_protect = int(value)
140 def get_obj_protect(self):
141 return bool(self.__obj_protect)
143 obj_protect = property(get_obj_protect, set_obj_protect)
145 #################################################################
147 def set_protect(self, value):
148 self.__protect = int(value)
150 def get_protect(self):
151 return bool(self.__protect)
153 protect = property(get_protect, set_protect)
155 #################################################################
157 def set_backup_on_save(self, value):
158 self.__backup_on_save = int(value)
160 def get_backup_on_save(self):
161 return bool(self.__backup_on_save)
163 backup_on_save = property(get_backup_on_save, set_backup_on_save)
165 #################################################################
167 def set_hpos(self, value):
168 self.__hpos_twips = value & 0xFFFF
170 def get_hpos(self):
171 return self.__hpos_twips
173 hpos = property(get_hpos, set_hpos)
175 #################################################################
177 def set_vpos(self, value):
178 self.__vpos_twips = value & 0xFFFF
180 def get_vpos(self):
181 return self.__vpos_twips
183 vpos = property(get_vpos, set_vpos)
185 #################################################################
187 def set_width(self, value):
188 self.__width_twips = value & 0xFFFF
190 def get_width(self):
191 return self.__width_twips
193 width = property(get_width, set_width)
195 #################################################################
197 def set_height(self, value):
198 self.__height_twips = value & 0xFFFF
200 def get_height(self):
201 return self.__height_twips
203 height = property(get_height, set_height)
205 #################################################################
207 def set_active_sheet(self, value):
208 self.__active_sheet = value & 0xFFFF
209 self.__first_tab_index = self.__active_sheet
211 def get_active_sheet(self):
212 return self.__active_sheet
214 active_sheet = property(get_active_sheet, set_active_sheet)
216 #################################################################
218 def set_tab_width(self, value):
219 self.__tab_width_twips = value & 0xFFFF
221 def get_tab_width(self):
222 return self.__tab_width_twips
224 tab_width = property(get_tab_width, set_tab_width)
226 #################################################################
228 def set_wnd_visible(self, value):
229 self.__wnd_hidden = int(not value)
231 def get_wnd_visible(self):
232 return not bool(self.__wnd_hidden)
234 wnd_visible = property(get_wnd_visible, set_wnd_visible)
236 #################################################################
238 def set_wnd_mini(self, value):
239 self.__wnd_mini = int(value)
241 def get_wnd_mini(self):
242 return bool(self.__wnd_mini)
244 wnd_mini = property(get_wnd_mini, set_wnd_mini)
246 #################################################################
248 def set_hscroll_visible(self, value):
249 self.__hscroll_visible = int(value)
251 def get_hscroll_visible(self):
252 return bool(self.__hscroll_visible)
254 hscroll_visible = property(get_hscroll_visible, set_hscroll_visible)
256 #################################################################
258 def set_vscroll_visible(self, value):
259 self.__vscroll_visible = int(value)
261 def get_vscroll_visible(self):
262 return bool(self.__vscroll_visible)
264 vscroll_visible = property(get_vscroll_visible, set_vscroll_visible)
266 #################################################################
268 def set_tabs_visible(self, value):
269 self.__tabs_visible = int(value)
271 def get_tabs_visible(self):
272 return bool(self.__tabs_visible)
274 tabs_visible = property(get_tabs_visible, set_tabs_visible)
276 #################################################################
278 def set_dates_1904(self, value):
279 self.__dates_1904 = int(value)
281 def get_dates_1904(self):
282 return bool(self.__dates_1904)
284 dates_1904 = property(get_dates_1904, set_dates_1904)
286 #################################################################
288 def set_use_cell_values(self, value):
289 self.__use_cell_values = int(value)
291 def get_use_cell_values(self):
292 return bool(self.__use_cell_values)
294 use_cell_values = property(get_use_cell_values, set_use_cell_values)
296 #################################################################
298 def get_default_style(self):
299 return self.__styles.default_style
301 default_style = property(get_default_style)
303 #################################################################
305 def set_colour_RGB(self, colour_index, red, green, blue):
306 if not(8 <= colour_index <= 63):
307 raise Exception("set_colour_RGB: colour_index (%d) not in range(8, 64)" %
308 colour_index)
309 if min(red, green, blue) < 0 or max(red, green, blue) > 255:
310 raise Exception("set_colour_RGB: colour values (%d,%d,%d) must be in range(0, 256)"
311 % (red, green, blue))
312 if self.__custom_palette_b8 is None:
313 self.__custom_palette_b8 = list(Style.excel_default_palette_b8)
314 # User-defined Palette starts at colour index 8,
315 # so subtract 8 from colour_index when placing in palette
316 palette_index = colour_index - 8
317 self.__custom_palette_b8[palette_index] = red << 24 | green << 16 | blue << 8
319 ##################################################################
320 ## Methods
321 ##################################################################
323 def add_style(self, style):
324 return self.__styles.add(style)
326 def add_font(self, font):
327 return self.__styles.add_font(font)
329 def add_str(self, s):
330 return self.__sst.add_str(s)
332 def del_str(self, sst_idx):
333 self.__sst.del_str(sst_idx)
335 def str_index(self, s):
336 return self.__sst.str_index(s)
338 def add_rt(self, rt):
339 return self.__sst.add_rt(rt)
341 def rt_index(self, rt):
342 return self.__sst.rt_index(rt)
344 def add_sheet(self, sheetname, cell_overwrite_ok=False):
345 """
346 This method is used to create Worksheets in a Workbook.
348 :param sheetname:
350 The name to use for this sheet, as it will appear in the
351 tabs at the bottom of the Excel application.
353 :param cell_overwrite_ok:
355 If ``True``, cells in the added worksheet will not raise an
356 exception if written to more than once.
358 :return:
360 The :class:`~xlwt.Worksheet.Worksheet` that was added.
362 """
363 from . import Utils
364 from .Worksheet import Worksheet
365 if not isinstance(sheetname, unicode_type):
366 sheetname = sheetname.decode(self.encoding)
367 if not Utils.valid_sheet_name(sheetname):
368 raise Exception("invalid worksheet name %r" % sheetname)
369 lower_name = sheetname.lower()
370 if lower_name in self.__worksheet_idx_from_name:
371 raise Exception("duplicate worksheet name %r" % sheetname)
372 self.__worksheet_idx_from_name[lower_name] = len(self.__worksheets)
373 self.__worksheets.append(Worksheet(sheetname, self, cell_overwrite_ok))
374 return self.__worksheets[-1]
376 def get_sheet(self, sheet):
377 if isinstance(sheet, int_types):
378 return self.__worksheets[sheet]
379 elif isinstance(sheet, basestring):
380 sheetnum = self.sheet_index(sheet)
381 return self.__worksheets[sheetnum]
382 else:
383 raise Exception("sheet must be integer or string")
385 def sheet_index(self, sheetname):
386 try:
387 sheetnum = self.__worksheet_idx_from_name[sheetname.lower()]
388 except KeyError:
389 self.raise_bad_sheetname(sheetname)
391 return sheetnum
393 def raise_bad_sheetname(self, sheetname):
394 raise Exception("Formula: unknown sheet name %s" % sheetname)
396 def convert_sheetindex(self, strg_ref, n_sheets):
397 idx = int(strg_ref)
398 if 0 <= idx < n_sheets:
399 return idx
400 msg = "Formula: sheet index (%s) >= number of sheets (%d)" % (strg_ref, n_sheets)
401 raise Exception(msg)
403 def _get_supbook_index(self, tag):
404 if tag in self._supbook_xref:
405 return self._supbook_xref[tag]
406 self._supbook_xref[tag] = idx = len(self._supbook_xref)
407 return idx
409 def setup_ownbook(self):
410 self._ownbook_supbookx = self._get_supbook_index(('ownbook', 0))
411 self._ownbook_supbook_ref = None
412 reference = (self._ownbook_supbookx, 0xFFFE, 0xFFFE)
413 if reference in self.__sheet_refs:
414 raise Exception("can't happen")
415 self.__sheet_refs[reference] = self._ownbook_supbook_ref = len(self.__sheet_refs)
417 def setup_xcall(self):
418 self._xcall_supbookx = self._get_supbook_index(('xcall', 0))
419 self._xcall_supbook_ref = None
420 reference = (self._xcall_supbookx, 0xFFFE, 0xFFFE)
421 if reference in self.__sheet_refs:
422 raise Exception("can't happen")
423 self.__sheet_refs[reference] = self._xcall_supbook_ref = len(self.__sheet_refs)
425 def add_sheet_reference(self, formula):
426 patches = []
427 n_sheets = len(self.__worksheets)
428 sheet_refs, xcall_refs = formula.get_references()
430 for ref0, ref1, offset in sheet_refs:
431 if not ref0.isdigit():
432 try:
433 ref0n = self.__worksheet_idx_from_name[ref0.lower()]
434 except KeyError:
435 self.raise_bad_sheetname(ref0)
436 else:
437 ref0n = self.convert_sheetindex(ref0, n_sheets)
438 if ref1 == ref0:
439 ref1n = ref0n
440 elif not ref1.isdigit():
441 try:
442 ref1n = self.__worksheet_idx_from_name[ref1.lower()]
443 except KeyError:
444 self.raise_bad_sheetname(ref1)
445 else:
446 ref1n = self.convert_sheetindex(ref1, n_sheets)
447 if ref1n < ref0n:
448 msg = "Formula: sheets out of order; %r:%r -> (%d, %d)" \
449 % (ref0, ref1, ref0n, ref1n)
450 raise Exception(msg)
451 if self._ownbook_supbookx is None:
452 self.setup_ownbook()
453 reference = (self._ownbook_supbookx, ref0n, ref1n)
454 if reference in self.__sheet_refs:
455 patches.append((offset, self.__sheet_refs[reference]))
456 else:
457 nrefs = len(self.__sheet_refs)
458 if nrefs > 65535:
459 raise Exception('More than 65536 inter-sheet references')
460 self.__sheet_refs[reference] = nrefs
461 patches.append((offset, nrefs))
463 for funcname, offset in xcall_refs:
464 if self._ownbook_supbookx is None:
465 self.setup_ownbook()
466 if self._xcall_supbookx is None:
467 self.setup_xcall()
468 # print funcname, self._supbook_xref
469 patches.append((offset, self._xcall_supbook_ref))
470 if not isinstance(funcname, unicode_type):
471 funcname = funcname.decode(self.encoding)
472 if funcname in self._xcall_xref:
473 idx = self._xcall_xref[funcname]
474 else:
475 self._xcall_xref[funcname] = idx = len(self._xcall_xref)
476 patches.append((offset + 2, idx + 1))
478 formula.patch_references(patches)
480 ##################################################################
481 ## BIFF records generation
482 ##################################################################
484 def __bof_rec(self):
485 return BIFFRecords.Biff8BOFRecord(BIFFRecords.Biff8BOFRecord.BOOK_GLOBAL).get()
487 def __eof_rec(self):
488 return BIFFRecords.EOFRecord().get()
490 def __intf_hdr_rec(self):
491 return BIFFRecords.InteraceHdrRecord().get()
493 def __intf_end_rec(self):
494 return BIFFRecords.InteraceEndRecord().get()
496 def __intf_mms_rec(self):
497 return BIFFRecords.MMSRecord().get()
499 def __write_access_rec(self):
500 return BIFFRecords.WriteAccessRecord(self.__owner).get()
502 def __wnd_protect_rec(self):
503 return BIFFRecords.WindowProtectRecord(self.__wnd_protect).get()
505 def __obj_protect_rec(self):
506 return BIFFRecords.ObjectProtectRecord(self.__obj_protect).get()
508 def __protect_rec(self):
509 return BIFFRecords.ProtectRecord(self.__protect).get()
511 def __password_rec(self):
512 return BIFFRecords.PasswordRecord().get()
514 def __prot4rev_rec(self):
515 return BIFFRecords.Prot4RevRecord().get()
517 def __prot4rev_pass_rec(self):
518 return BIFFRecords.Prot4RevPassRecord().get()
520 def __backup_rec(self):
521 return BIFFRecords.BackupRecord(self.__backup_on_save).get()
523 def __hide_obj_rec(self):
524 return BIFFRecords.HideObjRecord().get()
526 def __window1_rec(self):
527 flags = 0
528 flags |= (self.__wnd_hidden) << 0
529 flags |= (self.__wnd_mini) << 1
530 flags |= (self.__hscroll_visible) << 3
531 flags |= (self.__vscroll_visible) << 4
532 flags |= (self.__tabs_visible) << 5
534 return BIFFRecords.Window1Record(self.__hpos_twips, self.__vpos_twips,
535 self.__width_twips, self.__height_twips,
536 flags,
537 self.__active_sheet, self.__first_tab_index,
538 self.__selected_tabs, self.__tab_width_twips).get()
540 def __codepage_rec(self):
541 return BIFFRecords.CodepageBiff8Record().get()
543 def __country_rec(self):
544 if not self.__country_code:
545 return b''
546 return BIFFRecords.CountryRecord(self.__country_code, self.__country_code).get()
548 def __dsf_rec(self):
549 return BIFFRecords.DSFRecord().get()
551 def __tabid_rec(self):
552 return BIFFRecords.TabIDRecord(len(self.__worksheets)).get()
554 def __fngroupcount_rec(self):
555 return BIFFRecords.FnGroupCountRecord().get()
557 def __datemode_rec(self):
558 return BIFFRecords.DateModeRecord(self.__dates_1904).get()
560 def __precision_rec(self):
561 return BIFFRecords.PrecisionRecord(self.__use_cell_values).get()
563 def __refresh_all_rec(self):
564 return BIFFRecords.RefreshAllRecord().get()
566 def __bookbool_rec(self):
567 return BIFFRecords.BookBoolRecord().get()
569 def __all_fonts_num_formats_xf_styles_rec(self):
570 return self.__styles.get_biff_data()
572 def __palette_rec(self):
573 if self.__custom_palette_b8 is None:
574 return b''
575 info = BIFFRecords.PaletteRecord(self.__custom_palette_b8).get()
576 return info
578 def __useselfs_rec(self):
579 return BIFFRecords.UseSelfsRecord().get()
581 def __boundsheets_rec(self, data_len_before, data_len_after, sheet_biff_lens):
582 # .................................
583 # BOUNDSEHEET0
584 # BOUNDSEHEET1
585 # BOUNDSEHEET2
586 # ..................................
587 # WORKSHEET0
588 # WORKSHEET1
589 # WORKSHEET2
590 boundsheets_len = 0
591 for sheet in self.__worksheets:
592 boundsheets_len += len(BIFFRecords.BoundSheetRecord(
593 0x00, sheet.visibility, sheet.name, self.encoding
594 ).get())
596 start = data_len_before + boundsheets_len + data_len_after
598 result = b''
599 for sheet_biff_len, sheet in zip(sheet_biff_lens, self.__worksheets):
600 result += BIFFRecords.BoundSheetRecord(
601 start, sheet.visibility, sheet.name, self.encoding
602 ).get()
603 start += sheet_biff_len
604 return result
606 def __all_links_rec(self):
607 pieces = []
608 temp = [(idx, tag) for tag, idx in self._supbook_xref.items()]
609 temp.sort()
610 for idx, tag in temp:
611 stype, snum = tag
612 if stype == 'ownbook':
613 rec = BIFFRecords.InternalReferenceSupBookRecord(len(self.__worksheets)).get()
614 pieces.append(rec)
615 elif stype == 'xcall':
616 rec = BIFFRecords.XcallSupBookRecord().get()
617 pieces.append(rec)
618 temp = [(idx, name) for name, idx in self._xcall_xref.items()]
619 temp.sort()
620 for idx, name in temp:
621 rec = BIFFRecords.ExternnameRecord(
622 options=0, index=0, name=name, fmla='\x02\x00\x1c\x17').get()
623 pieces.append(rec)
624 else:
625 raise Exception('unknown supbook stype %r' % stype)
626 if len(self.__sheet_refs) > 0:
627 # get references in index order
628 temp = [(idx, ref) for ref, idx in self.__sheet_refs.items()]
629 temp.sort()
630 temp = [ref for idx, ref in temp]
631 externsheet_record = BIFFRecords.ExternSheetRecord(temp).get()
632 pieces.append(externsheet_record)
633 return b''.join(pieces)
635 def __sst_rec(self):
636 return self.__sst.get_biff_record()
638 def __ext_sst_rec(self, abs_stream_pos):
639 return b''
640 #return BIFFRecords.ExtSSTRecord(abs_stream_pos, self.sst_record.str_placement,
641 #self.sst_record.portions_len).get()
643 def get_biff_data(self):
644 before = b''
645 before += self.__bof_rec()
646 before += self.__intf_hdr_rec()
647 before += self.__intf_mms_rec()
648 before += self.__intf_end_rec()
649 before += self.__write_access_rec()
650 before += self.__codepage_rec()
651 before += self.__dsf_rec()
652 before += self.__tabid_rec()
653 before += self.__fngroupcount_rec()
654 before += self.__wnd_protect_rec()
655 before += self.__protect_rec()
656 before += self.__obj_protect_rec()
657 before += self.__password_rec()
658 before += self.__prot4rev_rec()
659 before += self.__prot4rev_pass_rec()
660 before += self.__backup_rec()
661 before += self.__hide_obj_rec()
662 before += self.__window1_rec()
663 before += self.__datemode_rec()
664 before += self.__precision_rec()
665 before += self.__refresh_all_rec()
666 before += self.__bookbool_rec()
667 before += self.__all_fonts_num_formats_xf_styles_rec()
668 before += self.__palette_rec()
669 before += self.__useselfs_rec()
671 country = self.__country_rec()
672 all_links = self.__all_links_rec()
674 shared_str_table = self.__sst_rec()
675 after = country + all_links + shared_str_table
677 ext_sst = self.__ext_sst_rec(0) # need fake cause we need calc stream pos
678 eof = self.__eof_rec()
680 self.__worksheets[self.__active_sheet].selected = True
681 sheets = b''
682 sheet_biff_lens = []
683 for sheet in self.__worksheets:
684 data = sheet.get_biff_data()
685 sheets += data
686 sheet_biff_lens.append(len(data))
688 bundlesheets = self.__boundsheets_rec(len(before), len(after)+len(ext_sst)+len(eof), sheet_biff_lens)
690 sst_stream_pos = len(before) + len(bundlesheets) + len(country) + len(all_links)
691 ext_sst = self.__ext_sst_rec(sst_stream_pos)
693 return before + bundlesheets + after + ext_sst + eof + sheets
695 def save(self, filename_or_stream):
696 """
697 This method is used to save the Workbook to a file in native Excel
698 format.
700 :param filename_or_stream:
701 This can be a string containing a filename of
702 the file, in which case the excel file is saved to disk using the name
703 provided. It can also be a stream object with a write method, such as
704 a :class:`~io.StringIO`, in which case the data for the excel
705 file is written to the stream.
706 """
707 from . import CompoundDoc
709 doc = CompoundDoc.XlsDoc()
710 doc.save(filename_or_stream, self.get_biff_data())