• R/O
  • SSH
  • HTTPS

traclight: Commit


Commit MetaInfo

Revision44 (tree)
Time2010-09-20 10:28:00
Authortag

Log Message

xlrdを0.7.1におきかえた。

Change Summary

Incremental Difference

--- branches/tl3_0/python-lib/xlrd/README.html (revision 43)
+++ branches/tl3_0/python-lib/xlrd/README.html (revision 44)
@@ -8,9 +8,9 @@
88 </p>
99 <p><b>Licence</b>: BSD-style (see licences.py)
1010 </p>
11-<p><b>Version of xlrd</b>: 0.6.1 final
11+<p><b>Version of xlrd</b>: 0.7.1 -- 2009-05-31
1212 </p>
13-<p><b>Version of Python required</b>: 2.1 or later.
13+<p><b>Versions of Python supported</b>: 2.1 to 2.6.
1414 </p>
1515 <p><b>External modules required</b>:
1616 </p>
@@ -22,8 +22,8 @@
2222 http://optik.sourceforge.net/
2323 </dl>
2424 <p><b>Versions of Excel supported</b>:
25- 2004, 2002, XP, 2000, 97, 95, 5.0, 4.0, 3.0.
26- 2.x could be done readily enough if any demand.
25+ 2004, 2003, XP, 2000, 97, 95, 5.0, 4.0, 3.0, 2.1, 2.0.
26+ Support for Excel 2007 .xlsx files scheduled for version 0.7.1.
2727 </p>
2828 <p><b>Outside the current scope</b>: xlrd will safely and reliably ignore any of these
2929 if present in the file:
@@ -97,7 +97,7 @@
9797 </ul>
9898 <p><b>Download URLs</b>:
9999 </p>
100-<ul><li> http://cheeseshop.python.org/pypi/xlrd
100+<ul><li> http://pypi.python.org/pypi/xlrd
101101 </li>
102102 <li> http://www.lexicon.net/sjmachin/xlrd.htm
103103 </li>
--- branches/tl3_0/python-lib/xlrd/HISTORY.html (revision 43)
+++ branches/tl3_0/python-lib/xlrd/HISTORY.html (revision 44)
@@ -1,7 +1,91 @@
1+TODO -- refer to svn log if you really need to know :-)
2+
3+<p> Revision : 3782 -- Author: sjmachin -- Date: 2009-02-23 23:00:50
4+</p><ul>
5+ <li> colname utility function now supports more than 256 columns.
6+</li><li> Fix bug where BIFF record type 0x806 was being regarded as a formula opcode.
7+</li><li> Ignore PALETTE record when formatting_info is false.
8+</li><li> Tolerate up to 4 bytes trailing junk on PALETTE record.
9+</li><li> Fixed bug in unused utility function xldate_from_date_tuple which affected some years after 2099.
10+</li><li> Added code for inspecting as-yet-unused record types: FILEPASS, TXO, NOTE.
11+</li><li> Added inspection code for add_in function calls.
12+</li><li> Added support for unnumbered biff_dump (better for doing diffs).
13+</li></ul>
14+<p> Revision : 3613 -- Author: chris -- Date: 2008-11-22 04:06:36
15+</p><ul>
16+ <li> ignore distutils cruft
17+</li></ul>
18+<p> Revision : 3574 -- Author: sjmachin -- Date: 2008-11-04 11:51:20
19+</p><ul>
20+ <li> Avoid assertion error in compdoc when -1 used instead of -2 for first_SID of empty SCSS
21+</li></ul>
22+<p> Revision : 3480 -- Author: chris -- Date: 2008-09-19 20:43:00
23+</p><ul>
24+ <li> Make version numbers match up.
25+</li></ul>
26+<p> Revision : 3431 -- Author: sjmachin -- Date: 2008-07-28 10:37:35
27+</p><ul>
28+ <li> Enhanced recovery from out-of-order/missing/wrong CODEPAGE record.
29+</li><li> Added Name.area2d convenience method.
30+</li><li> Avoided some checking of XF info when formatting_info is false.
31+</li><li> Minor changes in preparation for XLSX support.
32+</li></ul>
33+<p> Revision : 3311 -- Author: chris -- Date: 2008-03-14 22:09:01
34+</p><ul>
35+ <li> remove duplicate files that were out of date.
36+</li></ul>
37+<p> Revision : 3287 -- Author: sjmachin -- Date: 2008-02-14 06:33:32
38+</p><ul>
39+ <li> Basic support for Excel 2.0
40+</li></ul>
41+<p> Revision : 3284 -- Author: sjmachin -- Date: 2008-02-09 05:37:57
42+</p><ul>
43+ <li> Decouple Book init & load.
44+</li><li> runxlrd: minor fix for xfc.
45+</li><li> More Excel 2.x work.
46+</li><li> is_date_format() tweak.
47+</li><li> Better detection of IronPython.
48+</li></ul>
49+<p> Revision : 3265 -- Author: sjmachin -- Date: 2007-12-25 19:09:45
50+</p><ul>
51+ <li> Better error message (including first 8 bytes of file) when file is not in a supported format.
52+</li></ul>
53+<p> Revision : 3263 -- Author: sjmachin -- Date: 2007-12-20 07:04:55
54+</p><ul>
55+ <li> More BIFF2 formatting: ROW, COLWIDTH, and COLUMNDEFAULT records;
56+</li><li> finished stage 1 of XF records.
57+</li></ul>
58+<p> Revision : 3262 -- Author: sjmachin -- Date: 2007-12-11 07:40:33
59+</p><ul>
60+ <li> More work on supporting BIFF2 (Excel 2.x) files.
61+</li></ul>
62+<p> Revision : 3250 -- Author: sjmachin -- Date: 2007-12-04 20:37:14
63+</p><ul>
64+ <li> Added support for Excel 2.x (BIFF2) files. Data only, no formatting info. Alpha.
65+</li></ul>
66+<p> Revision : 3234 -- Author: sjmachin -- Date: 2007-11-21 00:55:56
67+</p><ul>
68+ <li> Wasn't coping with EXTERNSHEET record followed by CONTINUE record(s).
69+</li></ul>
70+<p> Revision : 3168 -- Author: sjmachin -- Date: 2007-10-13 09:19:01
71+</p><ul>
72+ <li> Allow for BIFF2/3-style FORMAT record in BIFF4/8 file
73+</li><li> Avoid crash when zero-length Unicode string missing options byte.
74+</li><li> Warning message if sector sizes are extremely large.
75+</li><li> Work around corrupt STYLE record
76+</li><li> Added missing entry for blank cell type to ctype_text
77+</li><li> Added "fonts" command to runxlrd script
78+</li><li> Warning: style XF whose parent XF index != 0xFFF
79+</li></ul>
80+<p> Revision : 2868 -- Author: sjmachin -- Date: 2007-07-11 11:02:55
81+</p><ul>
82+ <li> Logfile arg wasn't being passed from open_workbook to compdoc.CompDoc.
83+</li></ul>
84+
185 <p> Version 0.6.1, 2007-06-10
286 </p>
387 <ul>
4-<li> Version number updated to 1.6.1
88+<li> Version number updated to 0.6.1
589 </li>
690 <li> Documented runxlrd.py commands in its usage message. Changed commands: dump to biff_dump, count_records to biff_count.
791 </li>
--- branches/tl3_0/python-lib/xlrd/scripts/runxlrd.py (revision 43)
+++ branches/tl3_0/python-lib/xlrd/scripts/runxlrd.py (revision 44)
@@ -1,8 +1,13 @@
11 # -*- coding: cp1252 -*-
2-# <p>Copyright ゥ 2005-2007 Stephen John Machin, Lingfo Pty Ltd</p>
2+# <p>Copyright ゥ 2005-2008 Stephen John Machin, Lingfo Pty Ltd</p>
33 # <p>This script is part of the xlrd package, which is released under a
44 # BSD-style licence.</p>
55
6+# 2009-04-27 SJM Integrated on_demand patch by Armando Serrano Lombillo
7+# 2008-08-03 SJM Omit counts of FORMAT/FONT/XF records when formatting_info is false
8+# 2008-02-08 SJM Force formatting_info=1 for xfc command
9+# 2007-12-05 SJM Fixed usage of deprecated/removed Book.raw_xf_list
10+# 2007-10-13 SJM Added "fonts" command
611 # 2007-06-10 SJM Removed reference to removed "trimming" option-value.
712 # 2007-06-10 SJM Added documentation of commands.
813 # 2007-06-10 SJM Changed cmds: dump -> biff_dump, count_records -> biff_count.
@@ -15,6 +20,7 @@
1520 bench Same as "show", but doesn't print -- for profiling
1621 biff_count[1] Print a count of each type of BIFF record in the file
1722 biff_dump[1] Print a dump (char and hex) of the BIFF records in the file
23+fonts hdr + print a dump of all font objects
1824 hdr Mini-overview of file (no per-sheet information)
1925 hotshot Do a hotshot profile run e.g. ... -f1 hotshot bench bigfile*.xls
2026 labels Dump of sheet.col_label_ranges and ...row... for each sheet
@@ -86,14 +92,21 @@
8692 % (bk.codepage, bk.encoding, bk.countries)
8793 print "Last saved by: %r" % bk.user_name
8894 print "Number of data sheets: %d" % bk.nsheets
89- print "Pickleable: %d; Use mmap: %d; Formatting: %d" \
90- % (bk.pickleable, bk.use_mmap, bk.formatting_info)
91- print "FORMATs: %d, FONTs: %d, XFs: %d" \
92- % (len(bk.format_list), len(bk.font_list), len(bk.raw_xf_list))
95+ print "Pickleable: %d; Use mmap: %d; Formatting: %d; On demand: %d" \
96+ % (bk.pickleable, bk.use_mmap, bk.formatting_info, bk.on_demand)
97+ if bk.formatting_info:
98+ print "FORMATs: %d, FONTs: %d, XFs: %d" \
99+ % (len(bk.format_list), len(bk.font_list), len(bk.xf_list))
93100 print "Load time: %.2f seconds (stage 1) %.2f seconds (stage 2)" \
94101 % (bk.load_time_stage_1, bk.load_time_stage_2)
95102 print
96103
104+ def show_fonts(bk):
105+ print "Fonts:"
106+ for x in xrange(len(bk.font_list)):
107+ font = bk.font_list[x]
108+ font.dump(header='== Index %d ==' % x, indent=4)
109+
97110 def show_names(bk, dump=0):
98111 bk_header(bk)
99112 if bk.biff_version < 50:
@@ -236,6 +249,14 @@
236249 "-s", "--onesheet",
237250 default="",
238251 help="restrict output to this sheet (name or index)")
252+ oparser.add_option(
253+ "-u", "--unnumbered",
254+ action="store_true", default=0,
255+ help="omit line numbers or offsets in biff_dump")
256+ oparser.add_option(
257+ "-d", "--on-demand",
258+ action="store_true", default=0,
259+ help="load sheets on demand instead of all at once")
239260
240261 options, args = oparser.parse_args(cmd_args)
241262 if len(args) == 1 and args[0] in ("version", ):
@@ -245,7 +266,7 @@
245266 cmd = args[0]
246267 xlrd_version = getattr(xlrd, "__VERSION__", "unknown; before 0.5")
247268 if cmd == 'biff_dump':
248- xlrd.dump(args[1])
269+ xlrd.dump(args[1], unnumbered=options.unnumbered)
249270 sys.exit(0)
250271 if cmd == 'biff_count':
251272 xlrd.count_records(args[1])
@@ -264,7 +285,7 @@
264285 mmap_arg = mmap_opt
265286 elif mmap_opt != -1:
266287 print 'Unexpected value (%r) for mmap option -- assuming default' % mmap_opt
267- fmt_opt = options.formatting
288+ fmt_opt = options.formatting | (cmd in ('xfc', ))
268289 gc_mode = options.gc
269290 if gc_mode:
270291 gc.disable()
@@ -282,6 +303,7 @@
282303 pickleable=options.pickleable, use_mmap=mmap_arg,
283304 encoding_override=options.encoding,
284305 formatting_info=fmt_opt,
306+ on_demand=options.on_demand,
285307 )
286308 t1 = time.time()
287309 print >> logfile, "Open took %.2f seconds" % (t1-t0,)
@@ -308,7 +330,10 @@
308330 elif cmd == '3rows': # first row, 2nd row and last row
309331 show(bk, 3)
310332 elif cmd == 'bench':
311- show(bk, printit=False)
333+ show(bk, printit=0)
334+ elif cmd == 'fonts':
335+ bk_header(bk)
336+ show_fonts(bk)
312337 elif cmd == 'names': # named reference list
313338 show_names(bk)
314339 elif cmd == 'name_dump': # named reference list
--- branches/tl3_0/python-lib/xlrd/setup.py (revision 43)
+++ branches/tl3_0/python-lib/xlrd/setup.py (revision 44)
@@ -20,7 +20,7 @@
2020
2121 args = mkargs(
2222 name = 'xlrd',
23- version = '0.6.1',
23+ version = '0.7.1',
2424 author = 'John Machin',
2525 author_email = 'sjmachin@lexicon.net',
2626 url = the_url,
@@ -31,7 +31,7 @@
3131 description = 'Library for developers to extract data from Microsoft Excel (tm) spreadsheet files',
3232 long_description = \
3333 "Extract data from new and old Excel spreadsheets on any platform. " \
34- "Pure Python (2.1 or later). Strong support for Excel dates. Unicode-aware.",
34+ "Pure Python (2.1 to 2.6). Strong support for Excel dates. Unicode-aware.",
3535 platforms = ["Any platform -- don't need Windows"],
3636 license = 'BSD',
3737 keywords = ['xls', 'excel', 'spreadsheet', 'workbook'],
--- branches/tl3_0/python-lib/xlrd/xlrd/sheet.py (revision 43)
+++ branches/tl3_0/python-lib/xlrd/xlrd/sheet.py (revision 44)
@@ -1,10 +1,16 @@
11 # -*- coding: cp1252 -*-
22
33 ##
4-# <p> Portions copyright ゥ 2005-2006 Stephen John Machin, Lingfo Pty Ltd</p>
4+# <p> Portions copyright ゥ 2005-2009 Stephen John Machin, Lingfo Pty Ltd</p>
55 # <p>This module is part of the xlrd package, which is released under a BSD-style licence.</p>
66 ##
77
8+# 2009-05-31 SJM Fixed problem with no CODEPAGE record on extremely minimal BIFF2.x 3rd-party file
9+# 2009-04-27 SJM Integrated on_demand patch by Armando Serrano Lombillo
10+# 2008-02-09 SJM Excel 2.0: build XFs on the fly from cell attributes
11+# 2007-12-04 SJM Added support for Excel 2.x (BIFF2) files.
12+# 2007-10-11 SJM Added missing entry for blank cell type to ctype_text
13+# 2007-07-11 SJM Allow for BIFF2/3-style FORMAT record in BIFF4/8 file
814 # 2007-04-22 SJM Remove experimental "trimming" facility.
915
1016 from biffh import *
@@ -11,10 +17,11 @@
1117 from timemachine import *
1218 from struct import unpack
1319 from formula import dump_formula, decompile_formula, rangename2d
14-from formatting import nearest_colour_index
20+from formatting import nearest_colour_index, Format
1521 import time
1622
1723 DEBUG = 0
24+OBJ_MSO_DEBUG = 0
1825
1926 _WINDOW2_options = (
2027 # Attribute names and initial values to use in case
@@ -31,7 +38,7 @@
3138 ("sheet_selected", 0),
3239 # "sheet_visible" appears to be merely a clone of "sheet_selected".
3340 # The real thing is the visibility attribute from the BOUNDSHEET record.
34- ("sheet_visible", 0),
41+ ("sheet_visible", 0),
3542 ("show_in_page_break_preview", 0),
3643 )
3744
@@ -47,7 +54,7 @@
4754 # <p>WARNING: You don't call this class yourself. You access Sheet objects via the Book object that
4855 # was returned when you called xlrd.open_workbook("myfile.xls").</p>
4956
50-
57+
5158 class Sheet(BaseObject):
5259 ##
5360 # Name of sheet.
@@ -101,7 +108,7 @@
101108 # List of address ranges of cells which have been merged.
102109 # These are set up in Excel by Format > Cells > Alignment, then ticking
103110 # the "Merge cells" box.
104- # <br> -- New in version 0.6.1
111+ # <br> -- New in version 0.6.1. Extracted only if open_workbook(..., formatting_info=True)
105112 # <br>How to deconstruct the list:
106113 # <pre>
107114 # for crange in thesheet.merged_cells:
@@ -168,13 +175,13 @@
168175 # no ROW record for that row.
169176 # From the <i>optional</i> DEFAULTROWHEIGHT record.
170177 default_additional_space_below = None
171-
178+
172179 ##
173180 # Visibility of the sheet. 0 = visible, 1 = hidden (can be unhidden
174181 # by user -- Format/Sheet/Unhide), 2 = "very hidden" (can be unhidden
175182 # only by VBA macro).
176183 visibility = 0
177-
184+
178185 ##
179186 # A 256-element tuple corresponding to the contents of the GCW record for this sheet.
180187 # If no such record, treat as all bits zero.
@@ -225,14 +232,17 @@
225232 self.gridline_colour_rgb = None # pre-BIFF8
226233 self.cached_page_break_preview_mag_factor = 0
227234 self.cached_normal_view_mag_factor = 0
228-
235+ self._ixfe = None # BIFF2 only
236+ self._cell_attr_to_xfx = {} # BIFF2.0 only
237+
229238 #### Don't initialise this here, use class attribute initialisation.
230- #### self.gcw = (0, ) * 256 ####
231-
239+ #### self.gcw = (0, ) * 256 ####
240+
232241 if self.biff_version >= 80:
233242 self.utter_max_rows = 65536
234243 else:
235244 self.utter_max_rows = 16384
245+ self.utter_max_cols = 256
236246
237247 ##
238248 # Cell object in the given row and column.
@@ -260,7 +270,7 @@
260270
261271 ##
262272 # XF index of the cell in the given row and column.
263- # This is an index into Book.raw_xf_list and Book.computed_xf_list.
273+ # This is an index into Book.xf_list.
264274 # <br /> -- New in version 0.6.1
265275 def cell_xf_index(self, rowx, colx):
266276 self.req_fmt_info()
@@ -391,7 +401,7 @@
391401
392402 def extend_cells(self, nr, nc):
393403 # print "extend_cells_2", self.nrows, self.ncols, nr, nc
394- assert 1 <= nc <= 256
404+ assert 1 <= nc <= self.utter_max_cols
395405 assert 1 <= nr <= self.utter_max_rows
396406 if nr <= self.nrows:
397407 # New cell is in an existing row, so extend that row (if necessary).
@@ -481,10 +491,11 @@
481491 if 1 and self.merged_cells:
482492 nr = nc = 0
483493 umaxrows = self.utter_max_rows
494+ umaxcols = self.utter_max_cols
484495 for crange in self.merged_cells:
485496 rlo, rhi, clo, chi = crange
486497 if not (0 <= rlo < rhi <= umaxrows) \
487- or not (0 <= clo < chi <= 256):
498+ or not (0 <= clo < chi <= umaxcols):
488499 fprintf(self.logfile,
489500 "*** WARNING: sheet #%d (%r), MERGEDCELLS bad range %r\n",
490501 self.number, self.name, crange)
@@ -577,9 +588,9 @@
577588 DEBUG = 0
578589 blah = DEBUG or self.verbosity >= 2
579590 blah_rows = DEBUG or self.verbosity >= 4
580- blah_formulas = 0 and blah
591+ blah_formulas = 1 and blah
581592 oldpos = bk._position
582- bk.position(self._position)
593+ bk._position = self._position
583594 XL_SHRFMLA_ETC_ETC = (
584595 XL_SHRFMLA, XL_ARRAY, XL_TABLEOP, XL_TABLEOP2,
585596 XL_ARRAY2, XL_TABLEOP_B2,
@@ -614,7 +625,7 @@
614625 # RSTRING has extra richtext info at the end, but we ignore it.
615626 rowx, colx, xf_index = local_unpack('<HHH', data[0:6])
616627 if bv < BIFF_FIRST_UNICODE:
617- strg = unpack_string(data, 6, bk.encoding, lenlen=2)
628+ strg = unpack_string(data, 6, bk.encoding or bk.derive_encoding, lenlen=2)
618629 else:
619630 strg = unpack_unicode(data, 6, lenlen=2)
620631 self_put_cell(rowx, colx, XL_CELL_TEXT, strg, xf_index)
@@ -681,17 +692,30 @@
681692 print >> self.logfile, 'ROW', rowx, bits1, bits2
682693 r.dump(self.logfile,
683694 header="--- sh #%d, rowx=%d ---" % (self.number, rowx))
684- elif rc & 0xff == XL_FORMULA: # 06, 0206, 0406
695+ elif rc in XL_FORMULA_OPCODES: # 06, 0206, 0406
685696 # DEBUG = 1
686697 # if DEBUG: print "FORMULA: rc: 0x%04x data: %r" % (rc, data)
687- rowx, colx, xf_index, flags = local_unpack('<HHHxxxxxxxxH', data[0:16])
698+ if bv >= 50:
699+ rowx, colx, xf_index, result_str, flags = local_unpack('<HHH8sH', data[0:16])
700+ lenlen = 2
701+ tkarr_offset = 20
702+ elif bv >= 30:
703+ rowx, colx, xf_index, result_str, flags = local_unpack('<HHH8sH', data[0:16])
704+ lenlen = 2
705+ tkarr_offset = 16
706+ else: # BIFF2
707+ rowx, colx, cell_attr, result_str, flags = local_unpack('<HH3s8sB', data[0:16])
708+ xf_index = self.fixed_BIFF2_xfindex(cell_attr, rowx, colx)
709+ lenlen = 1
710+ tkarr_offset = 16
688711 if blah_formulas: # testing formula dumper
712+ #### XXXX FIXME
689713 fprintf(self.logfile, "FORMULA: rowx=%d colx=%d\n", rowx, colx)
690714 fmlalen = local_unpack("<H", data[20:22])[0]
691715 decompile_formula(bk, data[22:], fmlalen,
692716 reldelta=0, browx=rowx, bcolx=colx, blah=1)
693- if data[12] == '\xff' and data[13] == '\xff':
694- if data[6] == '\x00':
717+ if result_str[6:8] == "\xFF\xFF":
718+ if result_str[0] == '\x00':
695719 # need to read next record (STRING)
696720 gotstring = 0
697721 # if flags & 8:
@@ -698,7 +722,7 @@
698722 if 1: # "flags & 8" applies only to SHRFMLA
699723 # actually there's an optional SHRFMLA or ARRAY etc record to skip over
700724 rc2, data2_len, data2 = bk.get_record_parts()
701- if rc2 == XL_STRING:
725+ if rc2 == XL_STRING or rc2 == XL_STRING_B2:
702726 gotstring = 1
703727 elif rc2 == XL_ARRAY:
704728 row1x, rownx, col1x, colnx, array_flags, tokslen = \
@@ -721,30 +745,31 @@
721745 # now for the STRING record
722746 if not gotstring:
723747 rc2, _unused_len, data2 = bk.get_record_parts()
724- if rc2 != XL_STRING: raise XLRDError("Expected STRING record; found 0x%04x" % rc2)
748+ if rc2 not in (XL_STRING, XL_STRING_B2):
749+ raise XLRDError("Expected STRING record; found 0x%04x" % rc2)
725750 # if DEBUG: print "STRING: data=%r BIFF=%d cp=%d" % (data2, self.biff_version, bk.encoding)
726751 if self.biff_version < BIFF_FIRST_UNICODE:
727- strg = unpack_string(data2, 0, bk.encoding, lenlen=2)
752+ strg = unpack_string(data2, 0, bk.encoding or bk.derive_encoding, lenlen=1 + int(bv > 20))
728753 else:
729754 strg = unpack_unicode(data2, 0, lenlen=2)
730755 self.put_cell(rowx, colx, XL_CELL_TEXT, strg, xf_index)
731756 # if DEBUG: print "FORMULA strg %r" % strg
732- elif data[6] == '\x01':
757+ elif result_str[0] == '\x01':
733758 # boolean formula result
734- value = ord(data[8])
759+ value = ord(result_str[2])
735760 self.put_cell(rowx, colx, XL_CELL_BOOLEAN, value, xf_index)
736- elif data[6] == '\x02':
761+ elif result_str[0] == '\x02':
737762 # Error in cell
738- value = ord(data[8])
763+ value = ord(result_str[2])
739764 self.put_cell(rowx, colx, XL_CELL_ERROR, value, xf_index)
740- elif data[6] == '\x03':
765+ elif result_str[0] == '\x03':
741766 # empty ... i.e. empty (zero-length) string, NOT an empty cell.
742767 self.put_cell(rowx, colx, XL_CELL_TEXT, u"", xf_index)
743768 else:
744- raise XLRDError("unexpected special case (0x%02x) in FORMULA" % ord(data[6]))
769+ raise XLRDError("unexpected special case (0x%02x) in FORMULA" % ord(result_str[0]))
745770 else:
746771 # it is a number
747- d = local_unpack('<d', data[6:14])[0]
772+ d = local_unpack('<d', result_str)[0]
748773 self_put_number_cell(rowx, colx, d, xf_index)
749774 elif rc == XL_BOOLERR:
750775 rowx, colx, xf_index, value, is_err = local_unpack('<HHHBB', data[:8])
@@ -758,8 +783,8 @@
758783 c = Colinfo()
759784 first_colx, last_colx, c.width, c.xf_index, flags \
760785 = local_unpack("<HHHHH", data[:10])
761- #### Colinfo.width is denominated in 256ths of a character,
762- #### *not* in characters.
786+ #### Colinfo.width is denominated in 256ths of a character,
787+ #### *not* in characters.
763788 if not(0 <= first_colx <= last_colx <= 256):
764789 # Note: 256 instead of 255 is a common mistake.
765790 # We silently ignore the non-existing 257th column in that case.
@@ -853,7 +878,16 @@
853878 eof_found = 1
854879 break
855880 elif rc == XL_OBJ:
856- bk.handle_obj(data)
881+ # handle SHEET-level objects; note there's a separate Book.handle_obj
882+ self.handle_obj(data)
883+ elif rc == XL_MSO_DRAWING:
884+ self.handle_msodrawingetc(rc, data_len, data)
885+ elif rc == XL_TXO:
886+ self.handle_txo(data)
887+ elif rc == XL_NOTE:
888+ self.handle_note(data)
889+ elif rc == XL_FEAT11:
890+ self.handle_feat11(data)
857891 elif rc in bofcodes: ##### EMBEDDED BOF #####
858892 version, boftype = local_unpack('<HH', data[0:4])
859893 if boftype != 0x20: # embedded chart
@@ -1027,7 +1061,7 @@
10271061 # 9 0200H 0 = Sheet not selected 1 = Sheet selected (BIFF5-BIFF8)
10281062 # 10 0400H 0 = Sheet not visible 1 = Sheet visible (BIFF5-BIFF8)
10291063 # 11 0800H 0 = Show in normal view 1 = Show in page break preview (BIFF8)
1030- # The freeze flag specifies, if a following PANE record (6.71) describes unfrozen or frozen panes.
1064+ # The freeze flag specifies, if a following PANE record (6.71) describes unfrozen or frozen panes.
10311065 for attr, _unused_defval in _WINDOW2_options:
10321066 setattr(self, attr, options & 1)
10331067 options >>= 1
@@ -1036,16 +1070,18 @@
10361070 #### all of the following are for BIFF <= 4W
10371071 elif bv <= 45:
10381072 if rc == XL_FORMAT or rc == XL_FORMAT2:
1039- bk.handle_format(data)
1073+ bk.handle_format(data, rc)
10401074 elif rc == XL_FONT or rc == XL_FONT_B3B4:
10411075 bk.handle_font(data)
10421076 elif rc == XL_STYLE:
1077+ if not self.book._xf_epilogue_done:
1078+ self.book.xf_epilogue()
10431079 bk.handle_style(data)
10441080 elif rc == XL_PALETTE:
10451081 bk.handle_palette(data)
10461082 elif rc == XL_BUILTINFMTCOUNT:
10471083 bk.handle_builtinfmtcount(data)
1048- elif rc == XL_XF4 or rc == XL_XF3: #### N.B. not XL_XF
1084+ elif rc == XL_XF4 or rc == XL_XF3 or rc == XL_XF2: #### N.B. not XL_XF
10491085 bk.handle_xf(data)
10501086 elif rc == XL_DATEMODE:
10511087 bk.handle_datemode(data)
@@ -1055,6 +1091,115 @@
10551091 bk.handle_filepass(data)
10561092 elif rc == XL_WRITEACCESS:
10571093 bk.handle_writeaccess(data)
1094+ elif rc == XL_IXFE:
1095+ self._ixfe = local_unpack('<H', data)[0]
1096+ elif rc == XL_NUMBER_B2:
1097+ rowx, colx, cell_attr, d = local_unpack('<HH3sd', data)
1098+ self_put_number_cell(rowx, colx, d, self.fixed_BIFF2_xfindex(cell_attr, rowx, colx))
1099+ elif rc == XL_INTEGER:
1100+ rowx, colx, cell_attr, d = local_unpack('<HH3sH', data)
1101+ self_put_number_cell(rowx, colx, float(d), self.fixed_BIFF2_xfindex(cell_attr, rowx, colx))
1102+ elif rc == XL_LABEL_B2:
1103+ rowx, colx, cell_attr = local_unpack('<HH3s', data[0:7])
1104+ strg = unpack_string(data, 7, bk.encoding or bk.derive_encoding(), lenlen=1)
1105+ self_put_cell(rowx, colx, XL_CELL_TEXT, strg, self.fixed_BIFF2_xfindex(cell_attr, rowx, colx))
1106+ elif rc == XL_BOOLERR_B2:
1107+ rowx, colx, cell_attr, value, is_err = local_unpack('<HH3sBB', data)
1108+ cellty = (XL_CELL_BOOLEAN, XL_CELL_ERROR)[is_err]
1109+ # if DEBUG: print "XL_BOOLERR_B2", rowx, colx, cell_attr, value, is_err
1110+ self.put_cell(rowx, colx, cellty, value, self.fixed_BIFF2_xfindex(cell_attr, rowx, colx))
1111+ elif rc == XL_BLANK_B2:
1112+ if not fmt_info: continue
1113+ rowx, colx, cell_attr = local_unpack('<HH3s', data[:7])
1114+ self_put_blank_cell(rowx, colx, self.fixed_BIFF2_xfindex(cell_attr, rowx, colx))
1115+ elif rc == XL_EFONT:
1116+ bk.handle_efont(data)
1117+ elif rc == XL_ROW_B2:
1118+ if not fmt_info: continue
1119+ rowx, bits1, has_defaults = local_unpack('<H4xH2xB', data[0:11])
1120+ if not(0 <= rowx < self.utter_max_rows):
1121+ print >> self.logfile, \
1122+ "*** NOTE: ROW_B2 record has row index %d; " \
1123+ "should have 0 <= rowx < %d -- record ignored!" \
1124+ % (rowx, self.utter_max_rows)
1125+ continue
1126+ r = Rowinfo()
1127+ r.height = bits1 & 0x7fff
1128+ r.has_default_height = (bits1 >> 15) & 1
1129+ r.outline_level = 0
1130+ r.outline_group_starts_ends = 0
1131+ r.hidden = 0
1132+ r.height_mismatch = 0
1133+ r.has_default_xf_index = has_defaults & 1
1134+ r.additional_space_above = 0
1135+ r.additional_space_below = 0
1136+ if not r.has_default_xf_index:
1137+ r.xf_index = -1
1138+ elif data_len == 18:
1139+ # Seems the XF index in the cell_attr is dodgy
1140+ xfx = local_unpack('<H', data[16:18])[0]
1141+ r.xf_index = self.fixed_BIFF2_xfindex(cell_attr=None, rowx=rowx, colx=-1, true_xfx=xfx)
1142+ else:
1143+ cell_attr = data[13:16]
1144+ r.xf_index = self.fixed_BIFF2_xfindex(cell_attr, rowx, colx=-1)
1145+ self.rowinfo_map[rowx] = r
1146+ if 0 and r.xf_index > -1:
1147+ fprintf(self.logfile,
1148+ "**ROW %d %d %d\n",
1149+ self.number, rowx, r.xf_index)
1150+ if blah_rows:
1151+ print >> self.logfile, 'ROW_B2', rowx, bits1, has_defaults
1152+ r.dump(self.logfile,
1153+ header="--- sh #%d, rowx=%d ---" % (self.number, rowx))
1154+ elif rc == XL_COLWIDTH: # BIFF2 only
1155+ if not fmt_info: continue
1156+ first_colx, last_colx, width\
1157+ = local_unpack("<BBH", data[:4])
1158+ if not(first_colx <= last_colx):
1159+ print >> self.logfile, \
1160+ "*** NOTE: COLWIDTH record has first col index %d, last %d; " \
1161+ "should have first <= last -- record ignored!" \
1162+ % (first_colx, last_colx)
1163+ continue
1164+ for colx in xrange(first_colx, last_colx+1):
1165+ if self.colinfo_map.has_key(colx):
1166+ c = self.colinfo_map[colx]
1167+ else:
1168+ c = Colinfo()
1169+ self.colinfo_map[colx] = c
1170+ c.width = width
1171+ if blah:
1172+ fprintf(
1173+ self.logfile,
1174+ "COLWIDTH sheet #%d cols %d-%d: wid=%d\n",
1175+ self.number, first_colx, last_colx, width
1176+ )
1177+ elif rc == XL_COLUMNDEFAULT: # BIFF2 only
1178+ if not fmt_info: continue
1179+ first_colx, last_colx = local_unpack("<HH", data[:4])
1180+ #### Warning OOo docs wrong; first_colx <= colx < last_colx
1181+ if blah:
1182+ fprintf(
1183+ self.logfile,
1184+ "COLUMNDEFAULT sheet #%d cols in range(%d, %d)\n",
1185+ self.number, first_colx, last_colx
1186+ )
1187+ if not(0 <= first_colx < last_colx <= 256):
1188+ print >> self.logfile, \
1189+ "*** NOTE: COLUMNDEFAULT record has first col index %d, last %d; " \
1190+ "should have 0 <= first < last <= 256" \
1191+ % (first_colx, last_colx)
1192+ last_colx = min(last_colx, 256)
1193+ for colx in xrange(first_colx, last_colx):
1194+ offset = 4 + 3 * (colx - first_colx)
1195+ cell_attr = data[offset:offset+3]
1196+ xf_index = self.fixed_BIFF2_xfindex(cell_attr, rowx=-1, colx=colx)
1197+ if self.colinfo_map.has_key(colx):
1198+ c = self.colinfo_map[colx]
1199+ else:
1200+ c = Colinfo()
1201+ self.colinfo_map[colx] = c
1202+ c.xf_index = xf_index
10581203 else:
10591204 # if DEBUG: print "SHEET.READ: Unhandled record type %02x %d bytes %r" % (rc, data_len, data)
10601205 pass
@@ -1062,9 +1207,110 @@
10621207 raise XLRDError("Sheet %d (%r) missing EOF record" \
10631208 % (self.number, self.name))
10641209 self.tidy_dimensions()
1065- bk.position(oldpos)
1210+ bk._position = oldpos
10661211 return 1
10671212
1213+ def fixed_BIFF2_xfindex(self, cell_attr, rowx, colx, true_xfx=None):
1214+ DEBUG = 0
1215+ blah = DEBUG or self.verbosity >= 2
1216+ if self.biff_version == 21:
1217+ if self._xf_index_to_xl_type_map:
1218+ if true_xfx is not None:
1219+ xfx = true_xfx
1220+ else:
1221+ xfx = ord(cell_attr[0]) & 0x3F
1222+ if xfx == 0x3F:
1223+ if self._ixfe is None:
1224+ raise XLRDError("BIFF2 cell record has XF index 63 but no preceding IXFE record.")
1225+ xfx = self._ixfe
1226+ # OOo docs are capable of interpretation that each
1227+ # cell record is preceded immediately by its own IXFE record.
1228+ # Empirical evidence is that (sensibly) an IXFE record applies to all
1229+ # following cell records until another IXFE comes along.
1230+ return xfx
1231+ # Have either Excel 2.0, or broken 2.1 w/o XF records -- same effect.
1232+ self.biff_version = self.book.biff_version = 20
1233+ #### check that XF slot in cell_attr is zero
1234+ xfx_slot = ord(cell_attr[0]) & 0x3F
1235+ assert xfx_slot == 0
1236+ xfx = self._cell_attr_to_xfx.get(cell_attr)
1237+ if xfx is not None:
1238+ return xfx
1239+ if blah:
1240+ fprintf(self.logfile, "New cell_attr %r at (%r, %r)\n", cell_attr, rowx, colx)
1241+ book = self.book
1242+ xf = self.fake_XF_from_BIFF20_cell_attr(cell_attr)
1243+ xfx = len(book.xf_list)
1244+ xf.xf_index = xfx
1245+ book.xf_list.append(xf)
1246+ if blah:
1247+ xf.dump(self.logfile, header="=== Faked XF %d ===" % xfx, footer="======")
1248+ if not book.format_map.has_key(xf.format_key):
1249+ msg = "ERROR *** XF[%d] unknown format key (%d, 0x%04x)\n"
1250+ fprintf(self.logfile, msg,
1251+ xf.xf_index, xf.format_key, xf.format_key)
1252+ fmt = Format(xf.format_key, FUN, u"General")
1253+ book.format_map[xf.format_key] = fmt
1254+ while len(book.format_list) <= xf.format_key:
1255+ book.format_list.append(fmt)
1256+ cellty_from_fmtty = {
1257+ FNU: XL_CELL_NUMBER,
1258+ FUN: XL_CELL_NUMBER,
1259+ FGE: XL_CELL_NUMBER,
1260+ FDT: XL_CELL_DATE,
1261+ FTX: XL_CELL_NUMBER, # Yes, a number can be formatted as text.
1262+ }
1263+ fmt = book.format_map[xf.format_key]
1264+ cellty = cellty_from_fmtty[fmt.type]
1265+ self._xf_index_to_xl_type_map[xf.xf_index] = cellty
1266+ self._cell_attr_to_xfx[cell_attr] = xfx
1267+ return xfx
1268+
1269+ def fake_XF_from_BIFF20_cell_attr(self, cell_attr):
1270+ from formatting import XF, XFAlignment, XFBorder, XFBackground, XFProtection
1271+ xf = XF()
1272+ xf.alignment = XFAlignment()
1273+ xf.alignment.indent_level = 0
1274+ xf.alignment.shrink_to_fit = 0
1275+ xf.alignment.text_direction = 0
1276+ xf.border = XFBorder()
1277+ xf.border.diag_up = 0
1278+ xf.border.diag_down = 0
1279+ xf.border.diag_colour_index = 0
1280+ xf.border.diag_line_style = 0 # no line
1281+ xf.background = XFBackground()
1282+ xf.protection = XFProtection()
1283+ (prot_bits, font_and_format, halign_etc) = unpack('<BBB', cell_attr)
1284+ xf.format_key = font_and_format & 0x3F
1285+ xf.font_index = (font_and_format & 0xC0) >> 6
1286+ upkbits(xf.protection, prot_bits, (
1287+ (6, 0x40, 'cell_locked'),
1288+ (7, 0x80, 'formula_hidden'),
1289+ ))
1290+ xf.alignment.hor_align = halign_etc & 0x07
1291+ for mask, side in ((0x08, 'left'), (0x10, 'right'), (0x20, 'top'), (0x40, 'bottom')):
1292+ if halign_etc & mask:
1293+ colour_index, line_style = 8, 1 # black, thin
1294+ else:
1295+ colour_index, line_style = 0, 0 # none, none
1296+ setattr(xf.border, side + '_colour_index', colour_index)
1297+ setattr(xf.border, side + '_line_style', line_style)
1298+ bg = xf.background
1299+ if halign_etc & 0x80:
1300+ bg.fill_pattern = 17
1301+ else:
1302+ bg.fill_pattern = 0
1303+ bg.background_colour_index = 9 # white
1304+ bg.pattern_colour_index = 8 # black
1305+ xf.parent_style_index = 0 # ???????????
1306+ xf.alignment.vert_align = 2 # bottom
1307+ xf.alignment.rotation = 0
1308+ for attr_stem in \
1309+ "format font alignment border background protection".split():
1310+ attr = "_" + attr_stem + "_flag"
1311+ setattr(xf, attr, 1)
1312+ return xf
1313+
10681314 def req_fmt_info(self):
10691315 if not self.formatting_info:
10701316 raise XLRDError("Feature requires open_workbook(..., formatting_info=True)")
@@ -1077,9 +1323,9 @@
10771323 # Note that it is possible to find out the width that will be used to display
10781324 # columns with no cell information e.g. column IV (colx=255).
10791325 # @return The column width that will be used for displaying
1080- # the given column by Excel, in units of 1/256th of the width of a
1326+ # the given column by Excel, in units of 1/256th of the width of a
10811327 # standard character (the digit zero in the first font).
1082-
1328+
10831329 def computed_column_width(self, colx):
10841330 self.req_fmt_info()
10851331 if self.biff_version >= 80:
@@ -1104,9 +1350,201 @@
11041350 if self.defcolwidth is not None:
11051351 return self.defcolwidth * 256
11061352 return 8 * 256 # 8 is what Excel puts in a DEFCOLWIDTH record
1107-
1108-
11091353
1354+ def handle_msodrawingetc(self, recid, data_len, data):
1355+ if not OBJ_MSO_DEBUG:
1356+ return
1357+ DEBUG = 1
1358+ if self.biff_version < 80:
1359+ return
1360+ o = MSODrawing()
1361+ pos = 0
1362+ while pos < data_len:
1363+ tmp, fbt, cb = unpack('<HHI', data[pos:pos+8])
1364+ ver = tmp & 0xF
1365+ inst = (tmp >> 4) & 0xFFF
1366+ if ver == 0xF:
1367+ ndb = 0 # container
1368+ else:
1369+ ndb = cb
1370+ if DEBUG:
1371+ hex_char_dump(data, pos, ndb + 8, base=0, fout=self.logfile)
1372+ fprintf(self.logfile,
1373+ "fbt:0x%04X inst:%d ver:0x%X cb:%d (0x%04X)\n",
1374+ fbt, inst, ver, cb, cb)
1375+ if fbt == 0xF010: # Client Anchor
1376+ assert ndb == 18
1377+ (o.anchor_unk,
1378+ o.anchor_colx_lo, o.anchor_rowx_lo,
1379+ o.anchor_colx_hi, o.anchor_rowx_hi) = unpack('<Hiiii', data[pos+8:pos+8+ndb])
1380+ elif fbt == 0xF011: # Client Data
1381+ # must be followed by an OBJ record
1382+ assert cb == 0
1383+ assert pos + 8 == data_len
1384+ else:
1385+ pass
1386+ pos += ndb + 8
1387+ else:
1388+ # didn't break out of while loop
1389+ assert pos == data_len
1390+ if DEBUG:
1391+ o.dump(self.logfile, header="=== MSODrawing ===", footer= " ")
1392+
1393+
1394+ def handle_obj(self, data):
1395+ if not OBJ_MSO_DEBUG:
1396+ return
1397+ DEBUG = 1
1398+ if self.biff_version < 80:
1399+ return
1400+ o = MSObj()
1401+ data_len = len(data)
1402+ pos = 0
1403+ if DEBUG:
1404+ fprintf(self.logfile, "... OBJ record ...\n")
1405+ while pos < data_len:
1406+ ft, cb = unpack('<HH', data[pos:pos+4])
1407+ if DEBUG:
1408+ hex_char_dump(data, pos, cb, base=0, fout=self.logfile)
1409+ if ft == 0x15: # ftCmo ... s/b first
1410+ assert pos == 0
1411+ o.type, o.id, option_flags = unpack('<HHH', data[pos+4:pos+10])
1412+ upkbits(o, option_flags, (
1413+ ( 0, 0x0001, 'locked'),
1414+ ( 4, 0x0010, 'printable'),
1415+ ( 8, 0x0100, 'autofilter'), # not documented in Excel 97 dev kit
1416+ ( 9, 0x0200, 'scrollbar_flag'), # not documented in Excel 97 dev kit
1417+ (13, 0x2000, 'autofill'),
1418+ (14, 0x4000, 'autoline'),
1419+ ))
1420+ elif ft == 0x00:
1421+ assert cb == 0
1422+ assert pos + 4 == data_len
1423+ elif ft == 0x0C: # Scrollbar
1424+ values = unpack('<5H', data[pos+8:pos+18])
1425+ for value, tag in zip(values, ('value', 'min', 'max', 'inc', 'page')):
1426+ setattr(o, 'scrollbar_' + tag, value)
1427+ elif ft == 0x0D: # "Notes structure" [used for cell comments]
1428+ pass ############## not documented in Excel 97 dev kit
1429+ elif ft == 0x13: # list box data
1430+ if o.autofilter: # non standard exit. NOT documented
1431+ break
1432+ else:
1433+ pass
1434+ pos += cb + 4
1435+ else:
1436+ # didn't break out of while loop
1437+ assert pos == data_len
1438+ if DEBUG:
1439+ o.dump(self.logfile, header="=== MSOBj ===", footer= " ")
1440+
1441+ def handle_note(self, data):
1442+ if not OBJ_MSO_DEBUG:
1443+ return
1444+ DEBUG = 1
1445+ if self.biff_version < 80:
1446+ return
1447+ if DEBUG:
1448+ fprintf(self.logfile, '... NOTE record ...\n')
1449+ hex_char_dump(data, 0, len(data), base=0, fout=self.logfile)
1450+ o = MSNote()
1451+ data_len = len(data)
1452+ o.rowx, o.colx, option_flags, o.object_id = unpack('<4H', data[:8])
1453+ o.show = (option_flags >> 1) & 1
1454+ # Docs say NULL [sic] bytes padding between string count and string data
1455+ # to ensure that string is word-aligned. Appears to be nonsense.
1456+ # There also seems to be a random(?) byte after the string (not counted in the
1457+ # string length.
1458+ o.original_author, endpos = unpack_unicode_update_pos(data, 8, lenlen=2)
1459+ assert endpos == data_len - 1
1460+ o.last_byte = data[-1]
1461+ if DEBUG:
1462+ o.dump(self.logfile, header="=== MSNote ===", footer= " ")
1463+
1464+ def handle_txo(self, data):
1465+ if not OBJ_MSO_DEBUG:
1466+ return
1467+ DEBUG = 1
1468+ if self.biff_version < 80:
1469+ return
1470+ o = MSTxo()
1471+ data_len = len(data)
1472+ option_flags, o.rot, cchText, cbRuns = unpack('<HH6xHH4x', data)
1473+ upkbits(o, option_flags, (
1474+ (3, 0x000E, 'horz_align'),
1475+ (6, 0x0070, 'vert_align'),
1476+ (9, 0x0200, 'lock_text'),
1477+ ))
1478+ rc2, data2_len, data2 = self.book.get_record_parts()
1479+ assert rc2 == XL_CONTINUE
1480+ o.text, endpos = unpack_unicode_update_pos(data2, 0, known_len=cchText)
1481+ assert endpos == data2_len
1482+ rc3, data3_len, data3 = self.book.get_record_parts()
1483+ assert rc3 == XL_CONTINUE
1484+ # ignore the formatting runs for the moment
1485+ if DEBUG:
1486+ o.dump(self.logfile, header="=== MSTxo ===", footer= " ")
1487+
1488+ def handle_feat11(self, data):
1489+ if not OBJ_MSO_DEBUG:
1490+ return
1491+ # rt: Record type; this matches the BIFF rt in the first two bytes of the record; =0872h
1492+ # grbitFrt: FRT cell reference flag (see table below for details)
1493+ # Ref0: Range reference to a worksheet cell region if grbitFrt=1 (bitFrtRef). Otherwise blank.
1494+ # isf: Shared feature type index =5 for Table
1495+ # fHdr: =0 since this is for feat not feat header
1496+ # reserved0: Reserved for future use =0 for Table
1497+ # cref: Count of ref ranges this feature is on
1498+ # cbFeatData: Count of byte for the current feature data.
1499+ # reserved1: =0 currently not used
1500+ # Ref1: Repeat of Ref0. UNDOCUMENTED
1501+ rt, grbitFrt, Ref0, isf, fHdr, reserved0, cref, cbFeatData, reserved1, Ref1 = unpack('<HH8sHBiHiH8s', data[0:35])
1502+ assert reserved0 == 0
1503+ assert reserved1 == 0
1504+ assert isf == 5
1505+ assert rt == 0x872
1506+ assert fHdr == 0
1507+ assert Ref1 == Ref0
1508+ print "FEAT11: grbitFrt=%d Ref0=%r cref=%d cbFeatData=%d" % (grbitFrt, Ref0, cref, cbFeatData)
1509+ # lt: Table data source type:
1510+ # =0 for Excel Worksheet Table =1 for read-write SharePoint linked List
1511+ # =2 for XML mapper Table =3 for Query Table
1512+ # idList: The ID of the Table (unique per worksheet)
1513+ # crwHeader: How many header/title rows the Table has at the top
1514+ # crwTotals: How many total rows the Table has at the bottom
1515+ # idFieldNext: Next id to try when assigning a unique id to a new field
1516+ # cbFSData: The size of the Fixed Data portion of the Table data structure.
1517+ # rupBuild: the rupBuild that generated the record
1518+ # unusedShort: UNUSED short that can be used later. The value is reserved during round-tripping.
1519+ # listFlags: Collection of bit flags: (see listFlags' bit setting table below for detail.)
1520+ # lPosStmCache: Table data stream position of cached data
1521+ # cbStmCache: Count of bytes of cached data
1522+ # cchStmCache: Count of characters of uncompressed cached data in the stream
1523+ # lem: Table edit mode (see List (Table) Editing Mode (lem) setting table below for details.)
1524+ # rgbHashParam: Hash value for SharePoint Table
1525+ # cchName: Count of characters in the Table name string rgbName
1526+ (lt, idList, crwHeader, crwTotals, idFieldNext, cbFSData,
1527+ rupBuild, unusedShort, listFlags, lPosStmCache, cbStmCache,
1528+ cchStmCache, lem, rgbHashParam, cchName) = unpack('<iiiiiiHHiiiii16sH', data[35:35+66])
1529+ print "lt=%d idList=%d crwHeader=%d crwTotals=%d idFieldNext=%d cbFSData=%d\n"\
1530+ "rupBuild=%d unusedShort=%d listFlags=%04X lPosStmCache=%d cbStmCache=%d\n"\
1531+ "cchStmCache=%d lem=%d rgbHashParam=%r cchName=%d" % (
1532+ lt, idList, crwHeader, crwTotals, idFieldNext, cbFSData,
1533+ rupBuild, unusedShort,listFlags, lPosStmCache, cbStmCache,
1534+ cchStmCache, lem, rgbHashParam, cchName)
1535+
1536+class MSODrawing(BaseObject):
1537+ pass
1538+
1539+class MSObj(BaseObject):
1540+ pass
1541+
1542+class MSTxo(BaseObject):
1543+ pass
1544+
1545+class MSNote(BaseObject):
1546+ pass
1547+
11101548 # === helpers ===
11111549
11121550 def unpack_RK(rk_str):
@@ -1142,6 +1580,7 @@
11421580 XL_CELL_DATE: 'xldate',
11431581 XL_CELL_BOOLEAN: 'bool',
11441582 XL_CELL_ERROR: 'error',
1583+ XL_CELL_BLANK: 'blank',
11451584 }
11461585
11471586 ##
--- branches/tl3_0/python-lib/xlrd/xlrd/formatting.py (revision 43)
+++ branches/tl3_0/python-lib/xlrd/xlrd/formatting.py (revision 44)
@@ -3,7 +3,8 @@
33 ##
44 # Module for formatting information.
55 #
6-# <p>Copyright ゥ 2005-2006 Stephen John Machin, Lingfo Pty Ltd</p>
6+# <p>Copyright ゥ 2005-2008 Stephen John Machin, Lingfo Pty Ltd</p>
7+# <p>Copyright ゥ 2005-2009 Stephen John Machin, Lingfo Pty Ltd</p>
78 # <p>This module is part of the xlrd package, which is released under
89 # a BSD-style licence.</p>
910 ##
@@ -10,12 +11,25 @@
1011
1112 # No part of the content of this file was derived from the works of David Giffin.
1213
14+# 2009-05-31 SJM Fixed problem with non-zero reserved bits in some STYLE records in Mac Excel files
15+# 2008-08-03 SJM Ignore PALETTE record when Book.formatting_info is false
16+# 2008-08-03 SJM Tolerate up to 4 bytes trailing junk on PALETTE record
17+# 2008-05-10 SJM Do some XF checks only when Book.formatting_info is true
18+# 2008-02-08 SJM Preparation for Excel 2.0 support
19+# 2008-02-03 SJM Another tweak to is_date_format_string()
20+# 2007-12-04 SJM Added support for Excel 2.x (BIFF2) files.
21+# 2007-10-13 SJM Warning: style XF whose parent XF index != 0xFFF
22+# 2007-09-08 SJM Work around corrupt STYLE record
23+# 2007-07-11 SJM Allow for BIFF2/3-style FORMAT record in BIFF4/8 file
24+
1325 DEBUG = 0
14-import copy
26+import copy, re
1527 from timemachine import *
1628 from biffh import BaseObject, unpack_unicode, unpack_string, \
1729 upkbits, upkbitsL, fprintf, \
18- FUN, FDT, FNU, FGE, FTX, XL_CELL_NUMBER, XL_CELL_DATE
30+ FUN, FDT, FNU, FGE, FTX, XL_CELL_NUMBER, XL_CELL_DATE, \
31+ XL_FORMAT, XL_FORMAT2, \
32+ XLRDError
1933 from struct import unpack
2034
2135 excel_default_palette_b5 = (
@@ -35,7 +49,7 @@
3549 (153, 51, 0), (153, 51, 102), ( 51, 51, 153), ( 51, 51, 51),
3650 )
3751
38-excel_default_palette_b3 = excel_default_palette_b5[:16]
52+excel_default_palette_b2 = excel_default_palette_b5[:16]
3953
4054 # Following two tables borrowed from Gnumeric 1.4 source.
4155 excel_default_palette_b5_gnumeric_14 = (
@@ -76,9 +90,11 @@
7690 80: excel_default_palette_b8,
7791 70: excel_default_palette_b5,
7892 50: excel_default_palette_b5,
79- 45: excel_default_palette_b3,
80- 40: excel_default_palette_b3,
81- 30: excel_default_palette_b3,
93+ 45: excel_default_palette_b2,
94+ 40: excel_default_palette_b2,
95+ 30: excel_default_palette_b2,
96+ 21: excel_default_palette_b2,
97+ 20: excel_default_palette_b2,
8298 }
8399
84100 """
@@ -109,6 +125,8 @@
109125 def initialise_colour_map(book):
110126 book.colour_map = {}
111127 book.colour_indexes_used = {}
128+ if not book.formatting_info:
129+ return
112130 # Add the 8 invariant colours
113131 for i in xrange(8):
114132 book.colour_map[i] = excel_default_palette_b8[i]
@@ -127,7 +145,7 @@
127145 0x7FFF, # 32767, system window text colour for fonts
128146 ):
129147 book.colour_map[ci] = None
130-
148+
131149 def nearest_colour_index(colour_map, rgb, debug=0):
132150 # General purpose function. Uses Euclidean distance.
133151 # So far used only for pre-BIFF8 WINDOW2 record.
@@ -242,7 +260,14 @@
242260
243261 # No methods ...
244262
263+def handle_efont(book, data): # BIFF2 only
264+ if not book.formatting_info:
265+ return
266+ book.font_list[-1].colour_index = unpack('<H', data)[0]
267+
245268 def handle_font(book, data):
269+ if not book.formatting_info:
270+ return
246271 if not book.encoding:
247272 book.derive_encoding()
248273 blah = DEBUG or book.verbosity >= 2
@@ -273,7 +298,7 @@
273298 f.name = unpack_unicode(data, 14, lenlen=1)
274299 else:
275300 f.name = unpack_string(data, 14, book.encoding, lenlen=1)
276- else:
301+ elif bv >= 30:
277302 f.height, option_flags, f.colour_index = unpack('<HHH', data[0:6])
278303 f.bold = option_flags & 1
279304 f.italic = (option_flags & 2) >> 1
@@ -288,6 +313,22 @@
288313 f.underline_type = f.underlined # None or Single
289314 f.family = 0 # Unknown / don't care
290315 f.character_set = 1 # System default (0 means "ANSI Latin")
316+ else: # BIFF2
317+ f.height, option_flags = unpack('<HH', data[0:4])
318+ f.colour_index = 0x7FFF # "system window text colour"
319+ f.bold = option_flags & 1
320+ f.italic = (option_flags & 2) >> 1
321+ f.underlined = (option_flags & 4) >> 2
322+ f.struck_out = (option_flags & 8) >> 3
323+ f.outline = 0
324+ f.shadow = 0
325+ f.name = unpack_string(data, 4, book.encoding, lenlen=1)
326+ # Now cook up the remaining attributes ...
327+ f.weight = [400, 700][f.bold]
328+ f.escapement_type = 0 # None
329+ f.underline_type = f.underlined # None or Single
330+ f.family = 0 # Unknown / don't care
331+ f.character_set = 1 # System default (0 means "ANSI Latin")
291332 if blah:
292333 f.dump(
293334 book.logfile,
@@ -410,6 +451,8 @@
410451 u'@' :1,
411452 }
412453
454+fmt_bracketed_sub = re.compile(r'\[[^]]*\]').sub
455+
413456 # Boolean format strings (actual cases)
414457 # u'"Yes";"Yes";"No"'
415458 # u'"True";"True";"False"'
@@ -445,8 +488,9 @@
445488 # Ignore char after backslash, underscore or asterisk
446489 state = 0
447490 assert 0 <= state <= 2
448- # if book.verbosity >= 3:
449- # print "is_date_format_string: reduced format is %r" % s
491+ if book.verbosity >= 4:
492+ print "is_date_format_string: reduced format is %r" % s
493+ s = fmt_bracketed_sub('', s)
450494 if non_date_formats.has_key(s):
451495 return False
452496 state = 0
@@ -454,23 +498,12 @@
454498 got_sep = 0
455499 date_count = num_count = 0
456500 for c in s:
457- if state == 0:
458- if c == u'[':
459- state = 2
460- elif date_char_dict.has_key(c):
461- date_count += date_char_dict[c]
462- elif num_char_dict.has_key(c):
463- num_count += num_char_dict[c]
464- elif c == separator:
465- got_sep = 1
466- elif state == 2:
467- if c == u']':
468- state = 0
469- if state != 0:
470- fprintf(book.logfile,
471- "WARNING *** is_date_format_string: "
472- "parse failed: fmt=%r s=%r state=%d\n",
473- fmt, s, state)
501+ if date_char_dict.has_key(c):
502+ date_count += date_char_dict[c]
503+ elif num_char_dict.has_key(c):
504+ num_count += num_char_dict[c]
505+ elif c == separator:
506+ got_sep = 1
474507 # print num_count, date_count, repr(fmt)
475508 if date_count and not num_count:
476509 return True
@@ -486,9 +519,11 @@
486519 fmt)
487520 return date_count > num_count
488521
489-def handle_format(self, data):
522+def handle_format(self, data, rectype=XL_FORMAT):
490523 DEBUG = 0
491524 bv = self.biff_version
525+ if rectype == XL_FORMAT2:
526+ bv = min(bv, 30)
492527 if not self.encoding:
493528 self.derive_encoding()
494529 strpos = 2
@@ -537,6 +572,8 @@
537572 # =============================================================================
538573
539574 def handle_palette(book, data):
575+ if not book.formatting_info:
576+ return
540577 blah = DEBUG or book.verbosity >= 2
541578 n_colours, = unpack('<H', data[:2])
542579 expected_n_colours = (16, 56)[book.biff_version >= 50]
@@ -549,7 +586,12 @@
549586 fprintf(book.logfile,
550587 "PALETTE record with %d colours\n", n_colours)
551588 fmt = '<xx%di' % n_colours # use i to avoid long integers
552- colours = unpack(fmt, data)
589+ expected_size = 4 * n_colours + 2
590+ actual_size = len(data)
591+ tolerance = 4
592+ if not expected_size <= actual_size <= expected_size + tolerance:
593+ raise XLRDError('PALETTE record: expected size %d, actual size %d' % (expected_size, actual_size))
594+ colours = unpack(fmt, data[:expected_size])
553595 assert book.palette_record == [] # There should be only 1 PALETTE record
554596 # a colour will be 0xbbggrr
555597 # IOW, red is at the little end
@@ -591,11 +633,20 @@
591633 def handle_style(book, data):
592634 blah = DEBUG or book.verbosity >= 2
593635 bv = book.biff_version
594- xf_index, built_in_id, level = unpack('<HBB', data[:4])
595- if xf_index & 0x8000:
636+ flag_and_xfx, built_in_id, level = unpack('<HBB', data[:4])
637+ xf_index = flag_and_xfx & 0x0fff
638+ if (data == "\0\0\0\0"
639+ and "Normal" not in book.style_name_map):
640+ # Erroneous record (doesn't have built-in bit set).
641+ # Example file supplied by Jeff Bell.
642+ built_in = 1
643+ built_in_id = 0
644+ xf_index = 0
645+ name = "Normal"
646+ level = 255
647+ elif flag_and_xfx & 0x8000:
596648 # built-in style
597649 built_in = 1
598- xf_index &= 0x7fff
599650 name = built_in_style_names[built_in_id]
600651 if 1 <= built_in_id <= 2:
601652 name += str(level + 1)
@@ -605,6 +656,9 @@
605656 name = unpack_unicode(data, 2, lenlen=2)
606657 else:
607658 name = unpack_string(data, 2, book.encoding, lenlen=1)
659+ if blah and not name:
660+ print >> book.logfile, \
661+ "WARNING *** A user-defined style has a zero-length name"
608662 built_in = 0
609663 built_in_id = 0
610664 level = 0
@@ -844,6 +898,41 @@
844898 ))
845899 xf.alignment.vert_align = 2 # bottom
846900 xf.alignment.rotation = 0
901+ elif bv == 21:
902+ #### Warning: incomplete treatment; formatting_info not fully supported.
903+ #### Probably need to offset incoming BIFF2 XF[n] to BIFF8-like XF[n+16],
904+ #### and create XF[0:16] like the standard ones in BIFF8
905+ #### *AND* add 16 to all XF references in cell records :-(
906+ (xf.font_index, format_etc, halign_etc) = unpack('<BxBB', data)
907+ xf.format_key = format_etc & 0x3F
908+ upkbits(xf.protection, format_etc, (
909+ (6, 0x40, 'cell_locked'),
910+ (7, 0x80, 'formula_hidden'),
911+ ))
912+ upkbits(xf.alignment, halign_etc, (
913+ (0, 0x07, 'hor_align'),
914+ ))
915+ for mask, side in ((0x08, 'left'), (0x10, 'right'), (0x20, 'top'), (0x40, 'bottom')):
916+ if halign_etc & mask:
917+ colour_index, line_style = 8, 1 # black, thin
918+ else:
919+ colour_index, line_style = 0, 0 # none, none
920+ setattr(xf.border, side + '_colour_index', colour_index)
921+ setattr(xf.border, side + '_line_style', line_style)
922+ bg = xf.background
923+ if halign_etc & 0x80:
924+ bg.fill_pattern = 17
925+ else:
926+ bg.fill_pattern = 0
927+ bg.background_colour_index = 9 # white
928+ bg.pattern_colour_index = 8 # black
929+ xf.parent_style_index = 0 # ???????????
930+ xf.alignment.vert_align = 2 # bottom
931+ xf.alignment.rotation = 0
932+ for attr_stem in \
933+ "format font alignment border background protection".split():
934+ attr = "_" + attr_stem + "_flag"
935+ setattr(xf, attr, 1)
847936 else:
848937 raise XLRDError('programmer stuff-up: bv=%d' % bv)
849938
@@ -857,9 +946,11 @@
857946 footer=" ",
858947 )
859948 # Now for some assertions ...
860- if xf.is_style:
861- assert xf.parent_style_index == 0x0FFF
862- check_colour_indexes_in_obj(self, xf, xf.xf_index)
949+ if self.formatting_info:
950+ if xf.is_style and xf.parent_style_index != 0x0FFF:
951+ msg = "WARNING *** XF[%d] is a style XF but parent_style_index is 0x%04x, not 0x0fff\n"
952+ fprintf(self.logfile, msg, xf.xf_index, xf.parent_style_index)
953+ check_colour_indexes_in_obj(self, xf, xf.xf_index)
863954 if not self.format_map.has_key(xf.format_key):
864955 msg = "WARNING *** XF[%d] unknown (raw) format key (%d, 0x%04x)\n"
865956 fprintf(self.logfile, msg,
@@ -872,7 +963,9 @@
872963 num_xfs = len(self.xf_list)
873964 blah = DEBUG or self.verbosity >= 3
874965 blah1 = DEBUG or self.verbosity >= 1
875-
966+ if blah:
967+ fprintf(self.logfile, "xf_epilogue called ...\n")
968+
876969 def check_same(book_arg, xf_arg, parent_arg, attr):
877970 # the _arg caper is to avoid a Warning msg from Python 2.1 :-(
878971 if getattr(xf_arg, attr) != getattr(parent_arg, attr):
@@ -879,8 +972,9 @@
879972 fprintf(book_arg.logfile,
880973 "NOTE !!! XF[%d] parent[%d] %s different\n",
881974 xf_arg.xf_index, parent_arg.xf_index, attr)
882-
883- for xf in self.xf_list:
975+
976+ for xfx in xrange(num_xfs):
977+ xf = self.xf_list[xfx]
884978 if not self.format_map.has_key(xf.format_key):
885979 msg = "ERROR *** XF[%d] unknown format key (%d, 0x%04x)\n"
886980 fprintf(self.logfile, msg,
@@ -897,39 +991,44 @@
897991 cellty = cellty_from_fmtty[fmt.type]
898992 self._xf_index_to_xl_type_map[xf.xf_index] = cellty
899993 # Now for some assertions etc
994+ if not self.formatting_info:
995+ continue
900996 if xf.is_style:
901997 continue
902- assert 0 <= xf.parent_style_index < num_xfs
903- assert xf.parent_style_index != xf.xf_index
904- assert self.xf_list[xf.parent_style_index].is_style
905- if blah1 and xf.parent_style_index > xf.xf_index:
998+ if not(0 <= xf.parent_style_index < num_xfs):
906999 fprintf(self.logfile,
907- "NOTE !!! XF[%d]: parent_style_index is %d; out of order?\n",
908- xf.xf_index, xf.parent_style_index)
909- parent = self.xf_list[xf.parent_style_index]
910- if not xf._alignment_flag and not parent._alignment_flag:
911- if blah1: check_same(self, xf, parent, 'alignment')
912- if not xf._background_flag and not parent._background_flag:
913- if blah1: check_same(self, xf, parent, 'background')
914- if not xf._border_flag and not parent._border_flag:
915- if blah1: check_same(self, xf, parent, 'border')
916- if not xf._protection_flag and not parent._protection_flag:
917- if blah1: check_same(self, xf, parent, 'protection')
918- if not xf._format_flag and not parent._format_flag:
919- if blah1 and xf.format_key != parent.format_key:
1000+ "WARNING *** XF[%d]: is_style=%d but parent_style_index=%d\n",
1001+ xf.xf_index, xf.is_style, xf.parent_style_index)
1002+ # make it conform
1003+ xf.parent_style_index = 0
1004+ if self.biff_version >= 30:
1005+ assert xf.parent_style_index != xf.xf_index
1006+ assert self.xf_list[xf.parent_style_index].is_style
1007+ if blah1 and xf.parent_style_index > xf.xf_index:
9201008 fprintf(self.logfile,
921- "NOTE !!! XF[%d] fmtk=%d, parent[%d] fmtk=%r\n%r / %r\n",
922- xf.xf_index, xf.format_key, parent.xf_index, parent.format_key,
923- self.format_map[xf.format_key].format_str,
924- self.format_map[parent.format_key].format_str)
925- if not xf._font_flag and not parent._font_flag:
926- if blah1 and xf.font_index != parent.font_index:
927- fprintf(self.logfile,
928- "NOTE !!! XF[%d] fontx=%d, parent[%d] fontx=%r\n",
929- xf.xf_index, xf.font_index, parent.xf_index, parent.font_index)
930- # Following are deprecated, undocumented, and will vanish Real Soon Now.
931- self.raw_xf_list = self.xf_list
932- self.computed_xf_list = self.xf_list
1009+ "NOTE !!! XF[%d]: parent_style_index is %d; out of order?\n",
1010+ xf.xf_index, xf.parent_style_index)
1011+ parent = self.xf_list[xf.parent_style_index]
1012+ if not xf._alignment_flag and not parent._alignment_flag:
1013+ if blah1: check_same(self, xf, parent, 'alignment')
1014+ if not xf._background_flag and not parent._background_flag:
1015+ if blah1: check_same(self, xf, parent, 'background')
1016+ if not xf._border_flag and not parent._border_flag:
1017+ if blah1: check_same(self, xf, parent, 'border')
1018+ if not xf._protection_flag and not parent._protection_flag:
1019+ if blah1: check_same(self, xf, parent, 'protection')
1020+ if not xf._format_flag and not parent._format_flag:
1021+ if blah1 and xf.format_key != parent.format_key:
1022+ fprintf(self.logfile,
1023+ "NOTE !!! XF[%d] fmtk=%d, parent[%d] fmtk=%r\n%r / %r\n",
1024+ xf.xf_index, xf.format_key, parent.xf_index, parent.format_key,
1025+ self.format_map[xf.format_key].format_str,
1026+ self.format_map[parent.format_key].format_str)
1027+ if not xf._font_flag and not parent._font_flag:
1028+ if blah1 and xf.font_index != parent.font_index:
1029+ fprintf(self.logfile,
1030+ "NOTE !!! XF[%d] fontx=%d, parent[%d] fontx=%r\n",
1031+ xf.xf_index, xf.font_index, parent.xf_index, parent.font_index)
9331032
9341033 def initialise_book(book):
9351034 initialise_colour_map(book)
@@ -936,6 +1035,7 @@
9361035 book._xf_epilogue_done = 0
9371036 methods = (
9381037 handle_font,
1038+ handle_efont,
9391039 handle_format,
9401040 is_date_format_string,
9411041 handle_palette,
@@ -953,7 +1053,7 @@
9531053 # <p> An explanations of "colour index" is given in the Formatting
9541054 # section at the start of this document.
9551055 # There are five line style attributes; possible values and the
956-# associated meanings are:
1056+# associated meanings are:
9571057 # 0&nbsp;=&nbsp;No line,
9581058 # 1&nbsp;=&nbsp;Thin,
9591059 # 2&nbsp;=&nbsp;Medium,
@@ -1141,7 +1241,6 @@
11411241 # is the same as the index into format_list, and <i>only</i>
11421242 # if the index is less than 164.
11431243 # </p>
1144-
11451244 format_key = 0
11461245 ##
11471246 # An instance of an XFProtection object.
--- branches/tl3_0/python-lib/xlrd/xlrd/biffh.py (revision 43)
+++ branches/tl3_0/python-lib/xlrd/xlrd/biffh.py (revision 44)
@@ -3,10 +3,15 @@
33 ##
44 # Support module for the xlrd package.
55 #
6-# <p> Portions copyright ゥ 2005-2006 Stephen John Machin, Lingfo Pty Ltd</p>
6+# <p>Portions copyright ゥ 2005-2008 Stephen John Machin, Lingfo Pty Ltd</p>
77 # <p>This module is part of the xlrd package, which is released under a BSD-style licence.</p>
88 ##
99
10+# 2008-02-10 SJM BIFF2 BLANK record
11+# 2008-02-08 SJM Preparation for Excel 2.0 support
12+# 2008-02-02 SJM Added suffixes (_B2, _B2_ONLY, etc) on record names for biff_dump & biff_count
13+# 2007-12-04 SJM Added support for Excel 2.x (BIFF2) files.
14+# 2007-09-08 SJM Avoid crash when zero-length Unicode string missing options byte.
1015 # 2007-04-22 SJM Remove experimental "trimming" facility.
1116
1217 DEBUG = 0
@@ -69,7 +74,9 @@
6974 ) = range(7)
7075
7176 biff_text_from_num = {
72- 20: "2",
77+ 0: "(not BIFF)",
78+ 20: "2.0",
79+ 21: "2.1",
7380 30: "3",
7481 40: "4S",
7582 45: "4W",
@@ -116,13 +123,17 @@
116123 XL_ARRAY = 0x0221
117124 XL_ARRAY2 = 0x0021
118125 XL_BLANK = 0x0201
126+XL_BLANK_B2 = 0x01
119127 XL_BOF = 0x809
120128 XL_BOOLERR = 0x205
129+XL_BOOLERR_B2 = 0x5
121130 XL_BOUNDSHEET = 0x85
122131 XL_BUILTINFMTCOUNT = 0x56
123132 XL_CF = 0x01B1
124133 XL_CODEPAGE = 0x42
125134 XL_COLINFO = 0x7D
135+XL_COLUMNDEFAULT = 0x20 # BIFF2 only
136+XL_COLWIDTH = 0x24 # BIFF2 only
126137 XL_CONDFMT = 0x01B0
127138 XL_CONTINUE = 0x3c
128139 XL_COUNTRY = 0x8C
@@ -131,9 +142,12 @@
131142 XL_DEFCOLWIDTH = 0x55
132143 XL_DIMENSION = 0x200
133144 XL_DIMENSION2 = 0x0
145+XL_EFONT = 0x45
134146 XL_EOF = 0x0a
147+XL_EXTERNNAME = 0x23
135148 XL_EXTERNSHEET = 0x17
136149 XL_EXTSST = 0xff
150+XL_FEAT11 = 0x872
137151 XL_FILEPASS = 0x2f
138152 XL_FONT = 0x31
139153 XL_FONT_B3B4 = 0x231
@@ -144,8 +158,10 @@
144158 XL_FORMULA4 = 0x406
145159 XL_GCW = 0xab
146160 XL_INDEX = 0x20b
161+XL_INTEGER = 0x2 # BIFF2 only
162+XL_IXFE = 0x44 # BIFF2 only
147163 XL_LABEL = 0x204
148-XL_LABEL2 = 0x04
164+XL_LABEL_B2 = 0x04
149165 XL_LABELRANGES = 0x15f
150166 XL_LABELSST = 0xfd
151167 XL_MERGEDCELLS = 0xE5
@@ -157,10 +173,12 @@
157173 XL_NAME = 0x18
158174 XL_NOTE = 0x1c
159175 XL_NUMBER = 0x203
176+XL_NUMBER_B2 = 0x3
160177 XL_OBJ = 0x5D
161178 XL_PALETTE = 0x92
162179 XL_RK = 0x27e
163180 XL_ROW = 0x208
181+XL_ROW_B2 = 0x08
164182 XL_RSTRING = 0xd6
165183 XL_SHEETHDR = 0x8F # BIFF4W only
166184 XL_SHEETSOFFSET = 0x8E # BIFF4W only
@@ -168,6 +186,7 @@
168186 XL_SST = 0xfc
169187 XL_STANDARDWIDTH = 0x99
170188 XL_STRING = 0x207
189+XL_STRING_B2 = 0x7
171190 XL_STYLE = 0x293
172191 XL_SUPBOOK = 0x1AE
173192 XL_TABLEOP = 0x236
@@ -186,6 +205,8 @@
186205 boflen = {0x0809: 8, 0x0409: 6, 0x0209: 6, 0x0009: 4}
187206 bofcodes = (0x0809, 0x0409, 0x0209, 0x0009)
188207
208+XL_FORMULA_OPCODES = (0x0006, 0x0406, 0x0206)
209+
189210 _cell_opcode_list = [
190211 XL_BOOLERR,
191212 XL_FORMULA,
@@ -237,6 +258,10 @@
237258 def unpack_unicode(data, pos, lenlen=2):
238259 "Return unicode_strg"
239260 nchars = unpack('<' + 'BH'[lenlen-1], data[pos:pos+lenlen])[0]
261+ if not nchars:
262+ # Ambiguous whether 0-length string should have an "options" byte.
263+ # Avoid crash if missing.
264+ return u""
240265 pos += lenlen
241266 options = ord(data[pos])
242267 pos += 1
@@ -277,6 +302,9 @@
277302 else:
278303 nchars = unpack('<' + 'BH'[lenlen-1], data[pos:pos+lenlen])[0]
279304 pos += lenlen
305+ if not nchars and not data[pos:]:
306+ # Zero-length string with no options byte
307+ return (u"", pos)
280308 options = ord(data[pos])
281309 pos += 1
282310 phonetic = options & 0x04
@@ -322,18 +350,18 @@
322350 return pos
323351
324352 _brecstrg = """\
325-0000 DIMENSIONS
326-0001 BLANK
327-0002 INTEGER
328-0003 NUMBER
329-0004 LABEL
330-0005 BOOLERR
353+0000 DIMENSIONS_B2
354+0001 BLANK_B2
355+0002 INTEGER_B2_ONLY
356+0003 NUMBER_B2
357+0004 LABEL_B2
358+0005 BOOLERR_B2
331359 0006 FORMULA
332-0007 STRING
333-0008 ROW
334-0009 BOF
360+0007 STRING_B2
361+0008 ROW_B2
362+0009 BOF_B2
335363 000A EOF
336-000B INDEX
364+000B INDEX_B2_ONLY
337365 000C CALCCOUNT
338366 000D CALCMODE
339367 000E PRECISION
@@ -346,20 +374,20 @@
346374 0015 FOOTER
347375 0016 EXTERNCOUNT
348376 0017 EXTERNSHEET
349-0018 NAME
377+0018 NAME_B2,5+
350378 0019 WINDOWPROTECT
351379 001A VERTICALPAGEBREAKS
352380 001B HORIZONTALPAGEBREAKS
353381 001C NOTE
354382 001D SELECTION
355-001E FORMAT
356-001F BUILTINFMTCOUNT
357-0020 COLUMNDEFAULT
358-0021 ARRAY_B2
383+001E FORMAT_B2-3
384+001F BUILTINFMTCOUNT_B2
385+0020 COLUMNDEFAULT_B2_ONLY
386+0021 ARRAY_B2_ONLY
359387 0022 DATEMODE
360388 0023 EXTERNNAME
361-0024 COLWIDTH
362-0025 DEFAULTROWHEIGHT
389+0024 COLWIDTH_B2_ONLY
390+0025 DEFAULTROWHEIGHT_B2_ONLY
363391 0026 LEFTMARGIN
364392 0027 RIGHTMARGIN
365393 0028 TOPMARGIN
@@ -368,21 +396,22 @@
368396 002B PRINTGRIDLINES
369397 002F FILEPASS
370398 0031 FONT
399+0032 FONT2_B2_ONLY
371400 0036 TABLEOP_B2
372-0037 TABLEOP2
401+0037 TABLEOP2_B2
373402 003C CONTINUE
374403 003D WINDOW1
375-003E WINDOW2
404+003E WINDOW2_B2
376405 0040 BACKUP
377406 0041 PANE
378407 0042 CODEPAGE
379408 0043 XF_B2
380-0044 IXFE
381-0045 EFONT
409+0044 IXFE_B2_ONLY
410+0045 EFONT_B2_ONLY
382411 004D PLS
383412 0051 DCONREF
384413 0055 DEFCOLWIDTH
385-0056 BUILTINFMTCOUNT
414+0056 BUILTINFMTCOUNT_B3-4
386415 0059 XCT
387416 005A CRN
388417 005B FILESHARING
@@ -406,8 +435,11 @@
406435 008F SHEETHDR
407436 0090 SORT
408437 0092 PALETTE
438+0099 STANDARDWIDTH
439+009B FILTERMODE
409440 009C FNGROUPCOUNT
410-0099 STANDARDWIDTH
441+009D AUTOFILTERINFO
442+009E AUTOFILTER
411443 00A0 SCL
412444 00A1 SETUP
413445 00AB GCW
@@ -455,10 +487,10 @@
455487 0207 STRING
456488 0208 ROW
457489 0209 BOF
458-020B INDEX
490+020B INDEX_B3+
459491 0218 NAME
460492 0221 ARRAY
461-0223 EXTERNNAME
493+0223 EXTERNNAME_B3-4
462494 0225 DEFAULTROWHEIGHT
463495 0231 FONT_B3B4
464496 0236 TABLEOP
@@ -484,16 +516,20 @@
484516 biff_rec_name_dict[int(_numh, 16)] = _name
485517 del _buff, _name, _brecstrg
486518
487-def hex_char_dump(strg, ofs, dlen, base=0, fout=sys.stdout):
519+def hex_char_dump(strg, ofs, dlen, base=0, fout=sys.stdout, unnumbered=False):
488520 endpos = min(ofs + dlen, len(strg))
489521 pos = ofs
522+ numbered = not unnumbered
523+ num_prefix = ''
490524 while pos < endpos:
491525 endsub = min(pos + 16, endpos)
492526 substrg = strg[pos:endsub]
493527 lensub = endsub - pos
494528 if lensub <= 0 or lensub != len(substrg):
495- print '??? hex_char_dump: ofs=%d dlen=%d base=%d -> endpos=%d pos=%d endsub=%d substrg=%r' \
496- % (ofs, dlen, base, endpos, pos, endsub, substrg)
529+ fprintf(
530+ sys.stdout,
531+ '??? hex_char_dump: ofs=%d dlen=%d base=%d -> endpos=%d pos=%d endsub=%d substrg=%r\n',
532+ ofs, dlen, base, endpos, pos, endsub, substrg)
497533 break
498534 hexd = ''.join(["%02x " % ord(c) for c in substrg])
499535 chard = ''
@@ -503,14 +539,18 @@
503539 elif not (' ' <= c <= '~'):
504540 c = '?'
505541 chard += c
506- print >> fout, "%5d: %-48s %s" % (base+pos-ofs, hexd, chard)
542+ if numbered:
543+ num_prefix = "%5d: " % (base+pos-ofs)
544+ fprintf(fout, "%s %-48s %s\n", num_prefix, hexd, chard)
507545 pos = endsub
508546
509-def biff_dump(mem, stream_offset, stream_len, base=0, fout=sys.stdout):
547+def biff_dump(mem, stream_offset, stream_len, base=0, fout=sys.stdout, unnumbered=False):
510548 pos = stream_offset
511549 stream_end = stream_offset + stream_len
512550 adj = base - stream_offset
513551 dummies = 0
552+ numbered = not unnumbered
553+ num_prefix = ''
514554 while stream_end - pos >= 4:
515555 rc, length = unpack('<HH', mem[pos:pos+4])
516556 if rc == 0 and length == 0:
@@ -527,20 +567,28 @@
527567 pos += 4
528568 else:
529569 if dummies:
530- print >> fout, "%5d: ---- %d zero bytes skipped ----" % (adj+savpos, dummies)
570+ if numbered:
571+ num_prefix = "%5d: " % (adj + savpos)
572+ fprintf(fout, "%s---- %d zero bytes skipped ----\n", num_prefix, dummies)
531573 dummies = 0
532574 recname = biff_rec_name_dict.get(rc, '<UNKNOWN>')
533- print >> fout, "%5d: %04x %s len = %04x (%d)" % (adj+pos, rc, recname, length, length)
575+ if numbered:
576+ num_prefix = "%5d: " % (adj + pos)
577+ fprintf(fout, "%s%04x %s len = %04x (%d)\n", num_prefix, rc, recname, length, length)
534578 pos += 4
535- hex_char_dump(mem, pos, length, adj+pos, fout)
579+ hex_char_dump(mem, pos, length, adj+pos, fout, unnumbered)
536580 pos += length
537581 if dummies:
538- print >> fout, "%5d: ---- %d zero bytes skipped ----" % (adj+savpos, dummies, )
582+ if numbered:
583+ num_prefix = "%5d: " % (adj + savpos)
584+ fprintf(fout, "%s---- %d zero bytes skipped ----\n", num_prefix, dummies)
539585 if pos < stream_end:
540- print >> fout, "%5d: ---- Misc bytes at end ----" % (adj + pos,)
541- hex_char_dump(mem, pos, stream_end-pos, adj + pos, fout)
586+ if numbered:
587+ num_prefix = "%5d: " % (adj + pos)
588+ fprintf(fout, "%s---- Misc bytes at end ----\n", num_prefix)
589+ hex_char_dump(mem, pos, stream_end-pos, adj + pos, fout, unnumbered)
542590 elif pos > stream_end:
543- print >> fout, "Last dumped record has length (%d) that is too large" % length
591+ fprintf(fout, "Last dumped record has length (%d) that is too large\n", length)
544592
545593 def biff_count_records(mem, stream_offset, stream_len, fout=sys.stdout):
546594 pos = stream_offset
--- branches/tl3_0/python-lib/xlrd/xlrd/doc/README.html (revision 43)
+++ branches/tl3_0/python-lib/xlrd/xlrd/doc/README.html (nonexistent)
@@ -1,125 +0,0 @@
1-<p><h3>Python package "xlrd"</h3>
2-</p>
3-<p><b>Purpose</b>: Provide a library for developers to use to extract data
4- from Microsoft Excel (tm) spreadsheet files.
5- It is not an end-user tool.
6-</p>
7-<p><b>Author</b>: John Machin, Lingfo Pty Ltd (sjmachin@lexicon.net)
8-</p>
9-<p><b>Licence</b>: BSD-style (see licences.py)
10-</p>
11-<p><b>Version of xlrd</b>: 0.6.1 final
12-</p>
13-<p><b>Version of Python required</b>: 2.1 or later.
14-</p>
15-<p><b>External modules required</b>:
16-</p>
17-<dl><dd> The package itself is pure Python with no dependencies on modules or packages
18- outside the standard Python distribution.
19-
20-<dd> To run the demo script runxlrd.py with
21- Python 2.2 or 2.1 requires the Optik module (version 1.4.1 or later) from
22- http://optik.sourceforge.net/
23-</dl>
24-<p><b>Versions of Excel supported</b>:
25- 2004, 2002, XP, 2000, 97, 95, 5.0, 4.0, 3.0.
26- 2.x could be done readily enough if any demand.
27-</p>
28-<p><b>Outside the current scope</b>: xlrd will safely and reliably ignore any of these
29-if present in the file:
30-</p>
31-<ul>
32-<li> Charts, Macros, Pictures, any other embedded object. WARNING: currently
33- this includes embedded worksheets.
34-</li>
35-<li> VBA modules
36-</li>
37-<li> Formulas (results of formula calculations are extracted, of course).
38-</li>
39-<li> Comments
40-</li>
41-<li> Hyperlinks
42-</li>
43-</ul>
44-<p><b>Unlikely to be done</b>:
45-</p>
46-<ul><li> Handling password-protected (encrypted) files.
47-</li>
48-</ul>
49-<p><b>Particular emphasis (refer docs for details)</b>:
50-</p>
51-<ul><li> Operability across OS, regions, platforms
52-</li>
53-<li> Handling Excel's date problems, including the Windows / Macintosh
54- four-year differential.
55-</li>
56-<li> Providing access to named constants and named groups of cells (from version 0.6.0)
57-</li>
58-<li> Providing access to "visual" information: font, "number format", background, border,
59- alignment and protection for cells, height/width etc for rows/columns (from version 0.6.1)
60-</li>
61-</ul>
62-<p><b>Quick start</b>:
63-</p>
64-<pre><code> import xlrd
65- book = xlrd.open_workbook("myfile.xls")
66- print "The number of worksheets is", book.nsheets
67- print "Worksheet name(s):", book.sheet_names()
68- sh = book.sheet_by_index(0)
69- print sh.name, sh.nrows, sh.ncols
70- print "Cell D30 is", sh.cell_value(rowx=29, colx=3)
71- for rx in range(sh.nrows):
72- print sh.row(rx)
73- # Refer to docs for more details.
74- # Feedback on API is welcomed.
75-</code></pre><p>
76-</p>
77-<p><b>Another quick start</b>: This will show the first, second and last rows of each
78- sheet in each file:
79-</p>
80-<p><pre><code> OS-prompt>python PYDIR/scripts/runxlrd.py 3rows *blah*.xls</code></pre>
81-</p>
82-<p><b>Installation</b>:
83-</p>
84-<ul><li> On Windows: use the installer.
85-</li>
86-<li> Any OS: Unzip the .zip file into a suitable directory,
87- chdir to that directory, then do "python setup.py install".
88-</li>
89-<li> If PYDIR is your Python installation directory:
90- the main files are in PYDIR/Lib/site-packages/xlrd
91- (except for Python 2.1 where they will be in PYDIR/xlrd),
92- the docs are in the doc subdirectory,
93- and there's a sample script: PYDIR/Scripts/runxlrd.py
94-</li>
95-<li> If os.sep != "/": make the appropriate adjustments.
96-</li>
97-</ul>
98-<p><b>Download URLs</b>:
99-</p>
100-<ul><li> http://cheeseshop.python.org/pypi/xlrd
101-</li>
102-<li> http://www.lexicon.net/sjmachin/xlrd.htm
103-</li>
104-</ul>
105-<p><b>Acknowledgements</b>:
106-</p>
107-<ul><li> This package started life as a translation from C into Python
108-of parts of a utility called "xlreader" developed by David Giffin.
109-"This product includes software developed by David Giffin &lt;david@giffin.org&gt;."
110-</li>
111-<li> OpenOffice.org has truly excellent documentation of the Microsoft Excel file formats
112-and Compound Document file format, authored by Daniel Rentz. See http://sc.openoffice.org
113-</li>
114-<li> U+5F20 U+654F: over a decade of inspiration, support, and interesting decoding opportunities.
115-</li>
116-<li> Ksenia Marasanova: sample Macintosh and non-Latin1 files, alpha testing
117-</li>
118-<li> Backporting to Python 2.1 was partially funded by Journyx - provider of
119-timesheet and project accounting solutions (http://journyx.com/).
120-</li>
121-<li> Provision of formatting information in version 0.6.1 was funded by Simplistix Ltd
122- (http://www.simplistix.co.uk/)
123-</li>
124-<li> &lt;&lt; a growing list of names; see HISTORY.html &gt;&gt;: feedback, testing, test files, ...
125-</li></ul>
--- branches/tl3_0/python-lib/xlrd/xlrd/doc/HISTORY.html (revision 43)
+++ branches/tl3_0/python-lib/xlrd/xlrd/doc/HISTORY.html (nonexistent)
@@ -1,255 +0,0 @@
1-<p> Version 0.6.1, 2007-06-10
2-</p>
3-<ul>
4-<li> Version number updated to 1.6.1
5-</li>
6-<li> Documented runxlrd.py commands in its usage message. Changed commands: dump to biff_dump, count_records to biff_count.
7-</li>
8-</ul>
9-
10-<p> Version 0.6.1a5
11-</p>
12-<ul>
13-<li> Bug fixed: Missing "<" in a struct.unpack call means can't open files on bigendian platforms. Discovered by "Mihalis".
14-</li>
15-<li> Removed antique undocumented Book.get_name_dict method and experimental "trimming" facility.
16-</li>
17-<li> Meaningful exception instead of IndexError if a SAT (sector allocation table) is corrupted.
18-</li>
19-<li> If no CODEPAGE record in pre-8.0 file, assume ascii and keep going (instead of raising exception).
20-</li>
21-</ul>
22-
23-<p> Version 0.6.1a4
24-</p>
25-<ul>
26-<li> At least one source of XLS files writes parent style XF records *after* the child cell
27- XF records that refer to them, triggering IndexError in 0.5.2 and AssertionError in
28- later versions.
29- Reported with sample file by Todd O'Bryan.
30- Fixed by changing to two-pass processing of XF records.
31-</li>
32-<li> Formatting info in pre-BIFF8 files: Ensured appropriate defaults and lossless conversions to make
33- the info BIFF8-compatible. Fixed bug in extracting the "used" flags.
34-</li>
35-<li> Fixed problems discovered with opening test files from Planmaker 2006
36- (http://www.softmaker.com/english/ofwcomp_en.htm):
37- (1) Four files have reduced size of PALETTE record
38- (51 and 32 colours; Excel writes 56 always). xlrd now emits a NOTE to the logfile and continues.
39- (2) FORMULA records use the Excel 2.x record code 0x0021 instead of 0x0221. xlrd now continues silently.
40- (3) In two files, at the OLE2 compound document level, the internal directory says that the length of
41- the Short-Stream Container Stream is 16384 bytes, but the actual contents are 11264 and 9728 bytes respectively.
42- xlrd now emits a WARNING to the logfile and continues.
43-</li>
44-<li> After discussion with Daniel Rentz, the concept of two lists of XF (eXtended Format) objects
45- (raw_xf_list and computed_xf_list) has been abandoned. There is now a single list, called xf_list
46-</li>
47-</ul>
48-
49-<p> Version 0.6.1a3
50-</p>
51-<ul>
52-<li> Added Book.sheets ... for sheetx, sheet in enumerate(book.sheets):
53-</li>
54-<li> Formatting info: extraction of sheet-level flags from WINDOW2 record, and sheet.visibility
55- from BOUNDSHEET record. Added Macintosh-only Font attributes "outline" and "shadow'.
56-</li>
57-</ul>
58-
59-<p> Version 0.6.1a2
60-</p>
61-<ul>
62-<li> Added extraction of merged cells info.
63-</li>
64-<li> pyExcelerator uses "general" instead of "General" for the generic "number format". Worked around.
65-</li>
66-<li> Crystal Reports writes "WORKBOOK" in the OLE2 Compound Document directory instead of "Workbook".
67- Changed to case-insensitive directory search. Reported by Vic Simkus.
68-</li>
69-</ul>
70-
71-<p> Version 0.6.1a1, 2006-12-18
72-</p>
73-<ul>
74-<li> Added formatting information for cells (font, "number format", background, border, alignment and protection)
75- and rows/columns (height/width etc). To save memory and time for those who don't need it,
76- this information is extracted only if formatting_info=1 is supplied
77- to the open_workbook() function. The cell records BLANK and MULBLANKS
78- which contain no data, only formatting information, will continue to be ignored
79- in the default (no formatting info) case.
80-</li>
81-<li> Ralph Heimburger reported a problem with xlrd being intolerant
82- about an Excel 4.0 file (created by "some web app") with a DIMENSIONS record
83- that omitted Microsoft's usual padding with 2 unused bytes. Fixed.
84-</li>
85-</ul>
86-
87-<p> Version 0.6.0a4, not released
88-</p>
89-<ul>
90-<li> Added extraction of human-readable formulas from NAME records.
91-</li>
92-<li> Worked around OOo Calc writing 9-byte BOOLERR records instead of 8. Reported by Rory Campbell-Lange.
93-</li>
94-<li> This history file converted to descending chronological order and HTML format.
95-</li>
96-</ul>
97-
98-<p> Version 0.6.0a3, 2006-09-19
99-</p>
100-<ul>
101-<li> Names: minor bugfixes; added script xlrdnameAPIdemo.py
102-</li>
103-<li> ROW records were being used as additional hints for sizing memory requirements. In some
104- files the ROW records overstate the number of used columns, and/or there are ROW records for
105- rows that have no data in them. This would cause xlrd to report sheet.ncols and/or sheet.nrows
106- as larger than reasonably expected. Change: ROW records are ignored. The number of columns/rows is
107- based solely on the highest column/row index seen in non-empty data records. Empty data records (types
108- BLANK and MULBLANKS) which contain no data, only formatting information, have always been ignored, and
109- this will continue. Consequence: trailing rows and columns which contain only empty cells will
110- vanish.
111-</li>
112-</ul>
113-
114-<p> Version 0.6.0a2, 2006-09-13
115-</p>
116-<ul>
117-<li> Fixed a bug reported by Rory Campbell-Lange.: "open failed"; incorrect assumptions about the layout
118- of array formulas which return strings.
119-</li>
120-<li> Further work on defined names, especially the API.
121-</li>
122-</ul>
123-
124-<p> Version 0.6.0a1, 2006-09-08
125-</p>
126-<ul>
127-<li> Sheet objects have two new convenience methods: col_values(colx, start_rowx=0, end_rowx=None)
128- and the corresponding col_types. Suggested by Dennis O'Brien.
129-</li>
130-<li> BIFF 8 file missing its CODEPAGE record: xlrd will now assume utf_16_le encoding
131- (the only possibility) and keep going.
132-</li>
133-<li> Older files missing a CODEPAGE record: an exception will be raised.
134- Thanks to Sergey Krushinsky for a sample file.
135- The open_workbook() function has a new argument (encoding_override) which can
136- be used if the CODEPAGE record is missing or incorrect (for example, codepage=1251
137- but the data is actually encoded in koi8_r). The runxlrd.py script takes a
138- corresponding -e argument, for example -e cp1251
139-</li>
140-<li> Further work done on parsing "number formats". Thanks to Chris Withers for the
141- "General_)" example.
142-</li>
143-<li> Excel 97 introduced the concept of row and column labels, defined by Insert &gt; Name &gt; Labels.
144- The ranges containing the labels are now exposed as the Sheet attributes
145- row_label_ranges and col_label_ranges.
146-</li>
147-<li> The major effort in this 0.6.0 release has been the provision of access
148- to named cell ranges and named constants (Excel: Insert/Name/Define).
149- Juan C. M駭dez provided very useful real-world sample files.
150-</li>
151-</ul>
152-
153-<p> Version 0.5.3a1, 2006-05-24
154-</p>
155-<ul>
156-<li> John Popplewell and Richard Sharp provided sample files which caused any
157- reliance at all on DIMENSIONS records and ROW records to be abandoned.
158-</li>
159-<li> If the file size is not a whole number of OLE sectors, a warning message is logged.
160- Previously this caused an exception to be raised.
161-</li>
162-</ul>
163-
164-<p> Version 0.5.2, 2006-03-14, public release
165-</p>
166-<ul>
167-<li> Updated version numbers, README, HISTORY.
168-</li>
169-</ul>
170-
171-<p> Version 0.5.2a3, 2006-03-13
172-</p>
173-<ul>
174-<li> Gnumeric writes user-defined formats with format codes starting at
175- 50 instead of 164; worked around.
176-</li>
177-<li> Thanks to Didrik Pinte for reporting the need for xlrd to be more tolerant
178- of the idiosyncracies of other software, for supplying sample files,
179- and for performing alpha testing.
180-</li>
181-<li> '_' character in a format should be treated like an escape character; fixed.
182-</li>
183-<li> An "empty" formula result means a zero-length string, not an empty cell! Fixed.
184-</li>
185-</ul>
186-
187-<p> Version 0.5.2a2, 2006-03-09
188-</p>
189-<ul>
190-<li> Found that Gnumeric writes all DIMENSIONS records with nrows and ncols
191- each 1 less than they should be (except when it clamps ncols at 256!),
192- and pyXLwriter doesn't write ROW records. Cell memory pre-allocation was
193- generalised to use ROW records if available with fall-back to DIMENSIONS records.
194-</li>
195-</ul>
196-
197-<p> Version 0.5.2a1, 2006-03-06
198-</p>
199-<ul>
200-<li> pyXLwriter writes DIMENSIONS record with antique opcode 0x0000
201- instead of 0x0200; worked around
202-</li>
203-<li> A file written by Gnumeric had zeroes in DIMENSIONS record
204- but data in cell A1; worked around
205-</li>
206-</ul>
207-
208-<p> Version 0.5.1, 2006-02-18, released to Journyx
209-</p>
210-<ul>
211-<li> Python 2.1 mmap requires file to be opened for update access.
212- Added fall-back to read-only access without mmap if 2.1 open fails
213- because "permission denied".
214-</li>
215-</ul>
216-
217-<p> Version 0.5, 2006-02-07, released to Journyx
218-</p>
219-<ul>
220-<li> Now works with Python 2.1. Backporting to Python 2.1 was partially
221- funded by Journyx - provider of timesheet and project accounting
222- solutions (http://journyx.com/)
223-</li>
224-<li> open_workbook() can be given the contents of a file
225- instead of its name. Thanks to Remco Boerma for the suggestion.
226-</li>
227-<li> New module attribute __VERSION__ (as a string; for example "0.5")
228-</li>
229-<li> Minor enhancements to classification of formats as date or not-date.
230-</li>
231-<li> Added warnings about files with inconsistent OLE compound document
232- structures. Thanks to Roman V. Kiseliov (author of pyExcelerator)
233- for the tip-off.
234-</li>
235-</ul>
236-
237-<p> Version 0.4a1, 2005-09-07, released to Laurent T.
238-</p>
239-<ul>
240-<li> Book and sheet objects can now be pickled and unpickled.
241- Instead of reading a large spreadsheet multiple times,
242- consider pickling it once and loading the saved pickle;
243- can be much faster. Thanks to Laurent Thioudellet for the
244- enhancement request.
245-</li>
246-<li> Using the mmap module can be turned off.
247- But you would only do that for benchmarking purposes.
248-</li>
249-<li> Handling NUMBER records has been made faster
250-</li>
251-</ul>
252-
253-<p> Version 0.3a1, 2005-05-15, first public release
254-</p>
255-
--- branches/tl3_0/python-lib/xlrd/xlrd/doc/compdoc.html (revision 43)
+++ branches/tl3_0/python-lib/xlrd/xlrd/doc/compdoc.html (revision 44)
@@ -9,7 +9,7 @@
99 <p>Implements the minimal functionality required
1010 to extract a "Workbook" or "Book" stream (as one big string)
1111 from an OLE2 Compound Document file.
12-</p><p>Copyright &#169; 2005-2006 Stephen John Machin, Lingfo Pty Ltd</p>
12+</p><p>Copyright &#169; 2005-2008 Stephen John Machin, Lingfo Pty Ltd</p>
1313 <p>This module is part of the xlrd package, which is released under a BSD-style licence.</p>
1414 <h2>Module Contents</h2>
1515 <dl>
--- branches/tl3_0/python-lib/xlrd/xlrd/doc/xlrd.html (revision 43)
+++ branches/tl3_0/python-lib/xlrd/xlrd/doc/xlrd.html (revision 44)
@@ -7,6 +7,8 @@
77 <body>
88 <h1>The xlrd Module</h1>
99 <p /><p><b>A Python module for extracting data from MS Excel &#8482; spreadsheet files.
10+<br /><br />
11+Version 0.7.1 -- 2009-05-31
1012 </b></p>
1113
1214 <h2>General information</h2>
@@ -20,7 +22,7 @@
2022 The latest version is available from OpenOffice.org in
2123 <a href="http://sc.openoffice.org/excelfileformat.pdf"> PDF format</a>
2224 and
23-<a href="http://sc.openoffice.org/excelfileformat.sxw"> XML format.</a>
25+<a href="http://sc.openoffice.org/excelfileformat.odt"> ODT format.</a>
2426 Small portions of the OOo docs are reproduced in this
2527 document. A study of the OOo docs is recommended for those who wish a
2628 deeper understanding of the Excel file layout than the xlrd docs can provide.
@@ -245,46 +247,78 @@
245247 are inappropriate. Note that this does not affect users who are copying XLS
246248 files, only those who are visually rendering cells.</li>
247249 </ul>
248-</p><h2>Module Contents</h2>
250+
251+<h3>Loading worksheets on demand</h3>
252+
253+</p><p>This feature, new in version 0.7.1, is governed by the on_demand argument
254+to the open_workbook() function and allows saving memory and time by loading
255+only those sheets that the caller is interested in, and releasing sheets
256+when no longer required.</p>
257+
258+<p>on_demand=False (default): No change. open_workbook() loads global data
259+and all sheets, releases resources no longer required (principally the
260+str or mmap object containing the Workbook stream), and returns.</p>
261+
262+<p>on_demand=True and BIFF version &lt; 5.0: A warning message is emitted,
263+on_demand is recorded as False, and the old process is followed.</p>
264+
265+<p>on_demand=True and BIFF version &gt;= 5.0: open_workbook() loads global
266+data and returns without releasing resources. At this stage, the only
267+information available about sheets is Book.nsheets and Book.sheet_names().</p>
268+
269+<p>Book.sheet_by_name() and Book.sheet_by_index() will load the requested
270+sheet if it is not already loaded.</p>
271+
272+<p>Book.sheets() will load all/any unloaded sheets.</p>
273+
274+<p>The caller may save memory by calling
275+Book.unload_sheet(sheet_name_or_index) when finished with the sheet.
276+This applies irrespective of the state of on_demand.</p>
277+
278+<p>The caller may re-load an unloaded sheet by calling Book.sheet_by_xxxx()
279+ -- except if those required resources have been released (which will
280+have happened automatically when on_demand is false). This is the only
281+case where an exception will be raised.</p>
282+
283+<p>The caller may query the state of a sheet:
284+Book.sheet_loaded(sheet_name_or_index) -&gt; a bool</p>
285+
286+<h2>Module Contents</h2>
249287 <dl>
250-<dt><b>BaseObject</b> (class) [<a href='#xlrd.BaseObject-class'>#</a>]</dt>
288+<dt><b>BaseObject</b> (class) [<a href='#biffh.BaseObject-class'>#</a>]</dt>
251289 <dd>
252290 <p>Parent of almost all other classes in the package.</p>
253-<p>For more information about this class, see <a href='#xlrd.BaseObject-class'><i>The BaseObject Class</i></a>.</p>
291+<p>For more information about this class, see <a href='#biffh.BaseObject-class'><i>The BaseObject Class</i></a>.</p>
254292 </dd>
255-<dt><b>Book(filename=None, file_contents=None,
256-logfile=sys.stdout, verbosity=0, pickleable=True, use_mmap=USE_MMAP,
257-encoding_override=None,
258-formatting_info=False,
259-)</b> (class) [<a href='#xlrd.Book-class'>#</a>]</dt>
293+<dt><b>Book()</b> (class) [<a href='#__init__.Book-class'>#</a>]</dt>
260294 <dd>
261295 <p>Contents of a &quot;workbook&quot;.</p>
262-<p>For more information about this class, see <a href='#xlrd.Book-class'><i>The Book Class</i></a>.</p>
296+<p>For more information about this class, see <a href='#__init__.Book-class'><i>The Book Class</i></a>.</p>
263297 </dd>
264-<dt><b>Cell(ctype, value, xf_index=None)</b> (class) [<a href='#xlrd.Cell-class'>#</a>]</dt>
298+<dt><b>Cell(ctype, value, xf_index=None)</b> (class) [<a href='#sheet.Cell-class'>#</a>]</dt>
265299 <dd>
266300 <p>Contains the data for one cell.</p>
267-<p>For more information about this class, see <a href='#xlrd.Cell-class'><i>The Cell Class</i></a>.</p>
301+<p>For more information about this class, see <a href='#sheet.Cell-class'><i>The Cell Class</i></a>.</p>
268302 </dd>
269-<dt><a id='xlrd.cellname-function' name='xlrd.cellname-function'><b>cellname(rowx, colx)</b></a> [<a href='#xlrd.cellname-function'>#</a>]</dt>
303+<dt><a id='formula.cellname-function' name='formula.cellname-function'><b>cellname(rowx, colx)</b></a> [<a href='#formula.cellname-function'>#</a>]</dt>
270304 <dd>
271305 <p>Utility function: (5, 7) =&gt; 'H6'</p>
272306 </dd>
273-<dt><a id='xlrd.cellnameabs-function' name='xlrd.cellnameabs-function'><b>cellnameabs(rowx, colx)</b></a> [<a href='#xlrd.cellnameabs-function'>#</a>]</dt>
307+<dt><a id='formula.cellnameabs-function' name='formula.cellnameabs-function'><b>cellnameabs(rowx, colx)</b></a> [<a href='#formula.cellnameabs-function'>#</a>]</dt>
274308 <dd>
275309 <p>Utility function: (5, 7) =&gt; '$H$6'</p>
276310 </dd>
277-<dt><b>Colinfo</b> (class) [<a href='#xlrd.Colinfo-class'>#</a>]</dt>
311+<dt><b>Colinfo</b> (class) [<a href='#sheet.Colinfo-class'>#</a>]</dt>
278312 <dd>
279313 <p>Width and default formatting information that applies to one or
280314 more columns in a sheet.</p>
281-<p>For more information about this class, see <a href='#xlrd.Colinfo-class'><i>The Colinfo Class</i></a>.</p>
315+<p>For more information about this class, see <a href='#sheet.Colinfo-class'><i>The Colinfo Class</i></a>.</p>
282316 </dd>
283-<dt><a id='xlrd.colname-function' name='xlrd.colname-function'><b>colname(colx)</b></a> [<a href='#xlrd.colname-function'>#</a>]</dt>
317+<dt><a id='formula.colname-function' name='formula.colname-function'><b>colname(colx)</b></a> [<a href='#formula.colname-function'>#</a>]</dt>
284318 <dd>
285319 <p>Utility function: 7 =&gt; 'H', 27 =&gt; 'AB'</p>
286320 </dd>
287-<dt><a id='xlrd.count_records-function' name='xlrd.count_records-function'><b>count_records(filename, outfile=sys.stdout)</b></a> [<a href='#xlrd.count_records-function'>#</a>]</dt>
321+<dt><a id='__init__.count_records-function' name='__init__.count_records-function'><b>count_records(filename, outfile=sys.stdout)</b></a> [<a href='#__init__.count_records-function'>#</a>]</dt>
288322 <dd>
289323 <p>For debugging and analysis: summarise the file's BIFF records.
290324 I.e. produce a sorted file of (record_name, count).</p>
@@ -297,7 +331,7 @@
297331 An open file, to which the summary is written.</dd>
298332 </dl><br />
299333 </dd>
300-<dt><a id='xlrd.dump-function' name='xlrd.dump-function'><b>dump(filename, outfile=sys.stdout)</b></a> [<a href='#xlrd.dump-function'>#</a>]</dt>
334+<dt><a id='__init__.dump-function' name='__init__.dump-function'><b>dump(filename, outfile=sys.stdout, unnumbered=False)</b></a> [<a href='#__init__.dump-function'>#</a>]</dt>
301335 <dd>
302336 <p>For debugging: dump the file's BIFF records in char &amp; hex.
303337 </p><dl>
@@ -307,19 +341,22 @@
307341 <dt><i>outfile</i></dt>
308342 <dd>
309343 An open file, to which the dump is written.</dd>
344+<dt><i>unnumbered</i></dt>
345+<dd>
346+If true, omit offsets (for meaningful diffs).</dd>
310347 </dl><br />
311348 </dd>
312-<dt><a id='xlrd.empty_cell-variable' name='xlrd.empty_cell-variable'><b>empty_cell</b></a> (variable) [<a href='#xlrd.empty_cell-variable'>#</a>]</dt>
349+<dt><a id='sheet.empty_cell-variable' name='sheet.empty_cell-variable'><b>empty_cell</b></a> (variable) [<a href='#sheet.empty_cell-variable'>#</a>]</dt>
313350 <dd>
314351 <p>There is one and only one instance of an empty cell -- it's a singleton. This is it.
315352 You may use a test like &quot;acell is empty_cell&quot;.</p>
316353 </dd>
317-<dt><b>EqNeAttrs</b> (class) [<a href='#xlrd.EqNeAttrs-class'>#</a>]</dt>
354+<dt><b>EqNeAttrs</b> (class) [<a href='#formatting.EqNeAttrs-class'>#</a>]</dt>
318355 <dd>
319356 <p>This mixin class exists solely so that Format, Font, and XF....</p>
320-<p>For more information about this class, see <a href='#xlrd.EqNeAttrs-class'><i>The EqNeAttrs Class</i></a>.</p>
357+<p>For more information about this class, see <a href='#formatting.EqNeAttrs-class'><i>The EqNeAttrs Class</i></a>.</p>
321358 </dd>
322-<dt><a id='xlrd.error_text_from_code-variable' name='xlrd.error_text_from_code-variable'><b>error_text_from_code</b></a> (variable) [<a href='#xlrd.error_text_from_code-variable'>#</a>]</dt>
359+<dt><a id='biffh.error_text_from_code-variable' name='biffh.error_text_from_code-variable'><b>error_text_from_code</b></a> (variable) [<a href='#biffh.error_text_from_code-variable'>#</a>]</dt>
323360 <dd>
324361 <p /><p>This dictionary can be used to produce a text version of the internal codes
325362 that Excel uses for error cells. Here are its contents:
@@ -333,28 +370,28 @@
333370 0x2A: '#N/A!', # Argument or function not available
334371 </pre></p>
335372 </dd>
336-<dt><b>Font</b> (class) [<a href='#xlrd.Font-class'>#</a>]</dt>
373+<dt><b>Font</b> (class) [<a href='#formatting.Font-class'>#</a>]</dt>
337374 <dd>
338375 <p>An Excel &quot;font&quot; contains the details of not only what is normally
339376 considered a font, but also several other display attributes.</p>
340-<p>For more information about this class, see <a href='#xlrd.Font-class'><i>The Font Class</i></a>.</p>
377+<p>For more information about this class, see <a href='#formatting.Font-class'><i>The Font Class</i></a>.</p>
341378 </dd>
342-<dt><b>Format(format_key, ty, format_str)</b> (class) [<a href='#xlrd.Format-class'>#</a>]</dt>
379+<dt><b>Format(format_key, ty, format_str)</b> (class) [<a href='#formatting.Format-class'>#</a>]</dt>
343380 <dd>
344381 <p>&quot;Number format&quot; information from a FORMAT record.</p>
345-<p>For more information about this class, see <a href='#xlrd.Format-class'><i>The Format Class</i></a>.</p>
382+<p>For more information about this class, see <a href='#formatting.Format-class'><i>The Format Class</i></a>.</p>
346383 </dd>
347-<dt><b>Name</b> (class) [<a href='#xlrd.Name-class'>#</a>]</dt>
384+<dt><b>Name</b> (class) [<a href='#__init__.Name-class'>#</a>]</dt>
348385 <dd>
349386 <p>Information relating to a named reference, formula, macro, etc.</p>
350-<p>For more information about this class, see <a href='#xlrd.Name-class'><i>The Name Class</i></a>.</p>
387+<p>For more information about this class, see <a href='#__init__.Name-class'><i>The Name Class</i></a>.</p>
351388 </dd>
352-<dt><a id='xlrd.open_workbook-function' name='xlrd.open_workbook-function'><b>open_workbook(filename=None,
389+<dt><a id='__init__.open_workbook-function' name='__init__.open_workbook-function'><b>open_workbook(filename=None,
353390 logfile=sys.stdout, verbosity=0, pickleable=True, use_mmap=USE_MMAP,
354391 file_contents=None,
355392 encoding_override=None,
356-formatting_info=False,
357-)</b></a> [<a href='#xlrd.open_workbook-function'>#</a>]</dt>
393+formatting_info=False, on_demand=False,
394+)</b></a> [<a href='#__init__.open_workbook-function'>#</a>]</dt>
358395 <dd>
359396 <p>Open a spreadsheet file for data extraction.</p>
360397 <dl>
@@ -404,22 +441,27 @@
404441 <br /> -- New in version 0.6.1
405442
406443 </dd>
444+<dt><i>on_demand</i></dt>
445+<dd>
446+Governs whether sheets are all loaded initially or when demanded
447+by the caller. Please refer back to the section &quot;Loading worksheets on demand&quot; for details.
448+-- New in version 0.7.1</dd>
407449 <dt>Returns:</dt>
408450 <dd>
409451 An instance of the Book class.</dd>
410452 </dl><br />
411453 </dd>
412-<dt><b>Operand(akind=None, avalue=None, arank=0, atext='?')</b> (class) [<a href='#xlrd.Operand-class'>#</a>]</dt>
454+<dt><b>Operand(akind=None, avalue=None, arank=0, atext='?')</b> (class) [<a href='#formula.Operand-class'>#</a>]</dt>
413455 <dd>
414456 <p>Used in evaluating formulas.</p>
415-<p>For more information about this class, see <a href='#xlrd.Operand-class'><i>The Operand Class</i></a>.</p>
457+<p>For more information about this class, see <a href='#formula.Operand-class'><i>The Operand Class</i></a>.</p>
416458 </dd>
417-<dt><a id='xlrd.rangename3d-function' name='xlrd.rangename3d-function'><b>rangename3d(book, ref3d)</b></a> [<a href='#xlrd.rangename3d-function'>#</a>]</dt>
459+<dt><a id='formula.rangename3d-function' name='formula.rangename3d-function'><b>rangename3d(book, ref3d)</b></a> [<a href='#formula.rangename3d-function'>#</a>]</dt>
418460 <dd>
419461 <p>Utility function:
420462 <br /> Ref3D((1, 4, 5, 20, 7, 10)) =&gt; 'Sheet2:Sheet3!$H$6:$J$20'
421463 </p></dd>
422-<dt><a id='xlrd.rangename3drel-function' name='xlrd.rangename3drel-function'><b>rangename3drel(book, ref3d)</b></a> [<a href='#xlrd.rangename3drel-function'>#</a>]</dt>
464+<dt><a id='formula.rangename3drel-function' name='formula.rangename3drel-function'><b>rangename3drel(book, ref3d)</b></a> [<a href='#formula.rangename3drel-function'>#</a>]</dt>
423465 <dd>
424466 <p>Utility function:
425467 <br /> Ref3D(coords=(0, 1, -32, -22, -13, 13), relflags=(0, 0, 1, 1, 1, 1))
@@ -427,48 +469,48 @@
427469 where '@' refers to the current or base column and '#'
428470 refers to the current or base row.
429471 </p></dd>
430-<dt><b>Ref3D(atuple)</b> (class) [<a href='#xlrd.Ref3D-class'>#</a>]</dt>
472+<dt><b>Ref3D(atuple)</b> (class) [<a href='#formula.Ref3D-class'>#</a>]</dt>
431473 <dd>
432474 <p>Represents an absolute or relative 3-dimensional reference to a box
433475 of one or more cells.</p>
434-<p>For more information about this class, see <a href='#xlrd.Ref3D-class'><i>The Ref3D Class</i></a>.</p>
476+<p>For more information about this class, see <a href='#formula.Ref3D-class'><i>The Ref3D Class</i></a>.</p>
435477 </dd>
436-<dt><b>Rowinfo</b> (class) [<a href='#xlrd.Rowinfo-class'>#</a>]</dt>
478+<dt><b>Rowinfo</b> (class) [<a href='#sheet.Rowinfo-class'>#</a>]</dt>
437479 <dd>
438480 <p>Height and default formatting information that applies to a row in a sheet.</p>
439-<p>For more information about this class, see <a href='#xlrd.Rowinfo-class'><i>The Rowinfo Class</i></a>.</p>
481+<p>For more information about this class, see <a href='#sheet.Rowinfo-class'><i>The Rowinfo Class</i></a>.</p>
440482 </dd>
441-<dt><b>Sheet(book, position, name, number)</b> (class) [<a href='#xlrd.Sheet-class'>#</a>]</dt>
483+<dt><b>Sheet(book, position, name, number)</b> (class) [<a href='#sheet.Sheet-class'>#</a>]</dt>
442484 <dd>
443485 <p>Contains the data for one worksheet.</p>
444-<p>For more information about this class, see <a href='#xlrd.Sheet-class'><i>The Sheet Class</i></a>.</p>
486+<p>For more information about this class, see <a href='#sheet.Sheet-class'><i>The Sheet Class</i></a>.</p>
445487 </dd>
446-<dt><b>XF</b> (class) [<a href='#xlrd.XF-class'>#</a>]</dt>
488+<dt><b>XF</b> (class) [<a href='#formatting.XF-class'>#</a>]</dt>
447489 <dd>
448490 <p>eXtended Formatting information for cells, rows, columns and styles.</p>
449-<p>For more information about this class, see <a href='#xlrd.XF-class'><i>The XF Class</i></a>.</p>
491+<p>For more information about this class, see <a href='#formatting.XF-class'><i>The XF Class</i></a>.</p>
450492 </dd>
451-<dt><b>XFAlignment</b> (class) [<a href='#xlrd.XFAlignment-class'>#</a>]</dt>
493+<dt><b>XFAlignment</b> (class) [<a href='#formatting.XFAlignment-class'>#</a>]</dt>
452494 <dd>
453495 <p>A collection of the alignment and similar attributes of an XF record.</p>
454-<p>For more information about this class, see <a href='#xlrd.XFAlignment-class'><i>The XFAlignment Class</i></a>.</p>
496+<p>For more information about this class, see <a href='#formatting.XFAlignment-class'><i>The XFAlignment Class</i></a>.</p>
455497 </dd>
456-<dt><b>XFBackground</b> (class) [<a href='#xlrd.XFBackground-class'>#</a>]</dt>
498+<dt><b>XFBackground</b> (class) [<a href='#formatting.XFBackground-class'>#</a>]</dt>
457499 <dd>
458500 <p>A collection of the background-related attributes of an XF record.</p>
459-<p>For more information about this class, see <a href='#xlrd.XFBackground-class'><i>The XFBackground Class</i></a>.</p>
501+<p>For more information about this class, see <a href='#formatting.XFBackground-class'><i>The XFBackground Class</i></a>.</p>
460502 </dd>
461-<dt><b>XFBorder</b> (class) [<a href='#xlrd.XFBorder-class'>#</a>]</dt>
503+<dt><b>XFBorder</b> (class) [<a href='#formatting.XFBorder-class'>#</a>]</dt>
462504 <dd>
463505 <p>A collection of the border-related attributes of an XF record.</p>
464-<p>For more information about this class, see <a href='#xlrd.XFBorder-class'><i>The XFBorder Class</i></a>.</p>
506+<p>For more information about this class, see <a href='#formatting.XFBorder-class'><i>The XFBorder Class</i></a>.</p>
465507 </dd>
466-<dt><b>XFProtection</b> (class) [<a href='#xlrd.XFProtection-class'>#</a>]</dt>
508+<dt><b>XFProtection</b> (class) [<a href='#formatting.XFProtection-class'>#</a>]</dt>
467509 <dd>
468510 <p>A collection of the protection-related attributes of an XF record.</p>
469-<p>For more information about this class, see <a href='#xlrd.XFProtection-class'><i>The XFProtection Class</i></a>.</p>
511+<p>For more information about this class, see <a href='#formatting.XFProtection-class'><i>The XFProtection Class</i></a>.</p>
470512 </dd>
471-<dt><a id='xlrd.xldate_as_tuple-function' name='xlrd.xldate_as_tuple-function'><b>xldate_as_tuple(xldate, datemode)</b></a> [<a href='#xlrd.xldate_as_tuple-function'>#</a>]</dt>
513+<dt><a id='xldate.xldate_as_tuple-function' name='xldate.xldate_as_tuple-function'><b>xldate_as_tuple(xldate, datemode)</b></a> [<a href='#xldate.xldate_as_tuple-function'>#</a>]</dt>
472514 <dd>
473515 <p>Convert an Excel number (presumed to represent a date, a datetime or a time) into
474516 a tuple suitable for feeding to datetime or mx.DateTime constructors.</p>
@@ -506,7 +548,7 @@
506548 Covers the 4 specific errors</dd>
507549 </dl><br />
508550 </dd>
509-<dt><a id='xlrd.xldate_from_date_tuple-function' name='xlrd.xldate_from_date_tuple-function'><b>xldate_from_date_tuple((year, month, day), datemode)</b></a> [<a href='#xlrd.xldate_from_date_tuple-function'>#</a>]</dt>
551+<dt><a id='xldate.xldate_from_date_tuple-function' name='xldate.xldate_from_date_tuple-function'><b>xldate_from_date_tuple((year, month, day), datemode)</b></a> [<a href='#xldate.xldate_from_date_tuple-function'>#</a>]</dt>
510552 <dd>
511553 <p>Convert a date tuple (year, month, day) to an Excel date.</p>
512554 <dl>
@@ -535,7 +577,7 @@
535577 Covers the specific errors</dd>
536578 </dl><br />
537579 </dd>
538-<dt><a id='xlrd.xldate_from_datetime_tuple-function' name='xlrd.xldate_from_datetime_tuple-function'><b>xldate_from_datetime_tuple(datetime_tuple, datemode)</b></a> [<a href='#xlrd.xldate_from_datetime_tuple-function'>#</a>]</dt>
580+<dt><a id='xldate.xldate_from_datetime_tuple-function' name='xldate.xldate_from_datetime_tuple-function'><b>xldate_from_datetime_tuple(datetime_tuple, datemode)</b></a> [<a href='#xldate.xldate_from_datetime_tuple-function'>#</a>]</dt>
539581 <dd>
540582 <p>Convert a datetime tuple (year, month, day, hour, minute, second) to an Excel date value.
541583 For more details, refer to other xldate_from_*_tuple functions.</p>
@@ -548,7 +590,7 @@
548590 0: 1900-based, 1: 1904-based.</dd>
549591 </dl><br />
550592 </dd>
551-<dt><a id='xlrd.xldate_from_time_tuple-function' name='xlrd.xldate_from_time_tuple-function'><b>xldate_from_time_tuple((hour, minute, second))</b></a> [<a href='#xlrd.xldate_from_time_tuple-function'>#</a>]</dt>
593+<dt><a id='xldate.xldate_from_time_tuple-function' name='xldate.xldate_from_time_tuple-function'><b>xldate_from_time_tuple((hour, minute, second))</b></a> [<a href='#xldate.xldate_from_time_tuple-function'>#</a>]</dt>
552594 <dd>
553595 <p>Convert a time tuple (hour, minute, second) to an Excel &quot;date&quot; value (fraction of a day).</p>
554596 <dl>
@@ -569,14 +611,14 @@
569611 </dl><br />
570612 </dd>
571613 </dl>
572-<h2><a id='xlrd.BaseObject-class' name='xlrd.BaseObject-class'>The BaseObject Class</a></h2>
614+<h2><a id='biffh.BaseObject-class' name='biffh.BaseObject-class'>The BaseObject Class</a></h2>
573615 <dl>
574-<dt><b>BaseObject</b> (class) [<a href='#xlrd.BaseObject-class'>#</a>]</dt>
616+<dt><b>BaseObject</b> (class) [<a href='#biffh.BaseObject-class'>#</a>]</dt>
575617 <dd>
576618 <p>Parent of almost all other classes in the package. Defines a common &quot;dump&quot; method
577619 for debugging.</p>
578620 </dd>
579-<dt><a id='xlrd.BaseObject.dump-method' name='xlrd.BaseObject.dump-method'><b>dump(f=None, header=None, footer=None, indent=0)</b></a> [<a href='#xlrd.BaseObject.dump-method'>#</a>]</dt>
621+<dt><a id='biffh.BaseObject.dump-method' name='biffh.BaseObject.dump-method'><b>dump(f=None, header=None, footer=None, indent=0)</b></a> [<a href='#biffh.BaseObject.dump-method'>#</a>]</dt>
580622 <dd>
581623 <dl>
582624 <dt><i>f</i></dt>
@@ -594,25 +636,21 @@
594636 </dl><br />
595637 </dd>
596638 </dl>
597-<h2><a id='xlrd.Book-class' name='xlrd.Book-class'>The Book Class</a></h2>
639+<h2><a id='__init__.Book-class' name='__init__.Book-class'>The Book Class</a></h2>
598640 <dl>
599-<dt><b>Book(filename=None, file_contents=None,
600-logfile=sys.stdout, verbosity=0, pickleable=True, use_mmap=USE_MMAP,
601-encoding_override=None,
602-formatting_info=False,
603-)</b> (class) [<a href='#xlrd.Book-class'>#</a>]</dt>
641+<dt><b>Book()</b> (class) [<a href='#__init__.Book-class'>#</a>]</dt>
604642 <dd>
605643 <p>Contents of a "workbook".
606644 </p><p>WARNING: You don't call this class yourself. You use the Book object that
607645 was returned when you called xlrd.open_workbook("myfile.xls").</p>
608646 </dd>
609-<dt><a id='xlrd.Book.biff_version-attribute' name='xlrd.Book.biff_version-attribute'><b>biff_version</b></a> [<a href='#xlrd.Book.biff_version-attribute'>#</a>]</dt>
647+<dt><a id='__init__.Book.biff_version-attribute' name='__init__.Book.biff_version-attribute'><b>biff_version</b></a> [<a href='#__init__.Book.biff_version-attribute'>#</a>]</dt>
610648 <dd>
611649 <p>Version of BIFF (Binary Interchange File Format) used to create the file.
612650 Latest is 8.0 (represented here as 80), introduced with Excel 97.
613-Earliest supported by this module: 3.0 (represented as 30).</p>
651+Earliest supported by this module: 2.0 (represented as 20).</p>
614652 </dd>
615-<dt><a id='xlrd.Book.codepage-attribute' name='xlrd.Book.codepage-attribute'><b>codepage</b></a> [<a href='#xlrd.Book.codepage-attribute'>#</a>]</dt>
653+<dt><a id='__init__.Book.codepage-attribute' name='__init__.Book.codepage-attribute'><b>codepage</b></a> [<a href='#__init__.Book.codepage-attribute'>#</a>]</dt>
616654 <dd>
617655 <p>An integer denoting the character set used for strings in this file.
618656 For BIFF 8 and later, this will be 1200, meaning Unicode; more precisely, UTF_16_LE.
@@ -620,7 +658,7 @@
620658 to be used to convert to Unicode.
621659 Examples: 1252 -&gt; 'cp1252', 10000 -&gt; 'mac_roman'</p>
622660 </dd>
623-<dt><a id='xlrd.Book.colour_map-attribute' name='xlrd.Book.colour_map-attribute'><b>colour_map</b></a> [<a href='#xlrd.Book.colour_map-attribute'>#</a>]</dt>
661+<dt><a id='__init__.Book.colour_map-attribute' name='__init__.Book.colour_map-attribute'><b>colour_map</b></a> [<a href='#__init__.Book.colour_map-attribute'>#</a>]</dt>
624662 <dd>
625663 <p>This provides definitions for colour indexes. Please refer to the
626664 above section "The Palette; Colour Indexes" for an explanation
@@ -629,9 +667,9 @@
629667 "Magic" indexes e.g. 0x7FFF map to None.
630668 <i>colour_map</i> is what you need if you want to render cells on screen or in a PDF
631669 file. If you are writing an output XLS file, use <i>palette_record</i>.
632-<br /> -- New in version 0.6.1
670+<br /> -- New in version 0.6.1. Extracted only if open_workbook(..., formatting_info=True)
633671 </p></dd>
634-<dt><a id='xlrd.Book.countries-attribute' name='xlrd.Book.countries-attribute'><b>countries</b></a> [<a href='#xlrd.Book.countries-attribute'>#</a>]</dt>
672+<dt><a id='__init__.Book.countries-attribute' name='__init__.Book.countries-attribute'><b>countries</b></a> [<a href='#__init__.Book.countries-attribute'>#</a>]</dt>
635673 <dd>
636674 <p>A tuple containing the (telephone system) country code for:<br />
637675 [0]: the user-interface setting when the file was created.<br />
@@ -641,22 +679,22 @@
641679 For a long list of observed values, refer to the OpenOffice.org documentation for
642680 the COUNTRY record.
643681 </p></dd>
644-<dt><a id='xlrd.Book.datemode-attribute' name='xlrd.Book.datemode-attribute'><b>datemode</b></a> [<a href='#xlrd.Book.datemode-attribute'>#</a>]</dt>
682+<dt><a id='__init__.Book.datemode-attribute' name='__init__.Book.datemode-attribute'><b>datemode</b></a> [<a href='#__init__.Book.datemode-attribute'>#</a>]</dt>
645683 <dd>
646684 <p>Which date system was in force when this file was last saved.<br />
647685 0 =&gt; 1900 system (the Excel for Windows default).<br />
648686 1 =&gt; 1904 system (the Excel for Macintosh default).<br />
649687 </p></dd>
650-<dt><a id='xlrd.Book.encoding-attribute' name='xlrd.Book.encoding-attribute'><b>encoding</b></a> [<a href='#xlrd.Book.encoding-attribute'>#</a>]</dt>
688+<dt><a id='__init__.Book.encoding-attribute' name='__init__.Book.encoding-attribute'><b>encoding</b></a> [<a href='#__init__.Book.encoding-attribute'>#</a>]</dt>
651689 <dd>
652690 <p>The encoding that was derived from the codepage.</p>
653691 </dd>
654-<dt><a id='xlrd.Book.font_list-attribute' name='xlrd.Book.font_list-attribute'><b>font_list</b></a> [<a href='#xlrd.Book.font_list-attribute'>#</a>]</dt>
692+<dt><a id='__init__.Book.font_list-attribute' name='__init__.Book.font_list-attribute'><b>font_list</b></a> [<a href='#__init__.Book.font_list-attribute'>#</a>]</dt>
655693 <dd>
656694 <p>A list of Font class instances, each corresponding to a FONT record.
657695 <br /> -- New in version 0.6.1
658696 </p></dd>
659-<dt><a id='xlrd.Book.format_list-attribute' name='xlrd.Book.format_list-attribute'><b>format_list</b></a> [<a href='#xlrd.Book.format_list-attribute'>#</a>]</dt>
697+<dt><a id='__init__.Book.format_list-attribute' name='__init__.Book.format_list-attribute'><b>format_list</b></a> [<a href='#__init__.Book.format_list-attribute'>#</a>]</dt>
660698 <dd>
661699 <p>A list of Format objects, each corresponding to a FORMAT record, in
662700 the order that they appear in the input file.
@@ -666,41 +704,42 @@
666704 The collection to be used for all visual rendering purposes is format_map.
667705 <br /> -- New in version 0.6.1
668706 </p></dd>
669-<dt><a id='xlrd.Book.format_map-attribute' name='xlrd.Book.format_map-attribute'><b>format_map</b></a> [<a href='#xlrd.Book.format_map-attribute'>#</a>]</dt>
707+<dt><a id='__init__.Book.format_map-attribute' name='__init__.Book.format_map-attribute'><b>format_map</b></a> [<a href='#__init__.Book.format_map-attribute'>#</a>]</dt>
670708 <dd>
671709 <p>The mapping from XF.format_key to Format object.
672710 <br /> -- New in version 0.6.1
673711 </p></dd>
674-<dt><a id='xlrd.Book.load_time_stage_1-attribute' name='xlrd.Book.load_time_stage_1-attribute'><b>load_time_stage_1</b></a> [<a href='#xlrd.Book.load_time_stage_1-attribute'>#</a>]</dt>
712+<dt><a id='__init__.Book.load_time_stage_1-attribute' name='__init__.Book.load_time_stage_1-attribute'><b>load_time_stage_1</b></a> [<a href='#__init__.Book.load_time_stage_1-attribute'>#</a>]</dt>
675713 <dd>
676714 <p>Time in seconds to extract the XLS image as a contiguous string (or mmap equivalent).</p>
677715 </dd>
678-<dt><a id='xlrd.Book.load_time_stage_2-attribute' name='xlrd.Book.load_time_stage_2-attribute'><b>load_time_stage_2</b></a> [<a href='#xlrd.Book.load_time_stage_2-attribute'>#</a>]</dt>
716+<dt><a id='__init__.Book.load_time_stage_2-attribute' name='__init__.Book.load_time_stage_2-attribute'><b>load_time_stage_2</b></a> [<a href='#__init__.Book.load_time_stage_2-attribute'>#</a>]</dt>
679717 <dd>
680718 <p>Time in seconds to parse the data from the contiguous string (or mmap equivalent).</p>
681719 </dd>
682-<dt><a id='xlrd.Book.name_and_scope_map-attribute' name='xlrd.Book.name_and_scope_map-attribute'><b>name_and_scope_map</b></a> [<a href='#xlrd.Book.name_and_scope_map-attribute'>#</a>]</dt>
720+<dt><a id='__init__.Book.name_and_scope_map-attribute' name='__init__.Book.name_and_scope_map-attribute'><b>name_and_scope_map</b></a> [<a href='#__init__.Book.name_and_scope_map-attribute'>#</a>]</dt>
683721 <dd>
684722 <p>A mapping from (lower_case_name, scope) to a single Name object.
685-<br /> -- New in version 0.6.0
723+<br /> -- New in version 0.6.0
686724 </p></dd>
687-<dt><a id='xlrd.Book.name_map-attribute' name='xlrd.Book.name_map-attribute'><b>name_map</b></a> [<a href='#xlrd.Book.name_map-attribute'>#</a>]</dt>
725+<dt><a id='__init__.Book.name_map-attribute' name='__init__.Book.name_map-attribute'><b>name_map</b></a> [<a href='#__init__.Book.name_map-attribute'>#</a>]</dt>
688726 <dd>
689727 <p>A mapping from lower_case_name to a list of Name objects. The list is
690728 sorted in scope order. Typically there will be one item (of global scope)
691729 in the list.
692-<br /> -- New in version 0.6.0
730+<br /> -- New in version 0.6.0
693731 </p></dd>
694-<dt><a id='xlrd.Book.name_obj_list-attribute' name='xlrd.Book.name_obj_list-attribute'><b>name_obj_list</b></a> [<a href='#xlrd.Book.name_obj_list-attribute'>#</a>]</dt>
732+<dt><a id='__init__.Book.name_obj_list-attribute' name='__init__.Book.name_obj_list-attribute'><b>name_obj_list</b></a> [<a href='#__init__.Book.name_obj_list-attribute'>#</a>]</dt>
695733 <dd>
696734 <p>List containing a Name object for each NAME record in the workbook.
697-<br /> -- New in version 0.6.0
735+<br /> -- New in version 0.6.0
698736 </p></dd>
699-<dt><a id='xlrd.Book.nsheets-attribute' name='xlrd.Book.nsheets-attribute'><b>nsheets</b></a> [<a href='#xlrd.Book.nsheets-attribute'>#</a>]</dt>
737+<dt><a id='__init__.Book.nsheets-attribute' name='__init__.Book.nsheets-attribute'><b>nsheets</b></a> [<a href='#__init__.Book.nsheets-attribute'>#</a>]</dt>
700738 <dd>
701-<p>The number of worksheets in the workbook.</p>
739+<p>The number of worksheets present in the workbook file.
740+This information is available even when no sheets have yet been loaded.</p>
702741 </dd>
703-<dt><a id='xlrd.Book.palette_record-attribute' name='xlrd.Book.palette_record-attribute'><b>palette_record</b></a> [<a href='#xlrd.Book.palette_record-attribute'>#</a>]</dt>
742+<dt><a id='__init__.Book.palette_record-attribute' name='__init__.Book.palette_record-attribute'><b>palette_record</b></a> [<a href='#__init__.Book.palette_record-attribute'>#</a>]</dt>
704743 <dd>
705744 <p>If the user has changed any of the colours in the standard palette, the XLS
706745 file will contain a PALETTE record with 56 (16 for Excel 4.0 and earlier)
@@ -708,9 +747,9 @@
708747 Otherwise this list will be empty. This is what you need if you are
709748 writing an output XLS file. If you want to render cells on screen or in a PDF
710749 file, use colour_map.
711-<br /> -- New in version 0.6.1
750+<br /> -- New in version 0.6.1. Extracted only if open_workbook(..., formatting_info=True)
712751 </p></dd>
713-<dt><a id='xlrd.Book.sheet_by_index-method' name='xlrd.Book.sheet_by_index-method'><b>sheet_by_index(sheetx)</b></a> [<a href='#xlrd.Book.sheet_by_index-method'>#</a>]</dt>
752+<dt><a id='__init__.Book.sheet_by_index-method' name='__init__.Book.sheet_by_index-method'><b>sheet_by_index(sheetx)</b></a> [<a href='#__init__.Book.sheet_by_index-method'>#</a>]</dt>
714753 <dd>
715754 <dl>
716755 <dt><i>sheetx</i></dt>
@@ -721,7 +760,7 @@
721760 An object of the Sheet class</dd>
722761 </dl><br />
723762 </dd>
724-<dt><a id='xlrd.Book.sheet_by_name-method' name='xlrd.Book.sheet_by_name-method'><b>sheet_by_name(sheet_name)</b></a> [<a href='#xlrd.Book.sheet_by_name-method'>#</a>]</dt>
763+<dt><a id='__init__.Book.sheet_by_name-method' name='__init__.Book.sheet_by_name-method'><b>sheet_by_name(sheet_name)</b></a> [<a href='#__init__.Book.sheet_by_name-method'>#</a>]</dt>
725764 <dd>
726765 <dl>
727766 <dt><i>sheet_name</i></dt>
@@ -732,24 +771,39 @@
732771 An object of the Sheet class</dd>
733772 </dl><br />
734773 </dd>
735-<dt><a id='xlrd.Book.sheet_names-method' name='xlrd.Book.sheet_names-method'><b>sheet_names()</b></a> [<a href='#xlrd.Book.sheet_names-method'>#</a>]</dt>
774+<dt><a id='__init__.Book.sheet_loaded-method' name='__init__.Book.sheet_loaded-method'><b>sheet_loaded(sheet_name_or_index)</b></a> [<a href='#__init__.Book.sheet_loaded-method'>#</a>]</dt>
736775 <dd>
737776 <dl>
777+<dt><i>sheet_name_or_index</i></dt>
778+<dd>
779+Name or index of sheet enquired upon</dd>
738780 <dt>Returns:</dt>
739781 <dd>
740-A list of the names of the sheets in the book.</dd>
782+true if sheet is loaded, false otherwise
783+<br /> -- New in version 0.7.1
784+</dd>
741785 </dl><br />
742786 </dd>
743-<dt><a id='xlrd.Book.sheets-method' name='xlrd.Book.sheets-method'><b>sheets()</b></a> [<a href='#xlrd.Book.sheets-method'>#</a>]</dt>
787+<dt><a id='__init__.Book.sheet_names-method' name='__init__.Book.sheet_names-method'><b>sheet_names()</b></a> [<a href='#__init__.Book.sheet_names-method'>#</a>]</dt>
744788 <dd>
745789 <dl>
746790 <dt>Returns:</dt>
747791 <dd>
748-A list of all sheets in the book.</dd>
792+A list of the names of all the worksheets in the workbook file.
793+This information is available even when no sheets have yet been loaded.</dd>
749794 </dl><br />
750795 </dd>
751-<dt><a id='xlrd.Book.style_name_map-attribute' name='xlrd.Book.style_name_map-attribute'><b>style_name_map</b></a> [<a href='#xlrd.Book.style_name_map-attribute'>#</a>]</dt>
796+<dt><a id='__init__.Book.sheets-method' name='__init__.Book.sheets-method'><b>sheets()</b></a> [<a href='#__init__.Book.sheets-method'>#</a>]</dt>
752797 <dd>
798+<dl>
799+<dt>Returns:</dt>
800+<dd>
801+A list of all sheets in the book.
802+All sheets not already loaded will be loaded.</dd>
803+</dl><br />
804+</dd>
805+<dt><a id='__init__.Book.style_name_map-attribute' name='__init__.Book.style_name_map-attribute'><b>style_name_map</b></a> [<a href='#__init__.Book.style_name_map-attribute'>#</a>]</dt>
806+<dd>
753807 <p>This provides access via name to the extended format information for
754808 both built-in styles and user-defined styles.<br />
755809 It maps <i>name</i> to (<i>built_in</i>, <i>xf_index</i>), where:<br />
@@ -763,19 +817,29 @@
763817 References: OOo docs s6.99 (STYLE record); Excel UI Format/Style
764818 <br /> -- New in version 0.6.1
765819 </p></dd>
766-<dt><a id='xlrd.Book.user_name-attribute' name='xlrd.Book.user_name-attribute'><b>user_name</b></a> [<a href='#xlrd.Book.user_name-attribute'>#</a>]</dt>
820+<dt><a id='__init__.Book.unload_sheet-method' name='__init__.Book.unload_sheet-method'><b>unload_sheet(sheet_name_or_index)</b></a> [<a href='#__init__.Book.unload_sheet-method'>#</a>]</dt>
767821 <dd>
822+<dl>
823+<dt><i>sheet_name_or_index</i></dt>
824+<dd>
825+Name or index of sheet to be unloaded.
826+<br /> -- New in version 0.7.1
827+</dd>
828+</dl><br />
829+</dd>
830+<dt><a id='__init__.Book.user_name-attribute' name='__init__.Book.user_name-attribute'><b>user_name</b></a> [<a href='#__init__.Book.user_name-attribute'>#</a>]</dt>
831+<dd>
768832 <p>What (if anything) is recorded as the name of the last user to save the file.</p>
769833 </dd>
770-<dt><a id='xlrd.Book.xf_list-attribute' name='xlrd.Book.xf_list-attribute'><b>xf_list</b></a> [<a href='#xlrd.Book.xf_list-attribute'>#</a>]</dt>
834+<dt><a id='__init__.Book.xf_list-attribute' name='__init__.Book.xf_list-attribute'><b>xf_list</b></a> [<a href='#__init__.Book.xf_list-attribute'>#</a>]</dt>
771835 <dd>
772836 <p>A list of XF class instances, each corresponding to an XF record.
773837 <br /> -- New in version 0.6.1
774838 </p></dd>
775839 </dl>
776-<h2><a id='xlrd.Cell-class' name='xlrd.Cell-class'>The Cell Class</a></h2>
840+<h2><a id='sheet.Cell-class' name='sheet.Cell-class'>The Cell Class</a></h2>
777841 <dl>
778-<dt><b>Cell(ctype, value, xf_index=None)</b> (class) [<a href='#xlrd.Cell-class'>#</a>]</dt>
842+<dt><b>Cell(ctype, value, xf_index=None)</b> (class) [<a href='#sheet.Cell-class'>#</a>]</dt>
779843 <dd>
780844 <p /><p>Contains the data for one cell.</p>
781845
@@ -835,9 +899,9 @@
835899 <p />
836900 </dd>
837901 </dl>
838-<h2><a id='xlrd.Colinfo-class' name='xlrd.Colinfo-class'>The Colinfo Class</a></h2>
902+<h2><a id='sheet.Colinfo-class' name='sheet.Colinfo-class'>The Colinfo Class</a></h2>
839903 <dl>
840-<dt><b>Colinfo</b> (class) [<a href='#xlrd.Colinfo-class'>#</a>]</dt>
904+<dt><b>Colinfo</b> (class) [<a href='#sheet.Colinfo-class'>#</a>]</dt>
841905 <dd>
842906 <p>Width and default formatting information that applies to one or
843907 more columns in a sheet. Derived from COLINFO records.
@@ -873,45 +937,45 @@
873937 <br />-- New in version 0.6.1
874938 </p>
875939 </dd>
876-<dt><a id='xlrd.Colinfo.bit1_flag-attribute' name='xlrd.Colinfo.bit1_flag-attribute'><b>bit1_flag</b></a> [<a href='#xlrd.Colinfo.bit1_flag-attribute'>#</a>]</dt>
940+<dt><a id='sheet.Colinfo.bit1_flag-attribute' name='sheet.Colinfo.bit1_flag-attribute'><b>bit1_flag</b></a> [<a href='#sheet.Colinfo.bit1_flag-attribute'>#</a>]</dt>
877941 <dd>
878942 <p>Value of a 1-bit flag whose purpose is unknown
879943 but is often seen set to 1</p>
880944 </dd>
881-<dt><a id='xlrd.Colinfo.collapsed-attribute' name='xlrd.Colinfo.collapsed-attribute'><b>collapsed</b></a> [<a href='#xlrd.Colinfo.collapsed-attribute'>#</a>]</dt>
945+<dt><a id='sheet.Colinfo.collapsed-attribute' name='sheet.Colinfo.collapsed-attribute'><b>collapsed</b></a> [<a href='#sheet.Colinfo.collapsed-attribute'>#</a>]</dt>
882946 <dd>
883947 <p>1 = column is collapsed</p>
884948 </dd>
885-<dt><a id='xlrd.Colinfo.hidden-attribute' name='xlrd.Colinfo.hidden-attribute'><b>hidden</b></a> [<a href='#xlrd.Colinfo.hidden-attribute'>#</a>]</dt>
949+<dt><a id='sheet.Colinfo.hidden-attribute' name='sheet.Colinfo.hidden-attribute'><b>hidden</b></a> [<a href='#sheet.Colinfo.hidden-attribute'>#</a>]</dt>
886950 <dd>
887951 <p>1 = column is hidden</p>
888952 </dd>
889-<dt><a id='xlrd.Colinfo.outline_level-attribute' name='xlrd.Colinfo.outline_level-attribute'><b>outline_level</b></a> [<a href='#xlrd.Colinfo.outline_level-attribute'>#</a>]</dt>
953+<dt><a id='sheet.Colinfo.outline_level-attribute' name='sheet.Colinfo.outline_level-attribute'><b>outline_level</b></a> [<a href='#sheet.Colinfo.outline_level-attribute'>#</a>]</dt>
890954 <dd>
891955 <p>Outline level of the column, in range(7).
892956 (0 = no outline)</p>
893957 </dd>
894-<dt><a id='xlrd.Colinfo.width-attribute' name='xlrd.Colinfo.width-attribute'><b>width</b></a> [<a href='#xlrd.Colinfo.width-attribute'>#</a>]</dt>
958+<dt><a id='sheet.Colinfo.width-attribute' name='sheet.Colinfo.width-attribute'><b>width</b></a> [<a href='#sheet.Colinfo.width-attribute'>#</a>]</dt>
895959 <dd>
896960 <p>Width of the column in 1/256 of the width of the zero character,
897961 using default font (first FONT record in the file).</p>
898962 </dd>
899-<dt><a id='xlrd.Colinfo.xf_index-attribute' name='xlrd.Colinfo.xf_index-attribute'><b>xf_index</b></a> [<a href='#xlrd.Colinfo.xf_index-attribute'>#</a>]</dt>
963+<dt><a id='sheet.Colinfo.xf_index-attribute' name='sheet.Colinfo.xf_index-attribute'><b>xf_index</b></a> [<a href='#sheet.Colinfo.xf_index-attribute'>#</a>]</dt>
900964 <dd>
901965 <p>XF index to be used for formatting empty cells.</p>
902966 </dd>
903967 </dl>
904-<h2><a id='xlrd.EqNeAttrs-class' name='xlrd.EqNeAttrs-class'>The EqNeAttrs Class</a></h2>
968+<h2><a id='formatting.EqNeAttrs-class' name='formatting.EqNeAttrs-class'>The EqNeAttrs Class</a></h2>
905969 <dl>
906-<dt><b>EqNeAttrs</b> (class) [<a href='#xlrd.EqNeAttrs-class'>#</a>]</dt>
970+<dt><b>EqNeAttrs</b> (class) [<a href='#formatting.EqNeAttrs-class'>#</a>]</dt>
907971 <dd>
908972 <p>This mixin class exists solely so that Format, Font, and XF.... objects
909973 can be compared by value of their attributes.</p>
910974 </dd>
911975 </dl>
912-<h2><a id='xlrd.Font-class' name='xlrd.Font-class'>The Font Class</a></h2>
976+<h2><a id='formatting.Font-class' name='formatting.Font-class'>The Font Class</a></h2>
913977 <dl>
914-<dt><b>Font</b> (class) [<a href='#xlrd.Font-class'>#</a>]</dt>
978+<dt><b>Font</b> (class) [<a href='#formatting.Font-class'>#</a>]</dt>
915979 <dd>
916980 <p>An Excel "font" contains the details of not only what is normally
917981 considered a font, but also several other display attributes.
@@ -918,11 +982,11 @@
918982 Items correspond to those in the Excel UI's Format/Cells/Font tab.
919983 <br /> -- New in version 0.6.1
920984 </p></dd>
921-<dt><a id='xlrd.Font.bold-attribute' name='xlrd.Font.bold-attribute'><b>bold</b></a> [<a href='#xlrd.Font.bold-attribute'>#</a>]</dt>
985+<dt><a id='formatting.Font.bold-attribute' name='formatting.Font.bold-attribute'><b>bold</b></a> [<a href='#formatting.Font.bold-attribute'>#</a>]</dt>
922986 <dd>
923987 <p>1 = Characters are bold. Redundant; see &quot;weight&quot; attribute.</p>
924988 </dd>
925-<dt><a id='xlrd.Font.character_set-attribute' name='xlrd.Font.character_set-attribute'><b>character_set</b></a> [<a href='#xlrd.Font.character_set-attribute'>#</a>]</dt>
989+<dt><a id='formatting.Font.character_set-attribute' name='formatting.Font.character_set-attribute'><b>character_set</b></a> [<a href='#formatting.Font.character_set-attribute'>#</a>]</dt>
926990 <dd>
927991 <p>Values: 0 = ANSI Latin, 1 = System default, 2 = Symbol,
928992 77 = Apple Roman,
@@ -942,16 +1006,16 @@
9421006 238 = ANSI Latin II (Central European),
9431007 255 = OEM Latin I</p>
9441008 </dd>
945-<dt><a id='xlrd.Font.colour_index-attribute' name='xlrd.Font.colour_index-attribute'><b>colour_index</b></a> [<a href='#xlrd.Font.colour_index-attribute'>#</a>]</dt>
1009+<dt><a id='formatting.Font.colour_index-attribute' name='formatting.Font.colour_index-attribute'><b>colour_index</b></a> [<a href='#formatting.Font.colour_index-attribute'>#</a>]</dt>
9461010 <dd>
9471011 <p>An explanation of &quot;colour index&quot; is given in the Formatting
9481012 section at the start of this document.</p>
9491013 </dd>
950-<dt><a id='xlrd.Font.escapement-attribute' name='xlrd.Font.escapement-attribute'><b>escapement</b></a> [<a href='#xlrd.Font.escapement-attribute'>#</a>]</dt>
1014+<dt><a id='formatting.Font.escapement-attribute' name='formatting.Font.escapement-attribute'><b>escapement</b></a> [<a href='#formatting.Font.escapement-attribute'>#</a>]</dt>
9511015 <dd>
9521016 <p>1 = Superscript, 2 = Subscript.</p>
9531017 </dd>
954-<dt><a id='xlrd.Font.family-attribute' name='xlrd.Font.family-attribute'><b>family</b></a> [<a href='#xlrd.Font.family-attribute'>#</a>]</dt>
1018+<dt><a id='formatting.Font.family-attribute' name='formatting.Font.family-attribute'><b>family</b></a> [<a href='#formatting.Font.family-attribute'>#</a>]</dt>
9551019 <dd>
9561020 <p>0 = None (unknown or don't care)<br />
9571021 1 = Roman (variable width, serifed)<br />
@@ -960,67 +1024,67 @@
9601024 4 = Script (cursive)<br />
9611025 5 = Decorative (specialised, for example Old English, Fraktur)
9621026 </p></dd>
963-<dt><a id='xlrd.Font.font_index-attribute' name='xlrd.Font.font_index-attribute'><b>font_index</b></a> [<a href='#xlrd.Font.font_index-attribute'>#</a>]</dt>
1027+<dt><a id='formatting.Font.font_index-attribute' name='formatting.Font.font_index-attribute'><b>font_index</b></a> [<a href='#formatting.Font.font_index-attribute'>#</a>]</dt>
9641028 <dd>
9651029 <p>The 0-based index used to refer to this Font() instance.
9661030 Note that index 4 is never used; xlrd supplies a dummy place-holder.</p>
9671031 </dd>
968-<dt><a id='xlrd.Font.height-attribute' name='xlrd.Font.height-attribute'><b>height</b></a> [<a href='#xlrd.Font.height-attribute'>#</a>]</dt>
1032+<dt><a id='formatting.Font.height-attribute' name='formatting.Font.height-attribute'><b>height</b></a> [<a href='#formatting.Font.height-attribute'>#</a>]</dt>
9691033 <dd>
9701034 <p>Height of the font (in twips). A twip = 1/20 of a point.</p>
9711035 </dd>
972-<dt><a id='xlrd.Font.italic-attribute' name='xlrd.Font.italic-attribute'><b>italic</b></a> [<a href='#xlrd.Font.italic-attribute'>#</a>]</dt>
1036+<dt><a id='formatting.Font.italic-attribute' name='formatting.Font.italic-attribute'><b>italic</b></a> [<a href='#formatting.Font.italic-attribute'>#</a>]</dt>
9731037 <dd>
9741038 <p>1 = Characters are italic.</p>
9751039 </dd>
976-<dt><a id='xlrd.Font.name-attribute' name='xlrd.Font.name-attribute'><b>name</b></a> [<a href='#xlrd.Font.name-attribute'>#</a>]</dt>
1040+<dt><a id='formatting.Font.name-attribute' name='formatting.Font.name-attribute'><b>name</b></a> [<a href='#formatting.Font.name-attribute'>#</a>]</dt>
9771041 <dd>
9781042 <p>The name of the font. Example: u&quot;Arial&quot;</p>
9791043 </dd>
980-<dt><a id='xlrd.Font.outline-attribute' name='xlrd.Font.outline-attribute'><b>outline</b></a> [<a href='#xlrd.Font.outline-attribute'>#</a>]</dt>
1044+<dt><a id='formatting.Font.outline-attribute' name='formatting.Font.outline-attribute'><b>outline</b></a> [<a href='#formatting.Font.outline-attribute'>#</a>]</dt>
9811045 <dd>
9821046 <p>1 = Font is outline style (Macintosh only)</p>
9831047 </dd>
984-<dt><a id='xlrd.Font.shadow-attribute' name='xlrd.Font.shadow-attribute'><b>shadow</b></a> [<a href='#xlrd.Font.shadow-attribute'>#</a>]</dt>
1048+<dt><a id='formatting.Font.shadow-attribute' name='formatting.Font.shadow-attribute'><b>shadow</b></a> [<a href='#formatting.Font.shadow-attribute'>#</a>]</dt>
9851049 <dd>
9861050 <p>1 = Font is shadow style (Macintosh only)</p>
9871051 </dd>
988-<dt><a id='xlrd.Font.struck_out-attribute' name='xlrd.Font.struck_out-attribute'><b>struck_out</b></a> [<a href='#xlrd.Font.struck_out-attribute'>#</a>]</dt>
1052+<dt><a id='formatting.Font.struck_out-attribute' name='formatting.Font.struck_out-attribute'><b>struck_out</b></a> [<a href='#formatting.Font.struck_out-attribute'>#</a>]</dt>
9891053 <dd>
9901054 <p>1 = Characters are struck out.</p>
9911055 </dd>
992-<dt><a id='xlrd.Font.underline_type-attribute' name='xlrd.Font.underline_type-attribute'><b>underline_type</b></a> [<a href='#xlrd.Font.underline_type-attribute'>#</a>]</dt>
1056+<dt><a id='formatting.Font.underline_type-attribute' name='formatting.Font.underline_type-attribute'><b>underline_type</b></a> [<a href='#formatting.Font.underline_type-attribute'>#</a>]</dt>
9931057 <dd>
9941058 <p>0 = None<br />
9951059 1 = Single; 0x21 (33) = Single accounting<br />
9961060 2 = Double; 0x22 (34) = Double accounting
9971061 </p></dd>
998-<dt><a id='xlrd.Font.underlined-attribute' name='xlrd.Font.underlined-attribute'><b>underlined</b></a> [<a href='#xlrd.Font.underlined-attribute'>#</a>]</dt>
1062+<dt><a id='formatting.Font.underlined-attribute' name='formatting.Font.underlined-attribute'><b>underlined</b></a> [<a href='#formatting.Font.underlined-attribute'>#</a>]</dt>
9991063 <dd>
10001064 <p>1 = Characters are underlined. Redundant; see &quot;underline_type&quot; attribute.</p>
10011065 </dd>
1002-<dt><a id='xlrd.Font.weight-attribute' name='xlrd.Font.weight-attribute'><b>weight</b></a> [<a href='#xlrd.Font.weight-attribute'>#</a>]</dt>
1066+<dt><a id='formatting.Font.weight-attribute' name='formatting.Font.weight-attribute'><b>weight</b></a> [<a href='#formatting.Font.weight-attribute'>#</a>]</dt>
10031067 <dd>
10041068 <p>Font weight (100-1000). Standard values are 400 for normal text
10051069 and 700 for bold text.</p>
10061070 </dd>
10071071 </dl>
1008-<h2><a id='xlrd.Format-class' name='xlrd.Format-class'>The Format Class</a></h2>
1072+<h2><a id='formatting.Format-class' name='formatting.Format-class'>The Format Class</a></h2>
10091073 <dl>
1010-<dt><b>Format(format_key, ty, format_str)</b> (class) [<a href='#xlrd.Format-class'>#</a>]</dt>
1074+<dt><b>Format(format_key, ty, format_str)</b> (class) [<a href='#formatting.Format-class'>#</a>]</dt>
10111075 <dd>
10121076 <p>"Number format" information from a FORMAT record.
10131077 <br /> -- New in version 0.6.1
10141078 </p></dd>
1015-<dt><a id='xlrd.Format.format_key-attribute' name='xlrd.Format.format_key-attribute'><b>format_key</b></a> [<a href='#xlrd.Format.format_key-attribute'>#</a>]</dt>
1079+<dt><a id='formatting.Format.format_key-attribute' name='formatting.Format.format_key-attribute'><b>format_key</b></a> [<a href='#formatting.Format.format_key-attribute'>#</a>]</dt>
10161080 <dd>
10171081 <p>The key into Book.format_map</p>
10181082 </dd>
1019-<dt><a id='xlrd.Format.format_str-attribute' name='xlrd.Format.format_str-attribute'><b>format_str</b></a> [<a href='#xlrd.Format.format_str-attribute'>#</a>]</dt>
1083+<dt><a id='formatting.Format.format_str-attribute' name='formatting.Format.format_str-attribute'><b>format_str</b></a> [<a href='#formatting.Format.format_str-attribute'>#</a>]</dt>
10201084 <dd>
10211085 <p>The format string</p>
10221086 </dd>
1023-<dt><a id='xlrd.Format.type-attribute' name='xlrd.Format.type-attribute'><b>type</b></a> [<a href='#xlrd.Format.type-attribute'>#</a>]</dt>
1087+<dt><a id='formatting.Format.type-attribute' name='formatting.Format.type-attribute'><b>type</b></a> [<a href='#formatting.Format.type-attribute'>#</a>]</dt>
10241088 <dd>
10251089 <p>A classification that has been inferred from the format string.
10261090 Currently, this is used only to distinguish between numbers and dates.
@@ -1032,25 +1096,45 @@
10321096 <br />FTX = 4 # text
10331097 </p></dd>
10341098 </dl>
1035-<h2><a id='xlrd.Name-class' name='xlrd.Name-class'>The Name Class</a></h2>
1099+<h2><a id='__init__.Name-class' name='__init__.Name-class'>The Name Class</a></h2>
10361100 <dl>
1037-<dt><b>Name</b> (class) [<a href='#xlrd.Name-class'>#</a>]</dt>
1101+<dt><b>Name</b> (class) [<a href='#__init__.Name-class'>#</a>]</dt>
10381102 <dd>
10391103 <p>Information relating to a named reference, formula, macro, etc.
1040-<br /> -- New in version 0.6.0
1041-<br /> -- <i>Name information is <b>not</b> extracted from files older than
1104+<br /> -- New in version 0.6.0
1105+<br /> -- <i>Name information is <b>not</b> extracted from files older than
10421106 Excel 5.0 (Book.biff_version &lt; 50)</i>
10431107 </p></dd>
1044-<dt><a id='xlrd.Name.binary-attribute' name='xlrd.Name.binary-attribute'><b>binary</b></a> [<a href='#xlrd.Name.binary-attribute'>#</a>]</dt>
1108+<dt><a id='__init__.Name.area2d-method' name='__init__.Name.area2d-method'><b>area2d(clipped=True)</b></a> [<a href='#__init__.Name.area2d-method'>#</a>]</dt>
10451109 <dd>
1046-<p>0 = Formula definition; 1 = Binary data<br /> <i>No examples have been sighted.</i>
1110+<p>This is a convenience method for the use case where the name
1111+refers to one rectangular area in one worksheet.</p>
1112+<dl>
1113+<dt><i>clipped</i></dt>
1114+<dd>
1115+If true (the default), the returned rectangle is clipped
1116+to fit in (0, sheet.nrows, 0, sheet.ncols) -- it is guaranteed that
1117+0 &lt;= rowxlo &lt;= rowxhi &lt;= sheet.nrows and that the number of usable rows
1118+in the area (which may be zero) is rowxhi - rowxlo; likewise for columns.
1119+</dd>
1120+<dt>Returns:</dt>
1121+<dd>
1122+a tuple (sheet_object, rowxlo, rowxhi, colxlo, colxhi).</dd>
1123+<dt>Raises <b>XLRDError</b>:</dt><dd>
1124+The name is not a constant absolute reference
1125+to a single area in a single sheet.</dd>
1126+</dl><br />
1127+</dd>
1128+<dt><a id='__init__.Name.binary-attribute' name='__init__.Name.binary-attribute'><b>binary</b></a> [<a href='#__init__.Name.binary-attribute'>#</a>]</dt>
1129+<dd>
1130+<p>0 = Formula definition; 1 = Binary data<br /> <i>No examples have been sighted.</i>
10471131 </p></dd>
1048-<dt><a id='xlrd.Name.builtin-attribute' name='xlrd.Name.builtin-attribute'><b>builtin</b></a> [<a href='#xlrd.Name.builtin-attribute'>#</a>]</dt>
1132+<dt><a id='__init__.Name.builtin-attribute' name='__init__.Name.builtin-attribute'><b>builtin</b></a> [<a href='#__init__.Name.builtin-attribute'>#</a>]</dt>
10491133 <dd>
10501134 <p>0 = User-defined name; 1 = Built-in name
10511135 (common examples: Print_Area, Print_Titles; see OOo docs for full list)</p>
10521136 </dd>
1053-<dt><a id='xlrd.Name.cell-method' name='xlrd.Name.cell-method'><b>cell()</b></a> [<a href='#xlrd.Name.cell-method'>#</a>]</dt>
1137+<dt><a id='__init__.Name.cell-method' name='__init__.Name.cell-method'><b>cell()</b></a> [<a href='#__init__.Name.cell-method'>#</a>]</dt>
10541138 <dd>
10551139 <p>This is a convenience method for the frequent use case where the name
10561140 refers to a single cell.</p>
@@ -1063,40 +1147,40 @@
10631147 to a single cell.</dd>
10641148 </dl><br />
10651149 </dd>
1066-<dt><a id='xlrd.Name.complex-attribute' name='xlrd.Name.complex-attribute'><b>complex</b></a> [<a href='#xlrd.Name.complex-attribute'>#</a>]</dt>
1150+<dt><a id='__init__.Name.complex-attribute' name='__init__.Name.complex-attribute'><b>complex</b></a> [<a href='#__init__.Name.complex-attribute'>#</a>]</dt>
10671151 <dd>
10681152 <p>0 = Simple formula; 1 = Complex formula (array formula or user defined)<br />
10691153 <i>No examples have been sighted.</i>
10701154 </p></dd>
1071-<dt><a id='xlrd.Name.func-attribute' name='xlrd.Name.func-attribute'><b>func</b></a> [<a href='#xlrd.Name.func-attribute'>#</a>]</dt>
1155+<dt><a id='__init__.Name.func-attribute' name='__init__.Name.func-attribute'><b>func</b></a> [<a href='#__init__.Name.func-attribute'>#</a>]</dt>
10721156 <dd>
10731157 <p>0 = Command macro; 1 = Function macro. Relevant only if macro == 1</p>
10741158 </dd>
1075-<dt><a id='xlrd.Name.funcgroup-attribute' name='xlrd.Name.funcgroup-attribute'><b>funcgroup</b></a> [<a href='#xlrd.Name.funcgroup-attribute'>#</a>]</dt>
1159+<dt><a id='__init__.Name.funcgroup-attribute' name='__init__.Name.funcgroup-attribute'><b>funcgroup</b></a> [<a href='#__init__.Name.funcgroup-attribute'>#</a>]</dt>
10761160 <dd>
10771161 <p>Function group. Relevant only if macro == 1; see OOo docs for values.</p>
10781162 </dd>
1079-<dt><a id='xlrd.Name.hidden-attribute' name='xlrd.Name.hidden-attribute'><b>hidden</b></a> [<a href='#xlrd.Name.hidden-attribute'>#</a>]</dt>
1163+<dt><a id='__init__.Name.hidden-attribute' name='__init__.Name.hidden-attribute'><b>hidden</b></a> [<a href='#__init__.Name.hidden-attribute'>#</a>]</dt>
10801164 <dd>
10811165 <p>0 = Visible; 1 = Hidden</p>
10821166 </dd>
1083-<dt><a id='xlrd.Name.macro-attribute' name='xlrd.Name.macro-attribute'><b>macro</b></a> [<a href='#xlrd.Name.macro-attribute'>#</a>]</dt>
1167+<dt><a id='__init__.Name.macro-attribute' name='__init__.Name.macro-attribute'><b>macro</b></a> [<a href='#__init__.Name.macro-attribute'>#</a>]</dt>
10841168 <dd>
10851169 <p>0 = Standard name; 1 = Macro name</p>
10861170 </dd>
1087-<dt><a id='xlrd.Name.name-attribute' name='xlrd.Name.name-attribute'><b>name</b></a> [<a href='#xlrd.Name.name-attribute'>#</a>]</dt>
1171+<dt><a id='__init__.Name.name-attribute' name='__init__.Name.name-attribute'><b>name</b></a> [<a href='#__init__.Name.name-attribute'>#</a>]</dt>
10881172 <dd>
10891173 <p>A Unicode string. If builtin, decoded as per OOo docs.</p>
10901174 </dd>
1091-<dt><a id='xlrd.Name.name_index-attribute' name='xlrd.Name.name_index-attribute'><b>name_index</b></a> [<a href='#xlrd.Name.name_index-attribute'>#</a>]</dt>
1175+<dt><a id='__init__.Name.name_index-attribute' name='__init__.Name.name_index-attribute'><b>name_index</b></a> [<a href='#__init__.Name.name_index-attribute'>#</a>]</dt>
10921176 <dd>
10931177 <p>The index of this object in book.name_obj_list</p>
10941178 </dd>
1095-<dt><a id='xlrd.Name.raw_formula-attribute' name='xlrd.Name.raw_formula-attribute'><b>raw_formula</b></a> [<a href='#xlrd.Name.raw_formula-attribute'>#</a>]</dt>
1179+<dt><a id='__init__.Name.raw_formula-attribute' name='__init__.Name.raw_formula-attribute'><b>raw_formula</b></a> [<a href='#__init__.Name.raw_formula-attribute'>#</a>]</dt>
10961180 <dd>
10971181 <p>An 8-bit string.</p>
10981182 </dd>
1099-<dt><a id='xlrd.Name.result-attribute' name='xlrd.Name.result-attribute'><b>result</b></a> [<a href='#xlrd.Name.result-attribute'>#</a>]</dt>
1183+<dt><a id='__init__.Name.result-attribute' name='__init__.Name.result-attribute'><b>result</b></a> [<a href='#__init__.Name.result-attribute'>#</a>]</dt>
11001184 <dd>
11011185 <p>The result of evaluating the formula, if any.
11021186 If no formula, or evaluation of the formula encountered problems,
@@ -1103,7 +1187,7 @@
11031187 the result is None. Otherwise the result is a single instance of the
11041188 Operand class.</p>
11051189 </dd>
1106-<dt><a id='xlrd.Name.scope-attribute' name='xlrd.Name.scope-attribute'><b>scope</b></a> [<a href='#xlrd.Name.scope-attribute'>#</a>]</dt>
1190+<dt><a id='__init__.Name.scope-attribute' name='__init__.Name.scope-attribute'><b>scope</b></a> [<a href='#__init__.Name.scope-attribute'>#</a>]</dt>
11071191 <dd>
11081192 <p>-1: The name is global (visible in all calculation sheets).<br />
11091193 -2: The name belongs to a macro sheet or VBA sheet.<br />
@@ -1110,14 +1194,14 @@
11101194 -3: The name is invalid.<br />
11111195 0 &lt;= scope &lt; book.nsheets: The name is local to the sheet whose index is scope.
11121196 </p></dd>
1113-<dt><a id='xlrd.Name.vbasic-attribute' name='xlrd.Name.vbasic-attribute'><b>vbasic</b></a> [<a href='#xlrd.Name.vbasic-attribute'>#</a>]</dt>
1197+<dt><a id='__init__.Name.vbasic-attribute' name='__init__.Name.vbasic-attribute'><b>vbasic</b></a> [<a href='#__init__.Name.vbasic-attribute'>#</a>]</dt>
11141198 <dd>
11151199 <p>0 = Sheet macro; 1 = VisualBasic macro. Relevant only if macro == 1</p>
11161200 </dd>
11171201 </dl>
1118-<h2><a id='xlrd.Operand-class' name='xlrd.Operand-class'>The Operand Class</a></h2>
1202+<h2><a id='formula.Operand-class' name='formula.Operand-class'>The Operand Class</a></h2>
11191203 <dl>
1120-<dt><b>Operand(akind=None, avalue=None, arank=0, atext='?')</b> (class) [<a href='#xlrd.Operand-class'>#</a>]</dt>
1204+<dt><b>Operand(akind=None, avalue=None, arank=0, atext='?')</b> (class) [<a href='#formula.Operand-class'>#</a>]</dt>
11211205 <dd>
11221206 <p>Used in evaluating formulas.
11231207 The following table describes the kinds and how their values
@@ -1178,11 +1262,11 @@
11781262 </table>
11791263 <p />
11801264 </dd>
1181-<dt><a id='xlrd.Operand.kind-attribute' name='xlrd.Operand.kind-attribute'><b>kind</b></a> [<a href='#xlrd.Operand.kind-attribute'>#</a>]</dt>
1265+<dt><a id='formula.Operand.kind-attribute' name='formula.Operand.kind-attribute'><b>kind</b></a> [<a href='#formula.Operand.kind-attribute'>#</a>]</dt>
11821266 <dd>
11831267 <p>oUNK means that the kind of operand is not known unambiguously.</p>
11841268 </dd>
1185-<dt><a id='xlrd.Operand.text-attribute' name='xlrd.Operand.text-attribute'><b>text</b></a> [<a href='#xlrd.Operand.text-attribute'>#</a>]</dt>
1269+<dt><a id='formula.Operand.text-attribute' name='formula.Operand.text-attribute'><b>text</b></a> [<a href='#formula.Operand.text-attribute'>#</a>]</dt>
11861270 <dd>
11871271 <p>The reconstituted text of the original formula. Function names will be
11881272 in English irrespective of the original language, which doesn't seem
@@ -1189,15 +1273,15 @@
11891273 to be recorded anywhere. The separator is &quot;,&quot;, not &quot;;&quot; or whatever else
11901274 might be more appropriate for the end-user's locale; patches welcome.</p>
11911275 </dd>
1192-<dt><a id='xlrd.Operand.value-attribute' name='xlrd.Operand.value-attribute'><b>value</b></a> [<a href='#xlrd.Operand.value-attribute'>#</a>]</dt>
1276+<dt><a id='formula.Operand.value-attribute' name='formula.Operand.value-attribute'><b>value</b></a> [<a href='#formula.Operand.value-attribute'>#</a>]</dt>
11931277 <dd>
11941278 <p>None means that the actual value of the operand is a variable
11951279 (depends on cell data), not a constant.</p>
11961280 </dd>
11971281 </dl>
1198-<h2><a id='xlrd.Ref3D-class' name='xlrd.Ref3D-class'>The Ref3D Class</a></h2>
1282+<h2><a id='formula.Ref3D-class' name='formula.Ref3D-class'>The Ref3D Class</a></h2>
11991283 <dl>
1200-<dt><b>Ref3D(atuple)</b> (class) [<a href='#xlrd.Ref3D-class'>#</a>]</dt>
1284+<dt><b>Ref3D(atuple)</b> (class) [<a href='#formula.Ref3D-class'>#</a>]</dt>
12011285 <dd>
12021286 <p /><p>Represents an absolute or relative 3-dimensional reference to a box
12031287 of one or more cells.<br />
@@ -1232,15 +1316,15 @@
12321316 <br /> This will appear as coords = (0, 1, ...) and relflags = (1, 1, ...).
12331317 </p></dd>
12341318 </dl>
1235-<h2><a id='xlrd.Rowinfo-class' name='xlrd.Rowinfo-class'>The Rowinfo Class</a></h2>
1319+<h2><a id='sheet.Rowinfo-class' name='sheet.Rowinfo-class'>The Rowinfo Class</a></h2>
12361320 <dl>
1237-<dt><b>Rowinfo</b> (class) [<a href='#xlrd.Rowinfo-class'>#</a>]</dt>
1321+<dt><b>Rowinfo</b> (class) [<a href='#sheet.Rowinfo-class'>#</a>]</dt>
12381322 <dd>
12391323 <p>Height and default formatting information that applies to a row in a sheet.
12401324 Derived from ROW records.
12411325 <br /> -- New in version 0.6.1
12421326 </p></dd>
1243-<dt><a id='xlrd.Rowinfo.additional_space_above-attribute' name='xlrd.Rowinfo.additional_space_above-attribute'><b>additional_space_above</b></a> [<a href='#xlrd.Rowinfo.additional_space_above-attribute'>#</a>]</dt>
1327+<dt><a id='sheet.Rowinfo.additional_space_above-attribute' name='sheet.Rowinfo.additional_space_above-attribute'><b>additional_space_above</b></a> [<a href='#sheet.Rowinfo.additional_space_above-attribute'>#</a>]</dt>
12441328 <dd>
12451329 <p>This flag is set, if the upper border of at least one cell in this row
12461330 or if the lower border of at least one cell in the row above is
@@ -1247,7 +1331,7 @@
12471331 formatted with a thick line style. Thin and medium line styles are not
12481332 taken into account.</p>
12491333 </dd>
1250-<dt><a id='xlrd.Rowinfo.additional_space_below-attribute' name='xlrd.Rowinfo.additional_space_below-attribute'><b>additional_space_below</b></a> [<a href='#xlrd.Rowinfo.additional_space_below-attribute'>#</a>]</dt>
1334+<dt><a id='sheet.Rowinfo.additional_space_below-attribute' name='sheet.Rowinfo.additional_space_below-attribute'><b>additional_space_below</b></a> [<a href='#sheet.Rowinfo.additional_space_below-attribute'>#</a>]</dt>
12511335 <dd>
12521336 <p>This flag is set, if the lower border of at least one cell in this row
12531337 or if the upper border of at least one cell in the row below is
@@ -1254,45 +1338,45 @@
12541338 formatted with a medium or thick line style. Thin line styles are not
12551339 taken into account.</p>
12561340 </dd>
1257-<dt><a id='xlrd.Rowinfo.has_default_height-attribute' name='xlrd.Rowinfo.has_default_height-attribute'><b>has_default_height</b></a> [<a href='#xlrd.Rowinfo.has_default_height-attribute'>#</a>]</dt>
1341+<dt><a id='sheet.Rowinfo.has_default_height-attribute' name='sheet.Rowinfo.has_default_height-attribute'><b>has_default_height</b></a> [<a href='#sheet.Rowinfo.has_default_height-attribute'>#</a>]</dt>
12581342 <dd>
12591343 <p>0 = Row has custom height; 1 = Row has default height</p>
12601344 </dd>
1261-<dt><a id='xlrd.Rowinfo.has_default_xf_index-attribute' name='xlrd.Rowinfo.has_default_xf_index-attribute'><b>has_default_xf_index</b></a> [<a href='#xlrd.Rowinfo.has_default_xf_index-attribute'>#</a>]</dt>
1345+<dt><a id='sheet.Rowinfo.has_default_xf_index-attribute' name='sheet.Rowinfo.has_default_xf_index-attribute'><b>has_default_xf_index</b></a> [<a href='#sheet.Rowinfo.has_default_xf_index-attribute'>#</a>]</dt>
12621346 <dd>
12631347 <p>1 = the xf_index attribute is usable; 0 = ignore it</p>
12641348 </dd>
1265-<dt><a id='xlrd.Rowinfo.height-attribute' name='xlrd.Rowinfo.height-attribute'><b>height</b></a> [<a href='#xlrd.Rowinfo.height-attribute'>#</a>]</dt>
1349+<dt><a id='sheet.Rowinfo.height-attribute' name='sheet.Rowinfo.height-attribute'><b>height</b></a> [<a href='#sheet.Rowinfo.height-attribute'>#</a>]</dt>
12661350 <dd>
12671351 <p>Height of the row, in twips. One twip == 1/20 of a point</p>
12681352 </dd>
1269-<dt><a id='xlrd.Rowinfo.height_mismatch-attribute' name='xlrd.Rowinfo.height_mismatch-attribute'><b>height_mismatch</b></a> [<a href='#xlrd.Rowinfo.height_mismatch-attribute'>#</a>]</dt>
1353+<dt><a id='sheet.Rowinfo.height_mismatch-attribute' name='sheet.Rowinfo.height_mismatch-attribute'><b>height_mismatch</b></a> [<a href='#sheet.Rowinfo.height_mismatch-attribute'>#</a>]</dt>
12701354 <dd>
12711355 <p>1 = Row height and default font height do not match</p>
12721356 </dd>
1273-<dt><a id='xlrd.Rowinfo.hidden-attribute' name='xlrd.Rowinfo.hidden-attribute'><b>hidden</b></a> [<a href='#xlrd.Rowinfo.hidden-attribute'>#</a>]</dt>
1357+<dt><a id='sheet.Rowinfo.hidden-attribute' name='sheet.Rowinfo.hidden-attribute'><b>hidden</b></a> [<a href='#sheet.Rowinfo.hidden-attribute'>#</a>]</dt>
12741358 <dd>
12751359 <p>1 = Row is hidden (manually, or by a filter or outline group)</p>
12761360 </dd>
1277-<dt><a id='xlrd.Rowinfo.outline_group_starts_ends-attribute' name='xlrd.Rowinfo.outline_group_starts_ends-attribute'><b>outline_group_starts_ends</b></a> [<a href='#xlrd.Rowinfo.outline_group_starts_ends-attribute'>#</a>]</dt>
1361+<dt><a id='sheet.Rowinfo.outline_group_starts_ends-attribute' name='sheet.Rowinfo.outline_group_starts_ends-attribute'><b>outline_group_starts_ends</b></a> [<a href='#sheet.Rowinfo.outline_group_starts_ends-attribute'>#</a>]</dt>
12781362 <dd>
12791363 <p>1 = Outline group starts or ends here (depending on where the
12801364 outline buttons are located, see WSBOOL record [TODO ??]),
12811365 <i>and</i> is collapsed
12821366 </p></dd>
1283-<dt><a id='xlrd.Rowinfo.outline_level-attribute' name='xlrd.Rowinfo.outline_level-attribute'><b>outline_level</b></a> [<a href='#xlrd.Rowinfo.outline_level-attribute'>#</a>]</dt>
1367+<dt><a id='sheet.Rowinfo.outline_level-attribute' name='sheet.Rowinfo.outline_level-attribute'><b>outline_level</b></a> [<a href='#sheet.Rowinfo.outline_level-attribute'>#</a>]</dt>
12841368 <dd>
12851369 <p>Outline level of the row</p>
12861370 </dd>
1287-<dt><a id='xlrd.Rowinfo.xf_index-attribute' name='xlrd.Rowinfo.xf_index-attribute'><b>xf_index</b></a> [<a href='#xlrd.Rowinfo.xf_index-attribute'>#</a>]</dt>
1371+<dt><a id='sheet.Rowinfo.xf_index-attribute' name='sheet.Rowinfo.xf_index-attribute'><b>xf_index</b></a> [<a href='#sheet.Rowinfo.xf_index-attribute'>#</a>]</dt>
12881372 <dd>
12891373 <p>Index to default XF record for empty cells in this row.
12901374 Don't use this if has_default_xf_index == 0.</p>
12911375 </dd>
12921376 </dl>
1293-<h2><a id='xlrd.Sheet-class' name='xlrd.Sheet-class'>The Sheet Class</a></h2>
1377+<h2><a id='sheet.Sheet-class' name='sheet.Sheet-class'>The Sheet Class</a></h2>
12941378 <dl>
1295-<dt><b>Sheet(book, position, name, number)</b> (class) [<a href='#xlrd.Sheet-class'>#</a>]</dt>
1379+<dt><b>Sheet(book, position, name, number)</b> (class) [<a href='#sheet.Sheet-class'>#</a>]</dt>
12961380 <dd>
12971381 <p /><p>Contains the data for one worksheet.</p>
12981382
@@ -1305,30 +1389,30 @@
13051389 <p>WARNING: You don't call this class yourself. You access Sheet objects via the Book object that
13061390 was returned when you called xlrd.open_workbook("myfile.xls").</p>
13071391 </dd>
1308-<dt><a id='xlrd.Sheet.cell-method' name='xlrd.Sheet.cell-method'><b>cell(rowx, colx)</b></a> [<a href='#xlrd.Sheet.cell-method'>#</a>]</dt>
1392+<dt><a id='sheet.Sheet.cell-method' name='sheet.Sheet.cell-method'><b>cell(rowx, colx)</b></a> [<a href='#sheet.Sheet.cell-method'>#</a>]</dt>
13091393 <dd>
13101394 <p>Cell object in the given row and column.</p>
13111395 </dd>
1312-<dt><a id='xlrd.Sheet.cell_type-method' name='xlrd.Sheet.cell_type-method'><b>cell_type(rowx, colx)</b></a> [<a href='#xlrd.Sheet.cell_type-method'>#</a>]</dt>
1396+<dt><a id='sheet.Sheet.cell_type-method' name='sheet.Sheet.cell_type-method'><b>cell_type(rowx, colx)</b></a> [<a href='#sheet.Sheet.cell_type-method'>#</a>]</dt>
13131397 <dd>
13141398 <p>Type of the cell in the given row and column.
13151399 Refer to the documentation of the Cell class.</p>
13161400 </dd>
1317-<dt><a id='xlrd.Sheet.cell_value-method' name='xlrd.Sheet.cell_value-method'><b>cell_value(rowx, colx)</b></a> [<a href='#xlrd.Sheet.cell_value-method'>#</a>]</dt>
1401+<dt><a id='sheet.Sheet.cell_value-method' name='sheet.Sheet.cell_value-method'><b>cell_value(rowx, colx)</b></a> [<a href='#sheet.Sheet.cell_value-method'>#</a>]</dt>
13181402 <dd>
13191403 <p>Value of the cell in the given row and column.</p>
13201404 </dd>
1321-<dt><a id='xlrd.Sheet.cell_xf_index-method' name='xlrd.Sheet.cell_xf_index-method'><b>cell_xf_index(rowx, colx)</b></a> [<a href='#xlrd.Sheet.cell_xf_index-method'>#</a>]</dt>
1405+<dt><a id='sheet.Sheet.cell_xf_index-method' name='sheet.Sheet.cell_xf_index-method'><b>cell_xf_index(rowx, colx)</b></a> [<a href='#sheet.Sheet.cell_xf_index-method'>#</a>]</dt>
13221406 <dd>
13231407 <p>XF index of the cell in the given row and column.
1324-This is an index into Book.raw_xf_list and Book.computed_xf_list.
1408+This is an index into Book.xf_list.
13251409 <br /> -- New in version 0.6.1
13261410 </p></dd>
1327-<dt><a id='xlrd.Sheet.col-method' name='xlrd.Sheet.col-method'><b>col(colx)</b></a> [<a href='#xlrd.Sheet.col-method'>#</a>]</dt>
1411+<dt><a id='sheet.Sheet.col-method' name='sheet.Sheet.col-method'><b>col(colx)</b></a> [<a href='#sheet.Sheet.col-method'>#</a>]</dt>
13281412 <dd>
13291413 <p>Returns a sequence of the Cell objects in the given column.</p>
13301414 </dd>
1331-<dt><a id='xlrd.Sheet.col_label_ranges-attribute' name='xlrd.Sheet.col_label_ranges-attribute'><b>col_label_ranges</b></a> [<a href='#xlrd.Sheet.col_label_ranges-attribute'>#</a>]</dt>
1415+<dt><a id='sheet.Sheet.col_label_ranges-attribute' name='sheet.Sheet.col_label_ranges-attribute'><b>col_label_ranges</b></a> [<a href='#sheet.Sheet.col_label_ranges-attribute'>#</a>]</dt>
13321416 <dd>
13331417 <p>List of address ranges of cells containing column labels.
13341418 These are set up in Excel by Insert &gt; Name &gt; Labels &gt; Columns.
@@ -1343,19 +1427,19 @@
13431427 (rx, cx, thesheet.cell_value(rx, cx))
13441428 </pre>
13451429 </p></dd>
1346-<dt><a id='xlrd.Sheet.col_slice-method' name='xlrd.Sheet.col_slice-method'><b>col_slice(colx, start_rowx=0, end_rowx=None)</b></a> [<a href='#xlrd.Sheet.col_slice-method'>#</a>]</dt>
1430+<dt><a id='sheet.Sheet.col_slice-method' name='sheet.Sheet.col_slice-method'><b>col_slice(colx, start_rowx=0, end_rowx=None)</b></a> [<a href='#sheet.Sheet.col_slice-method'>#</a>]</dt>
13471431 <dd>
13481432 <p>Returns a slice of the Cell objects in the given column.</p>
13491433 </dd>
1350-<dt><a id='xlrd.Sheet.col_types-method' name='xlrd.Sheet.col_types-method'><b>col_types(colx, start_rowx=0, end_rowx=None)</b></a> [<a href='#xlrd.Sheet.col_types-method'>#</a>]</dt>
1434+<dt><a id='sheet.Sheet.col_types-method' name='sheet.Sheet.col_types-method'><b>col_types(colx, start_rowx=0, end_rowx=None)</b></a> [<a href='#sheet.Sheet.col_types-method'>#</a>]</dt>
13511435 <dd>
13521436 <p>Returns a slice of the types of the cells in the given column.</p>
13531437 </dd>
1354-<dt><a id='xlrd.Sheet.col_values-method' name='xlrd.Sheet.col_values-method'><b>col_values(colx, start_rowx=0, end_rowx=None)</b></a> [<a href='#xlrd.Sheet.col_values-method'>#</a>]</dt>
1438+<dt><a id='sheet.Sheet.col_values-method' name='sheet.Sheet.col_values-method'><b>col_values(colx, start_rowx=0, end_rowx=None)</b></a> [<a href='#sheet.Sheet.col_values-method'>#</a>]</dt>
13551439 <dd>
13561440 <p>Returns a slice of the values of the cells in the given column.</p>
13571441 </dd>
1358-<dt><a id='xlrd.Sheet.colinfo_map-attribute' name='xlrd.Sheet.colinfo_map-attribute'><b>colinfo_map</b></a> [<a href='#xlrd.Sheet.colinfo_map-attribute'>#</a>]</dt>
1442+<dt><a id='sheet.Sheet.colinfo_map-attribute' name='sheet.Sheet.colinfo_map-attribute'><b>colinfo_map</b></a> [<a href='#sheet.Sheet.colinfo_map-attribute'>#</a>]</dt>
13591443 <dd>
13601444 <p>The map from a column index to a Colinfo object. Often there is an entry
13611445 in COLINFO records for all column indexes in range(257).
@@ -1363,7 +1447,7 @@
13631447 257th column. On the other hand, there may be no entry for unused columns.
13641448 <br /> -- New in version 0.6.1
13651449 </p></dd>
1366-<dt><a id='xlrd.Sheet.computed_column_width-method' name='xlrd.Sheet.computed_column_width-method'><b>computed_column_width(colx)</b></a> [<a href='#xlrd.Sheet.computed_column_width-method'>#</a>]</dt>
1450+<dt><a id='sheet.Sheet.computed_column_width-method' name='sheet.Sheet.computed_column_width-method'><b>computed_column_width(colx)</b></a> [<a href='#sheet.Sheet.computed_column_width-method'>#</a>]</dt>
13671451 <dd>
13681452 <p>Determine column display width.
13691453 <br /> -- New in version 0.6.1
@@ -1381,37 +1465,37 @@
13811465 standard character (the digit zero in the first font).</dd>
13821466 </dl><br />
13831467 </dd>
1384-<dt><a id='xlrd.Sheet.default_additional_space_above-attribute' name='xlrd.Sheet.default_additional_space_above-attribute'><b>default_additional_space_above</b></a> [<a href='#xlrd.Sheet.default_additional_space_above-attribute'>#</a>]</dt>
1468+<dt><a id='sheet.Sheet.default_additional_space_above-attribute' name='sheet.Sheet.default_additional_space_above-attribute'><b>default_additional_space_above</b></a> [<a href='#sheet.Sheet.default_additional_space_above-attribute'>#</a>]</dt>
13851469 <dd>
13861470 <p>Default value to be used for a row if there is
13871471 no ROW record for that row.
13881472 From the <i>optional</i> DEFAULTROWHEIGHT record.
13891473 </p></dd>
1390-<dt><a id='xlrd.Sheet.default_additional_space_below-attribute' name='xlrd.Sheet.default_additional_space_below-attribute'><b>default_additional_space_below</b></a> [<a href='#xlrd.Sheet.default_additional_space_below-attribute'>#</a>]</dt>
1474+<dt><a id='sheet.Sheet.default_additional_space_below-attribute' name='sheet.Sheet.default_additional_space_below-attribute'><b>default_additional_space_below</b></a> [<a href='#sheet.Sheet.default_additional_space_below-attribute'>#</a>]</dt>
13911475 <dd>
13921476 <p>Default value to be used for a row if there is
13931477 no ROW record for that row.
13941478 From the <i>optional</i> DEFAULTROWHEIGHT record.
13951479 </p></dd>
1396-<dt><a id='xlrd.Sheet.default_row_height-attribute' name='xlrd.Sheet.default_row_height-attribute'><b>default_row_height</b></a> [<a href='#xlrd.Sheet.default_row_height-attribute'>#</a>]</dt>
1480+<dt><a id='sheet.Sheet.default_row_height-attribute' name='sheet.Sheet.default_row_height-attribute'><b>default_row_height</b></a> [<a href='#sheet.Sheet.default_row_height-attribute'>#</a>]</dt>
13971481 <dd>
13981482 <p>Default value to be used for a row if there is
13991483 no ROW record for that row.
14001484 From the <i>optional</i> DEFAULTROWHEIGHT record.
14011485 </p></dd>
1402-<dt><a id='xlrd.Sheet.default_row_height_mismatch-attribute' name='xlrd.Sheet.default_row_height_mismatch-attribute'><b>default_row_height_mismatch</b></a> [<a href='#xlrd.Sheet.default_row_height_mismatch-attribute'>#</a>]</dt>
1486+<dt><a id='sheet.Sheet.default_row_height_mismatch-attribute' name='sheet.Sheet.default_row_height_mismatch-attribute'><b>default_row_height_mismatch</b></a> [<a href='#sheet.Sheet.default_row_height_mismatch-attribute'>#</a>]</dt>
14031487 <dd>
14041488 <p>Default value to be used for a row if there is
14051489 no ROW record for that row.
14061490 From the <i>optional</i> DEFAULTROWHEIGHT record.
14071491 </p></dd>
1408-<dt><a id='xlrd.Sheet.default_row_hidden-attribute' name='xlrd.Sheet.default_row_hidden-attribute'><b>default_row_hidden</b></a> [<a href='#xlrd.Sheet.default_row_hidden-attribute'>#</a>]</dt>
1492+<dt><a id='sheet.Sheet.default_row_hidden-attribute' name='sheet.Sheet.default_row_hidden-attribute'><b>default_row_hidden</b></a> [<a href='#sheet.Sheet.default_row_hidden-attribute'>#</a>]</dt>
14091493 <dd>
14101494 <p>Default value to be used for a row if there is
14111495 no ROW record for that row.
14121496 From the <i>optional</i> DEFAULTROWHEIGHT record.
14131497 </p></dd>
1414-<dt><a id='xlrd.Sheet.defcolwidth-attribute' name='xlrd.Sheet.defcolwidth-attribute'><b>defcolwidth</b></a> [<a href='#xlrd.Sheet.defcolwidth-attribute'>#</a>]</dt>
1498+<dt><a id='sheet.Sheet.defcolwidth-attribute' name='sheet.Sheet.defcolwidth-attribute'><b>defcolwidth</b></a> [<a href='#sheet.Sheet.defcolwidth-attribute'>#</a>]</dt>
14151499 <dd>
14161500 <p>Default column width from DEFCOLWIDTH record, else None.
14171501 From the OOo docs:<br />
@@ -1425,18 +1509,18 @@
14251509 For the default hierarchy, refer to the Colinfo class above.
14261510 <br /> -- New in version 0.6.1
14271511 </p></dd>
1428-<dt><a id='xlrd.Sheet.gcw-attribute' name='xlrd.Sheet.gcw-attribute'><b>gcw</b></a> [<a href='#xlrd.Sheet.gcw-attribute'>#</a>]</dt>
1512+<dt><a id='sheet.Sheet.gcw-attribute' name='sheet.Sheet.gcw-attribute'><b>gcw</b></a> [<a href='#sheet.Sheet.gcw-attribute'>#</a>]</dt>
14291513 <dd>
14301514 <p>A 256-element tuple corresponding to the contents of the GCW record for this sheet.
14311515 If no such record, treat as all bits zero.
14321516 Applies to BIFF4-7 only. See docs of Colinfo class for discussion.</p>
14331517 </dd>
1434-<dt><a id='xlrd.Sheet.merged_cells-attribute' name='xlrd.Sheet.merged_cells-attribute'><b>merged_cells</b></a> [<a href='#xlrd.Sheet.merged_cells-attribute'>#</a>]</dt>
1518+<dt><a id='sheet.Sheet.merged_cells-attribute' name='sheet.Sheet.merged_cells-attribute'><b>merged_cells</b></a> [<a href='#sheet.Sheet.merged_cells-attribute'>#</a>]</dt>
14351519 <dd>
14361520 <p>List of address ranges of cells which have been merged.
14371521 These are set up in Excel by Format &gt; Cells &gt; Alignment, then ticking
14381522 the "Merge cells" box.
1439-<br /> -- New in version 0.6.1
1523+<br /> -- New in version 0.6.1. Extracted only if open_workbook(..., formatting_info=True)
14401524 <br />How to deconstruct the list:
14411525 <pre>
14421526 for crange in thesheet.merged_cells:
@@ -1450,43 +1534,43 @@
14501534 # the range.
14511535 </pre>
14521536 </p></dd>
1453-<dt><a id='xlrd.Sheet.name-attribute' name='xlrd.Sheet.name-attribute'><b>name</b></a> [<a href='#xlrd.Sheet.name-attribute'>#</a>]</dt>
1537+<dt><a id='sheet.Sheet.name-attribute' name='sheet.Sheet.name-attribute'><b>name</b></a> [<a href='#sheet.Sheet.name-attribute'>#</a>]</dt>
14541538 <dd>
14551539 <p>Name of sheet.</p>
14561540 </dd>
1457-<dt><a id='xlrd.Sheet.ncols-attribute' name='xlrd.Sheet.ncols-attribute'><b>ncols</b></a> [<a href='#xlrd.Sheet.ncols-attribute'>#</a>]</dt>
1541+<dt><a id='sheet.Sheet.ncols-attribute' name='sheet.Sheet.ncols-attribute'><b>ncols</b></a> [<a href='#sheet.Sheet.ncols-attribute'>#</a>]</dt>
14581542 <dd>
14591543 <p>Number of columns in sheet. A column index is in range(thesheet.ncols).</p>
14601544 </dd>
1461-<dt><a id='xlrd.Sheet.nrows-attribute' name='xlrd.Sheet.nrows-attribute'><b>nrows</b></a> [<a href='#xlrd.Sheet.nrows-attribute'>#</a>]</dt>
1545+<dt><a id='sheet.Sheet.nrows-attribute' name='sheet.Sheet.nrows-attribute'><b>nrows</b></a> [<a href='#sheet.Sheet.nrows-attribute'>#</a>]</dt>
14621546 <dd>
14631547 <p>Number of rows in sheet. A row index is in range(thesheet.nrows).</p>
14641548 </dd>
1465-<dt><a id='xlrd.Sheet.row-method' name='xlrd.Sheet.row-method'><b>row(rowx)</b></a> [<a href='#xlrd.Sheet.row-method'>#</a>]</dt>
1549+<dt><a id='sheet.Sheet.row-method' name='sheet.Sheet.row-method'><b>row(rowx)</b></a> [<a href='#sheet.Sheet.row-method'>#</a>]</dt>
14661550 <dd>
14671551 <p>Returns a sequence of the Cell objects in the given row.</p>
14681552 </dd>
1469-<dt><a id='xlrd.Sheet.row_label_ranges-attribute' name='xlrd.Sheet.row_label_ranges-attribute'><b>row_label_ranges</b></a> [<a href='#xlrd.Sheet.row_label_ranges-attribute'>#</a>]</dt>
1553+<dt><a id='sheet.Sheet.row_label_ranges-attribute' name='sheet.Sheet.row_label_ranges-attribute'><b>row_label_ranges</b></a> [<a href='#sheet.Sheet.row_label_ranges-attribute'>#</a>]</dt>
14701554 <dd>
14711555 <p>List of address ranges of cells containing row labels.
14721556 For more details, see <i>col_label_ranges</i> above.
14731557 <br /> -- New in version 0.6.0
14741558 </p></dd>
1475-<dt><a id='xlrd.Sheet.row_slice-method' name='xlrd.Sheet.row_slice-method'><b>row_slice(rowx, start_colx=0, end_colx=None)</b></a> [<a href='#xlrd.Sheet.row_slice-method'>#</a>]</dt>
1559+<dt><a id='sheet.Sheet.row_slice-method' name='sheet.Sheet.row_slice-method'><b>row_slice(rowx, start_colx=0, end_colx=None)</b></a> [<a href='#sheet.Sheet.row_slice-method'>#</a>]</dt>
14761560 <dd>
14771561 <p>Returns a slice of the Cell objects in the given row.</p>
14781562 </dd>
1479-<dt><a id='xlrd.Sheet.row_types-method' name='xlrd.Sheet.row_types-method'><b>row_types(rowx, start_colx=0, end_colx=None)</b></a> [<a href='#xlrd.Sheet.row_types-method'>#</a>]</dt>
1563+<dt><a id='sheet.Sheet.row_types-method' name='sheet.Sheet.row_types-method'><b>row_types(rowx, start_colx=0, end_colx=None)</b></a> [<a href='#sheet.Sheet.row_types-method'>#</a>]</dt>
14801564 <dd>
14811565 <p>Returns a slice of the types
14821566 of the cells in the given row.</p>
14831567 </dd>
1484-<dt><a id='xlrd.Sheet.row_values-method' name='xlrd.Sheet.row_values-method'><b>row_values(rowx, start_colx=0, end_colx=None)</b></a> [<a href='#xlrd.Sheet.row_values-method'>#</a>]</dt>
1568+<dt><a id='sheet.Sheet.row_values-method' name='sheet.Sheet.row_values-method'><b>row_values(rowx, start_colx=0, end_colx=None)</b></a> [<a href='#sheet.Sheet.row_values-method'>#</a>]</dt>
14851569 <dd>
14861570 <p>Returns a slice of the values
14871571 of the cells in the given row.</p>
14881572 </dd>
1489-<dt><a id='xlrd.Sheet.rowinfo_map-attribute' name='xlrd.Sheet.rowinfo_map-attribute'><b>rowinfo_map</b></a> [<a href='#xlrd.Sheet.rowinfo_map-attribute'>#</a>]</dt>
1573+<dt><a id='sheet.Sheet.rowinfo_map-attribute' name='sheet.Sheet.rowinfo_map-attribute'><b>rowinfo_map</b></a> [<a href='#sheet.Sheet.rowinfo_map-attribute'>#</a>]</dt>
14901574 <dd>
14911575 <p>The map from a row index to a Rowinfo object. Note that it is possible
14921576 to have missing entries -- at least one source of XLS files doesn't
@@ -1493,7 +1577,7 @@
14931577 bother writing ROW records.
14941578 <br /> -- New in version 0.6.1
14951579 </p></dd>
1496-<dt><a id='xlrd.Sheet.standardwidth-attribute' name='xlrd.Sheet.standardwidth-attribute'><b>standardwidth</b></a> [<a href='#xlrd.Sheet.standardwidth-attribute'>#</a>]</dt>
1580+<dt><a id='sheet.Sheet.standardwidth-attribute' name='sheet.Sheet.standardwidth-attribute'><b>standardwidth</b></a> [<a href='#sheet.Sheet.standardwidth-attribute'>#</a>]</dt>
14971581 <dd>
14981582 <p>Default column width from STANDARDWIDTH record, else None.
14991583 From the OOo docs:<br />
@@ -1502,7 +1586,7 @@
15021586 For the default hierarchy, refer to the Colinfo class above.
15031587 <br /> -- New in version 0.6.1
15041588 </p></dd>
1505-<dt><a id='xlrd.Sheet.visibility-attribute' name='xlrd.Sheet.visibility-attribute'><b>visibility</b></a> [<a href='#xlrd.Sheet.visibility-attribute'>#</a>]</dt>
1589+<dt><a id='sheet.Sheet.visibility-attribute' name='sheet.Sheet.visibility-attribute'><b>visibility</b></a> [<a href='#sheet.Sheet.visibility-attribute'>#</a>]</dt>
15061590 <dd>
15071591 <p>Visibility of the sheet. 0 = visible, 1 = hidden (can be unhidden
15081592 by user -- Format/Sheet/Unhide), 2 = &quot;very hidden&quot; (can be unhidden
@@ -1509,9 +1593,9 @@
15091593 only by VBA macro).</p>
15101594 </dd>
15111595 </dl>
1512-<h2><a id='xlrd.XF-class' name='xlrd.XF-class'>The XF Class</a></h2>
1596+<h2><a id='formatting.XF-class' name='formatting.XF-class'>The XF Class</a></h2>
15131597 <dl>
1514-<dt><b>XF</b> (class) [<a href='#xlrd.XF-class'>#</a>]</dt>
1598+<dt><b>XF</b> (class) [<a href='#formatting.XF-class'>#</a>]</dt>
15151599 <dd>
15161600 <p>eXtended Formatting information for cells, rows, columns and styles.
15171601 <br /> -- New in version 0.6.1
@@ -1529,42 +1613,42 @@
15291613 have had the above inheritance mechanism applied.
15301614 </p>
15311615 </dd>
1532-<dt><a id='xlrd.XF._alignment_flag-attribute' name='xlrd.XF._alignment_flag-attribute'><b>_alignment_flag</b></a> [<a href='#xlrd.XF._alignment_flag-attribute'>#</a>]</dt>
1616+<dt><a id='formatting.XF._alignment_flag-attribute' name='formatting.XF._alignment_flag-attribute'><b>_alignment_flag</b></a> [<a href='#formatting.XF._alignment_flag-attribute'>#</a>]</dt>
15331617 <dd>
15341618 </dd>
1535-<dt><a id='xlrd.XF._background_flag-attribute' name='xlrd.XF._background_flag-attribute'><b>_background_flag</b></a> [<a href='#xlrd.XF._background_flag-attribute'>#</a>]</dt>
1619+<dt><a id='formatting.XF._background_flag-attribute' name='formatting.XF._background_flag-attribute'><b>_background_flag</b></a> [<a href='#formatting.XF._background_flag-attribute'>#</a>]</dt>
15361620 <dd>
15371621 </dd>
1538-<dt><a id='xlrd.XF._border_flag-attribute' name='xlrd.XF._border_flag-attribute'><b>_border_flag</b></a> [<a href='#xlrd.XF._border_flag-attribute'>#</a>]</dt>
1622+<dt><a id='formatting.XF._border_flag-attribute' name='formatting.XF._border_flag-attribute'><b>_border_flag</b></a> [<a href='#formatting.XF._border_flag-attribute'>#</a>]</dt>
15391623 <dd>
15401624 </dd>
1541-<dt><a id='xlrd.XF._font_flag-attribute' name='xlrd.XF._font_flag-attribute'><b>_font_flag</b></a> [<a href='#xlrd.XF._font_flag-attribute'>#</a>]</dt>
1625+<dt><a id='formatting.XF._font_flag-attribute' name='formatting.XF._font_flag-attribute'><b>_font_flag</b></a> [<a href='#formatting.XF._font_flag-attribute'>#</a>]</dt>
15421626 <dd>
15431627 </dd>
1544-<dt><a id='xlrd.XF._format_flag-attribute' name='xlrd.XF._format_flag-attribute'><b>_format_flag</b></a> [<a href='#xlrd.XF._format_flag-attribute'>#</a>]</dt>
1628+<dt><a id='formatting.XF._format_flag-attribute' name='formatting.XF._format_flag-attribute'><b>_format_flag</b></a> [<a href='#formatting.XF._format_flag-attribute'>#</a>]</dt>
15451629 <dd>
15461630 </dd>
1547-<dt><a id='xlrd.XF._protection_flag-attribute' name='xlrd.XF._protection_flag-attribute'><b>_protection_flag</b></a> [<a href='#xlrd.XF._protection_flag-attribute'>#</a>]</dt>
1631+<dt><a id='formatting.XF._protection_flag-attribute' name='formatting.XF._protection_flag-attribute'><b>_protection_flag</b></a> [<a href='#formatting.XF._protection_flag-attribute'>#</a>]</dt>
15481632 <dd>
15491633 <p>&#160;
15501634 </p></dd>
1551-<dt><a id='xlrd.XF.alignment-attribute' name='xlrd.XF.alignment-attribute'><b>alignment</b></a> [<a href='#xlrd.XF.alignment-attribute'>#</a>]</dt>
1635+<dt><a id='formatting.XF.alignment-attribute' name='formatting.XF.alignment-attribute'><b>alignment</b></a> [<a href='#formatting.XF.alignment-attribute'>#</a>]</dt>
15521636 <dd>
15531637 <p>An instance of an XFAlignment object.</p>
15541638 </dd>
1555-<dt><a id='xlrd.XF.background-attribute' name='xlrd.XF.background-attribute'><b>background</b></a> [<a href='#xlrd.XF.background-attribute'>#</a>]</dt>
1639+<dt><a id='formatting.XF.background-attribute' name='formatting.XF.background-attribute'><b>background</b></a> [<a href='#formatting.XF.background-attribute'>#</a>]</dt>
15561640 <dd>
15571641 <p>An instance of an XFBackground object.</p>
15581642 </dd>
1559-<dt><a id='xlrd.XF.border-attribute' name='xlrd.XF.border-attribute'><b>border</b></a> [<a href='#xlrd.XF.border-attribute'>#</a>]</dt>
1643+<dt><a id='formatting.XF.border-attribute' name='formatting.XF.border-attribute'><b>border</b></a> [<a href='#formatting.XF.border-attribute'>#</a>]</dt>
15601644 <dd>
15611645 <p>An instance of an XFBorder object.</p>
15621646 </dd>
1563-<dt><a id='xlrd.XF.font_index-attribute' name='xlrd.XF.font_index-attribute'><b>font_index</b></a> [<a href='#xlrd.XF.font_index-attribute'>#</a>]</dt>
1647+<dt><a id='formatting.XF.font_index-attribute' name='formatting.XF.font_index-attribute'><b>font_index</b></a> [<a href='#formatting.XF.font_index-attribute'>#</a>]</dt>
15641648 <dd>
15651649 <p>Index into Book.font_list</p>
15661650 </dd>
1567-<dt><a id='xlrd.XF.format_key-attribute' name='xlrd.XF.format_key-attribute'><b>format_key</b></a> [<a href='#xlrd.XF.format_key-attribute'>#</a>]</dt>
1651+<dt><a id='formatting.XF.format_key-attribute' name='formatting.XF.format_key-attribute'><b>format_key</b></a> [<a href='#formatting.XF.format_key-attribute'>#</a>]</dt>
15681652 <dd>
15691653 <p>Key into Book.format_map
15701654 </p><p>
@@ -1576,42 +1660,42 @@
15761660 if the index is less than 164.
15771661 </p>
15781662 </dd>
1579-<dt><a id='xlrd.XF.is_style-attribute' name='xlrd.XF.is_style-attribute'><b>is_style</b></a> [<a href='#xlrd.XF.is_style-attribute'>#</a>]</dt>
1663+<dt><a id='formatting.XF.is_style-attribute' name='formatting.XF.is_style-attribute'><b>is_style</b></a> [<a href='#formatting.XF.is_style-attribute'>#</a>]</dt>
15801664 <dd>
15811665 <p>0 = cell XF, 1 = style XF</p>
15821666 </dd>
1583-<dt><a id='xlrd.XF.parent_style_index-attribute' name='xlrd.XF.parent_style_index-attribute'><b>parent_style_index</b></a> [<a href='#xlrd.XF.parent_style_index-attribute'>#</a>]</dt>
1667+<dt><a id='formatting.XF.parent_style_index-attribute' name='formatting.XF.parent_style_index-attribute'><b>parent_style_index</b></a> [<a href='#formatting.XF.parent_style_index-attribute'>#</a>]</dt>
15841668 <dd>
15851669 <p>cell XF: Index into Book.xf_list
15861670 of this XF's style XF<br />
15871671 style XF: 0xFFF
15881672 </p></dd>
1589-<dt><a id='xlrd.XF.protection-attribute' name='xlrd.XF.protection-attribute'><b>protection</b></a> [<a href='#xlrd.XF.protection-attribute'>#</a>]</dt>
1673+<dt><a id='formatting.XF.protection-attribute' name='formatting.XF.protection-attribute'><b>protection</b></a> [<a href='#formatting.XF.protection-attribute'>#</a>]</dt>
15901674 <dd>
15911675 <p>An instance of an XFProtection object.</p>
15921676 </dd>
1593-<dt><a id='xlrd.XF.xf_index-attribute' name='xlrd.XF.xf_index-attribute'><b>xf_index</b></a> [<a href='#xlrd.XF.xf_index-attribute'>#</a>]</dt>
1677+<dt><a id='formatting.XF.xf_index-attribute' name='formatting.XF.xf_index-attribute'><b>xf_index</b></a> [<a href='#formatting.XF.xf_index-attribute'>#</a>]</dt>
15941678 <dd>
15951679 <p>Index into Book.xf_list</p>
15961680 </dd>
15971681 </dl>
1598-<h2><a id='xlrd.XFAlignment-class' name='xlrd.XFAlignment-class'>The XFAlignment Class</a></h2>
1682+<h2><a id='formatting.XFAlignment-class' name='formatting.XFAlignment-class'>The XFAlignment Class</a></h2>
15991683 <dl>
1600-<dt><b>XFAlignment</b> (class) [<a href='#xlrd.XFAlignment-class'>#</a>]</dt>
1684+<dt><b>XFAlignment</b> (class) [<a href='#formatting.XFAlignment-class'>#</a>]</dt>
16011685 <dd>
16021686 <p>A collection of the alignment and similar attributes of an XF record.
16031687 Items correspond to those in the Excel UI's Format/Cells/Alignment tab.
16041688 <br /> -- New in version 0.6.1
16051689 </p></dd>
1606-<dt><a id='xlrd.XFAlignment.hor_align-attribute' name='xlrd.XFAlignment.hor_align-attribute'><b>hor_align</b></a> [<a href='#xlrd.XFAlignment.hor_align-attribute'>#</a>]</dt>
1690+<dt><a id='formatting.XFAlignment.hor_align-attribute' name='formatting.XFAlignment.hor_align-attribute'><b>hor_align</b></a> [<a href='#formatting.XFAlignment.hor_align-attribute'>#</a>]</dt>
16071691 <dd>
16081692 <p>Values: section 6.115 (p 214) of OOo docs</p>
16091693 </dd>
1610-<dt><a id='xlrd.XFAlignment.indent_level-attribute' name='xlrd.XFAlignment.indent_level-attribute'><b>indent_level</b></a> [<a href='#xlrd.XFAlignment.indent_level-attribute'>#</a>]</dt>
1694+<dt><a id='formatting.XFAlignment.indent_level-attribute' name='formatting.XFAlignment.indent_level-attribute'><b>indent_level</b></a> [<a href='#formatting.XFAlignment.indent_level-attribute'>#</a>]</dt>
16111695 <dd>
16121696 <p>A number in range(15).</p>
16131697 </dd>
1614-<dt><a id='xlrd.XFAlignment.rotation-attribute' name='xlrd.XFAlignment.rotation-attribute'><b>rotation</b></a> [<a href='#xlrd.XFAlignment.rotation-attribute'>#</a>]</dt>
1698+<dt><a id='formatting.XFAlignment.rotation-attribute' name='formatting.XFAlignment.rotation-attribute'><b>rotation</b></a> [<a href='#formatting.XFAlignment.rotation-attribute'>#</a>]</dt>
16151699 <dd>
16161700 <p>Values: section 6.115 (p 215) of OOo docs.<br />
16171701 Note: file versions BIFF7 and earlier use the documented
@@ -1618,26 +1702,26 @@
16181702 "orientation" attribute; this will be mapped (without loss)
16191703 into "rotation".
16201704 </p></dd>
1621-<dt><a id='xlrd.XFAlignment.shrink_to_fit-attribute' name='xlrd.XFAlignment.shrink_to_fit-attribute'><b>shrink_to_fit</b></a> [<a href='#xlrd.XFAlignment.shrink_to_fit-attribute'>#</a>]</dt>
1705+<dt><a id='formatting.XFAlignment.shrink_to_fit-attribute' name='formatting.XFAlignment.shrink_to_fit-attribute'><b>shrink_to_fit</b></a> [<a href='#formatting.XFAlignment.shrink_to_fit-attribute'>#</a>]</dt>
16221706 <dd>
16231707 <p>1 = shrink font size to fit text into cell.</p>
16241708 </dd>
1625-<dt><a id='xlrd.XFAlignment.text_direction-attribute' name='xlrd.XFAlignment.text_direction-attribute'><b>text_direction</b></a> [<a href='#xlrd.XFAlignment.text_direction-attribute'>#</a>]</dt>
1709+<dt><a id='formatting.XFAlignment.text_direction-attribute' name='formatting.XFAlignment.text_direction-attribute'><b>text_direction</b></a> [<a href='#formatting.XFAlignment.text_direction-attribute'>#</a>]</dt>
16261710 <dd>
16271711 <p>0 = according to context; 1 = left-to-right; 2 = right-to-left</p>
16281712 </dd>
1629-<dt><a id='xlrd.XFAlignment.text_wrapped-attribute' name='xlrd.XFAlignment.text_wrapped-attribute'><b>text_wrapped</b></a> [<a href='#xlrd.XFAlignment.text_wrapped-attribute'>#</a>]</dt>
1713+<dt><a id='formatting.XFAlignment.text_wrapped-attribute' name='formatting.XFAlignment.text_wrapped-attribute'><b>text_wrapped</b></a> [<a href='#formatting.XFAlignment.text_wrapped-attribute'>#</a>]</dt>
16301714 <dd>
16311715 <p>1 = text is wrapped at right margin</p>
16321716 </dd>
1633-<dt><a id='xlrd.XFAlignment.vert_align-attribute' name='xlrd.XFAlignment.vert_align-attribute'><b>vert_align</b></a> [<a href='#xlrd.XFAlignment.vert_align-attribute'>#</a>]</dt>
1717+<dt><a id='formatting.XFAlignment.vert_align-attribute' name='formatting.XFAlignment.vert_align-attribute'><b>vert_align</b></a> [<a href='#formatting.XFAlignment.vert_align-attribute'>#</a>]</dt>
16341718 <dd>
16351719 <p>Values: section 6.115 (p 215) of OOo docs</p>
16361720 </dd>
16371721 </dl>
1638-<h2><a id='xlrd.XFBackground-class' name='xlrd.XFBackground-class'>The XFBackground Class</a></h2>
1722+<h2><a id='formatting.XFBackground-class' name='formatting.XFBackground-class'>The XFBackground Class</a></h2>
16391723 <dl>
1640-<dt><b>XFBackground</b> (class) [<a href='#xlrd.XFBackground-class'>#</a>]</dt>
1724+<dt><b>XFBackground</b> (class) [<a href='#formatting.XFBackground-class'>#</a>]</dt>
16411725 <dd>
16421726 <p>A collection of the background-related attributes of an XF record.
16431727 Items correspond to those in the Excel UI's Format/Cells/Patterns tab.
@@ -1645,22 +1729,22 @@
16451729 section at the start of this document.
16461730 <br /> -- New in version 0.6.1
16471731 </p></dd>
1648-<dt><a id='xlrd.XFBackground.background_colour_index-attribute' name='xlrd.XFBackground.background_colour_index-attribute'><b>background_colour_index</b></a> [<a href='#xlrd.XFBackground.background_colour_index-attribute'>#</a>]</dt>
1732+<dt><a id='formatting.XFBackground.background_colour_index-attribute' name='formatting.XFBackground.background_colour_index-attribute'><b>background_colour_index</b></a> [<a href='#formatting.XFBackground.background_colour_index-attribute'>#</a>]</dt>
16491733 <dd>
16501734 <p>See section 3.11 of the OOo docs.</p>
16511735 </dd>
1652-<dt><a id='xlrd.XFBackground.fill_pattern-attribute' name='xlrd.XFBackground.fill_pattern-attribute'><b>fill_pattern</b></a> [<a href='#xlrd.XFBackground.fill_pattern-attribute'>#</a>]</dt>
1736+<dt><a id='formatting.XFBackground.fill_pattern-attribute' name='formatting.XFBackground.fill_pattern-attribute'><b>fill_pattern</b></a> [<a href='#formatting.XFBackground.fill_pattern-attribute'>#</a>]</dt>
16531737 <dd>
16541738 <p>See section 3.11 of the OOo docs.</p>
16551739 </dd>
1656-<dt><a id='xlrd.XFBackground.pattern_colour_index-attribute' name='xlrd.XFBackground.pattern_colour_index-attribute'><b>pattern_colour_index</b></a> [<a href='#xlrd.XFBackground.pattern_colour_index-attribute'>#</a>]</dt>
1740+<dt><a id='formatting.XFBackground.pattern_colour_index-attribute' name='formatting.XFBackground.pattern_colour_index-attribute'><b>pattern_colour_index</b></a> [<a href='#formatting.XFBackground.pattern_colour_index-attribute'>#</a>]</dt>
16571741 <dd>
16581742 <p>See section 3.11 of the OOo docs.</p>
16591743 </dd>
16601744 </dl>
1661-<h2><a id='xlrd.XFBorder-class' name='xlrd.XFBorder-class'>The XFBorder Class</a></h2>
1745+<h2><a id='formatting.XFBorder-class' name='formatting.XFBorder-class'>The XFBorder Class</a></h2>
16621746 <dl>
1663-<dt><b>XFBorder</b> (class) [<a href='#xlrd.XFBorder-class'>#</a>]</dt>
1747+<dt><b>XFBorder</b> (class) [<a href='#formatting.XFBorder-class'>#</a>]</dt>
16641748 <dd>
16651749 <p /><p>A collection of the border-related attributes of an XF record.
16661750 Items correspond to those in the Excel UI's Format/Cells/Border tab.</p>
@@ -1687,58 +1771,58 @@
16871771 &quot;Line Styles for Cell Borders (BIFF3-BIFF8)&quot;.</p>
16881772 <br /> -- New in version 0.6.1
16891773 </dd>
1690-<dt><a id='xlrd.XFBorder.bottom_colour_index-attribute' name='xlrd.XFBorder.bottom_colour_index-attribute'><b>bottom_colour_index</b></a> [<a href='#xlrd.XFBorder.bottom_colour_index-attribute'>#</a>]</dt>
1774+<dt><a id='formatting.XFBorder.bottom_colour_index-attribute' name='formatting.XFBorder.bottom_colour_index-attribute'><b>bottom_colour_index</b></a> [<a href='#formatting.XFBorder.bottom_colour_index-attribute'>#</a>]</dt>
16911775 <dd>
16921776 <p>The colour index for the cell's bottom line</p>
16931777 </dd>
1694-<dt><a id='xlrd.XFBorder.bottom_line_style-attribute' name='xlrd.XFBorder.bottom_line_style-attribute'><b>bottom_line_style</b></a> [<a href='#xlrd.XFBorder.bottom_line_style-attribute'>#</a>]</dt>
1778+<dt><a id='formatting.XFBorder.bottom_line_style-attribute' name='formatting.XFBorder.bottom_line_style-attribute'><b>bottom_line_style</b></a> [<a href='#formatting.XFBorder.bottom_line_style-attribute'>#</a>]</dt>
16951779 <dd>
16961780 <p>The line style for the cell's bottom line</p>
16971781 </dd>
1698-<dt><a id='xlrd.XFBorder.diag_colour_index-attribute' name='xlrd.XFBorder.diag_colour_index-attribute'><b>diag_colour_index</b></a> [<a href='#xlrd.XFBorder.diag_colour_index-attribute'>#</a>]</dt>
1782+<dt><a id='formatting.XFBorder.diag_colour_index-attribute' name='formatting.XFBorder.diag_colour_index-attribute'><b>diag_colour_index</b></a> [<a href='#formatting.XFBorder.diag_colour_index-attribute'>#</a>]</dt>
16991783 <dd>
17001784 <p>The colour index for the cell's diagonal lines, if any</p>
17011785 </dd>
1702-<dt><a id='xlrd.XFBorder.diag_down-attribute' name='xlrd.XFBorder.diag_down-attribute'><b>diag_down</b></a> [<a href='#xlrd.XFBorder.diag_down-attribute'>#</a>]</dt>
1786+<dt><a id='formatting.XFBorder.diag_down-attribute' name='formatting.XFBorder.diag_down-attribute'><b>diag_down</b></a> [<a href='#formatting.XFBorder.diag_down-attribute'>#</a>]</dt>
17031787 <dd>
17041788 <p>1 = draw a diagonal from top left to bottom right</p>
17051789 </dd>
1706-<dt><a id='xlrd.XFBorder.diag_line_style-attribute' name='xlrd.XFBorder.diag_line_style-attribute'><b>diag_line_style</b></a> [<a href='#xlrd.XFBorder.diag_line_style-attribute'>#</a>]</dt>
1790+<dt><a id='formatting.XFBorder.diag_line_style-attribute' name='formatting.XFBorder.diag_line_style-attribute'><b>diag_line_style</b></a> [<a href='#formatting.XFBorder.diag_line_style-attribute'>#</a>]</dt>
17071791 <dd>
17081792 <p>The line style for the cell's diagonal lines, if any</p>
17091793 </dd>
1710-<dt><a id='xlrd.XFBorder.diag_up-attribute' name='xlrd.XFBorder.diag_up-attribute'><b>diag_up</b></a> [<a href='#xlrd.XFBorder.diag_up-attribute'>#</a>]</dt>
1794+<dt><a id='formatting.XFBorder.diag_up-attribute' name='formatting.XFBorder.diag_up-attribute'><b>diag_up</b></a> [<a href='#formatting.XFBorder.diag_up-attribute'>#</a>]</dt>
17111795 <dd>
17121796 <p>1 = draw a diagonal from bottom left to top right</p>
17131797 </dd>
1714-<dt><a id='xlrd.XFBorder.left_colour_index-attribute' name='xlrd.XFBorder.left_colour_index-attribute'><b>left_colour_index</b></a> [<a href='#xlrd.XFBorder.left_colour_index-attribute'>#</a>]</dt>
1798+<dt><a id='formatting.XFBorder.left_colour_index-attribute' name='formatting.XFBorder.left_colour_index-attribute'><b>left_colour_index</b></a> [<a href='#formatting.XFBorder.left_colour_index-attribute'>#</a>]</dt>
17151799 <dd>
17161800 <p>The colour index for the cell's left line</p>
17171801 </dd>
1718-<dt><a id='xlrd.XFBorder.left_line_style-attribute' name='xlrd.XFBorder.left_line_style-attribute'><b>left_line_style</b></a> [<a href='#xlrd.XFBorder.left_line_style-attribute'>#</a>]</dt>
1802+<dt><a id='formatting.XFBorder.left_line_style-attribute' name='formatting.XFBorder.left_line_style-attribute'><b>left_line_style</b></a> [<a href='#formatting.XFBorder.left_line_style-attribute'>#</a>]</dt>
17191803 <dd>
17201804 <p>The line style for the cell's left line</p>
17211805 </dd>
1722-<dt><a id='xlrd.XFBorder.right_colour_index-attribute' name='xlrd.XFBorder.right_colour_index-attribute'><b>right_colour_index</b></a> [<a href='#xlrd.XFBorder.right_colour_index-attribute'>#</a>]</dt>
1806+<dt><a id='formatting.XFBorder.right_colour_index-attribute' name='formatting.XFBorder.right_colour_index-attribute'><b>right_colour_index</b></a> [<a href='#formatting.XFBorder.right_colour_index-attribute'>#</a>]</dt>
17231807 <dd>
17241808 <p>The colour index for the cell's right line</p>
17251809 </dd>
1726-<dt><a id='xlrd.XFBorder.right_line_style-attribute' name='xlrd.XFBorder.right_line_style-attribute'><b>right_line_style</b></a> [<a href='#xlrd.XFBorder.right_line_style-attribute'>#</a>]</dt>
1810+<dt><a id='formatting.XFBorder.right_line_style-attribute' name='formatting.XFBorder.right_line_style-attribute'><b>right_line_style</b></a> [<a href='#formatting.XFBorder.right_line_style-attribute'>#</a>]</dt>
17271811 <dd>
17281812 <p>The line style for the cell's right line</p>
17291813 </dd>
1730-<dt><a id='xlrd.XFBorder.top_colour_index-attribute' name='xlrd.XFBorder.top_colour_index-attribute'><b>top_colour_index</b></a> [<a href='#xlrd.XFBorder.top_colour_index-attribute'>#</a>]</dt>
1814+<dt><a id='formatting.XFBorder.top_colour_index-attribute' name='formatting.XFBorder.top_colour_index-attribute'><b>top_colour_index</b></a> [<a href='#formatting.XFBorder.top_colour_index-attribute'>#</a>]</dt>
17311815 <dd>
17321816 <p>The colour index for the cell's top line</p>
17331817 </dd>
1734-<dt><a id='xlrd.XFBorder.top_line_style-attribute' name='xlrd.XFBorder.top_line_style-attribute'><b>top_line_style</b></a> [<a href='#xlrd.XFBorder.top_line_style-attribute'>#</a>]</dt>
1818+<dt><a id='formatting.XFBorder.top_line_style-attribute' name='formatting.XFBorder.top_line_style-attribute'><b>top_line_style</b></a> [<a href='#formatting.XFBorder.top_line_style-attribute'>#</a>]</dt>
17351819 <dd>
17361820 <p>The line style for the cell's top line</p>
17371821 </dd>
17381822 </dl>
1739-<h2><a id='xlrd.XFProtection-class' name='xlrd.XFProtection-class'>The XFProtection Class</a></h2>
1823+<h2><a id='formatting.XFProtection-class' name='formatting.XFProtection-class'>The XFProtection Class</a></h2>
17401824 <dl>
1741-<dt><b>XFProtection</b> (class) [<a href='#xlrd.XFProtection-class'>#</a>]</dt>
1825+<dt><b>XFProtection</b> (class) [<a href='#formatting.XFProtection-class'>#</a>]</dt>
17421826 <dd>
17431827 <p>A collection of the protection-related attributes of an XF record.
17441828 Items correspond to those in the Excel UI's Format/Cells/Protection tab.
@@ -1747,12 +1831,12 @@
17471831 This is incorrect; the bit is used in determining which bundles to use.
17481832 <br /> -- New in version 0.6.1
17491833 </p></dd>
1750-<dt><a id='xlrd.XFProtection.cell_locked-attribute' name='xlrd.XFProtection.cell_locked-attribute'><b>cell_locked</b></a> [<a href='#xlrd.XFProtection.cell_locked-attribute'>#</a>]</dt>
1834+<dt><a id='formatting.XFProtection.cell_locked-attribute' name='formatting.XFProtection.cell_locked-attribute'><b>cell_locked</b></a> [<a href='#formatting.XFProtection.cell_locked-attribute'>#</a>]</dt>
17511835 <dd>
17521836 <p>1 = Cell is prevented from being changed, moved, resized, or deleted
17531837 (only if the sheet is protected).</p>
17541838 </dd>
1755-<dt><a id='xlrd.XFProtection.formula_hidden-attribute' name='xlrd.XFProtection.formula_hidden-attribute'><b>formula_hidden</b></a> [<a href='#xlrd.XFProtection.formula_hidden-attribute'>#</a>]</dt>
1839+<dt><a id='formatting.XFProtection.formula_hidden-attribute' name='formatting.XFProtection.formula_hidden-attribute'><b>formula_hidden</b></a> [<a href='#formatting.XFProtection.formula_hidden-attribute'>#</a>]</dt>
17561840 <dd>
17571841 <p>1 = Hide formula so that it doesn't appear in the formula bar when
17581842 the cell is selected (only if the sheet is protected).</p>
--- branches/tl3_0/python-lib/xlrd/xlrd/__init__.py (revision 43)
+++ branches/tl3_0/python-lib/xlrd/xlrd/__init__.py (revision 44)
@@ -1,8 +1,8 @@
11 # -*- coding: cp1252 -*-
22
3-__VERSION__ = "0.6.1" # 2007-06-10
3+__VERSION__ = "0.7.1" # 2009-05-31
44
5-# <p>Copyright ゥ 2005-2007 Stephen John Machin, Lingfo Pty Ltd</p>
5+# <p>Copyright ゥ 2005-2009 Stephen John Machin, Lingfo Pty Ltd</p>
66 # <p>This module is part of the xlrd package, which is released under a
77 # BSD-style licence.</p>
88
@@ -10,6 +10,8 @@
1010
1111 ##
1212 # <p><b>A Python module for extracting data from MS Excel spreadsheet files.
13+# <br /><br />
14+# Version 0.7.1 -- 2009-05-31
1315 # </b></p>
1416 #
1517 # <h2>General information</h2>
@@ -23,7 +25,7 @@
2325 # The latest version is available from OpenOffice.org in
2426 # <a href=http://sc.openoffice.org/excelfileformat.pdf> PDF format</a>
2527 # and
26-# <a href=http://sc.openoffice.org/excelfileformat.sxw> XML format.</a>
28+# <a href=http://sc.openoffice.org/excelfileformat.odt> ODT format.</a>
2729 # Small portions of the OOo docs are reproduced in this
2830 # document. A study of the OOo docs is recommended for those who wish a
2931 # deeper understanding of the Excel file layout than the xlrd docs can provide.
@@ -52,7 +54,7 @@
5254 # <small>
5355 # <p>If the CODEPAGE record is missing (possible if the file was created
5456 # by third-party software), xlrd will assume that the encoding is ascii, and keep going.
55-# If the actual encoding is not ascii, a UnicodeDecodeError exception will be raised and
57+# If the actual encoding is not ascii, a UnicodeDecodeError exception will be raised and
5658 # you will need to determine the encoding yourself, and tell xlrd:
5759 # <pre>
5860 # book = xlrd.open_workbook(..., encoding_override="cp1252")
@@ -134,7 +136,7 @@
134136 # <p>For further information, please refer to the documentation for the xldate_* functions.</p>
135137 #
136138 # <h3> Named references, constants, formulas, and macros</h3>
137-#
139+#
138140 # <p>
139141 # A name is used to refer to a cell, a group of cells, a constant
140142 # value, a formula, or a macro. Usually the scope of a name is global
@@ -248,10 +250,59 @@
248250 # are inappropriate. Note that this does not affect users who are copying XLS
249251 # files, only those who are visually rendering cells.</li>
250252 # </ul>
253+#
254+# <h3>Loading worksheets on demand</h3>
255+#
256+# <p>This feature, new in version 0.7.1, is governed by the on_demand argument
257+# to the open_workbook() function and allows saving memory and time by loading
258+# only those sheets that the caller is interested in, and releasing sheets
259+# when no longer required.</p>
260+#
261+# <p>on_demand=False (default): No change. open_workbook() loads global data
262+# and all sheets, releases resources no longer required (principally the
263+# str or mmap object containing the Workbook stream), and returns.</p>
264+#
265+# <p>on_demand=True and BIFF version < 5.0: A warning message is emitted,
266+# on_demand is recorded as False, and the old process is followed.</p>
267+#
268+# <p>on_demand=True and BIFF version >= 5.0: open_workbook() loads global
269+# data and returns without releasing resources. At this stage, the only
270+# information available about sheets is Book.nsheets and Book.sheet_names().</p>
271+#
272+# <p>Book.sheet_by_name() and Book.sheet_by_index() will load the requested
273+# sheet if it is not already loaded.</p>
274+#
275+# <p>Book.sheets() will load all/any unloaded sheets.</p>
276+#
277+# <p>The caller may save memory by calling
278+# Book.unload_sheet(sheet_name_or_index) when finished with the sheet.
279+# This applies irrespective of the state of on_demand.</p>
280+#
281+# <p>The caller may re-load an unloaded sheet by calling Book.sheet_by_xxxx()
282+# -- except if those required resources have been released (which will
283+# have happened automatically when on_demand is false). This is the only
284+# case where an exception will be raised.</p>
285+#
286+# <p>The caller may query the state of a sheet:
287+# Book.sheet_loaded(sheet_name_or_index) -> a bool</p>
288+#
251289 ##
252290
291+# 2009-04-27 SJM Integrated on_demand patch by Armando Serrano Lombillo
292+# 2008-11-23 SJM Support dumping FILEPASS and EXTERNNAME records; extra info from SUPBOOK records
293+# 2008-11-23 SJM colname utility function now supports more than 256 columns
294+# 2008-04-24 SJM Recovery code for file with out-of-order/missing/wrong CODEPAGE record needed to be called for EXTERNSHEET/BOUNDSHEET/NAME/SHEETHDR records.
295+# 2008-02-08 SJM Preparation for Excel 2.0 support
296+# 2008-02-03 SJM Minor tweaks for IronPython support
297+# 2008-02-02 SJM Previous change stopped dump() and count_records() ... fixed
298+# 2007-12-25 SJM Decouple Book initialisation & loading -- to allow for multiple loaders.
299+# 2007-12-20 SJM Better error message for unsupported file format.
300+# 2007-12-04 SJM Added support for Excel 2.x (BIFF2) files.
301+# 2007-11-20 SJM Wasn't handling EXTERNSHEET record that needed CONTINUE record(s)
302+# 2007-07-07 SJM Version changed to 0.7.0 (alpha 1)
303+# 2007-07-07 SJM Logfile arg wasn't being passed from open_workbook to compdoc.CompDoc
304+# 2007-05-21 SJM If no CODEPAGE record in pre-8.0 file, assume ascii and keep going.
253305 # 2007-04-22 SJM Removed antique undocumented Book.get_name_dict method.
254-# 2007-05-21 SJM If no CODEPAGE record in pre-8.0 file, assume ascii and keep going.
255306
256307 from timemachine import *
257308 from biffh import *
@@ -286,8 +337,10 @@
286337
287338 MY_EOF = 0xF00BAAA # not a 16-bit number
288339
289-SUPPORTED_VERSIONS = (80, 70, 50, 45, 40, 30)
340+SUPBOOK_UNK, SUPBOOK_INTERNAL, SUPBOOK_EXTERNAL, SUPBOOK_ADDIN, SUPBOOK_DDEOLE = range(5)
290341
342+SUPPORTED_VERSIONS = (80, 70, 50, 45, 40, 30, 21, 20)
343+
291344 code_from_builtin_name = {
292345 u"Consolidate_Area": u"\x00",
293346 u"Auto_Open": u"\x01",
@@ -346,6 +399,10 @@
346399 # XF information is available for each cell.
347400 # <br /> -- New in version 0.6.1
348401 #
402+# @param on_demand Governs whether sheets are all loaded initially or when demanded
403+# by the caller. Please refer back to the section "Loading worksheets on demand" for details.
404+# -- New in version 0.7.1
405+#
349406 # @return An instance of the Book class.
350407
351408 def open_workbook(filename=None,
@@ -352,7 +409,7 @@
352409 logfile=sys.stdout, verbosity=0, pickleable=True, use_mmap=USE_MMAP,
353410 file_contents=None,
354411 encoding_override=None,
355- formatting_info=False,
412+ formatting_info=False, on_demand=False,
356413 ):
357414 t0 = time.clock()
358415 if TOGGLE_GC:
@@ -359,11 +416,13 @@
359416 orig_gc_enabled = gc.isenabled()
360417 if orig_gc_enabled:
361418 gc.disable()
362- bk = Book(
419+ bk = Book()
420+ bk.biff2_8_load(
363421 filename=filename, file_contents=file_contents,
364422 logfile=logfile, verbosity=verbosity, pickleable=pickleable, use_mmap=use_mmap,
365423 encoding_override=encoding_override,
366424 formatting_info=formatting_info,
425+ on_demand=on_demand,
367426 )
368427 t1 = time.clock()
369428 bk.load_time_stage_1 = t1 - t0
@@ -378,13 +437,24 @@
378437 bk.biff_version = biff_version
379438 if biff_version <= 40:
380439 # no workbook globals, only 1 worksheet
440+ if on_demand:
441+ fprintf(bk.logfile,
442+ "*** WARNING: on_demand is not supported for this Excel version.\n"
443+ "*** Setting on_demand to False.\n")
444+ bk.on_demand = on_demand = False
381445 bk.fake_globals_get_sheet()
382446 elif biff_version == 45:
383447 # worksheet(s) embedded in global stream
384448 bk.parse_globals()
449+ if on_demand:
450+ fprintf(bk.logfile, "*** WARNING: on_demand is not supported for this Excel version.\n"
451+ "*** Setting on_demand to False.\n")
452+ bk.on_demand = on_demand = False
385453 else:
386454 bk.parse_globals()
387- bk.get_sheets()
455+ bk._sheet_list = [None for sh in bk._sheet_names]
456+ if not on_demand:
457+ bk.get_sheets()
388458 bk.nsheets = len(bk._sheet_list)
389459 if biff_version == 45 and bk.nsheets > 1:
390460 fprintf(bk.logfile,
@@ -392,7 +462,8 @@
392462 "*** Book-level data will be that of the last worksheet.\n",
393463 bk.nsheets
394464 )
395- bk.release_resources()
465+ if not on_demand:
466+ bk.release_resources()
396467 if TOGGLE_GC:
397468 if orig_gc_enabled:
398469 gc.enable()
@@ -404,10 +475,12 @@
404475 # For debugging: dump the file's BIFF records in char & hex.
405476 # @param filename The path to the file to be dumped.
406477 # @param outfile An open file, to which the dump is written.
478+# @param unnumbered If true, omit offsets (for meaningful diffs).
407479
408-def dump(filename, outfile=sys.stdout):
409- bk = Book(filename)
410- biff_dump(bk.mem, bk.base, bk.stream_len, 0, outfile)
480+def dump(filename, outfile=sys.stdout, unnumbered=False):
481+ bk = Book()
482+ bk.biff2_8_load(filename=filename, logfile=outfile, )
483+ biff_dump(bk.mem, bk.base, bk.stream_len, 0, outfile, unnumbered)
411484
412485 ##
413486 # For debugging and analysis: summarise the file's BIFF records.
@@ -416,13 +489,14 @@
416489 # @param outfile An open file, to which the summary is written.
417490
418491 def count_records(filename, outfile=sys.stdout):
419- bk = Book(filename)
492+ bk = Book()
493+ bk.biff2_8_load(filename=filename, logfile=outfile, )
420494 biff_count_records(bk.mem, bk.base, bk.stream_len, outfile)
421495
422496 ##
423497 # Information relating to a named reference, formula, macro, etc.
424-# <br> -- New in version 0.6.0
425-# <br> -- <i>Name information is <b>not</b> extracted from files older than
498+# <br /> -- New in version 0.6.0
499+# <br /> -- <i>Name information is <b>not</b> extracted from files older than
426500 # Excel 5.0 (Book.biff_version < 50)</i>
427501
428502 class Name(BaseObject):
@@ -447,7 +521,7 @@
447521 macro = 0
448522
449523 ##
450- # 0 = Simple formula; 1 = Complex formula (array formula or user defined)<br>
524+ # 0 = Simple formula; 1 = Complex formula (array formula or user defined)<br />
451525 # <i>No examples have been sighted.</i>
452526 complex = 0
453527
@@ -461,7 +535,7 @@
461535 funcgroup = 0
462536
463537 ##
464- # 0 = Formula definition; 1 = Binary data<br> <i>No examples have been sighted.</i>
538+ # 0 = Formula definition; 1 = Binary data<br /> <i>No examples have been sighted.</i>
465539 binary = 0
466540
467541 ##
@@ -477,9 +551,9 @@
477551 raw_formula = ""
478552
479553 ##
480- # -1: The name is global (visible in all calculation sheets).<br>
481- # -2: The name belongs to a macro sheet or VBA sheet.<br>
482- # -3: The name is invalid.<br>
554+ # -1: The name is global (visible in all calculation sheets).<br />
555+ # -2: The name belongs to a macro sheet or VBA sheet.<br />
556+ # -3: The name is invalid.<br />
483557 # 0 <= scope < book.nsheets: The name is local to the sheet whose index is scope.
484558 scope = -1
485559
@@ -516,6 +590,41 @@
516590 )
517591 raise XLRDError("Not a constant absolute reference to a single cell")
518592
593+ ##
594+ # This is a convenience method for the use case where the name
595+ # refers to one rectangular area in one worksheet.
596+ # @param clipped If true (the default), the returned rectangle is clipped
597+ # to fit in (0, sheet.nrows, 0, sheet.ncols) -- it is guaranteed that
598+ # 0 <= rowxlo <= rowxhi <= sheet.nrows and that the number of usable rows
599+ # in the area (which may be zero) is rowxhi - rowxlo; likewise for columns.
600+ # @return a tuple (sheet_object, rowxlo, rowxhi, colxlo, colxhi).
601+ # @throws XLRDError The name is not a constant absolute reference
602+ # to a single area in a single sheet.
603+ def area2d(self, clipped=True):
604+ res = self.result
605+ if res:
606+ # result should be an instance of the Operand class
607+ kind = res.kind
608+ value = res.value
609+ if kind == oREF and len(value) == 1: # only 1 reference
610+ ref3d = value[0]
611+ if 0 <= ref3d.shtxlo == ref3d.shtxhi - 1: # only 1 usable sheet
612+ sh = self.book.sheet_by_index(ref3d.shtxlo)
613+ if not clipped:
614+ return sh, ref3d.rowxlo, ref3d.rowxhi, ref3d.colxlo, ref3d.colxhi
615+ rowxlo = min(ref3d.rowxlo, sh.nrows)
616+ rowxhi = max(rowxlo, min(ref3d.rowxhi, sh.nrows))
617+ colxlo = min(ref3d.colxlo, sh.ncols)
618+ colxhi = max(colxlo, min(ref3d.colxhi, sh.ncols))
619+ assert 0 <= rowxlo <= rowxhi <= sh.nrows
620+ assert 0 <= colxlo <= colxhi <= sh.ncols
621+ return sh, rowxlo, rowxhi, colxlo, colxhi
622+ self.dump(self.book.logfile,
623+ header="=== Dump of Name object ===",
624+ footer="======= End of dump =======",
625+ )
626+ raise XLRDError("Not a constant absolute reference to a single area in a single sheet")
627+
519628 ##
520629 # Contents of a "workbook".
521630 # <p>WARNING: You don't call this class yourself. You use the Book object that
@@ -524,24 +633,25 @@
524633 class Book(BaseObject):
525634
526635 ##
527- # The number of worksheets in the workbook.
636+ # The number of worksheets present in the workbook file.
637+ # This information is available even when no sheets have yet been loaded.
528638 nsheets = 0
529639
530640 ##
531- # Which date system was in force when this file was last saved.<br>
532- # 0 => 1900 system (the Excel for Windows default).<br>
533- # 1 => 1904 system (the Excel for Macintosh default).<br>
641+ # Which date system was in force when this file was last saved.<br />
642+ # 0 => 1900 system (the Excel for Windows default).<br />
643+ # 1 => 1904 system (the Excel for Macintosh default).<br />
534644 datemode = 0 # In case it's not specified in the file.
535645
536646 ##
537647 # Version of BIFF (Binary Interchange File Format) used to create the file.
538648 # Latest is 8.0 (represented here as 80), introduced with Excel 97.
539- # Earliest supported by this module: 3.0 (represented as 30).
649+ # Earliest supported by this module: 2.0 (represented as 20).
540650 biff_version = 0
541651
542652 ##
543653 # List containing a Name object for each NAME record in the workbook.
544- # <br> -- New in version 0.6.0
654+ # <br /> -- New in version 0.6.0
545655 name_obj_list = []
546656
547657 ##
@@ -557,9 +667,9 @@
557667 encoding = None
558668
559669 ##
560- # A tuple containing the (telephone system) country code for:<br>
561- # [0]: the user-interface setting when the file was created.<br>
562- # [1]: the regional settings.<br>
670+ # A tuple containing the (telephone system) country code for:<br />
671+ # [0]: the user-interface setting when the file was created.<br />
672+ # [1]: the regional settings.<br />
563673 # Example: (1, 61) meaning (USA, Australia).
564674 # This information may give a clue to the correct encoding for an unknown codepage.
565675 # For a long list of observed values, refer to the OpenOffice.org documentation for
@@ -618,7 +728,7 @@
618728 # "Magic" indexes e.g. 0x7FFF map to None.
619729 # <i>colour_map</i> is what you need if you want to render cells on screen or in a PDF
620730 # file. If you are writing an output XLS file, use <i>palette_record</i>.
621- # <br /> -- New in version 0.6.1
731+ # <br /> -- New in version 0.6.1. Extracted only if open_workbook(..., formatting_info=True)
622732 colour_map = {}
623733
624734 ##
@@ -628,7 +738,7 @@
628738 # Otherwise this list will be empty. This is what you need if you are
629739 # writing an output XLS file. If you want to render cells on screen or in a PDF
630740 # file, use colour_map.
631- # <br /> -- New in version 0.6.1
741+ # <br /> -- New in version 0.6.1. Extracted only if open_workbook(..., formatting_info=True)
632742 palette_record = []
633743
634744 ##
@@ -641,13 +751,18 @@
641751
642752 ##
643753 # @return A list of all sheets in the book.
754+ # All sheets not already loaded will be loaded.
644755 def sheets(self):
645- return self._sheet_list
756+ for sheetx in xrange(self.nsheets):
757+ if not self._sheet_list[sheetx]:
758+ self.get_sheet(sheetx)
759+ return self._sheet_list[:]
760+
646761 ##
647762 # @param sheetx Sheet index in range(nsheets)
648763 # @return An object of the Sheet class
649764 def sheet_by_index(self, sheetx):
650- return self._sheet_list[sheetx]
765+ return self._sheet_list[sheetx] or self.get_sheet(sheetx)
651766
652767 ##
653768 # @param sheet_name Name of sheet required
@@ -657,16 +772,46 @@
657772 sheetx = self._sheet_names.index(sheet_name)
658773 except ValueError:
659774 raise XLRDError('No sheet named <%r>' % sheet_name)
660- return self._sheet_list[sheetx]
775+ return self.sheet_by_index(sheetx)
661776
662777 ##
663- # @return A list of the names of the sheets in the book.
778+ # @return A list of the names of all the worksheets in the workbook file.
779+ # This information is available even when no sheets have yet been loaded.
664780 def sheet_names(self):
665781 return self._sheet_names[:]
666782
667783 ##
784+ # @param sheet_name_or_index Name or index of sheet enquired upon
785+ # @return true if sheet is loaded, false otherwise
786+ # <br /> -- New in version 0.7.1
787+ def sheet_loaded(self, sheet_name_or_index):
788+ # using type(1) because int won't work with Python 2.1
789+ if isinstance(sheet_name_or_index, type(1)):
790+ sheetx = sheet_name_or_index
791+ else:
792+ try:
793+ sheetx = self._sheet_names.index(sheet_name_or_index)
794+ except ValueError:
795+ raise XLRDError('No sheet named <%r>' % sheet_name_or_index)
796+ return self._sheet_list[sheetx] and True or False # Python 2.1 again
797+
798+ ##
799+ # @param sheet_name_or_index Name or index of sheet to be unloaded.
800+ # <br /> -- New in version 0.7.1
801+ def unload_sheet(self, sheet_name_or_index):
802+ # using type(1) because int won't work with Python 2.1
803+ if isinstance(sheet_name_or_index, type(1)):
804+ sheetx = sheet_name_or_index
805+ else:
806+ try:
807+ sheetx = self._sheet_names.index(sheet_name_or_index)
808+ except ValueError:
809+ raise XLRDError('No sheet named <%r>' % sheet_name_or_index)
810+ self._sheet_list[sheetx] = None
811+
812+ ##
668813 # A mapping from (lower_case_name, scope) to a single Name object.
669- # <br> -- New in version 0.6.0
814+ # <br /> -- New in version 0.6.0
670815 name_and_scope_map = {}
671816
672817 ##
@@ -673,21 +818,10 @@
673818 # A mapping from lower_case_name to a list of Name objects. The list is
674819 # sorted in scope order. Typically there will be one item (of global scope)
675820 # in the list.
676- # <br> -- New in version 0.6.0
821+ # <br /> -- New in version 0.6.0
677822 name_map = {}
678823
679- def __init__(self, filename=None, file_contents=None,
680- logfile=sys.stdout, verbosity=0, pickleable=True, use_mmap=USE_MMAP,
681- encoding_override=None,
682- formatting_info=False,
683- ):
684- # DEBUG = 0
685- self.logfile = logfile
686- self.verbosity = verbosity
687- self.pickleable = pickleable
688- self.use_mmap = use_mmap
689- self.encoding_override = encoding_override
690- self.formatting_info = formatting_info
824+ def __init__(self):
691825 self._sheet_list = []
692826 self._sheet_names = []
693827 self._sheet_visibility = [] # from BOUNDSHEET record
@@ -701,6 +835,7 @@
701835 self._all_sheets_count = 0 # includes macro & VBA sheets
702836 self._supbook_count = 0
703837 self._supbook_locals_inx = None
838+ self._supbook_addins_inx = None
704839 self._all_sheets_map = [] # maps an all_sheets index to a calc-sheets index (or -1)
705840 self._externsheet_info = []
706841 self._externsheet_type_b57 = []
@@ -707,6 +842,9 @@
707842 self._extnsht_name_from_num = {}
708843 self._sheet_num_from_name = {}
709844 self._extnsht_count = 0
845+ self._supbook_types = []
846+ self._resources_released = 0
847+ self.addin_func_names = []
710848 self.name_obj_list = []
711849 self.colour_map = {}
712850 self.palette_record = []
@@ -713,6 +851,21 @@
713851 self.xf_list = []
714852 self.style_name_map = {}
715853
854+ def biff2_8_load(self, filename=None, file_contents=None,
855+ logfile=sys.stdout, verbosity=0, pickleable=True, use_mmap=USE_MMAP,
856+ encoding_override=None,
857+ formatting_info=False,
858+ on_demand=False,
859+ ):
860+ # DEBUG = 0
861+ self.logfile = logfile
862+ self.verbosity = verbosity
863+ self.pickleable = pickleable
864+ self.use_mmap = use_mmap and MMAP_AVAILABLE
865+ self.encoding_override = encoding_override
866+ self.formatting_info = formatting_info
867+ self.on_demand = on_demand
868+
716869 need_close_filestr = 0
717870 if not file_contents:
718871 if python_version < (2, 2) and self.use_mmap:
@@ -757,7 +910,7 @@
757910 # got this one at the antique store
758911 self.mem = filestr
759912 else:
760- cd = compdoc.CompDoc(filestr)
913+ cd = compdoc.CompDoc(filestr, logfile=self.logfile)
761914 if USE_FANCY_CD:
762915 for qname in [u'Workbook', u'Book']:
763916 self.mem, self.base, self.stream_len = cd.locate_named_stream(qname)
@@ -787,10 +940,12 @@
787940 self.xfcount = 0
788941 self.actualfmtcount = 0 # number of FORMAT records seen so far
789942 self._xf_index_to_xl_type_map = {}
943+ self._xf_epilogue_done = 0
790944 self.xf_list = []
791945 self.font_list = []
792946
793947 def release_resources(self):
948+ self._resources_released = 1
794949 del self.mem
795950 del self._sharedstrings
796951
@@ -824,7 +979,11 @@
824979 self._position = pos + length
825980 return (code, length, data)
826981
827- def get_sheet(self, sh_number):
982+ def get_sheet(self, sh_number, update_pos=True):
983+ if self._resources_released:
984+ raise XLRDError("Can't load sheets after releasing resources.")
985+ if update_pos:
986+ self._position = self._sh_abs_posn[sh_number]
828987 _unused_biff_version = self.getbof(XL_WORKSHEET)
829988 # assert biff_version == self.biff_version ### FAILS
830989 # Have an example where book is v7 but sheet reports v8!!!
@@ -837,6 +996,7 @@
837996 sh_number,
838997 )
839998 sh.read(self)
999+ self._sheet_list[sh_number] = sh
8401000 return sh
8411001
8421002 def get_sheets(self):
@@ -844,10 +1004,7 @@
8441004 if DEBUG: print >> self.logfile, "GET_SHEETS:", self._sheet_names, self._sh_abs_posn
8451005 for sheetno in xrange(len(self._sheet_names)):
8461006 if DEBUG: print >> self.logfile, "GET_SHEETS: sheetno =", sheetno, self._sheet_names, self._sh_abs_posn
847- newposn = self._sh_abs_posn[sheetno]
848- self.position(newposn)
849- sht = self.get_sheet(sheetno)
850- self._sheet_list.append(sht)
1007+ self.get_sheet(sheetno)
8511008
8521009 def fake_globals_get_sheet(self): # for BIFF 4.0 and earlier
8531010 formatting.initialise_book(self)
@@ -855,11 +1012,13 @@
8551012 self._sheet_names = [fake_sheet_name]
8561013 self._sh_abs_posn = [0]
8571014 self._sheet_visibility = [0] # one sheet, visible
1015+ self._sheet_list.append(None) # get_sheet updates _sheet_list but needs a None beforehand
8581016 self.get_sheets()
8591017
8601018 def handle_boundsheet(self, data):
8611019 # DEBUG = 1
8621020 bv = self.biff_version
1021+ self.derive_encoding()
8631022 if DEBUG:
8641023 fprintf(self.logfile, "BOUNDSHEET: bv=%d data %r\n", bv, data);
8651024 if bv == 45: # BIFF4W
@@ -934,7 +1093,7 @@
9341093 encoding = 'cp' + str(codepage)
9351094 else:
9361095 encoding = 'unknown_codepage_' + str(codepage)
937- if DEBUG or self.verbosity:
1096+ if DEBUG or (self.verbosity and encoding != self.encoding) :
9381097 fprintf(self.logfile, "CODEPAGE: codepage %r -> encoding %r\n", codepage, encoding)
9391098 self.encoding = encoding
9401099 if self.codepage != 1200: # utf_16_le
@@ -945,7 +1104,7 @@
9451104 except:
9461105 ei = sys.exc_info()[:2]
9471106 fprintf(self.logfile,
948- "ERROR *** codepage %d -> encoding %r -> %s: %s\n",
1107+ "ERROR *** codepage %r -> encoding %r -> %s: %s\n",
9491108 self.codepage, self.encoding, ei[0].__name__.split(".")[-1], ei[1])
9501109 raise
9511110 if self.raw_user_name:
@@ -955,6 +1114,7 @@
9551114 # print "CODEPAGE: user name decoded from %r to %r" % (self.user_name, strg)
9561115 self.user_name = strg
9571116 self.raw_user_name = False
1117+ return self.encoding
9581118
9591119 def handle_codepage(self, data):
9601120 # DEBUG = 0
@@ -976,11 +1136,39 @@
9761136 assert datemode in (0, 1)
9771137 self.datemode = datemode
9781138
1139+ def handle_externname(self, data):
1140+ blah = DEBUG or self.verbosity >= 2
1141+ if self.biff_version >= 80:
1142+ option_flags, other_info =unpack("<HI", data[:6])
1143+ pos = 6
1144+ name, pos = unpack_unicode_update_pos(data, pos, lenlen=1)
1145+ extra = data[pos:]
1146+ if self._supbook_types[-1] == SUPBOOK_ADDIN:
1147+ self.addin_func_names.append(name)
1148+ if blah:
1149+ fprintf(self.logfile,
1150+ "EXTERNNAME: sbktype=%d oflags=0x%04x oinfo=0x%08x name=%r extra=%r\n",
1151+ self._supbook_types[-1], option_flags, other_info, name, extra)
1152+
9791153 def handle_externsheet(self, data):
1154+ self.derive_encoding() # in case CODEPAGE record missing/out of order/wrong
9801155 self._extnsht_count += 1 # for use as a 1-based index
981- blah = DEBUG or self.verbosity >= 2
1156+ blah1 = DEBUG or self.verbosity >= 1
1157+ blah2 = DEBUG or self.verbosity >= 2
9821158 if self.biff_version >= 80:
9831159 num_refs = unpack("<H", data[0:2])[0]
1160+ bytes_reqd = num_refs * 6 + 2
1161+ while len(data) < bytes_reqd:
1162+ if blah1:
1163+ fprintf(
1164+ self.logfile,
1165+ "INFO: EXTERNSHEET needs %d bytes, have %d\n",
1166+ bytes_reqd, len(data),
1167+ )
1168+ code2, length2, data2 = self.get_record_parts()
1169+ if code2 != XL_CONTINUE:
1170+ raise XLRDError("Missing CONTINUE after EXTERNSHEET record")
1171+ data += data2
9841172 pos = 2
9851173 for k in xrange(num_refs):
9861174 info = unpack("<HHH", data[pos:pos+6])
@@ -987,7 +1175,7 @@
9871175 ref_recordx, ref_first_sheetx, ref_last_sheetx = info
9881176 self._externsheet_info.append(info)
9891177 pos += 6
990- if blah:
1178+ if blah2:
9911179 fprintf(
9921180 self.logfile,
9931181 "EXTERNSHEET(b8): k = %2d, record = %2d, first_sheet = %5d, last sheet = %5d\n",
@@ -995,7 +1183,7 @@
9951183 )
9961184 else:
9971185 nc, ty = unpack("<BB", data[:2])
998- if blah:
1186+ if blah2:
9991187 print "EXTERNSHEET(b7-):"
10001188 hex_char_dump(data, 0, len(data))
10011189 msg = {
@@ -1008,12 +1196,32 @@
10081196 if ty == 3:
10091197 sheet_name = unicode(data[2:nc+2], self.encoding)
10101198 self._extnsht_name_from_num[self._extnsht_count] = sheet_name
1011- if blah: print self._extnsht_name_from_num
1199+ if blah2: print self._extnsht_name_from_num
10121200 if not (1 <= ty <= 4):
10131201 ty = 0
10141202 self._externsheet_type_b57.append(ty)
10151203
1016- def handle_filepass(self, _unused_data):
1204+ def handle_filepass(self, data):
1205+ if self.verbosity >= 2:
1206+ logf = self.logfile
1207+ fprintf(logf, "FILEPASS:\n")
1208+ hex_char_dump(data, 0, len(data), base=0, fout=logf)
1209+ if self.biff_version >= 80:
1210+ kind1, = unpack('<H', data[:2])
1211+ if kind1 == 0: # weak XOR encryption
1212+ key, hash_value = unpack('<HH', data[2:])
1213+ fprintf(logf,
1214+ 'weak XOR: key=0x%04x hash=0x%04x\n',
1215+ key, hash_value)
1216+ elif kind1 == 1:
1217+ kind2, = unpack('<H', data[4:6])
1218+ if kind2 == 1: # BIFF8 standard encryption
1219+ caption = "BIFF8 std"
1220+ elif kind2 == 2:
1221+ caption = "BIFF8 strong"
1222+ else:
1223+ caption = "** UNKNOWN ENCRYPTION METHOD **"
1224+ fprintf(logf, "%s\n", caption)
10171225 raise XLRDError("Workbook is encrypted")
10181226
10191227 def handle_name(self, data):
@@ -1021,6 +1229,7 @@
10211229 bv = self.biff_version
10221230 if bv < 50:
10231231 return
1232+ self.derive_encoding()
10241233 # print
10251234 # hex_char_dump(data, 0, len(data))
10261235 (
@@ -1130,8 +1339,12 @@
11301339 name_lcase = nobj.name.lower()
11311340 key = (name_lcase, nobj.scope)
11321341 if name_and_scope_map.has_key(key):
1133- raise XLRDError(
1134- 'Duplicate entry %r in name_and_scope_map' % (key, ))
1342+ msg = 'Duplicate entry %r in name_and_scope_map' % (key, )
1343+ if 0:
1344+ raise XLRDError(msg)
1345+ else:
1346+ if self.verbosity:
1347+ print >> f, msg
11351348 name_and_scope_map[key] = nobj
11361349 if name_map.has_key(name_lcase):
11371350 name_map[name_lcase].append((nobj.scope, nobj))
@@ -1152,6 +1365,7 @@
11521365 # if DEBUG: print "---> handle_obj type=%d id=0x%08x" % (obj_type, obj_id)
11531366
11541367 def handle_supbook(self, data):
1368+ self._supbook_types.append(None)
11551369 blah = DEBUG or self.verbosity >= 2
11561370 if 0:
11571371 print "SUPBOOK:"
@@ -1160,6 +1374,7 @@
11601374 sbn = self._supbook_count
11611375 self._supbook_count += 1
11621376 if data[2:4] == "\x01\x04":
1377+ self._supbook_types[-1] = SUPBOOK_INTERNAL
11631378 self._supbook_locals_inx = self._supbook_count - 1
11641379 if blah:
11651380 print "SUPBOOK[%d]: internal 3D refs; %d sheets" % (sbn, num_sheets)
@@ -1166,12 +1381,16 @@
11661381 print " _all_sheets_map", self._all_sheets_map
11671382 return
11681383 if data[0:4] == "\x01\x00\x01\x3A":
1384+ self._supbook_types[-1] = SUPBOOK_ADDIN
1385+ self._supbook_addins_inx = self._supbook_count - 1
11691386 if blah: print "SUPBOOK[%d]: add-in functions" % sbn
11701387 return
11711388 url, pos = unpack_unicode_update_pos(data, 2, lenlen=2)
11721389 if num_sheets == 0:
1390+ self._supbook_types[-1] = SUPBOOK_DDEOLE
11731391 if blah: print "SUPBOOK[%d]: DDE/OLE document = %r" % (sbn, url)
11741392 return
1393+ self._supbook_types[-1] = SUPBOOK_EXTERNAL
11751394 if blah: print "SUPBOOK[%d]: url = %r" % (sbn, url)
11761395 sheet_names = []
11771396 for x in range(num_sheets):
@@ -1183,7 +1402,8 @@
11831402 # This a BIFF 4W special.
11841403 # The SHEETHDR record is followed by a (BOF ... EOF) substream containing
11851404 # a worksheet.
1186- # DEBUG = 0
1405+ # DEBUG = 1
1406+ self.derive_encoding()
11871407 sheet_len = unpack('<i', data[:4])[0]
11881408 sheet_name = unpack_string(data, 4, self.encoding, lenlen=1)
11891409 sheetno = self._sheethdr_count
@@ -1193,10 +1413,11 @@
11931413 posn = BOF_posn - 4 - len(data)
11941414 if DEBUG: print >> self.logfile, 'SHEETHDR %d at posn %d: len=%d name=%r' % (sheetno, posn, sheet_len, sheet_name)
11951415 self.initialise_format_info()
1196- sht = self.get_sheet(sheetno)
1416+ if DEBUG: print >> self.logfile, 'SHEETHDR: xf epilogue flag is %d' % self._xf_epilogue_done
1417+ self._sheet_list.append(None) # get_sheet updates _sheet_list but needs a None beforehand
1418+ self.get_sheet(sheetno, update_pos=False)
11971419 if DEBUG: print >> self.logfile, 'SHEETHDR: posn after get_sheet() =', self._position
1198- self.position(BOF_posn + sheet_len)
1199- self._sheet_list.append(sht)
1420+ self._position = BOF_posn + sheet_len
12001421
12011422 def handle_sheetsoffset(self, data):
12021423 # DEBUG = 0
@@ -1243,7 +1464,7 @@
12431464
12441465 def parse_globals(self):
12451466 # DEBUG = 0
1246- # self.position(self._own_bof) # no need to position, just start reading (after the BOF)
1467+ # no need to position, just start reading (after the BOF)
12471468 formatting.initialise_book(self)
12481469 while 1:
12491470 rc, length, data = self.get_record_parts()
@@ -1264,6 +1485,8 @@
12641485 self.handle_codepage(data)
12651486 elif rc == XL_COUNTRY:
12661487 self.handle_country(data)
1488+ elif rc == XL_EXTERNNAME:
1489+ self.handle_externname(data)
12671490 elif rc == XL_EXTERNSHEET:
12681491 self.handle_externsheet(data)
12691492 elif rc == XL_FILEPASS:
@@ -1303,9 +1526,6 @@
13031526 # print "parse_globals: ignoring record code 0x%04x" % rc
13041527 pass
13051528
1306- def position(self, pos):
1307- self._position = pos
1308-
13091529 def read(self, pos, length):
13101530 data = self.mem[pos:pos+length]
13111531 self._position = pos + len(data)
@@ -1315,23 +1535,25 @@
13151535 # DEBUG = 1
13161536 # if DEBUG: print >> self.logfile, "getbof(): position", self._position
13171537 if DEBUG: print >> self.logfile, "reqd: 0x%04x" % rqd_stream
1538+ def bof_error(msg):
1539+ raise XLRDError('Unsupported format, or corrupt file: ' + msg)
13181540 savpos = self._position
13191541 opcode = self.get2bytes()
13201542 if opcode == MY_EOF:
1321- raise XLRDError('Expected BOF record; met end of file')
1543+ bof_error('Expected BOF record; met end of file')
13221544 if opcode not in bofcodes:
1323- raise XLRDError('Expected BOF record; found 0x%04x' % opcode)
1545+ bof_error('Expected BOF record; found %r' % self.mem[savpos:savpos+8])
13241546 length = self.get2bytes()
13251547 if length == MY_EOF:
1326- raise XLRDError('Incomplete BOF record[1]; met end of file')
1548+ bof_error('Incomplete BOF record[1]; met end of file')
13271549 if length < boflen[opcode] or length > 20:
1328- raise XLRDError(
1550+ bof_error(
13291551 'Invalid length (%d) for BOF record type 0x%04x'
13301552 % (length, opcode))
13311553 data = self.read(self._position, length);
13321554 if DEBUG: print >> self.logfile, "\ngetbof(): data=%r" % data
13331555 if len(data) < length:
1334- raise XLRDError('Incomplete BOF record[2]; met end of file')
1556+ bof_error('Incomplete BOF record[2]; met end of file')
13351557 version1 = opcode >> 8
13361558 version2, streamtype = unpack('<HH', data[0:4])
13371559 if DEBUG:
@@ -1354,14 +1576,14 @@
13541576 else:
13551577 # dodgy one, created by a 3rd-party tool
13561578 version = {
1357- 0x0000: 2,
1358- 0x0007: 2,
1359- 0x0200: 2,
1360- 0x0300: 3,
1361- 0x0400: 4,
1362- }.get(version2, 0) * 10
1579+ 0x0000: 21,
1580+ 0x0007: 21,
1581+ 0x0200: 21,
1582+ 0x0300: 30,
1583+ 0x0400: 40,
1584+ }.get(version2, 0)
13631585 elif version1 in (0x04, 0x02, 0x00):
1364- version = {0x04: 40, 0x02: 30, 0x00: 20}[version1]
1586+ version = {0x04: 40, 0x02: 30, 0x00: 21}[version1]
13651587
13661588 if version == 40 and streamtype == XL_WORKBOOK_GLOBALS_4W:
13671589 version = 45 # i.e. 4W
@@ -1377,8 +1599,8 @@
13771599 if version < 50 and streamtype == XL_WORKSHEET:
13781600 return version
13791601 if version >= 50 and streamtype == 0x0100:
1380- raise XLRDError("Workspace file -- no spreadsheet data")
1381- raise XLRDError(
1602+ bof_error("Workspace file -- no spreadsheet data")
1603+ bof_error(
13821604 'BOF not workbook/worksheet: op=0x%04x vers=0x%04x strm=0x%04x build=%d year=%d -> BIFF%d' \
13831605 % (opcode, version2, streamtype, build, year, version)
13841606 )
@@ -1403,13 +1625,15 @@
14031625 relcol = 0
14041626 return outrow, outcol, relrow, relcol
14051627
1406-def colname(x, _A2Z="ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
1407- assert 0 <= x <= 255
1408- if x <= 25:
1409- return _A2Z[x]
1410- else:
1411- quot, rem = divmod(x, 26)
1412- return _A2Z[quot-1] + _A2Z[rem]
1628+def colname(colx, _A2Z="ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
1629+ assert colx >= 0
1630+ name = ''
1631+ while 1:
1632+ quot, rem = divmod(colx, 26)
1633+ name = _A2Z[rem] + name
1634+ if not quot:
1635+ return name
1636+ colx = quot - 1
14131637
14141638 def display_cell_address(rowx, colx, relrow, relcol):
14151639 if relrow:
--- branches/tl3_0/python-lib/xlrd/xlrd/xldate.py (revision 43)
+++ branches/tl3_0/python-lib/xlrd/xlrd/xldate.py (revision 44)
@@ -3,12 +3,14 @@
33 # No part of the content of this file was derived from the works of David Giffin.
44
55 ##
6-# <p>Copyright ゥ 2005-2006 Stephen John Machin, Lingfo Pty Ltd</p>
6+# <p>Copyright ゥ 2005-2008 Stephen John Machin, Lingfo Pty Ltd</p>
77 # <p>This module is part of the xlrd package, which is released under a BSD-style licence.</p>
88 #
99 # <p>Provides function(s) for dealing with Microsoft Excel dates.</p>
1010 ##
1111
12+# 2008-10-18 SJM Fix bug in xldate_from_date_tuple (affected some years after 2099)
13+
1214 # The conversion from days to (year, month, day) starts with
1315 # an integral "julian day number" aka JDN.
1416 # FWIW, JDN 0 corresponds to noon on Monday November 24 in Gregorian year -4713.
@@ -70,7 +72,6 @@
7072 minutes, second = divmod(seconds, 60)
7173 # minute = minutes % 60; hour = minutes // 60
7274 hour, minute = divmod(minutes, 60)
73-
7475 if xldays >= _XLDAYS_TOO_LARGE[datemode]:
7576 raise XLDateTooLarge(xldate)
7677
@@ -136,7 +137,7 @@
136137 else:
137138 Mp = M - 3
138139 jdn = ifd(1461 * Yp, 4) + ifd(979 * Mp + 16, 32) + \
139- day - 1364 - (3 * ifd(ifd(Yp + 184, 100), 4))
140+ day - 1364 - ifd(ifd(Yp + 184, 100) * 3, 4)
140141 xldays = jdn - _JDN_delta[datemode]
141142 if xldays <= 0:
142143 raise XLDateBadTuple("Invalid (year, month, day): %r" % ((year, month, day),))
--- branches/tl3_0/python-lib/xlrd/xlrd/timemachine.py (revision 43)
+++ branches/tl3_0/python-lib/xlrd/xlrd/timemachine.py (revision 44)
@@ -1,7 +1,7 @@
11 # -*- coding: cp1252 -*-
22
33 ##
4-# <p>Copyright ゥ 2006 Stephen John Machin, Lingfo Pty Ltd</p>
4+# <p>Copyright ゥ 2006-2008 Stephen John Machin, Lingfo Pty Ltd</p>
55 # <p>This module is part of the xlrd package, which is released under a BSD-style licence.</p>
66 ##
77
@@ -8,6 +8,8 @@
88 # timemachine.py -- adaptation for earlier Pythons e.g. 2.1
99 # usage: from timemachine import *
1010
11+# 2008-02-08 SJM Generalised method of detecting IronPython
12+
1113 import sys
1214
1315 python_version = sys.version_info[:2] # e.g. version 2.4 -> (2, 4)
@@ -15,7 +17,7 @@
1517 CAN_PICKLE_ARRAY = python_version >= (2, 5)
1618 CAN_SUBCLASS_BUILTIN = python_version >= (2, 2)
1719
18-if sys.version.startswith("IronPython"):
20+if sys.version.find("IronPython") >= 0:
1921 array_array = None
2022 else:
2123 from array import array as array_array
--- branches/tl3_0/python-lib/xlrd/xlrd/compdoc.py (revision 43)
+++ branches/tl3_0/python-lib/xlrd/xlrd/compdoc.py (revision 44)
@@ -4,15 +4,18 @@
44 # Implements the minimal functionality required
55 # to extract a "Workbook" or "Book" stream (as one big string)
66 # from an OLE2 Compound Document file.
7-# <p>Copyright ゥ 2005-2006 Stephen John Machin, Lingfo Pty Ltd</p>
7+# <p>Copyright ゥ 2005-2008 Stephen John Machin, Lingfo Pty Ltd</p>
88 # <p>This module is part of the xlrd package, which is released under a BSD-style licence.</p>
99 ##
1010
1111 # No part of the content of this file was derived from the works of David Giffin.
1212
13+# 2008-11-04 SJM Avoid assertion error when -1 used instead of -2 for first_SID of empty SCSS [Frank Hoffsuemmer]
14+# 2007-09-08 SJM Warning message if sector sizes are extremely large.
15+# 2007-05-07 SJM Meaningful exception instead of IndexError if a SAT (sector allocation table) is corrupted.
1316 # 2007-04-22 SJM Missing "<" in a struct.unpack call => can't open files on bigendian platforms.
14-# 2007-05-07 SJM Meaningful exception instead of IndexError if a SAT (sector allocation table) is corrupted.
1517
18+
1619 import sys
1720 from struct import unpack
1821 from timemachine import *
@@ -89,6 +92,16 @@
8992 print >> logfile, "\nCompDoc format: version=0x%04x revision=0x%04x" % (version, revision)
9093 self.mem = mem
9194 ssz, sssz = unpack('<HH', mem[30:34])
95+ if ssz > 20: # allows for 2**20 bytes i.e. 1MB
96+ print >> logfile, \
97+ "WARNING: sector size (2**%d) is preposterous; assuming 512 and continuing ..." \
98+ % ssz
99+ ssz = 9
100+ if sssz > ssz:
101+ print >> logfile, \
102+ "WARNING: short stream sector size (2**%d) is preposterous; assuming 64 and continuing ..." \
103+ % sssz
104+ sssz = 6
92105 self.sec_size = sec_size = 1 << ssz
93106 self.short_sec_size = 1 << sssz
94107 (
@@ -149,7 +162,8 @@
149162 news = list(unpack(fmt, mem[offset:offset+sec_size]))
150163 self.SAT.extend(news)
151164 if DEBUG:
152- print >> logfile, "SAT", self.SAT
165+ print >> logfile, "SAT: len =", len(self.SAT)
166+ print >> logfile, self.SAT
153167 # print >> logfile, "SAT ",
154168 # for i, s in enumerate(self.SAT):
155169 # print >> logfile, "entry: %4d offset: %6d, next entry: %4d" % (i, 512 + sec_size * i, s)
@@ -176,9 +190,18 @@
176190 #
177191 sscs_dir = self.dirlist[0]
178192 assert sscs_dir.etype == 5 # root entry
179- self.SSCS = self._get_stream(
180- self.mem, 512, self.SAT, sec_size, sscs_dir.first_SID,
181- sscs_dir.tot_size, name="SSCS")
193+ if sscs_dir.first_SID < 0 and sscs_dir.tot_size == 0:
194+ # Problem reported by Frank Hoffsuemmer: some software was
195+ # writing -1 instead of -2 (EOCSID) for the first_SID
196+ # when the SCCS was empty. Not having EOCSID caused assertion
197+ # failure in _get_stream.
198+ # Solution: avoid calling _get_stream in any case when the
199+ # SCSS appears to be empty.
200+ self.SSCS = ""
201+ else:
202+ self.SSCS = self._get_stream(
203+ self.mem, 512, self.SAT, sec_size, sscs_dir.first_SID,
204+ sscs_dir.tot_size, name="SSCS")
182205 # if DEBUG: print >> logfile, "SSCS", repr(self.SSCS)
183206 #
184207 # === build the SSAT ===
--- branches/tl3_0/python-lib/xlrd/xlrd/formula.py (revision 43)
+++ branches/tl3_0/python-lib/xlrd/xlrd/formula.py (revision 44)
@@ -3,7 +3,7 @@
33 ##
44 # Module for parsing/evaluating Microsoft Excel formulas.
55 #
6-# <p>Copyright ゥ 2005-2006 Stephen John Machin, Lingfo Pty Ltd</p>
6+# <p>Copyright ゥ 2005-2009 Stephen John Machin, Lingfo Pty Ltd</p>
77 # <p>This module is part of the xlrd package, which is released under
88 # a BSD-style licence.</p>
99 ##
@@ -411,6 +411,11 @@
411411 % (refx, len(bk._externsheet_info))
412412 return (-101, -101)
413413 ref_recordx, ref_first_sheetx, ref_last_sheetx = info
414+ if ref_recordx == bk._supbook_addins_inx:
415+ if blah:
416+ print "/// get_externsheet_local_range(refx=%d) -> addins %r" % (refx, info)
417+ assert ref_first_sheetx == 0xFFFE == ref_last_sheetx
418+ return (-5, -5)
414419 if ref_recordx != bk._supbook_locals_inx:
415420 if blah:
416421 print "/// get_externsheet_local_range(refx=%d) -> external %r" % (refx, info)
@@ -1571,7 +1576,11 @@
15711576 if blah:
15721577 print " FuncID=%d nargs=%d macro=%d prompt=%d" \
15731578 % (funcx, nargs, macro, prompt)
1574- func_attrs = func_defs.get(funcx, None)
1579+ #### TODO #### if funcx == 255: # call add-in function
1580+ if funcx == 255:
1581+ func_attrs = ("CALL_ADDIN", 1, 30)
1582+ else:
1583+ func_attrs = func_defs.get(funcx, None)
15751584 if not func_attrs:
15761585 print >> bk.logfile, "*** formula/tFuncVar unknown FuncID:%d" \
15771586 % funcx
@@ -1652,11 +1661,11 @@
16521661 # if blah: print >> bk.logfile, " ", res
16531662 elif opcode == 0x1A: # tRef3d
16541663 if bv >= 80:
1655- res = get_cell_addr(data, pos+3, bv, reldelta)
1664+ res = get_cell_addr(data, pos+3, bv, reldelta, browx, bcolx)
16561665 refx = unpack("<H", data[pos+1:pos+3])[0]
16571666 shx1, shx2 = get_externsheet_local_range(bk, refx, blah)
16581667 else:
1659- res = get_cell_addr(data, pos+15, bv, reldelta)
1668+ res = get_cell_addr(data, pos+15, bv, reldelta, browx, bcolx)
16601669 raw_extshtx, raw_shx1, raw_shx2 = \
16611670 unpack("<hxxxxxxxxhh", data[pos+1:pos+15])
16621671 if blah:
@@ -1749,7 +1758,13 @@
17491758 shx1, shx2 = (-1, -1) # internal, any sheet
17501759 else:
17511760 shx1, shx2 = (-666, -666)
1752- if dodgy or shx1 < -1:
1761+ okind = oUNK
1762+ ovalue = None
1763+ if shx1 == -5: # addin func name
1764+ okind = oSTRG
1765+ ovalue = bk.addin_func_names[tgtnamex]
1766+ otext = '"' + ovalue.replace('"', '""') + '"'
1767+ elif dodgy or shx1 < -1:
17531768 otext = "<<Name #%d in external(?) file #%d>>" \
17541769 % (tgtnamex, origrefx)
17551770 else:
@@ -1761,7 +1776,7 @@
17611776 % (bk._sheet_names[tgtobj.scope], tgtobj.name)
17621777 if blah:
17631778 print >> bk.logfile, " tNameX: setting text to", repr(res.text)
1764- res = Operand(oUNK, None, LEAF_RANK, otext)
1779+ res = Operand(okind, ovalue, LEAF_RANK, otext)
17651780 spush(res)
17661781 elif is_error_opcode(opcode):
17671782 any_err = 1
--- branches/tl3_0/python-lib/xlrd/xlrd/licences.py (revision 43)
+++ branches/tl3_0/python-lib/xlrd/xlrd/licences.py (revision 44)
@@ -1,7 +1,7 @@
11 # -*- coding: cp1252 -*-
22
33 """
4-Portions copyright ゥ 2005-2006, Stephen John Machin, Lingfo Pty Ltd
4+Portions copyright ゥ 2005-2009, Stephen John Machin, Lingfo Pty Ltd
55 All rights reserved.
66
77 Redistribution and use in source and binary forms, with or without
@@ -8,15 +8,15 @@
88 modification, are permitted provided that the following conditions are met:
99
1010 1. Redistributions of source code must retain the above copyright notice,
11-this list of conditions and the following disclaimer.
11+this list of conditions and the following disclaimer.
1212
1313 2. Redistributions in binary form must reproduce the above copyright notice,
1414 this list of conditions and the following disclaimer in the documentation
15-and/or other materials provided with the distribution.
15+and/or other materials provided with the distribution.
1616
1717 3. None of the names of Stephen John Machin, Lingfo Pty Ltd and any
1818 contributors may be used to endorse or promote products derived from this
19-software without specific prior written permission.
19+software without specific prior written permission.
2020
2121 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2222 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
@@ -36,7 +36,7 @@
3636 * Copyright (c) 2001 David Giffin.
3737 * All rights reserved.
3838 *
39- * Based on the the Java version: Andrew Khan Copyright (c) 2000.
39+ * Based on the the Java version: Andrew Khan Copyright (c) 2000.
4040 *
4141 *
4242 * Redistribution and use in source and binary forms, with or without
Show on old repository browser