BIFFRecords.py 95 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457
  1. # -*- coding: cp1252 -*-
  2. from struct import pack
  3. from .UnicodeUtils import upack1, upack2, upack2rt
  4. from .compat import basestring, unicode, unicode_type, xrange, iteritems
  5. class SharedStringTable(object):
  6. _SST_ID = 0x00FC
  7. _CONTINUE_ID = 0x003C
  8. def __init__(self, encoding):
  9. self.encoding = encoding
  10. self._str_indexes = {}
  11. self._rt_indexes = {}
  12. self._tally = []
  13. self._add_calls = 0
  14. # Following 3 attrs are used for temporary storage in the
  15. # get_biff_record() method and methods called by it. The pseudo-
  16. # initialisation here is for documentation purposes only.
  17. self._sst_record = None
  18. self._continues = None
  19. self._current_piece = None
  20. def add_str(self, s):
  21. if self.encoding != 'ascii' and not isinstance(s, unicode_type):
  22. s = unicode(s, self.encoding)
  23. self._add_calls += 1
  24. if s not in self._str_indexes:
  25. idx = len(self._str_indexes) + len(self._rt_indexes)
  26. self._str_indexes[s] = idx
  27. self._tally.append(1)
  28. else:
  29. idx = self._str_indexes[s]
  30. self._tally[idx] += 1
  31. return idx
  32. def add_rt(self, rt):
  33. rtList = []
  34. for s, xf in rt:
  35. if self.encoding != 'ascii' and not isinstance(s, unicode_type):
  36. s = unicode(s, self.encoding)
  37. rtList.append((s, xf))
  38. rt = tuple(rtList)
  39. self._add_calls += 1
  40. if rt not in self._rt_indexes:
  41. idx = len(self._str_indexes) + len(self._rt_indexes)
  42. self._rt_indexes[rt] = idx
  43. self._tally.append(1)
  44. else:
  45. idx = self._rt_indexes[rt]
  46. self._tally[idx] += 1
  47. return idx
  48. def del_str(self, idx):
  49. # This is called when we are replacing the contents of a string cell.
  50. # handles both regular and rt strings
  51. assert self._tally[idx] > 0
  52. self._tally[idx] -= 1
  53. self._add_calls -= 1
  54. def str_index(self, s):
  55. return self._str_indexes[s]
  56. def rt_index(self, rt):
  57. return self._rt_indexes[rt]
  58. def get_biff_record(self):
  59. self._sst_record = b''
  60. self._continues = [None, None]
  61. self._current_piece = pack('<II', 0, 0)
  62. data = [(idx, s) for s, idx in iteritems(self._str_indexes)]
  63. data.extend((idx, s) for s, idx in iteritems(self._rt_indexes))
  64. data.sort() # in index order
  65. for idx, s in data:
  66. if self._tally[idx] == 0:
  67. s = u''
  68. if isinstance(s, basestring):
  69. self._add_to_sst(s)
  70. else:
  71. self._add_rt_to_sst(s)
  72. del data
  73. self._new_piece()
  74. self._continues[0] = pack('<2HII', self._SST_ID, len(self._sst_record), self._add_calls, len(self._str_indexes) + len(self._rt_indexes))
  75. self._continues[1] = self._sst_record[8:]
  76. self._sst_record = None
  77. self._current_piece = None
  78. result = b''.join(self._continues)
  79. self._continues = None
  80. return result
  81. def _add_to_sst(self, s):
  82. u_str = upack2(s, self.encoding)
  83. is_unicode_str = u_str[2] == b'\x01'[0]
  84. if is_unicode_str:
  85. atom_len = 5 # 2 byte -- len,
  86. # 1 byte -- options,
  87. # 2 byte -- 1st sym
  88. else:
  89. atom_len = 4 # 2 byte -- len,
  90. # 1 byte -- options,
  91. # 1 byte -- 1st sym
  92. self._save_atom(u_str[0:atom_len])
  93. self._save_splitted(u_str[atom_len:], is_unicode_str)
  94. def _add_rt_to_sst(self, rt):
  95. rt_str, rt_fr = upack2rt(rt, self.encoding)
  96. is_unicode_str = rt_str[2] == b'\x09'[0]
  97. if is_unicode_str:
  98. atom_len = 7 # 2 byte -- len,
  99. # 1 byte -- options,
  100. # 2 byte -- number of rt runs
  101. # 2 byte -- 1st sym
  102. else:
  103. atom_len = 6 # 2 byte -- len,
  104. # 1 byte -- options,
  105. # 2 byte -- number of rt runs
  106. # 1 byte -- 1st sym
  107. self._save_atom(rt_str[0:atom_len])
  108. self._save_splitted(rt_str[atom_len:], is_unicode_str)
  109. for i in range(0, len(rt_fr), 4):
  110. self._save_atom(rt_fr[i:i+4])
  111. def _new_piece(self):
  112. if self._sst_record == b'':
  113. self._sst_record = self._current_piece
  114. else:
  115. curr_piece_len = len(self._current_piece)
  116. self._continues.append(pack('<2H%ds'%curr_piece_len, self._CONTINUE_ID, curr_piece_len, self._current_piece))
  117. self._current_piece = b''
  118. def _save_atom(self, s):
  119. atom_len = len(s)
  120. free_space = 0x2020 - len(self._current_piece)
  121. if free_space < atom_len:
  122. self._new_piece()
  123. self._current_piece += s
  124. def _save_splitted(self, s, is_unicode_str):
  125. i = 0
  126. str_len = len(s)
  127. while i < str_len:
  128. piece_len = len(self._current_piece)
  129. free_space = 0x2020 - piece_len
  130. tail_len = str_len - i
  131. need_more_space = free_space < tail_len
  132. if not need_more_space:
  133. atom_len = tail_len
  134. else:
  135. if is_unicode_str:
  136. atom_len = free_space & 0xFFFE
  137. else:
  138. atom_len = free_space
  139. self._current_piece += s[i:i+atom_len]
  140. if need_more_space:
  141. self._new_piece()
  142. if is_unicode_str:
  143. self._current_piece += b'\x01'
  144. else:
  145. self._current_piece += b'\x00'
  146. i += atom_len
  147. class BiffRecord(object):
  148. _rec_data = b'' # class attribute; child classes need to set this.
  149. def get_rec_header(self):
  150. return pack('<2H', self._REC_ID, len(self._rec_data))
  151. # Not over-ridden by any child classes, never called (except by "get"; see below).
  152. # def get_rec_data(self):
  153. # return self._rec_data
  154. def get(self):
  155. # data = self.get_rec_data()
  156. data = self._rec_data
  157. if len(data) > 0x2020: # limit for BIFF7/8
  158. chunks = []
  159. pos = 0
  160. while pos < len(data):
  161. chunk_pos = pos + 0x2020
  162. chunk = data[pos:chunk_pos]
  163. chunks.append(chunk)
  164. pos = chunk_pos
  165. continues = pack('<2H', self._REC_ID, len(chunks[0])) + chunks[0]
  166. for chunk in chunks[1:]:
  167. continues += pack('<2H%ds'%len(chunk), 0x003C, len(chunk), chunk)
  168. # 0x003C -- CONTINUE record id
  169. return continues
  170. else:
  171. return self.get_rec_header() + data
  172. class Biff8BOFRecord(BiffRecord):
  173. """
  174. Offset Size Contents
  175. 0 2 Version, contains 0600H for BIFF8 and BIFF8X
  176. 2 2 Type of the following data:
  177. 0005H = Workbook globals
  178. 0006H = Visual Basic module
  179. 0010H = Worksheet
  180. 0020H = Chart
  181. 0040H = Macro sheet
  182. 0100H = Workspace file
  183. 4 2 Build identifier
  184. 6 2 Build year
  185. 8 4 File history flags
  186. 12 4 Lowest Excel version that can read all records in this file
  187. """
  188. _REC_ID = 0x0809
  189. # stream types
  190. BOOK_GLOBAL = 0x0005
  191. VB_MODULE = 0x0006
  192. WORKSHEET = 0x0010
  193. CHART = 0x0020
  194. MACROSHEET = 0x0040
  195. WORKSPACE = 0x0100
  196. def __init__(self, rec_type):
  197. version = 0x0600
  198. build = 0x0DBB
  199. year = 0x07CC
  200. file_hist_flags = 0x00
  201. ver_can_read = 0x06
  202. self._rec_data = pack('<4H2I', version, rec_type, build, year, file_hist_flags, ver_can_read)
  203. class InteraceHdrRecord(BiffRecord):
  204. _REC_ID = 0x00E1
  205. def __init__(self):
  206. self._rec_data = pack('BB', 0xB0, 0x04)
  207. class InteraceEndRecord(BiffRecord):
  208. _REC_ID = 0x00E2
  209. def __init__(self):
  210. self._rec_data = b''
  211. class MMSRecord(BiffRecord):
  212. _REC_ID = 0x00C1
  213. def __init__(self):
  214. self._rec_data = pack('<H', 0x00)
  215. class WriteAccessRecord(BiffRecord):
  216. """
  217. This record is part of the file protection. It contains the name of the
  218. user that has saved the file. The user name is always stored as an
  219. equal-sized string. All unused characters after the name are filled
  220. with space characters. It is not required to write the mentioned string
  221. length. Every other length will be accepted too.
  222. """
  223. _REC_ID = 0x005C
  224. def __init__(self, owner):
  225. uowner = owner[0:0x30]
  226. uowner_len = len(uowner)
  227. if isinstance(uowner, unicode_type):
  228. uowner = uowner.encode('ascii') # probably not ascii, but play it safe until we know more
  229. self._rec_data = pack('%ds%ds' % (uowner_len, 0x70 - uowner_len), uowner, b' '*(0x70 - uowner_len))
  230. class DSFRecord(BiffRecord):
  231. """
  232. This record specifies if the file contains an additional BIFF5/BIFF7
  233. workbook stream.
  234. Record DSF, BIFF8:
  235. Offset Size Contents
  236. 0 2 0 = Only the BIFF8 Workbook stream is present
  237. 1 = Additional BIFF5/BIFF7 Book stream is in the file
  238. A double stream file can be read by Excel 5.0 and Excel 95, and still
  239. contains all new features added to BIFF8 (which are left out in the
  240. BIFF5/BIFF7 Book stream).
  241. """
  242. _REC_ID = 0x0161
  243. def __init__(self):
  244. self._rec_data = pack('<H', 0x00)
  245. class TabIDRecord(BiffRecord):
  246. _REC_ID = 0x013D
  247. def __init__(self, sheetcount):
  248. for i in range(sheetcount):
  249. self._rec_data += pack('<H', i+1)
  250. class FnGroupCountRecord(BiffRecord):
  251. _REC_ID = 0x009C
  252. def __init__(self):
  253. self._rec_data = pack('BB', 0x0E, 0x00)
  254. class WindowProtectRecord(BiffRecord):
  255. """
  256. This record is part of the worksheet/workbook protection. It determines
  257. whether the window configuration of this document is protected. Window
  258. protection is not active, if this record is omitted.
  259. """
  260. _REC_ID = 0x0019
  261. def __init__(self, wndprotect):
  262. self._rec_data = pack('<H', wndprotect)
  263. class ObjectProtectRecord(BiffRecord):
  264. """
  265. This record is part of the worksheet/workbook protection.
  266. It determines whether the objects of the current sheet are protected.
  267. Object protection is not active, if this record is omitted.
  268. """
  269. _REC_ID = 0x0063
  270. def __init__(self, objprotect):
  271. self._rec_data = pack('<H', objprotect)
  272. class ScenProtectRecord(BiffRecord):
  273. """
  274. This record is part of the worksheet/workbook protection. It
  275. determines whether the scenarios of the current sheet are protected.
  276. Scenario protection is not active, if this record is omitted.
  277. """
  278. _REC_ID = 0x00DD
  279. def __init__(self, scenprotect):
  280. self._rec_data = pack('<H', scenprotect)
  281. class ProtectRecord(BiffRecord):
  282. """
  283. This record is part of the worksheet/workbook protection. It specifies
  284. whether a worksheet or a workbook is protected against modification.
  285. Protection is not active, if this record is omitted.
  286. """
  287. _REC_ID = 0x0012
  288. def __init__(self, protect):
  289. self._rec_data = pack('<H', protect)
  290. class PasswordRecord(BiffRecord):
  291. """
  292. This record is part of the worksheet/workbook protection. It
  293. stores a 16-bit hash value, calculated from the worksheet or workbook
  294. protection password.
  295. """
  296. _REC_ID = 0x0013
  297. def passwd_hash(self, plaintext):
  298. """
  299. Based on the algorithm provided by Daniel Rentz of OpenOffice.
  300. """
  301. if plaintext == "":
  302. return 0
  303. passwd_hash = 0x0000
  304. for i, char in enumerate(plaintext):
  305. c = ord(char) << (i + 1)
  306. low_15 = c & 0x7fff
  307. high_15 = c & 0x7fff << 15
  308. high_15 = high_15 >> 15
  309. c = low_15 | high_15
  310. passwd_hash ^= c
  311. passwd_hash ^= len(plaintext)
  312. passwd_hash ^= 0xCE4B
  313. return passwd_hash
  314. def __init__(self, passwd = ""):
  315. self._rec_data = pack('<H', self.passwd_hash(passwd))
  316. class Prot4RevRecord(BiffRecord):
  317. _REC_ID = 0x01AF
  318. def __init__(self):
  319. self._rec_data = pack('<H', 0x00)
  320. class Prot4RevPassRecord(BiffRecord):
  321. _REC_ID = 0x01BC
  322. def __init__(self):
  323. self._rec_data = pack('<H', 0x00)
  324. class BackupRecord(BiffRecord):
  325. """
  326. This record contains a Boolean value determining whether Excel makes
  327. a backup of the file while saving.
  328. """
  329. _REC_ID = 0x0040
  330. def __init__(self, backup):
  331. self._rec_data = pack('<H', backup)
  332. class HideObjRecord(BiffRecord):
  333. """
  334. This record specifies whether and how to show objects in the workbook.
  335. Record HIDEOBJ, BIFF3-BIFF8:
  336. Offset Size Contents
  337. 0 2 Viewing mode for objects:
  338. 0 = Show all objects
  339. 1 = Show placeholders
  340. 2 = Do not show objects
  341. """
  342. _REC_ID = 0x008D
  343. def __init__(self):
  344. self._rec_data = pack('<H', 0x00)
  345. class RefreshAllRecord(BiffRecord):
  346. """
  347. """
  348. _REC_ID = 0x01B7
  349. def __init__(self):
  350. self._rec_data = pack('<H', 0x00)
  351. class BookBoolRecord(BiffRecord):
  352. """
  353. This record contains a Boolean value determining whether to save values
  354. linked from external workbooks (CRN records and XCT records). In BIFF3
  355. and BIFF4 this option is stored in the WSBOOL record.
  356. Record BOOKBOOL, BIFF5-BIFF8:
  357. Offset Size Contents
  358. 0 2 0 = Save external linked values;
  359. 1 = Do not save external linked values
  360. """
  361. _REC_ID = 0x00DA
  362. def __init__(self):
  363. self._rec_data = pack('<H', 0x00)
  364. class CountryRecord(BiffRecord):
  365. """
  366. This record stores two Windows country identifiers. The first
  367. represents the user interface language of the Excel version that has
  368. saved the file, and the second represents the system regional settings
  369. at the time the file was saved.
  370. Record COUNTRY, BIFF3-BIFF8:
  371. Offset Size Contents
  372. 0 2 Windows country identifier of the user interface language of Excel
  373. 2 2 Windows country identifier of the system regional settings
  374. The following table shows most of the used country identifiers. Most
  375. of these identifiers are equal to the international country calling
  376. codes.
  377. 1 USA
  378. 2 Canada
  379. 7 Russia
  380. """
  381. _REC_ID = 0x008C
  382. def __init__(self, ui_id, sys_settings_id):
  383. self._rec_data = pack('<2H', ui_id, sys_settings_id)
  384. class UseSelfsRecord(BiffRecord):
  385. """
  386. This record specifies if the formulas in the workbook can use natural
  387. language formulas. This type of formula can refer to cells by its
  388. content or the content of the column or row header cell.
  389. Record USESELFS, BIFF8:
  390. Offset Size Contents
  391. 0 2 0 = Do not use natural language formulas
  392. 1 = Use natural language formulas
  393. """
  394. _REC_ID = 0x0160
  395. def __init__(self):
  396. self._rec_data = pack('<H', 0x01)
  397. class EOFRecord(BiffRecord):
  398. _REC_ID = 0x000A
  399. def __init__(self):
  400. self._rec_data = b''
  401. class DateModeRecord(BiffRecord):
  402. """
  403. This record specifies the base date for displaying date values. All
  404. dates are stored as count of days past this base date. In BIFF2-BIFF4
  405. this record is part of the Calculation Settings Block.
  406. In BIFF5-BIFF8 it is stored in the Workbook Globals Substream.
  407. Record DATEMODE, BIFF2-BIFF8:
  408. Offset Size Contents
  409. 0 2 0 = Base is 1899-Dec-31 (the cell = 1 represents 1900-Jan-01)
  410. 1 = Base is 1904-Jan-01 (the cell = 1 represents 1904-Jan-02)
  411. """
  412. _REC_ID = 0x0022
  413. def __init__(self, from1904):
  414. if from1904:
  415. self._rec_data = pack('<H', 1)
  416. else:
  417. self._rec_data = pack('<H', 0)
  418. class PrecisionRecord(BiffRecord):
  419. """
  420. This record stores if formulas use the real cell values for calculation
  421. or the values displayed on the screen. In BIFF2- BIFF4 this record
  422. is part of the Calculation Settings Block. In BIFF5-BIFF8 it is stored
  423. in the Workbook Globals Substream.
  424. Record PRECISION, BIFF2-BIFF8:
  425. Offset Size Contents
  426. 0 2 0 = Use displayed values;
  427. 1 = Use real cell values
  428. """
  429. _REC_ID = 0x000E
  430. def __init__(self, use_real_values):
  431. if use_real_values:
  432. self._rec_data = pack('<H', 1)
  433. else:
  434. self._rec_data = pack('<H', 0)
  435. class CodepageBiff8Record(BiffRecord):
  436. """
  437. This record stores the text encoding used to write byte strings, stored
  438. as MS Windows code page identifier. The CODEPAGE record in BIFF8 always
  439. contains the code page 1200 (UTF-16). Therefore it is not
  440. possible to obtain the encoding used for a protection password (it is
  441. not UTF-16).
  442. Record CODEPAGE, BIFF2-BIFF8:
  443. Offset Size Contents
  444. 0 2 Code page identifier used for byte string text encoding:
  445. 016FH = 367 = ASCII
  446. 01B5H = 437 = IBM PC CP-437 (US)
  447. 02D0H = 720 = IBM PC CP-720 (OEM Arabic)
  448. 02E1H = 737 = IBM PC CP-737 (Greek)
  449. 0307H = 775 = IBM PC CP-775 (Baltic)
  450. 0352H = 850 = IBM PC CP-850 (Latin I)
  451. 0354H = 852 = IBM PC CP-852 (Latin II (Central European))
  452. 0357H = 855 = IBM PC CP-855 (Cyrillic)
  453. 0359H = 857 = IBM PC CP-857 (Turkish)
  454. 035AH = 858 = IBM PC CP-858 (Multilingual Latin I with Euro)
  455. 035CH = 860 = IBM PC CP-860 (Portuguese)
  456. 035DH = 861 = IBM PC CP-861 (Icelandic)
  457. 035EH = 862 = IBM PC CP-862 (Hebrew)
  458. 035FH = 863 = IBM PC CP-863 (Canadian (French))
  459. 0360H = 864 = IBM PC CP-864 (Arabic)
  460. 0361H = 865 = IBM PC CP-865 (Nordic)
  461. 0362H = 866 = IBM PC CP-866 (Cyrillic (Russian))
  462. 0365H = 869 = IBM PC CP-869 (Greek (Modern))
  463. 036AH = 874 = Windows CP-874 (Thai)
  464. 03A4H = 932 = Windows CP-932 (Japanese Shift-JIS)
  465. 03A8H = 936 = Windows CP-936 (Chinese Simplified GBK)
  466. 03B5H = 949 = Windows CP-949 (Korean (Wansung))
  467. 03B6H = 950 = Windows CP-950 (Chinese Traditional BIG5)
  468. 04B0H = 1200 = UTF-16 (BIFF8)
  469. 04E2H = 1250 = Windows CP-1250 (Latin II) (Central European)
  470. 04E3H = 1251 = Windows CP-1251 (Cyrillic)
  471. 04E4H = 1252 = Windows CP-1252 (Latin I) (BIFF4-BIFF7)
  472. 04E5H = 1253 = Windows CP-1253 (Greek)
  473. 04E6H = 1254 = Windows CP-1254 (Turkish)
  474. 04E7H = 1255 = Windows CP-1255 (Hebrew)
  475. 04E8H = 1256 = Windows CP-1256 (Arabic)
  476. 04E9H = 1257 = Windows CP-1257 (Baltic)
  477. 04EAH = 1258 = Windows CP-1258 (Vietnamese)
  478. 0551H = 1361 = Windows CP-1361 (Korean (Johab))
  479. 2710H = 10000 = Apple Roman
  480. 8000H = 32768 = Apple Roman
  481. 8001H = 32769 = Windows CP-1252 (Latin I) (BIFF2-BIFF3)
  482. """
  483. _REC_ID = 0x0042
  484. UTF_16 = 0x04B0
  485. def __init__(self):
  486. self._rec_data = pack('<H', self.UTF_16)
  487. class Window1Record(BiffRecord):
  488. """
  489. Offset Size Contents
  490. 0 2 Horizontal position of the document window (in twips = 1/20 of a point)
  491. 2 2 Vertical position of the document window (in twips = 1/20 of a point)
  492. 4 2 Width of the document window (in twips = 1/20 of a point)
  493. 6 2 Height of the document window (in twips = 1/20 of a point)
  494. 8 2 Option flags:
  495. Bits Mask Contents
  496. 0 0001H 0 = Window is visible 1 = Window is hidden
  497. 1 0002H 0 = Window is open 1 = Window is minimised
  498. 3 0008H 0 = Horizontal scroll bar hidden 1 = Horizontal scroll bar visible
  499. 4 0010H 0 = Vertical scroll bar hidden 1 = Vertical scroll bar visible
  500. 5 0020H 0 = Worksheet tab bar hidden 1 = Worksheet tab bar visible
  501. 10 2 Index to active (displayed) worksheet
  502. 12 2 Index of first visible tab in the worksheet tab bar
  503. 14 2 Number of selected worksheets (highlighted in the worksheet tab bar)
  504. 16 2 Width of worksheet tab bar (in 1/1000 of window width). The remaining space is used by the
  505. horizontal scrollbar.
  506. """
  507. _REC_ID = 0x003D
  508. # flags
  509. def __init__(self,
  510. hpos_twips, vpos_twips,
  511. width_twips, height_twips,
  512. flags,
  513. active_sheet,
  514. first_tab_index, selected_tabs, tab_width):
  515. self._rec_data = pack('<9H', hpos_twips, vpos_twips,
  516. width_twips, height_twips,
  517. flags,
  518. active_sheet,
  519. first_tab_index, selected_tabs, tab_width)
  520. class FontRecord(BiffRecord):
  521. """
  522. WARNING
  523. The font with index 4 is omitted in all BIFF versions.
  524. This means the first four fonts have zero-based indexes, and
  525. the fifth font and all following fonts are referenced with one-based
  526. indexes.
  527. Offset Size Contents
  528. 0 2 Height of the font (in twips = 1/20 of a point)
  529. 2 2 Option flags:
  530. Bit Mask Contents
  531. 0 0001H 1 = Characters are bold (redundant, see below)
  532. 1 0002H 1 = Characters are italic
  533. 2 0004H 1 = Characters are underlined (redundant, see below)
  534. 3 0008H 1 = Characters are struck out
  535. 0010H 1 = Outline
  536. 0020H 1 = Shadow
  537. 4 2 Colour index
  538. 6 2 Font weight (100-1000).
  539. Standard values are 0190H (400) for normal text and 02BCH
  540. (700) for bold text.
  541. 8 2 Escapement type:
  542. 0000H = None
  543. 0001H = Superscript
  544. 0002H = Subscript
  545. 10 1 Underline type:
  546. 00H = None
  547. 01H = Single
  548. 21H = Single accounting
  549. 02H = Double
  550. 22H = Double accounting
  551. 11 1 Font family:
  552. 00H = None (unknown or don't care)
  553. 01H = Roman (variable width, serifed)
  554. 02H = Swiss (variable width, sans-serifed)
  555. 03H = Modern (fixed width, serifed or sans-serifed)
  556. 04H = Script (cursive)
  557. 05H = Decorative (specialised, i.e. Old English, Fraktur)
  558. 12 1 Character set:
  559. 00H = 0 = ANSI Latin
  560. 01H = 1 = System default
  561. 02H = 2 = Symbol
  562. 4DH = 77 = Apple Roman
  563. 80H = 128 = ANSI Japanese Shift-JIS
  564. 81H = 129 = ANSI Korean (Hangul)
  565. 82H = 130 = ANSI Korean (Johab)
  566. 86H = 134 = ANSI Chinese Simplified GBK
  567. 88H = 136 = ANSI Chinese Traditional BIG5
  568. A1H = 161 = ANSI Greek
  569. A2H = 162 = ANSI Turkish
  570. A3H = 163 = ANSI Vietnamese
  571. B1H = 177 = ANSI Hebrew
  572. B2H = 178 = ANSI Arabic
  573. BAH = 186 = ANSI Baltic
  574. CCH = 204 = ANSI Cyrillic
  575. DEH = 222 = ANSI Thai
  576. EEH = 238 = ANSI Latin II (Central European)
  577. FFH = 255 = OEM Latin I
  578. 13 1 Not used
  579. 14 var. Font name:
  580. BIFF5/BIFF7: Byte string, 8-bit string length
  581. BIFF8: Unicode string, 8-bit string length
  582. The boldness and underline flags are still set in the options field,
  583. but not used on reading the font. Font weight and underline type
  584. are specified in separate fields instead.
  585. """
  586. _REC_ID = 0x0031
  587. def __init__(self,
  588. height, options, colour_index, weight, escapement,
  589. underline, family, charset,
  590. name):
  591. uname = upack1(name)
  592. uname_len = len(uname)
  593. self._rec_data = pack('<5H4B%ds' % uname_len, height, options, colour_index, weight, escapement,
  594. underline, family, charset, 0x00,
  595. uname)
  596. class NumberFormatRecord(BiffRecord):
  597. """
  598. Record FORMAT, BIFF8:
  599. Offset Size Contents
  600. 0 2 Format index used in other records
  601. 2 var. Number format string (Unicode string, 16-bit string length)
  602. From BIFF5 on, the built-in number formats will be omitted. The built-in
  603. formats are dependent on the current regional settings of the operating
  604. system. The following table shows which number formats are used by default
  605. in a US-English environment. All indexes from 0 to 163 are reserved for
  606. built-in formats. The first user-defined format starts at 164.
  607. The built-in number formats, BIFF5-BIFF8
  608. Index Type Format string
  609. 0 General General
  610. 1 Decimal 0
  611. 2 Decimal 0.00
  612. 3 Decimal #,##0
  613. 4 Decimal #,##0.00
  614. 5 Currency "$"#,##0_);("$"#,##
  615. 6 Currency "$"#,##0_);[Red]("$"#,##
  616. 7 Currency "$"#,##0.00_);("$"#,##
  617. 8 Currency "$"#,##0.00_);[Red]("$"#,##
  618. 9 Percent 0%
  619. 10 Percent 0.00%
  620. 11 Scientific 0.00E+00
  621. 12 Fraction # ?/?
  622. 13 Fraction # ??/??
  623. 14 Date M/D/YY
  624. 15 Date D-MMM-YY
  625. 16 Date D-MMM
  626. 17 Date MMM-YY
  627. 18 Time h:mm AM/PM
  628. 19 Time h:mm:ss AM/PM
  629. 20 Time h:mm
  630. 21 Time h:mm:ss
  631. 22 Date/Time M/D/YY h:mm
  632. 37 Account _(#,##0_);(#,##0)
  633. 38 Account _(#,##0_);[Red](#,##0)
  634. 39 Account _(#,##0.00_);(#,##0.00)
  635. 40 Account _(#,##0.00_);[Red](#,##0.00)
  636. 41 Currency _("$"* #,##0_);_("$"* (#,##0);_("$"* "-"_);_(@_)
  637. 42 Currency _(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)
  638. 43 Currency _("$"* #,##0.00_);_("$"* (#,##0.00);_("$"* "-"??_);_(@_)
  639. 44 Currency _(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)
  640. 45 Time mm:ss
  641. 46 Time [h]:mm:ss
  642. 47 Time mm:ss.0
  643. 48 Scientific ##0.0E+0
  644. 49 Text @
  645. """
  646. _REC_ID = 0x041E
  647. def __init__(self, idx, fmtstr):
  648. ufmtstr = upack2(fmtstr)
  649. ufmtstr_len = len(ufmtstr)
  650. self._rec_data = pack('<H%ds' % ufmtstr_len, idx, ufmtstr)
  651. class XFRecord(BiffRecord):
  652. """
  653. XF Substructures
  654. -------------------------------------------------------------------------
  655. XF_TYPE_PROT XF Type and Cell Protection (3 Bits), BIFF3-BIFF8
  656. These 3 bits are part of a specific data byte.
  657. Bit Mask Contents
  658. 0 01H 1 = Cell is locked
  659. 1 02H 1 = Formula is hidden
  660. 2 04H 0 = Cell XF; 1 = Style XF
  661. XF_USED_ATTRIB Attributes Used from Parent Style XF (6 Bits),
  662. BIFF3-BIFF8 Each bit describes the validity of a specific group
  663. of attributes. In cell XFs a cleared bit means the attributes of the
  664. parent style XF are used (but only if the attributes are valid there),
  665. a set bit means the attributes of this XF are used. In style XFs
  666. a cleared bit means the attribute setting is valid, a set bit means the
  667. attribute should be ignored.
  668. Bit Mask Contents
  669. 0 01H Flag for number format
  670. 1 02H Flag for font
  671. 2 04H Flag for horizontal and vertical alignment, text wrap, indentation, orientation, rotation, and
  672. text direction
  673. 3 08H Flag for border lines
  674. 4 10H Flag for background area style
  675. 5 20H Flag for cell protection (cell locked and formula hidden)
  676. XF_HOR_ALIGN Horizontal Alignment (3 Bits), BIFF2-BIFF8 The horizontal
  677. alignment consists of 3 bits and is part of a specific data byte.
  678. Value Horizontal alignment
  679. 00H General
  680. 01H Left
  681. 02H Centred
  682. 03H Right
  683. 04H Filled
  684. 05H Justified (BIFF4-BIFF8X)
  685. 06H Centred across selection (BIFF4-BIFF8X)
  686. 07H Distributed (BIFF8X)
  687. XF_VERT_ALIGN Vertical Alignment (2 or 3 Bits), BIFF4-BIFF8
  688. The vertical alignment consists of 2 bits (BIFF4) or 3 bits (BIFF5-BIFF8)
  689. and is part of a specific data byte. Vertical alignment is not available
  690. in BIFF2 and BIFF3.
  691. Value Vertical alignment
  692. 00H Top
  693. 01H Centred
  694. 02H Bottom
  695. 03H Justified (BIFF5-BIFF8X)
  696. 04H Distributed (BIFF8X)
  697. XF_ORIENTATION Text Orientation (2 Bits), BIFF4-BIFF7 In the BIFF
  698. versions BIFF4-BIFF7, text can be rotated in steps of 90 degrees
  699. or stacked. The orientation mode consists of 2 bits and is part of
  700. a specific data byte. In BIFF8 a rotation angle occurs instead of these
  701. flags.
  702. Value Text orientation
  703. 00H Not rotated
  704. 01H Letters are stacked top-to-bottom, but not rotated
  705. 02H Text is rotated 90 degrees counterclockwise
  706. 03H Text is rotated 90 degrees clockwise
  707. XF_ROTATION Text Rotation Angle (1 Byte), BIFF8
  708. Value Text rotation
  709. 0 Not rotated
  710. 1-90 1 to 90 degrees counterclockwise
  711. 91-180 1 to 90 degrees clockwise
  712. 255 Letters are stacked top-to-bottom, but not rotated
  713. XF_BORDER_34 Cell Border Style (4 Bytes), BIFF3-BIFF4 Cell borders
  714. contain a line style and a line colour for each line of the border.
  715. Bit Mask Contents
  716. 2-0 00000007H Top line style
  717. 7-3 000000F8H Colour index for top line colour
  718. 10-8 00000700H Left line style
  719. 15-11 0000F800H Colour index for left line colour
  720. 18-16 00070000H Bottom line style
  721. 23-19 00F80000H Colour index for bottom line colour
  722. 26-24 07000000H Right line style
  723. 31-27 F8000000H Colour index for right line colour
  724. XF_AREA_34 Cell Background Area Style (2 Bytes), BIFF3-BIFF4 A cell
  725. background area style contains an area pattern and a foreground and
  726. background colour.
  727. Bit Mask Contents
  728. 5-0 003FH Fill pattern
  729. 10-6 07C0H Colour index for pattern colour
  730. 15-11 F800H Colour index for pattern background
  731. ---------------------------------------------------------------------------------------------
  732. Record XF, BIFF8:
  733. Offset Size Contents
  734. 0 2 Index to FONT record
  735. 2 2 Index to FORMAT record
  736. 4 2 Bit Mask Contents
  737. 2-0 0007H XF_TYPE_PROT . XF type, cell protection (see above)
  738. 15-4 FFF0H Index to parent style XF (always FFFH in style XFs)
  739. 6 1 Bit Mask Contents
  740. 2-0 07H XF_HOR_ALIGN . Horizontal alignment (see above)
  741. 3 08H 1 = Text is wrapped at right border
  742. 6-4 70H XF_VERT_ALIGN . Vertical alignment (see above)
  743. 7 1 XF_ROTATION: Text rotation angle (see above)
  744. 8 1 Bit Mask Contents
  745. 3-0 0FH Indent level
  746. 4 10H 1 = Shrink content to fit into cell
  747. 5 merge
  748. 7-6 C0H Text direction (BIFF8X only)
  749. 00b = According to context
  750. 01b = Left-to-right
  751. 10b = Right-to-left
  752. 9 1 Bit Mask Contents
  753. 7-2 FCH XF_USED_ATTRIB . Used attributes (see above)
  754. 10 4 Cell border lines and background area:
  755. Bit Mask Contents
  756. 3-0 0000000FH Left line style
  757. 7-4 000000F0H Right line style
  758. 11-8 00000F00H Top line style
  759. 15-12 0000F000H Bottom line style
  760. 22-16 007F0000H Colour index for left line colour
  761. 29-23 3F800000H Colour index for right line colour
  762. 30 40000000H 1 = Diagonal line from top left to right bottom
  763. 31 80000000H 1 = Diagonal line from bottom left to right top
  764. 14 4 Bit Mask Contents
  765. 6-0 0000007FH Colour index for top line colour
  766. 13-7 00003F80H Colour index for bottom line colour
  767. 20-14 001FC000H Colour index for diagonal line colour
  768. 24-21 01E00000H Diagonal line style
  769. 31-26 FC000000H Fill pattern
  770. 18 2 Bit Mask Contents
  771. 6-0 007FH Colour index for pattern colour
  772. 13-7 3F80H Colour index for pattern background
  773. """
  774. _REC_ID = 0x00E0
  775. def __init__(self, xf, xftype='cell'):
  776. font_xf_idx, fmt_str_xf_idx, alignment, borders, pattern, protection = xf
  777. fnt = pack('<H', font_xf_idx)
  778. fmt = pack('<H', fmt_str_xf_idx)
  779. if xftype == 'cell':
  780. prt = pack('<H',
  781. ((protection.cell_locked & 0x01) << 0) |
  782. ((protection.formula_hidden & 0x01) << 1)
  783. )
  784. else:
  785. prt = pack('<H', 0xFFF5)
  786. aln = pack('B',
  787. ((alignment.horz & 0x07) << 0) |
  788. ((alignment.wrap & 0x01) << 3) |
  789. ((alignment.vert & 0x07) << 4)
  790. )
  791. rot = pack('B', alignment.rota)
  792. txt = pack('B',
  793. ((alignment.inde & 0x0F) << 0) |
  794. ((alignment.shri & 0x01) << 4) |
  795. ((alignment.merg & 0x01) << 5) |
  796. ((alignment.dire & 0x03) << 6)
  797. )
  798. if xftype == 'cell':
  799. used_attr = pack('B', 0xF8)
  800. else:
  801. used_attr = pack('B', 0xF4)
  802. if borders.left == borders.NO_LINE:
  803. borders.left_colour = 0x00
  804. if borders.right == borders.NO_LINE:
  805. borders.right_colour = 0x00
  806. if borders.top == borders.NO_LINE:
  807. borders.top_colour = 0x00
  808. if borders.bottom == borders.NO_LINE:
  809. borders.bottom_colour = 0x00
  810. if borders.diag == borders.NO_LINE:
  811. borders.diag_colour = 0x00
  812. brd1 = pack('<L',
  813. ((borders.left & 0x0F) << 0 ) |
  814. ((borders.right & 0x0F) << 4 ) |
  815. ((borders.top & 0x0F) << 8 ) |
  816. ((borders.bottom & 0x0F) << 12) |
  817. ((borders.left_colour & 0x7F) << 16) |
  818. ((borders.right_colour & 0x7F) << 23) |
  819. ((borders.need_diag1 & 0x01) << 30) |
  820. ((borders.need_diag2 & 0x01) << 31)
  821. )
  822. brd2 = pack('<L',
  823. ((borders.top_colour & 0x7F) << 0 ) |
  824. ((borders.bottom_colour & 0x7F) << 7 ) |
  825. ((borders.diag_colour & 0x7F) << 14) |
  826. ((borders.diag & 0x0F) << 21) |
  827. ((pattern.pattern & 0x3F) << 26)
  828. )
  829. pat = pack('<H',
  830. ((pattern.pattern_fore_colour & 0x7F) << 0 ) |
  831. ((pattern.pattern_back_colour & 0x7F) << 7 )
  832. )
  833. self._rec_data = fnt + fmt + prt + \
  834. aln + rot + txt + used_attr + \
  835. brd1 + brd2 + \
  836. pat
  837. class StyleRecord(BiffRecord):
  838. """
  839. STYLE record for user-defined cell styles, BIFF3-BIFF8:
  840. Offset Size Contents
  841. 0 2 Bit Mask Contents
  842. 11-0 0FFFH Index to style XF record
  843. 15 8000H Always 0 for user-defined styles
  844. 2 var. BIFF2-BIFF7: Non-empty byte string, 8-bit string length
  845. BIFF8: Non-empty Unicode string, 16-bit string length
  846. STYLE record for built-in cell styles, BIFF3-BIFF8:
  847. Offset Size Contents
  848. 0 2 Bit Mask Contents
  849. 11-0 0FFFH Index to style XF record
  850. 15 8000H Always 1 for built-in styles
  851. 2 1 Identifier of the built-in cell style:
  852. 00H = Normal
  853. 01H = RowLevel_lv (see next field)
  854. 02H = ColLevel_lv (see next field)
  855. 03H = Comma
  856. 04H = Currency
  857. 05H = Percent
  858. 06H = Comma [0] (BIFF4-BIFF8)
  859. 07H = Currency [0] (BIFF4-BIFF8)
  860. 08H = Hyperlink (BIFF8)
  861. 09H = Followed Hyperlink (BIFF8)
  862. 3 1 Level for RowLevel or ColLevel style
  863. (zero-based, lv), FFH otherwise
  864. The RowLevel and ColLevel styles specify the formatting of subtotal
  865. cells in a specific outline level. The level is specified by the last
  866. field in the STYLE record. Valid values are 0-6 for the outline levels
  867. 1-7.
  868. """
  869. _REC_ID = 0x0293
  870. def __init__(self):
  871. self._rec_data = pack('<HBB', 0x8000, 0x00, 0xFF)
  872. # TODO: implement user-defined styles???
  873. class PaletteRecord(BiffRecord):
  874. """
  875. This record contains the definition of all user-defined colours
  876. available for cell and object formatting.
  877. Record PALETTE, BIFF3-BIFF8:
  878. Offset Size Contents
  879. 0 2 Number of following colours (nm). Contains 16 in BIFF3-BIFF4 and 56 in BIFF5-BIFF8.
  880. 2 4*nm List of nm RGB colours
  881. The following table shows how colour indexes are used in other records:
  882. Colour index Resulting colour or internal list index
  883. 00H Built-in Black (R = 00H, G = 00H, B = 00H)
  884. 01H Built-in White (R = FFH, G = FFH, B = FFH)
  885. 02H Built-in Red (R = FFH, G = 00H, B = 00H)
  886. 03H Built-in Green (R = 00H, G = FFH, B = 00H)
  887. 04H Built-in Blue (R = 00H, G = 00H, B = FFH)
  888. 05H Built-in Yellow (R = FFH, G = FFH, B = 00H)
  889. 06H Built-in Magenta (R = FFH, G = 00H, B = FFH)
  890. 07H Built-in Cyan (R = 00H, G = FFH, B = FFH)
  891. 08H First user-defined colour from the PALETTE record (entry 0 from record colour list)
  892. .........................
  893. 17H (BIFF3-BIFF4) Last user-defined colour from the PALETTE record (entry 15 or 55 from record colour list)
  894. 3FH (BIFF5-BIFF8)
  895. 18H (BIFF3-BIFF4) System window text colour for border lines (used in records XF, CF, and
  896. 40H (BIFF5-BIFF8) WINDOW2 (BIFF8 only))
  897. 19H (BIFF3-BIFF4) System window background colour for pattern background (used in records XF, and CF)
  898. 41H (BIFF5-BIFF8)
  899. 43H System face colour (dialogue background colour)
  900. 4DH System window text colour for chart border lines
  901. 4EH System window background colour for chart areas
  902. 4FH Automatic colour for chart border lines (seems to be always Black)
  903. 50H System ToolTip background colour (used in note objects)
  904. 51H System ToolTip text colour (used in note objects)
  905. 7FFFH System window text colour for fonts (used in records FONT, EFONT, and CF)
  906. """
  907. _REC_ID = 0x0092
  908. def __init__(self, custom_palette):
  909. n_colours = len(custom_palette)
  910. assert n_colours == 56
  911. # Pack number of colors with little-endian, what xlrd and excel expect.
  912. self._rec_data = pack('<H', n_colours)
  913. # Microsoft lists colors in big-endian format with 24 bits/color.
  914. # Pad LSB of each color with 0x00, and write out in big-endian.
  915. fmt = '>%dI' % n_colours
  916. self._rec_data += pack(fmt, *(custom_palette))
  917. class BoundSheetRecord(BiffRecord):
  918. """
  919. This record is located in the workbook globals area and represents
  920. a sheet inside of the workbook. For each sheet a BOUNDSHEET record
  921. is written. It stores the sheet name and a stream offset to the BOF
  922. record within the workbook stream. The record is also known
  923. as BUNDLESHEET.
  924. Record BOUNDSHEET, BIFF5-BIFF8:
  925. Offset Size Contents
  926. 0 4 Absolute stream position of the BOF record of the sheet represented by this record. This
  927. field is never encrypted in protected files.
  928. 4 1 Visibility:
  929. 00H = Visible
  930. 01H = Hidden
  931. 02H = Strong hidden
  932. 5 1 Sheet type:
  933. 00H = Worksheet
  934. 02H = Chart
  935. 06H = Visual Basic module
  936. 6 var. Sheet name:
  937. BIFF5/BIFF7: Byte string, 8-bit string length
  938. BIFF8: Unicode string, 8-bit string length
  939. """
  940. _REC_ID = 0x0085
  941. def __init__(self, stream_pos, visibility, sheetname, encoding='ascii'):
  942. usheetname = upack1(sheetname, encoding)
  943. uusheetname_len = len(usheetname)
  944. self._rec_data = pack('<LBB%ds' % uusheetname_len, stream_pos, visibility, 0x00, usheetname)
  945. class ContinueRecord(BiffRecord):
  946. """
  947. Whenever the content of a record exceeds the given limits (see table),
  948. the record must be split. Several CONTINUE records containing the
  949. additional data are added after the parent record.
  950. BIFF version Maximum data size of a record
  951. BIFF2-BIFF7 2080 bytes (2084 bytes including record header)
  952. BIFF8 8224 bytes (8228 bytes including record header) (0x2020)
  953. Record CONTINUE, BIFF2-BIFF8:
  954. Offset Size Contents
  955. 0 var. Data continuation of the previous record
  956. Unicode strings are split in a special way. At the beginning of each
  957. CONTINUE record the option flags byte is repeated. Only the character
  958. size flag will be set in this flags byte, the Rich-Text flag and the
  959. Far-East flag are set to zero. In each CONTINUE record it is possible
  960. that the character size changes from 8-bit characters to 16-bit
  961. characters and vice versa.
  962. Never a Unicode string is split until and including the first
  963. character. That means, all header fields (string length, option flags,
  964. optional Rich-Text size, and optional Far-East data size) and the first
  965. character of the string have to occur together in the leading record,
  966. or have to be moved completely into the CONTINUE record. Formatting
  967. runs cannot be split between their components (character index and FONT
  968. record index). If a string is split between two formatting runs, the
  969. option flags field will not be repeated in the CONTINUE record.
  970. """
  971. _REC_ID = 0x003C
  972. class SSTRecord(BiffRecord):
  973. """
  974. This record contains a list of all strings used anywhere in the
  975. workbook. Each string occurs only once. The workbook uses indexes into
  976. the list to reference the strings.
  977. Record SST, BIFF8:
  978. Offset Size Contents
  979. 0 4 Total number of strings in the workbook (see below)
  980. 4 4 Number of following strings (nm)
  981. 8 var. List of nm Unicode strings, 16-bit string length
  982. The first field of the SST record counts the total occurrence
  983. of strings in the workbook. For instance, the string AAA is used
  984. 3 times and the string BBB is used 2 times. The first field contains
  985. 5 and the second field contains 2, followed by the two strings.
  986. """
  987. _REC_ID = 0x00FC
  988. class ExtSSTRecord(BiffRecord):
  989. """
  990. This record occurs in conjunction with the SST record. It is used
  991. by Excel to create a hash table with stream offsets to the SST record
  992. to optimise string search operations. Excel may not shorten this record
  993. if strings are deleted from the shared string table, so the last part
  994. might contain invalid data. The stream indexes in this record divide
  995. the SST into portions containing a constant number of strings.
  996. Record EXTSST, BIFF8:
  997. Offset Size Contents
  998. 0 2 Number of strings in a portion, this number is >=8
  999. 2 var. List of OFFSET structures for all portions. Each OFFSET contains the following data:
  1000. Offset Size Contents
  1001. 0 4 Absolute stream position of first string of the portion
  1002. 4 2 Position of first string of the portion inside of current record,
  1003. including record header. This counter restarts at zero, if the SST
  1004. record is continued with a CONTINUE record.
  1005. 6 2 Not used
  1006. """
  1007. _REC_ID = 0x00FF
  1008. def __init__(self, sst_stream_pos, str_placement, portions_len):
  1009. extsst = {}
  1010. abs_stream_pos = sst_stream_pos
  1011. str_counter = 0
  1012. portion_counter = 0
  1013. while str_counter < len(str_placement):
  1014. str_chunk_num, pos_in_chunk = str_placement[str_counter]
  1015. if str_chunk_num != portion_counter:
  1016. portion_counter = str_chunk_num
  1017. abs_stream_pos += portions_len[portion_counter-1]
  1018. #print hex(abs_stream_pos)
  1019. str_stream_pos = abs_stream_pos + pos_in_chunk + 4 # header
  1020. extsst[str_counter] = (pos_in_chunk, str_stream_pos)
  1021. str_counter += 1
  1022. exsst_str_count_delta = max(8, len(str_placement)*8/0x2000) # maybe smth else?
  1023. self._rec_data = pack('<H', exsst_str_count_delta)
  1024. str_counter = 0
  1025. while str_counter < len(str_placement):
  1026. self._rec_data += pack('<IHH', extsst[str_counter][1], extsst[str_counter][0], 0)
  1027. str_counter += exsst_str_count_delta
  1028. class DimensionsRecord(BiffRecord):
  1029. """
  1030. Record DIMENSIONS, BIFF8:
  1031. Offset Size Contents
  1032. 0 4 Index to first used row
  1033. 4 4 Index to last used row, increased by 1
  1034. 8 2 Index to first used column
  1035. 10 2 Index to last used column, increased by 1
  1036. 12 2 Not used
  1037. """
  1038. _REC_ID = 0x0200
  1039. def __init__(self, first_used_row, last_used_row, first_used_col, last_used_col):
  1040. if first_used_row > last_used_row or first_used_col > last_used_col:
  1041. # Special case: empty worksheet
  1042. first_used_row = first_used_col = 0
  1043. last_used_row = last_used_col = -1
  1044. self._rec_data = pack('<2L3H',
  1045. first_used_row, last_used_row + 1,
  1046. first_used_col, last_used_col + 1,
  1047. 0x00)
  1048. class Window2Record(BiffRecord):
  1049. """
  1050. Record WINDOW2, BIFF8:
  1051. Offset Size Contents
  1052. 0 2 Option flags (see below)
  1053. 2 2 Index to first visible row
  1054. 4 2 Index to first visible column
  1055. 6 2 Colour index of grid line colour. Note that in BIFF2-BIFF7 an RGB colour is
  1056. written instead.
  1057. 8 2 Not used
  1058. 10 2 Cached magnification factor in page break preview (in percent); 0 = Default (60%)
  1059. 12 2 Cached magnification factor in normal view (in percent); 0 = Default (100%)
  1060. 14 4 Not used
  1061. In BIFF8 this record stores used magnification factors for page break
  1062. preview and normal view. These values are used to restore the
  1063. magnification, when the view is changed. The real magnification of the
  1064. currently active view is stored in the SCL record. The type of the
  1065. active view is stored in the option flags field (see below).
  1066. 0 0001H 0 = Show formula results 1 = Show formulas
  1067. 1 0002H 0 = Do not show grid lines 1 = Show grid lines
  1068. 2 0004H 0 = Do not show sheet headers 1 = Show sheet headers
  1069. 3 0008H 0 = Panes are not frozen 1 = Panes are frozen (freeze)
  1070. 4 0010H 0 = Show zero values as empty cells 1 = Show zero values
  1071. 5 0020H 0 = Manual grid line colour 1 = Automatic grid line colour
  1072. 6 0040H 0 = Columns from left to right 1 = Columns from right to left
  1073. 7 0080H 0 = Do not show outline symbols 1 = Show outline symbols
  1074. 8 0100H 0 = Keep splits if pane freeze is removed 1 = Remove splits if pane freeze is removed
  1075. 9 0200H 0 = Sheet not selected 1 = Sheet selected (BIFF5-BIFF8)
  1076. 10 0400H 0 = Sheet not visible 1 = Sheet visible (BIFF5-BIFF8)
  1077. 11 0800H 0 = Show in normal view 1 = Show in page break preview (BIFF8)
  1078. The freeze flag specifies, if a following PANE record describes unfrozen or frozen panes.
  1079. *** This class appends the optional SCL record ***
  1080. Record SCL, BIFF4-BIFF8:
  1081. This record stores the magnification of the active view of the current worksheet.
  1082. In BIFF8 this can be either the normal view or the page break preview.
  1083. This is determined in the WINDOW2 record. The SCL record is part of the
  1084. Sheet View Settings Block.
  1085. Offset Size Contents
  1086. 0 2 Numerator of the view magnification fraction (num)
  1087. 2 2 Denumerator [denominator] of the view magnification fraction (den)
  1088. The magnification is stored as reduced fraction. The magnification results from num/den.
  1089. SJM note: Excel expresses (e.g.) 25% in reduced form i.e. 1/4. Reason unknown. This code
  1090. writes 25/100, and Excel is happy with that.
  1091. """
  1092. _REC_ID = 0x023E
  1093. def __init__(self, options, first_visible_row, first_visible_col,
  1094. grid_colour, preview_magn, normal_magn, scl_magn):
  1095. self._rec_data = pack('<7HL', options,
  1096. first_visible_row, first_visible_col,
  1097. grid_colour,
  1098. 0x00,
  1099. preview_magn, normal_magn,
  1100. 0x00)
  1101. if scl_magn is not None:
  1102. self._scl_rec = pack('<4H', 0x00A0, 4, scl_magn, 100)
  1103. else:
  1104. self._scl_rec = b''
  1105. def get(self):
  1106. return self.get_rec_header() + self._rec_data + self._scl_rec
  1107. class PanesRecord(BiffRecord):
  1108. """
  1109. This record stores the position of window panes. It is part of the Sheet
  1110. View Settings Block. If the sheet does not contain any splits, this
  1111. record will not occur.
  1112. A sheet can be split in two different ways, with unfrozen panes or with
  1113. frozen panes. A flag in the WINDOW2 record specifies, if the panes are
  1114. frozen, which affects the contents of this record.
  1115. Record PANE, BIFF2-BIFF8:
  1116. Offset Size Contents
  1117. 0 2 Position of the vertical split
  1118. (px, 0 = No vertical split):
  1119. Unfrozen pane: Width of the left pane(s)
  1120. (in twips = 1/20 of a point)
  1121. Frozen pane: Number of visible
  1122. columns in left pane(s)
  1123. 2 2 Position of the horizontal split
  1124. (py, 0 = No horizontal split):
  1125. Unfrozen pane: Height of the top pane(s)
  1126. (in twips = 1/20 of a point)
  1127. Frozen pane: Number of visible
  1128. rows in top pane(s)
  1129. 4 2 Index to first visible row
  1130. in bottom pane(s)
  1131. 6 2 Index to first visible column
  1132. in right pane(s)
  1133. 8 1 Identifier of pane with active
  1134. cell cursor
  1135. [9] 1 Not used (BIFF5-BIFF8 only, not written
  1136. in BIFF2-BIFF4)
  1137. If the panes are frozen, pane 0 is always active, regardless
  1138. of the cursor position. The correct identifiers for all possible
  1139. combinations of visible panes are shown in the following pictures.
  1140. px = 0, py = 0 px = 0, py > 0
  1141. -------------------------- ------------|-------------
  1142. | | | |
  1143. | | | 3 |
  1144. | | | |
  1145. - 3 - --------------------------
  1146. | | | |
  1147. | | | 2 |
  1148. | | | |
  1149. -------------------------- ------------|-------------
  1150. px > 0, py = 0 px > 0, py > 0
  1151. ------------|------------- ------------|-------------
  1152. | | | | | |
  1153. | | | | 3 | 2 |
  1154. | | | | | |
  1155. - 3 | 1 - --------------------------
  1156. | | | | | |
  1157. | | | | 1 | 0 |
  1158. | | | | | |
  1159. ------------|------------- ------------|-------------
  1160. """
  1161. _REC_ID = 0x0041
  1162. valid_active_pane = {
  1163. # entries are of the form:
  1164. # (int(px > 0),int(px>0)) -> allowed values
  1165. (0,0):(3,),
  1166. (0,1):(2,3),
  1167. (1,0):(1,3),
  1168. (1,1):(0,1,2,3),
  1169. }
  1170. def __init__(self, px, py, first_row_bottom, first_col_right, active_pane):
  1171. allowed = self.valid_active_pane.get(
  1172. (int(px > 0),int(py > 0))
  1173. )
  1174. if active_pane not in allowed:
  1175. raise ValueError('Cannot set active_pane to %i, must be one of %s' % (
  1176. active_pane, ', '.join(allowed)
  1177. ))
  1178. self._rec_data = pack('<5H',
  1179. px, py,
  1180. first_row_bottom, first_col_right,
  1181. active_pane)
  1182. class RowRecord(BiffRecord):
  1183. """
  1184. This record contains the properties of a single row in a sheet. Rows
  1185. and cells in a sheet are divided into blocks of 32 rows.
  1186. Record ROW, BIFF3-BIFF8:
  1187. Offset Size Contents
  1188. 0 2 Index of this row
  1189. 2 2 Index to column of the first cell which is described by a cell record
  1190. 4 2 Index to column of the last cell which is described by a cell record,
  1191. increased by 1
  1192. 6 2 Bit Mask Contents
  1193. 14-0 7FFFH Height of the row, in twips = 1/20 of a point
  1194. 15 8000H 0 = Row has custom height; 1 = Row has default height
  1195. 8 2 Not used
  1196. 10 2 In BIFF3-BIFF4 this field contains a relative offset
  1197. to calculate stream position of the first cell record
  1198. for this row. In BIFF5-BIFF8 this field is not used
  1199. anymore, but the DBCELL record instead.
  1200. 12 4 Option flags and default row formatting:
  1201. Bit Mask Contents
  1202. 2-0 00000007H Outline level of the row
  1203. 4 00000010H 1 = Outline group starts or ends here (depending
  1204. on where the outline buttons are located,
  1205. see WSBOOL record), and is collapsed
  1206. 5 00000020H 1 = Row is hidden (manually, or by a filter or outline group)
  1207. 6 00000040H 1 = Row height and default font height do not match
  1208. 7 00000080H 1 = Row has explicit default format (fl)
  1209. 8 00000100H Always 1
  1210. 27-16 0FFF0000H If fl=1: Index to default XF record
  1211. 28 10000000H 1 = Additional space above the row. This flag is set,
  1212. if the upper border of at least one cell in this row
  1213. or if the lower border of at least one cell in the row
  1214. above is formatted with a thick line style.
  1215. Thin and medium line styles are not taken into account.
  1216. 29 20000000H 1 = Additional space below the row. This flag is set,
  1217. if the lower border of at least one cell in this row
  1218. or if the upper border of at least one cell in the row
  1219. below is formatted with a medium or thick line style.
  1220. Thin line styles are not taken into account.
  1221. """
  1222. _REC_ID = 0x0208
  1223. def __init__(self, index, first_col, last_col, height_options, options):
  1224. self._rec_data = pack('<6HL', index, first_col, last_col + 1,
  1225. height_options,
  1226. 0x00, 0x00,
  1227. options)
  1228. class LabelSSTRecord(BiffRecord):
  1229. """
  1230. This record represents a cell that contains a string. It replaces the
  1231. LABEL record and RSTRING record used in BIFF2-BIFF7.
  1232. """
  1233. _REC_ID = 0x00FD
  1234. def __init__(self, row, col, xf_idx, sst_idx):
  1235. self._rec_data = pack('<3HL', row, col, xf_idx, sst_idx)
  1236. class MergedCellsRecord(BiffRecord):
  1237. """
  1238. This record contains all merged cell ranges of the current sheet.
  1239. Record MERGEDCELLS, BIFF8:
  1240. Offset Size Contents
  1241. 0 var. Cell range address list with all merged ranges
  1242. ------------------------------------------------------------------
  1243. A cell range address list consists of a field with the number of ranges
  1244. and the list of the range addresses.
  1245. Cell range address list, BIFF8:
  1246. Offset Size Contents
  1247. 0 2 Number of following cell range addresses (nm)
  1248. 2 8*nm List of nm cell range addresses
  1249. ---------------------------------------------------------------------
  1250. Cell range address, BIFF8:
  1251. Offset Size Contents
  1252. 0 2 Index to first row
  1253. 2 2 Index to last row
  1254. 4 2 Index to first column
  1255. 6 2 Index to last column
  1256. """
  1257. _REC_ID = 0x00E5
  1258. def __init__(self, merged_list):
  1259. i = len(merged_list) - 1
  1260. while i >= 0:
  1261. j = 0
  1262. merged = b''
  1263. while (i >= 0) and (j < 0x403):
  1264. r1, r2, c1, c2 = merged_list[i]
  1265. merged += pack('<4H', r1, r2, c1, c2)
  1266. i -= 1
  1267. j += 1
  1268. self._rec_data += pack('<3H', self._REC_ID, len(merged) + 2, j) + \
  1269. merged
  1270. # for some reason Excel doesn't use CONTINUE
  1271. def get(self):
  1272. return self._rec_data
  1273. class MulBlankRecord(BiffRecord):
  1274. """
  1275. This record represents a cell range of empty cells. All cells are
  1276. located in the same row.
  1277. Record MULBLANK, BIFF5-BIFF8:
  1278. Offset Size Contents
  1279. 0 2 Index to row
  1280. 2 2 Index to first column (fc)
  1281. 4 2*nc List of nc=lc-fc+1 16-bit indexes to XF records
  1282. 4+2*nc 2 Index to last column (lc)
  1283. """
  1284. _REC_ID = 0x00BE
  1285. def __init__(self, row, first_col, last_col, xf_index):
  1286. blanks_count = last_col-first_col+1
  1287. self._rec_data = pack('<%dH' % blanks_count, *([xf_index] * blanks_count))
  1288. self._rec_data = pack('<2H', row, first_col) + self._rec_data + pack('<H', last_col)
  1289. class BlankRecord(BiffRecord):
  1290. """
  1291. This record represents an empty cell.
  1292. Record BLANK, BIFF5-BIFF8:
  1293. Offset Size Contents
  1294. 0 2 Index to row
  1295. 2 2 Index to first column (fc)
  1296. 4 2 indexes to XF record
  1297. """
  1298. _REC_ID = 0x0201
  1299. def __init__(self, row, col, xf_index):
  1300. self._rec_data = pack('<3H', row, col, xf_index)
  1301. class RKRecord(BiffRecord):
  1302. """
  1303. This record represents a cell that contains an RK value (encoded integer or
  1304. floating-point value). If a floating-point value cannot be encoded to an RK value,
  1305. a NUMBER record will be written.
  1306. """
  1307. _REC_ID = 0x027E
  1308. def __init__(self, row, col, xf_index, rk_encoded):
  1309. self._rec_data = pack('<3Hi', row, col, xf_index, rk_encoded)
  1310. class NumberRecord(BiffRecord):
  1311. """
  1312. This record represents a cell that contains an IEEE-754 floating-point value.
  1313. """
  1314. _REC_ID = 0x0203
  1315. def __init__(self, row, col, xf_index, number):
  1316. self._rec_data = pack('<3Hd', row, col, xf_index, number)
  1317. class BoolErrRecord(BiffRecord):
  1318. """
  1319. This record represents a cell that contains a boolean or error value.
  1320. """
  1321. _REC_ID = 0x0205
  1322. def __init__(self, row, col, xf_index, number, is_error):
  1323. self._rec_data = pack('<3HBB', row, col, xf_index, number, is_error)
  1324. class FormulaRecord(BiffRecord):
  1325. """
  1326. Offset Size Contents
  1327. 0 2 Index to row
  1328. 2 2 Index to column
  1329. 4 2 Index to XF record
  1330. 6 8 Result of the formula
  1331. 14 2 Option flags:
  1332. Bit Mask Contents
  1333. 0 0001H 1 = Recalculate always
  1334. 1 0002H 1 = Calculate on open
  1335. 3 0008H 1 = Part of a shared formula
  1336. 16 4 Not used
  1337. 20 var. Formula data (RPN token array)
  1338. """
  1339. _REC_ID = 0x0006
  1340. def __init__(self, row, col, xf_index, rpn, calc_flags=0):
  1341. self._rec_data = pack('<3HQHL', row, col, xf_index, 0xFFFF000000000003, calc_flags & 3, 0) + rpn
  1342. class GutsRecord(BiffRecord):
  1343. """
  1344. This record contains information about the layout of outline symbols.
  1345. Record GUTS, BIFF3-BIFF8:
  1346. Offset Size Contents
  1347. 0 2 Width of the area to display row outlines (left of the sheet), in pixel
  1348. 2 2 Height of the area to display column outlines (above the sheet), in pixel
  1349. 4 2 Number of visible row outline levels (used row levels + 1; or 0, if not used)
  1350. 6 2 Number of visible column outline levels (used column levels + 1; or 0, if not used)
  1351. """
  1352. _REC_ID = 0x0080
  1353. def __init__(self, row_gut_width, col_gut_height, row_visible_levels, col_visible_levels):
  1354. self._rec_data = pack('<4H', row_gut_width, col_gut_height, row_visible_levels, col_visible_levels)
  1355. class WSBoolRecord(BiffRecord):
  1356. """
  1357. This record stores a 16 bit value with Boolean options for the current
  1358. sheet. From BIFF5 on the "Save external linked values" option is moved
  1359. to the record BOOKBOOL.
  1360. Option flags of record WSBOOL, BIFF3-BIFF8:
  1361. Bit Mask Contents
  1362. 0 0001H 0 = Do not show automatic page breaks
  1363. 1 = Show automatic page breaks
  1364. 4 0010H 0 = Standard sheet
  1365. 1 = Dialogue sheet (BIFF5-BIFF8)
  1366. 5 0020H 0 = No automatic styles in outlines
  1367. 1 = Apply automatic styles to outlines
  1368. 6 0040H 0 = Outline buttons above outline group
  1369. 1 = Outline buttons below outline group
  1370. 7 0080H 0 = Outline buttons left of outline group
  1371. 1 = Outline buttons right of outline group
  1372. 8 0100H 0 = Scale printout in percent
  1373. 1 = Fit printout to number of pages
  1374. 9 0200H 0 = Save external linked values (BIFF3?BIFF4 only)
  1375. 1 = Do not save external linked values (BIFF3?BIFF4 only)
  1376. 10 0400H 0 = Do not show row outline symbols
  1377. 1 = Show row outline symbols
  1378. 11 0800H 0 = Do not show column outline symbols
  1379. 1 = Show column outline symbols
  1380. 13-12 3000H These flags specify the arrangement of windows.
  1381. They are stored in BIFF4 only.
  1382. 00 = Arrange windows tiled
  1383. 01 = Arrange windows horizontal
  1384. 10 = Arrange windows vertical112 = Arrange windows cascaded
  1385. The following flags are valid for BIFF4-BIFF8 only:
  1386. 14 4000H 0 = Standard expression evaluation
  1387. 1 = Alternative expression evaluation
  1388. 15 8000H 0 = Standard formula entries
  1389. 1 = Alternative formula entries
  1390. """
  1391. _REC_ID = 0x0081
  1392. def __init__(self, options):
  1393. self._rec_data = pack('<H', options)
  1394. class ColInfoRecord(BiffRecord):
  1395. """
  1396. This record specifies the width for a given range of columns.
  1397. If a column does not have a corresponding COLINFO record,
  1398. the width specified in the record STANDARDWIDTH is used. If
  1399. this record is also not present, the contents of the record
  1400. DEFCOLWIDTH is used instead.
  1401. This record also specifies a default XF record to use for
  1402. cells in the columns that are not described by any cell record
  1403. (which contain the XF index for that cell). Additionally,
  1404. the option flags field contains hidden, outline, and collapsed
  1405. options applied at the columns.
  1406. Record COLINFO, BIFF3-BIFF8:
  1407. Offset Size Contents
  1408. 0 2 Index to first column in the range
  1409. 2 2 Index to last column in the range
  1410. 4 2 Width of the columns in 1/256 of the width of the zero character, using default font
  1411. (first FONT record in the file)
  1412. 6 2 Index to XF record for default column formatting
  1413. 8 2 Option flags:
  1414. Bits Mask Contents
  1415. 0 0001H 1 = Columns are hidden
  1416. 10-8 0700H Outline level of the columns (0 = no outline)
  1417. 12 1000H 1 = Columns are collapsed
  1418. 10 2 Not used
  1419. """
  1420. _REC_ID = 0x007D
  1421. def __init__(self, first_col, last_col, width, xf_index, options, unused):
  1422. self._rec_data = pack('<6H', first_col, last_col, width, xf_index, options, unused)
  1423. class CalcModeRecord(BiffRecord):
  1424. """
  1425. This record is part of the Calculation Settings Block.
  1426. It specifies whether to calculate formulas manually,
  1427. automatically or automatically except for multiple table operations.
  1428. Record CALCMODE, BIFF2-BIFF8:
  1429. Offset Size Contents
  1430. 0 2 FFFFH = automatic except for multiple table operations
  1431. 0000H = manually
  1432. 0001H = automatically (default)
  1433. """
  1434. _REC_ID = 0x000D
  1435. def __init__(self, calc_mode):
  1436. self._rec_data = pack('<h', calc_mode)
  1437. class CalcCountRecord(BiffRecord):
  1438. """
  1439. This record is part of the Calculation Settings Block. It specifies the maximum
  1440. number of times the formulas should be iteratively calculated. This is a fail-safe
  1441. against mutually recursive formulas locking up a spreadsheet application.
  1442. Record CALCCOUNT, BIFF2-BIFF8:
  1443. Offset Size Contents
  1444. 0 2 Maximum number of iterations allowed in circular references
  1445. """
  1446. _REC_ID = 0x000C
  1447. def __init__(self, calc_count):
  1448. self._rec_data = pack('<H', calc_count)
  1449. class RefModeRecord(BiffRecord):
  1450. """
  1451. This record is part of the Calculation Settings Block.
  1452. It stores which method is used to show cell addresses in formulas.
  1453. The “RC” mode uses numeric indexes for rows and columns,
  1454. i.e. “R(1)C(-1)”, or “R1C1:R2C2”.
  1455. The “A1” mode uses characters for columns and numbers for rows,
  1456. i.e. “B1”, or “$A$1:$B$2”.
  1457. Record REFMODE, BIFF2-BIFF8:
  1458. Offset Size Contents
  1459. 0 2 0 = RC mode; 1 = A1 mode
  1460. """
  1461. _REC_ID = 0x00F
  1462. def __init__(self, ref_mode):
  1463. self._rec_data = pack('<H', ref_mode)
  1464. class IterationRecord(BiffRecord):
  1465. """
  1466. This record is part of the Calculation Settings Block.
  1467. It stores if iterations are allowed while calculating recursive formulas.
  1468. Record ITERATION, BIFF2-BIFF8:
  1469. Offset Size Contents
  1470. 0 2 0 = Iterations off; 1 = Iterations on
  1471. """
  1472. _REC_ID = 0x011
  1473. def __init__(self, iterations_on):
  1474. self._rec_data = pack('<H', iterations_on)
  1475. class DeltaRecord(BiffRecord):
  1476. """
  1477. This record is part of the Calculation Settings Block.
  1478. It stores the maximum change of the result to exit an iteration.
  1479. Record DELTA, BIFF2-BIFF8:
  1480. Offset Size Contents
  1481. 0 8 Maximum change in iteration
  1482. (IEEE 754 floating-point value,
  1483. 64bit double precision)
  1484. """
  1485. _REC_ID = 0x010
  1486. def __init__(self, delta):
  1487. self._rec_data = pack('<d', delta)
  1488. class SaveRecalcRecord(BiffRecord):
  1489. """
  1490. This record is part of the Calculation Settings Block.
  1491. It contains the “Recalculate before save” option in
  1492. Excel's calculation settings dialogue.
  1493. Record SAVERECALC, BIFF3-BIFF8:
  1494. Offset Size Contents
  1495. 0 2 0 = Do not recalculate;
  1496. 1 = Recalculate before saving the document
  1497. """
  1498. _REC_ID = 0x05F
  1499. def __init__(self, recalc):
  1500. self._rec_data = pack('<H', recalc)
  1501. class PrintHeadersRecord(BiffRecord):
  1502. """
  1503. This record stores if the row and column headers
  1504. (the areas with row numbers and column letters) will be printed.
  1505. Record PRINTHEADERS, BIFF2-BIFF8:
  1506. Offset Size Contents
  1507. 0 2 0 = Do not print row/column headers;
  1508. 1 = Print row/column headers
  1509. """
  1510. _REC_ID = 0x02A
  1511. def __init__(self, print_headers):
  1512. self._rec_data = pack('<H', print_headers)
  1513. class PrintGridLinesRecord(BiffRecord):
  1514. """
  1515. This record stores if sheet grid lines will be printed.
  1516. Record PRINTGRIDLINES, BIFF2-BIFF8:
  1517. Offset Size Contents
  1518. 0 2 0 = Do not print sheet grid lines;
  1519. 1 = Print sheet grid lines
  1520. """
  1521. _REC_ID = 0x02B
  1522. def __init__(self, print_grid):
  1523. self._rec_data = pack('<H', print_grid)
  1524. class GridSetRecord(BiffRecord):
  1525. """
  1526. This record specifies if the option to print sheet grid lines
  1527. (record PRINTGRIDLINES) has ever been changed.
  1528. Record GRIDSET, BIFF3-BIFF8:
  1529. Offset Size Contents
  1530. 0 2 0 = Print grid lines option never changed
  1531. 1 = Print grid lines option changed
  1532. """
  1533. _REC_ID = 0x082
  1534. def __init__(self, print_grid_changed):
  1535. self._rec_data = pack('<H', print_grid_changed)
  1536. class DefaultRowHeightRecord(BiffRecord):
  1537. """
  1538. This record specifies the default height and default flags
  1539. for rows that do not have a corresponding ROW record.
  1540. Record DEFAULTROWHEIGHT, BIFF3-BIFF8:
  1541. Offset Size Contents
  1542. 0 2 Option flags:
  1543. Bit Mask Contents
  1544. 0 0001H 1 = Row height and default font height do not match
  1545. 1 0002H 1 = Row is hidden
  1546. 2 0004H 1 = Additional space above the row
  1547. 3 0008H 1 = Additional space below the row
  1548. 2 2 Default height for unused rows, in twips = 1/20 of a point
  1549. """
  1550. _REC_ID = 0x0225
  1551. def __init__(self, options, def_height):
  1552. self._rec_data = pack('<2H', options, def_height)
  1553. class DefColWidthRecord(BiffRecord):
  1554. """
  1555. This record specifies the default column width for columns that
  1556. do not have a specific width set using the record COLINFO or COLWIDTH.
  1557. This record has no effect, if a STANDARDWIDTH record is present in the file.
  1558. Record DEFCOLWIDTH, BIFF2-BIFF8:
  1559. Offset Size Contents
  1560. 0 2 Column width in characters, using the width of the zero
  1561. character from default font (first FONT record in the file)
  1562. """
  1563. _REC_ID = 0x0055
  1564. def __init__(self, def_width):
  1565. self._rec_data = pack('<H', options, def_width)
  1566. class HorizontalPageBreaksRecord(BiffRecord):
  1567. """
  1568. This record is part of the Page Settings Block. It contains all
  1569. horizontal manual page breaks.
  1570. Record HORIZONTALPAGEBREAKS, BIFF8:
  1571. Offset Size Contents
  1572. 0 2 Number of following row index structures (nm)
  1573. 2 6nm List of nm row index structures. Each row index
  1574. structure contains:
  1575. Offset Size Contents
  1576. 0 2 Index to first row below the page break
  1577. 2 2 Index to first column of this page break
  1578. 4 2 Index to last column of this page break
  1579. The row indexes in the lists must be ordered ascending.
  1580. If in BIFF8 a row contains several page breaks, they must be ordered
  1581. ascending by start column index.
  1582. """
  1583. _REC_ID = 0x001B
  1584. def __init__(self, breaks_list):
  1585. self._rec_data = pack('<H', len(breaks_list))
  1586. for r, c1, c2 in breaks_list:
  1587. self._rec_data += pack('<3H', r, c1, c2)
  1588. class VerticalPageBreaksRecord(BiffRecord):
  1589. """
  1590. This record is part of the Page Settings Block. It contains all
  1591. vertical manual page breaks.
  1592. Record VERTICALPAGEBREAKS, BIFF8:
  1593. Offset Size Contents
  1594. 0 2 Number of following column index structures (nm)
  1595. 2 6nm List of nm column index structures. Each column index
  1596. structure contains:
  1597. Offset Size Contents
  1598. 0 2 Index to first column following the page
  1599. break
  1600. 2 2 Index to first row of this page break
  1601. 4 2 Index to last row of this page break
  1602. The column indexes in the lists must be ordered ascending.
  1603. If in BIFF8 a column contains several page breaks, they must be ordered
  1604. ascending by start row index.
  1605. """
  1606. _REC_ID = 0x001A
  1607. def __init__(self, breaks_list):
  1608. self._rec_data = pack('<H', len(breaks_list))
  1609. for r, c1, c2 in breaks_list:
  1610. self._rec_data += pack('<3H', r, c1, c2)
  1611. class HeaderRecord(BiffRecord):
  1612. """
  1613. This record is part of the Page Settings Block. It specifies the
  1614. page header string for the current worksheet. If this record is not
  1615. present or completely empty (record size is 0), the sheet does not
  1616. contain a page header.
  1617. Record HEADER for non-empty page header, BIFF2-BIFF8:
  1618. Offset Size Contents
  1619. 0 var. Page header string
  1620. BIFF2-BIFF7: Non-empty byte string, 8bit string
  1621. length
  1622. BIFF8: Non-empty Unicode string, 16bit string length
  1623. The header string may contain special commands, i.e. placeholders for
  1624. the page number, current date, or text formatting attributes. These
  1625. fields are represented by single letters (exception: font name and
  1626. size, see below) with a leading ampersand ("&"). If the ampersand
  1627. is part of the regular header text, it will be duplicated ("&&"). The
  1628. page header is divided into 3 sections: the left, the centred, and the
  1629. right section. Each section is introduced by a special command. All
  1630. text and all commands following are part of the selected section. Each
  1631. section starts with the text formatting specified in the default font
  1632. (first FONT record in the file). Active formatting attributes from
  1633. a previous section do not go into the next section.
  1634. The following table shows all available commands:
  1635. Command Contents
  1636. && The "&" character itself
  1637. &L Start of the left section
  1638. &C Start of the centred section
  1639. &R Start of the right section
  1640. &P Current page number
  1641. &N Page count
  1642. &D Current date
  1643. &T Current time
  1644. &A Sheet name (BIFF5-BIFF8)
  1645. &F File name without path
  1646. &Z File path without file name (BIFF8X)
  1647. &G Picture (BIFF8X)
  1648. &B Bold on/off (BIFF2-BIFF4)
  1649. &I Italic on/off (BIFF2-BIFF4)
  1650. &U Underlining on/off
  1651. &E Double underlining on/off (BIFF5-BIFF8)
  1652. &S Strikeout on/off
  1653. &X Superscript on/off (BIFF5-BIFF8)
  1654. &Y Subscript on/off (BIFF5-BIFF8)
  1655. &"<fontname>" Set new font <fontname>
  1656. &"<fontname>,<fontstyle>"
  1657. Set new font with specified style <fontstyle>.
  1658. The style <fontstyle> is in most cases one of
  1659. "Regular", "Bold", "Italic", or "Bold Italic".
  1660. But this setting is dependent on the used font,
  1661. it may differ (localised style names, or "Standard",
  1662. "Oblique", ...). (BIFF5-BIFF8)
  1663. &<fontheight> Set font height in points (<fontheight> is a decimal value).
  1664. If this command is followed by a plain number to be printed
  1665. in the header, it will be separated from the font height
  1666. with a space character.
  1667. """
  1668. _REC_ID = 0x0014
  1669. def __init__(self, header_str):
  1670. self._rec_data = upack2(header_str)
  1671. class FooterRecord(BiffRecord):
  1672. """
  1673. Semantic is equal to HEADER record
  1674. """
  1675. _REC_ID = 0x0015
  1676. def __init__(self, footer_str):
  1677. self._rec_data = upack2(footer_str)
  1678. class HCenterRecord(BiffRecord):
  1679. """
  1680. This record is part of the Page Settings Block. It specifies if the
  1681. sheet is centred horizontally when printed.
  1682. Record HCENTER, BIFF3-BIFF8:
  1683. Offset Size Contents
  1684. 0 2 0 = Print sheet left aligned
  1685. 1 = Print sheet centred horizontally
  1686. """
  1687. _REC_ID = 0x0083
  1688. def __init__(self, is_horz_center):
  1689. self._rec_data = pack('<H', is_horz_center)
  1690. class VCenterRecord(BiffRecord):
  1691. """
  1692. This record is part of the Page Settings Block. It specifies if the
  1693. sheet is centred vertically when printed.
  1694. Record VCENTER, BIFF3-BIFF8:
  1695. Offset Size Contents
  1696. 0 2 0 = Print sheet aligned at top page border
  1697. 1 = Print sheet vertically centred
  1698. """
  1699. _REC_ID = 0x0084
  1700. def __init__(self, is_vert_center):
  1701. self._rec_data = pack('<H', is_vert_center)
  1702. class LeftMarginRecord(BiffRecord):
  1703. """
  1704. This record is part of the Page Settings Block. It contains the left
  1705. page margin of the current worksheet.
  1706. Record LEFTMARGIN, BIFF2-BIFF8:
  1707. Offset Size Contents
  1708. 0 8 Left page margin in inches
  1709. (IEEE 754 floating-point value, 64bit double precision)
  1710. """
  1711. _REC_ID = 0x0026
  1712. def __init__(self, margin):
  1713. self._rec_data = pack('<d', margin)
  1714. class RightMarginRecord(BiffRecord):
  1715. """
  1716. This record is part of the Page Settings Block. It contains the right
  1717. page margin of the current worksheet.
  1718. Offset Size Contents
  1719. 0 8 Right page margin in inches
  1720. (IEEE 754 floating-point value, 64?bit double precision)
  1721. """
  1722. _REC_ID = 0x0027
  1723. def __init__(self, margin):
  1724. self._rec_data = pack('<d', margin)
  1725. class TopMarginRecord(BiffRecord):
  1726. """
  1727. This record is part of the Page Settings Block. It contains the top
  1728. page margin of the current worksheet.
  1729. Offset Size Contents
  1730. 0 8 Top page margin in inches
  1731. (IEEE 754 floating-point value, 64?bit double precision)
  1732. """
  1733. _REC_ID = 0x0028
  1734. def __init__(self, margin):
  1735. self._rec_data = pack('<d', margin)
  1736. class BottomMarginRecord(BiffRecord):
  1737. """
  1738. This record is part of the Page Settings Block. It contains the bottom
  1739. page margin of the current worksheet.
  1740. Offset Size Contents
  1741. 0 8 Bottom page margin in inches
  1742. (IEEE 754 floating-point value, 64?bit double precision)
  1743. """
  1744. _REC_ID = 0x0029
  1745. def __init__(self, margin):
  1746. self._rec_data = pack('<d', margin)
  1747. class SetupPageRecord(BiffRecord):
  1748. """
  1749. This record is part of the Page Settings Block. It stores the page
  1750. format settings of the current sheet. The pages may be scaled in
  1751. percent or by using an absolute number of pages. This setting is
  1752. located in the WSBOOL record. If pages are scaled in percent,
  1753. the scaling factor in this record is used, otherwise the "Fit to
  1754. pages" values. One of the "Fit to pages" values may be 0. In this case
  1755. the sheet is scaled to fit only to the other value.
  1756. Record SETUP, BIFF5-BIFF8:
  1757. Offset Size Contents
  1758. 0 2 Paper size (see below)
  1759. 2 2 Scaling factor in percent
  1760. 4 2 Start page number
  1761. 6 2 Fit worksheet width to this number of pages
  1762. (0 = use as many as needed)
  1763. 8 2 Fit worksheet height to this number of pages
  1764. (0 = use as many as needed)
  1765. 10 2 Option flags:
  1766. Bit Mask Contents
  1767. 0 0001H 0 = Print pages in columns
  1768. 1 = Print pages in rows
  1769. 1 0002H 0 = Landscape
  1770. 1 = Portrait
  1771. 2 0004H 1 = Paper size, scaling factor,
  1772. paper orientation (portrait/landscape),
  1773. print resolution and number of copies
  1774. are not initialised
  1775. 3 0008H 0 = Print coloured
  1776. 1 = Print black and white
  1777. 4 0010H 0 = Default print quality
  1778. 1 = Draft quality
  1779. 5 0020H 0 = Do not print cell notes
  1780. 1 = Print cell notes
  1781. 6 0040H 0 = Paper orientation setting is valid
  1782. 1 = Paper orientation setting not
  1783. initialised
  1784. 7 0080H 0 = Automatic page numbers
  1785. 1 = Use start page number
  1786. The following flags are valid for BIFF8 only:
  1787. 9 0200H 0 = Print notes as displayed
  1788. 1 = Print notes at end of sheet
  1789. 11-10 0C00H 00 = Print errors as displayed
  1790. 01 = Do not print errors
  1791. 10 = Print errors as "--"
  1792. 11 = Print errors as "#N/A!"
  1793. 12 2 Print resolution in dpi
  1794. 14 2 Vertical print resolution in dpi
  1795. 16 8 Header margin (IEEE 754 floating-point value,
  1796. 64bit double precision)
  1797. 24 8 Footer margin (IEEE 754 floating-point value,
  1798. 64bit double precision)
  1799. 32 2 Number of copies to print
  1800. PAPER TYPES:
  1801. Index Paper type Paper size
  1802. 0 Undefined
  1803. 1 Letter 8 1/2" x 11"
  1804. 2 Letter small 8 1/2" x 11"
  1805. 3 Tabloid 11" x 17"
  1806. 4 Ledger 17" x 11"
  1807. 5 Legal 8 1/2" x 14"
  1808. 6 Statement 5 1/2" x 8 1/2"
  1809. 7 Executive 7 1/4" x 10 1/2"
  1810. 8 A3 297mm x 420mm
  1811. 9 A4 210mm x 297mm
  1812. 10 A4 small 210mm x 297mm
  1813. 11 A5 148mm x 210mm
  1814. 12 B4 (JIS) 257mm x 364mm
  1815. 13 B5 (JIS) 182mm x 257mm
  1816. 14 Folio 8 1/2" x 13"
  1817. 15 Quarto 215mm x 275mm
  1818. 16 10x14 10" x 14"
  1819. 17 11x17 11" x 17"
  1820. 18 Note 8 1/2" x 11"
  1821. 19 Envelope #9 3 7/8" x 8 7/8"
  1822. 20 Envelope #10 4 1/8" x 9 1/2"
  1823. 21 Envelope #11 4 1/2" x 10 3/8"
  1824. 22 Envelope #12 4 3/4" x 11"
  1825. 23 Envelope #14 5" x 11 1/2"
  1826. 24 C 17" x 22"
  1827. 25 D 22" x 34"
  1828. 26 E 34" x 44"
  1829. 27 Envelope DL 110mm x 220mm
  1830. 28 Envelope C5 162mm x 229mm
  1831. 29 Envelope C3 324mm x 458mm
  1832. 30 Envelope C4 229mm x 324mm
  1833. 31 Envelope C6 114mm x 162mm
  1834. 32 Envelope C6/C5 114mm x 229mm
  1835. 33 B4 (ISO) 250mm x 353mm
  1836. 34 B5 (ISO) 176mm x 250mm
  1837. 35 B6 (ISO) 125mm x 176mm
  1838. 36 Envelope Italy 110mm x 230mm
  1839. 37 Envelope Monarch 3 7/8" x 7 1/2"
  1840. 38 63/4 Envelope 3 5/8" x 6 1/2"
  1841. 39 US Standard Fanfold 14 7/8" x 11"
  1842. 40 German Std. Fanfold 8 1/2" x 12"
  1843. 41 German Legal Fanfold 8 1/2" x 13"
  1844. 42 B4 (ISO) 250mm x 353mm
  1845. 43 Japanese Postcard 100mm x 148mm
  1846. 44 9x11 9" x 11"
  1847. 45 10x11 10" x 11"
  1848. 46 15x11 15" x 11"
  1849. 47 Envelope Invite 220mm x 220mm
  1850. 48 Undefined
  1851. 49 Undefined
  1852. 50 Letter Extra 9 1/2" x 12"
  1853. 51 Legal Extra 9 1/2" x 15"
  1854. 52 Tabloid Extra 11 11/16" x 18"
  1855. 53 A4 Extra 235mm x 322mm
  1856. 54 Letter Transverse 8 1/2" x 11"
  1857. 55 A4 Transverse 210mm x 297mm
  1858. 56 Letter Extra Transv. 9 1/2" x 12"
  1859. 57 Super A/A4 227mm x 356mm
  1860. 58 Super B/A3 305mm x 487mm
  1861. 59 Letter Plus 8 1/2" x 12 11/16"
  1862. 60 A4 Plus 210mm x 330mm
  1863. 61 A5 Transverse 148mm x 210mm
  1864. 62 B5 (JIS) Transverse 182mm x 257mm
  1865. 63 A3 Extra 322mm x 445mm
  1866. 64 A5 Extra 174mm x 235mm
  1867. 65 B5 (ISO) Extra 201mm x 276mm
  1868. 66 A2 420mm x 594mm
  1869. 67 A3 Transverse 297mm x 420mm
  1870. 68 A3 Extra Transverse 322mm x 445mm
  1871. 69 Dbl. Japanese Postcard 200mm x 148mm
  1872. 70 A6 105mm x 148mm
  1873. 71
  1874. 72
  1875. 73
  1876. 74
  1877. 75 Letter Rotated 11" x 8 1/2"
  1878. 76 A3 Rotated 420mm x 297mm
  1879. 77 A4 Rotated 297mm x 210mm
  1880. 78 A5 Rotated 210mm x 148mm
  1881. 79 B4 (JIS) Rotated 364mm x 257mm
  1882. 80 B5 (JIS) Rotated 257mm x 182mm
  1883. 81 Japanese Postcard Rot. 148mm x 100mm
  1884. 82 Dbl. Jap. Postcard Rot. 148mm x 200mm
  1885. 83 A6 Rotated 148mm x 105mm
  1886. 84
  1887. 85
  1888. 86
  1889. 87
  1890. 88 B6 (JIS) 128mm x 182mm
  1891. 89 B6 (JIS) Rotated 182mm x 128mm
  1892. 90 12x11 12" x 11"
  1893. """
  1894. _REC_ID = 0x00A1
  1895. def __init__(self, paper, scaling, start_num, fit_width_to, fit_height_to,
  1896. options,
  1897. hres, vres,
  1898. header_margin, footer_margin,
  1899. num_copies):
  1900. self._rec_data = pack('<8H2dH', paper, scaling, start_num,
  1901. fit_width_to, fit_height_to, \
  1902. options,
  1903. hres, vres,
  1904. header_margin, footer_margin,
  1905. num_copies)
  1906. class NameRecord(BiffRecord):
  1907. """
  1908. This record is part of a Link Table. It contains the name and the token
  1909. array of an internal defined name. Token arrays of defined names
  1910. contain tokens with aberrant token classes.
  1911. Record NAME, BIFF5/BIFF7:
  1912. Offset Size Contents
  1913. 0 2 Option flags, see below
  1914. 2 1 Keyboard shortcut (only for command macro names, see below)
  1915. 3 1 Length of the name (character count, ln)
  1916. 4 2 Size of the formula data (sz)
  1917. 6 2 0 = Global name, otherwise index to EXTERNSHEET record (one-based)
  1918. 8 2 0 = Global name, otherwise index to sheet (one-based)
  1919. 10 1 Length of menu text (character count, lm)
  1920. 11 1 Length of description text (character count, ld)
  1921. 12 1 Length of help topic text (character count, lh)
  1922. 13 1 Length of status bar text (character count, ls)
  1923. 14 ln Character array of the name
  1924. 14+ln sz Formula data (RPN token array without size field, 4)
  1925. 14+ln+sz lm Character array of menu text
  1926. var. ld Character array of description text
  1927. var. lh Character array of help topic text
  1928. var. ls Character array of status bar text
  1929. Record NAME, BIFF8:
  1930. Offset Size Contents
  1931. 0 2 Option flags, see below
  1932. 2 1 Keyboard shortcut (only for command macro names, see below)
  1933. 3 1 Length of the name (character count, ln)
  1934. 4 2 Size of the formula data (sz)
  1935. 6 2 Not used
  1936. 8 2 0 = Global name, otherwise index to sheet (one-based)
  1937. 10 1 Length of menu text (character count, lm)
  1938. 11 1 Length of description text (character count, ld)
  1939. 12 1 Length of help topic text (character count, lh)
  1940. 13 1 Length of status bar text (character count, ls)
  1941. 14 var. Name (Unicode string without length field, 3.4)
  1942. var. sz Formula data (RPN token array without size field, 4)
  1943. [var.] var. (optional, only if lm > 0) Menu text (Unicode string without length field, 3.4)
  1944. [var.] var. (optional, only if ld > 0) Description text (Unicode string without length field, 3.4)
  1945. [var.] var. (optional, only if lh > 0) Help topic text (Unicode string without length field, 3.4)
  1946. [var.] var. (optional, only if ls > 0) Status bar text (Unicode string without length field, 3.4)
  1947. """
  1948. _REC_ID = 0x0018
  1949. def __init__(self, options, keyboard_shortcut, name, sheet_index, rpn, menu_text='', desc_text='', help_text='', status_text=''):
  1950. if type(name) == int:
  1951. uname = chr(name)
  1952. else:
  1953. uname = upack1(name)[1:]
  1954. uname_len = len(uname)
  1955. #~ 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
  1956. 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
  1957. # Excel (both 2003 and 2007) don't like refs
  1958. # split over a record boundary, which is what the
  1959. # standard BiffRecord.get method does.
  1960. # 8224 max data bytes in a BIFF record
  1961. # 6 bytes per ref
  1962. # 1370 = floor((8224 - 2) / 6.0) max refs in a record
  1963. _maxRefPerRecord = 1370
  1964. class ExternSheetRecord(BiffRecord):
  1965. """
  1966. In BIFF8 the record stores a list with indexes to SUPBOOK
  1967. records (list of REF structures, 6.100). See 5.10.3 for
  1968. details about external references in BIFF8.
  1969. Record EXTERNSHEET, BIFF8:
  1970. Offset Size Contents
  1971. 0 2 Number of following REF structures (nm)
  1972. 2 6nm List of nm REF structures. Each REF contains the following data:
  1973. Offset Size Contents
  1974. 0 2 Index to SUPBOOK record
  1975. 2 2 Index to first SUPBOOK sheet
  1976. 4 2 Index to last SUPBOOK sheet
  1977. """
  1978. _REC_ID = 0x0017
  1979. def __init__(self, refs):
  1980. # do we always need this ref? or only if there are no refs?
  1981. # (I believe that if there are no refs then we should not generate the link table - Ruben)
  1982. #refs.insert(0, (0,0,0))
  1983. self.refs = refs
  1984. def get(self):
  1985. res = []
  1986. nrefs = len(self.refs)
  1987. for idx in xrange(0, nrefs, _maxRefPerRecord):
  1988. chunk = self.refs[idx:idx+_maxRefPerRecord]
  1989. krefs = len(chunk)
  1990. if idx: # CONTINUE record
  1991. header = pack("<HH", 0x003C, 6 * krefs)
  1992. else: # ExternSheetRecord
  1993. header = pack("<HHH", self._REC_ID, 6 * krefs + 2, nrefs)
  1994. res.append(header)
  1995. res.extend(pack("<HHH", *r) for r in chunk)
  1996. return b''.join(res)
  1997. class SupBookRecord(BiffRecord):
  1998. """
  1999. This record mainly stores the URL of an external document
  2000. and a list of sheet names inside this document. Furthermore
  2001. it is used to store DDE and OLE object links, or to indicate
  2002. an internal 3D reference or an add-in function. See 5.10.3
  2003. for details about external references in BIFF8.
  2004. """
  2005. _REC_ID = 0x01AE
  2006. class InternalReferenceSupBookRecord(SupBookRecord):
  2007. """
  2008. In each file occurs a SUPBOOK that is used for internal 3D
  2009. references. It stores the number of sheets of the own document.
  2010. Record SUPBOOK for 3D references, BIFF8:
  2011. Offset Size Contents
  2012. 0 2 Number of sheets in this document
  2013. 2 2 01H 04H (relict of BIFF5/BIFF7, the byte string "<04H>", see 3.9.1)
  2014. """
  2015. def __init__(self, num_sheets):
  2016. self._rec_data = pack('<HBB', num_sheets, 0x01, 0x04)
  2017. class XcallSupBookRecord(SupBookRecord):
  2018. """
  2019. Add-in function names are stored in EXTERNNAME records following this record.
  2020. Offset Size Contents
  2021. 0 2 0001H
  2022. 2 2 01H 3AH (relict of BIFF5, the byte string ':', see EXTERNSHEET record, 5.41)
  2023. """
  2024. def __init__(self):
  2025. self._rec_data = pack('<HBB', 1, 0x01, 0x3A)
  2026. class ExternnameRecord(BiffRecord):
  2027. """
  2028. Record EXTERNNAME for external names and Analysis add-in functions, BIFF5-BIFF8:
  2029. Offset Size Contents
  2030. 0 2 Option flags (see below)
  2031. 2 2 0 for global names, or:
  2032. BIFF5: One-based index to EXTERNSHEET record containing the sheet name,
  2033. BIFF8: One-based index to sheet list in preceding EXTERNALBOOK record.
  2034. 4 2 Not used
  2035. 6 var. BIFF5: Name (byte string, 8-bit string length, ?2.5.2).
  2036. BIFF8: Name (Unicode string, 8-bit string length, ?2.5.3).
  2037. See DEFINEDNAME record (?5.33) for a list of built-in names, if the built-in flag is set
  2038. in the option flags above.
  2039. var. var. Formula data (RPN token array, ?3)
  2040. Option flags for external names (BIFF5-BIFF8)
  2041. Bit Mask Contents
  2042. 0 0001H 0 = Standard name; 1 = Built-in name
  2043. 1 0002H 0 = Manual link; 1 = Automatic link (DDE links and OLE links only)
  2044. 2 0004H 1 = Picture link (DDE links and OLE links only)
  2045. 3 0008H 1 = This is the “StdDocumentName” identifier (DDE links only)
  2046. 4 0010H 1 = OLE link
  2047. 14-5 7FE0H Clipboard format of last successful update (DDE links and OLE links only)
  2048. 15 8000H 1 = Iconified picture link (BIFF8 OLE links only)
  2049. """
  2050. _REC_ID = 0x0023
  2051. def __init__(self, options=0, index=0, name=None, fmla=None):
  2052. self._rec_data = pack('<HHH', options, index, 0) + upack1(name) + fmla