Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/xlwt/BIFFRecords.py: 51%

577 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1# -*- coding: cp1252 -*- 

2from struct import pack 

3from .UnicodeUtils import upack1, upack2, upack2rt 

4from .compat import basestring, unicode, unicode_type, xrange, iteritems 

5 

6class SharedStringTable(object): 

7 _SST_ID = 0x00FC 

8 _CONTINUE_ID = 0x003C 

9 

10 def __init__(self, encoding): 

11 self.encoding = encoding 

12 self._str_indexes = {} 

13 self._rt_indexes = {} 

14 self._tally = [] 

15 self._add_calls = 0 

16 # Following 3 attrs are used for temporary storage in the 

17 # get_biff_record() method and methods called by it. The pseudo- 

18 # initialisation here is for documentation purposes only. 

19 self._sst_record = None 

20 self._continues = None 

21 self._current_piece = None 

22 

23 def add_str(self, s): 

24 if self.encoding != 'ascii' and not isinstance(s, unicode_type): 

25 s = unicode(s, self.encoding) 

26 self._add_calls += 1 

27 if s not in self._str_indexes: 

28 idx = len(self._str_indexes) + len(self._rt_indexes) 

29 self._str_indexes[s] = idx 

30 self._tally.append(1) 

31 else: 

32 idx = self._str_indexes[s] 

33 self._tally[idx] += 1 

34 return idx 

35 

36 def add_rt(self, rt): 

37 rtList = [] 

38 for s, xf in rt: 

39 if self.encoding != 'ascii' and not isinstance(s, unicode_type): 

40 s = unicode(s, self.encoding) 

41 rtList.append((s, xf)) 

42 rt = tuple(rtList) 

43 self._add_calls += 1 

44 if rt not in self._rt_indexes: 

45 idx = len(self._str_indexes) + len(self._rt_indexes) 

46 self._rt_indexes[rt] = idx 

47 self._tally.append(1) 

48 else: 

49 idx = self._rt_indexes[rt] 

50 self._tally[idx] += 1 

51 return idx 

52 

53 def del_str(self, idx): 

54 # This is called when we are replacing the contents of a string cell. 

55 # handles both regular and rt strings 

56 assert self._tally[idx] > 0 

57 self._tally[idx] -= 1 

58 self._add_calls -= 1 

59 

60 def str_index(self, s): 

61 return self._str_indexes[s] 

62 

63 def rt_index(self, rt): 

64 return self._rt_indexes[rt] 

65 

66 def get_biff_record(self): 

67 self._sst_record = b'' 

68 self._continues = [None, None] 

69 self._current_piece = pack('<II', 0, 0) 

70 data = [(idx, s) for s, idx in iteritems(self._str_indexes)] 

71 data.extend((idx, s) for s, idx in iteritems(self._rt_indexes)) 

72 data.sort() # in index order 

73 for idx, s in data: 

74 if self._tally[idx] == 0: 

75 s = u'' 

76 if isinstance(s, basestring): 

77 self._add_to_sst(s) 

78 else: 

79 self._add_rt_to_sst(s) 

80 del data 

81 self._new_piece() 

82 self._continues[0] = pack('<2HII', self._SST_ID, len(self._sst_record), self._add_calls, len(self._str_indexes) + len(self._rt_indexes)) 

83 self._continues[1] = self._sst_record[8:] 

84 self._sst_record = None 

85 self._current_piece = None 

86 result = b''.join(self._continues) 

87 self._continues = None 

88 return result 

89 

90 

91 def _add_to_sst(self, s): 

92 u_str = upack2(s, self.encoding) 

93 

94 is_unicode_str = u_str[2] == b'\x01'[0] 

95 if is_unicode_str: 

96 atom_len = 5 # 2 byte -- len, 

97 # 1 byte -- options, 

98 # 2 byte -- 1st sym 

99 else: 

100 atom_len = 4 # 2 byte -- len, 

101 # 1 byte -- options, 

102 # 1 byte -- 1st sym 

103 

104 self._save_atom(u_str[0:atom_len]) 

105 self._save_splitted(u_str[atom_len:], is_unicode_str) 

106 

107 def _add_rt_to_sst(self, rt): 

108 rt_str, rt_fr = upack2rt(rt, self.encoding) 

109 is_unicode_str = rt_str[2] == b'\x09'[0] 

110 if is_unicode_str: 

111 atom_len = 7 # 2 byte -- len, 

112 # 1 byte -- options, 

113 # 2 byte -- number of rt runs 

114 # 2 byte -- 1st sym 

115 else: 

116 atom_len = 6 # 2 byte -- len, 

117 # 1 byte -- options, 

118 # 2 byte -- number of rt runs 

119 # 1 byte -- 1st sym 

120 self._save_atom(rt_str[0:atom_len]) 

121 self._save_splitted(rt_str[atom_len:], is_unicode_str) 

122 for i in range(0, len(rt_fr), 4): 

123 self._save_atom(rt_fr[i:i+4]) 

124 

125 def _new_piece(self): 

126 if self._sst_record == b'': 

127 self._sst_record = self._current_piece 

128 else: 

129 curr_piece_len = len(self._current_piece) 

130 self._continues.append(pack('<2H%ds'%curr_piece_len, self._CONTINUE_ID, curr_piece_len, self._current_piece)) 

131 self._current_piece = b'' 

132 

133 def _save_atom(self, s): 

134 atom_len = len(s) 

135 free_space = 0x2020 - len(self._current_piece) 

136 if free_space < atom_len: 

137 self._new_piece() 

138 self._current_piece += s 

139 

140 def _save_splitted(self, s, is_unicode_str): 

141 i = 0 

142 str_len = len(s) 

143 while i < str_len: 

144 piece_len = len(self._current_piece) 

145 free_space = 0x2020 - piece_len 

146 tail_len = str_len - i 

147 need_more_space = free_space < tail_len 

148 

149 if not need_more_space: 

150 atom_len = tail_len 

151 else: 

152 if is_unicode_str: 

153 atom_len = free_space & 0xFFFE 

154 else: 

155 atom_len = free_space 

156 

157 self._current_piece += s[i:i+atom_len] 

158 

159 if need_more_space: 

160 self._new_piece() 

161 if is_unicode_str: 

162 self._current_piece += b'\x01' 

163 else: 

164 self._current_piece += b'\x00' 

165 

166 i += atom_len 

167 

168 

169class BiffRecord(object): 

170 

171 _rec_data = b'' # class attribute; child classes need to set this. 

172 

173 def get_rec_header(self): 

174 return pack('<2H', self._REC_ID, len(self._rec_data)) 

175 

176 # Not over-ridden by any child classes, never called (except by "get"; see below). 

177 # def get_rec_data(self): 

178 # return self._rec_data 

179 

180 def get(self): 

181 # data = self.get_rec_data() 

182 data = self._rec_data 

183 if len(data) > 0x2020: # limit for BIFF7/8 

184 chunks = [] 

185 pos = 0 

186 while pos < len(data): 

187 chunk_pos = pos + 0x2020 

188 chunk = data[pos:chunk_pos] 

189 chunks.append(chunk) 

190 pos = chunk_pos 

191 continues = pack('<2H', self._REC_ID, len(chunks[0])) + chunks[0] 

192 for chunk in chunks[1:]: 

193 continues += pack('<2H%ds'%len(chunk), 0x003C, len(chunk), chunk) 

194 # 0x003C -- CONTINUE record id 

195 return continues 

196 else: 

197 return self.get_rec_header() + data 

198 

199 

200class Biff8BOFRecord(BiffRecord): 

201 """ 

202 Offset Size Contents 

203 0 2 Version, contains 0600H for BIFF8 and BIFF8X 

204 2 2 Type of the following data: 

205 0005H = Workbook globals 

206 0006H = Visual Basic module 

207 0010H = Worksheet 

208 0020H = Chart 

209 0040H = Macro sheet 

210 0100H = Workspace file 

211 4 2 Build identifier 

212 6 2 Build year 

213 8 4 File history flags 

214 12 4 Lowest Excel version that can read all records in this file 

215 """ 

216 _REC_ID = 0x0809 

217 # stream types 

218 BOOK_GLOBAL = 0x0005 

219 VB_MODULE = 0x0006 

220 WORKSHEET = 0x0010 

221 CHART = 0x0020 

222 MACROSHEET = 0x0040 

223 WORKSPACE = 0x0100 

224 

225 def __init__(self, rec_type): 

226 version = 0x0600 

227 build = 0x0DBB 

228 year = 0x07CC 

229 file_hist_flags = 0x00 

230 ver_can_read = 0x06 

231 

232 self._rec_data = pack('<4H2I', version, rec_type, build, year, file_hist_flags, ver_can_read) 

233 

234 

235class InteraceHdrRecord(BiffRecord): 

236 _REC_ID = 0x00E1 

237 

238 def __init__(self): 

239 self._rec_data = pack('BB', 0xB0, 0x04) 

240 

241 

242class InteraceEndRecord(BiffRecord): 

243 _REC_ID = 0x00E2 

244 

245 def __init__(self): 

246 self._rec_data = b'' 

247 

248 

249class MMSRecord(BiffRecord): 

250 _REC_ID = 0x00C1 

251 

252 def __init__(self): 

253 self._rec_data = pack('<H', 0x00) 

254 

255 

256class WriteAccessRecord(BiffRecord): 

257 """ 

258 This record is part of the file protection. It contains the name of the 

259 user that has saved the file. The user name is always stored as an 

260 equal-sized string. All unused characters after the name are filled 

261 with space characters. It is not required to write the mentioned string 

262 length. Every other length will be accepted too. 

263 """ 

264 _REC_ID = 0x005C 

265 

266 def __init__(self, owner): 

267 uowner = owner[0:0x30] 

268 uowner_len = len(uowner) 

269 if isinstance(uowner, unicode_type): 

270 uowner = uowner.encode('ascii') # probably not ascii, but play it safe until we know more 

271 self._rec_data = pack('%ds%ds' % (uowner_len, 0x70 - uowner_len), uowner, b' '*(0x70 - uowner_len)) 

272 

273 

274class DSFRecord(BiffRecord): 

275 """ 

276 This record specifies if the file contains an additional BIFF5/BIFF7 

277 workbook stream. 

278 Record DSF, BIFF8: 

279 Offset Size Contents 

280 0 2 0 = Only the BIFF8 Workbook stream is present 

281 1 = Additional BIFF5/BIFF7 Book stream is in the file 

282 A double stream file can be read by Excel 5.0 and Excel 95, and still 

283 contains all new features added to BIFF8 (which are left out in the 

284 BIFF5/BIFF7 Book stream). 

285 """ 

286 _REC_ID = 0x0161 

287 

288 def __init__(self): 

289 self._rec_data = pack('<H', 0x00) 

290 

291 

292class TabIDRecord(BiffRecord): 

293 _REC_ID = 0x013D 

294 

295 def __init__(self, sheetcount): 

296 for i in range(sheetcount): 

297 self._rec_data += pack('<H', i+1) 

298 

299 

300class FnGroupCountRecord(BiffRecord): 

301 _REC_ID = 0x009C 

302 

303 def __init__(self): 

304 self._rec_data = pack('BB', 0x0E, 0x00) 

305 

306 

307class WindowProtectRecord(BiffRecord): 

308 """ 

309 This record is part of the worksheet/workbook protection. It determines 

310 whether the window configuration of this document is protected. Window 

311 protection is not active, if this record is omitted. 

312 """ 

313 _REC_ID = 0x0019 

314 

315 def __init__(self, wndprotect): 

316 self._rec_data = pack('<H', wndprotect) 

317 

318 

319class ObjectProtectRecord(BiffRecord): 

320 """ 

321 This record is part of the worksheet/workbook protection. 

322 It determines whether the objects of the current sheet are protected. 

323 Object protection is not active, if this record is omitted. 

324 """ 

325 _REC_ID = 0x0063 

326 

327 

328 def __init__(self, objprotect): 

329 self._rec_data = pack('<H', objprotect) 

330 

331 

332class ScenProtectRecord(BiffRecord): 

333 """ 

334 This record is part of the worksheet/workbook protection. It 

335 determines whether the scenarios of the current sheet are protected. 

336 Scenario protection is not active, if this record is omitted. 

337 """ 

338 _REC_ID = 0x00DD 

339 

340 

341 def __init__(self, scenprotect): 

342 self._rec_data = pack('<H', scenprotect) 

343 

344 

345class ProtectRecord(BiffRecord): 

346 """ 

347 This record is part of the worksheet/workbook protection. It specifies 

348 whether a worksheet or a workbook is protected against modification. 

349 Protection is not active, if this record is omitted. 

350 """ 

351 

352 _REC_ID = 0x0012 

353 

354 def __init__(self, protect): 

355 self._rec_data = pack('<H', protect) 

356 

357 

358class PasswordRecord(BiffRecord): 

359 """ 

360 This record is part of the worksheet/workbook protection. It 

361 stores a 16-bit hash value, calculated from the worksheet or workbook 

362 protection password. 

363 """ 

364 _REC_ID = 0x0013 

365 def passwd_hash(self, plaintext): 

366 """ 

367 Based on the algorithm provided by Daniel Rentz of OpenOffice. 

368 """ 

369 if plaintext == "": 

370 return 0 

371 

372 passwd_hash = 0x0000 

373 for i, char in enumerate(plaintext): 

374 c = ord(char) << (i + 1) 

375 low_15 = c & 0x7fff 

376 high_15 = c & 0x7fff << 15 

377 high_15 = high_15 >> 15 

378 c = low_15 | high_15 

379 passwd_hash ^= c 

380 passwd_hash ^= len(plaintext) 

381 passwd_hash ^= 0xCE4B 

382 return passwd_hash 

383 

384 def __init__(self, passwd = ""): 

385 self._rec_data = pack('<H', self.passwd_hash(passwd)) 

386 

387 

388class Prot4RevRecord(BiffRecord): 

389 _REC_ID = 0x01AF 

390 

391 def __init__(self): 

392 self._rec_data = pack('<H', 0x00) 

393 

394 

395class Prot4RevPassRecord(BiffRecord): 

396 _REC_ID = 0x01BC 

397 

398 def __init__(self): 

399 self._rec_data = pack('<H', 0x00) 

400 

401 

402class BackupRecord(BiffRecord): 

403 """ 

404 This record contains a Boolean value determining whether Excel makes 

405 a backup of the file while saving. 

406 """ 

407 _REC_ID = 0x0040 

408 

409 def __init__(self, backup): 

410 self._rec_data = pack('<H', backup) 

411 

412class HideObjRecord(BiffRecord): 

413 """ 

414 This record specifies whether and how to show objects in the workbook. 

415 

416 Record HIDEOBJ, BIFF3-BIFF8: 

417 Offset Size Contents 

418 0 2 Viewing mode for objects: 

419 0 = Show all objects 

420 1 = Show placeholders 

421 2 = Do not show objects 

422 """ 

423 _REC_ID = 0x008D 

424 

425 def __init__(self): 

426 self._rec_data = pack('<H', 0x00) 

427 

428 

429 

430class RefreshAllRecord(BiffRecord): 

431 """ 

432 """ 

433 

434 _REC_ID = 0x01B7 

435 

436 def __init__(self): 

437 self._rec_data = pack('<H', 0x00) 

438 

439 

440class BookBoolRecord(BiffRecord): 

441 """ 

442 This record contains a Boolean value determining whether to save values 

443 linked from external workbooks (CRN records and XCT records). In BIFF3 

444 and BIFF4 this option is stored in the WSBOOL record. 

445 

446 Record BOOKBOOL, BIFF5-BIFF8: 

447 

448 Offset Size Contents 

449 0 2 0 = Save external linked values; 

450 1 = Do not save external linked values 

451 """ 

452 

453 _REC_ID = 0x00DA 

454 

455 def __init__(self): 

456 self._rec_data = pack('<H', 0x00) 

457 

458 

459class CountryRecord(BiffRecord): 

460 """ 

461 This record stores two Windows country identifiers. The first 

462 represents the user interface language of the Excel version that has 

463 saved the file, and the second represents the system regional settings 

464 at the time the file was saved. 

465 

466 Record COUNTRY, BIFF3-BIFF8: 

467 

468 Offset Size Contents 

469 0 2 Windows country identifier of the user interface language of Excel 

470 2 2 Windows country identifier of the system regional settings 

471 

472 The following table shows most of the used country identifiers. Most 

473 of these identifiers are equal to the international country calling 

474 codes. 

475 

476 1 USA 

477 2 Canada 

478 7 Russia 

479 """ 

480 

481 _REC_ID = 0x008C 

482 

483 def __init__(self, ui_id, sys_settings_id): 

484 self._rec_data = pack('<2H', ui_id, sys_settings_id) 

485 

486 

487class UseSelfsRecord(BiffRecord): 

488 """ 

489 This record specifies if the formulas in the workbook can use natural 

490 language formulas. This type of formula can refer to cells by its 

491 content or the content of the column or row header cell. 

492 

493 Record USESELFS, BIFF8: 

494 

495 Offset Size Contents 

496 0 2 0 = Do not use natural language formulas 

497 1 = Use natural language formulas 

498 

499 """ 

500 

501 _REC_ID = 0x0160 

502 

503 def __init__(self): 

504 self._rec_data = pack('<H', 0x01) 

505 

506 

507class EOFRecord(BiffRecord): 

508 _REC_ID = 0x000A 

509 

510 def __init__(self): 

511 self._rec_data = b'' 

512 

513 

514class DateModeRecord(BiffRecord): 

515 """ 

516 This record specifies the base date for displaying date values. All 

517 dates are stored as count of days past this base date. In BIFF2-BIFF4 

518 this record is part of the Calculation Settings Block. 

519 In BIFF5-BIFF8 it is stored in the Workbook Globals Substream. 

520 

521 Record DATEMODE, BIFF2-BIFF8: 

522 

523 Offset Size Contents 

524 0 2 0 = Base is 1899-Dec-31 (the cell = 1 represents 1900-Jan-01) 

525 1 = Base is 1904-Jan-01 (the cell = 1 represents 1904-Jan-02) 

526 """ 

527 _REC_ID = 0x0022 

528 

529 def __init__(self, from1904): 

530 if from1904: 

531 self._rec_data = pack('<H', 1) 

532 else: 

533 self._rec_data = pack('<H', 0) 

534 

535 

536class PrecisionRecord(BiffRecord): 

537 """ 

538 This record stores if formulas use the real cell values for calculation 

539 or the values displayed on the screen. In BIFF2- BIFF4 this record 

540 is part of the Calculation Settings Block. In BIFF5-BIFF8 it is stored 

541 in the Workbook Globals Substream. 

542 

543 Record PRECISION, BIFF2-BIFF8: 

544 

545 Offset Size Contents 

546 0 2 0 = Use displayed values; 

547 1 = Use real cell values 

548 """ 

549 _REC_ID = 0x000E 

550 

551 def __init__(self, use_real_values): 

552 if use_real_values: 

553 self._rec_data = pack('<H', 1) 

554 else: 

555 self._rec_data = pack('<H', 0) 

556 

557 

558class CodepageBiff8Record(BiffRecord): 

559 """ 

560 This record stores the text encoding used to write byte strings, stored 

561 as MS Windows code page identifier. The CODEPAGE record in BIFF8 always 

562 contains the code page 1200 (UTF-16). Therefore it is not 

563 possible to obtain the encoding used for a protection password (it is 

564 not UTF-16). 

565 

566 Record CODEPAGE, BIFF2-BIFF8: 

567 

568 Offset Size Contents 

569 0 2 Code page identifier used for byte string text encoding: 

570 016FH = 367 = ASCII 

571 01B5H = 437 = IBM PC CP-437 (US) 

572 02D0H = 720 = IBM PC CP-720 (OEM Arabic) 

573 02E1H = 737 = IBM PC CP-737 (Greek) 

574 0307H = 775 = IBM PC CP-775 (Baltic) 

575 0352H = 850 = IBM PC CP-850 (Latin I) 

576 0354H = 852 = IBM PC CP-852 (Latin II (Central European)) 

577 0357H = 855 = IBM PC CP-855 (Cyrillic) 

578 0359H = 857 = IBM PC CP-857 (Turkish) 

579 035AH = 858 = IBM PC CP-858 (Multilingual Latin I with Euro) 

580 035CH = 860 = IBM PC CP-860 (Portuguese) 

581 035DH = 861 = IBM PC CP-861 (Icelandic) 

582 035EH = 862 = IBM PC CP-862 (Hebrew) 

583 035FH = 863 = IBM PC CP-863 (Canadian (French)) 

584 0360H = 864 = IBM PC CP-864 (Arabic) 

585 0361H = 865 = IBM PC CP-865 (Nordic) 

586 0362H = 866 = IBM PC CP-866 (Cyrillic (Russian)) 

587 0365H = 869 = IBM PC CP-869 (Greek (Modern)) 

588 036AH = 874 = Windows CP-874 (Thai) 

589 03A4H = 932 = Windows CP-932 (Japanese Shift-JIS) 

590 03A8H = 936 = Windows CP-936 (Chinese Simplified GBK) 

591 03B5H = 949 = Windows CP-949 (Korean (Wansung)) 

592 03B6H = 950 = Windows CP-950 (Chinese Traditional BIG5) 

593 04B0H = 1200 = UTF-16 (BIFF8) 

594 04E2H = 1250 = Windows CP-1250 (Latin II) (Central European) 

595 04E3H = 1251 = Windows CP-1251 (Cyrillic) 

596 04E4H = 1252 = Windows CP-1252 (Latin I) (BIFF4-BIFF7) 

597 04E5H = 1253 = Windows CP-1253 (Greek) 

598 04E6H = 1254 = Windows CP-1254 (Turkish) 

599 04E7H = 1255 = Windows CP-1255 (Hebrew) 

600 04E8H = 1256 = Windows CP-1256 (Arabic) 

601 04E9H = 1257 = Windows CP-1257 (Baltic) 

602 04EAH = 1258 = Windows CP-1258 (Vietnamese) 

603 0551H = 1361 = Windows CP-1361 (Korean (Johab)) 

604 2710H = 10000 = Apple Roman 

605 8000H = 32768 = Apple Roman 

606 8001H = 32769 = Windows CP-1252 (Latin I) (BIFF2-BIFF3) 

607 """ 

608 _REC_ID = 0x0042 

609 UTF_16 = 0x04B0 

610 

611 def __init__(self): 

612 self._rec_data = pack('<H', self.UTF_16) 

613 

614class Window1Record(BiffRecord): 

615 """ 

616 Offset Size Contents 

617 0 2 Horizontal position of the document window (in twips = 1/20 of a point) 

618 2 2 Vertical position of the document window (in twips = 1/20 of a point) 

619 4 2 Width of the document window (in twips = 1/20 of a point) 

620 6 2 Height of the document window (in twips = 1/20 of a point) 

621 8 2 Option flags: 

622 Bits Mask Contents 

623 0 0001H 0 = Window is visible 1 = Window is hidden 

624 1 0002H 0 = Window is open 1 = Window is minimised 

625 3 0008H 0 = Horizontal scroll bar hidden 1 = Horizontal scroll bar visible 

626 4 0010H 0 = Vertical scroll bar hidden 1 = Vertical scroll bar visible 

627 5 0020H 0 = Worksheet tab bar hidden 1 = Worksheet tab bar visible 

628 10 2 Index to active (displayed) worksheet 

629 12 2 Index of first visible tab in the worksheet tab bar 

630 14 2 Number of selected worksheets (highlighted in the worksheet tab bar) 

631 16 2 Width of worksheet tab bar (in 1/1000 of window width). The remaining space is used by the 

632 horizontal scrollbar. 

633 """ 

634 _REC_ID = 0x003D 

635 # flags 

636 

637 def __init__(self, 

638 hpos_twips, vpos_twips, 

639 width_twips, height_twips, 

640 flags, 

641 active_sheet, 

642 first_tab_index, selected_tabs, tab_width): 

643 self._rec_data = pack('<9H', hpos_twips, vpos_twips, 

644 width_twips, height_twips, 

645 flags, 

646 active_sheet, 

647 first_tab_index, selected_tabs, tab_width) 

648 

649class FontRecord(BiffRecord): 

650 """ 

651 WARNING 

652 The font with index 4 is omitted in all BIFF versions. 

653 This means the first four fonts have zero-based indexes, and 

654 the fifth font and all following fonts are referenced with one-based 

655 indexes. 

656 

657 Offset Size Contents 

658 0 2 Height of the font (in twips = 1/20 of a point) 

659 2 2 Option flags: 

660 Bit Mask Contents 

661 0 0001H 1 = Characters are bold (redundant, see below) 

662 1 0002H 1 = Characters are italic 

663 2 0004H 1 = Characters are underlined (redundant, see below) 

664 3 0008H 1 = Characters are struck out 

665 0010H 1 = Outline 

666 0020H 1 = Shadow 

667 4 2 Colour index 

668 6 2 Font weight (100-1000). 

669 Standard values are 0190H (400) for normal text and 02BCH 

670 (700) for bold text. 

671 8 2 Escapement type: 

672 0000H = None 

673 0001H = Superscript 

674 0002H = Subscript 

675 10 1 Underline type: 

676 00H = None 

677 01H = Single 

678 21H = Single accounting 

679 02H = Double 

680 22H = Double accounting 

681 11 1 Font family: 

682 00H = None (unknown or don't care) 

683 01H = Roman (variable width, serifed) 

684 02H = Swiss (variable width, sans-serifed) 

685 03H = Modern (fixed width, serifed or sans-serifed) 

686 04H = Script (cursive) 

687 05H = Decorative (specialised, i.e. Old English, Fraktur) 

688 12 1 Character set: 

689 00H = 0 = ANSI Latin 

690 01H = 1 = System default 

691 02H = 2 = Symbol 

692 4DH = 77 = Apple Roman 

693 80H = 128 = ANSI Japanese Shift-JIS 

694 81H = 129 = ANSI Korean (Hangul) 

695 82H = 130 = ANSI Korean (Johab) 

696 86H = 134 = ANSI Chinese Simplified GBK 

697 88H = 136 = ANSI Chinese Traditional BIG5 

698 A1H = 161 = ANSI Greek 

699 A2H = 162 = ANSI Turkish 

700 A3H = 163 = ANSI Vietnamese 

701 B1H = 177 = ANSI Hebrew 

702 B2H = 178 = ANSI Arabic 

703 BAH = 186 = ANSI Baltic 

704 CCH = 204 = ANSI Cyrillic 

705 DEH = 222 = ANSI Thai 

706 EEH = 238 = ANSI Latin II (Central European) 

707 FFH = 255 = OEM Latin I 

708 13 1 Not used 

709 14 var. Font name: 

710 BIFF5/BIFF7: Byte string, 8-bit string length 

711 BIFF8: Unicode string, 8-bit string length 

712 The boldness and underline flags are still set in the options field, 

713 but not used on reading the font. Font weight and underline type 

714 are specified in separate fields instead. 

715 """ 

716 _REC_ID = 0x0031 

717 

718 def __init__(self, 

719 height, options, colour_index, weight, escapement, 

720 underline, family, charset, 

721 name): 

722 uname = upack1(name) 

723 uname_len = len(uname) 

724 

725 self._rec_data = pack('<5H4B%ds' % uname_len, height, options, colour_index, weight, escapement, 

726 underline, family, charset, 0x00, 

727 uname) 

728 

729class NumberFormatRecord(BiffRecord): 

730 """ 

731 Record FORMAT, BIFF8: 

732 Offset Size Contents 

733 0 2 Format index used in other records 

734 2 var. Number format string (Unicode string, 16-bit string length) 

735 

736 From BIFF5 on, the built-in number formats will be omitted. The built-in 

737 formats are dependent on the current regional settings of the operating 

738 system. The following table shows which number formats are used by default 

739 in a US-English environment. All indexes from 0 to 163 are reserved for 

740 built-in formats. The first user-defined format starts at 164. 

741 

742 The built-in number formats, BIFF5-BIFF8 

743 

744 Index Type Format string 

745 0 General General 

746 1 Decimal 0 

747 2 Decimal 0.00 

748 3 Decimal #,##0 

749 4 Decimal #,##0.00 

750 5 Currency "$"#,##0_);("$"#,## 

751 6 Currency "$"#,##0_);[Red]("$"#,## 

752 7 Currency "$"#,##0.00_);("$"#,## 

753 8 Currency "$"#,##0.00_);[Red]("$"#,## 

754 9 Percent 0% 

755 10 Percent 0.00% 

756 11 Scientific 0.00E+00 

757 12 Fraction # ?/? 

758 13 Fraction # ??/?? 

759 14 Date M/D/YY 

760 15 Date D-MMM-YY 

761 16 Date D-MMM 

762 17 Date MMM-YY 

763 18 Time h:mm AM/PM 

764 19 Time h:mm:ss AM/PM 

765 20 Time h:mm 

766 21 Time h:mm:ss 

767 22 Date/Time M/D/YY h:mm 

768 37 Account _(#,##0_);(#,##0) 

769 38 Account _(#,##0_);[Red](#,##0) 

770 39 Account _(#,##0.00_);(#,##0.00) 

771 40 Account _(#,##0.00_);[Red](#,##0.00) 

772 41 Currency _("$"* #,##0_);_("$"* (#,##0);_("$"* "-"_);_(@_) 

773 42 Currency _(* #,##0_);_(* (#,##0);_(* "-"_);_(@_) 

774 43 Currency _("$"* #,##0.00_);_("$"* (#,##0.00);_("$"* "-"??_);_(@_) 

775 44 Currency _(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_) 

776 45 Time mm:ss 

777 46 Time [h]:mm:ss 

778 47 Time mm:ss.0 

779 48 Scientific ##0.0E+0 

780 49 Text @ 

781 """ 

782 _REC_ID = 0x041E 

783 

784 def __init__(self, idx, fmtstr): 

785 ufmtstr = upack2(fmtstr) 

786 ufmtstr_len = len(ufmtstr) 

787 

788 self._rec_data = pack('<H%ds' % ufmtstr_len, idx, ufmtstr) 

789 

790 

791class XFRecord(BiffRecord): 

792 """ 

793 XF Substructures 

794 ------------------------------------------------------------------------- 

795 XF_TYPE_PROT XF Type and Cell Protection (3 Bits), BIFF3-BIFF8 

796 These 3 bits are part of a specific data byte. 

797 Bit Mask Contents 

798 0 01H 1 = Cell is locked 

799 1 02H 1 = Formula is hidden 

800 2 04H 0 = Cell XF; 1 = Style XF 

801 

802 XF_USED_ATTRIB Attributes Used from Parent Style XF (6 Bits), 

803 BIFF3-BIFF8 Each bit describes the validity of a specific group 

804 of attributes. In cell XFs a cleared bit means the attributes of the 

805 parent style XF are used (but only if the attributes are valid there), 

806 a set bit means the attributes of this XF are used. In style XFs 

807 a cleared bit means the attribute setting is valid, a set bit means the 

808 attribute should be ignored. 

809 Bit Mask Contents 

810 0 01H Flag for number format 

811 1 02H Flag for font 

812 2 04H Flag for horizontal and vertical alignment, text wrap, indentation, orientation, rotation, and 

813 text direction 

814 3 08H Flag for border lines 

815 4 10H Flag for background area style 

816 5 20H Flag for cell protection (cell locked and formula hidden) 

817 

818 XF_HOR_ALIGN Horizontal Alignment (3 Bits), BIFF2-BIFF8 The horizontal 

819 alignment consists of 3 bits and is part of a specific data byte. 

820 Value Horizontal alignment 

821 00H General 

822 01H Left 

823 02H Centred 

824 03H Right 

825 04H Filled 

826 05H Justified (BIFF4-BIFF8X) 

827 06H Centred across selection (BIFF4-BIFF8X) 

828 07H Distributed (BIFF8X) 

829 

830 XF_VERT_ALIGN Vertical Alignment (2 or 3 Bits), BIFF4-BIFF8 

831 The vertical alignment consists of 2 bits (BIFF4) or 3 bits (BIFF5-BIFF8) 

832 and is part of a specific data byte. Vertical alignment is not available 

833 in BIFF2 and BIFF3. 

834 Value Vertical alignment 

835 00H Top 

836 01H Centred 

837 02H Bottom 

838 03H Justified (BIFF5-BIFF8X) 

839 04H Distributed (BIFF8X) 

840 

841 XF_ORIENTATION Text Orientation (2 Bits), BIFF4-BIFF7 In the BIFF 

842 versions BIFF4-BIFF7, text can be rotated in steps of 90 degrees 

843 or stacked. The orientation mode consists of 2 bits and is part of 

844 a specific data byte. In BIFF8 a rotation angle occurs instead of these 

845 flags. 

846 Value Text orientation 

847 00H Not rotated 

848 01H Letters are stacked top-to-bottom, but not rotated 

849 02H Text is rotated 90 degrees counterclockwise 

850 03H Text is rotated 90 degrees clockwise 

851 

852 XF_ROTATION Text Rotation Angle (1 Byte), BIFF8 

853 Value Text rotation 

854 0 Not rotated 

855 1-90 1 to 90 degrees counterclockwise 

856 91-180 1 to 90 degrees clockwise 

857 255 Letters are stacked top-to-bottom, but not rotated 

858 

859 XF_BORDER_34 Cell Border Style (4 Bytes), BIFF3-BIFF4 Cell borders 

860 contain a line style and a line colour for each line of the border. 

861 Bit Mask Contents 

862 2-0 00000007H Top line style 

863 7-3 000000F8H Colour index for top line colour 

864 10-8 00000700H Left line style 

865 15-11 0000F800H Colour index for left line colour 

866 18-16 00070000H Bottom line style 

867 23-19 00F80000H Colour index for bottom line colour 

868 26-24 07000000H Right line style 

869 31-27 F8000000H Colour index for right line colour 

870 

871 XF_AREA_34 Cell Background Area Style (2 Bytes), BIFF3-BIFF4 A cell 

872 background area style contains an area pattern and a foreground and 

873 background colour. 

874 Bit Mask Contents 

875 5-0 003FH Fill pattern 

876 10-6 07C0H Colour index for pattern colour 

877 15-11 F800H Colour index for pattern background 

878 --------------------------------------------------------------------------------------------- 

879 Record XF, BIFF8: 

880 Offset Size Contents 

881 0 2 Index to FONT record 

882 2 2 Index to FORMAT record 

883 4 2 Bit Mask Contents 

884 2-0 0007H XF_TYPE_PROT . XF type, cell protection (see above) 

885 15-4 FFF0H Index to parent style XF (always FFFH in style XFs) 

886 6 1 Bit Mask Contents 

887 2-0 07H XF_HOR_ALIGN . Horizontal alignment (see above) 

888 3 08H 1 = Text is wrapped at right border 

889 6-4 70H XF_VERT_ALIGN . Vertical alignment (see above) 

890 7 1 XF_ROTATION: Text rotation angle (see above) 

891 8 1 Bit Mask Contents 

892 3-0 0FH Indent level 

893 4 10H 1 = Shrink content to fit into cell 

894 5 merge 

895 7-6 C0H Text direction (BIFF8X only) 

896 00b = According to context 

897 01b = Left-to-right 

898 10b = Right-to-left 

899 9 1 Bit Mask Contents 

900 7-2 FCH XF_USED_ATTRIB . Used attributes (see above) 

901 10 4 Cell border lines and background area: 

902 Bit Mask Contents 

903 3-0 0000000FH Left line style 

904 7-4 000000F0H Right line style 

905 11-8 00000F00H Top line style 

906 15-12 0000F000H Bottom line style 

907 22-16 007F0000H Colour index for left line colour 

908 29-23 3F800000H Colour index for right line colour 

909 30 40000000H 1 = Diagonal line from top left to right bottom 

910 31 80000000H 1 = Diagonal line from bottom left to right top 

911 14 4 Bit Mask Contents 

912 6-0 0000007FH Colour index for top line colour 

913 13-7 00003F80H Colour index for bottom line colour 

914 20-14 001FC000H Colour index for diagonal line colour 

915 24-21 01E00000H Diagonal line style 

916 31-26 FC000000H Fill pattern 

917 18 2 Bit Mask Contents 

918 6-0 007FH Colour index for pattern colour 

919 13-7 3F80H Colour index for pattern background 

920 

921 """ 

922 _REC_ID = 0x00E0 

923 

924 def __init__(self, xf, xftype='cell'): 

925 font_xf_idx, fmt_str_xf_idx, alignment, borders, pattern, protection = xf 

926 fnt = pack('<H', font_xf_idx) 

927 fmt = pack('<H', fmt_str_xf_idx) 

928 if xftype == 'cell': 

929 prt = pack('<H', 

930 ((protection.cell_locked & 0x01) << 0) | 

931 ((protection.formula_hidden & 0x01) << 1) 

932 ) 

933 else: 

934 prt = pack('<H', 0xFFF5) 

935 aln = pack('B', 

936 ((alignment.horz & 0x07) << 0) | 

937 ((alignment.wrap & 0x01) << 3) | 

938 ((alignment.vert & 0x07) << 4) 

939 ) 

940 rot = pack('B', alignment.rota) 

941 txt = pack('B', 

942 ((alignment.inde & 0x0F) << 0) | 

943 ((alignment.shri & 0x01) << 4) | 

944 ((alignment.merg & 0x01) << 5) | 

945 ((alignment.dire & 0x03) << 6) 

946 ) 

947 if xftype == 'cell': 

948 used_attr = pack('B', 0xF8) 

949 else: 

950 used_attr = pack('B', 0xF4) 

951 

952 if borders.left == borders.NO_LINE: 

953 borders.left_colour = 0x00 

954 if borders.right == borders.NO_LINE: 

955 borders.right_colour = 0x00 

956 if borders.top == borders.NO_LINE: 

957 borders.top_colour = 0x00 

958 if borders.bottom == borders.NO_LINE: 

959 borders.bottom_colour = 0x00 

960 if borders.diag == borders.NO_LINE: 

961 borders.diag_colour = 0x00 

962 brd1 = pack('<L', 

963 ((borders.left & 0x0F) << 0 ) | 

964 ((borders.right & 0x0F) << 4 ) | 

965 ((borders.top & 0x0F) << 8 ) | 

966 ((borders.bottom & 0x0F) << 12) | 

967 ((borders.left_colour & 0x7F) << 16) | 

968 ((borders.right_colour & 0x7F) << 23) | 

969 ((borders.need_diag1 & 0x01) << 30) | 

970 ((borders.need_diag2 & 0x01) << 31) 

971 ) 

972 brd2 = pack('<L', 

973 ((borders.top_colour & 0x7F) << 0 ) | 

974 ((borders.bottom_colour & 0x7F) << 7 ) | 

975 ((borders.diag_colour & 0x7F) << 14) | 

976 ((borders.diag & 0x0F) << 21) | 

977 ((pattern.pattern & 0x3F) << 26) 

978 ) 

979 pat = pack('<H', 

980 ((pattern.pattern_fore_colour & 0x7F) << 0 ) | 

981 ((pattern.pattern_back_colour & 0x7F) << 7 ) 

982 ) 

983 self._rec_data = fnt + fmt + prt + \ 

984 aln + rot + txt + used_attr + \ 

985 brd1 + brd2 + \ 

986 pat 

987 

988class StyleRecord(BiffRecord): 

989 """ 

990 STYLE record for user-defined cell styles, BIFF3-BIFF8: 

991 Offset Size Contents 

992 0 2 Bit Mask Contents 

993 11-0 0FFFH Index to style XF record 

994 15 8000H Always 0 for user-defined styles 

995 2 var. BIFF2-BIFF7: Non-empty byte string, 8-bit string length 

996 BIFF8: Non-empty Unicode string, 16-bit string length 

997 STYLE record for built-in cell styles, BIFF3-BIFF8: 

998 Offset Size Contents 

999 0 2 Bit Mask Contents 

1000 11-0 0FFFH Index to style XF record 

1001 15 8000H Always 1 for built-in styles 

1002 2 1 Identifier of the built-in cell style: 

1003 00H = Normal 

1004 01H = RowLevel_lv (see next field) 

1005 02H = ColLevel_lv (see next field) 

1006 03H = Comma 

1007 04H = Currency 

1008 05H = Percent 

1009 06H = Comma [0] (BIFF4-BIFF8) 

1010 07H = Currency [0] (BIFF4-BIFF8) 

1011 08H = Hyperlink (BIFF8) 

1012 09H = Followed Hyperlink (BIFF8) 

1013 3 1 Level for RowLevel or ColLevel style 

1014 (zero-based, lv), FFH otherwise 

1015 The RowLevel and ColLevel styles specify the formatting of subtotal 

1016 cells in a specific outline level. The level is specified by the last 

1017 field in the STYLE record. Valid values are 0-6 for the outline levels 

1018 1-7. 

1019 """ 

1020 _REC_ID = 0x0293 

1021 

1022 def __init__(self): 

1023 self._rec_data = pack('<HBB', 0x8000, 0x00, 0xFF) 

1024 # TODO: implement user-defined styles??? 

1025 

1026 

1027class PaletteRecord(BiffRecord): 

1028 """ 

1029 This record contains the definition of all user-defined colours 

1030 available for cell and object formatting. 

1031 

1032 Record PALETTE, BIFF3-BIFF8: 

1033 

1034 Offset Size Contents 

1035 0 2 Number of following colours (nm). Contains 16 in BIFF3-BIFF4 and 56 in BIFF5-BIFF8. 

1036 2 4*nm List of nm RGB colours 

1037 

1038 The following table shows how colour indexes are used in other records: 

1039 

1040 Colour index Resulting colour or internal list index 

1041 00H Built-in Black (R = 00H, G = 00H, B = 00H) 

1042 01H Built-in White (R = FFH, G = FFH, B = FFH) 

1043 02H Built-in Red (R = FFH, G = 00H, B = 00H) 

1044 03H Built-in Green (R = 00H, G = FFH, B = 00H) 

1045 04H Built-in Blue (R = 00H, G = 00H, B = FFH) 

1046 05H Built-in Yellow (R = FFH, G = FFH, B = 00H) 

1047 06H Built-in Magenta (R = FFH, G = 00H, B = FFH) 

1048 07H Built-in Cyan (R = 00H, G = FFH, B = FFH) 

1049 08H First user-defined colour from the PALETTE record (entry 0 from record colour list) 

1050 ......................... 

1051 

1052 17H (BIFF3-BIFF4) Last user-defined colour from the PALETTE record (entry 15 or 55 from record colour list) 

1053 3FH (BIFF5-BIFF8) 

1054 

1055 18H (BIFF3-BIFF4) System window text colour for border lines (used in records XF, CF, and 

1056 40H (BIFF5-BIFF8) WINDOW2 (BIFF8 only)) 

1057 

1058 19H (BIFF3-BIFF4) System window background colour for pattern background (used in records XF, and CF) 

1059 41H (BIFF5-BIFF8) 

1060 

1061 43H System face colour (dialogue background colour) 

1062 4DH System window text colour for chart border lines 

1063 4EH System window background colour for chart areas 

1064 4FH Automatic colour for chart border lines (seems to be always Black) 

1065 50H System ToolTip background colour (used in note objects) 

1066 51H System ToolTip text colour (used in note objects) 

1067 7FFFH System window text colour for fonts (used in records FONT, EFONT, and CF) 

1068 

1069 """ 

1070 _REC_ID = 0x0092 

1071 

1072 def __init__(self, custom_palette): 

1073 n_colours = len(custom_palette) 

1074 assert n_colours == 56 

1075 # Pack number of colors with little-endian, what xlrd and excel expect. 

1076 self._rec_data = pack('<H', n_colours) 

1077 # Microsoft lists colors in big-endian format with 24 bits/color. 

1078 # Pad LSB of each color with 0x00, and write out in big-endian. 

1079 fmt = '>%dI' % n_colours 

1080 self._rec_data += pack(fmt, *(custom_palette)) 

1081 

1082class BoundSheetRecord(BiffRecord): 

1083 """ 

1084 This record is located in the workbook globals area and represents 

1085 a sheet inside of the workbook. For each sheet a BOUNDSHEET record 

1086 is written. It stores the sheet name and a stream offset to the BOF 

1087 record within the workbook stream. The record is also known 

1088 as BUNDLESHEET. 

1089 

1090 Record BOUNDSHEET, BIFF5-BIFF8: 

1091 Offset Size Contents 

1092 0 4 Absolute stream position of the BOF record of the sheet represented by this record. This 

1093 field is never encrypted in protected files. 

1094 4 1 Visibility: 

1095 00H = Visible 

1096 01H = Hidden 

1097 02H = Strong hidden 

1098 5 1 Sheet type: 

1099 00H = Worksheet 

1100 02H = Chart 

1101 06H = Visual Basic module 

1102 6 var. Sheet name: 

1103 BIFF5/BIFF7: Byte string, 8-bit string length 

1104 BIFF8: Unicode string, 8-bit string length 

1105 """ 

1106 _REC_ID = 0x0085 

1107 

1108 def __init__(self, stream_pos, visibility, sheetname, encoding='ascii'): 

1109 usheetname = upack1(sheetname, encoding) 

1110 uusheetname_len = len(usheetname) 

1111 

1112 self._rec_data = pack('<LBB%ds' % uusheetname_len, stream_pos, visibility, 0x00, usheetname) 

1113 

1114 

1115class ContinueRecord(BiffRecord): 

1116 """ 

1117 Whenever the content of a record exceeds the given limits (see table), 

1118 the record must be split. Several CONTINUE records containing the 

1119 additional data are added after the parent record. 

1120 

1121 BIFF version Maximum data size of a record 

1122 BIFF2-BIFF7 2080 bytes (2084 bytes including record header) 

1123 BIFF8 8224 bytes (8228 bytes including record header) (0x2020) 

1124 

1125 Record CONTINUE, BIFF2-BIFF8: 

1126 Offset Size Contents 

1127 0 var. Data continuation of the previous record 

1128 

1129 Unicode strings are split in a special way. At the beginning of each 

1130 CONTINUE record the option flags byte is repeated. Only the character 

1131 size flag will be set in this flags byte, the Rich-Text flag and the 

1132 Far-East flag are set to zero. In each CONTINUE record it is possible 

1133 that the character size changes from 8-bit characters to 16-bit 

1134 characters and vice versa. 

1135 

1136 Never a Unicode string is split until and including the first 

1137 character. That means, all header fields (string length, option flags, 

1138 optional Rich-Text size, and optional Far-East data size) and the first 

1139 character of the string have to occur together in the leading record, 

1140 or have to be moved completely into the CONTINUE record. Formatting 

1141 runs cannot be split between their components (character index and FONT 

1142 record index). If a string is split between two formatting runs, the 

1143 option flags field will not be repeated in the CONTINUE record. 

1144 """ 

1145 _REC_ID = 0x003C 

1146 

1147 

1148class SSTRecord(BiffRecord): 

1149 """ 

1150 This record contains a list of all strings used anywhere in the 

1151 workbook. Each string occurs only once. The workbook uses indexes into 

1152 the list to reference the strings. 

1153 

1154 Record SST, BIFF8: 

1155 Offset Size Contents 

1156 0 4 Total number of strings in the workbook (see below) 

1157 4 4 Number of following strings (nm) 

1158 8 var. List of nm Unicode strings, 16-bit string length 

1159 

1160 The first field of the SST record counts the total occurrence 

1161 of strings in the workbook. For instance, the string AAA is used 

1162 3 times and the string BBB is used 2 times. The first field contains 

1163 5 and the second field contains 2, followed by the two strings. 

1164 """ 

1165 _REC_ID = 0x00FC 

1166 

1167 

1168class ExtSSTRecord(BiffRecord): 

1169 """ 

1170 This record occurs in conjunction with the SST record. It is used 

1171 by Excel to create a hash table with stream offsets to the SST record 

1172 to optimise string search operations. Excel may not shorten this record 

1173 if strings are deleted from the shared string table, so the last part 

1174 might contain invalid data. The stream indexes in this record divide 

1175 the SST into portions containing a constant number of strings. 

1176 

1177 Record EXTSST, BIFF8: 

1178 

1179 Offset Size Contents 

1180 0 2 Number of strings in a portion, this number is >=8 

1181 2 var. List of OFFSET structures for all portions. Each OFFSET contains the following data: 

1182 Offset Size Contents 

1183 0 4 Absolute stream position of first string of the portion 

1184 4 2 Position of first string of the portion inside of current record, 

1185 including record header. This counter restarts at zero, if the SST 

1186 record is continued with a CONTINUE record. 

1187 6 2 Not used 

1188 """ 

1189 _REC_ID = 0x00FF 

1190 

1191 def __init__(self, sst_stream_pos, str_placement, portions_len): 

1192 extsst = {} 

1193 abs_stream_pos = sst_stream_pos 

1194 str_counter = 0 

1195 portion_counter = 0 

1196 while str_counter < len(str_placement): 

1197 str_chunk_num, pos_in_chunk = str_placement[str_counter] 

1198 if str_chunk_num != portion_counter: 

1199 portion_counter = str_chunk_num 

1200 abs_stream_pos += portions_len[portion_counter-1] 

1201 #print hex(abs_stream_pos) 

1202 str_stream_pos = abs_stream_pos + pos_in_chunk + 4 # header 

1203 extsst[str_counter] = (pos_in_chunk, str_stream_pos) 

1204 str_counter += 1 

1205 

1206 exsst_str_count_delta = max(8, len(str_placement)*8/0x2000) # maybe smth else? 

1207 self._rec_data = pack('<H', exsst_str_count_delta) 

1208 str_counter = 0 

1209 while str_counter < len(str_placement): 

1210 self._rec_data += pack('<IHH', extsst[str_counter][1], extsst[str_counter][0], 0) 

1211 str_counter += exsst_str_count_delta 

1212 

1213class DimensionsRecord(BiffRecord): 

1214 """ 

1215 Record DIMENSIONS, BIFF8: 

1216 

1217 Offset Size Contents 

1218 0 4 Index to first used row 

1219 4 4 Index to last used row, increased by 1 

1220 8 2 Index to first used column 

1221 10 2 Index to last used column, increased by 1 

1222 12 2 Not used 

1223 """ 

1224 _REC_ID = 0x0200 

1225 def __init__(self, first_used_row, last_used_row, first_used_col, last_used_col): 

1226 if first_used_row > last_used_row or first_used_col > last_used_col: 

1227 # Special case: empty worksheet 

1228 first_used_row = first_used_col = 0 

1229 last_used_row = last_used_col = -1 

1230 self._rec_data = pack('<2L3H', 

1231 first_used_row, last_used_row + 1, 

1232 first_used_col, last_used_col + 1, 

1233 0x00) 

1234 

1235 

1236class Window2Record(BiffRecord): 

1237 """ 

1238 Record WINDOW2, BIFF8: 

1239 

1240 Offset Size Contents 

1241 0 2 Option flags (see below) 

1242 2 2 Index to first visible row 

1243 4 2 Index to first visible column 

1244 6 2 Colour index of grid line colour. Note that in BIFF2-BIFF7 an RGB colour is 

1245 written instead. 

1246 8 2 Not used 

1247 10 2 Cached magnification factor in page break preview (in percent); 0 = Default (60%) 

1248 12 2 Cached magnification factor in normal view (in percent); 0 = Default (100%) 

1249 14 4 Not used 

1250 

1251 In BIFF8 this record stores used magnification factors for page break 

1252 preview and normal view. These values are used to restore the 

1253 magnification, when the view is changed. The real magnification of the 

1254 currently active view is stored in the SCL record. The type of the 

1255 active view is stored in the option flags field (see below). 

1256 

1257 0 0001H 0 = Show formula results 1 = Show formulas 

1258 1 0002H 0 = Do not show grid lines 1 = Show grid lines 

1259 2 0004H 0 = Do not show sheet headers 1 = Show sheet headers 

1260 3 0008H 0 = Panes are not frozen 1 = Panes are frozen (freeze) 

1261 4 0010H 0 = Show zero values as empty cells 1 = Show zero values 

1262 5 0020H 0 = Manual grid line colour 1 = Automatic grid line colour 

1263 6 0040H 0 = Columns from left to right 1 = Columns from right to left 

1264 7 0080H 0 = Do not show outline symbols 1 = Show outline symbols 

1265 8 0100H 0 = Keep splits if pane freeze is removed 1 = Remove splits if pane freeze is removed 

1266 9 0200H 0 = Sheet not selected 1 = Sheet selected (BIFF5-BIFF8) 

1267 10 0400H 0 = Sheet not visible 1 = Sheet visible (BIFF5-BIFF8) 

1268 11 0800H 0 = Show in normal view 1 = Show in page break preview (BIFF8) 

1269 

1270 The freeze flag specifies, if a following PANE record describes unfrozen or frozen panes. 

1271 

1272 *** This class appends the optional SCL record *** 

1273 

1274 Record SCL, BIFF4-BIFF8: 

1275 

1276 This record stores the magnification of the active view of the current worksheet. 

1277 In BIFF8 this can be either the normal view or the page break preview. 

1278 This is determined in the WINDOW2 record. The SCL record is part of the 

1279 Sheet View Settings Block. 

1280 

1281 Offset Size Contents 

1282 0 2 Numerator of the view magnification fraction (num) 

1283 2 2 Denumerator [denominator] of the view magnification fraction (den) 

1284 The magnification is stored as reduced fraction. The magnification results from num/den. 

1285 

1286 SJM note: Excel expresses (e.g.) 25% in reduced form i.e. 1/4. Reason unknown. This code 

1287 writes 25/100, and Excel is happy with that. 

1288 

1289 """ 

1290 _REC_ID = 0x023E 

1291 

1292 def __init__(self, options, first_visible_row, first_visible_col, 

1293 grid_colour, preview_magn, normal_magn, scl_magn): 

1294 self._rec_data = pack('<7HL', options, 

1295 first_visible_row, first_visible_col, 

1296 grid_colour, 

1297 0x00, 

1298 preview_magn, normal_magn, 

1299 0x00) 

1300 if scl_magn is not None: 

1301 self._scl_rec = pack('<4H', 0x00A0, 4, scl_magn, 100) 

1302 else: 

1303 self._scl_rec = b'' 

1304 

1305 def get(self): 

1306 return self.get_rec_header() + self._rec_data + self._scl_rec 

1307 

1308 

1309class PanesRecord(BiffRecord): 

1310 """ 

1311 This record stores the position of window panes. It is part of the Sheet 

1312 View Settings Block. If the sheet does not contain any splits, this 

1313 record will not occur. 

1314 A sheet can be split in two different ways, with unfrozen panes or with 

1315 frozen panes. A flag in the WINDOW2 record specifies, if the panes are 

1316 frozen, which affects the contents of this record. 

1317 

1318 Record PANE, BIFF2-BIFF8: 

1319 Offset Size Contents 

1320 0 2 Position of the vertical split 

1321 (px, 0 = No vertical split): 

1322 Unfrozen pane: Width of the left pane(s) 

1323 (in twips = 1/20 of a point) 

1324 Frozen pane: Number of visible 

1325 columns in left pane(s) 

1326 2 2 Position of the horizontal split 

1327 (py, 0 = No horizontal split): 

1328 Unfrozen pane: Height of the top pane(s) 

1329 (in twips = 1/20 of a point) 

1330 Frozen pane: Number of visible 

1331 rows in top pane(s) 

1332 4 2 Index to first visible row 

1333 in bottom pane(s) 

1334 6 2 Index to first visible column 

1335 in right pane(s) 

1336 8 1 Identifier of pane with active 

1337 cell cursor 

1338 [9] 1 Not used (BIFF5-BIFF8 only, not written 

1339 in BIFF2-BIFF4) 

1340 

1341 If the panes are frozen, pane 0 is always active, regardless 

1342 of the cursor position. The correct identifiers for all possible 

1343 combinations of visible panes are shown in the following pictures. 

1344 

1345 px = 0, py = 0 px = 0, py > 0 

1346 -------------------------- ------------|------------- 

1347 | | | | 

1348 | | | 3 | 

1349 | | | | 

1350 - 3 - -------------------------- 

1351 | | | | 

1352 | | | 2 | 

1353 | | | | 

1354 -------------------------- ------------|------------- 

1355 

1356 px > 0, py = 0 px > 0, py > 0 

1357 ------------|------------- ------------|------------- 

1358 | | | | | | 

1359 | | | | 3 | 2 | 

1360 | | | | | | 

1361 - 3 | 1 - -------------------------- 

1362 | | | | | | 

1363 | | | | 1 | 0 | 

1364 | | | | | | 

1365 ------------|------------- ------------|------------- 

1366 """ 

1367 _REC_ID = 0x0041 

1368 

1369 valid_active_pane = { 

1370 # entries are of the form: 

1371 # (int(px > 0),int(px>0)) -> allowed values 

1372 (0,0):(3,), 

1373 (0,1):(2,3), 

1374 (1,0):(1,3), 

1375 (1,1):(0,1,2,3), 

1376 } 

1377 

1378 def __init__(self, px, py, first_row_bottom, first_col_right, active_pane): 

1379 allowed = self.valid_active_pane.get( 

1380 (int(px > 0),int(py > 0)) 

1381 ) 

1382 if active_pane not in allowed: 

1383 raise ValueError('Cannot set active_pane to %i, must be one of %s' % ( 

1384 active_pane, ', '.join(allowed) 

1385 )) 

1386 self._rec_data = pack('<5H', 

1387 px, py, 

1388 first_row_bottom, first_col_right, 

1389 active_pane) 

1390 

1391 

1392class RowRecord(BiffRecord): 

1393 """ 

1394 This record contains the properties of a single row in a sheet. Rows 

1395 and cells in a sheet are divided into blocks of 32 rows. 

1396 

1397 Record ROW, BIFF3-BIFF8: 

1398 

1399 Offset Size Contents 

1400 0 2 Index of this row 

1401 2 2 Index to column of the first cell which is described by a cell record 

1402 4 2 Index to column of the last cell which is described by a cell record, 

1403 increased by 1 

1404 6 2 Bit Mask Contents 

1405 14-0 7FFFH Height of the row, in twips = 1/20 of a point 

1406 15 8000H 0 = Row has custom height; 1 = Row has default height 

1407 8 2 Not used 

1408 10 2 In BIFF3-BIFF4 this field contains a relative offset 

1409 to calculate stream position of the first cell record 

1410 for this row. In BIFF5-BIFF8 this field is not used 

1411 anymore, but the DBCELL record instead. 

1412 12 4 Option flags and default row formatting: 

1413 Bit Mask Contents 

1414 2-0 00000007H Outline level of the row 

1415 4 00000010H 1 = Outline group starts or ends here (depending 

1416 on where the outline buttons are located, 

1417 see WSBOOL record), and is collapsed 

1418 5 00000020H 1 = Row is hidden (manually, or by a filter or outline group) 

1419 6 00000040H 1 = Row height and default font height do not match 

1420 7 00000080H 1 = Row has explicit default format (fl) 

1421 8 00000100H Always 1 

1422 27-16 0FFF0000H If fl=1: Index to default XF record 

1423 28 10000000H 1 = Additional space above the row. This flag is set, 

1424 if the upper border of at least one cell in this row 

1425 or if the lower border of at least one cell in the row 

1426 above is formatted with a thick line style. 

1427 Thin and medium line styles are not taken into account. 

1428 29 20000000H 1 = Additional space below the row. This flag is set, 

1429 if the lower border of at least one cell in this row 

1430 or if the upper border of at least one cell in the row 

1431 below is formatted with a medium or thick line style. 

1432 Thin line styles are not taken into account. 

1433 """ 

1434 

1435 _REC_ID = 0x0208 

1436 

1437 def __init__(self, index, first_col, last_col, height_options, options): 

1438 self._rec_data = pack('<6HL', index, first_col, last_col + 1, 

1439 height_options, 

1440 0x00, 0x00, 

1441 options) 

1442 

1443class LabelSSTRecord(BiffRecord): 

1444 """ 

1445 This record represents a cell that contains a string. It replaces the 

1446 LABEL record and RSTRING record used in BIFF2-BIFF7. 

1447 """ 

1448 _REC_ID = 0x00FD 

1449 

1450 def __init__(self, row, col, xf_idx, sst_idx): 

1451 self._rec_data = pack('<3HL', row, col, xf_idx, sst_idx) 

1452 

1453 

1454class MergedCellsRecord(BiffRecord): 

1455 """ 

1456 This record contains all merged cell ranges of the current sheet. 

1457 

1458 Record MERGEDCELLS, BIFF8: 

1459 

1460 Offset Size Contents 

1461 0 var. Cell range address list with all merged ranges 

1462 

1463 ------------------------------------------------------------------ 

1464 

1465 A cell range address list consists of a field with the number of ranges 

1466 and the list of the range addresses. 

1467 

1468 Cell range address list, BIFF8: 

1469 

1470 Offset Size Contents 

1471 0 2 Number of following cell range addresses (nm) 

1472 2 8*nm List of nm cell range addresses 

1473 

1474 --------------------------------------------------------------------- 

1475 Cell range address, BIFF8: 

1476 

1477 Offset Size Contents 

1478 0 2 Index to first row 

1479 2 2 Index to last row 

1480 4 2 Index to first column 

1481 6 2 Index to last column 

1482 

1483 """ 

1484 _REC_ID = 0x00E5 

1485 

1486 def __init__(self, merged_list): 

1487 i = len(merged_list) - 1 

1488 while i >= 0: 

1489 j = 0 

1490 merged = b'' 

1491 while (i >= 0) and (j < 0x403): 

1492 r1, r2, c1, c2 = merged_list[i] 

1493 merged += pack('<4H', r1, r2, c1, c2) 

1494 i -= 1 

1495 j += 1 

1496 self._rec_data += pack('<3H', self._REC_ID, len(merged) + 2, j) + \ 

1497 merged 

1498 

1499 # for some reason Excel doesn't use CONTINUE 

1500 def get(self): 

1501 return self._rec_data 

1502 

1503class MulBlankRecord(BiffRecord): 

1504 """ 

1505 This record represents a cell range of empty cells. All cells are 

1506 located in the same row. 

1507 

1508 Record MULBLANK, BIFF5-BIFF8: 

1509 

1510 Offset Size Contents 

1511 0 2 Index to row 

1512 2 2 Index to first column (fc) 

1513 4 2*nc List of nc=lc-fc+1 16-bit indexes to XF records 

1514 4+2*nc 2 Index to last column (lc) 

1515 """ 

1516 _REC_ID = 0x00BE 

1517 

1518 def __init__(self, row, first_col, last_col, xf_index): 

1519 blanks_count = last_col-first_col+1 

1520 self._rec_data = pack('<%dH' % blanks_count, *([xf_index] * blanks_count)) 

1521 self._rec_data = pack('<2H', row, first_col) + self._rec_data + pack('<H', last_col) 

1522 

1523 

1524class BlankRecord(BiffRecord): 

1525 """ 

1526 This record represents an empty cell. 

1527 

1528 Record BLANK, BIFF5-BIFF8: 

1529 

1530 Offset Size Contents 

1531 0 2 Index to row 

1532 2 2 Index to first column (fc) 

1533 4 2 indexes to XF record 

1534 """ 

1535 _REC_ID = 0x0201 

1536 

1537 def __init__(self, row, col, xf_index): 

1538 self._rec_data = pack('<3H', row, col, xf_index) 

1539 

1540 

1541class RKRecord(BiffRecord): 

1542 """ 

1543 This record represents a cell that contains an RK value (encoded integer or 

1544 floating-point value). If a floating-point value cannot be encoded to an RK value, 

1545 a NUMBER record will be written. 

1546 """ 

1547 _REC_ID = 0x027E 

1548 

1549 def __init__(self, row, col, xf_index, rk_encoded): 

1550 self._rec_data = pack('<3Hi', row, col, xf_index, rk_encoded) 

1551 

1552 

1553class NumberRecord(BiffRecord): 

1554 """ 

1555 This record represents a cell that contains an IEEE-754 floating-point value. 

1556 """ 

1557 _REC_ID = 0x0203 

1558 

1559 def __init__(self, row, col, xf_index, number): 

1560 self._rec_data = pack('<3Hd', row, col, xf_index, number) 

1561 

1562class BoolErrRecord(BiffRecord): 

1563 """ 

1564 This record represents a cell that contains a boolean or error value. 

1565 """ 

1566 _REC_ID = 0x0205 

1567 

1568 def __init__(self, row, col, xf_index, number, is_error): 

1569 self._rec_data = pack('<3HBB', row, col, xf_index, number, is_error) 

1570 

1571 

1572class FormulaRecord(BiffRecord): 

1573 """ 

1574 Offset Size Contents 

1575 0 2 Index to row 

1576 2 2 Index to column 

1577 4 2 Index to XF record 

1578 6 8 Result of the formula 

1579 14 2 Option flags: 

1580 Bit Mask Contents 

1581 0 0001H 1 = Recalculate always 

1582 1 0002H 1 = Calculate on open 

1583 3 0008H 1 = Part of a shared formula 

1584 16 4 Not used 

1585 20 var. Formula data (RPN token array) 

1586 

1587 """ 

1588 _REC_ID = 0x0006 

1589 

1590 def __init__(self, row, col, xf_index, rpn, calc_flags=0): 

1591 self._rec_data = pack('<3HQHL', row, col, xf_index, 0xFFFF000000000003, calc_flags & 3, 0) + rpn 

1592 

1593 

1594class GutsRecord(BiffRecord): 

1595 """ 

1596 This record contains information about the layout of outline symbols. 

1597 

1598 Record GUTS, BIFF3-BIFF8: 

1599 

1600 Offset Size Contents 

1601 0 2 Width of the area to display row outlines (left of the sheet), in pixel 

1602 2 2 Height of the area to display column outlines (above the sheet), in pixel 

1603 4 2 Number of visible row outline levels (used row levels + 1; or 0, if not used) 

1604 6 2 Number of visible column outline levels (used column levels + 1; or 0, if not used) 

1605 

1606 """ 

1607 

1608 _REC_ID = 0x0080 

1609 

1610 def __init__(self, row_gut_width, col_gut_height, row_visible_levels, col_visible_levels): 

1611 self._rec_data = pack('<4H', row_gut_width, col_gut_height, row_visible_levels, col_visible_levels) 

1612 

1613class WSBoolRecord(BiffRecord): 

1614 """ 

1615 This record stores a 16 bit value with Boolean options for the current 

1616 sheet. From BIFF5 on the "Save external linked values" option is moved 

1617 to the record BOOKBOOL. 

1618 

1619 Option flags of record WSBOOL, BIFF3-BIFF8: 

1620 

1621 Bit Mask Contents 

1622 0 0001H 0 = Do not show automatic page breaks 

1623 1 = Show automatic page breaks 

1624 4 0010H 0 = Standard sheet 

1625 1 = Dialogue sheet (BIFF5-BIFF8) 

1626 5 0020H 0 = No automatic styles in outlines 

1627 1 = Apply automatic styles to outlines 

1628 6 0040H 0 = Outline buttons above outline group 

1629 1 = Outline buttons below outline group 

1630 7 0080H 0 = Outline buttons left of outline group 

1631 1 = Outline buttons right of outline group 

1632 8 0100H 0 = Scale printout in percent 

1633 1 = Fit printout to number of pages 

1634 9 0200H 0 = Save external linked values (BIFF3?BIFF4 only) 

1635 1 = Do not save external linked values (BIFF3?BIFF4 only) 

1636 10 0400H 0 = Do not show row outline symbols 

1637 1 = Show row outline symbols 

1638 11 0800H 0 = Do not show column outline symbols 

1639 1 = Show column outline symbols 

1640 13-12 3000H These flags specify the arrangement of windows. 

1641 They are stored in BIFF4 only. 

1642 00 = Arrange windows tiled 

1643 01 = Arrange windows horizontal 

1644 10 = Arrange windows vertical112 = Arrange windows cascaded 

1645 The following flags are valid for BIFF4-BIFF8 only: 

1646 14 4000H 0 = Standard expression evaluation 

1647 1 = Alternative expression evaluation 

1648 15 8000H 0 = Standard formula entries 

1649 1 = Alternative formula entries 

1650 

1651 """ 

1652 _REC_ID = 0x0081 

1653 

1654 def __init__(self, options): 

1655 self._rec_data = pack('<H', options) 

1656 

1657class ColInfoRecord(BiffRecord): 

1658 """ 

1659 This record specifies the width for a given range of columns. 

1660 If a column does not have a corresponding COLINFO record, 

1661 the width specified in the record STANDARDWIDTH is used. If 

1662 this record is also not present, the contents of the record 

1663 DEFCOLWIDTH is used instead. 

1664 This record also specifies a default XF record to use for 

1665 cells in the columns that are not described by any cell record 

1666 (which contain the XF index for that cell). Additionally, 

1667 the option flags field contains hidden, outline, and collapsed 

1668 options applied at the columns. 

1669 

1670 Record COLINFO, BIFF3-BIFF8: 

1671 

1672 Offset Size Contents 

1673 0 2 Index to first column in the range 

1674 2 2 Index to last column in the range 

1675 4 2 Width of the columns in 1/256 of the width of the zero character, using default font 

1676 (first FONT record in the file) 

1677 6 2 Index to XF record for default column formatting 

1678 8 2 Option flags: 

1679 Bits Mask Contents 

1680 0 0001H 1 = Columns are hidden 

1681 10-8 0700H Outline level of the columns (0 = no outline) 

1682 12 1000H 1 = Columns are collapsed 

1683 10 2 Not used 

1684 

1685 """ 

1686 _REC_ID = 0x007D 

1687 

1688 def __init__(self, first_col, last_col, width, xf_index, options, unused): 

1689 self._rec_data = pack('<6H', first_col, last_col, width, xf_index, options, unused) 

1690 

1691class CalcModeRecord(BiffRecord): 

1692 """ 

1693 This record is part of the Calculation Settings Block. 

1694 It specifies whether to calculate formulas manually, 

1695 automatically or automatically except for multiple table operations. 

1696 

1697 Record CALCMODE, BIFF2-BIFF8: 

1698 

1699 Offset Size Contents 

1700 0 2 FFFFH = automatic except for multiple table operations 

1701 0000H = manually 

1702 0001H = automatically (default) 

1703 """ 

1704 _REC_ID = 0x000D 

1705 

1706 def __init__(self, calc_mode): 

1707 self._rec_data = pack('<h', calc_mode) 

1708 

1709 

1710class CalcCountRecord(BiffRecord): 

1711 """ 

1712 This record is part of the Calculation Settings Block. It specifies the maximum 

1713 number of times the formulas should be iteratively calculated. This is a fail-safe 

1714 against mutually recursive formulas locking up a spreadsheet application. 

1715 

1716 Record CALCCOUNT, BIFF2-BIFF8: 

1717 

1718 Offset Size Contents 

1719 0 2 Maximum number of iterations allowed in circular references 

1720 """ 

1721 

1722 _REC_ID = 0x000C 

1723 

1724 def __init__(self, calc_count): 

1725 self._rec_data = pack('<H', calc_count) 

1726 

1727class RefModeRecord(BiffRecord): 

1728 """ 

1729 This record is part of the Calculation Settings Block. 

1730 It stores which method is used to show cell addresses in formulas. 

1731 The “RC” mode uses numeric indexes for rows and columns, 

1732 i.e. “R(1)C(-1)”, or “R1C1:R2C2”. 

1733 The “A1” mode uses characters for columns and numbers for rows, 

1734 i.e. “B1”, or “$A$1:$B$2”. 

1735 

1736 Record REFMODE, BIFF2-BIFF8: 

1737 

1738 Offset Size Contents 

1739 0 2 0 = RC mode; 1 = A1 mode 

1740 

1741 """ 

1742 _REC_ID = 0x00F 

1743 

1744 def __init__(self, ref_mode): 

1745 self._rec_data = pack('<H', ref_mode) 

1746 

1747class IterationRecord(BiffRecord): 

1748 """ 

1749 This record is part of the Calculation Settings Block. 

1750 It stores if iterations are allowed while calculating recursive formulas. 

1751 

1752 Record ITERATION, BIFF2-BIFF8: 

1753 

1754 Offset Size Contents 

1755 0 2 0 = Iterations off; 1 = Iterations on 

1756 """ 

1757 _REC_ID = 0x011 

1758 

1759 def __init__(self, iterations_on): 

1760 self._rec_data = pack('<H', iterations_on) 

1761 

1762class DeltaRecord(BiffRecord): 

1763 """ 

1764 This record is part of the Calculation Settings Block. 

1765 It stores the maximum change of the result to exit an iteration. 

1766 

1767 Record DELTA, BIFF2-BIFF8: 

1768 

1769 Offset Size Contents 

1770 0 8 Maximum change in iteration 

1771 (IEEE 754 floating-point value, 

1772 64bit double precision) 

1773 """ 

1774 _REC_ID = 0x010 

1775 

1776 def __init__(self, delta): 

1777 self._rec_data = pack('<d', delta) 

1778 

1779class SaveRecalcRecord(BiffRecord): 

1780 """ 

1781 This record is part of the Calculation Settings Block. 

1782 It contains the “Recalculate before save” option in 

1783 Excel's calculation settings dialogue. 

1784 

1785 Record SAVERECALC, BIFF3-BIFF8: 

1786 

1787 Offset Size Contents 

1788 0 2 0 = Do not recalculate; 

1789 1 = Recalculate before saving the document 

1790 

1791 """ 

1792 _REC_ID = 0x05F 

1793 

1794 def __init__(self, recalc): 

1795 self._rec_data = pack('<H', recalc) 

1796 

1797class PrintHeadersRecord(BiffRecord): 

1798 """ 

1799 This record stores if the row and column headers 

1800 (the areas with row numbers and column letters) will be printed. 

1801 

1802 Record PRINTHEADERS, BIFF2-BIFF8: 

1803 

1804 Offset Size Contents 

1805 0 2 0 = Do not print row/column headers; 

1806 1 = Print row/column headers 

1807 """ 

1808 _REC_ID = 0x02A 

1809 

1810 def __init__(self, print_headers): 

1811 self._rec_data = pack('<H', print_headers) 

1812 

1813 

1814class PrintGridLinesRecord(BiffRecord): 

1815 """ 

1816 This record stores if sheet grid lines will be printed. 

1817 

1818 Record PRINTGRIDLINES, BIFF2-BIFF8: 

1819 

1820 Offset Size Contents 

1821 0 2 0 = Do not print sheet grid lines; 

1822 1 = Print sheet grid lines 

1823 

1824 """ 

1825 _REC_ID = 0x02B 

1826 

1827 def __init__(self, print_grid): 

1828 self._rec_data = pack('<H', print_grid) 

1829 

1830 

1831class GridSetRecord(BiffRecord): 

1832 """ 

1833 This record specifies if the option to print sheet grid lines 

1834 (record PRINTGRIDLINES) has ever been changed. 

1835 

1836 Record GRIDSET, BIFF3-BIFF8: 

1837 

1838 Offset Size Contents 

1839 0 2 0 = Print grid lines option never changed 

1840 1 = Print grid lines option changed 

1841 """ 

1842 _REC_ID = 0x082 

1843 

1844 def __init__(self, print_grid_changed): 

1845 self._rec_data = pack('<H', print_grid_changed) 

1846 

1847 

1848class DefaultRowHeightRecord(BiffRecord): 

1849 """ 

1850 This record specifies the default height and default flags 

1851 for rows that do not have a corresponding ROW record. 

1852 

1853 Record DEFAULTROWHEIGHT, BIFF3-BIFF8: 

1854 

1855 Offset Size Contents 

1856 0 2 Option flags: 

1857 Bit Mask Contents 

1858 0 0001H 1 = Row height and default font height do not match 

1859 1 0002H 1 = Row is hidden 

1860 2 0004H 1 = Additional space above the row 

1861 3 0008H 1 = Additional space below the row 

1862 2 2 Default height for unused rows, in twips = 1/20 of a point 

1863 

1864 """ 

1865 _REC_ID = 0x0225 

1866 

1867 def __init__(self, options, def_height): 

1868 self._rec_data = pack('<2H', options, def_height) 

1869 

1870 

1871class DefColWidthRecord(BiffRecord): 

1872 """ 

1873 This record specifies the default column width for columns that 

1874 do not have a specific width set using the record COLINFO or COLWIDTH. 

1875 This record has no effect, if a STANDARDWIDTH record is present in the file. 

1876 

1877 Record DEFCOLWIDTH, BIFF2-BIFF8: 

1878 

1879 Offset Size Contents 

1880 0 2 Column width in characters, using the width of the zero 

1881 character from default font (first FONT record in the file) 

1882 """ 

1883 _REC_ID = 0x0055 

1884 

1885 def __init__(self, def_width): 

1886 self._rec_data = pack('<H', options, def_width) 

1887 

1888class HorizontalPageBreaksRecord(BiffRecord): 

1889 """ 

1890 This record is part of the Page Settings Block. It contains all 

1891 horizontal manual page breaks. 

1892 

1893 Record HORIZONTALPAGEBREAKS, BIFF8: 

1894 Offset Size Contents 

1895 0 2 Number of following row index structures (nm) 

1896 2 6nm List of nm row index structures. Each row index 

1897 structure contains: 

1898 Offset Size Contents 

1899 0 2 Index to first row below the page break 

1900 2 2 Index to first column of this page break 

1901 4 2 Index to last column of this page break 

1902 

1903 The row indexes in the lists must be ordered ascending. 

1904 If in BIFF8 a row contains several page breaks, they must be ordered 

1905 ascending by start column index. 

1906 """ 

1907 _REC_ID = 0x001B 

1908 

1909 def __init__(self, breaks_list): 

1910 self._rec_data = pack('<H', len(breaks_list)) 

1911 for r, c1, c2 in breaks_list: 

1912 self._rec_data += pack('<3H', r, c1, c2) 

1913 

1914class VerticalPageBreaksRecord(BiffRecord): 

1915 """ 

1916 This record is part of the Page Settings Block. It contains all 

1917 vertical manual page breaks. 

1918 

1919 Record VERTICALPAGEBREAKS, BIFF8: 

1920 Offset Size Contents 

1921 0 2 Number of following column index structures (nm) 

1922 2 6nm List of nm column index structures. Each column index 

1923 structure contains: 

1924 Offset Size Contents 

1925 0 2 Index to first column following the page 

1926 break 

1927 2 2 Index to first row of this page break 

1928 4 2 Index to last row of this page break 

1929 

1930 The column indexes in the lists must be ordered ascending. 

1931 If in BIFF8 a column contains several page breaks, they must be ordered 

1932 ascending by start row index. 

1933 """ 

1934 _REC_ID = 0x001A 

1935 

1936 def __init__(self, breaks_list): 

1937 self._rec_data = pack('<H', len(breaks_list)) 

1938 for r, c1, c2 in breaks_list: 

1939 self._rec_data += pack('<3H', r, c1, c2) 

1940 

1941class HeaderRecord(BiffRecord): 

1942 """ 

1943 This record is part of the Page Settings Block. It specifies the 

1944 page header string for the current worksheet. If this record is not 

1945 present or completely empty (record size is 0), the sheet does not 

1946 contain a page header. 

1947 

1948 Record HEADER for non-empty page header, BIFF2-BIFF8: 

1949 Offset Size Contents 

1950 0 var. Page header string 

1951 BIFF2-BIFF7: Non-empty byte string, 8bit string 

1952 length 

1953 BIFF8: Non-empty Unicode string, 16bit string length 

1954 The header string may contain special commands, i.e. placeholders for 

1955 the page number, current date, or text formatting attributes. These 

1956 fields are represented by single letters (exception: font name and 

1957 size, see below) with a leading ampersand ("&"). If the ampersand 

1958 is part of the regular header text, it will be duplicated ("&&"). The 

1959 page header is divided into 3 sections: the left, the centred, and the 

1960 right section. Each section is introduced by a special command. All 

1961 text and all commands following are part of the selected section. Each 

1962 section starts with the text formatting specified in the default font 

1963 (first FONT record in the file). Active formatting attributes from 

1964 a previous section do not go into the next section. 

1965 

1966 The following table shows all available commands: 

1967 

1968 Command Contents 

1969 && The "&" character itself 

1970 &L Start of the left section 

1971 &C Start of the centred section 

1972 &R Start of the right section 

1973 &P Current page number 

1974 &N Page count 

1975 &D Current date 

1976 &T Current time 

1977 &A Sheet name (BIFF5-BIFF8) 

1978 &F File name without path 

1979 &Z File path without file name (BIFF8X) 

1980 &G Picture (BIFF8X) 

1981 &B Bold on/off (BIFF2-BIFF4) 

1982 &I Italic on/off (BIFF2-BIFF4) 

1983 &U Underlining on/off 

1984 &E Double underlining on/off (BIFF5-BIFF8) 

1985 &S Strikeout on/off 

1986 &X Superscript on/off (BIFF5-BIFF8) 

1987 &Y Subscript on/off (BIFF5-BIFF8) 

1988 &"<fontname>" Set new font <fontname> 

1989 &"<fontname>,<fontstyle>" 

1990 Set new font with specified style <fontstyle>. 

1991 The style <fontstyle> is in most cases one of 

1992 "Regular", "Bold", "Italic", or "Bold Italic". 

1993 But this setting is dependent on the used font, 

1994 it may differ (localised style names, or "Standard", 

1995 "Oblique", ...). (BIFF5-BIFF8) 

1996 &<fontheight> Set font height in points (<fontheight> is a decimal value). 

1997 If this command is followed by a plain number to be printed 

1998 in the header, it will be separated from the font height 

1999 with a space character. 

2000 

2001 """ 

2002 _REC_ID = 0x0014 

2003 

2004 def __init__(self, header_str): 

2005 self._rec_data = upack2(header_str) 

2006 

2007class FooterRecord(BiffRecord): 

2008 """ 

2009 Semantic is equal to HEADER record 

2010 """ 

2011 _REC_ID = 0x0015 

2012 

2013 def __init__(self, footer_str): 

2014 self._rec_data = upack2(footer_str) 

2015 

2016 

2017class HCenterRecord(BiffRecord): 

2018 """ 

2019 This record is part of the Page Settings Block. It specifies if the 

2020 sheet is centred horizontally when printed. 

2021 

2022 Record HCENTER, BIFF3-BIFF8: 

2023 

2024 Offset Size Contents 

2025 0 2 0 = Print sheet left aligned 

2026 1 = Print sheet centred horizontally 

2027 

2028 """ 

2029 _REC_ID = 0x0083 

2030 

2031 def __init__(self, is_horz_center): 

2032 self._rec_data = pack('<H', is_horz_center) 

2033 

2034 

2035class VCenterRecord(BiffRecord): 

2036 """ 

2037 This record is part of the Page Settings Block. It specifies if the 

2038 sheet is centred vertically when printed. 

2039 

2040 Record VCENTER, BIFF3-BIFF8: 

2041 

2042 Offset Size Contents 

2043 0 2 0 = Print sheet aligned at top page border 

2044 1 = Print sheet vertically centred 

2045 

2046 """ 

2047 _REC_ID = 0x0084 

2048 

2049 def __init__(self, is_vert_center): 

2050 self._rec_data = pack('<H', is_vert_center) 

2051 

2052 

2053class LeftMarginRecord(BiffRecord): 

2054 """ 

2055 This record is part of the Page Settings Block. It contains the left 

2056 page margin of the current worksheet. 

2057 

2058 Record LEFTMARGIN, BIFF2-BIFF8: 

2059 

2060 Offset Size Contents 

2061 0 8 Left page margin in inches 

2062 (IEEE 754 floating-point value, 64bit double precision) 

2063 

2064 """ 

2065 _REC_ID = 0x0026 

2066 

2067 def __init__(self, margin): 

2068 self._rec_data = pack('<d', margin) 

2069 

2070 

2071class RightMarginRecord(BiffRecord): 

2072 """ 

2073 This record is part of the Page Settings Block. It contains the right 

2074 page margin of the current worksheet. 

2075 

2076 Offset Size Contents 

2077 0 8 Right page margin in inches 

2078 (IEEE 754 floating-point value, 64?bit double precision) 

2079 

2080 """ 

2081 _REC_ID = 0x0027 

2082 

2083 def __init__(self, margin): 

2084 self._rec_data = pack('<d', margin) 

2085 

2086class TopMarginRecord(BiffRecord): 

2087 """ 

2088 This record is part of the Page Settings Block. It contains the top 

2089 page margin of the current worksheet. 

2090 

2091 Offset Size Contents 

2092 0 8 Top page margin in inches 

2093 (IEEE 754 floating-point value, 64?bit double precision) 

2094 

2095 """ 

2096 _REC_ID = 0x0028 

2097 

2098 def __init__(self, margin): 

2099 self._rec_data = pack('<d', margin) 

2100 

2101 

2102class BottomMarginRecord(BiffRecord): 

2103 """ 

2104 This record is part of the Page Settings Block. It contains the bottom 

2105 page margin of the current worksheet. 

2106 

2107 Offset Size Contents 

2108 0 8 Bottom page margin in inches 

2109 (IEEE 754 floating-point value, 64?bit double precision) 

2110 

2111 """ 

2112 _REC_ID = 0x0029 

2113 

2114 def __init__(self, margin): 

2115 self._rec_data = pack('<d', margin) 

2116 

2117class SetupPageRecord(BiffRecord): 

2118 """ 

2119 This record is part of the Page Settings Block. It stores the page 

2120 format settings of the current sheet. The pages may be scaled in 

2121 percent or by using an absolute number of pages. This setting is 

2122 located in the WSBOOL record. If pages are scaled in percent, 

2123 the scaling factor in this record is used, otherwise the "Fit to 

2124 pages" values. One of the "Fit to pages" values may be 0. In this case 

2125 the sheet is scaled to fit only to the other value. 

2126 

2127 Record SETUP, BIFF5-BIFF8: 

2128 

2129 Offset Size Contents 

2130 0 2 Paper size (see below) 

2131 2 2 Scaling factor in percent 

2132 4 2 Start page number 

2133 6 2 Fit worksheet width to this number of pages 

2134 (0 = use as many as needed) 

2135 8 2 Fit worksheet height to this number of pages 

2136 (0 = use as many as needed) 

2137 10 2 Option flags: 

2138 Bit Mask Contents 

2139 0 0001H 0 = Print pages in columns 

2140 1 = Print pages in rows 

2141 1 0002H 0 = Landscape 

2142 1 = Portrait 

2143 2 0004H 1 = Paper size, scaling factor, 

2144 paper orientation (portrait/landscape), 

2145 print resolution and number of copies 

2146 are not initialised 

2147 3 0008H 0 = Print coloured 

2148 1 = Print black and white 

2149 4 0010H 0 = Default print quality 

2150 1 = Draft quality 

2151 5 0020H 0 = Do not print cell notes 

2152 1 = Print cell notes 

2153 6 0040H 0 = Paper orientation setting is valid 

2154 1 = Paper orientation setting not 

2155 initialised 

2156 7 0080H 0 = Automatic page numbers 

2157 1 = Use start page number 

2158 The following flags are valid for BIFF8 only: 

2159 9 0200H 0 = Print notes as displayed 

2160 1 = Print notes at end of sheet 

2161 11-10 0C00H 00 = Print errors as displayed 

2162 01 = Do not print errors 

2163 10 = Print errors as "--" 

2164 11 = Print errors as "#N/A!" 

2165 12 2 Print resolution in dpi 

2166 14 2 Vertical print resolution in dpi 

2167 16 8 Header margin (IEEE 754 floating-point value, 

2168 64bit double precision) 

2169 24 8 Footer margin (IEEE 754 floating-point value, 

2170 64bit double precision) 

2171 32 2 Number of copies to print 

2172 

2173 

2174 PAPER TYPES: 

2175 

2176 Index Paper type Paper size 

2177 0 Undefined 

2178 1 Letter 8 1/2" x 11" 

2179 2 Letter small 8 1/2" x 11" 

2180 3 Tabloid 11" x 17" 

2181 4 Ledger 17" x 11" 

2182 5 Legal 8 1/2" x 14" 

2183 6 Statement 5 1/2" x 8 1/2" 

2184 7 Executive 7 1/4" x 10 1/2" 

2185 8 A3 297mm x 420mm 

2186 9 A4 210mm x 297mm 

2187 10 A4 small 210mm x 297mm 

2188 11 A5 148mm x 210mm 

2189 12 B4 (JIS) 257mm x 364mm 

2190 13 B5 (JIS) 182mm x 257mm 

2191 14 Folio 8 1/2" x 13" 

2192 15 Quarto 215mm x 275mm 

2193 16 10x14 10" x 14" 

2194 17 11x17 11" x 17" 

2195 18 Note 8 1/2" x 11" 

2196 19 Envelope #9 3 7/8" x 8 7/8" 

2197 20 Envelope #10 4 1/8" x 9 1/2" 

2198 21 Envelope #11 4 1/2" x 10 3/8" 

2199 22 Envelope #12 4 3/4" x 11" 

2200 23 Envelope #14 5" x 11 1/2" 

2201 24 C 17" x 22" 

2202 25 D 22" x 34" 

2203 26 E 34" x 44" 

2204 27 Envelope DL 110mm x 220mm 

2205 28 Envelope C5 162mm x 229mm 

2206 29 Envelope C3 324mm x 458mm 

2207 30 Envelope C4 229mm x 324mm 

2208 31 Envelope C6 114mm x 162mm 

2209 32 Envelope C6/C5 114mm x 229mm 

2210 33 B4 (ISO) 250mm x 353mm 

2211 34 B5 (ISO) 176mm x 250mm 

2212 35 B6 (ISO) 125mm x 176mm 

2213 36 Envelope Italy 110mm x 230mm 

2214 37 Envelope Monarch 3 7/8" x 7 1/2" 

2215 38 63/4 Envelope 3 5/8" x 6 1/2" 

2216 39 US Standard Fanfold 14 7/8" x 11" 

2217 40 German Std. Fanfold 8 1/2" x 12" 

2218 41 German Legal Fanfold 8 1/2" x 13" 

2219 42 B4 (ISO) 250mm x 353mm 

2220 43 Japanese Postcard 100mm x 148mm 

2221 44 9x11 9" x 11" 

2222 45 10x11 10" x 11" 

2223 46 15x11 15" x 11" 

2224 47 Envelope Invite 220mm x 220mm 

2225 48 Undefined 

2226 49 Undefined 

2227 50 Letter Extra 9 1/2" x 12" 

2228 51 Legal Extra 9 1/2" x 15" 

2229 52 Tabloid Extra 11 11/16" x 18" 

2230 53 A4 Extra 235mm x 322mm 

2231 54 Letter Transverse 8 1/2" x 11" 

2232 55 A4 Transverse 210mm x 297mm 

2233 56 Letter Extra Transv. 9 1/2" x 12" 

2234 57 Super A/A4 227mm x 356mm 

2235 58 Super B/A3 305mm x 487mm 

2236 59 Letter Plus 8 1/2" x 12 11/16" 

2237 60 A4 Plus 210mm x 330mm 

2238 61 A5 Transverse 148mm x 210mm 

2239 62 B5 (JIS) Transverse 182mm x 257mm 

2240 63 A3 Extra 322mm x 445mm 

2241 64 A5 Extra 174mm x 235mm 

2242 65 B5 (ISO) Extra 201mm x 276mm 

2243 66 A2 420mm x 594mm 

2244 67 A3 Transverse 297mm x 420mm 

2245 68 A3 Extra Transverse 322mm x 445mm 

2246 69 Dbl. Japanese Postcard 200mm x 148mm 

2247 70 A6 105mm x 148mm 

2248 71 

2249 72 

2250 73 

2251 74 

2252 75 Letter Rotated 11" x 8 1/2" 

2253 76 A3 Rotated 420mm x 297mm 

2254 77 A4 Rotated 297mm x 210mm 

2255 78 A5 Rotated 210mm x 148mm 

2256 79 B4 (JIS) Rotated 364mm x 257mm 

2257 80 B5 (JIS) Rotated 257mm x 182mm 

2258 81 Japanese Postcard Rot. 148mm x 100mm 

2259 82 Dbl. Jap. Postcard Rot. 148mm x 200mm 

2260 83 A6 Rotated 148mm x 105mm 

2261 84 

2262 85 

2263 86 

2264 87 

2265 88 B6 (JIS) 128mm x 182mm 

2266 89 B6 (JIS) Rotated 182mm x 128mm 

2267 90 12x11 12" x 11" 

2268 

2269 """ 

2270 _REC_ID = 0x00A1 

2271 def __init__(self, paper, scaling, start_num, fit_width_to, fit_height_to, 

2272 options, 

2273 hres, vres, 

2274 header_margin, footer_margin, 

2275 num_copies): 

2276 self._rec_data = pack('<8H2dH', paper, scaling, start_num, 

2277 fit_width_to, fit_height_to, \ 

2278 options, 

2279 hres, vres, 

2280 header_margin, footer_margin, 

2281 num_copies) 

2282 

2283class NameRecord(BiffRecord): 

2284 """ 

2285 This record is part of a Link Table. It contains the name and the token 

2286 array of an internal defined name. Token arrays of defined names 

2287 contain tokens with aberrant token classes. 

2288 

2289 Record NAME, BIFF5/BIFF7: 

2290 Offset Size Contents 

2291 0 2 Option flags, see below 

2292 2 1 Keyboard shortcut (only for command macro names, see below) 

2293 3 1 Length of the name (character count, ln) 

2294 4 2 Size of the formula data (sz) 

2295 6 2 0 = Global name, otherwise index to EXTERNSHEET record (one-based) 

2296 8 2 0 = Global name, otherwise index to sheet (one-based) 

2297 10 1 Length of menu text (character count, lm) 

2298 11 1 Length of description text (character count, ld) 

2299 12 1 Length of help topic text (character count, lh) 

2300 13 1 Length of status bar text (character count, ls) 

2301 14 ln Character array of the name 

2302 14+ln sz Formula data (RPN token array without size field, 4) 

2303 14+ln+sz lm Character array of menu text 

2304 var. ld Character array of description text 

2305 var. lh Character array of help topic text 

2306 var. ls Character array of status bar text 

2307 

2308 Record NAME, BIFF8: 

2309 Offset Size Contents 

2310 0 2 Option flags, see below 

2311 2 1 Keyboard shortcut (only for command macro names, see below) 

2312 3 1 Length of the name (character count, ln) 

2313 4 2 Size of the formula data (sz) 

2314 6 2 Not used 

2315 8 2 0 = Global name, otherwise index to sheet (one-based) 

2316 10 1 Length of menu text (character count, lm) 

2317 11 1 Length of description text (character count, ld) 

2318 12 1 Length of help topic text (character count, lh) 

2319 13 1 Length of status bar text (character count, ls) 

2320 14 var. Name (Unicode string without length field, 3.4) 

2321 var. sz Formula data (RPN token array without size field, 4) 

2322 [var.] var. (optional, only if lm > 0) Menu text (Unicode string without length field, 3.4) 

2323 [var.] var. (optional, only if ld > 0) Description text (Unicode string without length field, 3.4) 

2324 [var.] var. (optional, only if lh > 0) Help topic text (Unicode string without length field, 3.4) 

2325 [var.] var. (optional, only if ls > 0) Status bar text (Unicode string without length field, 3.4) 

2326 """ 

2327 _REC_ID = 0x0018 

2328 

2329 def __init__(self, options, keyboard_shortcut, name, sheet_index, rpn, menu_text='', desc_text='', help_text='', status_text=''): 

2330 if type(name) == int: 

2331 uname = chr(name) 

2332 else: 

2333 uname = upack1(name)[1:] 

2334 uname_len = len(uname) 

2335 

2336 #~ self._rec_data = pack('<HBBHHHBBBB%ds%ds' % (uname_len, len(rpn)), options, keyboard_shortcut, uname_len, len(rpn), 0x0000, sheet_index, len(menu_text), len(desc_text), len(help_text), len(status_text), uname, rpn) + menu_text + desc_text + help_text + status_text 

2337 self._rec_data = pack('<HBBHHHBBBBB%ds%ds' % (uname_len, len(rpn)), options, keyboard_shortcut, uname_len, len(rpn), 0x0000, sheet_index, 0x00, len(menu_text), len(desc_text), len(help_text), len(status_text), uname, rpn) + menu_text + desc_text + help_text + status_text 

2338 

2339# Excel (both 2003 and 2007) don't like refs 

2340# split over a record boundary, which is what the 

2341# standard BiffRecord.get method does. 

2342 

2343# 8224 max data bytes in a BIFF record 

2344# 6 bytes per ref 

2345# 1370 = floor((8224 - 2) / 6.0) max refs in a record 

2346 

2347_maxRefPerRecord = 1370 

2348 

2349class ExternSheetRecord(BiffRecord): 

2350 """ 

2351 In BIFF8 the record stores a list with indexes to SUPBOOK 

2352 records (list of REF structures, 6.100). See 5.10.3 for 

2353 details about external references in BIFF8. 

2354 

2355 Record EXTERNSHEET, BIFF8: 

2356 Offset Size Contents 

2357 0 2 Number of following REF structures (nm) 

2358 2 6nm List of nm REF structures. Each REF contains the following data: 

2359 Offset Size Contents 

2360 0 2 Index to SUPBOOK record 

2361 2 2 Index to first SUPBOOK sheet 

2362 4 2 Index to last SUPBOOK sheet 

2363 """ 

2364 _REC_ID = 0x0017 

2365 

2366 def __init__(self, refs): 

2367 

2368 # do we always need this ref? or only if there are no refs? 

2369 # (I believe that if there are no refs then we should not generate the link table - Ruben) 

2370 #refs.insert(0, (0,0,0)) 

2371 

2372 self.refs = refs 

2373 

2374 def get(self): 

2375 res = [] 

2376 nrefs = len(self.refs) 

2377 for idx in xrange(0, nrefs, _maxRefPerRecord): 

2378 chunk = self.refs[idx:idx+_maxRefPerRecord] 

2379 krefs = len(chunk) 

2380 if idx: # CONTINUE record 

2381 header = pack("<HH", 0x003C, 6 * krefs) 

2382 else: # ExternSheetRecord 

2383 header = pack("<HHH", self._REC_ID, 6 * krefs + 2, nrefs) 

2384 res.append(header) 

2385 res.extend(pack("<HHH", *r) for r in chunk) 

2386 return b''.join(res) 

2387 

2388class SupBookRecord(BiffRecord): 

2389 """ 

2390 This record mainly stores the URL of an external document 

2391 and a list of sheet names inside this document. Furthermore 

2392 it is used to store DDE and OLE object links, or to indicate 

2393 an internal 3D reference or an add-in function. See 5.10.3 

2394 for details about external references in BIFF8. 

2395 

2396 """ 

2397 _REC_ID = 0x01AE 

2398 

2399class InternalReferenceSupBookRecord(SupBookRecord): 

2400 """ 

2401 In each file occurs a SUPBOOK that is used for internal 3D 

2402 references. It stores the number of sheets of the own document. 

2403 

2404 Record SUPBOOK for 3D references, BIFF8: 

2405 Offset Size Contents 

2406 0 2 Number of sheets in this document 

2407 2 2 01H 04H (relict of BIFF5/BIFF7, the byte string "<04H>", see 3.9.1) 

2408 

2409 """ 

2410 

2411 def __init__(self, num_sheets): 

2412 self._rec_data = pack('<HBB', num_sheets, 0x01, 0x04) 

2413 

2414class XcallSupBookRecord(SupBookRecord): 

2415 """ 

2416 Add-in function names are stored in EXTERNNAME records following this record. 

2417 

2418 Offset Size Contents 

2419 0 2 0001H 

2420 2 2 01H 3AH (relict of BIFF5, the byte string ':', see EXTERNSHEET record, 5.41) 

2421 

2422 """ 

2423 

2424 def __init__(self): 

2425 self._rec_data = pack('<HBB', 1, 0x01, 0x3A) 

2426 

2427 

2428class ExternnameRecord(BiffRecord): 

2429 """ 

2430 Record EXTERNNAME for external names and Analysis add-in functions, BIFF5-BIFF8: 

2431 Offset Size Contents 

2432 0 2 Option flags (see below) 

2433 2 2 0 for global names, or: 

2434 BIFF5: One-based index to EXTERNSHEET record containing the sheet name, 

2435 BIFF8: One-based index to sheet list in preceding EXTERNALBOOK record. 

2436 4 2 Not used 

2437 6 var. BIFF5: Name (byte string, 8-bit string length, ?2.5.2). 

2438 BIFF8: Name (Unicode string, 8-bit string length, ?2.5.3). 

2439 See DEFINEDNAME record (?5.33) for a list of built-in names, if the built-in flag is set 

2440 in the option flags above. 

2441 var. var. Formula data (RPN token array, ?3) 

2442 

2443 Option flags for external names (BIFF5-BIFF8) 

2444 Bit Mask Contents 

2445 0 0001H 0 = Standard name; 1 = Built-in name 

2446 1 0002H 0 = Manual link; 1 = Automatic link (DDE links and OLE links only) 

2447 2 0004H 1 = Picture link (DDE links and OLE links only) 

2448 3 0008H 1 = This is the “StdDocumentName” identifier (DDE links only) 

2449 4 0010H 1 = OLE link 

2450 14-5 7FE0H Clipboard format of last successful update (DDE links and OLE links only) 

2451 15 8000H 1 = Iconified picture link (BIFF8 OLE links only) 

2452 """ 

2453 _REC_ID = 0x0023 

2454 

2455 def __init__(self, options=0, index=0, name=None, fmla=None): 

2456 self._rec_data = pack('<HHH', options, index, 0) + upack1(name) + fmla 

2457