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

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 

40 

41from . import BIFFRecords 

42from . import Style 

43from .compat import unicode_type, int_types, basestring 

44 

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 """ 

51 

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 

69 

70 self.__active_sheet = 0 

71 self.__first_tab_index = 0 

72 self.__selected_tabs = 0x01 

73 self.__tab_width_twips = 0x0258 

74 

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 

80 

81 self.__styles = Style.StyleCollection(style_compression) 

82 

83 self.__dates_1904 = 0 

84 self.__use_cell_values = 1 

85 

86 self.__sst = BIFFRecords.SharedStringTable(self.encoding) 

87 

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 

97 

98 

99 

100 ################################################################# 

101 ## Properties, "getters", "setters" 

102 ################################################################# 

103 

104 def get_style_stats(self): 

105 return self.__styles.stats[:] 

106 

107 def set_owner(self, value): 

108 self.__owner = value 

109 

110 def get_owner(self): 

111 return self.__owner 

112 

113 owner = property(get_owner, set_owner) 

114 

115 ################################################################# 

116 

117 def set_country_code(self, value): 

118 self.__country_code = value 

119 

120 def get_country_code(self): 

121 return self.__country_code 

122 

123 country_code = property(get_country_code, set_country_code) 

124 

125 ################################################################# 

126 

127 def set_wnd_protect(self, value): 

128 self.__wnd_protect = int(value) 

129 

130 def get_wnd_protect(self): 

131 return bool(self.__wnd_protect) 

132 

133 wnd_protect = property(get_wnd_protect, set_wnd_protect) 

134 

135 ################################################################# 

136 

137 def set_obj_protect(self, value): 

138 self.__obj_protect = int(value) 

139 

140 def get_obj_protect(self): 

141 return bool(self.__obj_protect) 

142 

143 obj_protect = property(get_obj_protect, set_obj_protect) 

144 

145 ################################################################# 

146 

147 def set_protect(self, value): 

148 self.__protect = int(value) 

149 

150 def get_protect(self): 

151 return bool(self.__protect) 

152 

153 protect = property(get_protect, set_protect) 

154 

155 ################################################################# 

156 

157 def set_backup_on_save(self, value): 

158 self.__backup_on_save = int(value) 

159 

160 def get_backup_on_save(self): 

161 return bool(self.__backup_on_save) 

162 

163 backup_on_save = property(get_backup_on_save, set_backup_on_save) 

164 

165 ################################################################# 

166 

167 def set_hpos(self, value): 

168 self.__hpos_twips = value & 0xFFFF 

169 

170 def get_hpos(self): 

171 return self.__hpos_twips 

172 

173 hpos = property(get_hpos, set_hpos) 

174 

175 ################################################################# 

176 

177 def set_vpos(self, value): 

178 self.__vpos_twips = value & 0xFFFF 

179 

180 def get_vpos(self): 

181 return self.__vpos_twips 

182 

183 vpos = property(get_vpos, set_vpos) 

184 

185 ################################################################# 

186 

187 def set_width(self, value): 

188 self.__width_twips = value & 0xFFFF 

189 

190 def get_width(self): 

191 return self.__width_twips 

192 

193 width = property(get_width, set_width) 

194 

195 ################################################################# 

196 

197 def set_height(self, value): 

198 self.__height_twips = value & 0xFFFF 

199 

200 def get_height(self): 

201 return self.__height_twips 

202 

203 height = property(get_height, set_height) 

204 

205 ################################################################# 

206 

207 def set_active_sheet(self, value): 

208 self.__active_sheet = value & 0xFFFF 

209 self.__first_tab_index = self.__active_sheet 

210 

211 def get_active_sheet(self): 

212 return self.__active_sheet 

213 

214 active_sheet = property(get_active_sheet, set_active_sheet) 

215 

216 ################################################################# 

217 

218 def set_tab_width(self, value): 

219 self.__tab_width_twips = value & 0xFFFF 

220 

221 def get_tab_width(self): 

222 return self.__tab_width_twips 

223 

224 tab_width = property(get_tab_width, set_tab_width) 

225 

226 ################################################################# 

227 

228 def set_wnd_visible(self, value): 

229 self.__wnd_hidden = int(not value) 

230 

231 def get_wnd_visible(self): 

232 return not bool(self.__wnd_hidden) 

233 

234 wnd_visible = property(get_wnd_visible, set_wnd_visible) 

235 

236 ################################################################# 

237 

238 def set_wnd_mini(self, value): 

239 self.__wnd_mini = int(value) 

240 

241 def get_wnd_mini(self): 

242 return bool(self.__wnd_mini) 

243 

244 wnd_mini = property(get_wnd_mini, set_wnd_mini) 

245 

246 ################################################################# 

247 

248 def set_hscroll_visible(self, value): 

249 self.__hscroll_visible = int(value) 

250 

251 def get_hscroll_visible(self): 

252 return bool(self.__hscroll_visible) 

253 

254 hscroll_visible = property(get_hscroll_visible, set_hscroll_visible) 

255 

256 ################################################################# 

257 

258 def set_vscroll_visible(self, value): 

259 self.__vscroll_visible = int(value) 

260 

261 def get_vscroll_visible(self): 

262 return bool(self.__vscroll_visible) 

263 

264 vscroll_visible = property(get_vscroll_visible, set_vscroll_visible) 

265 

266 ################################################################# 

267 

268 def set_tabs_visible(self, value): 

269 self.__tabs_visible = int(value) 

270 

271 def get_tabs_visible(self): 

272 return bool(self.__tabs_visible) 

273 

274 tabs_visible = property(get_tabs_visible, set_tabs_visible) 

275 

276 ################################################################# 

277 

278 def set_dates_1904(self, value): 

279 self.__dates_1904 = int(value) 

280 

281 def get_dates_1904(self): 

282 return bool(self.__dates_1904) 

283 

284 dates_1904 = property(get_dates_1904, set_dates_1904) 

285 

286 ################################################################# 

287 

288 def set_use_cell_values(self, value): 

289 self.__use_cell_values = int(value) 

290 

291 def get_use_cell_values(self): 

292 return bool(self.__use_cell_values) 

293 

294 use_cell_values = property(get_use_cell_values, set_use_cell_values) 

295 

296 ################################################################# 

297 

298 def get_default_style(self): 

299 return self.__styles.default_style 

300 

301 default_style = property(get_default_style) 

302 

303 ################################################################# 

304 

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 

318 

319 ################################################################## 

320 ## Methods 

321 ################################################################## 

322 

323 def add_style(self, style): 

324 return self.__styles.add(style) 

325 

326 def add_font(self, font): 

327 return self.__styles.add_font(font) 

328 

329 def add_str(self, s): 

330 return self.__sst.add_str(s) 

331 

332 def del_str(self, sst_idx): 

333 self.__sst.del_str(sst_idx) 

334 

335 def str_index(self, s): 

336 return self.__sst.str_index(s) 

337 

338 def add_rt(self, rt): 

339 return self.__sst.add_rt(rt) 

340 

341 def rt_index(self, rt): 

342 return self.__sst.rt_index(rt) 

343 

344 def add_sheet(self, sheetname, cell_overwrite_ok=False): 

345 """ 

346 This method is used to create Worksheets in a Workbook. 

347 

348 :param sheetname: 

349 

350 The name to use for this sheet, as it will appear in the 

351 tabs at the bottom of the Excel application. 

352 

353 :param cell_overwrite_ok: 

354 

355 If ``True``, cells in the added worksheet will not raise an 

356 exception if written to more than once. 

357 

358 :return: 

359 

360 The :class:`~xlwt.Worksheet.Worksheet` that was added. 

361 

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] 

375 

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") 

384 

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) 

390 

391 return sheetnum 

392 

393 def raise_bad_sheetname(self, sheetname): 

394 raise Exception("Formula: unknown sheet name %s" % sheetname) 

395 

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) 

402 

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 

408 

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) 

416 

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) 

424 

425 def add_sheet_reference(self, formula): 

426 patches = [] 

427 n_sheets = len(self.__worksheets) 

428 sheet_refs, xcall_refs = formula.get_references() 

429 

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)) 

462 

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)) 

477 

478 formula.patch_references(patches) 

479 

480 ################################################################## 

481 ## BIFF records generation 

482 ################################################################## 

483 

484 def __bof_rec(self): 

485 return BIFFRecords.Biff8BOFRecord(BIFFRecords.Biff8BOFRecord.BOOK_GLOBAL).get() 

486 

487 def __eof_rec(self): 

488 return BIFFRecords.EOFRecord().get() 

489 

490 def __intf_hdr_rec(self): 

491 return BIFFRecords.InteraceHdrRecord().get() 

492 

493 def __intf_end_rec(self): 

494 return BIFFRecords.InteraceEndRecord().get() 

495 

496 def __intf_mms_rec(self): 

497 return BIFFRecords.MMSRecord().get() 

498 

499 def __write_access_rec(self): 

500 return BIFFRecords.WriteAccessRecord(self.__owner).get() 

501 

502 def __wnd_protect_rec(self): 

503 return BIFFRecords.WindowProtectRecord(self.__wnd_protect).get() 

504 

505 def __obj_protect_rec(self): 

506 return BIFFRecords.ObjectProtectRecord(self.__obj_protect).get() 

507 

508 def __protect_rec(self): 

509 return BIFFRecords.ProtectRecord(self.__protect).get() 

510 

511 def __password_rec(self): 

512 return BIFFRecords.PasswordRecord().get() 

513 

514 def __prot4rev_rec(self): 

515 return BIFFRecords.Prot4RevRecord().get() 

516 

517 def __prot4rev_pass_rec(self): 

518 return BIFFRecords.Prot4RevPassRecord().get() 

519 

520 def __backup_rec(self): 

521 return BIFFRecords.BackupRecord(self.__backup_on_save).get() 

522 

523 def __hide_obj_rec(self): 

524 return BIFFRecords.HideObjRecord().get() 

525 

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 

533 

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() 

539 

540 def __codepage_rec(self): 

541 return BIFFRecords.CodepageBiff8Record().get() 

542 

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() 

547 

548 def __dsf_rec(self): 

549 return BIFFRecords.DSFRecord().get() 

550 

551 def __tabid_rec(self): 

552 return BIFFRecords.TabIDRecord(len(self.__worksheets)).get() 

553 

554 def __fngroupcount_rec(self): 

555 return BIFFRecords.FnGroupCountRecord().get() 

556 

557 def __datemode_rec(self): 

558 return BIFFRecords.DateModeRecord(self.__dates_1904).get() 

559 

560 def __precision_rec(self): 

561 return BIFFRecords.PrecisionRecord(self.__use_cell_values).get() 

562 

563 def __refresh_all_rec(self): 

564 return BIFFRecords.RefreshAllRecord().get() 

565 

566 def __bookbool_rec(self): 

567 return BIFFRecords.BookBoolRecord().get() 

568 

569 def __all_fonts_num_formats_xf_styles_rec(self): 

570 return self.__styles.get_biff_data() 

571 

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 

577 

578 def __useselfs_rec(self): 

579 return BIFFRecords.UseSelfsRecord().get() 

580 

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()) 

595 

596 start = data_len_before + boundsheets_len + data_len_after 

597 

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 

605 

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) 

634 

635 def __sst_rec(self): 

636 return self.__sst.get_biff_record() 

637 

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() 

642 

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() 

670 

671 country = self.__country_rec() 

672 all_links = self.__all_links_rec() 

673 

674 shared_str_table = self.__sst_rec() 

675 after = country + all_links + shared_str_table 

676 

677 ext_sst = self.__ext_sst_rec(0) # need fake cause we need calc stream pos 

678 eof = self.__eof_rec() 

679 

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)) 

687 

688 bundlesheets = self.__boundsheets_rec(len(before), len(after)+len(ext_sst)+len(eof), sheet_biff_lens) 

689 

690 sst_stream_pos = len(before) + len(bundlesheets) + len(country) + len(all_links) 

691 ext_sst = self.__ext_sst_rec(sst_stream_pos) 

692 

693 return before + bundlesheets + after + ext_sst + eof + sheets 

694 

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. 

699 

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 

708 

709 doc = CompoundDoc.XlsDoc() 

710 doc.save(filename_or_stream, self.get_biff_data()) 

711 

712