summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2017-02-20 21:29:22 +0100
committerIuri de Silvio <iurisilvio@gmail.com>2017-02-20 17:29:22 -0300
commit0ca5520bbc1474dbd872a3f330c681a5201336fd (patch)
tree84225bc603981a073c53e90d8ca12d250a9a94b5
parente66eb4a18967dd4d35e6e9da265622e9e4015103 (diff)
downloadtablib-0ca5520bbc1474dbd872a3f330c681a5201336fd.tar.gz
Replaced vendored xlrd/xlwt by dependencies (#277)
Refs #273.
-rw-r--r--NOTICE164
-rwxr-xr-xsetup.py6
-rw-r--r--tablib/compat.py6
-rw-r--r--tablib/formats/_xls.py5
-rw-r--r--tablib/packages/xlrd/__init__.py1720
-rw-r--r--tablib/packages/xlrd/biffh.py639
-rw-r--r--tablib/packages/xlrd/compdoc.py358
-rw-r--r--tablib/packages/xlrd/doc/compdoc.html69
-rw-r--r--tablib/packages/xlrd/doc/xlrd.html1845
-rw-r--r--tablib/packages/xlrd/examples/namesdemo.xlsbin22528 -> 0 bytes
-rw-r--r--tablib/packages/xlrd/examples/xlrdnameAPIdemo.py178
-rw-r--r--tablib/packages/xlrd/formatting.py1256
-rw-r--r--tablib/packages/xlrd/formula.py2092
-rw-r--r--tablib/packages/xlrd/licences.py77
-rw-r--r--tablib/packages/xlrd/sheet.py1768
-rw-r--r--tablib/packages/xlrd/timemachine.py44
-rw-r--r--tablib/packages/xlrd/xldate.py171
-rw-r--r--tablib/packages/xlrd3/__init__.py1642
-rw-r--r--tablib/packages/xlrd3/biffh.py620
-rw-r--r--tablib/packages/xlrd3/compdoc.py346
-rw-r--r--tablib/packages/xlrd3/formatting.py1186
-rw-r--r--tablib/packages/xlrd3/formula.py2083
-rw-r--r--tablib/packages/xlrd3/sheet.py1611
-rw-r--r--tablib/packages/xlrd3/xfcell.py276
-rw-r--r--tablib/packages/xlrd3/xfconst.py84
-rw-r--r--tablib/packages/xlrd3/xldate.py167
-rw-r--r--tablib/packages/xlwt/BIFFRecords.py2393
-rw-r--r--tablib/packages/xlwt/Bitmap.py262
-rw-r--r--tablib/packages/xlwt/Cell.py243
-rw-r--r--tablib/packages/xlwt/Column.py34
-rw-r--r--tablib/packages/xlwt/CompoundDoc.py516
-rw-r--r--tablib/packages/xlwt/ExcelFormula.py43
-rw-r--r--tablib/packages/xlwt/ExcelFormulaLexer.py128
-rw-r--r--tablib/packages/xlwt/ExcelFormulaParser.py677
-rw-r--r--tablib/packages/xlwt/ExcelMagic.py862
-rw-r--r--tablib/packages/xlwt/Formatting.py261
-rw-r--r--tablib/packages/xlwt/Row.py253
-rw-r--r--tablib/packages/xlwt/Style.py592
-rw-r--r--tablib/packages/xlwt/UnicodeUtils.py81
-rw-r--r--tablib/packages/xlwt/Utils.py196
-rw-r--r--tablib/packages/xlwt/Workbook.py636
-rw-r--r--tablib/packages/xlwt/Worksheet.py1297
-rw-r--r--tablib/packages/xlwt/__init__.py13
-rw-r--r--tablib/packages/xlwt/antlr.py2874
-rw-r--r--tablib/packages/xlwt/doc/xlwt.html199
-rw-r--r--tablib/packages/xlwt/examples/big-16Mb.py35
-rw-r--r--tablib/packages/xlwt/examples/big-35Mb.py34
-rw-r--r--tablib/packages/xlwt/examples/blanks.py36
-rw-r--r--tablib/packages/xlwt/examples/col_width.py19
-rw-r--r--tablib/packages/xlwt/examples/country.py10
-rw-r--r--tablib/packages/xlwt/examples/dates.py37
-rw-r--r--tablib/packages/xlwt/examples/format.py38
-rw-r--r--tablib/packages/xlwt/examples/formula_names.py34
-rw-r--r--tablib/packages/xlwt/examples/formulas.py47
-rw-r--r--tablib/packages/xlwt/examples/hyperlinks.py28
-rw-r--r--tablib/packages/xlwt/examples/image.py12
-rw-r--r--tablib/packages/xlwt/examples/merged.py39
-rw-r--r--tablib/packages/xlwt/examples/merged0.py30
-rw-r--r--tablib/packages/xlwt/examples/merged1.py102
-rw-r--r--tablib/packages/xlwt/examples/mini.py9
-rw-r--r--tablib/packages/xlwt/examples/num_formats.py60
-rw-r--r--tablib/packages/xlwt/examples/numbers.py25
-rw-r--r--tablib/packages/xlwt/examples/outline.py113
-rw-r--r--tablib/packages/xlwt/examples/panes.py58
-rw-r--r--tablib/packages/xlwt/examples/parse-fmla.py12
-rw-r--r--tablib/packages/xlwt/examples/protection.py122
-rw-r--r--tablib/packages/xlwt/examples/python.bmpbin37446 -> 0 bytes
-rw-r--r--tablib/packages/xlwt/examples/row_styles.py17
-rw-r--r--tablib/packages/xlwt/examples/row_styles_empty.py18
-rw-r--r--tablib/packages/xlwt/examples/simple.py24
-rw-r--r--tablib/packages/xlwt/examples/sst.py52
-rw-r--r--tablib/packages/xlwt/examples/unicode0.py12
-rw-r--r--tablib/packages/xlwt/examples/unicode1.py28
-rw-r--r--tablib/packages/xlwt/examples/unicode2.py19
-rw-r--r--tablib/packages/xlwt/examples/wsprops.py155
-rw-r--r--tablib/packages/xlwt/examples/xlwt_easyxf_simple_demo.py46
-rw-r--r--tablib/packages/xlwt/excel-formula.g374
-rw-r--r--tablib/packages/xlwt3/BIFFRecords.py2392
-rw-r--r--tablib/packages/xlwt3/Bitmap.py258
-rw-r--r--tablib/packages/xlwt3/Cell.py233
-rw-r--r--tablib/packages/xlwt3/Column.py34
-rw-r--r--tablib/packages/xlwt3/CompoundDoc.py516
-rw-r--r--tablib/packages/xlwt3/ExcelFormula.py41
-rw-r--r--tablib/packages/xlwt3/ExcelFormulaLexer.py126
-rw-r--r--tablib/packages/xlwt3/ExcelFormulaParser.py659
-rw-r--r--tablib/packages/xlwt3/ExcelMagic.py859
-rw-r--r--tablib/packages/xlwt3/Formatting.py261
-rw-r--r--tablib/packages/xlwt3/Row.py253
-rw-r--r--tablib/packages/xlwt3/Style.py593
-rw-r--r--tablib/packages/xlwt3/UnicodeUtils.py79
-rw-r--r--tablib/packages/xlwt3/Utils.py196
-rw-r--r--tablib/packages/xlwt3/Workbook.py635
-rw-r--r--tablib/packages/xlwt3/Worksheet.py1296
-rw-r--r--tablib/packages/xlwt3/__init__.py9
-rw-r--r--tablib/packages/xlwt3/antlr.py2868
95 files changed, 7 insertions, 42919 deletions
diff --git a/NOTICE b/NOTICE
index f79efa3..b5642d4 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,5 +1,5 @@
Tablib includes some vendorized python libraries: ordereddict, odfpy, pyyaml,
-simplejson, unicodecsv, xlrd, xlrd3, xlwt, and xlwt3.
+simplejson, unicodecsv.
Markup License
==============
@@ -295,165 +295,3 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those of the
authors and should not be interpreted as representing official policies, either expressed
or implied, of Jeremy Dunck.
-
-
-
-
-XLWT (and XLWT3) License
-========================
-
-Portions copyright © 2007, Stephen John Machin, Lingfo Pty Ltd
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright notice,
-this list of conditions and the following disclaimer in the documentation
-and/or other materials provided with the distribution.
-
-3. None of the names of Stephen John Machin, Lingfo Pty Ltd and any
-contributors may be used to endorse or promote products derived from this
-software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-THE POSSIBILITY OF SUCH DAMAGE.
-"""
-
-"""
- Copyright (C) 2005 Roman V. Kiseliov
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
- 3. All advertising materials mentioning features or use of this
- software must display the following acknowledgment:
- "This product includes software developed by
- Roman V. Kiseliov <roman@kiseliov.ru>."
-
- 4. Redistributions of any form whatsoever must retain the following
- acknowledgment:
- "This product includes software developed by
- Roman V. Kiseliov <roman@kiseliov.ru>."
-
- THIS SOFTWARE IS PROVIDED BY Roman V. Kiseliov ``AS IS'' AND ANY
- EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Roman V. Kiseliov OR
- ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Roman V. Kiseliov
-Russia
-Kursk
-Libknecht St., 4
-
-+7(0712)56-09-83
-
-<roman@kiseliov.ru>
-Subject: pyExcelerator
-
-
-
-
-XLRD (and XLRD3) License
-========================
-
-Portions copyright © 2005-2009, Stephen John Machin, Lingfo Pty Ltd
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright notice,
-this list of conditions and the following disclaimer in the documentation
-and/or other materials provided with the distribution.
-
-3. None of the names of Stephen John Machin, Lingfo Pty Ltd and any
-contributors may be used to endorse or promote products derived from this
-software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-THE POSSIBILITY OF SUCH DAMAGE.
-
-
-Copyright (c) 2001 David Giffin.
-All rights reserved.
-
-Based on the the Java version: Andrew Khan Copyright (c) 2000.
-
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-3. All advertising materials mentioning features or use of this
- software must display the following acknowledgment:
- "This product includes software developed by
- David Giffin <david@giffin.org>."
-
-4. Redistributions of any form whatsoever must retain the following
- acknowledgment:
- "This product includes software developed by
- David Giffin <david@giffin.org>."
-
-THIS SOFTWARE IS PROVIDED BY DAVID GIFFIN ``AS IS'' AND ANY
-EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID GIFFIN OR
-ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/setup.py b/setup.py
index b709901..8d824db 100755
--- a/setup.py
+++ b/setup.py
@@ -38,13 +38,9 @@ packages = [
'tablib', 'tablib.formats',
'tablib.packages',
'tablib.packages.omnijson',
- 'tablib.packages.xlwt',
- 'tablib.packages.xlrd',
'tablib.packages.odf',
'tablib.packages.yaml',
'tablib.packages.dbfpy',
- 'tablib.packages.xlwt3',
- 'tablib.packages.xlrd3',
'tablib.packages.odf3',
'tablib.packages.yaml3',
'tablib.packages.dbfpy3'
@@ -53,6 +49,8 @@ packages = [
install = [
'openpyxl',
'unicodecsv',
+ 'xlrd',
+ 'xlwt',
]
with open('tablib/core.py', 'r') as fd:
diff --git a/tablib/compat.py b/tablib/compat.py
index 533d480..9a7b872 100644
--- a/tablib/compat.py
+++ b/tablib/compat.py
@@ -22,9 +22,6 @@ except ImportError:
if is_py3:
from io import BytesIO
- import tablib.packages.xlwt3 as xlwt
- import tablib.packages.xlrd3 as xlrd
- from tablib.packages.xlrd3.biffh import XLRDError
from tablib.packages import markup3 as markup
from tablib.packages.odf3 import opendocument, style, text, table
import tablib.packages.dbfpy3 as dbfpy
@@ -42,9 +39,6 @@ if is_py3:
else:
from cStringIO import StringIO as BytesIO
from cStringIO import StringIO
- import tablib.packages.xlwt as xlwt
- import tablib.packages.xlrd as xlrd
- from tablib.packages.xlrd.biffh import XLRDError
from tablib.packages import markup
from itertools import ifilter
from tablib.packages.odf import opendocument, style, text, table
diff --git a/tablib/formats/_xls.py b/tablib/formats/_xls.py
index 787907a..77e2bb1 100644
--- a/tablib/formats/_xls.py
+++ b/tablib/formats/_xls.py
@@ -5,8 +5,11 @@
import sys
-from tablib.compat import BytesIO, xlwt, xlrd, XLRDError, xrange
+from tablib.compat import BytesIO, xrange
import tablib
+import xlrd
+import xlwt
+from xlrd.biffh import XLRDError
title = 'xls'
extensions = ('xls',)
diff --git a/tablib/packages/xlrd/__init__.py b/tablib/packages/xlrd/__init__.py
deleted file mode 100644
index 9097d9d..0000000
--- a/tablib/packages/xlrd/__init__.py
+++ /dev/null
@@ -1,1720 +0,0 @@
-# -*- coding: cp1252 -*-
-
-__VERSION__ = "0.7.1" # 2009-05-31
-
-# <p>Copyright 2005-2009 Stephen John Machin, Lingfo Pty Ltd</p>
-# <p>This module is part of the xlrd package, which is released under a
-# BSD-style licence.</p>
-
-import licences
-
-##
-# <p><b>A Python module for extracting data from MS Excel spreadsheet files.
-# <br /><br />
-# Version 0.7.1 -- 2009-05-31
-# </b></p>
-#
-# <h2>General information</h2>
-#
-# <h3>Acknowledgements</h3>
-#
-# <p>
-# Development of this module would not have been possible without the document
-# "OpenOffice.org's Documentation of the Microsoft Excel File Format"
-# ("OOo docs" for short).
-# The latest version is available from OpenOffice.org in
-# <a href=http://sc.openoffice.org/excelfileformat.pdf> PDF format</a>
-# and
-# <a href=http://sc.openoffice.org/excelfileformat.odt> ODT format.</a>
-# Small portions of the OOo docs are reproduced in this
-# document. A study of the OOo docs is recommended for those who wish a
-# deeper understanding of the Excel file layout than the xlrd docs can provide.
-# </p>
-#
-# <p>Backporting to Python 2.1 was partially funded by
-# <a href=http://journyx.com/>
-# Journyx - provider of timesheet and project accounting solutions.
-# </a>
-# </p>
-#
-# <p>Provision of formatting information in version 0.6.1 was funded by
-# <a href=http://www.simplistix.co.uk>
-# Simplistix Ltd.
-# </a>
-# </p>
-#
-# <h3>Unicode</h3>
-#
-# <p>This module presents all text strings as Python unicode objects.
-# From Excel 97 onwards, text in Excel spreadsheets has been stored as Unicode.
-# Older files (Excel 95 and earlier) don't keep strings in Unicode;
-# a CODEPAGE record provides a codepage number (for example, 1252) which is
-# used by xlrd to derive the encoding (for same example: "cp1252") which is
-# used to translate to Unicode.</p>
-# <small>
-# <p>If the CODEPAGE record is missing (possible if the file was created
-# by third-party software), xlrd will assume that the encoding is ascii, and keep going.
-# If the actual encoding is not ascii, a UnicodeDecodeError exception will be raised and
-# you will need to determine the encoding yourself, and tell xlrd:
-# <pre>
-# book = xlrd.open_workbook(..., encoding_override="cp1252")
-# </pre></p>
-# <p>If the CODEPAGE record exists but is wrong (for example, the codepage
-# number is 1251, but the strings are actually encoded in koi8_r),
-# it can be overridden using the same mechanism.
-# The supplied runxlrd.py has a corresponding command-line argument, which
-# may be used for experimentation:
-# <pre>
-# runxlrd.py -e koi8_r 3rows myfile.xls
-# </pre></p>
-# <p>The first place to look for an encoding ("codec name") is
-# <a href=http://docs.python.org/lib/standard-encodings.html>
-# the Python documentation</a>.
-# </p>
-# </small>
-#
-# <h3>Dates in Excel spreadsheets</h3>
-#
-# <p>In reality, there are no such things. What you have are floating point
-# numbers and pious hope.
-# There are several problems with Excel dates:</p>
-#
-# <p>(1) Dates are not stored as a separate data type; they are stored as
-# floating point numbers and you have to rely on
-# (a) the "number format" applied to them in Excel and/or
-# (b) knowing which cells are supposed to have dates in them.
-# This module helps with (a) by inspecting the
-# format that has been applied to each number cell;
-# if it appears to be a date format, the cell
-# is classified as a date rather than a number. Feedback on this feature,
-# especially from non-English-speaking locales, would be appreciated.</p>
-#
-# <p>(2) Excel for Windows stores dates by default as the number of
-# days (or fraction thereof) since 1899-12-31T00:00:00. Excel for
-# Macintosh uses a default start date of 1904-01-01T00:00:00. The date
-# system can be changed in Excel on a per-workbook basis (for example:
-# Tools -> Options -> Calculation, tick the "1904 date system" box).
-# This is of course a bad idea if there are already dates in the
-# workbook. There is no good reason to change it even if there are no
-# dates in the workbook. Which date system is in use is recorded in the
-# workbook. A workbook transported from Windows to Macintosh (or vice
-# versa) will work correctly with the host Excel. When using this
-# module's xldate_as_tuple function to convert numbers from a workbook,
-# you must use the datemode attribute of the Book object. If you guess,
-# or make a judgement depending on where you believe the workbook was
-# created, you run the risk of being 1462 days out of kilter.</p>
-#
-# <p>Reference:
-# http://support.microsoft.com/default.aspx?scid=KB;EN-US;q180162</p>
-#
-#
-# <p>(3) The Excel implementation of the Windows-default 1900-based date system works on the
-# incorrect premise that 1900 was a leap year. It interprets the number 60 as meaning 1900-02-29,
-# which is not a valid date. Consequently any number less than 61 is ambiguous. Example: is 59 the
-# result of 1900-02-28 entered directly, or is it 1900-03-01 minus 2 days? The OpenOffice.org Calc
-# program "corrects" the Microsoft problem; entering 1900-02-27 causes the number 59 to be stored.
-# Save as an XLS file, then open the file with Excel -- you'll see 1900-02-28 displayed.</p>
-#
-# <p>Reference: http://support.microsoft.com/default.aspx?scid=kb;en-us;214326</p>
-#
-# <p>(4) The Macintosh-default 1904-based date system counts 1904-01-02 as day 1 and 1904-01-01 as day zero.
-# Thus any number such that (0.0 <= number < 1.0) is ambiguous. Is 0.625 a time of day (15:00:00),
-# independent of the calendar,
-# or should it be interpreted as an instant on a particular day (1904-01-01T15:00:00)?
-# The xldate_* functions in this module
-# take the view that such a number is a calendar-independent time of day (like Python's datetime.time type) for both
-# date systems. This is consistent with more recent Microsoft documentation
-# (for example, the help file for Excel 2002 which says that the first day
-# in the 1904 date system is 1904-01-02).
-#
-# <p>(5) Usage of the Excel DATE() function may leave strange dates in a spreadsheet. Quoting the help file,
-# in respect of the 1900 date system: "If year is between 0 (zero) and 1899 (inclusive),
-# Excel adds that value to 1900 to calculate the year. For example, DATE(108,1,2) returns January 2, 2008 (1900+108)."
-# This gimmick, semi-defensible only for arguments up to 99 and only in the pre-Y2K-awareness era,
-# means that DATE(1899, 12, 31) is interpreted as 3799-12-31.</p>
-#
-# <p>For further information, please refer to the documentation for the xldate_* functions.</p>
-#
-# <h3> Named references, constants, formulas, and macros</h3>
-#
-# <p>
-# A name is used to refer to a cell, a group of cells, a constant
-# value, a formula, or a macro. Usually the scope of a name is global
-# across the whole workbook. However it can be local to a worksheet.
-# For example, if the sales figures are in different cells in
-# different sheets, the user may define the name "Sales" in each
-# sheet. There are built-in names, like "Print_Area" and
-# "Print_Titles"; these two are naturally local to a sheet.
-# </p><p>
-# To inspect the names with a user interface like MS Excel, OOo Calc,
-# or Gnumeric, click on Insert/Names/Define. This will show the global
-# names, plus those local to the currently selected sheet.
-# </p><p>
-# A Book object provides two dictionaries (name_map and
-# name_and_scope_map) and a list (name_obj_list) which allow various
-# ways of accessing the Name objects. There is one Name object for
-# each NAME record found in the workbook. Name objects have many
-# attributes, several of which are relevant only when obj.macro is 1.
-# </p><p>
-# In the examples directory you will find namesdemo.xls which
-# showcases the many different ways that names can be used, and
-# xlrdnamesAPIdemo.py which offers 3 different queries for inspecting
-# the names in your files, and shows how to extract whatever a name is
-# referring to. There is currently one "convenience method",
-# Name.cell(), which extracts the value in the case where the name
-# refers to a single cell. More convenience methods are planned. The
-# source code for Name.cell (in __init__.py) is an extra source of
-# information on how the Name attributes hang together.
-# </p>
-#
-# <p><i>Name information is <b>not</b> extracted from files older than
-# Excel 5.0 (Book.biff_version < 50)</i></p>
-#
-# <h3>Formatting</h3>
-#
-# <h4>Introduction</h4>
-#
-# <p>This collection of features, new in xlrd version 0.6.1, is intended
-# to provide the information needed to (1) display/render spreadsheet contents
-# (say) on a screen or in a PDF file, and (2) copy spreadsheet data to another
-# file without losing the ability to display/render it.</p>
-#
-# <h4>The Palette; Colour Indexes</h4>
-#
-# <p>A colour is represented in Excel as a (red, green, blue) ("RGB") tuple
-# with each component in range(256). However it is not possible to access an
-# unlimited number of colours; each spreadsheet is limited to a palette of 64 different
-# colours (24 in Excel 3.0 and 4.0, 8 in Excel 2.0). Colours are referenced by an index
-# ("colour index") into this palette.
-#
-# Colour indexes 0 to 7 represent 8 fixed built-in colours: black, white, red, green, blue,
-# yellow, magenta, and cyan.<p>
-#
-# The remaining colours in the palette (8 to 63 in Excel 5.0 and later)
-# can be changed by the user. In the Excel 2003 UI, Tools/Options/Color presents a palette
-# of 7 rows of 8 colours. The last two rows are reserved for use in charts.<br />
-# The correspondence between this grid and the assigned
-# colour indexes is NOT left-to-right top-to-bottom.<br />
-# Indexes 8 to 15 correspond to changeable
-# parallels of the 8 fixed colours -- for example, index 7 is forever cyan;
-# index 15 starts off being cyan but can be changed by the user.<br />
-#
-# The default colour for each index depends on the file version; tables of the defaults
-# are available in the source code. If the user changes one or more colours,
-# a PALETTE record appears in the XLS file -- it gives the RGB values for *all* changeable
-# indexes.<br />
-# Note that colours can be used in "number formats": "[CYAN]...." and "[COLOR8]...." refer
-# to colour index 7; "[COLOR16]...." will produce cyan
-# unless the user changes colour index 15 to something else.<br />
-#
-# <p>In addition, there are several "magic" colour indexes used by Excel:<br />
-# 0x18 (BIFF3-BIFF4), 0x40 (BIFF5-BIFF8): System window text colour for border lines
-# (used in XF, CF, and WINDOW2 records)<br />
-# 0x19 (BIFF3-BIFF4), 0x41 (BIFF5-BIFF8): System window background colour for pattern background
-# (used in XF and CF records )<br />
-# 0x43: System face colour (dialogue background colour)<br />
-# 0x4D: System window text colour for chart border lines<br />
-# 0x4E: System window background colour for chart areas<br />
-# 0x4F: Automatic colour for chart border lines (seems to be always Black)<br />
-# 0x50: System ToolTip background colour (used in note objects)<br />
-# 0x51: System ToolTip text colour (used in note objects)<br />
-# 0x7FFF: System window text colour for fonts (used in FONT and CF records)<br />
-# Note 0x7FFF appears to be the *default* colour index. It appears quite often in FONT
-# records.<br />
-#
-# <h4>Default Formatting</h4>
-#
-# Default formatting is applied to all empty cells (those not described by a cell record).
-# Firstly row default information (ROW record, Rowinfo class) is used if available.
-# Failing that, column default information (COLINFO record, Colinfo class) is used if available.
-# As a last resort the worksheet/workbook default cell format will be used; this
-# should always be present in an Excel file,
-# described by the XF record with the fixed index 15 (0-based). By default, it uses the
-# worksheet/workbook default cell style, described by the very first XF record (index 0).
-#
-# <h4> Formatting features not included in xlrd version 0.6.1</h4>
-# <ul>
-# <li>Rich text i.e. strings containing partial <b>bold</b> <i>italic</i>
-# and <u>underlined</u> text, change of font inside a string, etc.
-# See OOo docs s3.4 and s3.2</li>
-# <li>Asian phonetic text (known as "ruby"), used for Japanese furigana. See OOo docs
-# s3.4.2 (p15)</li>
-# <li>Conditional formatting. See OOo docs
-# s5.12, s6.21 (CONDFMT record), s6.16 (CF record)</li>
-# <li>Miscellaneous sheet-level and book-level items e.g. printing layout, screen panes. </li>
-# <li>Modern Excel file versions don't keep most of the built-in
-# "number formats" in the file; Excel loads formats according to the
-# user's locale. Currently xlrd's emulation of this is limited to
-# a hard-wired table that applies to the US English locale. This may mean
-# that currency symbols, date order, thousands separator, decimals separator, etc
-# are inappropriate. Note that this does not affect users who are copying XLS
-# files, only those who are visually rendering cells.</li>
-# </ul>
-#
-# <h3>Loading worksheets on demand</h3>
-#
-# <p>This feature, new in version 0.7.1, is governed by the on_demand argument
-# to the open_workbook() function and allows saving memory and time by loading
-# only those sheets that the caller is interested in, and releasing sheets
-# when no longer required.</p>
-#
-# <p>on_demand=False (default): No change. open_workbook() loads global data
-# and all sheets, releases resources no longer required (principally the
-# str or mmap object containing the Workbook stream), and returns.</p>
-#
-# <p>on_demand=True and BIFF version < 5.0: A warning message is emitted,
-# on_demand is recorded as False, and the old process is followed.</p>
-#
-# <p>on_demand=True and BIFF version >= 5.0: open_workbook() loads global
-# data and returns without releasing resources. At this stage, the only
-# information available about sheets is Book.nsheets and Book.sheet_names().</p>
-#
-# <p>Book.sheet_by_name() and Book.sheet_by_index() will load the requested
-# sheet if it is not already loaded.</p>
-#
-# <p>Book.sheets() will load all/any unloaded sheets.</p>
-#
-# <p>The caller may save memory by calling
-# Book.unload_sheet(sheet_name_or_index) when finished with the sheet.
-# This applies irrespective of the state of on_demand.</p>
-#
-# <p>The caller may re-load an unloaded sheet by calling Book.sheet_by_xxxx()
-# -- except if those required resources have been released (which will
-# have happened automatically when on_demand is false). This is the only
-# case where an exception will be raised.</p>
-#
-# <p>The caller may query the state of a sheet:
-# Book.sheet_loaded(sheet_name_or_index) -> a bool</p>
-#
-##
-
-# 2009-04-27 SJM Integrated on_demand patch by Armando Serrano Lombillo
-# 2008-11-23 SJM Support dumping FILEPASS and EXTERNNAME records; extra info from SUPBOOK records
-# 2008-11-23 SJM colname utility function now supports more than 256 columns
-# 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.
-# 2008-02-08 SJM Preparation for Excel 2.0 support
-# 2008-02-03 SJM Minor tweaks for IronPython support
-# 2008-02-02 SJM Previous change stopped dump() and count_records() ... fixed
-# 2007-12-25 SJM Decouple Book initialisation & loading -- to allow for multiple loaders.
-# 2007-12-20 SJM Better error message for unsupported file format.
-# 2007-12-04 SJM Added support for Excel 2.x (BIFF2) files.
-# 2007-11-20 SJM Wasn't handling EXTERNSHEET record that needed CONTINUE record(s)
-# 2007-07-07 SJM Version changed to 0.7.0 (alpha 1)
-# 2007-07-07 SJM Logfile arg wasn't being passed from open_workbook to compdoc.CompDoc
-# 2007-05-21 SJM If no CODEPAGE record in pre-8.0 file, assume ascii and keep going.
-# 2007-04-22 SJM Removed antique undocumented Book.get_name_dict method.
-
-from timemachine import *
-from biffh import *
-from struct import unpack
-import sys
-import time
-import sheet
-import compdoc
-from xldate import xldate_as_tuple, XLDateError
-from formula import *
-import formatting
-if sys.version.startswith("IronPython"):
- # print >> sys.stderr, "...importing encodings"
- import encodings
-
-empty_cell = sheet.empty_cell # for exposure to the world ...
-
-DEBUG = 0
-
-USE_FANCY_CD = 1
-
-TOGGLE_GC = 0
-import gc
-# gc.set_debug(gc.DEBUG_STATS)
-
-try:
- import mmap
- MMAP_AVAILABLE = 1
-except ImportError:
- MMAP_AVAILABLE = 0
-USE_MMAP = MMAP_AVAILABLE
-
-MY_EOF = 0xF00BAAA # not a 16-bit number
-
-SUPBOOK_UNK, SUPBOOK_INTERNAL, SUPBOOK_EXTERNAL, SUPBOOK_ADDIN, SUPBOOK_DDEOLE = range(5)
-
-SUPPORTED_VERSIONS = (80, 70, 50, 45, 40, 30, 21, 20)
-
-code_from_builtin_name = {
- u"Consolidate_Area": u"\x00",
- u"Auto_Open": u"\x01",
- u"Auto_Close": u"\x02",
- u"Extract": u"\x03",
- u"Database": u"\x04",
- u"Criteria": u"\x05",
- u"Print_Area": u"\x06",
- u"Print_Titles": u"\x07",
- u"Recorder": u"\x08",
- u"Data_Form": u"\x09",
- u"Auto_Activate": u"\x0A",
- u"Auto_Deactivate": u"\x0B",
- u"Sheet_Title": u"\x0C",
- u"_FilterDatabase": u"\x0D",
- }
-builtin_name_from_code = {}
-for _bin, _bic in code_from_builtin_name.items():
- builtin_name_from_code[_bic] = _bin
-del _bin, _bic
-
-##
-#
-# Open a spreadsheet file for data extraction.
-#
-# @param filename The path to the spreadsheet file to be opened.
-#
-# @param logfile An open file to which messages and diagnostics are written.
-#
-# @param verbosity Increases the volume of trace material written to the logfile.
-#
-# @param pickleable Default is true. In Python 2.4 or earlier, setting to false
-# will cause use of array.array objects which save some memory but can't be pickled.
-# In Python 2.5, array.arrays are used unconditionally. Note: if you have large files that
-# you need to read multiple times, it can be much faster to cPickle.dump() the xlrd.Book object
-# once, and use cPickle.load() multiple times.
-# @param use_mmap Whether to use the mmap module is determined heuristically.
-# Use this arg to override the result. Current heuristic: mmap is used if it exists.
-#
-# @param file_contents ... as a string or an mmap.mmap object or some other behave-alike object.
-# If file_contents is supplied, filename will not be used, except (possibly) in messages.
-#
-# @param encoding_override Used to overcome missing or bad codepage information
-# in older-version files. Refer to discussion in the <b>Unicode</b> section above.
-# <br /> -- New in version 0.6.0
-#
-# @param formatting_info Governs provision of a reference to an XF (eXtended Format) object
-# for each cell in the worksheet.
-# <br /> Default is <i>False</i>. This is backwards compatible and saves memory.
-# "Blank" cells (those with their own formatting information but no data) are treated as empty
-# (by ignoring the file's BLANK and MULBLANK records).
-# It cuts off any bottom "margin" of rows of empty (and blank) cells and
-# any right "margin" of columns of empty (and blank) cells.
-# Only cell_value and cell_type are available.
-# <br /> <i>True</i> provides all cells, including empty and blank cells.
-# XF information is available for each cell.
-# <br /> -- New in version 0.6.1
-#
-# @param on_demand Governs whether sheets are all loaded initially or when demanded
-# by the caller. Please refer back to the section "Loading worksheets on demand" for details.
-# -- New in version 0.7.1
-#
-# @return An instance of the Book class.
-
-def open_workbook(filename=None,
- logfile=sys.stdout, verbosity=0, pickleable=True, use_mmap=USE_MMAP,
- file_contents=None,
- encoding_override=None,
- formatting_info=False, on_demand=False,
- ):
- t0 = time.clock()
- if TOGGLE_GC:
- orig_gc_enabled = gc.isenabled()
- if orig_gc_enabled:
- gc.disable()
- bk = Book()
- bk.biff2_8_load(
- filename=filename, file_contents=file_contents,
- logfile=logfile, verbosity=verbosity, pickleable=pickleable, use_mmap=use_mmap,
- encoding_override=encoding_override,
- formatting_info=formatting_info,
- on_demand=on_demand,
- )
- t1 = time.clock()
- bk.load_time_stage_1 = t1 - t0
- biff_version = bk.getbof(XL_WORKBOOK_GLOBALS)
- if not biff_version:
- raise XLRDError("Can't determine file's BIFF version")
- if biff_version not in SUPPORTED_VERSIONS:
- raise XLRDError(
- "BIFF version %s is not supported"
- % biff_text_from_num[biff_version]
- )
- bk.biff_version = biff_version
- if biff_version <= 40:
- # no workbook globals, only 1 worksheet
- if on_demand:
- fprintf(bk.logfile,
- "*** WARNING: on_demand is not supported for this Excel version.\n"
- "*** Setting on_demand to False.\n")
- bk.on_demand = on_demand = False
- bk.fake_globals_get_sheet()
- elif biff_version == 45:
- # worksheet(s) embedded in global stream
- bk.parse_globals()
- if on_demand:
- fprintf(bk.logfile, "*** WARNING: on_demand is not supported for this Excel version.\n"
- "*** Setting on_demand to False.\n")
- bk.on_demand = on_demand = False
- else:
- bk.parse_globals()
- bk._sheet_list = [None for sh in bk._sheet_names]
- if not on_demand:
- bk.get_sheets()
- bk.nsheets = len(bk._sheet_list)
- if biff_version == 45 and bk.nsheets > 1:
- fprintf(bk.logfile,
- "*** WARNING: Excel 4.0 workbook (.XLW) file contains %d worksheets.\n"
- "*** Book-level data will be that of the last worksheet.\n",
- bk.nsheets
- )
- if not on_demand:
- bk.release_resources()
- if TOGGLE_GC:
- if orig_gc_enabled:
- gc.enable()
- t2 = time.clock()
- bk.load_time_stage_2 = t2 - t1
- return bk
-
-##
-# For debugging: dump the file's BIFF records in char & hex.
-# @param filename The path to the file to be dumped.
-# @param outfile An open file, to which the dump is written.
-# @param unnumbered If true, omit offsets (for meaningful diffs).
-
-def dump(filename, outfile=sys.stdout, unnumbered=False):
- bk = Book()
- bk.biff2_8_load(filename=filename, logfile=outfile, )
- biff_dump(bk.mem, bk.base, bk.stream_len, 0, outfile, unnumbered)
-
-##
-# For debugging and analysis: summarise the file's BIFF records.
-# I.e. produce a sorted file of (record_name, count).
-# @param filename The path to the file to be summarised.
-# @param outfile An open file, to which the summary is written.
-
-def count_records(filename, outfile=sys.stdout):
- bk = Book()
- bk.biff2_8_load(filename=filename, logfile=outfile, )
- biff_count_records(bk.mem, bk.base, bk.stream_len, outfile)
-
-##
-# Information relating to a named reference, formula, macro, etc.
-# <br /> -- New in version 0.6.0
-# <br /> -- <i>Name information is <b>not</b> extracted from files older than
-# Excel 5.0 (Book.biff_version < 50)</i>
-
-class Name(BaseObject):
-
- _repr_these = ['stack']
- book = None # parent
-
- ##
- # 0 = Visible; 1 = Hidden
- hidden = 0
-
- ##
- # 0 = Command macro; 1 = Function macro. Relevant only if macro == 1
- func = 0
-
- ##
- # 0 = Sheet macro; 1 = VisualBasic macro. Relevant only if macro == 1
- vbasic = 0
-
- ##
- # 0 = Standard name; 1 = Macro name
- macro = 0
-
- ##
- # 0 = Simple formula; 1 = Complex formula (array formula or user defined)<br />
- # <i>No examples have been sighted.</i>
- complex = 0
-
- ##
- # 0 = User-defined name; 1 = Built-in name
- # (common examples: Print_Area, Print_Titles; see OOo docs for full list)
- builtin = 0
-
- ##
- # Function group. Relevant only if macro == 1; see OOo docs for values.
- funcgroup = 0
-
- ##
- # 0 = Formula definition; 1 = Binary data<br /> <i>No examples have been sighted.</i>
- binary = 0
-
- ##
- # The index of this object in book.name_obj_list
- name_index = 0
-
- ##
- # A Unicode string. If builtin, decoded as per OOo docs.
- name = u""
-
- ##
- # An 8-bit string.
- raw_formula = ""
-
- ##
- # -1: The name is global (visible in all calculation sheets).<br />
- # -2: The name belongs to a macro sheet or VBA sheet.<br />
- # -3: The name is invalid.<br />
- # 0 <= scope < book.nsheets: The name is local to the sheet whose index is scope.
- scope = -1
-
- ##
- # The result of evaluating the formula, if any.
- # If no formula, or evaluation of the formula encountered problems,
- # the result is None. Otherwise the result is a single instance of the
- # Operand class.
- #
- result = None
-
- ##
- # This is a convenience method for the frequent use case where the name
- # refers to a single cell.
- # @return An instance of the Cell class.
- # @throws XLRDError The name is not a constant absolute reference
- # to a single cell.
- def cell(self):
- res = self.result
- if res:
- # result should be an instance of the Operand class
- kind = res.kind
- value = res.value
- if kind == oREF and len(value) == 1:
- ref3d = value[0]
- if (0 <= ref3d.shtxlo == ref3d.shtxhi - 1
- and ref3d.rowxlo == ref3d.rowxhi - 1
- and ref3d.colxlo == ref3d.colxhi - 1):
- sh = self.book.sheet_by_index(ref3d.shtxlo)
- return sh.cell(ref3d.rowxlo, ref3d.colxlo)
- self.dump(self.book.logfile,
- header="=== Dump of Name object ===",
- footer="======= End of dump =======",
- )
- raise XLRDError("Not a constant absolute reference to a single cell")
-
- ##
- # This is a convenience method for the use case where the name
- # refers to one rectangular area in one worksheet.
- # @param clipped If true (the default), the returned rectangle is clipped
- # to fit in (0, sheet.nrows, 0, sheet.ncols) -- it is guaranteed that
- # 0 <= rowxlo <= rowxhi <= sheet.nrows and that the number of usable rows
- # in the area (which may be zero) is rowxhi - rowxlo; likewise for columns.
- # @return a tuple (sheet_object, rowxlo, rowxhi, colxlo, colxhi).
- # @throws XLRDError The name is not a constant absolute reference
- # to a single area in a single sheet.
- def area2d(self, clipped=True):
- res = self.result
- if res:
- # result should be an instance of the Operand class
- kind = res.kind
- value = res.value
- if kind == oREF and len(value) == 1: # only 1 reference
- ref3d = value[0]
- if 0 <= ref3d.shtxlo == ref3d.shtxhi - 1: # only 1 usable sheet
- sh = self.book.sheet_by_index(ref3d.shtxlo)
- if not clipped:
- return sh, ref3d.rowxlo, ref3d.rowxhi, ref3d.colxlo, ref3d.colxhi
- rowxlo = min(ref3d.rowxlo, sh.nrows)
- rowxhi = max(rowxlo, min(ref3d.rowxhi, sh.nrows))
- colxlo = min(ref3d.colxlo, sh.ncols)
- colxhi = max(colxlo, min(ref3d.colxhi, sh.ncols))
- assert 0 <= rowxlo <= rowxhi <= sh.nrows
- assert 0 <= colxlo <= colxhi <= sh.ncols
- return sh, rowxlo, rowxhi, colxlo, colxhi
- self.dump(self.book.logfile,
- header="=== Dump of Name object ===",
- footer="======= End of dump =======",
- )
- raise XLRDError("Not a constant absolute reference to a single area in a single sheet")
-
-##
-# Contents of a "workbook".
-# <p>WARNING: You don't call this class yourself. You use the Book object that
-# was returned when you called xlrd.open_workbook("myfile.xls").</p>
-
-class Book(BaseObject):
-
- ##
- # The number of worksheets present in the workbook file.
- # This information is available even when no sheets have yet been loaded.
- nsheets = 0
-
- ##
- # Which date system was in force when this file was last saved.<br />
- # 0 => 1900 system (the Excel for Windows default).<br />
- # 1 => 1904 system (the Excel for Macintosh default).<br />
- datemode = 0 # In case it's not specified in the file.
-
- ##
- # Version of BIFF (Binary Interchange File Format) used to create the file.
- # Latest is 8.0 (represented here as 80), introduced with Excel 97.
- # Earliest supported by this module: 2.0 (represented as 20).
- biff_version = 0
-
- ##
- # List containing a Name object for each NAME record in the workbook.
- # <br /> -- New in version 0.6.0
- name_obj_list = []
-
- ##
- # An integer denoting the character set used for strings in this file.
- # For BIFF 8 and later, this will be 1200, meaning Unicode; more precisely, UTF_16_LE.
- # For earlier versions, this is used to derive the appropriate Python encoding
- # to be used to convert to Unicode.
- # Examples: 1252 -> 'cp1252', 10000 -> 'mac_roman'
- codepage = None
-
- ##
- # The encoding that was derived from the codepage.
- encoding = None
-
- ##
- # A tuple containing the (telephone system) country code for:<br />
- # [0]: the user-interface setting when the file was created.<br />
- # [1]: the regional settings.<br />
- # Example: (1, 61) meaning (USA, Australia).
- # This information may give a clue to the correct encoding for an unknown codepage.
- # For a long list of observed values, refer to the OpenOffice.org documentation for
- # the COUNTRY record.
- countries = (0, 0)
-
- ##
- # What (if anything) is recorded as the name of the last user to save the file.
- user_name = u''
-
- ##
- # A list of Font class instances, each corresponding to a FONT record.
- # <br /> -- New in version 0.6.1
- font_list = []
-
- ##
- # A list of XF class instances, each corresponding to an XF record.
- # <br /> -- New in version 0.6.1
- xf_list = []
-
- ##
- # A list of Format objects, each corresponding to a FORMAT record, in
- # the order that they appear in the input file.
- # It does <i>not</i> contain builtin formats.
- # If you are creating an output file using (for example) pyExcelerator,
- # use this list.
- # The collection to be used for all visual rendering purposes is format_map.
- # <br /> -- New in version 0.6.1
- format_list = []
-
- ##
- # The mapping from XF.format_key to Format object.
- # <br /> -- New in version 0.6.1
- format_map = {}
-
- ##
- # This provides access via name to the extended format information for
- # both built-in styles and user-defined styles.<br />
- # It maps <i>name</i> to (<i>built_in</i>, <i>xf_index</i>), where:<br />
- # <i>name</i> is either the name of a user-defined style,
- # or the name of one of the built-in styles. Known built-in names are
- # Normal, RowLevel_1 to RowLevel_7,
- # ColLevel_1 to ColLevel_7, Comma, Currency, Percent, "Comma [0]",
- # "Currency [0]", Hyperlink, and "Followed Hyperlink".<br />
- # <i>built_in</i> 1 = built-in style, 0 = user-defined<br />
- # <i>xf_index</i> is an index into Book.xf_list.<br />
- # References: OOo docs s6.99 (STYLE record); Excel UI Format/Style
- # <br /> -- New in version 0.6.1
- style_name_map = {}
-
- ##
- # This provides definitions for colour indexes. Please refer to the
- # above section "The Palette; Colour Indexes" for an explanation
- # of how colours are represented in Excel.<br />
- # Colour indexes into the palette map into (red, green, blue) tuples.
- # "Magic" indexes e.g. 0x7FFF map to None.
- # <i>colour_map</i> is what you need if you want to render cells on screen or in a PDF
- # file. If you are writing an output XLS file, use <i>palette_record</i>.
- # <br /> -- New in version 0.6.1. Extracted only if open_workbook(..., formatting_info=True)
- colour_map = {}
-
- ##
- # If the user has changed any of the colours in the standard palette, the XLS
- # file will contain a PALETTE record with 56 (16 for Excel 4.0 and earlier)
- # RGB values in it, and this list will be e.g. [(r0, b0, g0), ..., (r55, b55, g55)].
- # Otherwise this list will be empty. This is what you need if you are
- # writing an output XLS file. If you want to render cells on screen or in a PDF
- # file, use colour_map.
- # <br /> -- New in version 0.6.1. Extracted only if open_workbook(..., formatting_info=True)
- palette_record = []
-
- ##
- # Time in seconds to extract the XLS image as a contiguous string (or mmap equivalent).
- load_time_stage_1 = -1.0
-
- ##
- # Time in seconds to parse the data from the contiguous string (or mmap equivalent).
- load_time_stage_2 = -1.0
-
- ##
- # @return A list of all sheets in the book.
- # All sheets not already loaded will be loaded.
- def sheets(self):
- for sheetx in xrange(self.nsheets):
- if not self._sheet_list[sheetx]:
- self.get_sheet(sheetx)
- return self._sheet_list[:]
-
- ##
- # @param sheetx Sheet index in range(nsheets)
- # @return An object of the Sheet class
- def sheet_by_index(self, sheetx):
- return self._sheet_list[sheetx] or self.get_sheet(sheetx)
-
- ##
- # @param sheet_name Name of sheet required
- # @return An object of the Sheet class
- def sheet_by_name(self, sheet_name):
- try:
- sheetx = self._sheet_names.index(sheet_name)
- except ValueError:
- raise XLRDError('No sheet named <%r>' % sheet_name)
- return self.sheet_by_index(sheetx)
-
- ##
- # @return A list of the names of all the worksheets in the workbook file.
- # This information is available even when no sheets have yet been loaded.
- def sheet_names(self):
- return self._sheet_names[:]
-
- ##
- # @param sheet_name_or_index Name or index of sheet enquired upon
- # @return true if sheet is loaded, false otherwise
- # <br /> -- New in version 0.7.1
- def sheet_loaded(self, sheet_name_or_index):
- # using type(1) because int won't work with Python 2.1
- if isinstance(sheet_name_or_index, type(1)):
- sheetx = sheet_name_or_index
- else:
- try:
- sheetx = self._sheet_names.index(sheet_name_or_index)
- except ValueError:
- raise XLRDError('No sheet named <%r>' % sheet_name_or_index)
- return self._sheet_list[sheetx] and True or False # Python 2.1 again
-
- ##
- # @param sheet_name_or_index Name or index of sheet to be unloaded.
- # <br /> -- New in version 0.7.1
- def unload_sheet(self, sheet_name_or_index):
- # using type(1) because int won't work with Python 2.1
- if isinstance(sheet_name_or_index, type(1)):
- sheetx = sheet_name_or_index
- else:
- try:
- sheetx = self._sheet_names.index(sheet_name_or_index)
- except ValueError:
- raise XLRDError('No sheet named <%r>' % sheet_name_or_index)
- self._sheet_list[sheetx] = None
-
- ##
- # A mapping from (lower_case_name, scope) to a single Name object.
- # <br /> -- New in version 0.6.0
- name_and_scope_map = {}
-
- ##
- # A mapping from lower_case_name to a list of Name objects. The list is
- # sorted in scope order. Typically there will be one item (of global scope)
- # in the list.
- # <br /> -- New in version 0.6.0
- name_map = {}
-
- def __init__(self):
- self._sheet_list = []
- self._sheet_names = []
- self._sheet_visibility = [] # from BOUNDSHEET record
- self.nsheets = 0
- self._sh_abs_posn = [] # sheet's absolute position in the stream
- self._sharedstrings = []
- self.raw_user_name = False
- self._sheethdr_count = 0 # BIFF 4W only
- self.builtinfmtcount = -1 # unknown as yet. BIFF 3, 4S, 4W
- self.initialise_format_info()
- self._all_sheets_count = 0 # includes macro & VBA sheets
- self._supbook_count = 0
- self._supbook_locals_inx = None
- self._supbook_addins_inx = None
- self._all_sheets_map = [] # maps an all_sheets index to a calc-sheets index (or -1)
- self._externsheet_info = []
- self._externsheet_type_b57 = []
- self._extnsht_name_from_num = {}
- self._sheet_num_from_name = {}
- self._extnsht_count = 0
- self._supbook_types = []
- self._resources_released = 0
- self.addin_func_names = []
- self.name_obj_list = []
- self.colour_map = {}
- self.palette_record = []
- self.xf_list = []
- self.style_name_map = {}
-
- def biff2_8_load(self, filename=None, file_contents=None,
- logfile=sys.stdout, verbosity=0, pickleable=True, use_mmap=USE_MMAP,
- encoding_override=None,
- formatting_info=False,
- on_demand=False,
- ):
- # DEBUG = 0
- self.logfile = logfile
- self.verbosity = verbosity
- self.pickleable = pickleable
- self.use_mmap = use_mmap and MMAP_AVAILABLE
- self.encoding_override = encoding_override
- self.formatting_info = formatting_info
- self.on_demand = on_demand
-
- need_close_filestr = 0
- if not file_contents:
- if python_version < (2, 2) and self.use_mmap:
- # need to open for update
- open_mode = "r+b"
- else:
- open_mode = "rb"
- retry = False
- try:
- f = open(filename, open_mode)
- except IOError:
- e, v = sys.exc_info()[:2]
- if open_mode == "r+b" \
- and (v.errno == 13 or v.strerror == "Permission denied"):
- # Maybe the file is read-only
- retry = True
- self.use_mmap = False
- else:
- raise
- if retry:
- f = open(filename, "rb")
- if self.use_mmap:
- f.seek(0, 2) # EOF
- size = f.tell()
- f.seek(0, 0) # BOF
- if python_version < (2, 2):
- filestr = mmap.mmap(f.fileno(), size)
- else:
- filestr = mmap.mmap(f.fileno(), size, access=mmap.ACCESS_READ)
- need_close_filestr = 1
- self.stream_len = size
- else:
- filestr = f.read()
- self.stream_len = len(filestr)
- f.close()
- else:
- filestr = file_contents
- self.stream_len = len(file_contents)
-
- self.base = 0
- if filestr[:8] != compdoc.SIGNATURE:
- # got this one at the antique store
- self.mem = filestr
- else:
- cd = compdoc.CompDoc(filestr, logfile=self.logfile)
- if USE_FANCY_CD:
- for qname in [u'Workbook', u'Book']:
- self.mem, self.base, self.stream_len = cd.locate_named_stream(qname)
- if self.mem: break
- else:
- raise XLRDError("Can't find workbook in OLE2 compound document")
- else:
- for qname in [u'Workbook', u'Book']:
- self.mem = cd.get_named_stream(qname)
- if self.mem: break
- else:
- raise XLRDError("Can't find workbook in OLE2 compound document")
- self.stream_len = len(self.mem)
- del cd
- if self.mem is not filestr:
- if need_close_filestr:
- filestr.close()
- del filestr
- self._position = self.base
- if DEBUG:
- print >> self.logfile, "mem: %s, base: %d, len: %d" % (type(self.mem), self.base, self.stream_len)
-
- def initialise_format_info(self):
- # needs to be done once per sheet for BIFF 4W :-(
- self.format_map = {}
- self.format_list = []
- self.xfcount = 0
- self.actualfmtcount = 0 # number of FORMAT records seen so far
- self._xf_index_to_xl_type_map = {}
- self._xf_epilogue_done = 0
- self.xf_list = []
- self.font_list = []
-
- def release_resources(self):
- self._resources_released = 1
- del self.mem
- del self._sharedstrings
-
- def get2bytes(self):
- pos = self._position
- buff_two = self.mem[pos:pos+2]
- lenbuff = len(buff_two)
- self._position += lenbuff
- if lenbuff < 2:
- return MY_EOF
- lo, hi = buff_two
- return (ord(hi) << 8) | ord(lo)
-
- def get_record_parts(self):
- pos = self._position
- mem = self.mem
- code, length = unpack('<HH', mem[pos:pos+4])
- pos += 4
- data = mem[pos:pos+length]
- self._position = pos + length
- return (code, length, data)
-
- def get_record_parts_conditional(self, reqd_record):
- pos = self._position
- mem = self.mem
- code, length = unpack('<HH', mem[pos:pos+4])
- if code != reqd_record:
- return (None, 0, '')
- pos += 4
- data = mem[pos:pos+length]
- self._position = pos + length
- return (code, length, data)
-
- def get_sheet(self, sh_number, update_pos=True):
- if self._resources_released:
- raise XLRDError("Can't load sheets after releasing resources.")
- if update_pos:
- self._position = self._sh_abs_posn[sh_number]
- _unused_biff_version = self.getbof(XL_WORKSHEET)
- # assert biff_version == self.biff_version ### FAILS
- # Have an example where book is v7 but sheet reports v8!!!
- # It appears to work OK if the sheet version is ignored.
- # Confirmed by Daniel Rentz: happens when Excel does "save as"
- # creating an old version file; ignore version details on sheet BOF.
- sh = sheet.Sheet(self,
- self._position,
- self._sheet_names[sh_number],
- sh_number,
- )
- sh.read(self)
- self._sheet_list[sh_number] = sh
- return sh
-
- def get_sheets(self):
- # DEBUG = 0
- if DEBUG: print >> self.logfile, "GET_SHEETS:", self._sheet_names, self._sh_abs_posn
- for sheetno in xrange(len(self._sheet_names)):
- if DEBUG: print >> self.logfile, "GET_SHEETS: sheetno =", sheetno, self._sheet_names, self._sh_abs_posn
- self.get_sheet(sheetno)
-
- def fake_globals_get_sheet(self): # for BIFF 4.0 and earlier
- formatting.initialise_book(self)
- fake_sheet_name = u'Sheet 1'
- self._sheet_names = [fake_sheet_name]
- self._sh_abs_posn = [0]
- self._sheet_visibility = [0] # one sheet, visible
- self._sheet_list.append(None) # get_sheet updates _sheet_list but needs a None beforehand
- self.get_sheets()
-
- def handle_boundsheet(self, data):
- # DEBUG = 1
- bv = self.biff_version
- self.derive_encoding()
- if DEBUG:
- fprintf(self.logfile, "BOUNDSHEET: bv=%d data %r\n", bv, data);
- if bv == 45: # BIFF4W
- #### Not documented in OOo docs ...
- # In fact, the *only* data is the name of the sheet.
- sheet_name = unpack_string(data, 0, self.encoding, lenlen=1)
- visibility = 0
- sheet_type = XL_BOUNDSHEET_WORKSHEET # guess, patch later
- if len(self._sh_abs_posn) == 0:
- abs_posn = self._sheetsoffset + self.base
- # Note (a) this won't be used
- # (b) it's the position of the SHEETHDR record
- # (c) add 11 to get to the worksheet BOF record
- else:
- abs_posn = -1 # unknown
- else:
- offset, visibility, sheet_type = unpack('<iBB', data[0:6])
- abs_posn = offset + self.base # because global BOF is always at posn 0 in the stream
- if bv < BIFF_FIRST_UNICODE:
- sheet_name = unpack_string(data, 6, self.encoding, lenlen=1)
- else:
- sheet_name = unpack_unicode(data, 6, lenlen=1)
-
- if DEBUG or self.verbosity >= 2:
- fprintf(self.logfile,
- "BOUNDSHEET: inx=%d vis=%r sheet_name=%r abs_posn=%d sheet_type=0x%02x\n",
- self._all_sheets_count, visibility, sheet_name, abs_posn, sheet_type)
- self._all_sheets_count += 1
- if sheet_type != XL_BOUNDSHEET_WORKSHEET:
- self._all_sheets_map.append(-1)
- descr = {
- 1: 'Macro sheet',
- 2: 'Chart',
- 6: 'Visual Basic module',
- }.get(sheet_type, 'UNKNOWN')
-
- fprintf(self.logfile,
- "NOTE *** Ignoring non-worksheet data named %r (type 0x%02x = %s)\n",
- sheet_name, sheet_type, descr)
- else:
- snum = len(self._sheet_names)
- self._all_sheets_map.append(snum)
- self._sheet_names.append(sheet_name)
- self._sh_abs_posn.append(abs_posn)
- self._sheet_visibility.append(visibility)
- self._sheet_num_from_name[sheet_name] = snum
-
- def handle_builtinfmtcount(self, data):
- ### N.B. This count appears to be utterly useless.
- # DEBUG = 1
- builtinfmtcount = unpack('<H', data[0:2])[0]
- if DEBUG: fprintf(self.logfile, "BUILTINFMTCOUNT: %r\n", builtinfmtcount)
- self.builtinfmtcount = builtinfmtcount
-
- def derive_encoding(self):
- if self.encoding_override:
- self.encoding = self.encoding_override
- elif self.codepage is None:
- if self.biff_version < 80:
- fprintf(self.logfile,
- "*** No CODEPAGE record, no encoding_override: will use 'ascii'\n")
- self.encoding = 'ascii'
- else:
- self.codepage = 1200 # utf16le
- if self.verbosity >= 2:
- fprintf(self.logfile, "*** No CODEPAGE record; assuming 1200 (utf_16_le)\n")
- else:
- codepage = self.codepage
- if encoding_from_codepage.has_key(codepage):
- encoding = encoding_from_codepage[codepage]
- elif 300 <= codepage <= 1999:
- encoding = 'cp' + str(codepage)
- else:
- encoding = 'unknown_codepage_' + str(codepage)
- if DEBUG or (self.verbosity and encoding != self.encoding) :
- fprintf(self.logfile, "CODEPAGE: codepage %r -> encoding %r\n", codepage, encoding)
- self.encoding = encoding
- if self.codepage != 1200: # utf_16_le
- # If we don't have a codec that can decode ASCII into Unicode,
- # we're well & truly stuffed -- let the punter know ASAP.
- try:
- _unused = unicode('trial', self.encoding)
- except:
- ei = sys.exc_info()[:2]
- fprintf(self.logfile,
- "ERROR *** codepage %r -> encoding %r -> %s: %s\n",
- self.codepage, self.encoding, ei[0].__name__.split(".")[-1], ei[1])
- raise
- if self.raw_user_name:
- strg = unpack_string(self.user_name, 0, self.encoding, lenlen=1)
- strg = strg.rstrip()
- # if DEBUG:
- # print "CODEPAGE: user name decoded from %r to %r" % (self.user_name, strg)
- self.user_name = strg
- self.raw_user_name = False
- return self.encoding
-
- def handle_codepage(self, data):
- # DEBUG = 0
- codepage = unpack('<H', data[0:2])[0]
- self.codepage = codepage
- self.derive_encoding()
-
- def handle_country(self, data):
- countries = unpack('<HH', data[0:4])
- if self.verbosity: print >> self.logfile, "Countries:", countries
- # Note: in BIFF7 and earlier, country record was put (redundantly?) in each worksheet.
- assert self.countries == (0, 0) or self.countries == countries
- self.countries = countries
-
- def handle_datemode(self, data):
- datemode = unpack('<H', data[0:2])[0]
- if DEBUG or self.verbosity:
- fprintf(self.logfile, "DATEMODE: datemode %r\n", datemode)
- assert datemode in (0, 1)
- self.datemode = datemode
-
- def handle_externname(self, data):
- blah = DEBUG or self.verbosity >= 2
- if self.biff_version >= 80:
- option_flags, other_info =unpack("<HI", data[:6])
- pos = 6
- name, pos = unpack_unicode_update_pos(data, pos, lenlen=1)
- extra = data[pos:]
- if self._supbook_types[-1] == SUPBOOK_ADDIN:
- self.addin_func_names.append(name)
- if blah:
- fprintf(self.logfile,
- "EXTERNNAME: sbktype=%d oflags=0x%04x oinfo=0x%08x name=%r extra=%r\n",
- self._supbook_types[-1], option_flags, other_info, name, extra)
-
- def handle_externsheet(self, data):
- self.derive_encoding() # in case CODEPAGE record missing/out of order/wrong
- self._extnsht_count += 1 # for use as a 1-based index
- blah1 = DEBUG or self.verbosity >= 1
- blah2 = DEBUG or self.verbosity >= 2
- if self.biff_version >= 80:
- num_refs = unpack("<H", data[0:2])[0]
- bytes_reqd = num_refs * 6 + 2
- while len(data) < bytes_reqd:
- if blah1:
- fprintf(
- self.logfile,
- "INFO: EXTERNSHEET needs %d bytes, have %d\n",
- bytes_reqd, len(data),
- )
- code2, length2, data2 = self.get_record_parts()
- if code2 != XL_CONTINUE:
- raise XLRDError("Missing CONTINUE after EXTERNSHEET record")
- data += data2
- pos = 2
- for k in xrange(num_refs):
- info = unpack("<HHH", data[pos:pos+6])
- ref_recordx, ref_first_sheetx, ref_last_sheetx = info
- self._externsheet_info.append(info)
- pos += 6
- if blah2:
- fprintf(
- self.logfile,
- "EXTERNSHEET(b8): k = %2d, record = %2d, first_sheet = %5d, last sheet = %5d\n",
- k, ref_recordx, ref_first_sheetx, ref_last_sheetx,
- )
- else:
- nc, ty = unpack("<BB", data[:2])
- if blah2:
- print "EXTERNSHEET(b7-):"
- hex_char_dump(data, 0, len(data))
- msg = {
- 1: "Encoded URL",
- 2: "Current sheet!!",
- 3: "Specific sheet in own doc't",
- 4: "Nonspecific sheet in own doc't!!",
- }.get(ty, "Not encoded")
- print " %3d chars, type is %d (%s)" % (nc, ty, msg)
- if ty == 3:
- sheet_name = unicode(data[2:nc+2], self.encoding)
- self._extnsht_name_from_num[self._extnsht_count] = sheet_name
- if blah2: print self._extnsht_name_from_num
- if not (1 <= ty <= 4):
- ty = 0
- self._externsheet_type_b57.append(ty)
-
- def handle_filepass(self, data):
- if self.verbosity >= 2:
- logf = self.logfile
- fprintf(logf, "FILEPASS:\n")
- hex_char_dump(data, 0, len(data), base=0, fout=logf)
- if self.biff_version >= 80:
- kind1, = unpack('<H', data[:2])
- if kind1 == 0: # weak XOR encryption
- key, hash_value = unpack('<HH', data[2:])
- fprintf(logf,
- 'weak XOR: key=0x%04x hash=0x%04x\n',
- key, hash_value)
- elif kind1 == 1:
- kind2, = unpack('<H', data[4:6])
- if kind2 == 1: # BIFF8 standard encryption
- caption = "BIFF8 std"
- elif kind2 == 2:
- caption = "BIFF8 strong"
- else:
- caption = "** UNKNOWN ENCRYPTION METHOD **"
- fprintf(logf, "%s\n", caption)
- raise XLRDError("Workbook is encrypted")
-
- def handle_name(self, data):
- blah = DEBUG or self.verbosity >= 2
- bv = self.biff_version
- if bv < 50:
- return
- self.derive_encoding()
- # print
- # hex_char_dump(data, 0, len(data))
- (
- option_flags, kb_shortcut, name_len, fmla_len, extsht_index, sheet_index,
- menu_text_len, description_text_len, help_topic_text_len, status_bar_text_len,
- ) = unpack("<HBBHHH4B", data[0:14])
- nobj = Name()
- nobj.book = self ### CIRCULAR ###
- name_index = len(self.name_obj_list)
- nobj.name_index = name_index
- self.name_obj_list.append(nobj)
- nobj.option_flags = option_flags
- for attr, mask, nshift in (
- ('hidden', 1, 0),
- ('func', 2, 1),
- ('vbasic', 4, 2),
- ('macro', 8, 3),
- ('complex', 0x10, 4),
- ('builtin', 0x20, 5),
- ('funcgroup', 0xFC0, 6),
- ('binary', 0x1000, 12),
- ):
- setattr(nobj, attr, (option_flags & mask) >> nshift)
-
- macro_flag = " M"[nobj.macro]
- if bv < 80:
- internal_name, pos = unpack_string_update_pos(data, 14, self.encoding, known_len=name_len)
- else:
- internal_name, pos = unpack_unicode_update_pos(data, 14, known_len=name_len)
- nobj.extn_sheet_num = extsht_index
- nobj.excel_sheet_index = sheet_index
- nobj.scope = None # patched up in the names_epilogue() method
- if blah:
- print "NAME[%d]:%s oflags=%d, name_len=%d, fmla_len=%d, extsht_index=%d, sheet_index=%d, name=%r" \
- % (name_index, macro_flag, option_flags, name_len,
- fmla_len, extsht_index, sheet_index, internal_name)
- name = internal_name
- if nobj.builtin:
- name = builtin_name_from_code.get(name, "??Unknown??")
- if blah: print " builtin: %s" % name
- nobj.name = name
- nobj.raw_formula = data[pos:]
- nobj.basic_formula_len = fmla_len
- nobj.evaluated = 0
- if blah:
- nobj.dump(
- self.logfile,
- header="--- handle_name: name[%d] ---" % name_index,
- footer="-------------------",
- )
-
- def names_epilogue(self):
- blah = self.verbosity >= 2
- f = self.logfile
- if blah:
- print >> f, "+++++ names_epilogue +++++"
- print >> f, "_all_sheets_map", self._all_sheets_map
- print >> f, "_extnsht_name_from_num", self._extnsht_name_from_num
- print >> f, "_sheet_num_from_name", self._sheet_num_from_name
- num_names = len(self.name_obj_list)
- for namex in range(num_names):
- nobj = self.name_obj_list[namex]
- # Convert from excel_sheet_index to scope.
- # This is done here because in BIFF7 and earlier, the
- # BOUNDSHEET records (from which _all_sheets_map is derived)
- # come after the NAME records.
- if self.biff_version >= 80:
- sheet_index = nobj.excel_sheet_index
- if sheet_index == 0:
- intl_sheet_index = -1 # global
- elif 1 <= sheet_index <= len(self._all_sheets_map):
- intl_sheet_index = self._all_sheets_map[sheet_index-1]
- if intl_sheet_index == -1: # maps to a macro or VBA sheet
- intl_sheet_index = -2 # valid sheet reference but not useful
- else:
- # huh?
- intl_sheet_index = -3 # invalid
- elif 50 <= self.biff_version <= 70:
- sheet_index = nobj.extn_sheet_num
- if sheet_index == 0:
- intl_sheet_index = -1 # global
- else:
- sheet_name = self._extnsht_name_from_num[sheet_index]
- intl_sheet_index = self._sheet_num_from_name.get(sheet_name, -2)
- nobj.scope = intl_sheet_index
-
- for namex in range(num_names):
- nobj = self.name_obj_list[namex]
- # Parse the formula ...
- if nobj.macro or nobj.binary: continue
- if nobj.evaluated: continue
- evaluate_name_formula(self, nobj, namex, blah=blah)
-
- if self.verbosity >= 2:
- print >> f, "---------- name object dump ----------"
- for namex in range(num_names):
- nobj = self.name_obj_list[namex]
- nobj.dump(f, header="--- name[%d] ---" % namex)
- print >> f, "--------------------------------------"
- #
- # Build some dicts for access to the name objects
- #
- name_and_scope_map = {} # (name.lower(), scope): Name_object
- name_map = {} # name.lower() : list of Name_objects (sorted in scope order)
- for namex in range(num_names):
- nobj = self.name_obj_list[namex]
- name_lcase = nobj.name.lower()
- key = (name_lcase, nobj.scope)
- if name_and_scope_map.has_key(key):
- msg = 'Duplicate entry %r in name_and_scope_map' % (key, )
- if 0:
- raise XLRDError(msg)
- else:
- if self.verbosity:
- print >> f, msg
- name_and_scope_map[key] = nobj
- if name_map.has_key(name_lcase):
- name_map[name_lcase].append((nobj.scope, nobj))
- else:
- name_map[name_lcase] = [(nobj.scope, nobj)]
- for key in name_map.keys():
- alist = name_map[key]
- alist.sort()
- name_map[key] = [x[1] for x in alist]
- self.name_and_scope_map = name_and_scope_map
- self.name_map = name_map
-
- def handle_obj(self, data):
- # Not doing much handling at all.
- # Worrying about embedded (BOF ... EOF) substreams is done elsewhere.
- # DEBUG = 1
- obj_type, obj_id = unpack('<HI', data[4:10])
- # if DEBUG: print "---> handle_obj type=%d id=0x%08x" % (obj_type, obj_id)
-
- def handle_supbook(self, data):
- self._supbook_types.append(None)
- blah = DEBUG or self.verbosity >= 2
- if 0:
- print "SUPBOOK:"
- hex_char_dump(data, 0, len(data))
- num_sheets = unpack("<H", data[0:2])[0]
- sbn = self._supbook_count
- self._supbook_count += 1
- if data[2:4] == "\x01\x04":
- self._supbook_types[-1] = SUPBOOK_INTERNAL
- self._supbook_locals_inx = self._supbook_count - 1
- if blah:
- print "SUPBOOK[%d]: internal 3D refs; %d sheets" % (sbn, num_sheets)
- print " _all_sheets_map", self._all_sheets_map
- return
- if data[0:4] == "\x01\x00\x01\x3A":
- self._supbook_types[-1] = SUPBOOK_ADDIN
- self._supbook_addins_inx = self._supbook_count - 1
- if blah: print "SUPBOOK[%d]: add-in functions" % sbn
- return
- url, pos = unpack_unicode_update_pos(data, 2, lenlen=2)
- if num_sheets == 0:
- self._supbook_types[-1] = SUPBOOK_DDEOLE
- if blah: print "SUPBOOK[%d]: DDE/OLE document = %r" % (sbn, url)
- return
- self._supbook_types[-1] = SUPBOOK_EXTERNAL
- if blah: print "SUPBOOK[%d]: url = %r" % (sbn, url)
- sheet_names = []
- for x in range(num_sheets):
- shname, pos = unpack_unicode_update_pos(data, pos, lenlen=2)
- sheet_names.append(shname)
- if blah: print " sheet %d: %r" % (x, shname)
-
- def handle_sheethdr(self, data):
- # This a BIFF 4W special.
- # The SHEETHDR record is followed by a (BOF ... EOF) substream containing
- # a worksheet.
- # DEBUG = 1
- self.derive_encoding()
- sheet_len = unpack('<i', data[:4])[0]
- sheet_name = unpack_string(data, 4, self.encoding, lenlen=1)
- sheetno = self._sheethdr_count
- assert sheet_name == self._sheet_names[sheetno]
- self._sheethdr_count += 1
- BOF_posn = self._position
- posn = BOF_posn - 4 - len(data)
- if DEBUG: print >> self.logfile, 'SHEETHDR %d at posn %d: len=%d name=%r' % (sheetno, posn, sheet_len, sheet_name)
- self.initialise_format_info()
- if DEBUG: print >> self.logfile, 'SHEETHDR: xf epilogue flag is %d' % self._xf_epilogue_done
- self._sheet_list.append(None) # get_sheet updates _sheet_list but needs a None beforehand
- self.get_sheet(sheetno, update_pos=False)
- if DEBUG: print >> self.logfile, 'SHEETHDR: posn after get_sheet() =', self._position
- self._position = BOF_posn + sheet_len
-
- def handle_sheetsoffset(self, data):
- # DEBUG = 0
- posn = unpack('<i', data)[0]
- if DEBUG: print >> self.logfile, 'SHEETSOFFSET:', posn
- self._sheetsoffset = posn
-
- def handle_sst(self, data):
- # DEBUG = 1
- if DEBUG:
- print >> self.logfile, "SST Processing"
- t0 = time.time()
- nbt = len(data)
- strlist = [data]
- uniquestrings = unpack('<i', data[4:8])[0]
- if DEBUG or self.verbosity >= 2:
- fprintf(self.logfile, "SST: unique strings: %d\n", uniquestrings)
- while 1:
- code, nb, data = self.get_record_parts_conditional(XL_CONTINUE)
- if code is None:
- break
- nbt += nb
- if DEBUG >= 2:
- fprintf(self.logfile, "CONTINUE: adding %d bytes to SST -> %d\n", nb, nbt)
- strlist.append(data)
- self._sharedstrings = unpack_SST_table(strlist, uniquestrings)
- if DEBUG:
- t1 = time.time()
- print >> self.logfile, "SST processing took %.2f seconds" % (t1 - t0, )
-
- def handle_writeaccess(self, data):
- # DEBUG = 0
- if self.biff_version < 80:
- if not self.encoding:
- self.raw_user_name = True
- self.user_name = data
- return
- strg = unpack_string(data, 0, self.encoding, lenlen=1)
- else:
- strg = unpack_unicode(data, 0, lenlen=2)
- if DEBUG: print >> self.logfile, "WRITEACCESS: %d bytes; raw=%d %r" % (len(data), self.raw_user_name, strg)
- strg = strg.rstrip()
- self.user_name = strg
-
- def parse_globals(self):
- # DEBUG = 0
- # no need to position, just start reading (after the BOF)
- formatting.initialise_book(self)
- while 1:
- rc, length, data = self.get_record_parts()
- if DEBUG: print "parse_globals: record code is 0x%04x" % rc
- if rc == XL_SST:
- self.handle_sst(data)
- elif rc == XL_FONT or rc == XL_FONT_B3B4:
- self.handle_font(data)
- elif rc == XL_FORMAT: # XL_FORMAT2 is BIFF <= 3.0, can't appear in globals
- self.handle_format(data)
- elif rc == XL_XF:
- self.handle_xf(data)
- elif rc == XL_BOUNDSHEET:
- self.handle_boundsheet(data)
- elif rc == XL_DATEMODE:
- self.handle_datemode(data)
- elif rc == XL_CODEPAGE:
- self.handle_codepage(data)
- elif rc == XL_COUNTRY:
- self.handle_country(data)
- elif rc == XL_EXTERNNAME:
- self.handle_externname(data)
- elif rc == XL_EXTERNSHEET:
- self.handle_externsheet(data)
- elif rc == XL_FILEPASS:
- self.handle_filepass(data)
- elif rc == XL_WRITEACCESS:
- self.handle_writeaccess(data)
- elif rc == XL_SHEETSOFFSET:
- self.handle_sheetsoffset(data)
- elif rc == XL_SHEETHDR:
- self.handle_sheethdr(data)
- elif rc == XL_SUPBOOK:
- self.handle_supbook(data)
- elif rc == XL_NAME:
- self.handle_name(data)
- elif rc == XL_PALETTE:
- self.handle_palette(data)
- elif rc == XL_STYLE:
- self.handle_style(data)
- elif rc & 0xff == 9:
- print >> self.logfile, "*** Unexpected BOF at posn %d: 0x%04x len=%d data=%r" \
- % (self._position - length - 4, rc, length, data)
- elif rc == XL_EOF:
- self.xf_epilogue()
- self.names_epilogue()
- self.palette_epilogue()
- if not self.encoding:
- self.derive_encoding()
- if self.biff_version == 45:
- # DEBUG = 0
- if DEBUG: print "global EOF: position", self._position
- # if DEBUG:
- # pos = self._position - 4
- # print repr(self.mem[pos:pos+40])
- return
- else:
- # if DEBUG:
- # print "parse_globals: ignoring record code 0x%04x" % rc
- pass
-
- def read(self, pos, length):
- data = self.mem[pos:pos+length]
- self._position = pos + len(data)
- return data
-
- def getbof(self, rqd_stream):
- # DEBUG = 1
- # if DEBUG: print >> self.logfile, "getbof(): position", self._position
- if DEBUG: print >> self.logfile, "reqd: 0x%04x" % rqd_stream
- def bof_error(msg):
- raise XLRDError('Unsupported format, or corrupt file: ' + msg)
- savpos = self._position
- opcode = self.get2bytes()
- if opcode == MY_EOF:
- bof_error('Expected BOF record; met end of file')
- if opcode not in bofcodes:
- bof_error('Expected BOF record; found %r' % self.mem[savpos:savpos+8])
- length = self.get2bytes()
- if length == MY_EOF:
- bof_error('Incomplete BOF record[1]; met end of file')
- if length < boflen[opcode] or length > 20:
- bof_error(
- 'Invalid length (%d) for BOF record type 0x%04x'
- % (length, opcode))
- data = self.read(self._position, length);
- if DEBUG: print >> self.logfile, "\ngetbof(): data=%r" % data
- if len(data) < length:
- bof_error('Incomplete BOF record[2]; met end of file')
- version1 = opcode >> 8
- version2, streamtype = unpack('<HH', data[0:4])
- if DEBUG:
- print >> self.logfile, "getbof(): op=0x%04x version2=0x%04x streamtype=0x%04x" \
- % (opcode, version2, streamtype)
- bof_offset = self._position - 4 - length
- if DEBUG:
- print >> self.logfile, "getbof(): BOF found at offset %d; savpos=%d" \
- % (bof_offset, savpos)
- version = build = year = 0
- if version1 == 0x08:
- build, year = unpack('<HH', data[4:8])
- if version2 == 0x0600:
- version = 80
- elif version2 == 0x0500:
- if year < 1994 or build in (2412, 3218, 3321):
- version = 50
- else:
- version = 70
- else:
- # dodgy one, created by a 3rd-party tool
- version = {
- 0x0000: 21,
- 0x0007: 21,
- 0x0200: 21,
- 0x0300: 30,
- 0x0400: 40,
- }.get(version2, 0)
- elif version1 in (0x04, 0x02, 0x00):
- version = {0x04: 40, 0x02: 30, 0x00: 21}[version1]
-
- if version == 40 and streamtype == XL_WORKBOOK_GLOBALS_4W:
- version = 45 # i.e. 4W
-
- if DEBUG or self.verbosity >= 2:
- print >> self.logfile, \
- "BOF: op=0x%04x vers=0x%04x stream=0x%04x buildid=%d buildyr=%d -> BIFF%d" \
- % (opcode, version2, streamtype, build, year, version)
- got_globals = streamtype == XL_WORKBOOK_GLOBALS or (
- version == 45 and streamtype == XL_WORKBOOK_GLOBALS_4W)
- if (rqd_stream == XL_WORKBOOK_GLOBALS and got_globals) or streamtype == rqd_stream:
- return version
- if version < 50 and streamtype == XL_WORKSHEET:
- return version
- if version >= 50 and streamtype == 0x0100:
- bof_error("Workspace file -- no spreadsheet data")
- bof_error(
- 'BOF not workbook/worksheet: op=0x%04x vers=0x%04x strm=0x%04x build=%d year=%d -> BIFF%d' \
- % (opcode, version2, streamtype, build, year, version)
- )
-
-# === helper functions
-
-def expand_cell_address(inrow, incol):
- # Ref : OOo docs, "4.3.4 Cell Addresses in BIFF8"
- outrow = inrow
- if incol & 0x8000:
- if outrow >= 32768:
- outrow -= 65536
- relrow = 1
- else:
- relrow = 0
- outcol = incol & 0xFF
- if incol & 0x4000:
- if outcol >= 128:
- outcol -= 256
- relcol = 1
- else:
- relcol = 0
- return outrow, outcol, relrow, relcol
-
-def colname(colx, _A2Z="ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
- assert colx >= 0
- name = ''
- while 1:
- quot, rem = divmod(colx, 26)
- name = _A2Z[rem] + name
- if not quot:
- return name
- colx = quot - 1
-
-def display_cell_address(rowx, colx, relrow, relcol):
- if relrow:
- rowpart = "(*%s%d)" % ("+-"[rowx < 0], abs(rowx))
- else:
- rowpart = "$%d" % (rowx+1,)
- if relcol:
- colpart = "(*%s%d)" % ("+-"[colx < 0], abs(colx))
- else:
- colpart = "$" + colname(colx)
- return colpart + rowpart
-
-def unpack_SST_table(datatab, nstrings):
- "Return list of strings"
- datainx = 0
- ndatas = len(datatab)
- data = datatab[0]
- datalen = len(data)
- pos = 8
- strings = []
- strappend = strings.append
- local_unpack = unpack
- local_min = min
- local_ord = ord
- latin_1 = "latin_1"
- for _unused_i in xrange(nstrings):
- nchars = local_unpack('<H', data[pos:pos+2])[0]
- pos += 2
- options = local_ord(data[pos])
- pos += 1
- rtsz = 0
- if options & 0x08: # richtext
- rtsz = 4 * local_unpack('<H', data[pos:pos+2])[0]
- pos += 2
- if options & 0x04: # phonetic
- rtsz += local_unpack('<i', data[pos:pos+4])[0]
- pos += 4
- accstrg = u''
- charsgot = 0
- while 1:
- charsneed = nchars - charsgot
- if options & 0x01:
- # Uncompressed UTF-16
- charsavail = local_min((datalen - pos) >> 1, charsneed)
- rawstrg = data[pos:pos+2*charsavail]
- # if DEBUG: print "SST U16: nchars=%d pos=%d rawstrg=%r" % (nchars, pos, rawstrg)
- try:
- accstrg += unicode(rawstrg, "utf_16_le")
- except:
- # print "SST U16: nchars=%d pos=%d rawstrg=%r" % (nchars, pos, rawstrg)
- # Probable cause: dodgy data e.g. unfinished surrogate pair.
- # E.g. file unicode2.xls in pyExcelerator's examples has cells containing
- # unichr(i) for i in range(0x100000)
- # so this will include 0xD800 etc
- raise
- pos += 2*charsavail
- else:
- # Note: this is COMPRESSED (not ASCII!) encoding!!!
- charsavail = local_min(datalen - pos, charsneed)
- rawstrg = data[pos:pos+charsavail]
- # if DEBUG: print "SST CMPRSD: nchars=%d pos=%d rawstrg=%r" % (nchars, pos, rawstrg)
- accstrg += unicode(rawstrg, latin_1)
- pos += charsavail
- charsgot += charsavail
- if charsgot == nchars:
- break
- datainx += 1
- data = datatab[datainx]
- datalen = len(data)
- options = local_ord(data[0])
- pos = 1
- pos += rtsz # size of richtext & phonetic stuff to skip
- # also allow for the rich text etc being split ...
- if pos >= datalen:
- # adjust to correct position in next record
- pos = pos - datalen
- datainx += 1
- if datainx < ndatas:
- data = datatab[datainx]
- datalen = len(data)
- else:
- assert _unused_i == nstrings - 1
- strappend(accstrg)
- return strings
diff --git a/tablib/packages/xlrd/biffh.py b/tablib/packages/xlrd/biffh.py
deleted file mode 100644
index ba3b26c..0000000
--- a/tablib/packages/xlrd/biffh.py
+++ /dev/null
@@ -1,639 +0,0 @@
-# -*- coding: cp1252 -*-
-
-##
-# Support module for the xlrd package.
-#
-# <p>Portions copyright 2005-2008 Stephen John Machin, Lingfo Pty Ltd</p>
-# <p>This module is part of the xlrd package, which is released under a BSD-style licence.</p>
-##
-
-# 2008-02-10 SJM BIFF2 BLANK record
-# 2008-02-08 SJM Preparation for Excel 2.0 support
-# 2008-02-02 SJM Added suffixes (_B2, _B2_ONLY, etc) on record names for biff_dump & biff_count
-# 2007-12-04 SJM Added support for Excel 2.x (BIFF2) files.
-# 2007-09-08 SJM Avoid crash when zero-length Unicode string missing options byte.
-# 2007-04-22 SJM Remove experimental "trimming" facility.
-
-DEBUG = 0
-
-from struct import unpack
-import sys
-from timemachine import *
-
-class XLRDError(Exception):
- pass
-
-##
-# Parent of almost all other classes in the package. Defines a common "dump" method
-# for debugging.
-
-class BaseObject(object):
-
- _repr_these = []
-
- ##
- # @param f open file object, to which the dump is written
- # @param header text to write before the dump
- # @param footer text to write after the dump
- # @param indent number of leading spaces (for recursive calls)
-
- def dump(self, f=None, header=None, footer=None, indent=0):
- if f is None:
- f = sys.stderr
- alist = self.__dict__.items()
- alist.sort()
- pad = " " * indent
- if header is not None: print >> f, header
- list_type = type([])
- dict_type = type({})
- for attr, value in alist:
- if getattr(value, 'dump', None) and attr != 'book':
- value.dump(f,
- header="%s%s (%s object):" % (pad, attr, value.__class__.__name__),
- indent=indent+4)
- elif attr not in self._repr_these and (
- isinstance(value, list_type) or isinstance(value, dict_type)
- ):
- print >> f, "%s%s: %s, len = %d" % (pad, attr, type(value), len(value))
- else:
- print >> f, "%s%s: %r" % (pad, attr, value)
- if footer is not None: print >> f, footer
-
-FUN, FDT, FNU, FGE, FTX = range(5) # unknown, date, number, general, text
-DATEFORMAT = FDT
-NUMBERFORMAT = FNU
-
-(
- XL_CELL_EMPTY,
- XL_CELL_TEXT,
- XL_CELL_NUMBER,
- XL_CELL_DATE,
- XL_CELL_BOOLEAN,
- XL_CELL_ERROR,
- XL_CELL_BLANK, # for use in debugging, gathering stats, etc
-) = range(7)
-
-biff_text_from_num = {
- 0: "(not BIFF)",
- 20: "2.0",
- 21: "2.1",
- 30: "3",
- 40: "4S",
- 45: "4W",
- 50: "5",
- 70: "7",
- 80: "8",
- 85: "8X",
- }
-
-##
-# <p>This dictionary can be used to produce a text version of the internal codes
-# that Excel uses for error cells. Here are its contents:
-# <pre>
-# 0x00: '#NULL!', # Intersection of two cell ranges is empty
-# 0x07: '#DIV/0!', # Division by zero
-# 0x0F: '#VALUE!', # Wrong type of operand
-# 0x17: '#REF!', # Illegal or deleted cell reference
-# 0x1D: '#NAME?', # Wrong function or range name
-# 0x24: '#NUM!', # Value range overflow
-# 0x2A: '#N/A!', # Argument or function not available
-# </pre></p>
-
-error_text_from_code = {
- 0x00: '#NULL!', # Intersection of two cell ranges is empty
- 0x07: '#DIV/0!', # Division by zero
- 0x0F: '#VALUE!', # Wrong type of operand
- 0x17: '#REF!', # Illegal or deleted cell reference
- 0x1D: '#NAME?', # Wrong function or range name
- 0x24: '#NUM!', # Value range overflow
- 0x2A: '#N/A!', # Argument or function not available
-}
-
-BIFF_FIRST_UNICODE = 80
-
-XL_WORKBOOK_GLOBALS = WBKBLOBAL = 0x5
-XL_WORKBOOK_GLOBALS_4W = 0x100
-XL_WORKSHEET = WRKSHEET = 0x10
-
-XL_BOUNDSHEET_WORKSHEET = 0x00
-XL_BOUNDSHEET_CHART = 0x02
-XL_BOUNDSHEET_VB_MODULE = 0x06
-
-# XL_RK2 = 0x7e
-XL_ARRAY = 0x0221
-XL_ARRAY2 = 0x0021
-XL_BLANK = 0x0201
-XL_BLANK_B2 = 0x01
-XL_BOF = 0x809
-XL_BOOLERR = 0x205
-XL_BOOLERR_B2 = 0x5
-XL_BOUNDSHEET = 0x85
-XL_BUILTINFMTCOUNT = 0x56
-XL_CF = 0x01B1
-XL_CODEPAGE = 0x42
-XL_COLINFO = 0x7D
-XL_COLUMNDEFAULT = 0x20 # BIFF2 only
-XL_COLWIDTH = 0x24 # BIFF2 only
-XL_CONDFMT = 0x01B0
-XL_CONTINUE = 0x3c
-XL_COUNTRY = 0x8C
-XL_DATEMODE = 0x22
-XL_DEFAULTROWHEIGHT = 0x0225
-XL_DEFCOLWIDTH = 0x55
-XL_DIMENSION = 0x200
-XL_DIMENSION2 = 0x0
-XL_EFONT = 0x45
-XL_EOF = 0x0a
-XL_EXTERNNAME = 0x23
-XL_EXTERNSHEET = 0x17
-XL_EXTSST = 0xff
-XL_FEAT11 = 0x872
-XL_FILEPASS = 0x2f
-XL_FONT = 0x31
-XL_FONT_B3B4 = 0x231
-XL_FORMAT = 0x41e
-XL_FORMAT2 = 0x1E # BIFF2, BIFF3
-XL_FORMULA = 0x6
-XL_FORMULA3 = 0x206
-XL_FORMULA4 = 0x406
-XL_GCW = 0xab
-XL_INDEX = 0x20b
-XL_INTEGER = 0x2 # BIFF2 only
-XL_IXFE = 0x44 # BIFF2 only
-XL_LABEL = 0x204
-XL_LABEL_B2 = 0x04
-XL_LABELRANGES = 0x15f
-XL_LABELSST = 0xfd
-XL_MERGEDCELLS = 0xE5
-XL_MSO_DRAWING = 0x00EC
-XL_MSO_DRAWING_GROUP = 0x00EB
-XL_MSO_DRAWING_SELECTION = 0x00ED
-XL_MULRK = 0xbd
-XL_MULBLANK = 0xbe
-XL_NAME = 0x18
-XL_NOTE = 0x1c
-XL_NUMBER = 0x203
-XL_NUMBER_B2 = 0x3
-XL_OBJ = 0x5D
-XL_PALETTE = 0x92
-XL_RK = 0x27e
-XL_ROW = 0x208
-XL_ROW_B2 = 0x08
-XL_RSTRING = 0xd6
-XL_SHEETHDR = 0x8F # BIFF4W only
-XL_SHEETSOFFSET = 0x8E # BIFF4W only
-XL_SHRFMLA = 0x04bc
-XL_SST = 0xfc
-XL_STANDARDWIDTH = 0x99
-XL_STRING = 0x207
-XL_STRING_B2 = 0x7
-XL_STYLE = 0x293
-XL_SUPBOOK = 0x1AE
-XL_TABLEOP = 0x236
-XL_TABLEOP2 = 0x37
-XL_TABLEOP_B2 = 0x36
-XL_TXO = 0x1b6
-XL_UNCALCED = 0x5e
-XL_UNKNOWN = 0xffff
-XL_WINDOW2 = 0x023E
-XL_WRITEACCESS = 0x5C
-XL_XF = 0xe0
-XL_XF2 = 0x0043 # BIFF2 version of XF record
-XL_XF3 = 0x0243 # BIFF3 version of XF record
-XL_XF4 = 0x0443 # BIFF4 version of XF record
-
-boflen = {0x0809: 8, 0x0409: 6, 0x0209: 6, 0x0009: 4}
-bofcodes = (0x0809, 0x0409, 0x0209, 0x0009)
-
-XL_FORMULA_OPCODES = (0x0006, 0x0406, 0x0206)
-
-_cell_opcode_list = [
- XL_BOOLERR,
- XL_FORMULA,
- XL_FORMULA3,
- XL_FORMULA4,
- XL_LABEL,
- XL_LABELSST,
- XL_MULRK,
- XL_NUMBER,
- XL_RK,
- XL_RSTRING,
- ]
-_cell_opcode_dict = {}
-for _cell_opcode in _cell_opcode_list:
- _cell_opcode_dict[_cell_opcode] = 1
-is_cell_opcode = _cell_opcode_dict.has_key
-
-# def fprintf(f, fmt, *vargs): f.write(fmt % vargs)
-
-def fprintf(f, fmt, *vargs):
- if fmt.endswith('\n'):
- print >> f, fmt[:-1] % vargs
- else:
- print >> f, fmt % vargs,
-
-def upkbits(tgt_obj, src, manifest, local_setattr=setattr):
- for n, mask, attr in manifest:
- local_setattr(tgt_obj, attr, (src & mask) >> n)
-
-def upkbitsL(tgt_obj, src, manifest, local_setattr=setattr, local_int=int):
- for n, mask, attr in manifest:
- local_setattr(tgt_obj, attr, local_int((src & mask) >> n))
-
-def unpack_string(data, pos, encoding, lenlen=1):
- nchars = unpack('<' + 'BH'[lenlen-1], data[pos:pos+lenlen])[0]
- pos += lenlen
- return unicode(data[pos:pos+nchars], encoding)
-
-def unpack_string_update_pos(data, pos, encoding, lenlen=1, known_len=None):
- if known_len is not None:
- # On a NAME record, the length byte is detached from the front of the string.
- nchars = known_len
- else:
- nchars = unpack('<' + 'BH'[lenlen-1], data[pos:pos+lenlen])[0]
- pos += lenlen
- newpos = pos + nchars
- return (unicode(data[pos:newpos], encoding), newpos)
-
-def unpack_unicode(data, pos, lenlen=2):
- "Return unicode_strg"
- nchars = unpack('<' + 'BH'[lenlen-1], data[pos:pos+lenlen])[0]
- if not nchars:
- # Ambiguous whether 0-length string should have an "options" byte.
- # Avoid crash if missing.
- return u""
- pos += lenlen
- options = ord(data[pos])
- pos += 1
- # phonetic = options & 0x04
- # richtext = options & 0x08
- if options & 0x08:
- # rt = unpack('<H', data[pos:pos+2])[0] # unused
- pos += 2
- if options & 0x04:
- # sz = unpack('<i', data[pos:pos+4])[0] # unused
- pos += 4
- if options & 0x01:
- # Uncompressed UTF-16-LE
- rawstrg = data[pos:pos+2*nchars]
- # if DEBUG: print "nchars=%d pos=%d rawstrg=%r" % (nchars, pos, rawstrg)
- strg = unicode(rawstrg, 'utf_16_le')
- # pos += 2*nchars
- else:
- # Note: this is COMPRESSED (not ASCII!) encoding!!!
- # Merely returning the raw bytes would work OK 99.99% of the time
- # if the local codepage was cp1252 -- however this would rapidly go pear-shaped
- # for other codepages so we grit our Anglocentric teeth and return Unicode :-)
-
- strg = unicode(data[pos:pos+nchars], "latin_1")
- # pos += nchars
- # if richtext:
- # pos += 4 * rt
- # if phonetic:
- # pos += sz
- # return (strg, pos)
- return strg
-
-def unpack_unicode_update_pos(data, pos, lenlen=2, known_len=None):
- "Return (unicode_strg, updated value of pos)"
- if known_len is not None:
- # On a NAME record, the length byte is detached from the front of the string.
- nchars = known_len
- else:
- nchars = unpack('<' + 'BH'[lenlen-1], data[pos:pos+lenlen])[0]
- pos += lenlen
- if not nchars and not data[pos:]:
- # Zero-length string with no options byte
- return (u"", pos)
- options = ord(data[pos])
- pos += 1
- phonetic = options & 0x04
- richtext = options & 0x08
- if richtext:
- rt = unpack('<H', data[pos:pos+2])[0]
- pos += 2
- if phonetic:
- sz = unpack('<i', data[pos:pos+4])[0]
- pos += 4
- if options & 0x01:
- # Uncompressed UTF-16-LE
- strg = unicode(data[pos:pos+2*nchars], 'utf_16_le')
- pos += 2*nchars
- else:
- # Note: this is COMPRESSED (not ASCII!) encoding!!!
- strg = unicode(data[pos:pos+nchars], "latin_1")
- pos += nchars
- if richtext:
- pos += 4 * rt
- if phonetic:
- pos += sz
- return (strg, pos)
-
-def unpack_cell_range_address_list_update_pos(
- output_list, data, pos, biff_version, addr_size=6):
- # output_list is updated in situ
- if biff_version < 80:
- assert addr_size == 6
- else:
- assert addr_size in (6, 8)
- n, = unpack("<H", data[pos:pos+2])
- pos += 2
- if n:
- if addr_size == 6:
- fmt = "<HHBB"
- else:
- fmt = "<HHHH"
- for _unused in xrange(n):
- ra, rb, ca, cb = unpack(fmt, data[pos:pos+addr_size])
- output_list.append((ra, rb+1, ca, cb+1))
- pos += addr_size
- return pos
-
-_brecstrg = """\
-0000 DIMENSIONS_B2
-0001 BLANK_B2
-0002 INTEGER_B2_ONLY
-0003 NUMBER_B2
-0004 LABEL_B2
-0005 BOOLERR_B2
-0006 FORMULA
-0007 STRING_B2
-0008 ROW_B2
-0009 BOF_B2
-000A EOF
-000B INDEX_B2_ONLY
-000C CALCCOUNT
-000D CALCMODE
-000E PRECISION
-000F REFMODE
-0010 DELTA
-0011 ITERATION
-0012 PROTECT
-0013 PASSWORD
-0014 HEADER
-0015 FOOTER
-0016 EXTERNCOUNT
-0017 EXTERNSHEET
-0018 NAME_B2,5+
-0019 WINDOWPROTECT
-001A VERTICALPAGEBREAKS
-001B HORIZONTALPAGEBREAKS
-001C NOTE
-001D SELECTION
-001E FORMAT_B2-3
-001F BUILTINFMTCOUNT_B2
-0020 COLUMNDEFAULT_B2_ONLY
-0021 ARRAY_B2_ONLY
-0022 DATEMODE
-0023 EXTERNNAME
-0024 COLWIDTH_B2_ONLY
-0025 DEFAULTROWHEIGHT_B2_ONLY
-0026 LEFTMARGIN
-0027 RIGHTMARGIN
-0028 TOPMARGIN
-0029 BOTTOMMARGIN
-002A PRINTHEADERS
-002B PRINTGRIDLINES
-002F FILEPASS
-0031 FONT
-0032 FONT2_B2_ONLY
-0036 TABLEOP_B2
-0037 TABLEOP2_B2
-003C CONTINUE
-003D WINDOW1
-003E WINDOW2_B2
-0040 BACKUP
-0041 PANE
-0042 CODEPAGE
-0043 XF_B2
-0044 IXFE_B2_ONLY
-0045 EFONT_B2_ONLY
-004D PLS
-0051 DCONREF
-0055 DEFCOLWIDTH
-0056 BUILTINFMTCOUNT_B3-4
-0059 XCT
-005A CRN
-005B FILESHARING
-005C WRITEACCESS
-005D OBJECT
-005E UNCALCED
-005F SAVERECALC
-0063 OBJECTPROTECT
-007D COLINFO
-007E RK2_mythical_?
-0080 GUTS
-0081 WSBOOL
-0082 GRIDSET
-0083 HCENTER
-0084 VCENTER
-0085 BOUNDSHEET
-0086 WRITEPROT
-008C COUNTRY
-008D HIDEOBJ
-008E SHEETSOFFSET
-008F SHEETHDR
-0090 SORT
-0092 PALETTE
-0099 STANDARDWIDTH
-009B FILTERMODE
-009C FNGROUPCOUNT
-009D AUTOFILTERINFO
-009E AUTOFILTER
-00A0 SCL
-00A1 SETUP
-00AB GCW
-00BD MULRK
-00BE MULBLANK
-00C1 MMS
-00D6 RSTRING
-00D7 DBCELL
-00DA BOOKBOOL
-00DD SCENPROTECT
-00E0 XF
-00E1 INTERFACEHDR
-00E2 INTERFACEEND
-00E5 MERGEDCELLS
-00E9 BITMAP
-00EB MSO_DRAWING_GROUP
-00EC MSO_DRAWING
-00ED MSO_DRAWING_SELECTION
-00EF PHONETIC
-00FC SST
-00FD LABELSST
-00FF EXTSST
-013D TABID
-015F LABELRANGES
-0160 USESELFS
-0161 DSF
-01AE SUPBOOK
-01AF PROTECTIONREV4
-01B0 CONDFMT
-01B1 CF
-01B2 DVAL
-01B6 TXO
-01B7 REFRESHALL
-01B8 HLINK
-01BC PASSWORDREV4
-01BE DV
-01C0 XL9FILE
-01C1 RECALCID
-0200 DIMENSIONS
-0201 BLANK
-0203 NUMBER
-0204 LABEL
-0205 BOOLERR
-0206 FORMULA_B3
-0207 STRING
-0208 ROW
-0209 BOF
-020B INDEX_B3+
-0218 NAME
-0221 ARRAY
-0223 EXTERNNAME_B3-4
-0225 DEFAULTROWHEIGHT
-0231 FONT_B3B4
-0236 TABLEOP
-023E WINDOW2
-0243 XF_B3
-027E RK
-0293 STYLE
-0406 FORMULA_B4
-0409 BOF
-041E FORMAT
-0443 XF_B4
-04BC SHRFMLA
-0800 QUICKTIP
-0809 BOF
-0862 SHEETLAYOUT
-0867 SHEETPROTECTION
-0868 RANGEPROTECTION
-"""
-
-biff_rec_name_dict = {}
-for _buff in _brecstrg.splitlines():
- _numh, _name = _buff.split()
- biff_rec_name_dict[int(_numh, 16)] = _name
-del _buff, _name, _brecstrg
-
-def hex_char_dump(strg, ofs, dlen, base=0, fout=sys.stdout, unnumbered=False):
- endpos = min(ofs + dlen, len(strg))
- pos = ofs
- numbered = not unnumbered
- num_prefix = ''
- while pos < endpos:
- endsub = min(pos + 16, endpos)
- substrg = strg[pos:endsub]
- lensub = endsub - pos
- if lensub <= 0 or lensub != len(substrg):
- fprintf(
- sys.stdout,
- '??? hex_char_dump: ofs=%d dlen=%d base=%d -> endpos=%d pos=%d endsub=%d substrg=%r\n',
- ofs, dlen, base, endpos, pos, endsub, substrg)
- break
- hexd = ''.join(["%02x " % ord(c) for c in substrg])
- chard = ''
- for c in substrg:
- if c == '\0':
- c = '~'
- elif not (' ' <= c <= '~'):
- c = '?'
- chard += c
- if numbered:
- num_prefix = "%5d: " % (base+pos-ofs)
- fprintf(fout, "%s %-48s %s\n", num_prefix, hexd, chard)
- pos = endsub
-
-def biff_dump(mem, stream_offset, stream_len, base=0, fout=sys.stdout, unnumbered=False):
- pos = stream_offset
- stream_end = stream_offset + stream_len
- adj = base - stream_offset
- dummies = 0
- numbered = not unnumbered
- num_prefix = ''
- while stream_end - pos >= 4:
- rc, length = unpack('<HH', mem[pos:pos+4])
- if rc == 0 and length == 0:
- if mem[pos:] == '\0' * (stream_end - pos):
- dummies = stream_end - pos
- savpos = pos
- pos = stream_end
- break
- if dummies:
- dummies += 4
- else:
- savpos = pos
- dummies = 4
- pos += 4
- else:
- if dummies:
- if numbered:
- num_prefix = "%5d: " % (adj + savpos)
- fprintf(fout, "%s---- %d zero bytes skipped ----\n", num_prefix, dummies)
- dummies = 0
- recname = biff_rec_name_dict.get(rc, '<UNKNOWN>')
- if numbered:
- num_prefix = "%5d: " % (adj + pos)
- fprintf(fout, "%s%04x %s len = %04x (%d)\n", num_prefix, rc, recname, length, length)
- pos += 4
- hex_char_dump(mem, pos, length, adj+pos, fout, unnumbered)
- pos += length
- if dummies:
- if numbered:
- num_prefix = "%5d: " % (adj + savpos)
- fprintf(fout, "%s---- %d zero bytes skipped ----\n", num_prefix, dummies)
- if pos < stream_end:
- if numbered:
- num_prefix = "%5d: " % (adj + pos)
- fprintf(fout, "%s---- Misc bytes at end ----\n", num_prefix)
- hex_char_dump(mem, pos, stream_end-pos, adj + pos, fout, unnumbered)
- elif pos > stream_end:
- fprintf(fout, "Last dumped record has length (%d) that is too large\n", length)
-
-def biff_count_records(mem, stream_offset, stream_len, fout=sys.stdout):
- pos = stream_offset
- stream_end = stream_offset + stream_len
- tally = {}
- while stream_end - pos >= 4:
- rc, length = unpack('<HH', mem[pos:pos+4])
- if rc == 0 and length == 0:
- if mem[pos:] == '\0' * (stream_end - pos):
- break
- recname = "<Dummy (zero)>"
- else:
- recname = biff_rec_name_dict.get(rc, None)
- if recname is None:
- recname = "Unknown_0x%04X" % rc
- if tally.has_key(recname):
- tally[recname] += 1
- else:
- tally[recname] = 1
- pos += length + 4
- slist = tally.items()
- slist.sort()
- for recname, count in slist:
- print >> fout, "%8d %s" % (count, recname)
-
-encoding_from_codepage = {
- 1200 : 'utf_16_le',
- 10000: 'mac_roman',
- 10006: 'mac_greek', # guess
- 10007: 'mac_cyrillic', # guess
- 10029: 'mac_latin2', # guess
- 10079: 'mac_iceland', # guess
- 10081: 'mac_turkish', # guess
- 32768: 'mac_roman',
- 32769: 'cp1252',
- }
-# some more guessing, for Indic scripts
-# codepage 57000 range:
-# 2 Devanagari [0]
-# 3 Bengali [1]
-# 4 Tamil [5]
-# 5 Telegu [6]
-# 6 Assamese [1] c.f. Bengali
-# 7 Oriya [4]
-# 8 Kannada [7]
-# 9 Malayalam [8]
-# 10 Gujarati [3]
-# 11 Gurmukhi [2]
diff --git a/tablib/packages/xlrd/compdoc.py b/tablib/packages/xlrd/compdoc.py
deleted file mode 100644
index 3abb7a6..0000000
--- a/tablib/packages/xlrd/compdoc.py
+++ /dev/null
@@ -1,358 +0,0 @@
-# -*- coding: cp1252 -*-
-
-##
-# Implements the minimal functionality required
-# to extract a "Workbook" or "Book" stream (as one big string)
-# from an OLE2 Compound Document file.
-# <p>Copyright 2005-2008 Stephen John Machin, Lingfo Pty Ltd</p>
-# <p>This module is part of the xlrd package, which is released under a BSD-style licence.</p>
-##
-
-# No part of the content of this file was derived from the works of David Giffin.
-
-# 2008-11-04 SJM Avoid assertion error when -1 used instead of -2 for first_SID of empty SCSS [Frank Hoffsuemmer]
-# 2007-09-08 SJM Warning message if sector sizes are extremely large.
-# 2007-05-07 SJM Meaningful exception instead of IndexError if a SAT (sector allocation table) is corrupted.
-# 2007-04-22 SJM Missing "<" in a struct.unpack call => can't open files on bigendian platforms.
-
-
-import sys
-from struct import unpack
-from timemachine import *
-
-##
-# Magic cookie that should appear in the first 8 bytes of the file.
-SIGNATURE = "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"
-
-EOCSID = -2
-FREESID = -1
-SATSID = -3
-MSATSID = -4
-
-class CompDocError(Exception):
- pass
-
-class DirNode(object):
-
- def __init__(self, DID, dent, DEBUG=0):
- # dent is the 128-byte directory entry
- self.DID = DID
- # (cbufsize, self.etype, self.colour, self.left_DID, self.right_DID,
- # self.root_DID,
- # self.first_SID,
- # self.tot_size) = \
- # unpack('<HBBiii16x4x8x8xii4x', dent[64:128])
- (cbufsize, self.etype, self.colour, self.left_DID, self.right_DID,
- self.root_DID) = \
- unpack('<HBBiii', dent[64:80])
- (self.first_SID, self.tot_size) = \
- unpack('<ii', dent[116:124])
- if cbufsize == 0:
- self.name = u''
- else:
- self.name = unicode(dent[0:cbufsize-2], 'utf_16_le') # omit the trailing U+0000
- self.children = [] # filled in later
- self.parent = -1 # indicates orphan; fixed up later
- self.tsinfo = unpack('<IIII', dent[100:116])
- if DEBUG:
- self.dump(DEBUG)
-
- def dump(self, DEBUG=1):
- print "DID=%d name=%r etype=%d DIDs(left=%d right=%d root=%d parent=%d kids=%r) first_SID=%d tot_size=%d" \
- % (self.DID, self.name, self.etype, self.left_DID,
- self.right_DID, self.root_DID, self.parent, self.children, self.first_SID, self.tot_size)
- if DEBUG == 2:
- # cre_lo, cre_hi, mod_lo, mod_hi = tsinfo
- print "timestamp info", self.tsinfo
-
-def _build_family_tree(dirlist, parent_DID, child_DID):
- if child_DID < 0: return
- _build_family_tree(dirlist, parent_DID, dirlist[child_DID].left_DID)
- dirlist[parent_DID].children.append(child_DID)
- dirlist[child_DID].parent = parent_DID
- _build_family_tree(dirlist, parent_DID, dirlist[child_DID].right_DID)
- if dirlist[child_DID].etype == 1: # storage
- _build_family_tree(dirlist, child_DID, dirlist[child_DID].root_DID)
-
-##
-# Compound document handler.
-# @param mem The raw contents of the file, as a string, or as an mmap.mmap() object. The
-# only operation it needs to support is slicing.
-
-class CompDoc(object):
-
- def __init__(self, mem, logfile=sys.stdout, DEBUG=0):
- self.logfile = logfile
- if mem[0:8] != SIGNATURE:
- raise CompDocError('Not an OLE2 compound document')
- if mem[28:30] != '\xFE\xFF':
- raise CompDocError('Expected "little-endian" marker, found %r' % mem[28:30])
- revision, version = unpack('<HH', mem[24:28])
- if DEBUG:
- print >> logfile, "\nCompDoc format: version=0x%04x revision=0x%04x" % (version, revision)
- self.mem = mem
- ssz, sssz = unpack('<HH', mem[30:34])
- if ssz > 20: # allows for 2**20 bytes i.e. 1MB
- print >> logfile, \
- "WARNING: sector size (2**%d) is preposterous; assuming 512 and continuing ..." \
- % ssz
- ssz = 9
- if sssz > ssz:
- print >> logfile, \
- "WARNING: short stream sector size (2**%d) is preposterous; assuming 64 and continuing ..." \
- % sssz
- sssz = 6
- self.sec_size = sec_size = 1 << ssz
- self.short_sec_size = 1 << sssz
- (
- SAT_tot_secs, self.dir_first_sec_sid, _unused, self.min_size_std_stream,
- SSAT_first_sec_sid, SSAT_tot_secs,
- MSAT_first_sec_sid, MSAT_tot_secs,
- # ) = unpack('<ii4xiiiii', mem[44:76])
- ) = unpack('<iiiiiiii', mem[44:76])
- mem_data_len = len(mem) - 512
- mem_data_secs, left_over = divmod(mem_data_len, sec_size)
- if left_over:
- #### raise CompDocError("Not a whole number of sectors")
- print >> logfile, \
- "WARNING *** file size (%d) not 512 + multiple of sector size (%d)" \
- % (len(mem), sec_size)
- if DEBUG:
- print >> logfile, 'sec sizes', ssz, sssz, sec_size, self.short_sec_size
- print >> logfile, "mem data: %d bytes == %d sectors" % (mem_data_len, mem_data_secs)
- print >> logfile, "SAT_tot_secs=%d, dir_first_sec_sid=%d, min_size_std_stream=%d" \
- % (SAT_tot_secs, self.dir_first_sec_sid, self.min_size_std_stream,)
- print >> logfile, "SSAT_first_sec_sid=%d, SSAT_tot_secs=%d" % (SSAT_first_sec_sid, SSAT_tot_secs,)
- print >> logfile, "MSAT_first_sec_sid=%d, MSAT_tot_secs=%d" % (MSAT_first_sec_sid, MSAT_tot_secs,)
- nent = int_floor_div(sec_size, 4) # number of SID entries in a sector
- fmt = "<%di" % nent
- trunc_warned = 0
- #
- # === build the MSAT ===
- #
- MSAT = list(unpack('<109i', mem[76:512]))
- sid = MSAT_first_sec_sid
- while sid >= 0:
- if sid >= mem_data_secs:
- raise CompDocError(
- "MSAT extension: accessing sector %d but only %d in file" % (sid, mem_data_secs)
- )
- offset = 512 + sec_size * sid
- news = list(unpack(fmt, mem[offset:offset+sec_size]))
- sid = news.pop()
- MSAT.extend(news)
- if DEBUG:
- print >> logfile, "MSAT: len =", len(MSAT)
- print >> logfile, MSAT
- #
- # === build the SAT ===
- #
- self.SAT = []
- for msid in MSAT:
- if msid == FREESID: continue
- if msid >= mem_data_secs:
- if not trunc_warned:
- print >> logfile, "WARNING *** File is truncated, or OLE2 MSAT is corrupt!!"
- print >> logfile, \
- "INFO: Trying to access sector %d but only %d available" \
- % (msid, mem_data_secs)
- trunc_warned = 1
- continue
- offset = 512 + sec_size * msid
- news = list(unpack(fmt, mem[offset:offset+sec_size]))
- self.SAT.extend(news)
- if DEBUG:
- print >> logfile, "SAT: len =", len(self.SAT)
- print >> logfile, self.SAT
- # print >> logfile, "SAT ",
- # for i, s in enumerate(self.SAT):
- # print >> logfile, "entry: %4d offset: %6d, next entry: %4d" % (i, 512 + sec_size * i, s)
- # print >> logfile, "%d:%d " % (i, s),
- print
-
- # === build the directory ===
- #
- dbytes = self._get_stream(
- self.mem, 512, self.SAT, self.sec_size, self.dir_first_sec_sid,
- name="directory")
- dirlist = []
- did = -1
- for pos in xrange(0, len(dbytes), 128):
- did += 1
- dirlist.append(DirNode(did, dbytes[pos:pos+128], 0))
- self.dirlist = dirlist
- _build_family_tree(dirlist, 0, dirlist[0].root_DID) # and stand well back ...
- if DEBUG:
- for d in dirlist:
- d.dump(DEBUG)
- #
- # === get the SSCS ===
- #
- sscs_dir = self.dirlist[0]
- assert sscs_dir.etype == 5 # root entry
- if sscs_dir.first_SID < 0 and sscs_dir.tot_size == 0:
- # Problem reported by Frank Hoffsuemmer: some software was
- # writing -1 instead of -2 (EOCSID) for the first_SID
- # when the SCCS was empty. Not having EOCSID caused assertion
- # failure in _get_stream.
- # Solution: avoid calling _get_stream in any case when the
- # SCSS appears to be empty.
- self.SSCS = ""
- else:
- self.SSCS = self._get_stream(
- self.mem, 512, self.SAT, sec_size, sscs_dir.first_SID,
- sscs_dir.tot_size, name="SSCS")
- # if DEBUG: print >> logfile, "SSCS", repr(self.SSCS)
- #
- # === build the SSAT ===
- #
- self.SSAT = []
- if SSAT_tot_secs > 0 and sscs_dir.tot_size == 0:
- print >> logfile, \
- "WARNING *** OLE2 inconsistency: SSCS size is 0 but SSAT size is non-zero"
- if sscs_dir.tot_size > 0:
- sid = SSAT_first_sec_sid
- nsecs = SSAT_tot_secs
- while sid >= 0 and nsecs > 0:
- nsecs -= 1
- start_pos = 512 + sid * sec_size
- news = list(unpack(fmt, mem[start_pos:start_pos+sec_size]))
- self.SSAT.extend(news)
- sid = self.SAT[sid]
- # assert SSAT_tot_secs == 0 or sid == EOCSID
- if DEBUG: print >> logfile, "SSAT last sid %d; remaining sectors %d" % (sid, nsecs)
- assert nsecs == 0 and sid == EOCSID
- if DEBUG: print >> logfile, "SSAT", self.SSAT
-
- def _get_stream(self, mem, base, sat, sec_size, start_sid, size=None, name=''):
- # print >> self.logfile, "_get_stream", base, sec_size, start_sid, size
- sectors = []
- s = start_sid
- if size is None:
- # nothing to check against
- while s >= 0:
- start_pos = base + s * sec_size
- sectors.append(mem[start_pos:start_pos+sec_size])
- try:
- s = sat[s]
- except IndexError:
- raise CompDocError(
- "OLE2 stream %r: sector allocation table invalid entry (%d)" %
- (name, s)
- )
- assert s == EOCSID
- else:
- todo = size
- while s >= 0:
- start_pos = base + s * sec_size
- grab = sec_size
- if grab > todo:
- grab = todo
- todo -= grab
- sectors.append(mem[start_pos:start_pos+grab])
- try:
- s = sat[s]
- except IndexError:
- raise CompDocError(
- "OLE2 stream %r: sector allocation table invalid entry (%d)" %
- (name, s)
- )
- assert s == EOCSID
- if todo != 0:
- print >> self.logfile, \
- "WARNING *** OLE2 stream %r: expected size %d, actual size %d" \
- % (name, size, size - todo)
- return ''.join(sectors)
-
- def _dir_search(self, path, storage_DID=0):
- # Return matching DirNode instance, or None
- head = path[0]
- tail = path[1:]
- dl = self.dirlist
- for child in dl[storage_DID].children:
- if dl[child].name.lower() == head.lower():
- et = dl[child].etype
- if et == 2:
- return dl[child]
- if et == 1:
- if not tail:
- raise CompDocError("Requested component is a 'storage'")
- return self._dir_search(tail, child)
- dl[child].dump(1)
- raise CompDocError("Requested stream is not a 'user stream'")
- return None
-
- ##
- # Interrogate the compound document's directory; return the stream as a string if found, otherwise
- # return None.
- # @param qname Name of the desired stream e.g. u'Workbook'. Should be in Unicode or convertible thereto.
-
- def get_named_stream(self, qname):
- d = self._dir_search(qname.split("/"))
- if d is None:
- return None
- if d.tot_size >= self.min_size_std_stream:
- return self._get_stream(
- self.mem, 512, self.SAT, self.sec_size, d.first_SID,
- d.tot_size, name=qname)
- else:
- return self._get_stream(
- self.SSCS, 0, self.SSAT, self.short_sec_size, d.first_SID,
- d.tot_size, name=qname + " (from SSCS)")
-
- ##
- # Interrogate the compound document's directory.
- # If the named stream is not found, (None, 0, 0) will be returned.
- # If the named stream is found and is contiguous within the original byte sequence ("mem")
- # used when the document was opened,
- # then (mem, offset_to_start_of_stream, length_of_stream) is returned.
- # Otherwise a new string is built from the fragments and (new_string, 0, length_of_stream) is returned.
- # @param qname Name of the desired stream e.g. u'Workbook'. Should be in Unicode or convertible thereto.
-
- def locate_named_stream(self, qname):
- d = self._dir_search(qname.split("/"))
- if d is None:
- return (None, 0, 0)
- if d.tot_size >= self.min_size_std_stream:
- return self._locate_stream(self.mem, 512, self.SAT, self.sec_size, d.first_SID, d.tot_size)
- else:
- return (
- self._get_stream(
- self.SSCS, 0, self.SSAT, self.short_sec_size, d.first_SID,
- d.tot_size, qname + " (from SSCS)"),
- 0,
- d.tot_size
- )
- return (None, 0, 0) # not found
-
- def _locate_stream(self, mem, base, sat, sec_size, start_sid, size):
- # print >> self.logfile, "_locate_stream", base, sec_size, start_sid, size
- s = start_sid
- if s < 0:
- raise CompDocError("_locate_stream: start_sid (%d) is -ve" % start_sid)
- p = -99 # dummy previous SID
- start_pos = -9999
- end_pos = -8888
- slices = []
- while s >= 0:
- if s == p+1:
- # contiguous sectors
- end_pos += sec_size
- else:
- # start new slice
- if p >= 0:
- # not first time
- slices.append((start_pos, end_pos))
- start_pos = base + s * sec_size
- end_pos = start_pos + sec_size
- p = s
- s = sat[s]
- assert s == EOCSID
- # print >> self.logfile, len(slices) + 1, "slices"
- if not slices:
- # The stream is contiguous ... just what we like!
- return (mem, start_pos, size)
- slices.append((start_pos, end_pos))
- return (''.join([mem[start_pos:end_pos] for start_pos, end_pos in slices]), 0, size)
-
-# ==========================================================================================
diff --git a/tablib/packages/xlrd/doc/compdoc.html b/tablib/packages/xlrd/doc/compdoc.html
deleted file mode 100644
index c55a194..0000000
--- a/tablib/packages/xlrd/doc/compdoc.html
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
-<html>
-<head>
-<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
-<title>The compdoc Module</title>
-</head>
-<body>
-<h1>The compdoc Module</h1>
-<p>Implements the minimal functionality required
-to extract a "Workbook" or "Book" stream (as one big string)
-from an OLE2 Compound Document file.
-</p><p>Copyright &#169; 2005-2008 Stephen John Machin, Lingfo Pty Ltd</p>
-<p>This module is part of the xlrd package, which is released under a BSD-style licence.</p>
-<h2>Module Contents</h2>
-<dl>
-<dt><b>CompDoc(mem, logfile=sys.stdout, DEBUG=0)</b> (class) [<a href='#compdoc.CompDoc-class'>#</a>]</dt>
-<dd>
-<p>Compound document handler.</p>
-<dl>
-<dt><i>mem</i></dt>
-<dd>
-The raw contents of the file, as a string, or as an mmap.mmap() object. The
-only operation it needs to support is slicing.</dd>
-</dl><br />
-<p>For more information about this class, see <a href='#compdoc.CompDoc-class'><i>The CompDoc Class</i></a>.</p>
-</dd>
-<dt><a id='compdoc.SIGNATURE-variable' name='compdoc.SIGNATURE-variable'><b>SIGNATURE</b></a> (variable) [<a href='#compdoc.SIGNATURE-variable'>#</a>]</dt>
-<dd>
-<p>Magic cookie that should appear in the first 8 bytes of the file.</p>
-</dd>
-</dl>
-<h2><a id='compdoc.CompDoc-class' name='compdoc.CompDoc-class'>The CompDoc Class</a></h2>
-<dl>
-<dt><b>CompDoc(mem, logfile=sys.stdout, DEBUG=0)</b> (class) [<a href='#compdoc.CompDoc-class'>#</a>]</dt>
-<dd>
-<p>Compound document handler.</p>
-<dl>
-<dt><i>mem</i></dt>
-<dd>
-The raw contents of the file, as a string, or as an mmap.mmap() object. The
-only operation it needs to support is slicing.</dd>
-</dl><br />
-</dd>
-<dt><a id='compdoc.CompDoc.get_named_stream-method' name='compdoc.CompDoc.get_named_stream-method'><b>get_named_stream(qname)</b></a> [<a href='#compdoc.CompDoc.get_named_stream-method'>#</a>]</dt>
-<dd>
-<p>Interrogate the compound document's directory; return the stream as a string if found, otherwise
-return None.</p>
-<dl>
-<dt><i>qname</i></dt>
-<dd>
-Name of the desired stream e.g. u'Workbook'. Should be in Unicode or convertible thereto.</dd>
-</dl><br />
-</dd>
-<dt><a id='compdoc.CompDoc.locate_named_stream-method' name='compdoc.CompDoc.locate_named_stream-method'><b>locate_named_stream(qname)</b></a> [<a href='#compdoc.CompDoc.locate_named_stream-method'>#</a>]</dt>
-<dd>
-<p>Interrogate the compound document's directory.
-If the named stream is not found, (None, 0, 0) will be returned.
-If the named stream is found and is contiguous within the original byte sequence (&quot;mem&quot;)
-used when the document was opened,
-then (mem, offset_to_start_of_stream, length_of_stream) is returned.
-Otherwise a new string is built from the fragments and (new_string, 0, length_of_stream) is returned.</p>
-<dl>
-<dt><i>qname</i></dt>
-<dd>
-Name of the desired stream e.g. u'Workbook'. Should be in Unicode or convertible thereto.</dd>
-</dl><br />
-</dd>
-</dl>
-</body></html>
diff --git a/tablib/packages/xlrd/doc/xlrd.html b/tablib/packages/xlrd/doc/xlrd.html
deleted file mode 100644
index f982e0e..0000000
--- a/tablib/packages/xlrd/doc/xlrd.html
+++ /dev/null
@@ -1,1845 +0,0 @@
-<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
-<html>
-<head>
-<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
-<title>The xlrd Module</title>
-</head>
-<body>
-<h1>The xlrd Module</h1>
-<p /><p><b>A Python module for extracting data from MS Excel &#8482; spreadsheet files.
-<br /><br />
-Version 0.7.1 -- 2009-05-31
-</b></p>
-
-<h2>General information</h2>
-
-<h3>Acknowledgements</h3>
-
-<p>
-Development of this module would not have been possible without the document
-"OpenOffice.org's Documentation of the Microsoft Excel File Format"
-("OOo docs" for short).
-The latest version is available from OpenOffice.org in
-<a href="http://sc.openoffice.org/excelfileformat.pdf"> PDF format</a>
-and
-<a href="http://sc.openoffice.org/excelfileformat.odt"> ODT format.</a>
-Small portions of the OOo docs are reproduced in this
-document. A study of the OOo docs is recommended for those who wish a
-deeper understanding of the Excel file layout than the xlrd docs can provide.
-</p>
-
-<p>Backporting to Python 2.1 was partially funded by
- <a href="http://journyx.com/">
- Journyx - provider of timesheet and project accounting solutions.
- </a>
-</p>
-
-<p>Provision of formatting information in version 0.6.1 was funded by
- <a href="http://www.simplistix.co.uk">
- Simplistix Ltd.
- </a>
-</p>
-
-<h3>Unicode</h3>
-
-<p>This module presents all text strings as Python unicode objects.
-From Excel 97 onwards, text in Excel spreadsheets has been stored as Unicode.
-Older files (Excel 95 and earlier) don't keep strings in Unicode;
-a CODEPAGE record provides a codepage number (for example, 1252) which is
-used by xlrd to derive the encoding (for same example: "cp1252") which is
-used to translate to Unicode.</p>
-<small>
-<p>If the CODEPAGE record is missing (possible if the file was created
-by third-party software), xlrd will assume that the encoding is ascii, and keep going.
-If the actual encoding is not ascii, a UnicodeDecodeError exception will be raised and
-you will need to determine the encoding yourself, and tell xlrd:
-<pre>
- book = xlrd.open_workbook(..., encoding_override="cp1252")
-</pre></p>
-<p>If the CODEPAGE record exists but is wrong (for example, the codepage
-number is 1251, but the strings are actually encoded in koi8_r),
-it can be overridden using the same mechanism.
-The supplied runxlrd.py has a corresponding command-line argument, which
-may be used for experimentation:
-<pre>
- runxlrd.py -e koi8_r 3rows myfile.xls
-</pre></p>
-<p>The first place to look for an encoding ("codec name") is
-<a href="http://docs.python.org/lib/standard-encodings.html">
-the Python documentation</a>.
-</p>
-</small>
-
-<h3>Dates in Excel spreadsheets</h3>
-
-<p>In reality, there are no such things. What you have are floating point
-numbers and pious hope.
-There are several problems with Excel dates:</p>
-
-<p>(1) Dates are not stored as a separate data type; they are stored as
-floating point numbers and you have to rely on
-(a) the "number format" applied to them in Excel and/or
-(b) knowing which cells are supposed to have dates in them.
-This module helps with (a) by inspecting the
-format that has been applied to each number cell;
-if it appears to be a date format, the cell
-is classified as a date rather than a number. Feedback on this feature,
-especially from non-English-speaking locales, would be appreciated.</p>
-
-<p>(2) Excel for Windows stores dates by default as the number of
-days (or fraction thereof) since 1899-12-31T00:00:00. Excel for
-Macintosh uses a default start date of 1904-01-01T00:00:00. The date
-system can be changed in Excel on a per-workbook basis (for example:
-Tools -&gt; Options -&gt; Calculation, tick the "1904 date system" box).
-This is of course a bad idea if there are already dates in the
-workbook. There is no good reason to change it even if there are no
-dates in the workbook. Which date system is in use is recorded in the
-workbook. A workbook transported from Windows to Macintosh (or vice
-versa) will work correctly with the host Excel. When using this
-module's xldate_as_tuple function to convert numbers from a workbook,
-you must use the datemode attribute of the Book object. If you guess,
-or make a judgement depending on where you believe the workbook was
-created, you run the risk of being 1462 days out of kilter.</p>
-
-<p>Reference:
-http://support.microsoft.com/default.aspx?scid=KB;EN-US;q180162</p>
-
-
-<p>(3) The Excel implementation of the Windows-default 1900-based date system works on the
-incorrect premise that 1900 was a leap year. It interprets the number 60 as meaning 1900-02-29,
-which is not a valid date. Consequently any number less than 61 is ambiguous. Example: is 59 the
-result of 1900-02-28 entered directly, or is it 1900-03-01 minus 2 days? The OpenOffice.org Calc
-program "corrects" the Microsoft problem; entering 1900-02-27 causes the number 59 to be stored.
-Save as an XLS file, then open the file with Excel -- you'll see 1900-02-28 displayed.</p>
-
-<p>Reference: http://support.microsoft.com/default.aspx?scid=kb;en-us;214326</p>
-
-<p>(4) The Macintosh-default 1904-based date system counts 1904-01-02 as day 1 and 1904-01-01 as day zero.
-Thus any number such that (0.0 &lt;= number &lt; 1.0) is ambiguous. Is 0.625 a time of day (15:00:00),
-independent of the calendar,
-or should it be interpreted as an instant on a particular day (1904-01-01T15:00:00)?
-The xldate_* functions in this module
-take the view that such a number is a calendar-independent time of day (like Python's datetime.time type) for both
-date systems. This is consistent with more recent Microsoft documentation
-(for example, the help file for Excel 2002 which says that the first day
-in the 1904 date system is 1904-01-02).
-
-</p><p>(5) Usage of the Excel DATE() function may leave strange dates in a spreadsheet. Quoting the help file,
-in respect of the 1900 date system: "If year is between 0 (zero) and 1899 (inclusive),
-Excel adds that value to 1900 to calculate the year. For example, DATE(108,1,2) returns January 2, 2008 (1900+108)."
-This gimmick, semi-defensible only for arguments up to 99 and only in the pre-Y2K-awareness era,
-means that DATE(1899, 12, 31) is interpreted as 3799-12-31.</p>
-
-<p>For further information, please refer to the documentation for the xldate_* functions.</p>
-
-<h3> Named references, constants, formulas, and macros</h3>
-
-<p>
-A name is used to refer to a cell, a group of cells, a constant
-value, a formula, or a macro. Usually the scope of a name is global
-across the whole workbook. However it can be local to a worksheet.
-For example, if the sales figures are in different cells in
-different sheets, the user may define the name "Sales" in each
-sheet. There are built-in names, like "Print_Area" and
-"Print_Titles"; these two are naturally local to a sheet.
-</p><p>
-To inspect the names with a user interface like MS Excel, OOo Calc,
-or Gnumeric, click on Insert/Names/Define. This will show the global
-names, plus those local to the currently selected sheet.
-</p><p>
-A Book object provides two dictionaries (name_map and
-name_and_scope_map) and a list (name_obj_list) which allow various
-ways of accessing the Name objects. There is one Name object for
-each NAME record found in the workbook. Name objects have many
-attributes, several of which are relevant only when obj.macro is 1.
-</p><p>
-In the examples directory you will find namesdemo.xls which
-showcases the many different ways that names can be used, and
-xlrdnamesAPIdemo.py which offers 3 different queries for inspecting
-the names in your files, and shows how to extract whatever a name is
-referring to. There is currently one "convenience method",
-Name.cell(), which extracts the value in the case where the name
-refers to a single cell. More convenience methods are planned. The
-source code for Name.cell (in __init__.py) is an extra source of
-information on how the Name attributes hang together.
-</p>
-
-<p><i>Name information is <b>not</b> extracted from files older than
-Excel 5.0 (Book.biff_version &lt; 50)</i></p>
-
-<h3>Formatting</h3>
-
-<h4>Introduction</h4>
-
-<p>This collection of features, new in xlrd version 0.6.1, is intended
-to provide the information needed to (1) display/render spreadsheet contents
-(say) on a screen or in a PDF file, and (2) copy spreadsheet data to another
-file without losing the ability to display/render it.</p>
-
-<h4>The Palette; Colour Indexes</h4>
-
-<p>A colour is represented in Excel as a (red, green, blue) ("RGB") tuple
-with each component in range(256). However it is not possible to access an
-unlimited number of colours; each spreadsheet is limited to a palette of 64 different
-colours (24 in Excel 3.0 and 4.0, 8 in Excel 2.0). Colours are referenced by an index
-("colour index") into this palette.
-
-Colour indexes 0 to 7 represent 8 fixed built-in colours: black, white, red, green, blue,
-yellow, magenta, and cyan.</p><p>
-
-The remaining colours in the palette (8 to 63 in Excel 5.0 and later)
-can be changed by the user. In the Excel 2003 UI, Tools/Options/Color presents a palette
-of 7 rows of 8 colours. The last two rows are reserved for use in charts.<br />
-The correspondence between this grid and the assigned
-colour indexes is NOT left-to-right top-to-bottom.<br />
-Indexes 8 to 15 correspond to changeable
-parallels of the 8 fixed colours -- for example, index 7 is forever cyan;
-index 15 starts off being cyan but can be changed by the user.<br />
-
-The default colour for each index depends on the file version; tables of the defaults
-are available in the source code. If the user changes one or more colours,
-a PALETTE record appears in the XLS file -- it gives the RGB values for *all* changeable
-indexes.<br />
-Note that colours can be used in "number formats": "[CYAN]...." and "[COLOR8]...." refer
-to colour index 7; "[COLOR16]...." will produce cyan
-unless the user changes colour index 15 to something else.<br />
-
-</p><p>In addition, there are several "magic" colour indexes used by Excel:<br />
-0x18 (BIFF3-BIFF4), 0x40 (BIFF5-BIFF8): System window text colour for border lines
-(used in XF, CF, and WINDOW2 records)<br />
-0x19 (BIFF3-BIFF4), 0x41 (BIFF5-BIFF8): System window background colour for pattern background
-(used in XF and CF records )<br />
-0x43: System face colour (dialogue background colour)<br />
-0x4D: System window text colour for chart border lines<br />
-0x4E: System window background colour for chart areas<br />
-0x4F: Automatic colour for chart border lines (seems to be always Black)<br />
-0x50: System ToolTip background colour (used in note objects)<br />
-0x51: System ToolTip text colour (used in note objects)<br />
-0x7FFF: System window text colour for fonts (used in FONT and CF records)<br />
-Note 0x7FFF appears to be the *default* colour index. It appears quite often in FONT
-records.<br />
-
-<h4>Default Formatting</h4>
-
-Default formatting is applied to all empty cells (those not described by a cell record).
-Firstly row default information (ROW record, Rowinfo class) is used if available.
-Failing that, column default information (COLINFO record, Colinfo class) is used if available.
-As a last resort the worksheet/workbook default cell format will be used; this
-should always be present in an Excel file,
-described by the XF record with the fixed index 15 (0-based). By default, it uses the
-worksheet/workbook default cell style, described by the very first XF record (index 0).
-
-<h4> Formatting features not included in xlrd version 0.6.1</h4>
-<ul>
- <li>Rich text i.e. strings containing partial <b>bold</b> <i>italic</i>
- and <u>underlined</u> text, change of font inside a string, etc.
- See OOo docs s3.4 and s3.2</li>
- <li>Asian phonetic text (known as "ruby"), used for Japanese furigana. See OOo docs
- s3.4.2 (p15)</li>
- <li>Conditional formatting. See OOo docs
- s5.12, s6.21 (CONDFMT record), s6.16 (CF record)</li>
- <li>Miscellaneous sheet-level and book-level items e.g. printing layout, screen panes. </li>
- <li>Modern Excel file versions don't keep most of the built-in
- "number formats" in the file; Excel loads formats according to the
- user's locale. Currently xlrd's emulation of this is limited to
- a hard-wired table that applies to the US English locale. This may mean
- that currency symbols, date order, thousands separator, decimals separator, etc
- are inappropriate. Note that this does not affect users who are copying XLS
- files, only those who are visually rendering cells.</li>
-</ul>
-
-<h3>Loading worksheets on demand</h3>
-
-</p><p>This feature, new in version 0.7.1, is governed by the on_demand argument
-to the open_workbook() function and allows saving memory and time by loading
-only those sheets that the caller is interested in, and releasing sheets
-when no longer required.</p>
-
-<p>on_demand=False (default): No change. open_workbook() loads global data
-and all sheets, releases resources no longer required (principally the
-str or mmap object containing the Workbook stream), and returns.</p>
-
-<p>on_demand=True and BIFF version &lt; 5.0: A warning message is emitted,
-on_demand is recorded as False, and the old process is followed.</p>
-
-<p>on_demand=True and BIFF version &gt;= 5.0: open_workbook() loads global
-data and returns without releasing resources. At this stage, the only
-information available about sheets is Book.nsheets and Book.sheet_names().</p>
-
-<p>Book.sheet_by_name() and Book.sheet_by_index() will load the requested
-sheet if it is not already loaded.</p>
-
-<p>Book.sheets() will load all/any unloaded sheets.</p>
-
-<p>The caller may save memory by calling
-Book.unload_sheet(sheet_name_or_index) when finished with the sheet.
-This applies irrespective of the state of on_demand.</p>
-
-<p>The caller may re-load an unloaded sheet by calling Book.sheet_by_xxxx()
- -- except if those required resources have been released (which will
-have happened automatically when on_demand is false). This is the only
-case where an exception will be raised.</p>
-
-<p>The caller may query the state of a sheet:
-Book.sheet_loaded(sheet_name_or_index) -&gt; a bool</p>
-
-<h2>Module Contents</h2>
-<dl>
-<dt><b>BaseObject</b> (class) [<a href='#biffh.BaseObject-class'>#</a>]</dt>
-<dd>
-<p>Parent of almost all other classes in the package.</p>
-<p>For more information about this class, see <a href='#biffh.BaseObject-class'><i>The BaseObject Class</i></a>.</p>
-</dd>
-<dt><b>Book()</b> (class) [<a href='#__init__.Book-class'>#</a>]</dt>
-<dd>
-<p>Contents of a &quot;workbook&quot;.</p>
-<p>For more information about this class, see <a href='#__init__.Book-class'><i>The Book Class</i></a>.</p>
-</dd>
-<dt><b>Cell(ctype, value, xf_index=None)</b> (class) [<a href='#sheet.Cell-class'>#</a>]</dt>
-<dd>
-<p>Contains the data for one cell.</p>
-<p>For more information about this class, see <a href='#sheet.Cell-class'><i>The Cell Class</i></a>.</p>
-</dd>
-<dt><a id='formula.cellname-function' name='formula.cellname-function'><b>cellname(rowx, colx)</b></a> [<a href='#formula.cellname-function'>#</a>]</dt>
-<dd>
-<p>Utility function: (5, 7) =&gt; 'H6'</p>
-</dd>
-<dt><a id='formula.cellnameabs-function' name='formula.cellnameabs-function'><b>cellnameabs(rowx, colx)</b></a> [<a href='#formula.cellnameabs-function'>#</a>]</dt>
-<dd>
-<p>Utility function: (5, 7) =&gt; '$H$6'</p>
-</dd>
-<dt><b>Colinfo</b> (class) [<a href='#sheet.Colinfo-class'>#</a>]</dt>
-<dd>
-<p>Width and default formatting information that applies to one or
-more columns in a sheet.</p>
-<p>For more information about this class, see <a href='#sheet.Colinfo-class'><i>The Colinfo Class</i></a>.</p>
-</dd>
-<dt><a id='formula.colname-function' name='formula.colname-function'><b>colname(colx)</b></a> [<a href='#formula.colname-function'>#</a>]</dt>
-<dd>
-<p>Utility function: 7 =&gt; 'H', 27 =&gt; 'AB'</p>
-</dd>
-<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>
-<dd>
-<p>For debugging and analysis: summarise the file's BIFF records.
-I.e. produce a sorted file of (record_name, count).</p>
-<dl>
-<dt><i>filename</i></dt>
-<dd>
-The path to the file to be summarised.</dd>
-<dt><i>outfile</i></dt>
-<dd>
-An open file, to which the summary is written.</dd>
-</dl><br />
-</dd>
-<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>
-<dd>
-<p>For debugging: dump the file's BIFF records in char &amp; hex.
-</p><dl>
-<dt><i>filename</i></dt>
-<dd>
-The path to the file to be dumped.</dd>
-<dt><i>outfile</i></dt>
-<dd>
-An open file, to which the dump is written.</dd>
-<dt><i>unnumbered</i></dt>
-<dd>
-If true, omit offsets (for meaningful diffs).</dd>
-</dl><br />
-</dd>
-<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>
-<dd>
-<p>There is one and only one instance of an empty cell -- it's a singleton. This is it.
-You may use a test like &quot;acell is empty_cell&quot;.</p>
-</dd>
-<dt><b>EqNeAttrs</b> (class) [<a href='#formatting.EqNeAttrs-class'>#</a>]</dt>
-<dd>
-<p>This mixin class exists solely so that Format, Font, and XF....</p>
-<p>For more information about this class, see <a href='#formatting.EqNeAttrs-class'><i>The EqNeAttrs Class</i></a>.</p>
-</dd>
-<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>
-<dd>
-<p /><p>This dictionary can be used to produce a text version of the internal codes
-that Excel uses for error cells. Here are its contents:
-<pre>
-0x00: '#NULL!', # Intersection of two cell ranges is empty
-0x07: '#DIV/0!', # Division by zero
-0x0F: '#VALUE!', # Wrong type of operand
-0x17: '#REF!', # Illegal or deleted cell reference
-0x1D: '#NAME?', # Wrong function or range name
-0x24: '#NUM!', # Value range overflow
-0x2A: '#N/A!', # Argument or function not available
-</pre></p>
-</dd>
-<dt><b>Font</b> (class) [<a href='#formatting.Font-class'>#</a>]</dt>
-<dd>
-<p>An Excel &quot;font&quot; contains the details of not only what is normally
-considered a font, but also several other display attributes.</p>
-<p>For more information about this class, see <a href='#formatting.Font-class'><i>The Font Class</i></a>.</p>
-</dd>
-<dt><b>Format(format_key, ty, format_str)</b> (class) [<a href='#formatting.Format-class'>#</a>]</dt>
-<dd>
-<p>&quot;Number format&quot; information from a FORMAT record.</p>
-<p>For more information about this class, see <a href='#formatting.Format-class'><i>The Format Class</i></a>.</p>
-</dd>
-<dt><b>Name</b> (class) [<a href='#__init__.Name-class'>#</a>]</dt>
-<dd>
-<p>Information relating to a named reference, formula, macro, etc.</p>
-<p>For more information about this class, see <a href='#__init__.Name-class'><i>The Name Class</i></a>.</p>
-</dd>
-<dt><a id='__init__.open_workbook-function' name='__init__.open_workbook-function'><b>open_workbook(filename=None,
-logfile=sys.stdout, verbosity=0, pickleable=True, use_mmap=USE_MMAP,
-file_contents=None,
-encoding_override=None,
-formatting_info=False, on_demand=False,
-)</b></a> [<a href='#__init__.open_workbook-function'>#</a>]</dt>
-<dd>
-<p>Open a spreadsheet file for data extraction.</p>
-<dl>
-<dt><i>filename</i></dt>
-<dd>
-The path to the spreadsheet file to be opened.</dd>
-<dt><i>logfile</i></dt>
-<dd>
-An open file to which messages and diagnostics are written.</dd>
-<dt><i>verbosity</i></dt>
-<dd>
-Increases the volume of trace material written to the logfile.</dd>
-<dt><i>pickleable</i></dt>
-<dd>
-Default is true. In Python 2.4 or earlier, setting to false
-will cause use of array.array objects which save some memory but can't be pickled.
-In Python 2.5, array.arrays are used unconditionally. Note: if you have large files that
-you need to read multiple times, it can be much faster to cPickle.dump() the xlrd.Book object
-once, and use cPickle.load() multiple times.</dd>
-<dt><i>use_mmap</i></dt>
-<dd>
-Whether to use the mmap module is determined heuristically.
-Use this arg to override the result. Current heuristic: mmap is used if it exists.</dd>
-<dt><i>file_contents</i></dt>
-<dd>
-... as a string or an mmap.mmap object or some other behave-alike object.
-If file_contents is supplied, filename will not be used, except (possibly) in messages.</dd>
-<dt><i>encoding_override</i></dt>
-<dd>
-Used to overcome missing or bad codepage information
-in older-version files. Refer to discussion in the <b>Unicode</b> section above.
-<br /> -- New in version 0.6.0
-
-</dd>
-<dt><i>formatting_info</i></dt>
-<dd>
-Governs provision of a reference to an XF (eXtended Format) object
-for each cell in the worksheet.
-<br /> Default is <i>False</i>. This is backwards compatible and saves memory.
-"Blank" cells (those with their own formatting information but no data) are treated as empty
-(by ignoring the file's BLANK and MULBLANK records).
-It cuts off any bottom "margin" of rows of empty (and blank) cells and
-any right "margin" of columns of empty (and blank) cells.
-Only cell_value and cell_type are available.
-<br /> <i>True</i> provides all cells, including empty and blank cells.
-XF information is available for each cell.
-<br /> -- New in version 0.6.1
-
-</dd>
-<dt><i>on_demand</i></dt>
-<dd>
-Governs whether sheets are all loaded initially or when demanded
-by the caller. Please refer back to the section &quot;Loading worksheets on demand&quot; for details.
--- New in version 0.7.1</dd>
-<dt>Returns:</dt>
-<dd>
-An instance of the Book class.</dd>
-</dl><br />
-</dd>
-<dt><b>Operand(akind=None, avalue=None, arank=0, atext='?')</b> (class) [<a href='#formula.Operand-class'>#</a>]</dt>
-<dd>
-<p>Used in evaluating formulas.</p>
-<p>For more information about this class, see <a href='#formula.Operand-class'><i>The Operand Class</i></a>.</p>
-</dd>
-<dt><a id='formula.rangename3d-function' name='formula.rangename3d-function'><b>rangename3d(book, ref3d)</b></a> [<a href='#formula.rangename3d-function'>#</a>]</dt>
-<dd>
-<p>Utility function:
-<br /> Ref3D((1, 4, 5, 20, 7, 10)) =&gt; 'Sheet2:Sheet3!$H$6:$J$20'
-</p></dd>
-<dt><a id='formula.rangename3drel-function' name='formula.rangename3drel-function'><b>rangename3drel(book, ref3d)</b></a> [<a href='#formula.rangename3drel-function'>#</a>]</dt>
-<dd>
-<p>Utility function:
-<br /> Ref3D(coords=(0, 1, -32, -22, -13, 13), relflags=(0, 0, 1, 1, 1, 1))
-=&gt; 'Sheet1![@-13,#-32]:[@+12,#-23]'
-where '@' refers to the current or base column and '#'
-refers to the current or base row.
-</p></dd>
-<dt><b>Ref3D(atuple)</b> (class) [<a href='#formula.Ref3D-class'>#</a>]</dt>
-<dd>
-<p>Represents an absolute or relative 3-dimensional reference to a box
-of one or more cells.</p>
-<p>For more information about this class, see <a href='#formula.Ref3D-class'><i>The Ref3D Class</i></a>.</p>
-</dd>
-<dt><b>Rowinfo</b> (class) [<a href='#sheet.Rowinfo-class'>#</a>]</dt>
-<dd>
-<p>Height and default formatting information that applies to a row in a sheet.</p>
-<p>For more information about this class, see <a href='#sheet.Rowinfo-class'><i>The Rowinfo Class</i></a>.</p>
-</dd>
-<dt><b>Sheet(book, position, name, number)</b> (class) [<a href='#sheet.Sheet-class'>#</a>]</dt>
-<dd>
-<p>Contains the data for one worksheet.</p>
-<p>For more information about this class, see <a href='#sheet.Sheet-class'><i>The Sheet Class</i></a>.</p>
-</dd>
-<dt><b>XF</b> (class) [<a href='#formatting.XF-class'>#</a>]</dt>
-<dd>
-<p>eXtended Formatting information for cells, rows, columns and styles.</p>
-<p>For more information about this class, see <a href='#formatting.XF-class'><i>The XF Class</i></a>.</p>
-</dd>
-<dt><b>XFAlignment</b> (class) [<a href='#formatting.XFAlignment-class'>#</a>]</dt>
-<dd>
-<p>A collection of the alignment and similar attributes of an XF record.</p>
-<p>For more information about this class, see <a href='#formatting.XFAlignment-class'><i>The XFAlignment Class</i></a>.</p>
-</dd>
-<dt><b>XFBackground</b> (class) [<a href='#formatting.XFBackground-class'>#</a>]</dt>
-<dd>
-<p>A collection of the background-related attributes of an XF record.</p>
-<p>For more information about this class, see <a href='#formatting.XFBackground-class'><i>The XFBackground Class</i></a>.</p>
-</dd>
-<dt><b>XFBorder</b> (class) [<a href='#formatting.XFBorder-class'>#</a>]</dt>
-<dd>
-<p>A collection of the border-related attributes of an XF record.</p>
-<p>For more information about this class, see <a href='#formatting.XFBorder-class'><i>The XFBorder Class</i></a>.</p>
-</dd>
-<dt><b>XFProtection</b> (class) [<a href='#formatting.XFProtection-class'>#</a>]</dt>
-<dd>
-<p>A collection of the protection-related attributes of an XF record.</p>
-<p>For more information about this class, see <a href='#formatting.XFProtection-class'><i>The XFProtection Class</i></a>.</p>
-</dd>
-<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>
-<dd>
-<p>Convert an Excel number (presumed to represent a date, a datetime or a time) into
-a tuple suitable for feeding to datetime or mx.DateTime constructors.</p>
-<dl>
-<dt><i>xldate</i></dt>
-<dd>
-The Excel number</dd>
-<dt><i>datemode</i></dt>
-<dd>
-0: 1900-based, 1: 1904-based.
-<br />WARNING: when using this function to
-interpret the contents of a workbook, you should pass in the Book.datemode
-attribute of that workbook. Whether
-the workbook has ever been anywhere near a Macintosh is irrelevant.
-</dd>
-<dt>Returns:</dt>
-<dd>
-Gregorian (year, month, day, hour, minute, nearest_second).
-<br />Special case: if 0.0 &lt;= xldate &lt; 1.0, it is assumed to represent a time;
-(0, 0, 0, hour, minute, second) will be returned.
-<br />Note: 1904-01-01 is not regarded as a valid date in the datemode 1 system; its "serial number"
-is zero.
-</dd>
-<dt>Raises <b>XLDateNegative</b>:</dt><dd>
-xldate &lt; 0.00
-</dd>
-<dt>Raises <b>XLDateAmbiguous</b>:</dt><dd>
-The 1900 leap-year problem (datemode == 0 and 1.0 &lt;= xldate &lt; 61.0)
-</dd>
-<dt>Raises <b>XLDateTooLarge</b>:</dt><dd>
-Gregorian year 10000 or later</dd>
-<dt>Raises <b>XLDateBadDatemode</b>:</dt><dd>
-datemode arg is neither 0 nor 1</dd>
-<dt>Raises <b>XLDateError</b>:</dt><dd>
-Covers the 4 specific errors</dd>
-</dl><br />
-</dd>
-<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>
-<dd>
-<p>Convert a date tuple (year, month, day) to an Excel date.</p>
-<dl>
-<dt><i>year</i></dt>
-<dd>
-Gregorian year.</dd>
-<dt><i>month</i></dt>
-<dd>
-1 &lt;= month &lt;= 12
-</dd>
-<dt><i>day</i></dt>
-<dd>
-1 &lt;= day &lt;= last day of that (year, month)
-</dd>
-<dt><i>datemode</i></dt>
-<dd>
-0: 1900-based, 1: 1904-based.</dd>
-<dt>Raises <b>XLDateAmbiguous</b>:</dt><dd>
-The 1900 leap-year problem (datemode == 0 and 1.0 &lt;= xldate &lt; 61.0)
-</dd>
-<dt>Raises <b>XLDateBadDatemode</b>:</dt><dd>
-datemode arg is neither 0 nor 1</dd>
-<dt>Raises <b>XLDateBadTuple</b>:</dt><dd>
-(year, month, day) is too early/late or has invalid component(s)</dd>
-<dt>Raises <b>XLDateError</b>:</dt><dd>
-Covers the specific errors</dd>
-</dl><br />
-</dd>
-<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>
-<dd>
-<p>Convert a datetime tuple (year, month, day, hour, minute, second) to an Excel date value.
-For more details, refer to other xldate_from_*_tuple functions.</p>
-<dl>
-<dt><i>datetime_tuple</i></dt>
-<dd>
-(year, month, day, hour, minute, second)</dd>
-<dt><i>datemode</i></dt>
-<dd>
-0: 1900-based, 1: 1904-based.</dd>
-</dl><br />
-</dd>
-<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>
-<dd>
-<p>Convert a time tuple (hour, minute, second) to an Excel &quot;date&quot; value (fraction of a day).</p>
-<dl>
-<dt><i>hour</i></dt>
-<dd>
-0 &lt;= hour &lt; 24
-</dd>
-<dt><i>minute</i></dt>
-<dd>
-0 &lt;= minute &lt; 60
-</dd>
-<dt><i>second</i></dt>
-<dd>
-0 &lt;= second &lt; 60
-</dd>
-<dt>Raises <b>XLDateBadTuple</b>:</dt><dd>
-Out-of-range hour, minute, or second</dd>
-</dl><br />
-</dd>
-</dl>
-<h2><a id='biffh.BaseObject-class' name='biffh.BaseObject-class'>The BaseObject Class</a></h2>
-<dl>
-<dt><b>BaseObject</b> (class) [<a href='#biffh.BaseObject-class'>#</a>]</dt>
-<dd>
-<p>Parent of almost all other classes in the package. Defines a common &quot;dump&quot; method
-for debugging.</p>
-</dd>
-<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>
-<dd>
-<dl>
-<dt><i>f</i></dt>
-<dd>
-open file object, to which the dump is written</dd>
-<dt><i>header</i></dt>
-<dd>
-text to write before the dump</dd>
-<dt><i>footer</i></dt>
-<dd>
-text to write after the dump</dd>
-<dt><i>indent</i></dt>
-<dd>
-number of leading spaces (for recursive calls)</dd>
-</dl><br />
-</dd>
-</dl>
-<h2><a id='__init__.Book-class' name='__init__.Book-class'>The Book Class</a></h2>
-<dl>
-<dt><b>Book()</b> (class) [<a href='#__init__.Book-class'>#</a>]</dt>
-<dd>
-<p>Contents of a "workbook".
-</p><p>WARNING: You don't call this class yourself. You use the Book object that
-was returned when you called xlrd.open_workbook("myfile.xls").</p>
-</dd>
-<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>
-<dd>
-<p>Version of BIFF (Binary Interchange File Format) used to create the file.
-Latest is 8.0 (represented here as 80), introduced with Excel 97.
-Earliest supported by this module: 2.0 (represented as 20).</p>
-</dd>
-<dt><a id='__init__.Book.codepage-attribute' name='__init__.Book.codepage-attribute'><b>codepage</b></a> [<a href='#__init__.Book.codepage-attribute'>#</a>]</dt>
-<dd>
-<p>An integer denoting the character set used for strings in this file.
-For BIFF 8 and later, this will be 1200, meaning Unicode; more precisely, UTF_16_LE.
-For earlier versions, this is used to derive the appropriate Python encoding
-to be used to convert to Unicode.
-Examples: 1252 -&gt; 'cp1252', 10000 -&gt; 'mac_roman'</p>
-</dd>
-<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>
-<dd>
-<p>This provides definitions for colour indexes. Please refer to the
-above section "The Palette; Colour Indexes" for an explanation
-of how colours are represented in Excel.<br />
-Colour indexes into the palette map into (red, green, blue) tuples.
-"Magic" indexes e.g. 0x7FFF map to None.
-<i>colour_map</i> is what you need if you want to render cells on screen or in a PDF
-file. If you are writing an output XLS file, use <i>palette_record</i>.
-<br /> -- New in version 0.6.1. Extracted only if open_workbook(..., formatting_info=True)
-</p></dd>
-<dt><a id='__init__.Book.countries-attribute' name='__init__.Book.countries-attribute'><b>countries</b></a> [<a href='#__init__.Book.countries-attribute'>#</a>]</dt>
-<dd>
-<p>A tuple containing the (telephone system) country code for:<br />
- [0]: the user-interface setting when the file was created.<br />
- [1]: the regional settings.<br />
-Example: (1, 61) meaning (USA, Australia).
-This information may give a clue to the correct encoding for an unknown codepage.
-For a long list of observed values, refer to the OpenOffice.org documentation for
-the COUNTRY record.
-</p></dd>
-<dt><a id='__init__.Book.datemode-attribute' name='__init__.Book.datemode-attribute'><b>datemode</b></a> [<a href='#__init__.Book.datemode-attribute'>#</a>]</dt>
-<dd>
-<p>Which date system was in force when this file was last saved.<br />
- 0 =&gt; 1900 system (the Excel for Windows default).<br />
- 1 =&gt; 1904 system (the Excel for Macintosh default).<br />
-</p></dd>
-<dt><a id='__init__.Book.encoding-attribute' name='__init__.Book.encoding-attribute'><b>encoding</b></a> [<a href='#__init__.Book.encoding-attribute'>#</a>]</dt>
-<dd>
-<p>The encoding that was derived from the codepage.</p>
-</dd>
-<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>
-<dd>
-<p>A list of Font class instances, each corresponding to a FONT record.
-<br /> -- New in version 0.6.1
-</p></dd>
-<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>
-<dd>
-<p>A list of Format objects, each corresponding to a FORMAT record, in
-the order that they appear in the input file.
-It does <i>not</i> contain builtin formats.
-If you are creating an output file using (for example) pyExcelerator,
-use this list.
-The collection to be used for all visual rendering purposes is format_map.
-<br /> -- New in version 0.6.1
-</p></dd>
-<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>
-<dd>
-<p>The mapping from XF.format_key to Format object.
-<br /> -- New in version 0.6.1
-</p></dd>
-<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>
-<dd>
-<p>Time in seconds to extract the XLS image as a contiguous string (or mmap equivalent).</p>
-</dd>
-<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>
-<dd>
-<p>Time in seconds to parse the data from the contiguous string (or mmap equivalent).</p>
-</dd>
-<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>
-<dd>
-<p>A mapping from (lower_case_name, scope) to a single Name object.
-<br /> -- New in version 0.6.0
-</p></dd>
-<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>
-<dd>
-<p>A mapping from lower_case_name to a list of Name objects. The list is
-sorted in scope order. Typically there will be one item (of global scope)
-in the list.
-<br /> -- New in version 0.6.0
-</p></dd>
-<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>
-<dd>
-<p>List containing a Name object for each NAME record in the workbook.
-<br /> -- New in version 0.6.0
-</p></dd>
-<dt><a id='__init__.Book.nsheets-attribute' name='__init__.Book.nsheets-attribute'><b>nsheets</b></a> [<a href='#__init__.Book.nsheets-attribute'>#</a>]</dt>
-<dd>
-<p>The number of worksheets present in the workbook file.
-This information is available even when no sheets have yet been loaded.</p>
-</dd>
-<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>
-<dd>
-<p>If the user has changed any of the colours in the standard palette, the XLS
-file will contain a PALETTE record with 56 (16 for Excel 4.0 and earlier)
-RGB values in it, and this list will be e.g. [(r0, b0, g0), ..., (r55, b55, g55)].
-Otherwise this list will be empty. This is what you need if you are
-writing an output XLS file. If you want to render cells on screen or in a PDF
-file, use colour_map.
-<br /> -- New in version 0.6.1. Extracted only if open_workbook(..., formatting_info=True)
-</p></dd>
-<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>
-<dd>
-<dl>
-<dt><i>sheetx</i></dt>
-<dd>
-Sheet index in range(nsheets)</dd>
-<dt>Returns:</dt>
-<dd>
-An object of the Sheet class</dd>
-</dl><br />
-</dd>
-<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>
-<dd>
-<dl>
-<dt><i>sheet_name</i></dt>
-<dd>
-Name of sheet required</dd>
-<dt>Returns:</dt>
-<dd>
-An object of the Sheet class</dd>
-</dl><br />
-</dd>
-<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>
-<dd>
-<dl>
-<dt><i>sheet_name_or_index</i></dt>
-<dd>
-Name or index of sheet enquired upon</dd>
-<dt>Returns:</dt>
-<dd>
-true if sheet is loaded, false otherwise
-<br /> -- New in version 0.7.1
-</dd>
-</dl><br />
-</dd>
-<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>
-<dd>
-<dl>
-<dt>Returns:</dt>
-<dd>
-A list of the names of all the worksheets in the workbook file.
-This information is available even when no sheets have yet been loaded.</dd>
-</dl><br />
-</dd>
-<dt><a id='__init__.Book.sheets-method' name='__init__.Book.sheets-method'><b>sheets()</b></a> [<a href='#__init__.Book.sheets-method'>#</a>]</dt>
-<dd>
-<dl>
-<dt>Returns:</dt>
-<dd>
-A list of all sheets in the book.
-All sheets not already loaded will be loaded.</dd>
-</dl><br />
-</dd>
-<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>
-<dd>
-<p>This provides access via name to the extended format information for
-both built-in styles and user-defined styles.<br />
-It maps <i>name</i> to (<i>built_in</i>, <i>xf_index</i>), where:<br />
-<i>name</i> is either the name of a user-defined style,
-or the name of one of the built-in styles. Known built-in names are
-Normal, RowLevel_1 to RowLevel_7,
-ColLevel_1 to ColLevel_7, Comma, Currency, Percent, "Comma [0]",
-"Currency [0]", Hyperlink, and "Followed Hyperlink".<br />
-<i>built_in</i> 1 = built-in style, 0 = user-defined<br />
-<i>xf_index</i> is an index into Book.xf_list.<br />
-References: OOo docs s6.99 (STYLE record); Excel UI Format/Style
-<br /> -- New in version 0.6.1
-</p></dd>
-<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>
-<dd>
-<dl>
-<dt><i>sheet_name_or_index</i></dt>
-<dd>
-Name or index of sheet to be unloaded.
-<br /> -- New in version 0.7.1
-</dd>
-</dl><br />
-</dd>
-<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>
-<dd>
-<p>What (if anything) is recorded as the name of the last user to save the file.</p>
-</dd>
-<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>
-<dd>
-<p>A list of XF class instances, each corresponding to an XF record.
-<br /> -- New in version 0.6.1
-</p></dd>
-</dl>
-<h2><a id='sheet.Cell-class' name='sheet.Cell-class'>The Cell Class</a></h2>
-<dl>
-<dt><b>Cell(ctype, value, xf_index=None)</b> (class) [<a href='#sheet.Cell-class'>#</a>]</dt>
-<dd>
-<p /><p>Contains the data for one cell.</p>
-
-<p>WARNING: You don't call this class yourself. You access Cell objects
-via methods of the Sheet object(s) that you found in the Book object that
-was returned when you called xlrd.open_workbook("myfile.xls").</p>
-<p> Cell objects have three attributes: <i>ctype</i> is an int, <i>value</i>
-(which depends on <i>ctype</i>) and <i>xf_index</i>.
-If "formatting_info" is not enabled when the workbook is opened, xf_index will be None.
-The following table describes the types of cells and how their values
-are represented in Python.</p>
-
-<table border="1" cellpadding="7">
-<tr>
-<th>Type symbol</th>
-<th>Type number</th>
-<th>Python value</th>
-</tr>
-<tr>
-<td>XL_CELL_EMPTY</td>
-<td align="center">0</td>
-<td>empty string u''</td>
-</tr>
-<tr>
-<td>XL_CELL_TEXT</td>
-<td align="center">1</td>
-<td>a Unicode string</td>
-</tr>
-<tr>
-<td>XL_CELL_NUMBER</td>
-<td align="center">2</td>
-<td>float</td>
-</tr>
-<tr>
-<td>XL_CELL_DATE</td>
-<td align="center">3</td>
-<td>float</td>
-</tr>
-<tr>
-<td>XL_CELL_BOOLEAN</td>
-<td align="center">4</td>
-<td>int; 1 means TRUE, 0 means FALSE</td>
-</tr>
-<tr>
-<td>XL_CELL_ERROR</td>
-<td align="center">5</td>
-<td>int representing internal Excel codes; for a text representation,
-refer to the supplied dictionary error_text_from_code</td>
-</tr>
-<tr>
-<td>XL_CELL_BLANK</td>
-<td align="center">6</td>
-<td>empty string u''. Note: this type will appear only when
-open_workbook(..., formatting_info=True) is used.</td>
-</tr>
-</table>
-<p />
-</dd>
-</dl>
-<h2><a id='sheet.Colinfo-class' name='sheet.Colinfo-class'>The Colinfo Class</a></h2>
-<dl>
-<dt><b>Colinfo</b> (class) [<a href='#sheet.Colinfo-class'>#</a>]</dt>
-<dd>
-<p>Width and default formatting information that applies to one or
-more columns in a sheet. Derived from COLINFO records.
-
-</p><p> Here is the default hierarchy for width, according to the OOo docs:
-
-<br />"""In BIFF3, if a COLINFO record is missing for a column,
-the width specified in the record DEFCOLWIDTH is used instead.
-
-<br />In BIFF4-BIFF7, the width set in this [COLINFO] record is only used,
-if the corresponding bit for this column is cleared in the GCW
-record, otherwise the column width set in the DEFCOLWIDTH record
-is used (the STANDARDWIDTH record is always ignored in this case [see footnote!]).
-
-<br />In BIFF8, if a COLINFO record is missing for a column,
-the width specified in the record STANDARDWIDTH is used.
-If this [STANDARDWIDTH] record is also missing,
-the column width of the record DEFCOLWIDTH is used instead."""
-<br />
-
-Footnote: The docs on the GCW record say this:
-"""<br />
-If a bit is set, the corresponding column uses the width set in the STANDARDWIDTH
-record. If a bit is cleared, the corresponding column uses the width set in the
-COLINFO record for this column.
-<br />If a bit is set, and the worksheet does not contain the STANDARDWIDTH record, or if
-the bit is cleared, and the worksheet does not contain the COLINFO record, the DEFCOLWIDTH
-record of the worksheet will be used instead.
-<br />"""<br />
-At the moment (2007-01-17) xlrd is going with the GCW version of the story.
-Reference to the source may be useful: see the computed_column_width(colx) method
-of the Sheet class.
-<br />-- New in version 0.6.1
-</p>
-</dd>
-<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>
-<dd>
-<p>Value of a 1-bit flag whose purpose is unknown
-but is often seen set to 1</p>
-</dd>
-<dt><a id='sheet.Colinfo.collapsed-attribute' name='sheet.Colinfo.collapsed-attribute'><b>collapsed</b></a> [<a href='#sheet.Colinfo.collapsed-attribute'>#</a>]</dt>
-<dd>
-<p>1 = column is collapsed</p>
-</dd>
-<dt><a id='sheet.Colinfo.hidden-attribute' name='sheet.Colinfo.hidden-attribute'><b>hidden</b></a> [<a href='#sheet.Colinfo.hidden-attribute'>#</a>]</dt>
-<dd>
-<p>1 = column is hidden</p>
-</dd>
-<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>
-<dd>
-<p>Outline level of the column, in range(7).
-(0 = no outline)</p>
-</dd>
-<dt><a id='sheet.Colinfo.width-attribute' name='sheet.Colinfo.width-attribute'><b>width</b></a> [<a href='#sheet.Colinfo.width-attribute'>#</a>]</dt>
-<dd>
-<p>Width of the column in 1/256 of the width of the zero character,
-using default font (first FONT record in the file).</p>
-</dd>
-<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>
-<dd>
-<p>XF index to be used for formatting empty cells.</p>
-</dd>
-</dl>
-<h2><a id='formatting.EqNeAttrs-class' name='formatting.EqNeAttrs-class'>The EqNeAttrs Class</a></h2>
-<dl>
-<dt><b>EqNeAttrs</b> (class) [<a href='#formatting.EqNeAttrs-class'>#</a>]</dt>
-<dd>
-<p>This mixin class exists solely so that Format, Font, and XF.... objects
-can be compared by value of their attributes.</p>
-</dd>
-</dl>
-<h2><a id='formatting.Font-class' name='formatting.Font-class'>The Font Class</a></h2>
-<dl>
-<dt><b>Font</b> (class) [<a href='#formatting.Font-class'>#</a>]</dt>
-<dd>
-<p>An Excel "font" contains the details of not only what is normally
-considered a font, but also several other display attributes.
-Items correspond to those in the Excel UI's Format/Cells/Font tab.
-<br /> -- New in version 0.6.1
-</p></dd>
-<dt><a id='formatting.Font.bold-attribute' name='formatting.Font.bold-attribute'><b>bold</b></a> [<a href='#formatting.Font.bold-attribute'>#</a>]</dt>
-<dd>
-<p>1 = Characters are bold. Redundant; see &quot;weight&quot; attribute.</p>
-</dd>
-<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>
-<dd>
-<p>Values: 0 = ANSI Latin, 1 = System default, 2 = Symbol,
-77 = Apple Roman,
-128 = ANSI Japanese Shift-JIS,
-129 = ANSI Korean (Hangul),
-130 = ANSI Korean (Johab),
-134 = ANSI Chinese Simplified GBK,
-136 = ANSI Chinese Traditional BIG5,
-161 = ANSI Greek,
-162 = ANSI Turkish,
-163 = ANSI Vietnamese,
-177 = ANSI Hebrew,
-178 = ANSI Arabic,
-186 = ANSI Baltic,
-204 = ANSI Cyrillic,
-222 = ANSI Thai,
-238 = ANSI Latin II (Central European),
-255 = OEM Latin I</p>
-</dd>
-<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>
-<dd>
-<p>An explanation of &quot;colour index&quot; is given in the Formatting
-section at the start of this document.</p>
-</dd>
-<dt><a id='formatting.Font.escapement-attribute' name='formatting.Font.escapement-attribute'><b>escapement</b></a> [<a href='#formatting.Font.escapement-attribute'>#</a>]</dt>
-<dd>
-<p>1 = Superscript, 2 = Subscript.</p>
-</dd>
-<dt><a id='formatting.Font.family-attribute' name='formatting.Font.family-attribute'><b>family</b></a> [<a href='#formatting.Font.family-attribute'>#</a>]</dt>
-<dd>
-<p>0 = None (unknown or don't care)<br />
-1 = Roman (variable width, serifed)<br />
-2 = Swiss (variable width, sans-serifed)<br />
-3 = Modern (fixed width, serifed or sans-serifed)<br />
-4 = Script (cursive)<br />
-5 = Decorative (specialised, for example Old English, Fraktur)
-</p></dd>
-<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>
-<dd>
-<p>The 0-based index used to refer to this Font() instance.
-Note that index 4 is never used; xlrd supplies a dummy place-holder.</p>
-</dd>
-<dt><a id='formatting.Font.height-attribute' name='formatting.Font.height-attribute'><b>height</b></a> [<a href='#formatting.Font.height-attribute'>#</a>]</dt>
-<dd>
-<p>Height of the font (in twips). A twip = 1/20 of a point.</p>
-</dd>
-<dt><a id='formatting.Font.italic-attribute' name='formatting.Font.italic-attribute'><b>italic</b></a> [<a href='#formatting.Font.italic-attribute'>#</a>]</dt>
-<dd>
-<p>1 = Characters are italic.</p>
-</dd>
-<dt><a id='formatting.Font.name-attribute' name='formatting.Font.name-attribute'><b>name</b></a> [<a href='#formatting.Font.name-attribute'>#</a>]</dt>
-<dd>
-<p>The name of the font. Example: u&quot;Arial&quot;</p>
-</dd>
-<dt><a id='formatting.Font.outline-attribute' name='formatting.Font.outline-attribute'><b>outline</b></a> [<a href='#formatting.Font.outline-attribute'>#</a>]</dt>
-<dd>
-<p>1 = Font is outline style (Macintosh only)</p>
-</dd>
-<dt><a id='formatting.Font.shadow-attribute' name='formatting.Font.shadow-attribute'><b>shadow</b></a> [<a href='#formatting.Font.shadow-attribute'>#</a>]</dt>
-<dd>
-<p>1 = Font is shadow style (Macintosh only)</p>
-</dd>
-<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>
-<dd>
-<p>1 = Characters are struck out.</p>
-</dd>
-<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>
-<dd>
-<p>0 = None<br />
-1 = Single; 0x21 (33) = Single accounting<br />
-2 = Double; 0x22 (34) = Double accounting
-</p></dd>
-<dt><a id='formatting.Font.underlined-attribute' name='formatting.Font.underlined-attribute'><b>underlined</b></a> [<a href='#formatting.Font.underlined-attribute'>#</a>]</dt>
-<dd>
-<p>1 = Characters are underlined. Redundant; see &quot;underline_type&quot; attribute.</p>
-</dd>
-<dt><a id='formatting.Font.weight-attribute' name='formatting.Font.weight-attribute'><b>weight</b></a> [<a href='#formatting.Font.weight-attribute'>#</a>]</dt>
-<dd>
-<p>Font weight (100-1000). Standard values are 400 for normal text
-and 700 for bold text.</p>
-</dd>
-</dl>
-<h2><a id='formatting.Format-class' name='formatting.Format-class'>The Format Class</a></h2>
-<dl>
-<dt><b>Format(format_key, ty, format_str)</b> (class) [<a href='#formatting.Format-class'>#</a>]</dt>
-<dd>
-<p>"Number format" information from a FORMAT record.
-<br /> -- New in version 0.6.1
-</p></dd>
-<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>
-<dd>
-<p>The key into Book.format_map</p>
-</dd>
-<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>
-<dd>
-<p>The format string</p>
-</dd>
-<dt><a id='formatting.Format.type-attribute' name='formatting.Format.type-attribute'><b>type</b></a> [<a href='#formatting.Format.type-attribute'>#</a>]</dt>
-<dd>
-<p>A classification that has been inferred from the format string.
-Currently, this is used only to distinguish between numbers and dates.
-<br />Values:
-<br />FUN = 0 # unknown
-<br />FDT = 1 # date
-<br />FNU = 2 # number
-<br />FGE = 3 # general
-<br />FTX = 4 # text
-</p></dd>
-</dl>
-<h2><a id='__init__.Name-class' name='__init__.Name-class'>The Name Class</a></h2>
-<dl>
-<dt><b>Name</b> (class) [<a href='#__init__.Name-class'>#</a>]</dt>
-<dd>
-<p>Information relating to a named reference, formula, macro, etc.
-<br /> -- New in version 0.6.0
-<br /> -- <i>Name information is <b>not</b> extracted from files older than
-Excel 5.0 (Book.biff_version &lt; 50)</i>
-</p></dd>
-<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>
-<dd>
-<p>This is a convenience method for the use case where the name
-refers to one rectangular area in one worksheet.</p>
-<dl>
-<dt><i>clipped</i></dt>
-<dd>
-If true (the default), the returned rectangle is clipped
-to fit in (0, sheet.nrows, 0, sheet.ncols) -- it is guaranteed that
-0 &lt;= rowxlo &lt;= rowxhi &lt;= sheet.nrows and that the number of usable rows
-in the area (which may be zero) is rowxhi - rowxlo; likewise for columns.
-</dd>
-<dt>Returns:</dt>
-<dd>
-a tuple (sheet_object, rowxlo, rowxhi, colxlo, colxhi).</dd>
-<dt>Raises <b>XLRDError</b>:</dt><dd>
-The name is not a constant absolute reference
-to a single area in a single sheet.</dd>
-</dl><br />
-</dd>
-<dt><a id='__init__.Name.binary-attribute' name='__init__.Name.binary-attribute'><b>binary</b></a> [<a href='#__init__.Name.binary-attribute'>#</a>]</dt>
-<dd>
-<p>0 = Formula definition; 1 = Binary data<br /> <i>No examples have been sighted.</i>
-</p></dd>
-<dt><a id='__init__.Name.builtin-attribute' name='__init__.Name.builtin-attribute'><b>builtin</b></a> [<a href='#__init__.Name.builtin-attribute'>#</a>]</dt>
-<dd>
-<p>0 = User-defined name; 1 = Built-in name
-(common examples: Print_Area, Print_Titles; see OOo docs for full list)</p>
-</dd>
-<dt><a id='__init__.Name.cell-method' name='__init__.Name.cell-method'><b>cell()</b></a> [<a href='#__init__.Name.cell-method'>#</a>]</dt>
-<dd>
-<p>This is a convenience method for the frequent use case where the name
-refers to a single cell.</p>
-<dl>
-<dt>Returns:</dt>
-<dd>
-An instance of the Cell class.</dd>
-<dt>Raises <b>XLRDError</b>:</dt><dd>
-The name is not a constant absolute reference
-to a single cell.</dd>
-</dl><br />
-</dd>
-<dt><a id='__init__.Name.complex-attribute' name='__init__.Name.complex-attribute'><b>complex</b></a> [<a href='#__init__.Name.complex-attribute'>#</a>]</dt>
-<dd>
-<p>0 = Simple formula; 1 = Complex formula (array formula or user defined)<br />
-<i>No examples have been sighted.</i>
-</p></dd>
-<dt><a id='__init__.Name.func-attribute' name='__init__.Name.func-attribute'><b>func</b></a> [<a href='#__init__.Name.func-attribute'>#</a>]</dt>
-<dd>
-<p>0 = Command macro; 1 = Function macro. Relevant only if macro == 1</p>
-</dd>
-<dt><a id='__init__.Name.funcgroup-attribute' name='__init__.Name.funcgroup-attribute'><b>funcgroup</b></a> [<a href='#__init__.Name.funcgroup-attribute'>#</a>]</dt>
-<dd>
-<p>Function group. Relevant only if macro == 1; see OOo docs for values.</p>
-</dd>
-<dt><a id='__init__.Name.hidden-attribute' name='__init__.Name.hidden-attribute'><b>hidden</b></a> [<a href='#__init__.Name.hidden-attribute'>#</a>]</dt>
-<dd>
-<p>0 = Visible; 1 = Hidden</p>
-</dd>
-<dt><a id='__init__.Name.macro-attribute' name='__init__.Name.macro-attribute'><b>macro</b></a> [<a href='#__init__.Name.macro-attribute'>#</a>]</dt>
-<dd>
-<p>0 = Standard name; 1 = Macro name</p>
-</dd>
-<dt><a id='__init__.Name.name-attribute' name='__init__.Name.name-attribute'><b>name</b></a> [<a href='#__init__.Name.name-attribute'>#</a>]</dt>
-<dd>
-<p>A Unicode string. If builtin, decoded as per OOo docs.</p>
-</dd>
-<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>
-<dd>
-<p>The index of this object in book.name_obj_list</p>
-</dd>
-<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>
-<dd>
-<p>An 8-bit string.</p>
-</dd>
-<dt><a id='__init__.Name.result-attribute' name='__init__.Name.result-attribute'><b>result</b></a> [<a href='#__init__.Name.result-attribute'>#</a>]</dt>
-<dd>
-<p>The result of evaluating the formula, if any.
-If no formula, or evaluation of the formula encountered problems,
-the result is None. Otherwise the result is a single instance of the
-Operand class.</p>
-</dd>
-<dt><a id='__init__.Name.scope-attribute' name='__init__.Name.scope-attribute'><b>scope</b></a> [<a href='#__init__.Name.scope-attribute'>#</a>]</dt>
-<dd>
-<p>-1: The name is global (visible in all calculation sheets).<br />
--2: The name belongs to a macro sheet or VBA sheet.<br />
--3: The name is invalid.<br />
-0 &lt;= scope &lt; book.nsheets: The name is local to the sheet whose index is scope.
-</p></dd>
-<dt><a id='__init__.Name.vbasic-attribute' name='__init__.Name.vbasic-attribute'><b>vbasic</b></a> [<a href='#__init__.Name.vbasic-attribute'>#</a>]</dt>
-<dd>
-<p>0 = Sheet macro; 1 = VisualBasic macro. Relevant only if macro == 1</p>
-</dd>
-</dl>
-<h2><a id='formula.Operand-class' name='formula.Operand-class'>The Operand Class</a></h2>
-<dl>
-<dt><b>Operand(akind=None, avalue=None, arank=0, atext='?')</b> (class) [<a href='#formula.Operand-class'>#</a>]</dt>
-<dd>
-<p>Used in evaluating formulas.
-The following table describes the kinds and how their values
-are represented.</p>
-
-<table border="1" cellpadding="7">
-<tr>
-<th>Kind symbol</th>
-<th>Kind number</th>
-<th>Value representation</th>
-</tr>
-<tr>
-<td>oBOOL</td>
-<td align="center">3</td>
-<td>integer: 0 =&gt; False; 1 =&gt; True</td>
-</tr>
-<tr>
-<td>oERR</td>
-<td align="center">4</td>
-<td>None, or an int error code (same as XL_CELL_ERROR in the Cell class).
-</td>
-</tr>
-<tr>
-<td>oMSNG</td>
-<td align="center">5</td>
-<td>Used by Excel as a placeholder for a missing (not supplied) function
-argument. Should *not* appear as a final formula result. Value is None.</td>
-</tr>
-<tr>
-<td>oNUM</td>
-<td align="center">2</td>
-<td>A float. Note that there is no way of distinguishing dates.</td>
-</tr>
-<tr>
-<td>oREF</td>
-<td align="center">-1</td>
-<td>The value is either None or a non-empty list of
-absolute Ref3D instances.<br />
-</td>
-</tr>
-<tr>
-<td>oREL</td>
-<td align="center">-2</td>
-<td>The value is None or a non-empty list of
-fully or partially relative Ref3D instances.
-</td>
-</tr>
-<tr>
-<td>oSTRG</td>
-<td align="center">1</td>
-<td>A Unicode string.</td>
-</tr>
-<tr>
-<td>oUNK</td>
-<td align="center">0</td>
-<td>The kind is unknown or ambiguous. The value is None</td>
-</tr>
-</table>
-<p />
-</dd>
-<dt><a id='formula.Operand.kind-attribute' name='formula.Operand.kind-attribute'><b>kind</b></a> [<a href='#formula.Operand.kind-attribute'>#</a>]</dt>
-<dd>
-<p>oUNK means that the kind of operand is not known unambiguously.</p>
-</dd>
-<dt><a id='formula.Operand.text-attribute' name='formula.Operand.text-attribute'><b>text</b></a> [<a href='#formula.Operand.text-attribute'>#</a>]</dt>
-<dd>
-<p>The reconstituted text of the original formula. Function names will be
-in English irrespective of the original language, which doesn't seem
-to be recorded anywhere. The separator is &quot;,&quot;, not &quot;;&quot; or whatever else
-might be more appropriate for the end-user's locale; patches welcome.</p>
-</dd>
-<dt><a id='formula.Operand.value-attribute' name='formula.Operand.value-attribute'><b>value</b></a> [<a href='#formula.Operand.value-attribute'>#</a>]</dt>
-<dd>
-<p>None means that the actual value of the operand is a variable
-(depends on cell data), not a constant.</p>
-</dd>
-</dl>
-<h2><a id='formula.Ref3D-class' name='formula.Ref3D-class'>The Ref3D Class</a></h2>
-<dl>
-<dt><b>Ref3D(atuple)</b> (class) [<a href='#formula.Ref3D-class'>#</a>]</dt>
-<dd>
-<p /><p>Represents an absolute or relative 3-dimensional reference to a box
-of one or more cells.<br />
--- New in version 0.6.0
-</p>
-
-<p>The <i>coords</i> attribute is a tuple of the form:<br />
-(shtxlo, shtxhi, rowxlo, rowxhi, colxlo, colxhi)<br />
-where 0 &lt;= thingxlo &lt;= thingx &lt; thingxhi.<br />
-Note that it is quite possible to have thingx &gt; nthings; for example
-Print_Titles could have colxhi == 256 and/or rowxhi == 65536
-irrespective of how many columns/rows are actually used in the worksheet.
-The caller will need to decide how to handle this situation.
-Keyword: IndexError :-)
-</p>
-
-<p>The components of the coords attribute are also available as individual
-attributes: shtxlo, shtxhi, rowxlo, rowxhi, colxlo, and colxhi.</p>
-
-<p>The <i>relflags</i> attribute is a 6-tuple of flags which indicate whether
-the corresponding (sheet|row|col)(lo|hi) is relative (1) or absolute (0).<br />
-Note that there is necessarily no information available as to what cell(s)
-the reference could possibly be relative to. The caller must decide what if
-any use to make of oREL operands. Note also that a partially relative
-reference may well be a typo.
-For example, define name A1Z10 as $a$1:$z10 (missing $ after z)
-while the cursor is on cell Sheet3!A27.<br />
-The resulting Ref3D instance will have coords = (2, 3, 0, -16, 0, 26)
-and relflags = (0, 0, 0, 1, 0, 0).<br />
-So far, only one possibility of a sheet-relative component in
-a reference has been noticed: a 2D reference located in the "current sheet".
-<br /> This will appear as coords = (0, 1, ...) and relflags = (1, 1, ...).
-</p></dd>
-</dl>
-<h2><a id='sheet.Rowinfo-class' name='sheet.Rowinfo-class'>The Rowinfo Class</a></h2>
-<dl>
-<dt><b>Rowinfo</b> (class) [<a href='#sheet.Rowinfo-class'>#</a>]</dt>
-<dd>
-<p>Height and default formatting information that applies to a row in a sheet.
-Derived from ROW records.
-<br /> -- New in version 0.6.1
-</p></dd>
-<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>
-<dd>
-<p>This flag is set, if the upper border of at least one cell in this row
-or if the lower border of at least one cell in the row above is
-formatted with a thick line style. Thin and medium line styles are not
-taken into account.</p>
-</dd>
-<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>
-<dd>
-<p>This flag is set, if the lower border of at least one cell in this row
-or if the upper border of at least one cell in the row below is
-formatted with a medium or thick line style. Thin line styles are not
-taken into account.</p>
-</dd>
-<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>
-<dd>
-<p>0 = Row has custom height; 1 = Row has default height</p>
-</dd>
-<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>
-<dd>
-<p>1 = the xf_index attribute is usable; 0 = ignore it</p>
-</dd>
-<dt><a id='sheet.Rowinfo.height-attribute' name='sheet.Rowinfo.height-attribute'><b>height</b></a> [<a href='#sheet.Rowinfo.height-attribute'>#</a>]</dt>
-<dd>
-<p>Height of the row, in twips. One twip == 1/20 of a point</p>
-</dd>
-<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>
-<dd>
-<p>1 = Row height and default font height do not match</p>
-</dd>
-<dt><a id='sheet.Rowinfo.hidden-attribute' name='sheet.Rowinfo.hidden-attribute'><b>hidden</b></a> [<a href='#sheet.Rowinfo.hidden-attribute'>#</a>]</dt>
-<dd>
-<p>1 = Row is hidden (manually, or by a filter or outline group)</p>
-</dd>
-<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>
-<dd>
-<p>1 = Outline group starts or ends here (depending on where the
-outline buttons are located, see WSBOOL record [TODO ??]),
-<i>and</i> is collapsed
-</p></dd>
-<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>
-<dd>
-<p>Outline level of the row</p>
-</dd>
-<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>
-<dd>
-<p>Index to default XF record for empty cells in this row.
-Don't use this if has_default_xf_index == 0.</p>
-</dd>
-</dl>
-<h2><a id='sheet.Sheet-class' name='sheet.Sheet-class'>The Sheet Class</a></h2>
-<dl>
-<dt><b>Sheet(book, position, name, number)</b> (class) [<a href='#sheet.Sheet-class'>#</a>]</dt>
-<dd>
-<p /><p>Contains the data for one worksheet.</p>
-
-<p>In the cell access functions, "rowx" is a row index, counting from zero, and "colx" is a
-column index, counting from zero.
-Negative values for row/column indexes and slice positions are supported in the expected fashion.</p>
-
-<p>For information about cell types and cell values, refer to the documentation of the Cell class.</p>
-
-<p>WARNING: You don't call this class yourself. You access Sheet objects via the Book object that
-was returned when you called xlrd.open_workbook("myfile.xls").</p>
-</dd>
-<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>
-<dd>
-<p>Cell object in the given row and column.</p>
-</dd>
-<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>
-<dd>
-<p>Type of the cell in the given row and column.
-Refer to the documentation of the Cell class.</p>
-</dd>
-<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>
-<dd>
-<p>Value of the cell in the given row and column.</p>
-</dd>
-<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>
-<dd>
-<p>XF index of the cell in the given row and column.
-This is an index into Book.xf_list.
-<br /> -- New in version 0.6.1
-</p></dd>
-<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>
-<dd>
-<p>Returns a sequence of the Cell objects in the given column.</p>
-</dd>
-<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>
-<dd>
-<p>List of address ranges of cells containing column labels.
-These are set up in Excel by Insert &gt; Name &gt; Labels &gt; Columns.
-<br /> -- New in version 0.6.0
-<br />How to deconstruct the list:
-<pre>
-for crange in thesheet.col_label_ranges:
- rlo, rhi, clo, chi = crange
- for rx in xrange(rlo, rhi):
- for cx in xrange(clo, chi):
- print "Column label at (rowx=%d, colx=%d) is %r" \
- (rx, cx, thesheet.cell_value(rx, cx))
-</pre>
-</p></dd>
-<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>
-<dd>
-<p>Returns a slice of the Cell objects in the given column.</p>
-</dd>
-<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>
-<dd>
-<p>Returns a slice of the types of the cells in the given column.</p>
-</dd>
-<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>
-<dd>
-<p>Returns a slice of the values of the cells in the given column.</p>
-</dd>
-<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>
-<dd>
-<p>The map from a column index to a Colinfo object. Often there is an entry
-in COLINFO records for all column indexes in range(257).
-Note that xlrd ignores the entry for the non-existent
-257th column. On the other hand, there may be no entry for unused columns.
-<br /> -- New in version 0.6.1
-</p></dd>
-<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>
-<dd>
-<p>Determine column display width.
-<br /> -- New in version 0.6.1
-<br />
-</p><dl>
-<dt><i>colx</i></dt>
-<dd>
-Index of the queried column, range 0 to 255.
-Note that it is possible to find out the width that will be used to display
-columns with no cell information e.g. column IV (colx=255).</dd>
-<dt>Returns:</dt>
-<dd>
-The column width that will be used for displaying
-the given column by Excel, in units of 1/256th of the width of a
-standard character (the digit zero in the first font).</dd>
-</dl><br />
-</dd>
-<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>
-<dd>
-<p>Default value to be used for a row if there is
-no ROW record for that row.
-From the <i>optional</i> DEFAULTROWHEIGHT record.
-</p></dd>
-<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>
-<dd>
-<p>Default value to be used for a row if there is
-no ROW record for that row.
-From the <i>optional</i> DEFAULTROWHEIGHT record.
-</p></dd>
-<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>
-<dd>
-<p>Default value to be used for a row if there is
-no ROW record for that row.
-From the <i>optional</i> DEFAULTROWHEIGHT record.
-</p></dd>
-<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>
-<dd>
-<p>Default value to be used for a row if there is
-no ROW record for that row.
-From the <i>optional</i> DEFAULTROWHEIGHT record.
-</p></dd>
-<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>
-<dd>
-<p>Default value to be used for a row if there is
-no ROW record for that row.
-From the <i>optional</i> DEFAULTROWHEIGHT record.
-</p></dd>
-<dt><a id='sheet.Sheet.defcolwidth-attribute' name='sheet.Sheet.defcolwidth-attribute'><b>defcolwidth</b></a> [<a href='#sheet.Sheet.defcolwidth-attribute'>#</a>]</dt>
-<dd>
-<p>Default column width from DEFCOLWIDTH record, else None.
-From the OOo docs:<br />
-"""Column width in characters, using the width of the zero character
-from default font (first FONT record in the file). Excel adds some
-extra space to the default width, depending on the default font and
-default font size. The algorithm how to exactly calculate the resulting
-column width is not known.<br />
-Example: The default width of 8 set in this record results in a column
-width of 8.43 using Arial font with a size of 10 points."""<br />
-For the default hierarchy, refer to the Colinfo class above.
-<br /> -- New in version 0.6.1
-</p></dd>
-<dt><a id='sheet.Sheet.gcw-attribute' name='sheet.Sheet.gcw-attribute'><b>gcw</b></a> [<a href='#sheet.Sheet.gcw-attribute'>#</a>]</dt>
-<dd>
-<p>A 256-element tuple corresponding to the contents of the GCW record for this sheet.
-If no such record, treat as all bits zero.
-Applies to BIFF4-7 only. See docs of Colinfo class for discussion.</p>
-</dd>
-<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>
-<dd>
-<p>List of address ranges of cells which have been merged.
-These are set up in Excel by Format &gt; Cells &gt; Alignment, then ticking
-the "Merge cells" box.
-<br /> -- New in version 0.6.1. Extracted only if open_workbook(..., formatting_info=True)
-<br />How to deconstruct the list:
-<pre>
-for crange in thesheet.merged_cells:
- rlo, rhi, clo, chi = crange
- for rowx in xrange(rlo, rhi):
- for colx in xrange(clo, chi):
- # cell (rlo, clo) (the top left one) will carry the data
- # and formatting info; the remainder will be recorded as
- # blank cells, but a renderer will apply the formatting info
- # for the top left cell (e.g. border, pattern) to all cells in
- # the range.
-</pre>
-</p></dd>
-<dt><a id='sheet.Sheet.name-attribute' name='sheet.Sheet.name-attribute'><b>name</b></a> [<a href='#sheet.Sheet.name-attribute'>#</a>]</dt>
-<dd>
-<p>Name of sheet.</p>
-</dd>
-<dt><a id='sheet.Sheet.ncols-attribute' name='sheet.Sheet.ncols-attribute'><b>ncols</b></a> [<a href='#sheet.Sheet.ncols-attribute'>#</a>]</dt>
-<dd>
-<p>Number of columns in sheet. A column index is in range(thesheet.ncols).</p>
-</dd>
-<dt><a id='sheet.Sheet.nrows-attribute' name='sheet.Sheet.nrows-attribute'><b>nrows</b></a> [<a href='#sheet.Sheet.nrows-attribute'>#</a>]</dt>
-<dd>
-<p>Number of rows in sheet. A row index is in range(thesheet.nrows).</p>
-</dd>
-<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>
-<dd>
-<p>Returns a sequence of the Cell objects in the given row.</p>
-</dd>
-<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>
-<dd>
-<p>List of address ranges of cells containing row labels.
-For more details, see <i>col_label_ranges</i> above.
-<br /> -- New in version 0.6.0
-</p></dd>
-<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>
-<dd>
-<p>Returns a slice of the Cell objects in the given row.</p>
-</dd>
-<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>
-<dd>
-<p>Returns a slice of the types
-of the cells in the given row.</p>
-</dd>
-<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>
-<dd>
-<p>Returns a slice of the values
-of the cells in the given row.</p>
-</dd>
-<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>
-<dd>
-<p>The map from a row index to a Rowinfo object. Note that it is possible
-to have missing entries -- at least one source of XLS files doesn't
-bother writing ROW records.
-<br /> -- New in version 0.6.1
-</p></dd>
-<dt><a id='sheet.Sheet.standardwidth-attribute' name='sheet.Sheet.standardwidth-attribute'><b>standardwidth</b></a> [<a href='#sheet.Sheet.standardwidth-attribute'>#</a>]</dt>
-<dd>
-<p>Default column width from STANDARDWIDTH record, else None.
-From the OOo docs:<br />
-"""Default width of the columns in 1/256 of the width of the zero
-character, using default font (first FONT record in the file)."""<br />
-For the default hierarchy, refer to the Colinfo class above.
-<br /> -- New in version 0.6.1
-</p></dd>
-<dt><a id='sheet.Sheet.visibility-attribute' name='sheet.Sheet.visibility-attribute'><b>visibility</b></a> [<a href='#sheet.Sheet.visibility-attribute'>#</a>]</dt>
-<dd>
-<p>Visibility of the sheet. 0 = visible, 1 = hidden (can be unhidden
-by user -- Format/Sheet/Unhide), 2 = &quot;very hidden&quot; (can be unhidden
-only by VBA macro).</p>
-</dd>
-</dl>
-<h2><a id='formatting.XF-class' name='formatting.XF-class'>The XF Class</a></h2>
-<dl>
-<dt><b>XF</b> (class) [<a href='#formatting.XF-class'>#</a>]</dt>
-<dd>
-<p>eXtended Formatting information for cells, rows, columns and styles.
-<br /> -- New in version 0.6.1
-
-</p><p>Each of the 6 flags below describes the validity of
-a specific group of attributes.
-<br />
-In cell XFs, flag==0 means the attributes of the parent style XF are used,
-(but only if the attributes are valid there); flag==1 means the attributes
-of this XF are used.<br />
-In style XFs, flag==0 means the attribute setting is valid; flag==1 means
-the attribute should be ignored.<br />
-Note that the API
-provides both "raw" XFs and "computed" XFs -- in the latter case, cell XFs
-have had the above inheritance mechanism applied.
-</p>
-</dd>
-<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>
-<dd>
-</dd>
-<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>
-<dd>
-</dd>
-<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>
-<dd>
-</dd>
-<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>
-<dd>
-</dd>
-<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>
-<dd>
-</dd>
-<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>
-<dd>
-<p>&#160;
-</p></dd>
-<dt><a id='formatting.XF.alignment-attribute' name='formatting.XF.alignment-attribute'><b>alignment</b></a> [<a href='#formatting.XF.alignment-attribute'>#</a>]</dt>
-<dd>
-<p>An instance of an XFAlignment object.</p>
-</dd>
-<dt><a id='formatting.XF.background-attribute' name='formatting.XF.background-attribute'><b>background</b></a> [<a href='#formatting.XF.background-attribute'>#</a>]</dt>
-<dd>
-<p>An instance of an XFBackground object.</p>
-</dd>
-<dt><a id='formatting.XF.border-attribute' name='formatting.XF.border-attribute'><b>border</b></a> [<a href='#formatting.XF.border-attribute'>#</a>]</dt>
-<dd>
-<p>An instance of an XFBorder object.</p>
-</dd>
-<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>
-<dd>
-<p>Index into Book.font_list</p>
-</dd>
-<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>
-<dd>
-<p>Key into Book.format_map
-</p><p>
-Warning: OOo docs on the XF record call this "Index to FORMAT record".
-It is not an index in the Python sense. It is a key to a map.
-It is true <i>only</i> for Excel 4.0 and earlier files
-that the key into format_map from an XF instance
-is the same as the index into format_list, and <i>only</i>
-if the index is less than 164.
-</p>
-</dd>
-<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>
-<dd>
-<p>0 = cell XF, 1 = style XF</p>
-</dd>
-<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>
-<dd>
-<p>cell XF: Index into Book.xf_list
-of this XF's style XF<br />
-style XF: 0xFFF
-</p></dd>
-<dt><a id='formatting.XF.protection-attribute' name='formatting.XF.protection-attribute'><b>protection</b></a> [<a href='#formatting.XF.protection-attribute'>#</a>]</dt>
-<dd>
-<p>An instance of an XFProtection object.</p>
-</dd>
-<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>
-<dd>
-<p>Index into Book.xf_list</p>
-</dd>
-</dl>
-<h2><a id='formatting.XFAlignment-class' name='formatting.XFAlignment-class'>The XFAlignment Class</a></h2>
-<dl>
-<dt><b>XFAlignment</b> (class) [<a href='#formatting.XFAlignment-class'>#</a>]</dt>
-<dd>
-<p>A collection of the alignment and similar attributes of an XF record.
-Items correspond to those in the Excel UI's Format/Cells/Alignment tab.
-<br /> -- New in version 0.6.1
-</p></dd>
-<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>
-<dd>
-<p>Values: section 6.115 (p 214) of OOo docs</p>
-</dd>
-<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>
-<dd>
-<p>A number in range(15).</p>
-</dd>
-<dt><a id='formatting.XFAlignment.rotation-attribute' name='formatting.XFAlignment.rotation-attribute'><b>rotation</b></a> [<a href='#formatting.XFAlignment.rotation-attribute'>#</a>]</dt>
-<dd>
-<p>Values: section 6.115 (p 215) of OOo docs.<br />
-Note: file versions BIFF7 and earlier use the documented
-"orientation" attribute; this will be mapped (without loss)
-into "rotation".
-</p></dd>
-<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>
-<dd>
-<p>1 = shrink font size to fit text into cell.</p>
-</dd>
-<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>
-<dd>
-<p>0 = according to context; 1 = left-to-right; 2 = right-to-left</p>
-</dd>
-<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>
-<dd>
-<p>1 = text is wrapped at right margin</p>
-</dd>
-<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>
-<dd>
-<p>Values: section 6.115 (p 215) of OOo docs</p>
-</dd>
-</dl>
-<h2><a id='formatting.XFBackground-class' name='formatting.XFBackground-class'>The XFBackground Class</a></h2>
-<dl>
-<dt><b>XFBackground</b> (class) [<a href='#formatting.XFBackground-class'>#</a>]</dt>
-<dd>
-<p>A collection of the background-related attributes of an XF record.
-Items correspond to those in the Excel UI's Format/Cells/Patterns tab.
-An explanation of "colour index" is given in the Formatting
-section at the start of this document.
-<br /> -- New in version 0.6.1
-</p></dd>
-<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>
-<dd>
-<p>See section 3.11 of the OOo docs.</p>
-</dd>
-<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>
-<dd>
-<p>See section 3.11 of the OOo docs.</p>
-</dd>
-<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>
-<dd>
-<p>See section 3.11 of the OOo docs.</p>
-</dd>
-</dl>
-<h2><a id='formatting.XFBorder-class' name='formatting.XFBorder-class'>The XFBorder Class</a></h2>
-<dl>
-<dt><b>XFBorder</b> (class) [<a href='#formatting.XFBorder-class'>#</a>]</dt>
-<dd>
-<p /><p>A collection of the border-related attributes of an XF record.
-Items correspond to those in the Excel UI's Format/Cells/Border tab.</p>
-<p> An explanations of &quot;colour index&quot; is given in the Formatting
-section at the start of this document.
-There are five line style attributes; possible values and the
-associated meanings are:
-0&#160;=&#160;No line,
-1&#160;=&#160;Thin,
-2&#160;=&#160;Medium,
-3&#160;=&#160;Dashed,
-4&#160;=&#160;Dotted,
-5&#160;=&#160;Thick,
-6&#160;=&#160;Double,
-7&#160;=&#160;Hair,
-8&#160;=&#160;Medium dashed,
-9&#160;=&#160;Thin dash-dotted,
-10&#160;=&#160;Medium dash-dotted,
-11&#160;=&#160;Thin dash-dot-dotted,
-12&#160;=&#160;Medium dash-dot-dotted,
-13&#160;=&#160;Slanted medium dash-dotted.
-The line styles 8 to 13 appear in BIFF8 files (Excel 97 and later) only.
-For pictures of the line styles, refer to OOo docs s3.10 (p22)
-&quot;Line Styles for Cell Borders (BIFF3-BIFF8)&quot;.</p>
-<br /> -- New in version 0.6.1
-</dd>
-<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>
-<dd>
-<p>The colour index for the cell's bottom line</p>
-</dd>
-<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>
-<dd>
-<p>The line style for the cell's bottom line</p>
-</dd>
-<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>
-<dd>
-<p>The colour index for the cell's diagonal lines, if any</p>
-</dd>
-<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>
-<dd>
-<p>1 = draw a diagonal from top left to bottom right</p>
-</dd>
-<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>
-<dd>
-<p>The line style for the cell's diagonal lines, if any</p>
-</dd>
-<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>
-<dd>
-<p>1 = draw a diagonal from bottom left to top right</p>
-</dd>
-<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>
-<dd>
-<p>The colour index for the cell's left line</p>
-</dd>
-<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>
-<dd>
-<p>The line style for the cell's left line</p>
-</dd>
-<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>
-<dd>
-<p>The colour index for the cell's right line</p>
-</dd>
-<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>
-<dd>
-<p>The line style for the cell's right line</p>
-</dd>
-<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>
-<dd>
-<p>The colour index for the cell's top line</p>
-</dd>
-<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>
-<dd>
-<p>The line style for the cell's top line</p>
-</dd>
-</dl>
-<h2><a id='formatting.XFProtection-class' name='formatting.XFProtection-class'>The XFProtection Class</a></h2>
-<dl>
-<dt><b>XFProtection</b> (class) [<a href='#formatting.XFProtection-class'>#</a>]</dt>
-<dd>
-<p>A collection of the protection-related attributes of an XF record.
-Items correspond to those in the Excel UI's Format/Cells/Protection tab.
-Note the OOo docs include the "cell or style" bit
-in this bundle of attributes.
-This is incorrect; the bit is used in determining which bundles to use.
-<br /> -- New in version 0.6.1
-</p></dd>
-<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>
-<dd>
-<p>1 = Cell is prevented from being changed, moved, resized, or deleted
-(only if the sheet is protected).</p>
-</dd>
-<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>
-<dd>
-<p>1 = Hide formula so that it doesn't appear in the formula bar when
-the cell is selected (only if the sheet is protected).</p>
-</dd>
-</dl>
-</body></html>
diff --git a/tablib/packages/xlrd/examples/namesdemo.xls b/tablib/packages/xlrd/examples/namesdemo.xls
deleted file mode 100644
index 8a16865..0000000
--- a/tablib/packages/xlrd/examples/namesdemo.xls
+++ /dev/null
Binary files differ
diff --git a/tablib/packages/xlrd/examples/xlrdnameAPIdemo.py b/tablib/packages/xlrd/examples/xlrdnameAPIdemo.py
deleted file mode 100644
index 6cd60df..0000000
--- a/tablib/packages/xlrd/examples/xlrdnameAPIdemo.py
+++ /dev/null
@@ -1,178 +0,0 @@
-# -*- coding: cp1252 -*-
-
-##
-# Module/script example of the xlrd API for extracting information
-# about named references, named constants, etc.
-#
-# <p>Copyright 2006 Stephen John Machin, Lingfo Pty Ltd</p>
-# <p>This module is part of the xlrd package, which is released under a BSD-style licence.</p>
-##
-
-import xlrd
-import sys
-import glob
-
-def scope_as_string(book, scope):
- if 0 <= scope < book.nsheets:
- return "sheet #%d (%r)" % (scope, book.sheet_names()[scope])
- if scope == -1:
- return "Global"
- if scope == -2:
- return "Macro/VBA"
- return "Unknown scope value (%r)" % scope
-
-def do_scope_query(book, scope_strg, show_contents=0, f=sys.stdout):
- try:
- qscope = int(scope_strg)
- except ValueError:
- if scope_strg == "*":
- qscope = None # means "all'
- else:
- # so assume it's a sheet name ...
- qscope = book.sheet_names().index(scope_strg)
- print >> f, "%r => %d" % (scope_strg, qscope)
- for nobj in book.name_obj_list:
- if qscope is None or nobj.scope == qscope:
- show_name_object(book, nobj, show_contents, f)
-
-def show_name_details(book, name, show_contents=0, f=sys.stdout):
- """
- book -- Book object obtained from xlrd.open_workbook().
- name -- The name that's being investigated.
- show_contents -- 0: Don't; 1: Non-empty cells only; 2: All cells
- f -- Open output file handle.
- """
- name_lcase = name.lower() # Excel names are case-insensitive.
- nobj_list = book.name_map.get(name_lcase)
- if not nobj_list:
- print >> f, "%r: unknown name" % name
- return
- for nobj in nobj_list:
- show_name_object(book, nobj, show_contents, f)
-
-def show_name_details_in_scope(
- book, name, scope_strg, show_contents=0, f=sys.stdout,
- ):
- try:
- scope = int(scope_strg)
- except ValueError:
- # so assume it's a sheet name ...
- scope = book.sheet_names().index(scope_strg)
- print >> f, "%r => %d" % (scope_strg, scope)
- name_lcase = name.lower() # Excel names are case-insensitive.
- while 1:
- nobj = book.name_and_scope_map.get((name_lcase, scope))
- if nobj:
- break
- print >> f, "Name %r not found in scope %d" % (name, scope)
- if scope == -1:
- return
- scope = -1 # Try again with global scope
- print >> f, "Name %r found in scope %d" % (name, scope)
- show_name_object(book, nobj, show_contents, f)
-
-def showable_cell_value(celltype, cellvalue, datemode):
- if celltype == xlrd.XL_CELL_DATE:
- try:
- showval = xlrd.xldate_as_tuple(cellvalue, datemode)
- except xlrd.XLDateError:
- e1, e2 = sys.exc_info()[:2]
- showval = "%s:%s" % (e1.__name__, e2)
- elif celltype == xlrd.XL_CELL_ERROR:
- showval = xlrd.error_text_from_code.get(
- cellvalue, '<Unknown error code 0x%02x>' % cellvalue)
- else:
- showval = cellvalue
- return showval
-
-def show_name_object(book, nobj, show_contents=0, f=sys.stdout):
- print >> f, "\nName: %r, scope: %r (%s)" \
- % (nobj.name, nobj.scope, scope_as_string(book, nobj.scope))
- res = nobj.result
- print >> f, "Formula eval result: %r" % res
- if res is None:
- return
- # result should be an instance of the Operand class
- kind = res.kind
- value = res.value
- if kind >= 0:
- # A scalar, or unknown ... you've seen all there is to see.
- pass
- elif kind == xlrd.oREL:
- # A list of Ref3D objects representing *relative* ranges
- for i in xrange(len(value)):
- ref3d = value[i]
- print >> f, "Range %d: %r ==> %s"% (i, ref3d.coords, xlrd.rangename3drel(book, ref3d))
- elif kind == xlrd.oREF:
- # A list of Ref3D objects
- for i in xrange(len(value)):
- ref3d = value[i]
- print >> f, "Range %d: %r ==> %s"% (i, ref3d.coords, xlrd.rangename3d(book, ref3d))
- if not show_contents:
- continue
- datemode = book.datemode
- for shx in xrange(ref3d.shtxlo, ref3d.shtxhi):
- sh = book.sheet_by_index(shx)
- print >> f, " Sheet #%d (%s)" % (shx, sh.name)
- rowlim = min(ref3d.rowxhi, sh.nrows)
- collim = min(ref3d.colxhi, sh.ncols)
- for rowx in xrange(ref3d.rowxlo, rowlim):
- for colx in xrange(ref3d.colxlo, collim):
- cty = sh.cell_type(rowx, colx)
- if cty == xlrd.XL_CELL_EMPTY and show_contents == 1:
- continue
- cval = sh.cell_value(rowx, colx)
- sval = showable_cell_value(cty, cval, datemode)
- print >> f, " (%3d,%3d) %-5s: %r" \
- % (rowx, colx, xlrd.cellname(rowx, colx), sval)
-
-if __name__ == "__main__":
- def usage():
- text = """
-usage: xlrdnameAIPdemo.py glob_pattern name scope show_contents
-
-where:
- "glob_pattern" designates a set of files
- "name" is a name or '*' (all names)
- "scope" is -1 (global) or a sheet number
- or a sheet name or * (all scopes)
- "show_contents" is one of 0 (no show),
- 1 (only non-empty cells), or 2 (all cells)
-
-Examples (script name and glob_pattern arg omitted for brevity)
- [Searching through book.name_obj_list]
- * * 0 lists all names
- * * 1 lists all names, showing referenced non-empty cells
- * 1 0 lists all names local to the 2nd sheet
- * Northern 0 lists all names local to the 'Northern' sheet
- * -1 0 lists all names with global scope
- [Initial direct access through book.name_map]
- Sales * 0 lists all occurrences of "Sales" in any scope
- [Direct access through book.name_and_scope_map]
- Revenue -1 0 checks if "Revenue" exists in global scope
-
-"""
- sys.stdout.write(text)
-
- if len(sys.argv) != 5:
- usage()
- sys.exit(0)
- arg_pattern = sys.argv[1] # glob pattern e.g. "foo*.xls"
- arg_name = sys.argv[2] # see below
- arg_scope = sys.argv[3] # see below
- arg_show_contents = int(sys.argv[4]) # 0: no show, 1: only non-empty cells,
- # 2: all cells
- for fname in glob.glob(arg_pattern):
- book = xlrd.open_workbook(fname)
- if arg_name == "*":
- # Examine book.name_obj_list to find all names
- # in a given scope ("*" => all scopes)
- do_scope_query(book, arg_scope, arg_show_contents)
- elif arg_scope == "*":
- # Using book.name_map to find all usage of a name.
- show_name_details(book, arg_name, arg_show_contents)
- else:
- # Using book.name_and_scope_map to find which if any instances
- # of a name are visible in the given scope, which can be supplied
- # as -1 (global) or a sheet number or a sheet name.
- show_name_details_in_scope(book, arg_name, arg_scope, arg_show_contents)
diff --git a/tablib/packages/xlrd/formatting.py b/tablib/packages/xlrd/formatting.py
deleted file mode 100644
index 302764b..0000000
--- a/tablib/packages/xlrd/formatting.py
+++ /dev/null
@@ -1,1256 +0,0 @@
-# -*- coding:cp1252 -*-
-
-##
-# Module for formatting information.
-#
-# <p>Copyright 2005-2008 Stephen John Machin, Lingfo Pty Ltd</p>
-# <p>Copyright 2005-2009 Stephen John Machin, Lingfo Pty Ltd</p>
-# <p>This module is part of the xlrd package, which is released under
-# a BSD-style licence.</p>
-##
-
-# No part of the content of this file was derived from the works of David Giffin.
-
-# 2009-05-31 SJM Fixed problem with non-zero reserved bits in some STYLE records in Mac Excel files
-# 2008-08-03 SJM Ignore PALETTE record when Book.formatting_info is false
-# 2008-08-03 SJM Tolerate up to 4 bytes trailing junk on PALETTE record
-# 2008-05-10 SJM Do some XF checks only when Book.formatting_info is true
-# 2008-02-08 SJM Preparation for Excel 2.0 support
-# 2008-02-03 SJM Another tweak to is_date_format_string()
-# 2007-12-04 SJM Added support for Excel 2.x (BIFF2) files.
-# 2007-10-13 SJM Warning: style XF whose parent XF index != 0xFFF
-# 2007-09-08 SJM Work around corrupt STYLE record
-# 2007-07-11 SJM Allow for BIFF2/3-style FORMAT record in BIFF4/8 file
-
-DEBUG = 0
-import copy, re
-from timemachine import *
-from biffh import BaseObject, unpack_unicode, unpack_string, \
- upkbits, upkbitsL, fprintf, \
- FUN, FDT, FNU, FGE, FTX, XL_CELL_NUMBER, XL_CELL_DATE, \
- XL_FORMAT, XL_FORMAT2, \
- XLRDError
-from struct import unpack
-
-excel_default_palette_b5 = (
- ( 0, 0, 0), (255, 255, 255), (255, 0, 0), ( 0, 255, 0),
- ( 0, 0, 255), (255, 255, 0), (255, 0, 255), ( 0, 255, 255),
- (128, 0, 0), ( 0, 128, 0), ( 0, 0, 128), (128, 128, 0),
- (128, 0, 128), ( 0, 128, 128), (192, 192, 192), (128, 128, 128),
- (153, 153, 255), (153, 51, 102), (255, 255, 204), (204, 255, 255),
- (102, 0, 102), (255, 128, 128), ( 0, 102, 204), (204, 204, 255),
- ( 0, 0, 128), (255, 0, 255), (255, 255, 0), ( 0, 255, 255),
- (128, 0, 128), (128, 0, 0), ( 0, 128, 128), ( 0, 0, 255),
- ( 0, 204, 255), (204, 255, 255), (204, 255, 204), (255, 255, 153),
- (153, 204, 255), (255, 153, 204), (204, 153, 255), (227, 227, 227),
- ( 51, 102, 255), ( 51, 204, 204), (153, 204, 0), (255, 204, 0),
- (255, 153, 0), (255, 102, 0), (102, 102, 153), (150, 150, 150),
- ( 0, 51, 102), ( 51, 153, 102), ( 0, 51, 0), ( 51, 51, 0),
- (153, 51, 0), (153, 51, 102), ( 51, 51, 153), ( 51, 51, 51),
- )
-
-excel_default_palette_b2 = excel_default_palette_b5[:16]
-
-# Following two tables borrowed from Gnumeric 1.4 source.
-excel_default_palette_b5_gnumeric_14 = (
- #### dodgy; didn't match Excel results
- ( 0, 0, 0), (255,255,255), (255, 0, 0), ( 0,255, 0),
- ( 0, 0,255), (255,255, 0), (255, 0,255), ( 0,255,255),
- (128, 0, 0), ( 0,128, 0), ( 0, 0,128), (128,128, 0),
- (128, 0,128), ( 0,128,128), (192,192,192), (128,128,128),
- (128,128,255), (128, 32, 96), (255,255,192), (160,224,224),
- ( 96, 0,128), (255,128,128), ( 0,128,192), (192,192,255),
- ( 0, 0,128), (255, 0,255), (255,255, 0), ( 0,255,255),
- (128, 0,128), (128, 0, 0), ( 0,128,128), ( 0, 0,255),
- ( 0,204,255), (105,255,255), (204,255,204), (255,255,153),
- (166,202,240), (204,156,204), (204,153,255), (227,227,227),
- ( 51,102,255), ( 51,204,204), ( 51,153, 51), (153,153, 51),
- (153,102, 51), (153,102,102), (102,102,153), (150,150,150),
- ( 51, 51,204), ( 51,102,102), ( 0, 51, 0), ( 51, 51, 0),
- (102, 51, 0), (153, 51,102), ( 51, 51,153), ( 66, 66, 66),
- )
-excel_default_palette_b8 = ( # (red, green, blue)
- ( 0, 0, 0), (255,255,255), (255, 0, 0), ( 0,255, 0),
- ( 0, 0,255), (255,255, 0), (255, 0,255), ( 0,255,255),
- (128, 0, 0), ( 0,128, 0), ( 0, 0,128), (128,128, 0),
- (128, 0,128), ( 0,128,128), (192,192,192), (128,128,128),
- (153,153,255), (153, 51,102), (255,255,204), (204,255,255),
- (102, 0,102), (255,128,128), ( 0,102,204), (204,204,255),
- ( 0, 0,128), (255, 0,255), (255,255, 0), ( 0,255,255),
- (128, 0,128), (128, 0, 0), ( 0,128,128), ( 0, 0,255),
- ( 0,204,255), (204,255,255), (204,255,204), (255,255,153),
- (153,204,255), (255,153,204), (204,153,255), (255,204,153),
- ( 51,102,255), ( 51,204,204), (153,204, 0), (255,204, 0),
- (255,153, 0), (255,102, 0), (102,102,153), (150,150,150),
- ( 0, 51,102), ( 51,153,102), ( 0, 51, 0), ( 51, 51, 0),
- (153, 51, 0), (153, 51,102), ( 51, 51,153), ( 51, 51, 51),
- )
-
-default_palette = {
- 80: excel_default_palette_b8,
- 70: excel_default_palette_b5,
- 50: excel_default_palette_b5,
- 45: excel_default_palette_b2,
- 40: excel_default_palette_b2,
- 30: excel_default_palette_b2,
- 21: excel_default_palette_b2,
- 20: excel_default_palette_b2,
- }
-
-"""
-00H = Normal
-01H = RowLevel_lv (see next field)
-02H = ColLevel_lv (see next field)
-03H = Comma
-04H = Currency
-05H = Percent
-06H = Comma [0] (BIFF4-BIFF8)
-07H = Currency [0] (BIFF4-BIFF8)
-08H = Hyperlink (BIFF8)
-09H = Followed Hyperlink (BIFF8)
-"""
-built_in_style_names = [
- "Normal",
- "RowLevel_",
- "ColLevel_",
- "Comma",
- "Currency",
- "Percent",
- "Comma [0]",
- "Currency [0]",
- "Hyperlink",
- "Followed Hyperlink",
- ]
-
-def initialise_colour_map(book):
- book.colour_map = {}
- book.colour_indexes_used = {}
- if not book.formatting_info:
- return
- # Add the 8 invariant colours
- for i in xrange(8):
- book.colour_map[i] = excel_default_palette_b8[i]
- # Add the default palette depending on the version
- dpal = default_palette[book.biff_version]
- ndpal = len(dpal)
- for i in xrange(ndpal):
- book.colour_map[i+8] = dpal[i]
- # Add the specials -- None means the RGB value is not known
- # System window text colour for border lines
- book.colour_map[ndpal+8] = None
- # System window background colour for pattern background
- book.colour_map[ndpal+8+1] = None #
- for ci in (
- 0x51, # System ToolTip text colour (used in note objects)
- 0x7FFF, # 32767, system window text colour for fonts
- ):
- book.colour_map[ci] = None
-
-def nearest_colour_index(colour_map, rgb, debug=0):
- # General purpose function. Uses Euclidean distance.
- # So far used only for pre-BIFF8 WINDOW2 record.
- # Doesn't have to be fast.
- # Doesn't have to be fancy.
- best_metric = 3 * 256 * 256
- best_colourx = 0
- for colourx, cand_rgb in colour_map.items():
- if cand_rgb is None:
- continue
- metric = 0
- for v1, v2 in zip(rgb, cand_rgb):
- metric += (v1 - v2) * (v1 - v2)
- if metric < best_metric:
- best_metric = metric
- best_colourx = colourx
- if metric == 0:
- break
- if debug:
- print "nearest_colour_index for %r is %r -> %r; best_metric is %d" \
- % (rgb, best_colourx, colour_map[best_colourx], best_metric)
- return best_colourx
-
-##
-# This mixin class exists solely so that Format, Font, and XF.... objects
-# can be compared by value of their attributes.
-class EqNeAttrs(object):
-
- def __eq__(self, other):
- return self.__dict__ == other.__dict__
-
- def __ne__(self, other):
- return self.__dict__ != other.__dict__
-
-##
-# An Excel "font" contains the details of not only what is normally
-# considered a font, but also several other display attributes.
-# Items correspond to those in the Excel UI's Format/Cells/Font tab.
-# <br /> -- New in version 0.6.1
-class Font(BaseObject, EqNeAttrs):
- ##
- # 1 = Characters are bold. Redundant; see "weight" attribute.
- bold = 0
- ##
- # Values: 0 = ANSI Latin, 1 = System default, 2 = Symbol,
- # 77 = Apple Roman,
- # 128 = ANSI Japanese Shift-JIS,
- # 129 = ANSI Korean (Hangul),
- # 130 = ANSI Korean (Johab),
- # 134 = ANSI Chinese Simplified GBK,
- # 136 = ANSI Chinese Traditional BIG5,
- # 161 = ANSI Greek,
- # 162 = ANSI Turkish,
- # 163 = ANSI Vietnamese,
- # 177 = ANSI Hebrew,
- # 178 = ANSI Arabic,
- # 186 = ANSI Baltic,
- # 204 = ANSI Cyrillic,
- # 222 = ANSI Thai,
- # 238 = ANSI Latin II (Central European),
- # 255 = OEM Latin I
- character_set = 0
- ##
- # An explanation of "colour index" is given in the Formatting
- # section at the start of this document.
- colour_index = 0
- ##
- # 1 = Superscript, 2 = Subscript.
- escapement = 0
- ##
- # 0 = None (unknown or don't care)<br />
- # 1 = Roman (variable width, serifed)<br />
- # 2 = Swiss (variable width, sans-serifed)<br />
- # 3 = Modern (fixed width, serifed or sans-serifed)<br />
- # 4 = Script (cursive)<br />
- # 5 = Decorative (specialised, for example Old English, Fraktur)
- family = 0
- ##
- # The 0-based index used to refer to this Font() instance.
- # Note that index 4 is never used; xlrd supplies a dummy place-holder.
- font_index = 0
- ##
- # Height of the font (in twips). A twip = 1/20 of a point.
- height = 0
- ##
- # 1 = Characters are italic.
- italic = 0
- ##
- # The name of the font. Example: u"Arial"
- name = u""
- ##
- # 1 = Characters are struck out.
- struck_out = 0
- ##
- # 0 = None<br />
- # 1 = Single; 0x21 (33) = Single accounting<br />
- # 2 = Double; 0x22 (34) = Double accounting
- underline_type = 0
- ##
- # 1 = Characters are underlined. Redundant; see "underline_type" attribute.
- underlined = 0
- ##
- # Font weight (100-1000). Standard values are 400 for normal text
- # and 700 for bold text.
- weight = 400
- ##
- # 1 = Font is outline style (Macintosh only)
- outline = 0
- ##
- # 1 = Font is shadow style (Macintosh only)
- shadow = 0
-
- # No methods ...
-
-def handle_efont(book, data): # BIFF2 only
- if not book.formatting_info:
- return
- book.font_list[-1].colour_index = unpack('<H', data)[0]
-
-def handle_font(book, data):
- if not book.formatting_info:
- return
- if not book.encoding:
- book.derive_encoding()
- blah = DEBUG or book.verbosity >= 2
- bv = book.biff_version
- k = len(book.font_list)
- if k == 4:
- f = Font()
- f.name = u'Dummy Font'
- f.font_index = k
- book.font_list.append(f)
- k += 1
- f = Font()
- f.font_index = k
- book.font_list.append(f)
- if bv >= 50:
- (
- f.height, option_flags, f.colour_index, f.weight,
- f.escapement_type, f.underline_type, f.family,
- f.character_set,
- ) = unpack('<HHHHHBBB', data[0:13])
- f.bold = option_flags & 1
- f.italic = (option_flags & 2) >> 1
- f.underlined = (option_flags & 4) >> 2
- f.struck_out = (option_flags & 8) >> 3
- f.outline = (option_flags & 16) >> 4
- f.shadow = (option_flags & 32) >> 5
- if bv >= 80:
- f.name = unpack_unicode(data, 14, lenlen=1)
- else:
- f.name = unpack_string(data, 14, book.encoding, lenlen=1)
- elif bv >= 30:
- f.height, option_flags, f.colour_index = unpack('<HHH', data[0:6])
- f.bold = option_flags & 1
- f.italic = (option_flags & 2) >> 1
- f.underlined = (option_flags & 4) >> 2
- f.struck_out = (option_flags & 8) >> 3
- f.outline = (option_flags & 16) >> 4
- f.shadow = (option_flags & 32) >> 5
- f.name = unpack_string(data, 6, book.encoding, lenlen=1)
- # Now cook up the remaining attributes ...
- f.weight = [400, 700][f.bold]
- f.escapement_type = 0 # None
- f.underline_type = f.underlined # None or Single
- f.family = 0 # Unknown / don't care
- f.character_set = 1 # System default (0 means "ANSI Latin")
- else: # BIFF2
- f.height, option_flags = unpack('<HH', data[0:4])
- f.colour_index = 0x7FFF # "system window text colour"
- f.bold = option_flags & 1
- f.italic = (option_flags & 2) >> 1
- f.underlined = (option_flags & 4) >> 2
- f.struck_out = (option_flags & 8) >> 3
- f.outline = 0
- f.shadow = 0
- f.name = unpack_string(data, 4, book.encoding, lenlen=1)
- # Now cook up the remaining attributes ...
- f.weight = [400, 700][f.bold]
- f.escapement_type = 0 # None
- f.underline_type = f.underlined # None or Single
- f.family = 0 # Unknown / don't care
- f.character_set = 1 # System default (0 means "ANSI Latin")
- if blah:
- f.dump(
- book.logfile,
- header="--- handle_font: font[%d] ---" % f.font_index,
- footer="-------------------",
- )
-
-# === "Number formats" ===
-
-##
-# "Number format" information from a FORMAT record.
-# <br /> -- New in version 0.6.1
-class Format(BaseObject, EqNeAttrs):
- ##
- # The key into Book.format_map
- format_key = 0
- ##
- # A classification that has been inferred from the format string.
- # Currently, this is used only to distinguish between numbers and dates.
- # <br />Values:
- # <br />FUN = 0 # unknown
- # <br />FDT = 1 # date
- # <br />FNU = 2 # number
- # <br />FGE = 3 # general
- # <br />FTX = 4 # text
- type = FUN
- ##
- # The format string
- format_str = u''
-
- def __init__(self, format_key, ty, format_str):
- self.format_key = format_key
- self.type = ty
- self.format_str = format_str
-
-std_format_strings = {
- # "std" == "standard for US English locale"
- # #### TODO ... a lot of work to tailor these to the user's locale.
- # See e.g. gnumeric-1.x.y/src/formats.c
- 0x00: "General",
- 0x01: "0",
- 0x02: "0.00",
- 0x03: "#,##0",
- 0x04: "#,##0.00",
- 0x05: "$#,##0_);($#,##0)",
- 0x06: "$#,##0_);[Red]($#,##0)",
- 0x07: "$#,##0.00_);($#,##0.00)",
- 0x08: "$#,##0.00_);[Red]($#,##0.00)",
- 0x09: "0%",
- 0x0a: "0.00%",
- 0x0b: "0.00E+00",
- 0x0c: "# ?/?",
- 0x0d: "# ??/??",
- 0x0e: "m/d/yy",
- 0x0f: "d-mmm-yy",
- 0x10: "d-mmm",
- 0x11: "mmm-yy",
- 0x12: "h:mm AM/PM",
- 0x13: "h:mm:ss AM/PM",
- 0x14: "h:mm",
- 0x15: "h:mm:ss",
- 0x16: "m/d/yy h:mm",
- 0x25: "#,##0_);(#,##0)",
- 0x26: "#,##0_);[Red](#,##0)",
- 0x27: "#,##0.00_);(#,##0.00)",
- 0x28: "#,##0.00_);[Red](#,##0.00)",
- 0x29: "_(* #,##0_);_(* (#,##0);_(* \"-\"_);_(@_)",
- 0x2a: "_($* #,##0_);_($* (#,##0);_($* \"-\"_);_(@_)",
- 0x2b: "_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);_(@_)",
- 0x2c: "_($* #,##0.00_);_($* (#,##0.00);_($* \"-\"??_);_(@_)",
- 0x2d: "mm:ss",
- 0x2e: "[h]:mm:ss",
- 0x2f: "mm:ss.0",
- 0x30: "##0.0E+0",
- 0x31: "@",
- }
-
-fmt_code_ranges = [ # both-inclusive ranges of "standard" format codes
- # Source: the openoffice.org doc't
- ( 0, 0, FGE),
- ( 1, 13, FNU),
- (14, 22, FDT),
- #### (27, 36, FDT), # Japanese dates -- not sure of reliability of this
- (37, 44, FNU),
- (45, 47, FDT),
- (48, 48, FNU),
- (49, 49, FTX),
- ####(50, 58, FDT), # Japanese dates -- but Gnumeric assumes
- # built-in formats finish at 49, not at 163
- ]
-
-std_format_code_types = {}
-for lo, hi, ty in fmt_code_ranges:
- for x in xrange(lo, hi+1):
- std_format_code_types[x] = ty
-del lo, hi, ty, x
-
-date_chars = u'ymdhs' # year, month/minute, day, hour, second
-date_char_dict = {}
-for _c in date_chars + date_chars.upper():
- date_char_dict[_c] = 5
-del _c, date_chars
-
-skip_char_dict = {}
-for _c in u'$-+/(): ':
- skip_char_dict[_c] = 1
-
-num_char_dict = {
- u'0': 5,
- u'#': 5,
- u'?': 5,
- }
-
-non_date_formats = {
- u'0.00E+00':1,
- u'##0.0E+0':1,
- u'General' :1,
- u'GENERAL' :1, # OOo Calc 1.1.4 does this.
- u'general' :1, # pyExcelerator 0.6.3 does this.
- u'@' :1,
- }
-
-fmt_bracketed_sub = re.compile(r'\[[^]]*\]').sub
-
-# Boolean format strings (actual cases)
-# u'"Yes";"Yes";"No"'
-# u'"True";"True";"False"'
-# u'"On";"On";"Off"'
-
-def is_date_format_string(book, fmt):
- # Heuristics:
- # Ignore "text" and [stuff in square brackets (aarrgghh -- see below)].
- # Handle backslashed-escaped chars properly.
- # E.g. hh\hmm\mss\s should produce a display like 23h59m59s
- # Date formats have one or more of ymdhs (caseless) in them.
- # Numeric formats have # and 0.
- # N.B. u'General"."' hence get rid of "text" first.
- # TODO: Find where formats are interpreted in Gnumeric
- # TODO: u'[h]\\ \\h\\o\\u\\r\\s' ([h] means don't care about hours > 23)
- state = 0
- s = ''
- ignorable = skip_char_dict.has_key
- for c in fmt:
- if state == 0:
- if c == u'"':
- state = 1
- elif c in ur"\_*":
- state = 2
- elif ignorable(c):
- pass
- else:
- s += c
- elif state == 1:
- if c == u'"':
- state = 0
- elif state == 2:
- # Ignore char after backslash, underscore or asterisk
- state = 0
- assert 0 <= state <= 2
- if book.verbosity >= 4:
- print "is_date_format_string: reduced format is %r" % s
- s = fmt_bracketed_sub('', s)
- if non_date_formats.has_key(s):
- return False
- state = 0
- separator = ";"
- got_sep = 0
- date_count = num_count = 0
- for c in s:
- if date_char_dict.has_key(c):
- date_count += date_char_dict[c]
- elif num_char_dict.has_key(c):
- num_count += num_char_dict[c]
- elif c == separator:
- got_sep = 1
- # print num_count, date_count, repr(fmt)
- if date_count and not num_count:
- return True
- if num_count and not date_count:
- return False
- if date_count:
- fprintf(book.logfile,
- 'WARNING *** is_date_format: ambiguous d=%d n=%d fmt=%r\n',
- date_count, num_count, fmt)
- elif not got_sep:
- fprintf(book.logfile,
- "WARNING *** format %r produces constant result\n",
- fmt)
- return date_count > num_count
-
-def handle_format(self, data, rectype=XL_FORMAT):
- DEBUG = 0
- bv = self.biff_version
- if rectype == XL_FORMAT2:
- bv = min(bv, 30)
- if not self.encoding:
- self.derive_encoding()
- strpos = 2
- if bv >= 50:
- fmtkey = unpack('<H', data[0:2])[0]
- else:
- fmtkey = self.actualfmtcount
- if bv <= 30:
- strpos = 0
- self.actualfmtcount += 1
- if bv >= 80:
- unistrg = unpack_unicode(data, 2)
- else:
- unistrg = unpack_string(data, strpos, self.encoding, lenlen=1)
- blah = DEBUG or self.verbosity >= 3
- if blah:
- fprintf(self.logfile,
- "FORMAT: count=%d fmtkey=0x%04x (%d) s=%r\n",
- self.actualfmtcount, fmtkey, fmtkey, unistrg)
- is_date_s = self.is_date_format_string(unistrg)
- ty = [FGE, FDT][is_date_s]
- if not(fmtkey > 163 or bv < 50):
- # user_defined if fmtkey > 163
- # N.B. Gnumeric incorrectly starts these at 50 instead of 164 :-(
- # if earlier than BIFF 5, standard info is useless
- std_ty = std_format_code_types.get(fmtkey, FUN)
- # print "std ty", std_ty
- is_date_c = std_ty == FDT
- if 0 < fmtkey < 50 and (is_date_c ^ is_date_s):
- DEBUG = 2
- fprintf(self.logfile,
- "WARNING *** Conflict between "
- "std format key %d and its format string %r\n",
- fmtkey, unistrg)
- if DEBUG == 2:
- fprintf(self.logfile,
- "ty: %d; is_date_c: %r; is_date_s: %r; fmt_strg: %r",
- ty, is_date_c, is_date_s, unistrg)
- fmtobj = Format(fmtkey, ty, unistrg)
- if blah:
- fmtobj.dump(self.logfile,
- header="--- handle_format [%d] ---" % (self.actualfmtcount-1, ))
- self.format_map[fmtkey] = fmtobj
- self.format_list.append(fmtobj)
-
-# =============================================================================
-
-def handle_palette(book, data):
- if not book.formatting_info:
- return
- blah = DEBUG or book.verbosity >= 2
- n_colours, = unpack('<H', data[:2])
- expected_n_colours = (16, 56)[book.biff_version >= 50]
- if ((DEBUG or book.verbosity >= 1)
- and n_colours != expected_n_colours):
- fprintf(book.logfile,
- "NOTE *** Expected %d colours in PALETTE record, found %d\n",
- expected_n_colours, n_colours)
- elif blah:
- fprintf(book.logfile,
- "PALETTE record with %d colours\n", n_colours)
- fmt = '<xx%di' % n_colours # use i to avoid long integers
- expected_size = 4 * n_colours + 2
- actual_size = len(data)
- tolerance = 4
- if not expected_size <= actual_size <= expected_size + tolerance:
- raise XLRDError('PALETTE record: expected size %d, actual size %d' % (expected_size, actual_size))
- colours = unpack(fmt, data[:expected_size])
- assert book.palette_record == [] # There should be only 1 PALETTE record
- # a colour will be 0xbbggrr
- # IOW, red is at the little end
- for i in xrange(n_colours):
- c = colours[i]
- red = c & 0xff
- green = (c >> 8) & 0xff
- blue = (c >> 16) & 0xff
- old_rgb = book.colour_map[8+i]
- new_rgb = (red, green, blue)
- book.palette_record.append(new_rgb)
- book.colour_map[8+i] = new_rgb
- if blah:
- if new_rgb != old_rgb:
- print >> book.logfile, "%2d: %r -> %r" % (i, old_rgb, new_rgb)
-
-def palette_epilogue(book):
- # Check colour indexes in fonts etc.
- # This must be done here as FONT records
- # come *before* the PALETTE record :-(
- for font in book.font_list:
- if font.font_index == 4: # the missing font record
- continue
- cx = font.colour_index
- if cx == 0x7fff: # system window text colour
- continue
- if book.colour_map.has_key(cx):
- book.colour_indexes_used[cx] = 1
- else:
- print "Size of colour table:", len(book.colour_map)
- print >> book.logfile, \
- "*** Font #%d (%r): colour index 0x%04x is unknown" \
- % (font.font_index, font.name, cx)
- if book.verbosity >= 1:
- used = book.colour_indexes_used.keys()
- used.sort()
- print >> book.logfile, "\nColour indexes used:\n%r\n" % used
-
-def handle_style(book, data):
- blah = DEBUG or book.verbosity >= 2
- bv = book.biff_version
- flag_and_xfx, built_in_id, level = unpack('<HBB', data[:4])
- xf_index = flag_and_xfx & 0x0fff
- if (data == "\0\0\0\0"
- and "Normal" not in book.style_name_map):
- # Erroneous record (doesn't have built-in bit set).
- # Example file supplied by Jeff Bell.
- built_in = 1
- built_in_id = 0
- xf_index = 0
- name = "Normal"
- level = 255
- elif flag_and_xfx & 0x8000:
- # built-in style
- built_in = 1
- name = built_in_style_names[built_in_id]
- if 1 <= built_in_id <= 2:
- name += str(level + 1)
- else:
- # user-defined style
- if bv >= 80:
- name = unpack_unicode(data, 2, lenlen=2)
- else:
- name = unpack_string(data, 2, book.encoding, lenlen=1)
- if blah and not name:
- print >> book.logfile, \
- "WARNING *** A user-defined style has a zero-length name"
- built_in = 0
- built_in_id = 0
- level = 0
- book.style_name_map[name] = (built_in, xf_index)
- if blah:
- print >> book.logfile, \
- "STYLE: built_in=%d xf_index=%d built_in_id=%d level=%d name=%r" \
- % (built_in, xf_index, built_in_id, level, name)
-
-def check_colour_indexes_in_obj(book, obj, orig_index):
- alist = obj.__dict__.items()
- alist.sort()
- for attr, nobj in alist:
- if hasattr(nobj, 'dump'):
- check_colour_indexes_in_obj(book, nobj, orig_index)
- elif attr.find('colour_index') >= 0:
- if book.colour_map.has_key(nobj):
- book.colour_indexes_used[nobj] = 1
- continue
- oname = obj.__class__.__name__
- print >> book.logfile, \
- "*** xf #%d : %s.%s = 0x%04x (unknown)" \
- % (orig_index, oname, attr, nobj)
-
-def handle_xf(self, data):
- ### self is a Book instance
- # DEBUG = 0
- blah = DEBUG or self.verbosity >= 3
- bv = self.biff_version
- xf = XF()
- xf.alignment = XFAlignment()
- xf.alignment.indent_level = 0
- xf.alignment.shrink_to_fit = 0
- xf.alignment.text_direction = 0
- xf.border = XFBorder()
- xf.border.diag_up = 0
- xf.border.diag_down = 0
- xf.border.diag_colour_index = 0
- xf.border.diag_line_style = 0 # no line
- xf.background = XFBackground()
- xf.protection = XFProtection()
- # fill in the known standard formats
- if bv >= 50 and not self.xfcount:
- # i.e. do this once before we process the first XF record
- for x in std_format_code_types.keys():
- if not self.format_map.has_key(x):
- ty = std_format_code_types[x]
- fmt_str = std_format_strings[x]
- fmtobj = Format(x, ty, fmt_str)
- self.format_map[x] = fmtobj
- if bv >= 80:
- unpack_fmt = '<HHHBBBBIiH'
- (xf.font_index, xf.format_key, pkd_type_par,
- pkd_align1, xf.alignment.rotation, pkd_align2,
- pkd_used, pkd_brdbkg1, pkd_brdbkg2, pkd_brdbkg3,
- ) = unpack(unpack_fmt, data[0:20])
- upkbits(xf.protection, pkd_type_par, (
- (0, 0x01, 'cell_locked'),
- (1, 0x02, 'formula_hidden'),
- ))
- upkbits(xf, pkd_type_par, (
- (2, 0x0004, 'is_style'),
- # Following is not in OOo docs, but is mentioned
- # in Gnumeric source and also in (deep breath)
- # org.apache.poi.hssf.record.ExtendedFormatRecord.java
- (3, 0x0008, 'lotus_123_prefix'), # Meaning is not known.
- (4, 0xFFF0, 'parent_style_index'),
- ))
- upkbits(xf.alignment, pkd_align1, (
- (0, 0x07, 'hor_align'),
- (3, 0x08, 'text_wrapped'),
- (4, 0x70, 'vert_align'),
- ))
- upkbits(xf.alignment, pkd_align2, (
- (0, 0x0f, 'indent_level'),
- (4, 0x10, 'shrink_to_fit'),
- (6, 0xC0, 'text_direction'),
- ))
- reg = pkd_used >> 2
- for attr_stem in \
- "format font alignment border background protection".split():
- attr = "_" + attr_stem + "_flag"
- setattr(xf, attr, reg & 1)
- reg >>= 1
- upkbitsL(xf.border, pkd_brdbkg1, (
- (0, 0x0000000f, 'left_line_style'),
- (4, 0x000000f0, 'right_line_style'),
- (8, 0x00000f00, 'top_line_style'),
- (12, 0x0000f000, 'bottom_line_style'),
- (16, 0x007f0000, 'left_colour_index'),
- (23, 0x3f800000, 'right_colour_index'),
- (30, 0x40000000, 'diag_down'),
- (31, 0x80000000L, 'diag_up'),
- ))
- upkbits(xf.border, pkd_brdbkg2, (
- (0, 0x0000007F, 'top_colour_index'),
- (7, 0x00003F80, 'bottom_colour_index'),
- (14, 0x001FC000, 'diag_colour_index'),
- (21, 0x01E00000, 'diag_line_style'),
- ))
- upkbitsL(xf.background, pkd_brdbkg2, (
- (26, 0xFC000000L, 'fill_pattern'),
- ))
- upkbits(xf.background, pkd_brdbkg3, (
- (0, 0x007F, 'pattern_colour_index'),
- (7, 0x3F80, 'background_colour_index'),
- ))
- elif bv >= 50:
- unpack_fmt = '<HHHBBIi'
- (xf.font_index, xf.format_key, pkd_type_par,
- pkd_align1, pkd_orient_used,
- pkd_brdbkg1, pkd_brdbkg2,
- ) = unpack(unpack_fmt, data[0:16])
- upkbits(xf.protection, pkd_type_par, (
- (0, 0x01, 'cell_locked'),
- (1, 0x02, 'formula_hidden'),
- ))
- upkbits(xf, pkd_type_par, (
- (2, 0x0004, 'is_style'),
- (3, 0x0008, 'lotus_123_prefix'), # Meaning is not known.
- (4, 0xFFF0, 'parent_style_index'),
- ))
- upkbits(xf.alignment, pkd_align1, (
- (0, 0x07, 'hor_align'),
- (3, 0x08, 'text_wrapped'),
- (4, 0x70, 'vert_align'),
- ))
- orientation = pkd_orient_used & 0x03
- xf.alignment.rotation = [0, 255, 90, 180][orientation]
- reg = pkd_orient_used >> 2
- for attr_stem in \
- "format font alignment border background protection".split():
- attr = "_" + attr_stem + "_flag"
- setattr(xf, attr, reg & 1)
- reg >>= 1
- upkbitsL(xf.background, pkd_brdbkg1, (
- ( 0, 0x0000007F, 'pattern_colour_index'),
- ( 7, 0x00003F80, 'background_colour_index'),
- (16, 0x003F0000, 'fill_pattern'),
- ))
- upkbitsL(xf.border, pkd_brdbkg1, (
- (22, 0x01C00000, 'bottom_line_style'),
- (25, 0xFE000000L, 'bottom_colour_index'),
- ))
- upkbits(xf.border, pkd_brdbkg2, (
- ( 0, 0x00000007, 'top_line_style'),
- ( 3, 0x00000038, 'left_line_style'),
- ( 6, 0x000001C0, 'right_line_style'),
- ( 9, 0x0000FE00, 'top_colour_index'),
- (16, 0x007F0000, 'left_colour_index'),
- (23, 0x3F800000, 'right_colour_index'),
- ))
- elif bv >= 40:
- unpack_fmt = '<BBHBBHI'
- (xf.font_index, xf.format_key, pkd_type_par,
- pkd_align_orient, pkd_used,
- pkd_bkg_34, pkd_brd_34,
- ) = unpack(unpack_fmt, data[0:12])
- upkbits(xf.protection, pkd_type_par, (
- (0, 0x01, 'cell_locked'),
- (1, 0x02, 'formula_hidden'),
- ))
- upkbits(xf, pkd_type_par, (
- (2, 0x0004, 'is_style'),
- (3, 0x0008, 'lotus_123_prefix'), # Meaning is not known.
- (4, 0xFFF0, 'parent_style_index'),
- ))
- upkbits(xf.alignment, pkd_align_orient, (
- (0, 0x07, 'hor_align'),
- (3, 0x08, 'text_wrapped'),
- (4, 0x30, 'vert_align'),
- ))
- orientation = (pkd_align_orient & 0xC0) >> 6
- xf.alignment.rotation = [0, 255, 90, 180][orientation]
- reg = pkd_used >> 2
- for attr_stem in \
- "format font alignment border background protection".split():
- attr = "_" + attr_stem + "_flag"
- setattr(xf, attr, reg & 1)
- reg >>= 1
- upkbits(xf.background, pkd_bkg_34, (
- ( 0, 0x003F, 'fill_pattern'),
- ( 6, 0x07C0, 'pattern_colour_index'),
- (11, 0xF800, 'background_colour_index'),
- ))
- upkbitsL(xf.border, pkd_brd_34, (
- ( 0, 0x00000007, 'top_line_style'),
- ( 3, 0x000000F8, 'top_colour_index'),
- ( 8, 0x00000700, 'left_line_style'),
- (11, 0x0000F800, 'left_colour_index'),
- (16, 0x00070000, 'bottom_line_style'),
- (19, 0x00F80000, 'bottom_colour_index'),
- (24, 0x07000000, 'right_line_style'),
- (27, 0xF8000000L, 'right_colour_index'),
- ))
- elif bv == 30:
- unpack_fmt = '<BBBBHHI'
- (xf.font_index, xf.format_key, pkd_type_prot,
- pkd_used, pkd_align_par,
- pkd_bkg_34, pkd_brd_34,
- ) = unpack(unpack_fmt, data[0:12])
- upkbits(xf.protection, pkd_type_prot, (
- (0, 0x01, 'cell_locked'),
- (1, 0x02, 'formula_hidden'),
- ))
- upkbits(xf, pkd_type_prot, (
- (2, 0x0004, 'is_style'),
- (3, 0x0008, 'lotus_123_prefix'), # Meaning is not known.
- ))
- upkbits(xf.alignment, pkd_align_par, (
- (0, 0x07, 'hor_align'),
- (3, 0x08, 'text_wrapped'),
- ))
- upkbits(xf, pkd_align_par, (
- (4, 0xFFF0, 'parent_style_index'),
- ))
- reg = pkd_used >> 2
- for attr_stem in \
- "format font alignment border background protection".split():
- attr = "_" + attr_stem + "_flag"
- setattr(xf, attr, reg & 1)
- reg >>= 1
- upkbits(xf.background, pkd_bkg_34, (
- ( 0, 0x003F, 'fill_pattern'),
- ( 6, 0x07C0, 'pattern_colour_index'),
- (11, 0xF800, 'background_colour_index'),
- ))
- upkbitsL(xf.border, pkd_brd_34, (
- ( 0, 0x00000007, 'top_line_style'),
- ( 3, 0x000000F8, 'top_colour_index'),
- ( 8, 0x00000700, 'left_line_style'),
- (11, 0x0000F800, 'left_colour_index'),
- (16, 0x00070000, 'bottom_line_style'),
- (19, 0x00F80000, 'bottom_colour_index'),
- (24, 0x07000000, 'right_line_style'),
- (27, 0xF8000000L, 'right_colour_index'),
- ))
- xf.alignment.vert_align = 2 # bottom
- xf.alignment.rotation = 0
- elif bv == 21:
- #### Warning: incomplete treatment; formatting_info not fully supported.
- #### Probably need to offset incoming BIFF2 XF[n] to BIFF8-like XF[n+16],
- #### and create XF[0:16] like the standard ones in BIFF8
- #### *AND* add 16 to all XF references in cell records :-(
- (xf.font_index, format_etc, halign_etc) = unpack('<BxBB', data)
- xf.format_key = format_etc & 0x3F
- upkbits(xf.protection, format_etc, (
- (6, 0x40, 'cell_locked'),
- (7, 0x80, 'formula_hidden'),
- ))
- upkbits(xf.alignment, halign_etc, (
- (0, 0x07, 'hor_align'),
- ))
- for mask, side in ((0x08, 'left'), (0x10, 'right'), (0x20, 'top'), (0x40, 'bottom')):
- if halign_etc & mask:
- colour_index, line_style = 8, 1 # black, thin
- else:
- colour_index, line_style = 0, 0 # none, none
- setattr(xf.border, side + '_colour_index', colour_index)
- setattr(xf.border, side + '_line_style', line_style)
- bg = xf.background
- if halign_etc & 0x80:
- bg.fill_pattern = 17
- else:
- bg.fill_pattern = 0
- bg.background_colour_index = 9 # white
- bg.pattern_colour_index = 8 # black
- xf.parent_style_index = 0 # ???????????
- xf.alignment.vert_align = 2 # bottom
- xf.alignment.rotation = 0
- for attr_stem in \
- "format font alignment border background protection".split():
- attr = "_" + attr_stem + "_flag"
- setattr(xf, attr, 1)
- else:
- raise XLRDError('programmer stuff-up: bv=%d' % bv)
-
- xf.xf_index = len(self.xf_list)
- self.xf_list.append(xf)
- self.xfcount += 1
- if blah:
- xf.dump(
- self.logfile,
- header="--- handle_xf: xf[%d] ---" % xf.xf_index,
- footer=" ",
- )
- # Now for some assertions ...
- if self.formatting_info:
- if xf.is_style and xf.parent_style_index != 0x0FFF:
- msg = "WARNING *** XF[%d] is a style XF but parent_style_index is 0x%04x, not 0x0fff\n"
- fprintf(self.logfile, msg, xf.xf_index, xf.parent_style_index)
- check_colour_indexes_in_obj(self, xf, xf.xf_index)
- if not self.format_map.has_key(xf.format_key):
- msg = "WARNING *** XF[%d] unknown (raw) format key (%d, 0x%04x)\n"
- fprintf(self.logfile, msg,
- xf.xf_index, xf.format_key, xf.format_key)
- xf.format_key = 0
-
-def xf_epilogue(self):
- # self is a Book instance.
- self._xf_epilogue_done = 1
- num_xfs = len(self.xf_list)
- blah = DEBUG or self.verbosity >= 3
- blah1 = DEBUG or self.verbosity >= 1
- if blah:
- fprintf(self.logfile, "xf_epilogue called ...\n")
-
- def check_same(book_arg, xf_arg, parent_arg, attr):
- # the _arg caper is to avoid a Warning msg from Python 2.1 :-(
- if getattr(xf_arg, attr) != getattr(parent_arg, attr):
- fprintf(book_arg.logfile,
- "NOTE !!! XF[%d] parent[%d] %s different\n",
- xf_arg.xf_index, parent_arg.xf_index, attr)
-
- for xfx in xrange(num_xfs):
- xf = self.xf_list[xfx]
- if not self.format_map.has_key(xf.format_key):
- msg = "ERROR *** XF[%d] unknown format key (%d, 0x%04x)\n"
- fprintf(self.logfile, msg,
- xf.xf_index, xf.format_key, xf.format_key)
- xf.format_key = 0
- cellty_from_fmtty = {
- FNU: XL_CELL_NUMBER,
- FUN: XL_CELL_NUMBER,
- FGE: XL_CELL_NUMBER,
- FDT: XL_CELL_DATE,
- FTX: XL_CELL_NUMBER, # Yes, a number can be formatted as text.
- }
- fmt = self.format_map[xf.format_key]
- cellty = cellty_from_fmtty[fmt.type]
- self._xf_index_to_xl_type_map[xf.xf_index] = cellty
- # Now for some assertions etc
- if not self.formatting_info:
- continue
- if xf.is_style:
- continue
- if not(0 <= xf.parent_style_index < num_xfs):
- fprintf(self.logfile,
- "WARNING *** XF[%d]: is_style=%d but parent_style_index=%d\n",
- xf.xf_index, xf.is_style, xf.parent_style_index)
- # make it conform
- xf.parent_style_index = 0
- if self.biff_version >= 30:
- assert xf.parent_style_index != xf.xf_index
- assert self.xf_list[xf.parent_style_index].is_style
- if blah1 and xf.parent_style_index > xf.xf_index:
- fprintf(self.logfile,
- "NOTE !!! XF[%d]: parent_style_index is %d; out of order?\n",
- xf.xf_index, xf.parent_style_index)
- parent = self.xf_list[xf.parent_style_index]
- if not xf._alignment_flag and not parent._alignment_flag:
- if blah1: check_same(self, xf, parent, 'alignment')
- if not xf._background_flag and not parent._background_flag:
- if blah1: check_same(self, xf, parent, 'background')
- if not xf._border_flag and not parent._border_flag:
- if blah1: check_same(self, xf, parent, 'border')
- if not xf._protection_flag and not parent._protection_flag:
- if blah1: check_same(self, xf, parent, 'protection')
- if not xf._format_flag and not parent._format_flag:
- if blah1 and xf.format_key != parent.format_key:
- fprintf(self.logfile,
- "NOTE !!! XF[%d] fmtk=%d, parent[%d] fmtk=%r\n%r / %r\n",
- xf.xf_index, xf.format_key, parent.xf_index, parent.format_key,
- self.format_map[xf.format_key].format_str,
- self.format_map[parent.format_key].format_str)
- if not xf._font_flag and not parent._font_flag:
- if blah1 and xf.font_index != parent.font_index:
- fprintf(self.logfile,
- "NOTE !!! XF[%d] fontx=%d, parent[%d] fontx=%r\n",
- xf.xf_index, xf.font_index, parent.xf_index, parent.font_index)
-
-def initialise_book(book):
- initialise_colour_map(book)
- book._xf_epilogue_done = 0
- methods = (
- handle_font,
- handle_efont,
- handle_format,
- is_date_format_string,
- handle_palette,
- palette_epilogue,
- handle_style,
- handle_xf,
- xf_epilogue,
- )
- for method in methods:
- setattr(book.__class__, method.__name__, method)
-
-##
-# <p>A collection of the border-related attributes of an XF record.
-# Items correspond to those in the Excel UI's Format/Cells/Border tab.</p>
-# <p> An explanations of "colour index" is given in the Formatting
-# section at the start of this document.
-# There are five line style attributes; possible values and the
-# associated meanings are:
-# 0&nbsp;=&nbsp;No line,
-# 1&nbsp;=&nbsp;Thin,
-# 2&nbsp;=&nbsp;Medium,
-# 3&nbsp;=&nbsp;Dashed,
-# 4&nbsp;=&nbsp;Dotted,
-# 5&nbsp;=&nbsp;Thick,
-# 6&nbsp;=&nbsp;Double,
-# 7&nbsp;=&nbsp;Hair,
-# 8&nbsp;=&nbsp;Medium dashed,
-# 9&nbsp;=&nbsp;Thin dash-dotted,
-# 10&nbsp;=&nbsp;Medium dash-dotted,
-# 11&nbsp;=&nbsp;Thin dash-dot-dotted,
-# 12&nbsp;=&nbsp;Medium dash-dot-dotted,
-# 13&nbsp;=&nbsp;Slanted medium dash-dotted.
-# The line styles 8 to 13 appear in BIFF8 files (Excel 97 and later) only.
-# For pictures of the line styles, refer to OOo docs s3.10 (p22)
-# "Line Styles for Cell Borders (BIFF3-BIFF8)".</p>
-# <br /> -- New in version 0.6.1
-class XFBorder(BaseObject, EqNeAttrs):
-
- ##
- # The colour index for the cell's top line
- top_colour_index = 0
- ##
- # The colour index for the cell's bottom line
- bottom_colour_index = 0
- ##
- # The colour index for the cell's left line
- left_colour_index = 0
- ##
- # The colour index for the cell's right line
- right_colour_index = 0
- ##
- # The colour index for the cell's diagonal lines, if any
- diag_colour_index = 0
- ##
- # The line style for the cell's top line
- top_line_style = 0
- ##
- # The line style for the cell's bottom line
- bottom_line_style = 0
- ##
- # The line style for the cell's left line
- left_line_style = 0
- ##
- # The line style for the cell's right line
- right_line_style = 0
- ##
- # The line style for the cell's diagonal lines, if any
- diag_line_style = 0
- ##
- # 1 = draw a diagonal from top left to bottom right
- diag_down = 0
- ##
- # 1 = draw a diagonal from bottom left to top right
- diag_up = 0
-
-##
-# A collection of the background-related attributes of an XF record.
-# Items correspond to those in the Excel UI's Format/Cells/Patterns tab.
-# An explanation of "colour index" is given in the Formatting
-# section at the start of this document.
-# <br /> -- New in version 0.6.1
-class XFBackground(BaseObject, EqNeAttrs):
-
- ##
- # See section 3.11 of the OOo docs.
- fill_pattern = 0
- ##
- # See section 3.11 of the OOo docs.
- background_colour_index = 0
- ##
- # See section 3.11 of the OOo docs.
- pattern_colour_index = 0
-
-##
-# A collection of the alignment and similar attributes of an XF record.
-# Items correspond to those in the Excel UI's Format/Cells/Alignment tab.
-# <br /> -- New in version 0.6.1
-
-class XFAlignment(BaseObject, EqNeAttrs):
-
- ##
- # Values: section 6.115 (p 214) of OOo docs
- hor_align = 0
- ##
- # Values: section 6.115 (p 215) of OOo docs
- vert_align = 0
- ##
- # Values: section 6.115 (p 215) of OOo docs.<br />
- # Note: file versions BIFF7 and earlier use the documented
- # "orientation" attribute; this will be mapped (without loss)
- # into "rotation".
- rotation = 0
- ##
- # 1 = text is wrapped at right margin
- text_wrapped = 0
- ##
- # A number in range(15).
- indent_level = 0
- ##
- # 1 = shrink font size to fit text into cell.
- shrink_to_fit = 0
- ##
- # 0 = according to context; 1 = left-to-right; 2 = right-to-left
- text_direction = 0
-
-##
-# A collection of the protection-related attributes of an XF record.
-# Items correspond to those in the Excel UI's Format/Cells/Protection tab.
-# Note the OOo docs include the "cell or style" bit
-# in this bundle of attributes.
-# This is incorrect; the bit is used in determining which bundles to use.
-# <br /> -- New in version 0.6.1
-
-class XFProtection(BaseObject, EqNeAttrs):
-
- ##
- # 1 = Cell is prevented from being changed, moved, resized, or deleted
- # (only if the sheet is protected).
- cell_locked = 0
- ##
- # 1 = Hide formula so that it doesn't appear in the formula bar when
- # the cell is selected (only if the sheet is protected).
- formula_hidden = 0
-
-##
-# eXtended Formatting information for cells, rows, columns and styles.
-# <br /> -- New in version 0.6.1
-#
-# <p>Each of the 6 flags below describes the validity of
-# a specific group of attributes.
-# <br />
-# In cell XFs, flag==0 means the attributes of the parent style XF are used,
-# (but only if the attributes are valid there); flag==1 means the attributes
-# of this XF are used.<br />
-# In style XFs, flag==0 means the attribute setting is valid; flag==1 means
-# the attribute should be ignored.<br />
-# Note that the API
-# provides both "raw" XFs and "computed" XFs -- in the latter case, cell XFs
-# have had the above inheritance mechanism applied.
-# </p>
-
-class XF(BaseObject):
-
- ##
- # 0 = cell XF, 1 = style XF
- is_style = 0
- ##
- # cell XF: Index into Book.xf_list
- # of this XF's style XF<br />
- # style XF: 0xFFF
- parent_style_index = 0
- ##
- #
- _format_flag = 0
- ##
- #
- _font_flag = 0
- ##
- #
- _alignment_flag = 0
- ##
- #
- _border_flag = 0
- ##
- #
- _background_flag = 0
- ##
- # &nbsp;
- _protection_flag = 0
- ##
- # Index into Book.xf_list
- xf_index = 0
- ##
- # Index into Book.font_list
- font_index = 0
- ##
- # Key into Book.format_map
- # <p>
- # Warning: OOo docs on the XF record call this "Index to FORMAT record".
- # It is not an index in the Python sense. It is a key to a map.
- # It is true <i>only</i> for Excel 4.0 and earlier files
- # that the key into format_map from an XF instance
- # is the same as the index into format_list, and <i>only</i>
- # if the index is less than 164.
- # </p>
- format_key = 0
- ##
- # An instance of an XFProtection object.
- protection = None
- ##
- # An instance of an XFBackground object.
- background = None
- ##
- # An instance of an XFAlignment object.
- alignment = None
- ##
- # An instance of an XFBorder object.
- border = None
diff --git a/tablib/packages/xlrd/formula.py b/tablib/packages/xlrd/formula.py
deleted file mode 100644
index 4edbc29..0000000
--- a/tablib/packages/xlrd/formula.py
+++ /dev/null
@@ -1,2092 +0,0 @@
-# -*- coding: cp1252 -*-
-
-##
-# Module for parsing/evaluating Microsoft Excel formulas.
-#
-# <p>Copyright 2005-2009 Stephen John Machin, Lingfo Pty Ltd</p>
-# <p>This module is part of the xlrd package, which is released under
-# a BSD-style licence.</p>
-##
-
-# No part of the content of this file was derived from the works of David Giffin.
-
-import copy
-from struct import unpack
-from timemachine import *
-from biffh import unpack_unicode_update_pos, unpack_string_update_pos, \
- XLRDError, hex_char_dump, error_text_from_code, BaseObject
-
-__all__ = [
- 'oBOOL', 'oERR', 'oNUM', 'oREF', 'oREL', 'oSTRG', 'oUNK',
- 'decompile_formula',
- 'dump_formula',
- 'evaluate_name_formula',
- 'okind_dict',
- 'rangename3d', 'rangename3drel', 'cellname', 'cellnameabs', 'colname',
- ]
-
-# sztabN[opcode] -> the number of bytes to consume.
-# -1 means variable
-# -2 means this opcode not implemented in this version.
-# Which N to use? Depends on biff_version; see szdict.
-sztab0 = [-2, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -2, -1, 8, 4, 2, 2, 3, 9, 8, 2, 3, 8, 4, 7, 5, 5, 5, 2, 4, 7, 4, 7, 2, 2, -2, -2, -2, -2, -2, -2, -2, -2, 3, -2, -2, -2, -2, -2, -2, -2]
-sztab1 = [-2, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -2, -1, 11, 5, 2, 2, 3, 9, 9, 2, 3, 11, 4, 7, 7, 7, 7, 3, 4, 7, 4, 7, 3, 3, -2, -2, -2, -2, -2, -2, -2, -2, 3, -2, -2, -2, -2, -2, -2, -2]
-sztab2 = [-2, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -2, -1, 11, 5, 2, 2, 3, 9, 9, 3, 4, 11, 4, 7, 7, 7, 7, 3, 4, 7, 4, 7, 3, 3, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2]
-sztab3 = [-2, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -2, -1, -2, -2, 2, 2, 3, 9, 9, 3, 4, 15, 4, 7, 7, 7, 7, 3, 4, 7, 4, 7, 3, 3, -2, -2, -2, -2, -2, -2, -2, -2, -2, 25, 18, 21, 18, 21, -2, -2]
-sztab4 = [-2, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -2, -2, 2, 2, 3, 9, 9, 3, 4, 5, 5, 9, 7, 7, 7, 3, 5, 9, 5, 9, 3, 3, -2, -2, -2, -2, -2, -2, -2, -2, -2, 7, 7, 11, 7, 11, -2, -2]
-
-szdict = {
- 20 : sztab0,
- 30 : sztab1,
- 40 : sztab2,
- 45 : sztab2,
- 50 : sztab3,
- 70 : sztab3,
- 80 : sztab4,
- }
-
-# For debugging purposes ... the name for each opcode
-# (without the prefix "t" used on OOo docs)
-onames = ['Unk00', 'Exp', 'Tbl', 'Add', 'Sub', 'Mul', 'Div', 'Power', 'Concat', 'LT', 'LE', 'EQ', 'GE', 'GT', 'NE', 'Isect', 'List', 'Range', 'Uplus', 'Uminus', 'Percent', 'Paren', 'MissArg', 'Str', 'Extended', 'Attr', 'Sheet', 'EndSheet', 'Err', 'Bool', 'Int', 'Num', 'Array', 'Func', 'FuncVar', 'Name', 'Ref', 'Area', 'MemArea', 'MemErr', 'MemNoMem', 'MemFunc', 'RefErr', 'AreaErr', 'RefN', 'AreaN', 'MemAreaN', 'MemNoMemN', '', '', '', '', '', '', '', '', 'FuncCE', 'NameX', 'Ref3d', 'Area3d', 'RefErr3d', 'AreaErr3d', '', '']
-
-func_defs = {
- # index: (name, min#args, max#args, flags, #known_args, return_type, kargs)
- 0 : ('COUNT', 0, 30, 0x04, 1, 'V', 'R'),
- 1 : ('IF', 2, 3, 0x04, 3, 'V', 'VRR'),
- 2 : ('ISNA', 1, 1, 0x02, 1, 'V', 'V'),
- 3 : ('ISERROR', 1, 1, 0x02, 1, 'V', 'V'),
- 4 : ('SUM', 0, 30, 0x04, 1, 'V', 'R'),
- 5 : ('AVERAGE', 1, 30, 0x04, 1, 'V', 'R'),
- 6 : ('MIN', 1, 30, 0x04, 1, 'V', 'R'),
- 7 : ('MAX', 1, 30, 0x04, 1, 'V', 'R'),
- 8 : ('ROW', 0, 1, 0x04, 1, 'V', 'R'),
- 9 : ('COLUMN', 0, 1, 0x04, 1, 'V', 'R'),
- 10 : ('NA', 0, 0, 0x02, 0, 'V', ''),
- 11 : ('NPV', 2, 30, 0x04, 2, 'V', 'VR'),
- 12 : ('STDEV', 1, 30, 0x04, 1, 'V', 'R'),
- 13 : ('DOLLAR', 1, 2, 0x04, 1, 'V', 'V'),
- 14 : ('FIXED', 2, 3, 0x04, 3, 'V', 'VVV'),
- 15 : ('SIN', 1, 1, 0x02, 1, 'V', 'V'),
- 16 : ('COS', 1, 1, 0x02, 1, 'V', 'V'),
- 17 : ('TAN', 1, 1, 0x02, 1, 'V', 'V'),
- 18 : ('ATAN', 1, 1, 0x02, 1, 'V', 'V'),
- 19 : ('PI', 0, 0, 0x02, 0, 'V', ''),
- 20 : ('SQRT', 1, 1, 0x02, 1, 'V', 'V'),
- 21 : ('EXP', 1, 1, 0x02, 1, 'V', 'V'),
- 22 : ('LN', 1, 1, 0x02, 1, 'V', 'V'),
- 23 : ('LOG10', 1, 1, 0x02, 1, 'V', 'V'),
- 24 : ('ABS', 1, 1, 0x02, 1, 'V', 'V'),
- 25 : ('INT', 1, 1, 0x02, 1, 'V', 'V'),
- 26 : ('SIGN', 1, 1, 0x02, 1, 'V', 'V'),
- 27 : ('ROUND', 2, 2, 0x02, 2, 'V', 'VV'),
- 28 : ('LOOKUP', 2, 3, 0x04, 2, 'V', 'VR'),
- 29 : ('INDEX', 2, 4, 0x0c, 4, 'R', 'RVVV'),
- 30 : ('REPT', 2, 2, 0x02, 2, 'V', 'VV'),
- 31 : ('MID', 3, 3, 0x02, 3, 'V', 'VVV'),
- 32 : ('LEN', 1, 1, 0x02, 1, 'V', 'V'),
- 33 : ('VALUE', 1, 1, 0x02, 1, 'V', 'V'),
- 34 : ('TRUE', 0, 0, 0x02, 0, 'V', ''),
- 35 : ('FALSE', 0, 0, 0x02, 0, 'V', ''),
- 36 : ('AND', 1, 30, 0x04, 1, 'V', 'R'),
- 37 : ('OR', 1, 30, 0x04, 1, 'V', 'R'),
- 38 : ('NOT', 1, 1, 0x02, 1, 'V', 'V'),
- 39 : ('MOD', 2, 2, 0x02, 2, 'V', 'VV'),
- 40 : ('DCOUNT', 3, 3, 0x02, 3, 'V', 'RRR'),
- 41 : ('DSUM', 3, 3, 0x02, 3, 'V', 'RRR'),
- 42 : ('DAVERAGE', 3, 3, 0x02, 3, 'V', 'RRR'),
- 43 : ('DMIN', 3, 3, 0x02, 3, 'V', 'RRR'),
- 44 : ('DMAX', 3, 3, 0x02, 3, 'V', 'RRR'),
- 45 : ('DSTDEV', 3, 3, 0x02, 3, 'V', 'RRR'),
- 46 : ('VAR', 1, 30, 0x04, 1, 'V', 'R'),
- 47 : ('DVAR', 3, 3, 0x02, 3, 'V', 'RRR'),
- 48 : ('TEXT', 2, 2, 0x02, 2, 'V', 'VV'),
- 49 : ('LINEST', 1, 4, 0x04, 4, 'A', 'RRVV'),
- 50 : ('TREND', 1, 4, 0x04, 4, 'A', 'RRRV'),
- 51 : ('LOGEST', 1, 4, 0x04, 4, 'A', 'RRVV'),
- 52 : ('GROWTH', 1, 4, 0x04, 4, 'A', 'RRRV'),
- 56 : ('PV', 3, 5, 0x04, 5, 'V', 'VVVVV'),
- 57 : ('FV', 3, 5, 0x04, 5, 'V', 'VVVVV'),
- 58 : ('NPER', 3, 5, 0x04, 5, 'V', 'VVVVV'),
- 59 : ('PMT', 3, 5, 0x04, 5, 'V', 'VVVVV'),
- 60 : ('RATE', 3, 6, 0x04, 6, 'V', 'VVVVVV'),
- 61 : ('MIRR', 3, 3, 0x02, 3, 'V', 'RVV'),
- 62 : ('IRR', 1, 2, 0x04, 2, 'V', 'RV'),
- 63 : ('RAND', 0, 0, 0x0a, 0, 'V', ''),
- 64 : ('MATCH', 2, 3, 0x04, 3, 'V', 'VRR'),
- 65 : ('DATE', 3, 3, 0x02, 3, 'V', 'VVV'),
- 66 : ('TIME', 3, 3, 0x02, 3, 'V', 'VVV'),
- 67 : ('DAY', 1, 1, 0x02, 1, 'V', 'V'),
- 68 : ('MONTH', 1, 1, 0x02, 1, 'V', 'V'),
- 69 : ('YEAR', 1, 1, 0x02, 1, 'V', 'V'),
- 70 : ('WEEKDAY', 1, 2, 0x04, 2, 'V', 'VV'),
- 71 : ('HOUR', 1, 1, 0x02, 1, 'V', 'V'),
- 72 : ('MINUTE', 1, 1, 0x02, 1, 'V', 'V'),
- 73 : ('SECOND', 1, 1, 0x02, 1, 'V', 'V'),
- 74 : ('NOW', 0, 0, 0x0a, 0, 'V', ''),
- 75 : ('AREAS', 1, 1, 0x02, 1, 'V', 'R'),
- 76 : ('ROWS', 1, 1, 0x02, 1, 'V', 'R'),
- 77 : ('COLUMNS', 1, 1, 0x02, 1, 'V', 'R'),
- 78 : ('OFFSET', 3, 5, 0x04, 5, 'R', 'RVVVV'),
- 82 : ('SEARCH', 2, 3, 0x04, 3, 'V', 'VVV'),
- 83 : ('TRANSPOSE', 1, 1, 0x02, 1, 'A', 'A'),
- 86 : ('TYPE', 1, 1, 0x02, 1, 'V', 'V'),
- 92 : ('SERIESSUM', 4, 4, 0x02, 4, 'V', 'VVVA'),
- 97 : ('ATAN2', 2, 2, 0x02, 2, 'V', 'VV'),
- 98 : ('ASIN', 1, 1, 0x02, 1, 'V', 'V'),
- 99 : ('ACOS', 1, 1, 0x02, 1, 'V', 'V'),
- 100: ('CHOOSE', 2, 30, 0x04, 2, 'V', 'VR'),
- 101: ('HLOOKUP', 3, 4, 0x04, 4, 'V', 'VRRV'),
- 102: ('VLOOKUP', 3, 4, 0x04, 4, 'V', 'VRRV'),
- 105: ('ISREF', 1, 1, 0x02, 1, 'V', 'R'),
- 109: ('LOG', 1, 2, 0x04, 2, 'V', 'VV'),
- 111: ('CHAR', 1, 1, 0x02, 1, 'V', 'V'),
- 112: ('LOWER', 1, 1, 0x02, 1, 'V', 'V'),
- 113: ('UPPER', 1, 1, 0x02, 1, 'V', 'V'),
- 114: ('PROPER', 1, 1, 0x02, 1, 'V', 'V'),
- 115: ('LEFT', 1, 2, 0x04, 2, 'V', 'VV'),
- 116: ('RIGHT', 1, 2, 0x04, 2, 'V', 'VV'),
- 117: ('EXACT', 2, 2, 0x02, 2, 'V', 'VV'),
- 118: ('TRIM', 1, 1, 0x02, 1, 'V', 'V'),
- 119: ('REPLACE', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 120: ('SUBSTITUTE', 3, 4, 0x04, 4, 'V', 'VVVV'),
- 121: ('CODE', 1, 1, 0x02, 1, 'V', 'V'),
- 124: ('FIND', 2, 3, 0x04, 3, 'V', 'VVV'),
- 125: ('CELL', 1, 2, 0x0c, 2, 'V', 'VR'),
- 126: ('ISERR', 1, 1, 0x02, 1, 'V', 'V'),
- 127: ('ISTEXT', 1, 1, 0x02, 1, 'V', 'V'),
- 128: ('ISNUMBER', 1, 1, 0x02, 1, 'V', 'V'),
- 129: ('ISBLANK', 1, 1, 0x02, 1, 'V', 'V'),
- 130: ('T', 1, 1, 0x02, 1, 'V', 'R'),
- 131: ('N', 1, 1, 0x02, 1, 'V', 'R'),
- 140: ('DATEVALUE', 1, 1, 0x02, 1, 'V', 'V'),
- 141: ('TIMEVALUE', 1, 1, 0x02, 1, 'V', 'V'),
- 142: ('SLN', 3, 3, 0x02, 3, 'V', 'VVV'),
- 143: ('SYD', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 144: ('DDB', 4, 5, 0x04, 5, 'V', 'VVVVV'),
- 148: ('INDIRECT', 1, 2, 0x0c, 2, 'R', 'VV'),
- 162: ('CLEAN', 1, 1, 0x02, 1, 'V', 'V'),
- 163: ('MDETERM', 1, 1, 0x02, 1, 'V', 'A'),
- 164: ('MINVERSE', 1, 1, 0x02, 1, 'A', 'A'),
- 165: ('MMULT', 2, 2, 0x02, 2, 'A', 'AA'),
- 167: ('IPMT', 4, 6, 0x04, 6, 'V', 'VVVVVV'),
- 168: ('PPMT', 4, 6, 0x04, 6, 'V', 'VVVVVV'),
- 169: ('COUNTA', 0, 30, 0x04, 1, 'V', 'R'),
- 183: ('PRODUCT', 0, 30, 0x04, 1, 'V', 'R'),
- 184: ('FACT', 1, 1, 0x02, 1, 'V', 'V'),
- 189: ('DPRODUCT', 3, 3, 0x02, 3, 'V', 'RRR'),
- 190: ('ISNONTEXT', 1, 1, 0x02, 1, 'V', 'V'),
- 193: ('STDEVP', 1, 30, 0x04, 1, 'V', 'R'),
- 194: ('VARP', 1, 30, 0x04, 1, 'V', 'R'),
- 195: ('DSTDEVP', 3, 3, 0x02, 3, 'V', 'RRR'),
- 196: ('DVARP', 3, 3, 0x02, 3, 'V', 'RRR'),
- 197: ('TRUNC', 1, 2, 0x04, 2, 'V', 'VV'),
- 198: ('ISLOGICAL', 1, 1, 0x02, 1, 'V', 'V'),
- 199: ('DCOUNTA', 3, 3, 0x02, 3, 'V', 'RRR'),
- 204: ('USDOLLAR', 1, 2, 0x04, 2, 'V', 'VV'),
- 205: ('FINDB', 2, 3, 0x04, 3, 'V', 'VVV'),
- 206: ('SEARCHB', 2, 3, 0x04, 3, 'V', 'VVV'),
- 207: ('REPLACEB', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 208: ('LEFTB', 1, 2, 0x04, 2, 'V', 'VV'),
- 209: ('RIGHTB', 1, 2, 0x04, 2, 'V', 'VV'),
- 210: ('MIDB', 3, 3, 0x02, 3, 'V', 'VVV'),
- 211: ('LENB', 1, 1, 0x02, 1, 'V', 'V'),
- 212: ('ROUNDUP', 2, 2, 0x02, 2, 'V', 'VV'),
- 213: ('ROUNDDOWN', 2, 2, 0x02, 2, 'V', 'VV'),
- 214: ('ASC', 1, 1, 0x02, 1, 'V', 'V'),
- 215: ('DBCS', 1, 1, 0x02, 1, 'V', 'V'),
- 216: ('RANK', 2, 3, 0x04, 3, 'V', 'VRV'),
- 219: ('ADDRESS', 2, 5, 0x04, 5, 'V', 'VVVVV'),
- 220: ('DAYS360', 2, 3, 0x04, 3, 'V', 'VVV'),
- 221: ('TODAY', 0, 0, 0x0a, 0, 'V', ''),
- 222: ('VDB', 5, 7, 0x04, 7, 'V', 'VVVVVVV'),
- 227: ('MEDIAN', 1, 30, 0x04, 1, 'V', 'R'),
- 228: ('SUMPRODUCT', 1, 30, 0x04, 1, 'V', 'A'),
- 229: ('SINH', 1, 1, 0x02, 1, 'V', 'V'),
- 230: ('COSH', 1, 1, 0x02, 1, 'V', 'V'),
- 231: ('TANH', 1, 1, 0x02, 1, 'V', 'V'),
- 232: ('ASINH', 1, 1, 0x02, 1, 'V', 'V'),
- 233: ('ACOSH', 1, 1, 0x02, 1, 'V', 'V'),
- 234: ('ATANH', 1, 1, 0x02, 1, 'V', 'V'),
- 235: ('DGET', 3, 3, 0x02, 3, 'V', 'RRR'),
- 244: ('INFO', 1, 1, 0x02, 1, 'V', 'V'),
- 247: ('DB', 4, 5, 0x04, 5, 'V', 'VVVVV'),
- 252: ('FREQUENCY', 2, 2, 0x02, 2, 'A', 'RR'),
- 261: ('ERROR.TYPE', 1, 1, 0x02, 1, 'V', 'V'),
- 269: ('AVEDEV', 1, 30, 0x04, 1, 'V', 'R'),
- 270: ('BETADIST', 3, 5, 0x04, 1, 'V', 'V'),
- 271: ('GAMMALN', 1, 1, 0x02, 1, 'V', 'V'),
- 272: ('BETAINV', 3, 5, 0x04, 1, 'V', 'V'),
- 273: ('BINOMDIST', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 274: ('CHIDIST', 2, 2, 0x02, 2, 'V', 'VV'),
- 275: ('CHIINV', 2, 2, 0x02, 2, 'V', 'VV'),
- 276: ('COMBIN', 2, 2, 0x02, 2, 'V', 'VV'),
- 277: ('CONFIDENCE', 3, 3, 0x02, 3, 'V', 'VVV'),
- 278: ('CRITBINOM', 3, 3, 0x02, 3, 'V', 'VVV'),
- 279: ('EVEN', 1, 1, 0x02, 1, 'V', 'V'),
- 280: ('EXPONDIST', 3, 3, 0x02, 3, 'V', 'VVV'),
- 281: ('FDIST', 3, 3, 0x02, 3, 'V', 'VVV'),
- 282: ('FINV', 3, 3, 0x02, 3, 'V', 'VVV'),
- 283: ('FISHER', 1, 1, 0x02, 1, 'V', 'V'),
- 284: ('FISHERINV', 1, 1, 0x02, 1, 'V', 'V'),
- 285: ('FLOOR', 2, 2, 0x02, 2, 'V', 'VV'),
- 286: ('GAMMADIST', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 287: ('GAMMAINV', 3, 3, 0x02, 3, 'V', 'VVV'),
- 288: ('CEILING', 2, 2, 0x02, 2, 'V', 'VV'),
- 289: ('HYPGEOMDIST', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 290: ('LOGNORMDIST', 3, 3, 0x02, 3, 'V', 'VVV'),
- 291: ('LOGINV', 3, 3, 0x02, 3, 'V', 'VVV'),
- 292: ('NEGBINOMDIST', 3, 3, 0x02, 3, 'V', 'VVV'),
- 293: ('NORMDIST', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 294: ('NORMSDIST', 1, 1, 0x02, 1, 'V', 'V'),
- 295: ('NORMINV', 3, 3, 0x02, 3, 'V', 'VVV'),
- 296: ('NORMSINV', 1, 1, 0x02, 1, 'V', 'V'),
- 297: ('STANDARDIZE', 3, 3, 0x02, 3, 'V', 'VVV'),
- 298: ('ODD', 1, 1, 0x02, 1, 'V', 'V'),
- 299: ('PERMUT', 2, 2, 0x02, 2, 'V', 'VV'),
- 300: ('POISSON', 3, 3, 0x02, 3, 'V', 'VVV'),
- 301: ('TDIST', 3, 3, 0x02, 3, 'V', 'VVV'),
- 302: ('WEIBULL', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 303: ('SUMXMY2', 2, 2, 0x02, 2, 'V', 'AA'),
- 304: ('SUMX2MY2', 2, 2, 0x02, 2, 'V', 'AA'),
- 305: ('SUMX2PY2', 2, 2, 0x02, 2, 'V', 'AA'),
- 306: ('CHITEST', 2, 2, 0x02, 2, 'V', 'AA'),
- 307: ('CORREL', 2, 2, 0x02, 2, 'V', 'AA'),
- 308: ('COVAR', 2, 2, 0x02, 2, 'V', 'AA'),
- 309: ('FORECAST', 3, 3, 0x02, 3, 'V', 'VAA'),
- 310: ('FTEST', 2, 2, 0x02, 2, 'V', 'AA'),
- 311: ('INTERCEPT', 2, 2, 0x02, 2, 'V', 'AA'),
- 312: ('PEARSON', 2, 2, 0x02, 2, 'V', 'AA'),
- 313: ('RSQ', 2, 2, 0x02, 2, 'V', 'AA'),
- 314: ('STEYX', 2, 2, 0x02, 2, 'V', 'AA'),
- 315: ('SLOPE', 2, 2, 0x02, 2, 'V', 'AA'),
- 316: ('TTEST', 4, 4, 0x02, 4, 'V', 'AAVV'),
- 317: ('PROB', 3, 4, 0x04, 3, 'V', 'AAV'),
- 318: ('DEVSQ', 1, 30, 0x04, 1, 'V', 'R'),
- 319: ('GEOMEAN', 1, 30, 0x04, 1, 'V', 'R'),
- 320: ('HARMEAN', 1, 30, 0x04, 1, 'V', 'R'),
- 321: ('SUMSQ', 0, 30, 0x04, 1, 'V', 'R'),
- 322: ('KURT', 1, 30, 0x04, 1, 'V', 'R'),
- 323: ('SKEW', 1, 30, 0x04, 1, 'V', 'R'),
- 324: ('ZTEST', 2, 3, 0x04, 2, 'V', 'RV'),
- 325: ('LARGE', 2, 2, 0x02, 2, 'V', 'RV'),
- 326: ('SMALL', 2, 2, 0x02, 2, 'V', 'RV'),
- 327: ('QUARTILE', 2, 2, 0x02, 2, 'V', 'RV'),
- 328: ('PERCENTILE', 2, 2, 0x02, 2, 'V', 'RV'),
- 329: ('PERCENTRANK', 2, 3, 0x04, 2, 'V', 'RV'),
- 330: ('MODE', 1, 30, 0x04, 1, 'V', 'A'),
- 331: ('TRIMMEAN', 2, 2, 0x02, 2, 'V', 'RV'),
- 332: ('TINV', 2, 2, 0x02, 2, 'V', 'VV'),
- 336: ('CONCATENATE', 0, 30, 0x04, 1, 'V', 'V'),
- 337: ('POWER', 2, 2, 0x02, 2, 'V', 'VV'),
- 342: ('RADIANS', 1, 1, 0x02, 1, 'V', 'V'),
- 343: ('DEGREES', 1, 1, 0x02, 1, 'V', 'V'),
- 344: ('SUBTOTAL', 2, 30, 0x04, 2, 'V', 'VR'),
- 345: ('SUMIF', 2, 3, 0x04, 3, 'V', 'RVR'),
- 346: ('COUNTIF', 2, 2, 0x02, 2, 'V', 'RV'),
- 347: ('COUNTBLANK', 1, 1, 0x02, 1, 'V', 'R'),
- 350: ('ISPMT', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 351: ('DATEDIF', 3, 3, 0x02, 3, 'V', 'VVV'),
- 352: ('DATESTRING', 1, 1, 0x02, 1, 'V', 'V'),
- 353: ('NUMBERSTRING', 2, 2, 0x02, 2, 'V', 'VV'),
- 354: ('ROMAN', 1, 2, 0x04, 2, 'V', 'VV'),
- 358: ('GETPIVOTDATA', 2, 2, 0x02, 2, 'V', 'RV'),
- 359: ('HYPERLINK', 1, 2, 0x04, 2, 'V', 'VV'),
- 360: ('PHONETIC', 1, 1, 0x02, 1, 'V', 'V'),
- 361: ('AVERAGEA', 1, 30, 0x04, 1, 'V', 'R'),
- 362: ('MAXA', 1, 30, 0x04, 1, 'V', 'R'),
- 363: ('MINA', 1, 30, 0x04, 1, 'V', 'R'),
- 364: ('STDEVPA', 1, 30, 0x04, 1, 'V', 'R'),
- 365: ('VARPA', 1, 30, 0x04, 1, 'V', 'R'),
- 366: ('STDEVA', 1, 30, 0x04, 1, 'V', 'R'),
- 367: ('VARA', 1, 30, 0x04, 1, 'V', 'R'),
- 368: ('BAHTTEXT', 1, 1, 0x02, 1, 'V', 'V'),
- 369: ('THAIDAYOFWEEK', 1, 1, 0x02, 1, 'V', 'V'),
- 370: ('THAIDIGIT', 1, 1, 0x02, 1, 'V', 'V'),
- 371: ('THAIMONTHOFYEAR', 1, 1, 0x02, 1, 'V', 'V'),
- 372: ('THAINUMSOUND', 1, 1, 0x02, 1, 'V', 'V'),
- 373: ('THAINUMSTRING', 1, 1, 0x02, 1, 'V', 'V'),
- 374: ('THAISTRINGLENGTH', 1, 1, 0x02, 1, 'V', 'V'),
- 375: ('ISTHAIDIGIT', 1, 1, 0x02, 1, 'V', 'V'),
- 376: ('ROUNDBAHTDOWN', 1, 1, 0x02, 1, 'V', 'V'),
- 377: ('ROUNDBAHTUP', 1, 1, 0x02, 1, 'V', 'V'),
- 378: ('THAIYEAR', 1, 1, 0x02, 1, 'V', 'V'),
- 379: ('RTD', 2, 5, 0x04, 1, 'V', 'V'),
- }
-
-tAttrNames = {
- 0x00: "Skip??", # seen in SAMPLES.XLS which shipped with Excel 5.0
- 0x01: "Volatile",
- 0x02: "If",
- 0x04: "Choose",
- 0x08: "Skip",
- 0x10: "Sum",
- 0x20: "Assign",
- 0x40: "Space",
- 0x41: "SpaceVolatile",
- }
-
-_error_opcodes = {}
-for _x in [0x07, 0x08, 0x0A, 0x0B, 0x1C, 0x1D, 0x2F]:
- _error_opcodes[_x] = 1
-is_error_opcode = _error_opcodes.has_key
-
-tRangeFuncs = (min, max, min, max, min, max)
-tIsectFuncs = (max, min, max, min, max, min)
-
-def do_box_funcs(box_funcs, boxa, boxb):
- return tuple([
- func(numa, numb)
- for func, numa, numb in zip(box_funcs, boxa.coords, boxb.coords)
- ])
-
-def adjust_cell_addr_biff8(rowval, colval, reldelta, browx=None, bcolx=None):
- row_rel = (colval >> 15) & 1
- col_rel = (colval >> 14) & 1
- rowx = rowval
- colx = colval & 0xff
- if reldelta:
- if row_rel and rowx >= 32768:
- rowx -= 65536
- if col_rel and colx >= 128:
- colx -= 256
- else:
- if row_rel:
- rowx -= browx
- if col_rel:
- colx -= bcolx
- return rowx, colx, row_rel, col_rel
-
-def adjust_cell_addr_biff_le7(
- rowval, colval, reldelta, browx=None, bcolx=None):
- row_rel = (rowval >> 15) & 1
- col_rel = (rowval >> 14) & 1
- rowx = rowval & 0x3fff
- colx = colval
- if reldelta:
- if row_rel and rowx >= 8192:
- rowx -= 16384
- if col_rel and colx >= 128:
- colx -= 256
- else:
- if row_rel:
- rowx -= browx
- if col_rel:
- colx -= bcolx
- return rowx, colx, row_rel, col_rel
-
-def get_cell_addr(data, pos, bv, reldelta, browx=None, bcolx=None):
- if bv >= 80:
- rowval, colval = unpack("<HH", data[pos:pos+4])
- # print " rv=%04xh cv=%04xh" % (rowval, colval)
- return adjust_cell_addr_biff8(rowval, colval, reldelta, browx, bcolx)
- else:
- rowval, colval = unpack("<HB", data[pos:pos+3])
- # print " rv=%04xh cv=%04xh" % (rowval, colval)
- return adjust_cell_addr_biff_le7(
- rowval, colval, reldelta, browx, bcolx)
-
-def get_cell_range_addr(data, pos, bv, reldelta, browx=None, bcolx=None):
- if bv >= 80:
- row1val, row2val, col1val, col2val = unpack("<HHHH", data[pos:pos+8])
- # print " rv=%04xh cv=%04xh" % (row1val, col1val)
- # print " rv=%04xh cv=%04xh" % (row2val, col2val)
- res1 = adjust_cell_addr_biff8(row1val, col1val, reldelta, browx, bcolx)
- res2 = adjust_cell_addr_biff8(row2val, col2val, reldelta, browx, bcolx)
- return res1, res2
- else:
- row1val, row2val, col1val, col2val = unpack("<HHBB", data[pos:pos+6])
- # print " rv=%04xh cv=%04xh" % (row1val, col1val)
- # print " rv=%04xh cv=%04xh" % (row2val, col2val)
- res1 = adjust_cell_addr_biff_le7(
- row1val, col1val, reldelta, browx, bcolx)
- res2 = adjust_cell_addr_biff_le7(
- row2val, col2val, reldelta, browx, bcolx)
- return res1, res2
-
-def get_externsheet_local_range(bk, refx, blah=0):
- try:
- info = bk._externsheet_info[refx]
- except IndexError:
- print "!!! get_externsheet_local_range: refx=%d, not in range(%d)" \
- % (refx, len(bk._externsheet_info))
- return (-101, -101)
- ref_recordx, ref_first_sheetx, ref_last_sheetx = info
- if ref_recordx == bk._supbook_addins_inx:
- if blah:
- print "/// get_externsheet_local_range(refx=%d) -> addins %r" % (refx, info)
- assert ref_first_sheetx == 0xFFFE == ref_last_sheetx
- return (-5, -5)
- if ref_recordx != bk._supbook_locals_inx:
- if blah:
- print "/// get_externsheet_local_range(refx=%d) -> external %r" % (refx, info)
- return (-4, -4) # external reference
- if ref_first_sheetx == 0xFFFE == ref_last_sheetx:
- if blah:
- print "/// get_externsheet_local_range(refx=%d) -> unspecified sheet %r" % (refx, info)
- return (-1, -1) # internal reference, any sheet
- if ref_first_sheetx == 0xFFFF == ref_last_sheetx:
- if blah:
- print "/// get_externsheet_local_range(refx=%d) -> deleted sheet(s)" % (refx, )
- return (-2, -2) # internal reference, deleted sheet(s)
- nsheets = len(bk._all_sheets_map)
- if not(0 <= ref_first_sheetx <= ref_last_sheetx < nsheets):
- if blah:
- print "/// get_externsheet_local_range(refx=%d) -> %r" % (refx, info)
- print "--- first/last sheet not in range(%d)" % nsheets
- return (-102, -102) # stuffed up somewhere :-(
- xlrd_sheetx1 = bk._all_sheets_map[ref_first_sheetx]
- xlrd_sheetx2 = bk._all_sheets_map[ref_last_sheetx]
- if not(0 <= xlrd_sheetx1 <= xlrd_sheetx2):
- return (-3, -3) # internal reference, but to a macro sheet
- return xlrd_sheetx1, xlrd_sheetx2
-
-def get_externsheet_local_range_b57(
- bk, raw_extshtx, ref_first_sheetx, ref_last_sheetx, blah=0):
- if raw_extshtx > 0:
- if blah:
- print "/// get_externsheet_local_range_b57(raw_extshtx=%d) -> external" % raw_extshtx
- return (-4, -4) # external reference
- if ref_first_sheetx == -1 and ref_last_sheetx == -1:
- return (-2, -2) # internal reference, deleted sheet(s)
- nsheets = len(bk._all_sheets_map)
- if not(0 <= ref_first_sheetx <= ref_last_sheetx < nsheets):
- if blah:
- print "/// get_externsheet_local_range_b57(%d, %d, %d) -> ???" \
- % (raw_extshtx, ref_first_sheetx, ref_last_sheetx)
- print "--- first/last sheet not in range(%d)" % nsheets
- return (-103, -103) # stuffed up somewhere :-(
- xlrd_sheetx1 = bk._all_sheets_map[ref_first_sheetx]
- xlrd_sheetx2 = bk._all_sheets_map[ref_last_sheetx]
- if not(0 <= xlrd_sheetx1 <= xlrd_sheetx2):
- return (-3, -3) # internal reference, but to a macro sheet
- return xlrd_sheetx1, xlrd_sheetx2
-
-class FormulaError(Exception):
- pass
-
-oBOOL = 3
-oERR = 4
-oMSNG = 5 # tMissArg
-oNUM = 2
-oREF = -1
-oREL = -2
-oSTRG = 1
-oUNK = 0
-
-okind_dict = {
- -2: "oREL",
- -1: "oREF",
- 0 : "oUNK",
- 1 : "oSTRG",
- 2 : "oNUM",
- 3 : "oBOOL",
- 4 : "oERR",
- 5 : "oMSNG",
- }
-
-listsep = ',' #### probably should depend on locale
-
-##
-# Used in evaluating formulas.
-# The following table describes the kinds and how their values
-# are represented.</p>
-#
-# <table border="1" cellpadding="7">
-# <tr>
-# <th>Kind symbol</th>
-# <th>Kind number</th>
-# <th>Value representation</th>
-# </tr>
-# <tr>
-# <td>oBOOL</td>
-# <td align="center">3</td>
-# <td>integer: 0 => False; 1 => True</td>
-# </tr>
-# <tr>
-# <td>oERR</td>
-# <td align="center">4</td>
-# <td>None, or an int error code (same as XL_CELL_ERROR in the Cell class).
-# </td>
-# </tr>
-# <tr>
-# <td>oMSNG</td>
-# <td align="center">5</td>
-# <td>Used by Excel as a placeholder for a missing (not supplied) function
-# argument. Should *not* appear as a final formula result. Value is None.</td>
-# </tr>
-# <tr>
-# <td>oNUM</td>
-# <td align="center">2</td>
-# <td>A float. Note that there is no way of distinguishing dates.</td>
-# </tr>
-# <tr>
-# <td>oREF</td>
-# <td align="center">-1</td>
-# <td>The value is either None or a non-empty list of
-# absolute Ref3D instances.<br>
-# </td>
-# </tr>
-# <tr>
-# <td>oREL</td>
-# <td align="center">-2</td>
-# <td>The value is None or a non-empty list of
-# fully or partially relative Ref3D instances.
-# </td>
-# </tr>
-# <tr>
-# <td>oSTRG</td>
-# <td align="center">1</td>
-# <td>A Unicode string.</td>
-# </tr>
-# <tr>
-# <td>oUNK</td>
-# <td align="center">0</td>
-# <td>The kind is unknown or ambiguous. The value is None</td>
-# </tr>
-# </table>
-#<p></p>
-
-class Operand(object):
-
- ##
- # None means that the actual value of the operand is a variable
- # (depends on cell data), not a constant.
- value = None
- ##
- # oUNK means that the kind of operand is not known unambiguously.
- kind = oUNK
- ##
- # The reconstituted text of the original formula. Function names will be
- # in English irrespective of the original language, which doesn't seem
- # to be recorded anywhere. The separator is ",", not ";" or whatever else
- # might be more appropriate for the end-user's locale; patches welcome.
- text = '?'
-
- def __init__(self, akind=None, avalue=None, arank=0, atext='?'):
- if akind is not None:
- self.kind = akind
- if avalue is not None:
- self.value = avalue
- self.rank = arank
- # rank is an internal gizmo (operator precedence);
- # it's used in reconstructing formula text.
- self.text = atext
-
- def __repr__(self):
- kind_text = okind_dict.get(self.kind, "?Unknown kind?")
- return "Operand(kind=%s, value=%r, text=%r)" \
- % (kind_text, self.value, self.text)
-
-if CAN_SUBCLASS_BUILTIN:
- _ref3d_base = tuple
-else:
- _ref3d_base = object
-
-##
-# <p>Represents an absolute or relative 3-dimensional reference to a box
-# of one or more cells.<br />
-# -- New in version 0.6.0
-# </p>
-#
-# <p>The <i>coords</i> attribute is a tuple of the form:<br />
-# (shtxlo, shtxhi, rowxlo, rowxhi, colxlo, colxhi)<br />
-# where 0 <= thingxlo <= thingx < thingxhi.<br />
-# Note that it is quite possible to have thingx > nthings; for example
-# Print_Titles could have colxhi == 256 and/or rowxhi == 65536
-# irrespective of how many columns/rows are actually used in the worksheet.
-# The caller will need to decide how to handle this situation.
-# Keyword: IndexError :-)
-# </p>
-#
-# <p>The components of the coords attribute are also available as individual
-# attributes: shtxlo, shtxhi, rowxlo, rowxhi, colxlo, and colxhi.</p>
-#
-# <p>The <i>relflags</i> attribute is a 6-tuple of flags which indicate whether
-# the corresponding (sheet|row|col)(lo|hi) is relative (1) or absolute (0).<br>
-# Note that there is necessarily no information available as to what cell(s)
-# the reference could possibly be relative to. The caller must decide what if
-# any use to make of oREL operands. Note also that a partially relative
-# reference may well be a typo.
-# For example, define name A1Z10 as $a$1:$z10 (missing $ after z)
-# while the cursor is on cell Sheet3!A27.<br>
-# The resulting Ref3D instance will have coords = (2, 3, 0, -16, 0, 26)
-# and relflags = (0, 0, 0, 1, 0, 0).<br>
-# So far, only one possibility of a sheet-relative component in
-# a reference has been noticed: a 2D reference located in the "current sheet".
-# <br /> This will appear as coords = (0, 1, ...) and relflags = (1, 1, ...).
-
-class Ref3D(_ref3d_base):
-
- def __init__(self, atuple):
- self.coords = atuple[0:6]
- self.relflags = atuple[6:12]
- if not self.relflags:
- self.relflags = (0, 0, 0, 0, 0, 0)
- (self.shtxlo, self.shtxhi,
- self.rowxlo, self.rowxhi,
- self.colxlo, self.colxhi) = self.coords
-
- def __repr__(self):
- if not self.relflags or self.relflags == (0, 0, 0, 0, 0, 0):
- return "Ref3D(coords=%r)" % (self.coords, )
- else:
- return "Ref3D(coords=%r, relflags=%r)" \
- % (self.coords, self.relflags)
-
-tAdd = 0x03
-tSub = 0x04
-tMul = 0x05
-tDiv = 0x06
-tPower = 0x07
-tConcat = 0x08
-tLT, tLE, tEQ, tGE, tGT, tNE = range(0x09, 0x0F)
-
-import operator as opr
-
-def nop(x):
- return x
-
-def _opr_pow(x, y): return x ** y
-
-def _opr_lt(x, y): return x < y
-def _opr_le(x, y): return x <= y
-def _opr_eq(x, y): return x == y
-def _opr_ge(x, y): return x >= y
-def _opr_gt(x, y): return x > y
-def _opr_ne(x, y): return x != y
-
-def num2strg(num):
- """Attempt to emulate Excel's default conversion
- from number to string.
- """
- s = str(num)
- if s.endswith(".0"):
- s = s[:-2]
- return s
-
-_arith_argdict = {oNUM: nop, oSTRG: float}
-_cmp_argdict = {oNUM: nop, oSTRG: nop}
-# Seems no conversions done on relops; in Excel, "1" > 9 produces TRUE.
-_strg_argdict = {oNUM:num2strg, oSTRG:nop}
-binop_rules = {
- tAdd: (_arith_argdict, oNUM, opr.add, 30, '+'),
- tSub: (_arith_argdict, oNUM, opr.sub, 30, '-'),
- tMul: (_arith_argdict, oNUM, opr.mul, 40, '*'),
- tDiv: (_arith_argdict, oNUM, opr.div, 40, '/'),
- tPower: (_arith_argdict, oNUM, _opr_pow, 50, '^',),
- tConcat:(_strg_argdict, oSTRG, opr.add, 20, '&'),
- tLT: (_cmp_argdict, oBOOL, _opr_lt, 10, '<'),
- tLE: (_cmp_argdict, oBOOL, _opr_le, 10, '<='),
- tEQ: (_cmp_argdict, oBOOL, _opr_eq, 10, '='),
- tGE: (_cmp_argdict, oBOOL, _opr_ge, 10, '>='),
- tGT: (_cmp_argdict, oBOOL, _opr_gt, 10, '>'),
- tNE: (_cmp_argdict, oBOOL, _opr_ne, 10, '<>'),
- }
-
-unop_rules = {
- 0x13: (lambda x: -x, 70, '-', ''), # unary minus
- 0x12: (lambda x: x, 70, '+', ''), # unary plus
- 0x14: (lambda x: x / 100.0, 60, '', '%'),# percent
- }
-
-LEAF_RANK = 90
-FUNC_RANK = 90
-
-STACK_ALARM_LEVEL = 5
-STACK_PANIC_LEVEL = 10
-
-def evaluate_name_formula(bk, nobj, namex, blah=0, level=0):
- if level > STACK_ALARM_LEVEL:
- blah = 1
- data = nobj.raw_formula
- fmlalen = nobj.basic_formula_len
- bv = bk.biff_version
- reldelta = 1 # All defined name formulas use "Method B" [OOo docs]
- if blah:
- print "::: evaluate_name_formula %r %r %d %d %r level=%d" \
- % (namex, nobj.name, fmlalen, bv, data, level)
- hex_char_dump(data, 0, fmlalen)
- if level > STACK_PANIC_LEVEL:
- raise XLRDError("Excessive indirect references in NAME formula")
- sztab = szdict[bv]
- pos = 0
- stack = []
- any_rel = 0
- any_err = 0
- any_external = 0
- unk_opnd = Operand(oUNK, None)
- error_opnd = Operand(oERR, None)
- spush = stack.append
-
- def do_binop(opcd, stk):
- assert len(stk) >= 2
- bop = stk.pop()
- aop = stk.pop()
- argdict, result_kind, func, rank, sym = binop_rules[opcd]
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- resop = Operand(result_kind, None, rank, otext)
- try:
- bconv = argdict[bop.kind]
- aconv = argdict[aop.kind]
- except KeyError:
- stk.append(resop)
- return
- if bop.value is None or aop.value is None:
- stk.append(resop)
- return
- bval = bconv(bop.value)
- aval = aconv(aop.value)
- result = func(aval, bval)
- if result_kind == oBOOL:
- result = intbool(result) # -> 1 or 0
- resop.value = result
- stk.append(resop)
-
- def do_unaryop(opcode, arglist, result_kind, stk):
- assert len(stk) >= 1
- aop = stk.pop()
- assert aop.kind in arglist
- val = aop.value
- func, rank, sym1, sym2 = unop_rules[opcode]
- otext = ''.join([
- sym1,
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym2,
- ])
- if val is not None:
- val = func(val)
- stk.append(Operand(result_kind, val, rank, otext))
-
- def not_in_name_formula(op_arg, oname_arg):
- msg = "ERROR *** Token 0x%02x (%s) found in NAME formula" \
- % (op_arg, oname_arg)
- raise FormulaError(msg)
-
- if fmlalen == 0:
- stack = [unk_opnd]
-
- while 0 <= pos < fmlalen:
- op = ord(data[pos])
- opcode = op & 0x1f
- optype = (op & 0x60) >> 5
- if optype:
- opx = opcode + 32
- else:
- opx = opcode
- oname = onames[opx] # + [" RVA"][optype]
- sz = sztab[opx]
- if blah:
- print "Pos:%d Op:0x%02x Name:t%s Sz:%d opcode:%02xh optype:%02xh" \
- % (pos, op, oname, sz, opcode, optype)
- print "Stack =", stack
- if sz == -2:
- msg = 'ERROR *** Unexpected token 0x%02x ("%s"); biff_version=%d' \
- % (op, oname, bv)
- raise FormulaError(msg)
- if not optype:
- if 0x00 <= opcode <= 0x02: # unk_opnd, tExp, tTbl
- not_in_name_formula(op, oname)
- elif 0x03 <= opcode <= 0x0E:
- # Add, Sub, Mul, Div, Power
- # tConcat
- # tLT, ..., tNE
- do_binop(opcode, stack)
- elif opcode == 0x0F: # tIsect
- if blah: print >> bk.logfile, "tIsect pre", stack
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- sym = ' '
- rank = 80 ########## check #######
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- res = Operand(oREF)
- res.text = otext
- if bop.kind == oERR or aop.kind == oERR:
- res.kind = oERR
- elif bop.kind == oUNK or aop.kind == oUNK:
- # This can happen with undefined
- # (go search in the current sheet) labels.
- # For example =Bob Sales
- # Each label gets a NAME record with an empty formula (!)
- # Evaluation of the tName token classifies it as oUNK
- # res.kind = oREF
- pass
- elif bop.kind == oREF == aop.kind:
- if aop.value is not None and bop.value is not None:
- assert len(aop.value) == 1
- assert len(bop.value) == 1
- coords = do_box_funcs(
- tIsectFuncs, aop.value[0], bop.value[0])
- res.value = [Ref3D(coords)]
- elif bop.kind == oREL == aop.kind:
- res.kind = oREL
- if aop.value is not None and bop.value is not None:
- assert len(aop.value) == 1
- assert len(bop.value) == 1
- coords = do_box_funcs(
- tIsectFuncs, aop.value[0], bop.value[0])
- relfa = aop.value[0].relflags
- relfb = bop.value[0].relflags
- if relfa == relfb:
- res.value = [Ref3D(coords + relfa)]
- else:
- pass
- spush(res)
- if blah: print >> bk.logfile, "tIsect post", stack
- elif opcode == 0x10: # tList
- if blah: print >> bk.logfile, "tList pre", stack
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- sym = ','
- rank = 80 ########## check #######
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- res = Operand(oREF, None, rank, otext)
- if bop.kind == oERR or aop.kind == oERR:
- res.kind = oERR
- elif bop.kind in (oREF, oREL) and aop.kind in (oREF, oREL):
- res.kind = oREF
- if aop.kind == oREL or bop.kind == oREL:
- res.kind = oREL
- if aop.value is not None and bop.value is not None:
- assert len(aop.value) >= 1
- assert len(bop.value) == 1
- res.value = aop.value + bop.value
- else:
- pass
- spush(res)
- if blah: print >> bk.logfile, "tList post", stack
- elif opcode == 0x11: # tRange
- if blah: print >> bk.logfile, "tRange pre", stack
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- sym = ':'
- rank = 80 ########## check #######
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- res = Operand(oREF, None, rank, otext)
- if bop.kind == oERR or aop.kind == oERR:
- res = oERR
- elif bop.kind == oREF == aop.kind:
- if aop.value is not None and bop.value is not None:
- assert len(aop.value) == 1
- assert len(bop.value) == 1
- coords = do_box_funcs(
- tRangeFuncs, aop.value[0], bop.value[0])
- res.value = [Ref3D(coords)]
- elif bop.kind == oREL == aop.kind:
- res.kind = oREL
- if aop.value is not None and bop.value is not None:
- assert len(aop.value) == 1
- assert len(bop.value) == 1
- coords = do_box_funcs(
- tRangeFuncs, aop.value[0], bop.value[0])
- relfa = aop.value[0].relflags
- relfb = bop.value[0].relflags
- if relfa == relfb:
- res.value = [Ref3D(coords + relfa)]
- else:
- pass
- spush(res)
- if blah: print >> bk.logfile, "tRange post", stack
- elif 0x12 <= opcode <= 0x14: # tUplus, tUminus, tPercent
- do_unaryop(opcode, (oUNK, oNUM,), oNUM, stack)
- elif opcode == 0x15: # tParen
- # source cosmetics
- pass
- elif opcode == 0x16: # tMissArg
- spush(Operand(oMSNG, None, LEAF_RANK, ''))
- elif opcode == 0x17: # tStr
- if bv <= 70:
- strg, newpos = unpack_string_update_pos(
- data, pos+1, bk.encoding, lenlen=1)
- else:
- strg, newpos = unpack_unicode_update_pos(
- data, pos+1, lenlen=1)
- sz = newpos - pos
- if blah: print >> bk.logfile, " sz=%d strg=%r" % (sz, strg)
- text = '"' + strg.replace('"', '""') + '"'
- spush(Operand(oSTRG, strg, LEAF_RANK, text))
- elif opcode == 0x18: # tExtended
- # new with BIFF 8
- assert bv >= 80
- # not in OOo docs
- raise FormulaError("tExtended token not implemented")
- elif opcode == 0x19: # tAttr
- subop, nc = unpack("<BH", data[pos+1:pos+4])
- subname = tAttrNames.get(subop, "??Unknown??")
- if subop == 0x04: # Choose
- sz = nc * 2 + 6
- elif subop == 0x10: # Sum (single arg)
- sz = 4
- if blah: print >> bk.logfile, "tAttrSum", stack
- assert len(stack) >= 1
- aop = stack[-1]
- otext = 'SUM(%s)' % aop.text
- stack[-1] = Operand(oNUM, None, FUNC_RANK, otext)
- else:
- sz = 4
- if blah:
- print " subop=%02xh subname=t%s sz=%d nc=%02xh" \
- % (subop, subname, sz, nc)
- elif 0x1A <= opcode <= 0x1B: # tSheet, tEndSheet
- assert bv < 50
- raise FormulaError("tSheet & tEndsheet tokens not implemented")
- elif 0x1C <= opcode <= 0x1F: # tErr, tBool, tInt, tNum
- inx = opcode - 0x1C
- nb = [1, 1, 2, 8][inx]
- kind = [oERR, oBOOL, oNUM, oNUM][inx]
- value, = unpack("<" + "BBHd"[inx], data[pos+1:pos+1+nb])
- if inx == 2: # tInt
- value = float(value)
- text = str(value)
- elif inx == 3: # tNum
- text = str(value)
- elif inx == 1: # tBool
- text = ('FALSE', 'TRUE')[value]
- else:
- text = '"' +error_text_from_code[value] + '"'
- spush(Operand(kind, value, LEAF_RANK, text))
- else:
- raise FormulaError("Unhandled opcode: 0x%02x" % opcode)
- if sz <= 0:
- raise FormulaError("Size not set for opcode 0x%02x" % opcode)
- pos += sz
- continue
- if opcode == 0x00: # tArray
- spush(unk_opnd)
- elif opcode == 0x01: # tFunc
- nb = 1 + int(bv >= 40)
- funcx = unpack("<" + " BH"[nb], data[pos+1:pos+1+nb])[0]
- func_attrs = func_defs.get(funcx, None)
- if not func_attrs:
- print >> bk.logfile, "*** formula/tFunc unknown FuncID:%d" \
- % funcx
- spush(unk_opnd)
- else:
- func_name, nargs = func_attrs[:2]
- if blah:
- print " FuncID=%d name=%s nargs=%d" \
- % (funcx, func_name, nargs)
- assert len(stack) >= nargs
- argtext = listsep.join([arg.text for arg in stack[-nargs:]])
- otext = "%s(%s)" % (func_name, argtext)
- del stack[-nargs:]
- res = Operand(oUNK, None, FUNC_RANK, otext)
- spush(res)
- elif opcode == 0x02: #tFuncVar
- nb = 1 + int(bv >= 40)
- nargs, funcx = unpack("<B" + " BH"[nb], data[pos+1:pos+2+nb])
- prompt, nargs = divmod(nargs, 128)
- macro, funcx = divmod(funcx, 32768)
- if blah:
- print " FuncID=%d nargs=%d macro=%d prompt=%d" \
- % (funcx, nargs, macro, prompt)
- func_attrs = func_defs.get(funcx, None)
- if not func_attrs:
- print >> bk.logfile, "*** formula/tFuncVar unknown FuncID:%d" \
- % funcx
- spush(unk_opnd)
- else:
- func_name, minargs, maxargs = func_attrs[:3]
- if blah:
- print " name: %r, min~max args: %d~%d" \
- % (func_name, minargs, maxargs)
- assert minargs <= nargs <= maxargs
- assert len(stack) >= nargs
- assert len(stack) >= nargs
- argtext = listsep.join([arg.text for arg in stack[-nargs:]])
- otext = "%s(%s)" % (func_name, argtext)
- res = Operand(oUNK, None, FUNC_RANK, otext)
- if funcx == 1: # IF
- testarg = stack[-nargs]
- if testarg.kind not in (oNUM, oBOOL):
- if blah and testarg.kind != oUNK:
- print "IF testarg kind?"
- elif testarg.value not in (0, 1):
- if blah and testarg.value is not None:
- print "IF testarg value?"
- else:
- if nargs == 2 and not testarg.value:
- # IF(FALSE, tv) => FALSE
- res.kind, res.value = oBOOL, 0
- else:
- respos = -nargs + 2 - int(testarg.value)
- chosen = stack[respos]
- if chosen.kind == oMSNG:
- res.kind, res.value = oNUM, 0
- else:
- res.kind, res.value = chosen.kind, chosen.value
- if blah:
- print "$$$$$$ IF => constant"
- elif funcx == 100: # CHOOSE
- testarg = stack[-nargs]
- if testarg.kind == oNUM:
- if 1 <= testarg.value < nargs:
- chosen = stack[-nargs + int(testarg.value)]
- if chosen.kind == oMSNG:
- res.kind, res.value = oNUM, 0
- else:
- res.kind, res.value = chosen.kind, chosen.value
- del stack[-nargs:]
- spush(res)
- elif opcode == 0x03: #tName
- tgtnamex = unpack("<H", data[pos+1:pos+3])[0] - 1
- # Only change with BIFF version is number of trailing UNUSED bytes!
- if blah: print >> bk.logfile, " tgtnamex=%d" % tgtnamex
- tgtobj = bk.name_obj_list[tgtnamex]
- if not tgtobj.evaluated:
- ### recursive ###
- evaluate_name_formula(bk, tgtobj, tgtnamex, blah, level+1)
- if tgtobj.macro or tgtobj.binary \
- or tgtobj.any_err:
- if blah:
- tgtobj.dump(
- bk.logfile,
- header="!!! tgtobj has problems!!!",
- footer="----------- --------",
- )
- res = Operand(oUNK, None)
- any_err = any_err or tgtobj.macro or tgtobj.binary or tgtobj.any_err
- any_rel = any_rel or tgtobj.any_rel
- else:
- assert len(tgtobj.stack) == 1
- res = copy.deepcopy(tgtobj.stack[0])
- res.rank = LEAF_RANK
- if tgtobj.scope == -1:
- res.text = tgtobj.name
- else:
- res.text = "%s!%s" \
- % (bk._sheet_names[tgtobj.scope], tgtobj.name)
- if blah:
- print >> bk.logfile, " tName: setting text to", repr(res.text)
- spush(res)
- elif opcode == 0x04: # tRef
- # not_in_name_formula(op, oname)
- res = get_cell_addr(data, pos+1, bv, reldelta)
- if blah: print >> bk.logfile, " ", res
- rowx, colx, row_rel, col_rel = res
- shx1 = shx2 = 0 ####### N.B. relative to the CURRENT SHEET
- any_rel = 1
- coords = (shx1, shx2+1, rowx, rowx+1, colx, colx+1)
- if blah: print >> bk.logfile, " ", coords
- res = Operand(oUNK, None)
- if optype == 1:
- relflags = (1, 1, row_rel, row_rel, col_rel, col_rel)
- res = Operand(oREL, [Ref3D(coords + relflags)])
- spush(res)
- elif opcode == 0x05: # tArea
- # not_in_name_formula(op, oname)
- res1, res2 = get_cell_range_addr(data, pos+1, bv, reldelta)
- if blah: print >> bk.logfile, " ", res1, res2
- rowx1, colx1, row_rel1, col_rel1 = res1
- rowx2, colx2, row_rel2, col_rel2 = res2
- shx1 = shx2 = 0 ####### N.B. relative to the CURRENT SHEET
- any_rel = 1
- coords = (shx1, shx2+1, rowx1, rowx2+1, colx1, colx2+1)
- if blah: print >> bk.logfile, " ", coords
- res = Operand(oUNK, None)
- if optype == 1:
- relflags = (1, 1, row_rel1, row_rel2, col_rel1, col_rel2)
- res = Operand(oREL, [Ref3D(coords + relflags)])
- spush(res)
- elif opcode == 0x06: # tMemArea
- not_in_name_formula(op, oname)
- elif opcode == 0x09: # tMemFunc
- nb = unpack("<H", data[pos+1:pos+3])[0]
- if blah: print >> bk.logfile, " %d bytes of cell ref formula" % nb
- # no effect on stack
- elif opcode == 0x0C: #tRefN
- not_in_name_formula(op, oname)
- # res = get_cell_addr(data, pos+1, bv, reldelta=1)
- # # note *ALL* tRefN usage has signed offset for relative addresses
- # any_rel = 1
- # if blah: print >> bk.logfile, " ", res
- # spush(res)
- elif opcode == 0x0D: #tAreaN
- not_in_name_formula(op, oname)
- # res = get_cell_range_addr(data, pos+1, bv, reldelta=1)
- # # note *ALL* tAreaN usage has signed offset for relative addresses
- # any_rel = 1
- # if blah: print >> bk.logfile, " ", res
- elif opcode == 0x1A: # tRef3d
- if bv >= 80:
- res = get_cell_addr(data, pos+3, bv, reldelta)
- refx = unpack("<H", data[pos+1:pos+3])[0]
- shx1, shx2 = get_externsheet_local_range(bk, refx, blah)
- else:
- res = get_cell_addr(data, pos+15, bv, reldelta)
- raw_extshtx, raw_shx1, raw_shx2 = \
- unpack("<hxxxxxxxxhh", data[pos+1:pos+15])
- if blah:
- print >> bk.logfile, "tRef3d", raw_extshtx, raw_shx1, raw_shx2
- shx1, shx2 = get_externsheet_local_range_b57(
- bk, raw_extshtx, raw_shx1, raw_shx2, blah)
- rowx, colx, row_rel, col_rel = res
- is_rel = row_rel or col_rel
- any_rel = any_rel or is_rel
- coords = (shx1, shx2+1, rowx, rowx+1, colx, colx+1)
- any_err |= shx1 < -1
- if blah: print >> bk.logfile, " ", coords
- res = Operand(oUNK, None)
- if is_rel:
- relflags = (0, 0, row_rel, row_rel, col_rel, col_rel)
- ref3d = Ref3D(coords + relflags)
- res.kind = oREL
- res.text = rangename3drel(bk, ref3d)
- else:
- ref3d = Ref3D(coords)
- res.kind = oREF
- res.text = rangename3d(bk, ref3d)
- res.rank = LEAF_RANK
- if optype == 1:
- res.value = [ref3d]
- spush(res)
- elif opcode == 0x1B: # tArea3d
- if bv >= 80:
- res1, res2 = get_cell_range_addr(data, pos+3, bv, reldelta)
- refx = unpack("<H", data[pos+1:pos+3])[0]
- shx1, shx2 = get_externsheet_local_range(bk, refx, blah)
- else:
- res1, res2 = get_cell_range_addr(data, pos+15, bv, reldelta)
- raw_extshtx, raw_shx1, raw_shx2 = \
- unpack("<hxxxxxxxxhh", data[pos+1:pos+15])
- if blah:
- print >> bk.logfile, "tArea3d", raw_extshtx, raw_shx1, raw_shx2
- shx1, shx2 = get_externsheet_local_range_b57(
- bk, raw_extshtx, raw_shx1, raw_shx2, blah)
- any_err |= shx1 < -1
- rowx1, colx1, row_rel1, col_rel1 = res1
- rowx2, colx2, row_rel2, col_rel2 = res2
- is_rel = row_rel1 or col_rel1 or row_rel2 or col_rel2
- any_rel = any_rel or is_rel
- coords = (shx1, shx2+1, rowx1, rowx2+1, colx1, colx2+1)
- if blah: print >> bk.logfile, " ", coords
- res = Operand(oUNK, None)
- if is_rel:
- relflags = (0, 0, row_rel1, row_rel2, col_rel1, col_rel2)
- ref3d = Ref3D(coords + relflags)
- res.kind = oREL
- res.text = rangename3drel(bk, ref3d)
- else:
- ref3d = Ref3D(coords)
- res.kind = oREF
- res.text = rangename3d(bk, ref3d)
- res.rank = LEAF_RANK
- if optype == 1:
- res.value = [ref3d]
-
- spush(res)
- elif opcode == 0x19: # tNameX
- dodgy = 0
- res = Operand(oUNK, None)
- if bv >= 80:
- refx, tgtnamex = unpack("<HH", data[pos+1:pos+5])
- tgtnamex -= 1
- origrefx = refx
- else:
- refx, tgtnamex = unpack("<hxxxxxxxxH", data[pos+1:pos+13])
- tgtnamex -= 1
- origrefx = refx
- if refx > 0:
- refx -= 1
- elif refx < 0:
- refx = -refx - 1
- else:
- dodgy = 1
- if blah:
- print >> bk.logfile, \
- " origrefx=%d refx=%d tgtnamex=%d dodgy=%d" \
- % (origrefx, refx, tgtnamex, dodgy)
- if tgtnamex == namex:
- if blah: print >> bk.logfile, "!!!! Self-referential !!!!"
- dodgy = any_err = 1
- if not dodgy:
- if bv >= 80:
- shx1, shx2 = get_externsheet_local_range(bk, refx, blah)
- elif origrefx > 0:
- shx1, shx2 = (-4, -4) # external ref
- else:
- exty = bk._externsheet_type_b57[refx]
- if exty == 4: # non-specific sheet in own doc't
- shx1, shx2 = (-1, -1) # internal, any sheet
- else:
- shx1, shx2 = (-666, -666)
- if dodgy or shx1 < -1:
- otext = "<<Name #%d in external(?) file #%d>>" \
- % (tgtnamex, origrefx)
- res = Operand(oUNK, None, LEAF_RANK, otext)
- else:
- tgtobj = bk.name_obj_list[tgtnamex]
- if not tgtobj.evaluated:
- ### recursive ###
- evaluate_name_formula(bk, tgtobj, tgtnamex, blah, level+1)
- if tgtobj.macro or tgtobj.binary \
- or tgtobj.any_err:
- if blah:
- tgtobj.dump(
- bk.logfile,
- header="!!! bad tgtobj !!!",
- footer="------------------",
- )
- res = Operand(oUNK, None)
- any_err = any_err or tgtobj.macro or tgtobj.binary or tgtobj.any_err
- any_rel = any_rel or tgtobj.any_rel
- else:
- assert len(tgtobj.stack) == 1
- res = copy.deepcopy(tgtobj.stack[0])
- res.rank = LEAF_RANK
- if tgtobj.scope == -1:
- res.text = tgtobj.name
- else:
- res.text = "%s!%s" \
- % (bk._sheet_names[tgtobj.scope], tgtobj.name)
- if blah:
- print >> bk.logfile, " tNameX: setting text to", repr(res.text)
- spush(res)
- elif is_error_opcode(opcode):
- any_err = 1
- spush(error_opnd)
- else:
- if blah:
- print >> bk.logfile, "FORMULA: /// Not handled yet: t" + oname
- any_err = 1
- if sz <= 0:
- raise FormulaError("Fatal: token size is not positive")
- pos += sz
- any_rel = not not any_rel
- if blah:
- print "End of formula. level=%d any_rel=%d any_err=%d stack=%r" % \
- (level, not not any_rel, any_err, stack)
- if len(stack) >= 2:
- print "*** Stack has unprocessed args"
- print
- nobj.stack = stack
- if len(stack) != 1:
- nobj.result = None
- else:
- nobj.result = stack[0]
- nobj.any_rel = any_rel
- nobj.any_err = any_err
- nobj.any_external = any_external
- nobj.evaluated = 1
-
-#### under construction ####
-def decompile_formula(bk, fmla, fmlalen,
- reldelta, browx=None, bcolx=None,
- # browx & bcolx are required when reldelta == 0
- blah=0, level=0):
- if level > STACK_ALARM_LEVEL:
- blah = 1
- data = fmla
- bv = bk.biff_version
- if blah:
- print "::: decompile_formula len=%d reldelta=%d %r level=%d" \
- % (fmlalen, reldelta, data, level)
- hex_char_dump(data, 0, fmlalen)
- if level > STACK_PANIC_LEVEL:
- raise XLRDError("Excessive indirect references in formula")
- sztab = szdict[bv]
- pos = 0
- stack = []
- any_rel = 0
- any_err = 0
- any_external = 0
- unk_opnd = Operand(oUNK, None)
- error_opnd = Operand(oERR, None)
- spush = stack.append
-
- def do_binop(opcd, stk):
- assert len(stk) >= 2
- bop = stk.pop()
- aop = stk.pop()
- argdict, result_kind, func, rank, sym = binop_rules[opcd]
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- resop = Operand(result_kind, None, rank, otext)
- stk.append(resop)
-
- def do_unaryop(opcode, arglist, result_kind, stk):
- assert len(stk) >= 1
- aop = stk.pop()
- assert aop.kind in arglist
- func, rank, sym1, sym2 = unop_rules[opcode]
- otext = ''.join([
- sym1,
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym2,
- ])
- stk.append(Operand(result_kind, None, rank, otext))
-
- def not_in_name_formula(op_arg, oname_arg):
- msg = "ERROR *** Unexpected token 0x%02x (%s) found in formula" \
- % (op_arg, oname_arg)
- # print msg
- raise FormulaError(msg)
-
- if fmlalen == 0:
- stack = [unk_opnd]
-
- while 0 <= pos < fmlalen:
- op = ord(data[pos])
- opcode = op & 0x1f
- optype = (op & 0x60) >> 5
- if optype:
- opx = opcode + 32
- else:
- opx = opcode
- oname = onames[opx] # + [" RVA"][optype]
- sz = sztab[opx]
- if blah:
- print "Pos:%d Op:0x%02x opname:t%s Sz:%d opcode:%02xh optype:%02xh" \
- % (pos, op, oname, sz, opcode, optype)
- print "Stack =", stack
- if sz == -2:
- msg = 'ERROR *** Unexpected token 0x%02x ("%s"); biff_version=%d' \
- % (op, oname, bv)
- raise FormulaError(msg)
- if not optype:
- if 0x00 <= opcode <= 0x02: # unk_opnd, tExp, tTbl
- not_in_name_formula(op, oname)
- elif 0x03 <= opcode <= 0x0E:
- # Add, Sub, Mul, Div, Power
- # tConcat
- # tLT, ..., tNE
- do_binop(opcode, stack)
- elif opcode == 0x0F: # tIsect
- if blah: print >> bk.logfile, "tIsect pre", stack
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- sym = ' '
- rank = 80 ########## check #######
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- res = Operand(oREF)
- res.text = otext
- if bop.kind == oERR or aop.kind == oERR:
- res.kind = oERR
- elif bop.kind == oUNK or aop.kind == oUNK:
- # This can happen with undefined
- # (go search in the current sheet) labels.
- # For example =Bob Sales
- # Each label gets a NAME record with an empty formula (!)
- # Evaluation of the tName token classifies it as oUNK
- # res.kind = oREF
- pass
- elif bop.kind == oREF == aop.kind:
- pass
- elif bop.kind == oREL == aop.kind:
- res.kind = oREL
- else:
- pass
- spush(res)
- if blah: print >> bk.logfile, "tIsect post", stack
- elif opcode == 0x10: # tList
- if blah: print >> bk.logfile, "tList pre", stack
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- sym = ','
- rank = 80 ########## check #######
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- res = Operand(oREF, None, rank, otext)
- if bop.kind == oERR or aop.kind == oERR:
- res.kind = oERR
- elif bop.kind in (oREF, oREL) and aop.kind in (oREF, oREL):
- res.kind = oREF
- if aop.kind == oREL or bop.kind == oREL:
- res.kind = oREL
- else:
- pass
- spush(res)
- if blah: print >> bk.logfile, "tList post", stack
- elif opcode == 0x11: # tRange
- if blah: print >> bk.logfile, "tRange pre", stack
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- sym = ':'
- rank = 80 ########## check #######
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- res = Operand(oREF, None, rank, otext)
- if bop.kind == oERR or aop.kind == oERR:
- res = oERR
- elif bop.kind == oREF == aop.kind:
- pass
- else:
- pass
- spush(res)
- if blah: print >> bk.logfile, "tRange post", stack
- elif 0x12 <= opcode <= 0x14: # tUplus, tUminus, tPercent
- do_unaryop(opcode, (oUNK, oNUM,), oNUM, stack)
- elif opcode == 0x15: # tParen
- # source cosmetics
- pass
- elif opcode == 0x16: # tMissArg
- spush(Operand(oMSNG, None, LEAF_RANK, ''))
- elif opcode == 0x17: # tStr
- if bv <= 70:
- strg, newpos = unpack_string_update_pos(
- data, pos+1, bk.encoding, lenlen=1)
- else:
- strg, newpos = unpack_unicode_update_pos(
- data, pos+1, lenlen=1)
- sz = newpos - pos
- if blah: print >> bk.logfile, " sz=%d strg=%r" % (sz, strg)
- text = '"' + strg.replace('"', '""') + '"'
- spush(Operand(oSTRG, None, LEAF_RANK, text))
- elif opcode == 0x18: # tExtended
- # new with BIFF 8
- assert bv >= 80
- # not in OOo docs
- raise FormulaError("tExtended token not implemented")
- elif opcode == 0x19: # tAttr
- subop, nc = unpack("<BH", data[pos+1:pos+4])
- subname = tAttrNames.get(subop, "??Unknown??")
- if subop == 0x04: # Choose
- sz = nc * 2 + 6
- elif subop == 0x10: # Sum (single arg)
- sz = 4
- if blah: print >> bk.logfile, "tAttrSum", stack
- assert len(stack) >= 1
- aop = stack[-1]
- otext = 'SUM(%s)' % aop.text
- stack[-1] = Operand(oNUM, None, FUNC_RANK, otext)
- else:
- sz = 4
- if blah:
- print " subop=%02xh subname=t%s sz=%d nc=%02xh" \
- % (subop, subname, sz, nc)
- elif 0x1A <= opcode <= 0x1B: # tSheet, tEndSheet
- assert bv < 50
- raise FormulaError("tSheet & tEndsheet tokens not implemented")
- elif 0x1C <= opcode <= 0x1F: # tErr, tBool, tInt, tNum
- inx = opcode - 0x1C
- nb = [1, 1, 2, 8][inx]
- kind = [oERR, oBOOL, oNUM, oNUM][inx]
- value, = unpack("<" + "BBHd"[inx], data[pos+1:pos+1+nb])
- if inx == 2: # tInt
- value = float(value)
- text = str(value)
- elif inx == 3: # tNum
- text = str(value)
- elif inx == 1: # tBool
- text = ('FALSE', 'TRUE')[value]
- else:
- text = '"' +error_text_from_code[value] + '"'
- spush(Operand(kind, None, LEAF_RANK, text))
- else:
- raise FormulaError("Unhandled opcode: 0x%02x" % opcode)
- if sz <= 0:
- raise FormulaError("Size not set for opcode 0x%02x" % opcode)
- pos += sz
- continue
- if opcode == 0x00: # tArray
- spush(unk_opnd)
- elif opcode == 0x01: # tFunc
- nb = 1 + int(bv >= 40)
- funcx = unpack("<" + " BH"[nb], data[pos+1:pos+1+nb])[0]
- func_attrs = func_defs.get(funcx, None)
- if not func_attrs:
- print >> bk.logfile, "*** formula/tFunc unknown FuncID:%d" % funcx
- spush(unk_opnd)
- else:
- func_name, nargs = func_attrs[:2]
- if blah:
- print " FuncID=%d name=%s nargs=%d" \
- % (funcx, func_name, nargs)
- assert len(stack) >= nargs
- argtext = listsep.join([arg.text for arg in stack[-nargs:]])
- otext = "%s(%s)" % (func_name, argtext)
- del stack[-nargs:]
- res = Operand(oUNK, None, FUNC_RANK, otext)
- spush(res)
- elif opcode == 0x02: #tFuncVar
- nb = 1 + int(bv >= 40)
- nargs, funcx = unpack("<B" + " BH"[nb], data[pos+1:pos+2+nb])
- prompt, nargs = divmod(nargs, 128)
- macro, funcx = divmod(funcx, 32768)
- if blah:
- print " FuncID=%d nargs=%d macro=%d prompt=%d" \
- % (funcx, nargs, macro, prompt)
- #### TODO #### if funcx == 255: # call add-in function
- if funcx == 255:
- func_attrs = ("CALL_ADDIN", 1, 30)
- else:
- func_attrs = func_defs.get(funcx, None)
- if not func_attrs:
- print >> bk.logfile, "*** formula/tFuncVar unknown FuncID:%d" \
- % funcx
- spush(unk_opnd)
- else:
- func_name, minargs, maxargs = func_attrs[:3]
- if blah:
- print " name: %r, min~max args: %d~%d" \
- % (func_name, minargs, maxargs)
- assert minargs <= nargs <= maxargs
- assert len(stack) >= nargs
- assert len(stack) >= nargs
- argtext = listsep.join([arg.text for arg in stack[-nargs:]])
- otext = "%s(%s)" % (func_name, argtext)
- res = Operand(oUNK, None, FUNC_RANK, otext)
- del stack[-nargs:]
- spush(res)
- elif opcode == 0x03: #tName
- tgtnamex = unpack("<H", data[pos+1:pos+3])[0] - 1
- # Only change with BIFF version is number of trailing UNUSED bytes!
- if blah: print >> bk.logfile, " tgtnamex=%d" % tgtnamex
- tgtobj = bk.name_obj_list[tgtnamex]
- if tgtobj.scope == -1:
- otext = tgtobj.name
- else:
- otext = "%s!%s" % (bk._sheet_names[tgtobj.scope], tgtobj.name)
- if blah:
- print >> bk.logfile, " tName: setting text to", repr(otext)
- res = Operand(oUNK, None, LEAF_RANK, otext)
- spush(res)
- elif opcode == 0x04: # tRef
- res = get_cell_addr(data, pos+1, bv, reldelta, browx, bcolx)
- if blah: print >> bk.logfile, " ", res
- rowx, colx, row_rel, col_rel = res
- is_rel = row_rel or col_rel
- if is_rel:
- okind = oREL
- else:
- okind = oREF
- otext = cellnamerel(rowx, colx, row_rel, col_rel)
- res = Operand(okind, None, LEAF_RANK, otext)
- spush(res)
- elif opcode == 0x05: # tArea
- res1, res2 = get_cell_range_addr(
- data, pos+1, bv, reldelta, browx, bcolx)
- if blah: print >> bk.logfile, " ", res1, res2
- rowx1, colx1, row_rel1, col_rel1 = res1
- rowx2, colx2, row_rel2, col_rel2 = res2
- coords = (rowx1, rowx2+1, colx1, colx2+1)
- relflags = (row_rel1, row_rel2, col_rel1, col_rel2)
- is_rel = intbool(sum(relflags))
- if is_rel:
- okind = oREL
- else:
- okind = oREF
- if blah: print >> bk.logfile, " ", coords, relflags
- otext = rangename2drel(coords, relflags)
- res = Operand(okind, None, LEAF_RANK, otext)
- spush(res)
- elif opcode == 0x06: # tMemArea
- not_in_name_formula(op, oname)
- elif opcode == 0x09: # tMemFunc
- nb = unpack("<H", data[pos+1:pos+3])[0]
- if blah: print >> bk.logfile, " %d bytes of cell ref formula" % nb
- # no effect on stack
- elif opcode == 0x0C: #tRefN
- not_in_name_formula(op, oname)
- # res = get_cell_addr(data, pos+1, bv, reldelta=1)
- # # note *ALL* tRefN usage has signed offset for relative addresses
- # any_rel = 1
- # if blah: print >> bk.logfile, " ", res
- # spush(res)
- elif opcode == 0x0D: #tAreaN
- not_in_name_formula(op, oname)
- # res = get_cell_range_addr(data, pos+1, bv, reldelta=1)
- # # note *ALL* tAreaN usage has signed offset for relative addresses
- # any_rel = 1
- # if blah: print >> bk.logfile, " ", res
- elif opcode == 0x1A: # tRef3d
- if bv >= 80:
- res = get_cell_addr(data, pos+3, bv, reldelta, browx, bcolx)
- refx = unpack("<H", data[pos+1:pos+3])[0]
- shx1, shx2 = get_externsheet_local_range(bk, refx, blah)
- else:
- res = get_cell_addr(data, pos+15, bv, reldelta, browx, bcolx)
- raw_extshtx, raw_shx1, raw_shx2 = \
- unpack("<hxxxxxxxxhh", data[pos+1:pos+15])
- if blah:
- print >> bk.logfile, "tRef3d", raw_extshtx, raw_shx1, raw_shx2
- shx1, shx2 = get_externsheet_local_range_b57(
- bk, raw_extshtx, raw_shx1, raw_shx2, blah)
- rowx, colx, row_rel, col_rel = res
- is_rel = row_rel or col_rel
- any_rel = any_rel or is_rel
- coords = (shx1, shx2+1, rowx, rowx+1, colx, colx+1)
- any_err |= shx1 < -1
- if blah: print >> bk.logfile, " ", coords
- res = Operand(oUNK, None)
- if is_rel:
- relflags = (0, 0, row_rel, row_rel, col_rel, col_rel)
- ref3d = Ref3D(coords + relflags)
- res.kind = oREL
- res.text = rangename3drel(bk, ref3d)
- else:
- ref3d = Ref3D(coords)
- res.kind = oREF
- res.text = rangename3d(bk, ref3d)
- res.rank = LEAF_RANK
- res.value = None
- spush(res)
- elif opcode == 0x1B: # tArea3d
- if bv >= 80:
- res1, res2 = get_cell_range_addr(data, pos+3, bv, reldelta)
- refx = unpack("<H", data[pos+1:pos+3])[0]
- shx1, shx2 = get_externsheet_local_range(bk, refx, blah)
- else:
- res1, res2 = get_cell_range_addr(data, pos+15, bv, reldelta)
- raw_extshtx, raw_shx1, raw_shx2 = \
- unpack("<hxxxxxxxxhh", data[pos+1:pos+15])
- if blah:
- print >> bk.logfile, "tArea3d", raw_extshtx, raw_shx1, raw_shx2
- shx1, shx2 = get_externsheet_local_range_b57(
- bk, raw_extshtx, raw_shx1, raw_shx2, blah)
- any_err |= shx1 < -1
- rowx1, colx1, row_rel1, col_rel1 = res1
- rowx2, colx2, row_rel2, col_rel2 = res2
- is_rel = row_rel1 or col_rel1 or row_rel2 or col_rel2
- any_rel = any_rel or is_rel
- coords = (shx1, shx2+1, rowx1, rowx2+1, colx1, colx2+1)
- if blah: print >> bk.logfile, " ", coords
- res = Operand(oUNK, None)
- if is_rel:
- relflags = (0, 0, row_rel1, row_rel2, col_rel1, col_rel2)
- ref3d = Ref3D(coords + relflags)
- res.kind = oREL
- res.text = rangename3drel(bk, ref3d)
- else:
- ref3d = Ref3D(coords)
- res.kind = oREF
- res.text = rangename3d(bk, ref3d)
- res.rank = LEAF_RANK
- spush(res)
- elif opcode == 0x19: # tNameX
- dodgy = 0
- res = Operand(oUNK, None)
- if bv >= 80:
- refx, tgtnamex = unpack("<HH", data[pos+1:pos+5])
- tgtnamex -= 1
- origrefx = refx
- else:
- refx, tgtnamex = unpack("<hxxxxxxxxH", data[pos+1:pos+13])
- tgtnamex -= 1
- origrefx = refx
- if refx > 0:
- refx -= 1
- elif refx < 0:
- refx = -refx - 1
- else:
- dodgy = 1
- if blah:
- print >> bk.logfile, \
- " origrefx=%d refx=%d tgtnamex=%d dodgy=%d" \
- % (origrefx, refx, tgtnamex, dodgy)
- # if tgtnamex == namex:
- # if blah: print >> bk.logfile, "!!!! Self-referential !!!!"
- # dodgy = any_err = 1
- if not dodgy:
- if bv >= 80:
- shx1, shx2 = get_externsheet_local_range(bk, refx, blah)
- elif origrefx > 0:
- shx1, shx2 = (-4, -4) # external ref
- else:
- exty = bk._externsheet_type_b57[refx]
- if exty == 4: # non-specific sheet in own doc't
- shx1, shx2 = (-1, -1) # internal, any sheet
- else:
- shx1, shx2 = (-666, -666)
- okind = oUNK
- ovalue = None
- if shx1 == -5: # addin func name
- okind = oSTRG
- ovalue = bk.addin_func_names[tgtnamex]
- otext = '"' + ovalue.replace('"', '""') + '"'
- elif dodgy or shx1 < -1:
- otext = "<<Name #%d in external(?) file #%d>>" \
- % (tgtnamex, origrefx)
- else:
- tgtobj = bk.name_obj_list[tgtnamex]
- if tgtobj.scope == -1:
- otext = tgtobj.name
- else:
- otext = "%s!%s" \
- % (bk._sheet_names[tgtobj.scope], tgtobj.name)
- if blah:
- print >> bk.logfile, " tNameX: setting text to", repr(res.text)
- res = Operand(okind, ovalue, LEAF_RANK, otext)
- spush(res)
- elif is_error_opcode(opcode):
- any_err = 1
- spush(error_opnd)
- else:
- if blah:
- print >> bk.logfile, "FORMULA: /// Not handled yet: t" + oname
- any_err = 1
- if sz <= 0:
- raise FormulaError("Fatal: token size is not positive")
- pos += sz
- any_rel = not not any_rel
- if blah:
- print "End of formula. level=%d any_rel=%d any_err=%d stack=%r" % \
- (level, not not any_rel, any_err, stack)
- if len(stack) >= 2:
- print "*** Stack has unprocessed args"
- print
-
- if len(stack) != 1:
- result = None
- else:
- result = stack[0].text
- return result
-
-#### under deconstruction ###
-def dump_formula(bk, data, fmlalen, bv, reldelta, blah=0, isname=0):
- if blah:
- print "dump_formula", fmlalen, bv, len(data)
- hex_char_dump(data, 0, fmlalen)
- assert bv >= 80 #### this function needs updating ####
- sztab = szdict[bv]
- pos = 0
- stack = []
- any_rel = 0
- any_err = 0
- spush = stack.append
- while 0 <= pos < fmlalen:
- op = ord(data[pos])
- opcode = op & 0x1f
- optype = (op & 0x60) >> 5
- if optype:
- opx = opcode + 32
- else:
- opx = opcode
- oname = onames[opx] # + [" RVA"][optype]
-
- sz = sztab[opx]
- if blah:
- print "Pos:%d Op:0x%02x Name:t%s Sz:%d opcode:%02xh optype:%02xh" \
- % (pos, op, oname, sz, opcode, optype)
- if not optype:
- if 0x01 <= opcode <= 0x02: # tExp, tTbl
- # reference to a shared formula or table record
- rowx, colx = unpack("<HH", data[pos+1:pos+5])
- if blah: print >> bk.logfile, " ", (rowx, colx)
- elif opcode == 0x10: # tList
- if blah: print >> bk.logfile, "tList pre", stack
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- spush(aop + bop)
- if blah: print >> bk.logfile, "tlist post", stack
- elif opcode == 0x11: # tRange
- if blah: print >> bk.logfile, "tRange pre", stack
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- assert len(aop) == 1
- assert len(bop) == 1
- result = do_box_funcs(tRangeFuncs, aop[0], bop[0])
- spush(result)
- if blah: print >> bk.logfile, "tRange post", stack
- elif opcode == 0x0F: # tIsect
- if blah: print >> bk.logfile, "tIsect pre", stack
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- assert len(aop) == 1
- assert len(bop) == 1
- result = do_box_funcs(tIsectFuncs, aop[0], bop[0])
- spush(result)
- if blah: print >> bk.logfile, "tIsect post", stack
- elif opcode == 0x19: # tAttr
- subop, nc = unpack("<BH", data[pos+1:pos+4])
- subname = tAttrNames.get(subop, "??Unknown??")
- if subop == 0x04: # Choose
- sz = nc * 2 + 6
- else:
- sz = 4
- if blah: print >> bk.logfile, " subop=%02xh subname=t%s sz=%d nc=%02xh" % (subop, subname, sz, nc)
- elif opcode == 0x17: # tStr
- if bv <= 70:
- nc = ord(data[pos+1])
- strg = data[pos+2:pos+2+nc] # left in 8-bit encoding
- sz = nc + 2
- else:
- strg, newpos = unpack_unicode_update_pos(data, pos+1, lenlen=1)
- sz = newpos - pos
- if blah: print >> bk.logfile, " sz=%d strg=%r" % (sz, strg)
- else:
- if sz <= 0:
- print "**** Dud size; exiting ****"
- return
- pos += sz
- continue
- if opcode == 0x00: # tArray
- pass
- elif opcode == 0x01: # tFunc
- nb = 1 + int(bv >= 40)
- funcx = unpack("<" + " BH"[nb], data[pos+1:pos+1+nb])
- if blah: print >> bk.logfile, " FuncID=%d" % funcx
- elif opcode == 0x02: #tFuncVar
- nb = 1 + int(bv >= 40)
- nargs, funcx = unpack("<B" + " BH"[nb], data[pos+1:pos+2+nb])
- prompt, nargs = divmod(nargs, 128)
- macro, funcx = divmod(funcx, 32768)
- if blah: print >> bk.logfile, " FuncID=%d nargs=%d macro=%d prompt=%d" % (funcx, nargs, macro, prompt)
- elif opcode == 0x03: #tName
- namex = unpack("<H", data[pos+1:pos+3])
- # Only change with BIFF version is the number of trailing UNUSED bytes!!!
- if blah: print >> bk.logfile, " namex=%d" % namex
- elif opcode == 0x04: # tRef
- res = get_cell_addr(data, pos+1, bv, reldelta)
- if blah: print >> bk.logfile, " ", res
- elif opcode == 0x05: # tArea
- res = get_cell_range_addr(data, pos+1, bv, reldelta)
- if blah: print >> bk.logfile, " ", res
- elif opcode == 0x09: # tMemFunc
- nb = unpack("<H", data[pos+1:pos+3])[0]
- if blah: print >> bk.logfile, " %d bytes of cell ref formula" % nb
- elif opcode == 0x0C: #tRefN
- res = get_cell_addr(data, pos+1, bv, reldelta=1)
- # note *ALL* tRefN usage has signed offset for relative addresses
- any_rel = 1
- if blah: print >> bk.logfile, " ", res
- elif opcode == 0x0D: #tAreaN
- res = get_cell_range_addr(data, pos+1, bv, reldelta=1)
- # note *ALL* tAreaN usage has signed offset for relative addresses
- any_rel = 1
- if blah: print >> bk.logfile, " ", res
- elif opcode == 0x1A: # tRef3d
- refx = unpack("<H", data[pos+1:pos+3])[0]
- res = get_cell_addr(data, pos+3, bv, reldelta)
- if blah: print >> bk.logfile, " ", refx, res
- rowx, colx, row_rel, col_rel = res
- any_rel = any_rel or row_rel or col_rel
- shx1, shx2 = get_externsheet_local_range(bk, refx, blah)
- any_err |= shx1 < -1
- coords = (shx1, shx2+1, rowx, rowx+1, colx, colx+1)
- if blah: print >> bk.logfile, " ", coords
- if optype == 1: spush([coords])
- elif opcode == 0x1B: # tArea3d
- refx = unpack("<H", data[pos+1:pos+3])[0]
- res1, res2 = get_cell_range_addr(data, pos+3, bv, reldelta)
- if blah: print >> bk.logfile, " ", refx, res1, res2
- rowx1, colx1, row_rel1, col_rel1 = res1
- rowx2, colx2, row_rel2, col_rel2 = res2
- any_rel = any_rel or row_rel1 or col_rel1 or row_rel2 or col_rel2
- shx1, shx2 = get_externsheet_local_range(bk, refx, blah)
- any_err |= shx1 < -1
- coords = (shx1, shx2+1, rowx1, rowx2+1, colx1, colx2+1)
- if blah: print >> bk.logfile, " ", coords
- if optype == 1: spush([coords])
- elif opcode == 0x19: # tNameX
- refx, namex = unpack("<HH", data[pos+1:pos+5])
- if blah: print >> bk.logfile, " refx=%d namex=%d" % (refx, namex)
- elif is_error_opcode(opcode):
- any_err = 1
- else:
- if blah: print >> bk.logfile, "FORMULA: /// Not handled yet: t" + oname
- any_err = 1
- if sz <= 0:
- print "**** Dud size; exiting ****"
- return
- pos += sz
- if blah:
- print >> bk.logfile, "End of formula. any_rel=%d any_err=%d stack=%r" % \
- (not not any_rel, any_err, stack)
- if len(stack) >= 2:
- print >> bk.logfile, "*** Stack has unprocessed args"
-
-# === Some helper functions for displaying cell references ===
-
-# Note that a "non-standard" syntax is used in row and column
-# components in relative references.
-# For example, consider a relative reference: up two rows, right 3 columns.
-# On screen, with cursor in cell D10, this would appear as G8.
-# On screen, with cursor in cell Z100, this would appear as AC98.
-# On screen, with cursor in cell A1, this would appear as D65535.
-# These functions will display such a reference as [@+3,#-2].
-# "@" refers to the unknown base column.
-# "#" refers to the unknown base row.
-#
-# I'm aware of only one possibility of a sheet-relative component in
-# a reference: a 2D reference located in the "current sheet".
-# xlrd stores this internally with bounds of (0, 1, ...) and
-# relative flags of (1, 1, ...). These functions display the
-# sheet component as empty, just like Excel etc.
-
-def rownamerel(rowx, rowxrel):
- if not rowxrel:
- return "$%d" % rowx
- if rowx > 0:
- return "#+%d" % rowx
- if rowx < 0:
- return "#-%d" % (-rowx)
- return "#"
-
-def colnamerel(colx, colxrel):
- if not colxrel:
- return "$" + colname(colx)
- if colx > 0:
- return "@+%d" % colx
- if colx < 0:
- return "@-%d" % (-colx)
- return "@"
-##
-# Utility function: (5, 7) => 'H6'
-def cellname(rowx, colx):
- """ (5, 7) => 'H6' """
- return "%s%d" % (colname(colx), rowx+1)
-
-##
-# Utility function: (5, 7) => '$H$6'
-def cellnameabs(rowx, colx):
- """ (5, 7) => '$H$6' """
- return "$%s$%d" % (colname(colx), rowx+1)
-
-def cellnamerel(rowx, colx, rowxrel, colxrel):
- if not rowxrel and not colxrel:
- return cellnameabs(rowx, colx)
- return "[%s,%s]" % (
- colnamerel(colx, colxrel),
- rownamerel(rowx, rowxrel))
-##
-# Utility function: 7 => 'H', 27 => 'AB'
-def colname(colx):
- """ 7 => 'H', 27 => 'AB' """
- alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- if colx <= 25:
- return alphabet[colx]
- else:
- xdiv26, xmod26 = divmod(colx, 26)
- return alphabet[xdiv26 - 1] + alphabet[xmod26]
-
-def rangename2d(rlo, rhi, clo, chi):
- """ (5, 20, 7, 10) => '$H$6:$J$20' """
- if rhi == rlo+1 and chi == clo+1:
- return cellnameabs(rlo, clo)
- return "%s:%s" % (cellnameabs(rlo, clo), cellnameabs(rhi-1, chi-1))
-
-def rangename2drel((rlo, rhi, clo, chi), (rlorel, rhirel, clorel, chirel)):
- return "%s:%s" % (
- cellnamerel(rlo, clo, rlorel, clorel),
- cellnamerel(rhi-1, chi-1, rhirel, chirel)
- )
-##
-# Utility function:
-# <br /> Ref3D((1, 4, 5, 20, 7, 10)) => 'Sheet2:Sheet3!$H$6:$J$20'
-def rangename3d(book, ref3d):
- """ Ref3D(1, 4, 5, 20, 7, 10) => 'Sheet2:Sheet3!$H$6:$J$20'
- (assuming Excel's default sheetnames) """
- coords = ref3d.coords
- return "%s!%s" % (
- sheetrange(book, *coords[:2]),
- rangename2d(*coords[2:6]))
-
-##
-# Utility function:
-# <br /> Ref3D(coords=(0, 1, -32, -22, -13, 13), relflags=(0, 0, 1, 1, 1, 1))
-# => 'Sheet1![@-13,#-32]:[@+12,#-23]'
-# where '@' refers to the current or base column and '#'
-# refers to the current or base row.
-def rangename3drel(book, ref3d):
- coords = ref3d.coords
- relflags = ref3d.relflags
- shdesc = sheetrangerel(book, coords[:2], relflags[:2])
- rngdesc = rangename2drel(coords[2:6], relflags[2:6])
- if not shdesc:
- return rngdesc
- return "%s!%s" % (shdesc, rngdesc)
-
-def quotedsheetname(shnames, shx):
- if shx >= 0:
- shname = shnames[shx]
- else:
- shname = {
- -1: "?internal; any sheet?",
- -2: "internal; deleted sheet",
- -3: "internal; macro sheet",
- -4: "<<external>>",
- }.get(shx, "?error %d?" % shx)
- if "'" in shname:
- return "'" + shname.replace("'", "''") + "'"
- if " " in shname:
- return "'" + shname + "'"
- return shname
-
-def sheetrange(book, slo, shi):
- shnames = book.sheet_names()
- shdesc = quotedsheetname(shnames, slo)
- if slo != shi-1:
- shdesc += ":" + quotedsheetname(shnames, shi-1)
- return shdesc
-
-def sheetrangerel(book, (slo, shi), (slorel, shirel)):
- if not slorel and not shirel:
- return sheetrange(book, slo, shi)
- assert (slo == 0 == shi-1) and slorel and shirel
- return ""
-
-# ==============================================================
diff --git a/tablib/packages/xlrd/licences.py b/tablib/packages/xlrd/licences.py
deleted file mode 100644
index 1e262a9..0000000
--- a/tablib/packages/xlrd/licences.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# -*- coding: cp1252 -*-
-
-"""
-Portions copyright 2005-2009, Stephen John Machin, Lingfo Pty Ltd
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright notice,
-this list of conditions and the following disclaimer in the documentation
-and/or other materials provided with the distribution.
-
-3. None of the names of Stephen John Machin, Lingfo Pty Ltd and any
-contributors may be used to endorse or promote products derived from this
-software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-THE POSSIBILITY OF SUCH DAMAGE.
-"""
-
-"""
-/*-
- * Copyright (c) 2001 David Giffin.
- * All rights reserved.
- *
- * Based on the the Java version: Andrew Khan Copyright (c) 2000.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * David Giffin <david@giffin.org>."
- *
- * 4. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * David Giffin <david@giffin.org>."
- *
- * THIS SOFTWARE IS PROVIDED BY DAVID GIFFIN ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID GIFFIN OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-"""
diff --git a/tablib/packages/xlrd/sheet.py b/tablib/packages/xlrd/sheet.py
deleted file mode 100644
index 70f7779..0000000
--- a/tablib/packages/xlrd/sheet.py
+++ /dev/null
@@ -1,1768 +0,0 @@
-# -*- coding: cp1252 -*-
-
-##
-# <p> Portions copyright 2005-2009 Stephen John Machin, Lingfo Pty Ltd</p>
-# <p>This module is part of the xlrd package, which is released under a BSD-style licence.</p>
-##
-
-# 2009-05-31 SJM Fixed problem with no CODEPAGE record on extremely minimal BIFF2.x 3rd-party file
-# 2009-04-27 SJM Integrated on_demand patch by Armando Serrano Lombillo
-# 2008-02-09 SJM Excel 2.0: build XFs on the fly from cell attributes
-# 2007-12-04 SJM Added support for Excel 2.x (BIFF2) files.
-# 2007-10-11 SJM Added missing entry for blank cell type to ctype_text
-# 2007-07-11 SJM Allow for BIFF2/3-style FORMAT record in BIFF4/8 file
-# 2007-04-22 SJM Remove experimental "trimming" facility.
-
-from biffh import *
-from timemachine import *
-from struct import unpack
-from formula import dump_formula, decompile_formula, rangename2d
-from formatting import nearest_colour_index, Format
-import time
-
-DEBUG = 0
-OBJ_MSO_DEBUG = 0
-
-_WINDOW2_options = (
- # Attribute names and initial values to use in case
- # a WINDOW2 record is not written.
- ("show_formulas", 0),
- ("show_grid_lines", 1),
- ("show_sheet_headers", 1),
- ("panes_are_frozen", 0),
- ("show_zero_values", 1),
- ("automatic_grid_line_colour", 1),
- ("columns_from_right_to_left", 0),
- ("show_outline_symbols", 1),
- ("remove_splits_if_pane_freeze_is_removed", 0),
- ("sheet_selected", 0),
- # "sheet_visible" appears to be merely a clone of "sheet_selected".
- # The real thing is the visibility attribute from the BOUNDSHEET record.
- ("sheet_visible", 0),
- ("show_in_page_break_preview", 0),
- )
-
-##
-# <p>Contains the data for one worksheet.</p>
-#
-# <p>In the cell access functions, "rowx" is a row index, counting from zero, and "colx" is a
-# column index, counting from zero.
-# Negative values for row/column indexes and slice positions are supported in the expected fashion.</p>
-#
-# <p>For information about cell types and cell values, refer to the documentation of the Cell class.</p>
-#
-# <p>WARNING: You don't call this class yourself. You access Sheet objects via the Book object that
-# was returned when you called xlrd.open_workbook("myfile.xls").</p>
-
-
-class Sheet(BaseObject):
- ##
- # Name of sheet.
- name = ''
-
- ##
- # Number of rows in sheet. A row index is in range(thesheet.nrows).
- nrows = 0
-
- ##
- # Number of columns in sheet. A column index is in range(thesheet.ncols).
- ncols = 0
-
- ##
- # The map from a column index to a Colinfo object. Often there is an entry
- # in COLINFO records for all column indexes in range(257).
- # Note that xlrd ignores the entry for the non-existent
- # 257th column. On the other hand, there may be no entry for unused columns.
- # <br /> -- New in version 0.6.1
- colinfo_map = {}
-
- ##
- # The map from a row index to a Rowinfo object. Note that it is possible
- # to have missing entries -- at least one source of XLS files doesn't
- # bother writing ROW records.
- # <br /> -- New in version 0.6.1
- rowinfo_map = {}
-
- ##
- # List of address ranges of cells containing column labels.
- # These are set up in Excel by Insert > Name > Labels > Columns.
- # <br> -- New in version 0.6.0
- # <br>How to deconstruct the list:
- # <pre>
- # for crange in thesheet.col_label_ranges:
- # rlo, rhi, clo, chi = crange
- # for rx in xrange(rlo, rhi):
- # for cx in xrange(clo, chi):
- # print "Column label at (rowx=%d, colx=%d) is %r" \
- # (rx, cx, thesheet.cell_value(rx, cx))
- # </pre>
- col_label_ranges = []
-
- ##
- # List of address ranges of cells containing row labels.
- # For more details, see <i>col_label_ranges</i> above.
- # <br> -- New in version 0.6.0
- row_label_ranges = []
-
- ##
- # List of address ranges of cells which have been merged.
- # These are set up in Excel by Format > Cells > Alignment, then ticking
- # the "Merge cells" box.
- # <br> -- New in version 0.6.1. Extracted only if open_workbook(..., formatting_info=True)
- # <br>How to deconstruct the list:
- # <pre>
- # for crange in thesheet.merged_cells:
- # rlo, rhi, clo, chi = crange
- # for rowx in xrange(rlo, rhi):
- # for colx in xrange(clo, chi):
- # # cell (rlo, clo) (the top left one) will carry the data
- # # and formatting info; the remainder will be recorded as
- # # blank cells, but a renderer will apply the formatting info
- # # for the top left cell (e.g. border, pattern) to all cells in
- # # the range.
- # </pre>
- merged_cells = []
-
- ##
- # Default column width from DEFCOLWIDTH record, else None.
- # From the OOo docs:<br />
- # """Column width in characters, using the width of the zero character
- # from default font (first FONT record in the file). Excel adds some
- # extra space to the default width, depending on the default font and
- # default font size. The algorithm how to exactly calculate the resulting
- # column width is not known.<br />
- # Example: The default width of 8 set in this record results in a column
- # width of 8.43 using Arial font with a size of 10 points."""<br />
- # For the default hierarchy, refer to the Colinfo class above.
- # <br /> -- New in version 0.6.1
- defcolwidth = None
-
- ##
- # Default column width from STANDARDWIDTH record, else None.
- # From the OOo docs:<br />
- # """Default width of the columns in 1/256 of the width of the zero
- # character, using default font (first FONT record in the file)."""<br />
- # For the default hierarchy, refer to the Colinfo class above.
- # <br /> -- New in version 0.6.1
- standardwidth = None
-
- ##
- # Default value to be used for a row if there is
- # no ROW record for that row.
- # From the <i>optional</i> DEFAULTROWHEIGHT record.
- default_row_height = None
-
- ##
- # Default value to be used for a row if there is
- # no ROW record for that row.
- # From the <i>optional</i> DEFAULTROWHEIGHT record.
- default_row_height_mismatch = None
-
- ##
- # Default value to be used for a row if there is
- # no ROW record for that row.
- # From the <i>optional</i> DEFAULTROWHEIGHT record.
- default_row_hidden = None
-
- ##
- # Default value to be used for a row if there is
- # no ROW record for that row.
- # From the <i>optional</i> DEFAULTROWHEIGHT record.
- default_additional_space_above = None
-
- ##
- # Default value to be used for a row if there is
- # no ROW record for that row.
- # From the <i>optional</i> DEFAULTROWHEIGHT record.
- default_additional_space_below = None
-
- ##
- # Visibility of the sheet. 0 = visible, 1 = hidden (can be unhidden
- # by user -- Format/Sheet/Unhide), 2 = "very hidden" (can be unhidden
- # only by VBA macro).
- visibility = 0
-
- ##
- # A 256-element tuple corresponding to the contents of the GCW record for this sheet.
- # If no such record, treat as all bits zero.
- # Applies to BIFF4-7 only. See docs of Colinfo class for discussion.
- gcw = (0, ) * 256
-
- def __init__(self, book, position, name, number):
- self.book = book
- self.biff_version = book.biff_version
- self._position = position
- self.logfile = book.logfile
- self.pickleable = book.pickleable
- self.dont_use_array = not(array_array and (CAN_PICKLE_ARRAY or not book.pickleable))
- self.name = name
- self.number = number
- self.verbosity = book.verbosity
- self.formatting_info = book.formatting_info
- self._xf_index_to_xl_type_map = book._xf_index_to_xl_type_map
- self.nrows = 0 # actual, including possibly empty cells
- self.ncols = 0
- self._maxdatarowx = -1 # highest rowx containing a non-empty cell
- self._maxdatacolx = -1 # highest colx containing a non-empty cell
- self._dimnrows = 0 # as per DIMENSIONS record
- self._dimncols = 0
- self._cell_values = []
- self._cell_types = []
- self._cell_xf_indexes = []
- self._need_fix_ragged_rows = 0
- self.defcolwidth = None
- self.standardwidth = None
- self.default_row_height = None
- self.default_row_height_mismatch = 0
- self.default_row_hidden = 0
- self.default_additional_space_above = 0
- self.default_additional_space_below = 0
- self.colinfo_map = {}
- self.rowinfo_map = {}
- self.col_label_ranges = []
- self.row_label_ranges = []
- self.merged_cells = []
- self._xf_index_stats = [0, 0, 0, 0]
- self.visibility = book._sheet_visibility[number] # from BOUNDSHEET record
- for attr, defval in _WINDOW2_options:
- setattr(self, attr, defval)
- self.first_visible_rowx = 0
- self.first_visible_colx = 0
- self.gridline_colour_index = 0x40
- self.gridline_colour_rgb = None # pre-BIFF8
- self.cached_page_break_preview_mag_factor = 0
- self.cached_normal_view_mag_factor = 0
- self._ixfe = None # BIFF2 only
- self._cell_attr_to_xfx = {} # BIFF2.0 only
-
- #### Don't initialise this here, use class attribute initialisation.
- #### self.gcw = (0, ) * 256 ####
-
- if self.biff_version >= 80:
- self.utter_max_rows = 65536
- else:
- self.utter_max_rows = 16384
- self.utter_max_cols = 256
-
- ##
- # Cell object in the given row and column.
- def cell(self, rowx, colx):
- if self.formatting_info:
- xfx = self.cell_xf_index(rowx, colx)
- else:
- xfx = None
- return Cell(
- self._cell_types[rowx][colx],
- self._cell_values[rowx][colx],
- xfx,
- )
-
- ##
- # Value of the cell in the given row and column.
- def cell_value(self, rowx, colx):
- return self._cell_values[rowx][colx]
-
- ##
- # Type of the cell in the given row and column.
- # Refer to the documentation of the Cell class.
- def cell_type(self, rowx, colx):
- return self._cell_types[rowx][colx]
-
- ##
- # XF index of the cell in the given row and column.
- # This is an index into Book.xf_list.
- # <br /> -- New in version 0.6.1
- def cell_xf_index(self, rowx, colx):
- self.req_fmt_info()
- xfx = self._cell_xf_indexes[rowx][colx]
- if xfx > -1:
- self._xf_index_stats[0] += 1
- return xfx
- # Check for a row xf_index
- try:
- xfx = self.rowinfo_map[rowx].xf_index
- if xfx > -1:
- self._xf_index_stats[1] += 1
- return xfx
- except KeyError:
- pass
- # Check for a column xf_index
- try:
- xfx = self.colinfo_map[colx].xf_index
- assert xfx > -1
- self._xf_index_stats[2] += 1
- return xfx
- except KeyError:
- # If all else fails, 15 is used as hardwired global default xf_index.
- self._xf_index_stats[3] += 1
- return 15
-
- ##
- # Returns a sequence of the Cell objects in the given row.
- def row(self, rowx):
- return [
- self.cell(rowx, colx)
- for colx in xrange(self.ncols)
- ]
-
- ##
- # Returns a slice of the types
- # of the cells in the given row.
- def row_types(self, rowx, start_colx=0, end_colx=None):
- if end_colx is None:
- return self._cell_types[rowx][start_colx:]
- return self._cell_types[rowx][start_colx:end_colx]
-
- ##
- # Returns a slice of the values
- # of the cells in the given row.
- def row_values(self, rowx, start_colx=0, end_colx=None):
- if end_colx is None:
- return self._cell_values[rowx][start_colx:]
- return self._cell_values[rowx][start_colx:end_colx]
-
- ##
- # Returns a slice of the Cell objects in the given row.
- def row_slice(self, rowx, start_colx=0, end_colx=None):
- nc = self.ncols
- if start_colx < 0:
- start_colx += nc
- if start_colx < 0:
- start_colx = 0
- if end_colx is None or end_colx > nc:
- end_colx = nc
- elif end_colx < 0:
- end_colx += nc
- return [
- self.cell(rowx, colx)
- for colx in xrange(start_colx, end_colx)
- ]
-
- ##
- # Returns a slice of the Cell objects in the given column.
- def col_slice(self, colx, start_rowx=0, end_rowx=None):
- nr = self.nrows
- if start_rowx < 0:
- start_rowx += nr
- if start_rowx < 0:
- start_rowx = 0
- if end_rowx is None or end_rowx > nr:
- end_rowx = nr
- elif end_rowx < 0:
- end_rowx += nr
- return [
- self.cell(rowx, colx)
- for rowx in xrange(start_rowx, end_rowx)
- ]
-
- ##
- # Returns a slice of the values of the cells in the given column.
- def col_values(self, colx, start_rowx=0, end_rowx=None):
- nr = self.nrows
- if start_rowx < 0:
- start_rowx += nr
- if start_rowx < 0:
- start_rowx = 0
- if end_rowx is None or end_rowx > nr:
- end_rowx = nr
- elif end_rowx < 0:
- end_rowx += nr
- return [
- self._cell_values[rowx][colx]
- for rowx in xrange(start_rowx, end_rowx)
- ]
-
- ##
- # Returns a slice of the types of the cells in the given column.
- def col_types(self, colx, start_rowx=0, end_rowx=None):
- nr = self.nrows
- if start_rowx < 0:
- start_rowx += nr
- if start_rowx < 0:
- start_rowx = 0
- if end_rowx is None or end_rowx > nr:
- end_rowx = nr
- elif end_rowx < 0:
- end_rowx += nr
- return [
- self._cell_types[rowx][colx]
- for rowx in xrange(start_rowx, end_rowx)
- ]
-
- ##
- # Returns a sequence of the Cell objects in the given column.
- def col(self, colx):
- return self.col_slice(colx)
- # Above two lines just for the docs. Here's the real McCoy:
- col = col_slice
-
- # === Following methods are used in building the worksheet.
- # === They are not part of the API.
-
- def extend_cells(self, nr, nc):
- # print "extend_cells_2", self.nrows, self.ncols, nr, nc
- assert 1 <= nc <= self.utter_max_cols
- assert 1 <= nr <= self.utter_max_rows
- if nr <= self.nrows:
- # New cell is in an existing row, so extend that row (if necessary).
- # Note that nr < self.nrows means that the cell data
- # is not in ascending row order!!
- self._need_fix_ragged_rows = 1
- nrx = nr - 1
- trow = self._cell_types[nrx]
- tlen = len(trow)
- nextra = max(nc, self.ncols) - tlen
- if nextra > 0:
- xce = XL_CELL_EMPTY
- if self.dont_use_array:
- trow.extend([xce] * nextra)
- if self.formatting_info:
- self._cell_xf_indexes[nrx].extend([-1] * nextra)
- else:
- aa = array_array
- trow.extend(aa('B', [xce]) * nextra)
- if self.formatting_info:
- self._cell_xf_indexes[nrx].extend(aa('h', [-1]) * nextra)
- self._cell_values[nrx].extend([''] * nextra)
- if nc > self.ncols:
- self.ncols = nc
- self._need_fix_ragged_rows = 1
- if nr > self.nrows:
- scta = self._cell_types.append
- scva = self._cell_values.append
- scxa = self._cell_xf_indexes.append
- fmt_info = self.formatting_info
- xce = XL_CELL_EMPTY
- nc = self.ncols
- if self.dont_use_array:
- for _unused in xrange(self.nrows, nr):
- scta([xce] * nc)
- scva([''] * nc)
- if fmt_info:
- scxa([-1] * nc)
- else:
- aa = array_array
- for _unused in xrange(self.nrows, nr):
- scta(aa('B', [xce]) * nc)
- scva([''] * nc)
- if fmt_info:
- scxa(aa('h', [-1]) * nc)
- self.nrows = nr
-
- def fix_ragged_rows(self):
- t0 = time.time()
- ncols = self.ncols
- xce = XL_CELL_EMPTY
- aa = array_array
- s_cell_types = self._cell_types
- s_cell_values = self._cell_values
- s_cell_xf_indexes = self._cell_xf_indexes
- s_dont_use_array = self.dont_use_array
- s_fmt_info = self.formatting_info
- totrowlen = 0
- for rowx in xrange(self.nrows):
- trow = s_cell_types[rowx]
- rlen = len(trow)
- totrowlen += rlen
- nextra = ncols - rlen
- if nextra > 0:
- s_cell_values[rowx][rlen:] = [''] * nextra
- if s_dont_use_array:
- trow[rlen:] = [xce] * nextra
- if s_fmt_info:
- s_cell_xf_indexes[rowx][rlen:] = [-1] * nextra
- else:
- trow.extend(aa('B', [xce]) * nextra)
- if s_fmt_info:
- s_cell_xf_indexes[rowx][rlen:] = aa('h', [-1]) * nextra
- self._fix_ragged_rows_time = time.time() - t0
- if 0 and self.nrows:
- avgrowlen = float(totrowlen) / self.nrows
- print >> self.logfile, \
- "sheet %d: avg row len %.1f; max row len %d" \
- % (self.number, avgrowlen, self.ncols)
-
- def tidy_dimensions(self):
- if self.verbosity >= 3:
- fprintf(self.logfile,
- "tidy_dimensions: nrows=%d ncols=%d _need_fix_ragged_rows=%d\n",
- self.nrows, self.ncols, self._need_fix_ragged_rows,
- )
- if 1 and self.merged_cells:
- nr = nc = 0
- umaxrows = self.utter_max_rows
- umaxcols = self.utter_max_cols
- for crange in self.merged_cells:
- rlo, rhi, clo, chi = crange
- if not (0 <= rlo < rhi <= umaxrows) \
- or not (0 <= clo < chi <= umaxcols):
- fprintf(self.logfile,
- "*** WARNING: sheet #%d (%r), MERGEDCELLS bad range %r\n",
- self.number, self.name, crange)
- if rhi > nr: nr = rhi
- if chi > nc: nc = chi
- self.extend_cells(nr, nc)
- if self.verbosity >= 1 \
- and (self.nrows != self._dimnrows or self.ncols != self._dimncols):
- fprintf(self.logfile,
- "NOTE *** sheet %d (%r): DIMENSIONS R,C = %d,%d should be %d,%d\n",
- self.number,
- self.name,
- self._dimnrows,
- self._dimncols,
- self.nrows,
- self.ncols,
- )
- if self._need_fix_ragged_rows:
- self.fix_ragged_rows()
-
- def put_cell(self, rowx, colx, ctype, value, xf_index):
- try:
- self._cell_types[rowx][colx] = ctype
- self._cell_values[rowx][colx] = value
- if self.formatting_info:
- self._cell_xf_indexes[rowx][colx] = xf_index
- except IndexError:
- # print >> self.logfile, "put_cell extending", rowx, colx
- self.extend_cells(rowx+1, colx+1)
- try:
- self._cell_types[rowx][colx] = ctype
- self._cell_values[rowx][colx] = value
- if self.formatting_info:
- self._cell_xf_indexes[rowx][colx] = xf_index
- except:
- print >> self.logfile, "put_cell", rowx, colx
- raise
- except:
- print >> self.logfile, "put_cell", rowx, colx
- raise
-
- def put_blank_cell(self, rowx, colx, xf_index):
- # This is used for cells from BLANK and MULBLANK records
- ctype = XL_CELL_BLANK
- value = ''
- try:
- self._cell_types[rowx][colx] = ctype
- self._cell_values[rowx][colx] = value
- self._cell_xf_indexes[rowx][colx] = xf_index
- except IndexError:
- # print >> self.logfile, "put_cell extending", rowx, colx
- self.extend_cells(rowx+1, colx+1)
- try:
- self._cell_types[rowx][colx] = ctype
- self._cell_values[rowx][colx] = value
- self._cell_xf_indexes[rowx][colx] = xf_index
- except:
- print >> self.logfile, "put_cell", rowx, colx
- raise
- except:
- print >> self.logfile, "put_cell", rowx, colx
- raise
-
- def put_number_cell(self, rowx, colx, value, xf_index):
- ctype = self._xf_index_to_xl_type_map[xf_index]
- try:
- self._cell_types[rowx][colx] = ctype
- self._cell_values[rowx][colx] = value
- if self.formatting_info:
- self._cell_xf_indexes[rowx][colx] = xf_index
- except IndexError:
- # print >> self.logfile, "put_number_cell extending", rowx, colx
- self.extend_cells(rowx+1, colx+1)
- try:
- self._cell_types[rowx][colx] = ctype
- self._cell_values[rowx][colx] = value
- if self.formatting_info:
- self._cell_xf_indexes[rowx][colx] = xf_index
- except:
- print >> self.logfile, "put_number_cell", rowx, colx
- raise
- except:
- print >> self.logfile, "put_number_cell", rowx, colx
- raise
-
- # === Methods after this line neither know nor care about how cells are stored.
-
- def read(self, bk):
- global rc_stats
- DEBUG = 0
- blah = DEBUG or self.verbosity >= 2
- blah_rows = DEBUG or self.verbosity >= 4
- blah_formulas = 1 and blah
- oldpos = bk._position
- bk._position = self._position
- XL_SHRFMLA_ETC_ETC = (
- XL_SHRFMLA, XL_ARRAY, XL_TABLEOP, XL_TABLEOP2,
- XL_ARRAY2, XL_TABLEOP_B2,
- )
- self_put_number_cell = self.put_number_cell
- self_put_cell = self.put_cell
- self_put_blank_cell = self.put_blank_cell
- local_unpack = unpack
- bk_get_record_parts = bk.get_record_parts
- bv = self.biff_version
- fmt_info = self.formatting_info
- eof_found = 0
- while 1:
- # if DEBUG: print "SHEET.READ: about to read from position %d" % bk._position
- rc, data_len, data = bk_get_record_parts()
- # if rc in rc_stats:
- # rc_stats[rc] += 1
- # else:
- # rc_stats[rc] = 1
- # if DEBUG: print "SHEET.READ: op 0x%04x, %d bytes %r" % (rc, data_len, data)
- if rc == XL_NUMBER:
- rowx, colx, xf_index, d = local_unpack('<HHHd', data)
- # if xf_index == 0:
- # fprintf(self.logfile,
- # "NUMBER: r=%d c=%d xfx=%d %f\n", rowx, colx, xf_index, d)
- self_put_number_cell(rowx, colx, d, xf_index)
- elif rc == XL_LABELSST:
- rowx, colx, xf_index, sstindex = local_unpack('<HHHi', data)
- # print "LABELSST", rowx, colx, sstindex, bk._sharedstrings[sstindex]
- self_put_cell(rowx, colx, XL_CELL_TEXT, bk._sharedstrings[sstindex], xf_index)
- elif rc == XL_LABEL or rc == XL_RSTRING:
- # RSTRING has extra richtext info at the end, but we ignore it.
- rowx, colx, xf_index = local_unpack('<HHH', data[0:6])
- if bv < BIFF_FIRST_UNICODE:
- strg = unpack_string(data, 6, bk.encoding or bk.derive_encoding, lenlen=2)
- else:
- strg = unpack_unicode(data, 6, lenlen=2)
- self_put_cell(rowx, colx, XL_CELL_TEXT, strg, xf_index)
- elif rc == XL_RK:
- rowx, colx, xf_index = local_unpack('<HHH', data[:6])
- d = unpack_RK(data[6:10])
- self_put_number_cell(rowx, colx, d, xf_index)
- elif rc == XL_MULRK:
- mulrk_row, mulrk_first = local_unpack('<HH', data[0:4])
- mulrk_last, = local_unpack('<H', data[-2:])
- pos = 4
- for colx in xrange(mulrk_first, mulrk_last+1):
- xf_index, = local_unpack('<H', data[pos:pos+2])
- d = unpack_RK(data[pos+2:pos+6])
- pos += 6
- self_put_number_cell(mulrk_row, colx, d, xf_index)
- elif rc == XL_ROW:
- # Version 0.6.0a3: ROW records are just not worth using (for memory allocation).
- # Version 0.6.1: now used for formatting info.
- if not fmt_info: continue
- rowx, bits1, bits2 = local_unpack('<H4xH4xi', data[0:16])
- if not(0 <= rowx < self.utter_max_rows):
- print >> self.logfile, \
- "*** NOTE: ROW record has row index %d; " \
- "should have 0 <= rowx < %d -- record ignored!" \
- % (rowx, self.utter_max_rows)
- continue
- r = Rowinfo()
- # Using upkbits() is far too slow on a file
- # with 30 sheets each with 10K rows :-(
- # upkbits(r, bits1, (
- # ( 0, 0x7FFF, 'height'),
- # (15, 0x8000, 'has_default_height'),
- # ))
- # upkbits(r, bits2, (
- # ( 0, 0x00000007, 'outline_level'),
- # ( 4, 0x00000010, 'outline_group_starts_ends'),
- # ( 5, 0x00000020, 'hidden'),
- # ( 6, 0x00000040, 'height_mismatch'),
- # ( 7, 0x00000080, 'has_default_xf_index'),
- # (16, 0x0FFF0000, 'xf_index'),
- # (28, 0x10000000, 'additional_space_above'),
- # (29, 0x20000000, 'additional_space_below'),
- # ))
- # So:
- r.height = bits1 & 0x7fff
- r.has_default_height = (bits1 >> 15) & 1
- r.outline_level = bits2 & 7
- r.outline_group_starts_ends = (bits2 >> 4) & 1
- r.hidden = (bits2 >> 5) & 1
- r.height_mismatch = (bits2 >> 6) & 1
- r.has_default_xf_index = (bits2 >> 7) & 1
- r.xf_index = (bits2 >> 16) & 0xfff
- r.additional_space_above = (bits2 >> 28) & 1
- r.additional_space_below = (bits2 >> 29) & 1
- if not r.has_default_xf_index:
- r.xf_index = -1
- self.rowinfo_map[rowx] = r
- if 0 and r.xf_index > -1:
- fprintf(self.logfile,
- "**ROW %d %d %d\n",
- self.number, rowx, r.xf_index)
- if blah_rows:
- print >> self.logfile, 'ROW', rowx, bits1, bits2
- r.dump(self.logfile,
- header="--- sh #%d, rowx=%d ---" % (self.number, rowx))
- elif rc in XL_FORMULA_OPCODES: # 06, 0206, 0406
- # DEBUG = 1
- # if DEBUG: print "FORMULA: rc: 0x%04x data: %r" % (rc, data)
- if bv >= 50:
- rowx, colx, xf_index, result_str, flags = local_unpack('<HHH8sH', data[0:16])
- lenlen = 2
- tkarr_offset = 20
- elif bv >= 30:
- rowx, colx, xf_index, result_str, flags = local_unpack('<HHH8sH', data[0:16])
- lenlen = 2
- tkarr_offset = 16
- else: # BIFF2
- rowx, colx, cell_attr, result_str, flags = local_unpack('<HH3s8sB', data[0:16])
- xf_index = self.fixed_BIFF2_xfindex(cell_attr, rowx, colx)
- lenlen = 1
- tkarr_offset = 16
- if blah_formulas: # testing formula dumper
- #### XXXX FIXME
- fprintf(self.logfile, "FORMULA: rowx=%d colx=%d\n", rowx, colx)
- fmlalen = local_unpack("<H", data[20:22])[0]
- decompile_formula(bk, data[22:], fmlalen,
- reldelta=0, browx=rowx, bcolx=colx, blah=1)
- if result_str[6:8] == "\xFF\xFF":
- if result_str[0] == '\x00':
- # need to read next record (STRING)
- gotstring = 0
- # if flags & 8:
- if 1: # "flags & 8" applies only to SHRFMLA
- # actually there's an optional SHRFMLA or ARRAY etc record to skip over
- rc2, data2_len, data2 = bk.get_record_parts()
- if rc2 == XL_STRING or rc2 == XL_STRING_B2:
- gotstring = 1
- elif rc2 == XL_ARRAY:
- row1x, rownx, col1x, colnx, array_flags, tokslen = \
- local_unpack("<HHBBBxxxxxH", data2[:14])
- if blah_formulas:
- fprintf(self.logfile, "ARRAY: %d %d %d %d %d\n",
- row1x, rownx, col1x, colnx, array_flags)
- dump_formula(bk, data2[14:], tokslen, bv, reldelta=0, blah=1)
- elif rc2 == XL_SHRFMLA:
- row1x, rownx, col1x, colnx, nfmlas, tokslen = \
- local_unpack("<HHBBxBH", data2[:10])
- if blah_formulas:
- fprintf(self.logfile, "SHRFMLA (sub): %d %d %d %d %d\n",
- row1x, rownx, col1x, colnx, nfmlas)
- decompile_formula(bk, data2[10:], tokslen, reldelta=1, blah=1)
- elif rc2 not in XL_SHRFMLA_ETC_ETC:
- raise XLRDError(
- "Expected SHRFMLA, ARRAY, TABLEOP* or STRING record; found 0x%04x" % rc2)
- # if DEBUG: print "gotstring:", gotstring
- # now for the STRING record
- if not gotstring:
- rc2, _unused_len, data2 = bk.get_record_parts()
- if rc2 not in (XL_STRING, XL_STRING_B2):
- raise XLRDError("Expected STRING record; found 0x%04x" % rc2)
- # if DEBUG: print "STRING: data=%r BIFF=%d cp=%d" % (data2, self.biff_version, bk.encoding)
- if self.biff_version < BIFF_FIRST_UNICODE:
- strg = unpack_string(data2, 0, bk.encoding or bk.derive_encoding, lenlen=1 + int(bv > 20))
- else:
- strg = unpack_unicode(data2, 0, lenlen=2)
- self.put_cell(rowx, colx, XL_CELL_TEXT, strg, xf_index)
- # if DEBUG: print "FORMULA strg %r" % strg
- elif result_str[0] == '\x01':
- # boolean formula result
- value = ord(result_str[2])
- self.put_cell(rowx, colx, XL_CELL_BOOLEAN, value, xf_index)
- elif result_str[0] == '\x02':
- # Error in cell
- value = ord(result_str[2])
- self.put_cell(rowx, colx, XL_CELL_ERROR, value, xf_index)
- elif result_str[0] == '\x03':
- # empty ... i.e. empty (zero-length) string, NOT an empty cell.
- self.put_cell(rowx, colx, XL_CELL_TEXT, u"", xf_index)
- else:
- raise XLRDError("unexpected special case (0x%02x) in FORMULA" % ord(result_str[0]))
- else:
- # it is a number
- d = local_unpack('<d', result_str)[0]
- self_put_number_cell(rowx, colx, d, xf_index)
- elif rc == XL_BOOLERR:
- rowx, colx, xf_index, value, is_err = local_unpack('<HHHBB', data[:8])
- # Note OOo Calc 2.0 writes 9-byte BOOLERR records.
- # OOo docs say 8. Excel writes 8.
- cellty = (XL_CELL_BOOLEAN, XL_CELL_ERROR)[is_err]
- # if DEBUG: print "XL_BOOLERR", rowx, colx, xf_index, value, is_err
- self.put_cell(rowx, colx, cellty, value, xf_index)
- elif rc == XL_COLINFO:
- if not fmt_info: continue
- c = Colinfo()
- first_colx, last_colx, c.width, c.xf_index, flags \
- = local_unpack("<HHHHH", data[:10])
- #### Colinfo.width is denominated in 256ths of a character,
- #### *not* in characters.
- if not(0 <= first_colx <= last_colx <= 256):
- # Note: 256 instead of 255 is a common mistake.
- # We silently ignore the non-existing 257th column in that case.
- print >> self.logfile, \
- "*** NOTE: COLINFO record has first col index %d, last %d; " \
- "should have 0 <= first <= last <= 255 -- record ignored!" \
- % (first_colx, last_colx)
- del c
- continue
- upkbits(c, flags, (
- ( 0, 0x0001, 'hidden'),
- ( 1, 0x0002, 'bit1_flag'),
- # *ALL* colinfos created by Excel in "default" cases are 0x0002!!
- # Maybe it's "locked" by analogy with XFProtection data.
- ( 8, 0x0700, 'outline_level'),
- (12, 0x1000, 'collapsed'),
- ))
- for colx in xrange(first_colx, last_colx+1):
- if colx > 255: break # Excel does 0 to 256 inclusive
- self.colinfo_map[colx] = c
- if 0:
- fprintf(self.logfile,
- "**COL %d %d %d\n",
- self.number, colx, c.xf_index)
- if blah:
- fprintf(
- self.logfile,
- "COLINFO sheet #%d cols %d-%d: wid=%d xf_index=%d flags=0x%04x\n",
- self.number, first_colx, last_colx, c.width, c.xf_index, flags,
- )
- c.dump(self.logfile, header='===')
- elif rc == XL_DEFCOLWIDTH:
- self.defcolwidth, = local_unpack("<H", data[:2])
- if 0: print >> self.logfile, 'DEFCOLWIDTH', self.defcolwidth
- elif rc == XL_STANDARDWIDTH:
- if data_len != 2:
- print >> self.logfile, '*** ERROR *** STANDARDWIDTH', data_len, repr(data)
- self.standardwidth, = local_unpack("<H", data[:2])
- if 0: print >> self.logfile, 'STANDARDWIDTH', self.standardwidth
- elif rc == XL_GCW:
- if not fmt_info: continue # useless w/o COLINFO
- assert data_len == 34
- assert data[0:2] == "\x20\x00"
- iguff = unpack("<8i", data[2:34])
- gcw = []
- for bits in iguff:
- for j in xrange(32):
- gcw.append(bits & 1)
- bits >>= 1
- self.gcw = tuple(gcw)
- if 0:
- showgcw = "".join(map(lambda x: "F "[x], gcw)).rstrip().replace(' ', '.')
- print "GCW:", showgcw
- elif rc == XL_BLANK:
- if not fmt_info: continue
- rowx, colx, xf_index = local_unpack('<HHH', data[:6])
- if 0: print >> self.logfile, "BLANK", rowx, colx, xf_index
- self_put_blank_cell(rowx, colx, xf_index)
- elif rc == XL_MULBLANK: # 00BE
- if not fmt_info: continue
- mul_row, mul_first = local_unpack('<HH', data[0:4])
- mul_last, = local_unpack('<H', data[-2:])
- if 0:
- print >> self.logfile, "MULBLANK", mul_row, mul_first, mul_last
- pos = 4
- for colx in xrange(mul_first, mul_last+1):
- xf_index, = local_unpack('<H', data[pos:pos+2])
- pos += 2
- self_put_blank_cell(mul_row, colx, xf_index)
- elif rc == XL_DIMENSION or rc == XL_DIMENSION2:
- # if data_len == 10:
- # Was crashing on BIFF 4.0 file w/o the two trailing unused bytes.
- # Reported by Ralph Heimburger.
- if bv < 80:
- dim_tuple = local_unpack('<HxxH', data[2:8])
- else:
- dim_tuple = local_unpack('<ixxH', data[4:12])
- self.nrows, self.ncols = 0, 0
- self._dimnrows, self._dimncols = dim_tuple
- if not self.book._xf_epilogue_done:
- # Needed for bv <= 40
- self.book.xf_epilogue()
- if blah:
- fprintf(self.logfile,
- "sheet %d(%r) DIMENSIONS: ncols=%d nrows=%d\n",
- self.number, self.name, self._dimncols, self._dimnrows
- )
- elif rc == XL_EOF:
- DEBUG = 0
- if DEBUG: print >> self.logfile, "SHEET.READ: EOF"
- eof_found = 1
- break
- elif rc == XL_OBJ:
- # handle SHEET-level objects; note there's a separate Book.handle_obj
- self.handle_obj(data)
- elif rc == XL_MSO_DRAWING:
- self.handle_msodrawingetc(rc, data_len, data)
- elif rc == XL_TXO:
- self.handle_txo(data)
- elif rc == XL_NOTE:
- self.handle_note(data)
- elif rc == XL_FEAT11:
- self.handle_feat11(data)
- elif rc in bofcodes: ##### EMBEDDED BOF #####
- version, boftype = local_unpack('<HH', data[0:4])
- if boftype != 0x20: # embedded chart
- print >> self.logfile, \
- "*** Unexpected embedded BOF (0x%04x) at offset %d: version=0x%04x type=0x%04x" \
- % (rc, bk._position - data_len - 4, version, boftype)
- while 1:
- code, data_len, data = bk.get_record_parts()
- if code == XL_EOF:
- break
- if DEBUG: print >> self.logfile, "---> found EOF"
- elif rc == XL_COUNTRY:
- bk.handle_country(data)
- elif rc == XL_LABELRANGES:
- pos = 0
- pos = unpack_cell_range_address_list_update_pos(
- self.row_label_ranges, data, pos, bv, addr_size=8,
- )
- pos = unpack_cell_range_address_list_update_pos(
- self.col_label_ranges, data, pos, bv, addr_size=8,
- )
- assert pos == data_len
- elif rc == XL_ARRAY:
- row1x, rownx, col1x, colnx, array_flags, tokslen = \
- local_unpack("<HHBBBxxxxxH", data[:14])
- if blah_formulas:
- print "ARRAY:", row1x, rownx, col1x, colnx, array_flags
- dump_formula(bk, data[14:], tokslen, bv, reldelta=0, blah=1)
- elif rc == XL_SHRFMLA:
- row1x, rownx, col1x, colnx, nfmlas, tokslen = \
- local_unpack("<HHBBxBH", data[:10])
- if blah_formulas:
- print "SHRFMLA (main):", row1x, rownx, col1x, colnx, nfmlas
- decompile_formula(bk, data[10:], tokslen, reldelta=0, blah=1)
- elif rc == XL_CONDFMT:
- if not fmt_info: continue
- assert bv >= 80
- num_CFs, needs_recalc, browx1, browx2, bcolx1, bcolx2 = \
- unpack("<6H", data[0:12])
- if self.verbosity >= 1:
- fprintf(self.logfile,
- "\n*** WARNING: Ignoring CONDFMT (conditional formatting) record\n" \
- "*** in Sheet %d (%r).\n" \
- "*** %d CF record(s); needs_recalc_or_redraw = %d\n" \
- "*** Bounding box is %s\n",
- self.number, self.name, num_CFs, needs_recalc,
- rangename2d(browx1, browx2+1, bcolx1, bcolx2+1),
- )
- olist = [] # updated by the function
- pos = unpack_cell_range_address_list_update_pos(
- olist, data, 12, bv, addr_size=8)
- # print >> self.logfile, repr(result), len(result)
- if self.verbosity >= 1:
- fprintf(self.logfile,
- "*** %d individual range(s):\n" \
- "*** %s\n",
- len(olist),
- ", ".join([rangename2d(*coords) for coords in olist]),
- )
- elif rc == XL_CF:
- if not fmt_info: continue
- cf_type, cmp_op, sz1, sz2, flags = unpack("<BBHHi", data[0:10])
- font_block = (flags >> 26) & 1
- bord_block = (flags >> 28) & 1
- patt_block = (flags >> 29) & 1
- if self.verbosity >= 1:
- fprintf(self.logfile,
- "\n*** WARNING: Ignoring CF (conditional formatting) sub-record.\n" \
- "*** cf_type=%d, cmp_op=%d, sz1=%d, sz2=%d, flags=0x%08x\n" \
- "*** optional data blocks: font=%d, border=%d, pattern=%d\n",
- cf_type, cmp_op, sz1, sz2, flags,
- font_block, bord_block, patt_block,
- )
- # hex_char_dump(data, 0, data_len)
- pos = 12
- if font_block:
- (font_height, font_options, weight, escapement, underline,
- font_colour_index, two_bits, font_esc, font_underl) = \
- unpack("<64x i i H H B 3x i 4x i i i 18x", data[pos:pos+118])
- font_style = (two_bits > 1) & 1
- posture = (font_options > 1) & 1
- font_canc = (two_bits > 7) & 1
- cancellation = (font_options > 7) & 1
- if self.verbosity >= 1:
- fprintf(self.logfile,
- "*** Font info: height=%d, weight=%d, escapement=%d,\n" \
- "*** underline=%d, colour_index=%d, esc=%d, underl=%d,\n" \
- "*** style=%d, posture=%d, canc=%d, cancellation=%d\n",
- font_height, weight, escapement, underline,
- font_colour_index, font_esc, font_underl,
- font_style, posture, font_canc, cancellation,
- )
- pos += 118
- if bord_block:
- pos += 8
- if patt_block:
- pos += 4
- fmla1 = data[pos:pos+sz1]
- pos += sz1
- if blah and sz1:
- fprintf(self.logfile,
- "*** formula 1:\n",
- )
- dump_formula(bk, fmla1, sz1, bv, reldelta=0, blah=1)
- fmla2 = data[pos:pos+sz2]
- pos += sz2
- assert pos == data_len
- if blah and sz2:
- fprintf(self.logfile,
- "*** formula 2:\n",
- )
- dump_formula(bk, fmla2, sz2, bv, reldelta=0, blah=1)
- elif rc == XL_DEFAULTROWHEIGHT:
- if data_len == 4:
- bits, self.default_row_height = unpack("<HH", data[:4])
- elif data_len == 2:
- self.default_row_height, = unpack("<H", data)
- bits = 0
- fprintf(self.logfile,
- "*** WARNING: DEFAULTROWHEIGHT record len is 2, " \
- "should be 4; assuming BIFF2 format\n")
- else:
- bits = 0
- fprintf(self.logfile,
- "*** WARNING: DEFAULTROWHEIGHT record len is %d, " \
- "should be 4; ignoring this record\n",
- data_len)
- self.default_row_height_mismatch = bits & 1
- self.default_row_hidden = (bits >> 1) & 1
- self.default_additional_space_above = (bits >> 2) & 1
- self.default_additional_space_below = (bits >> 3) & 1
- elif rc == XL_MERGEDCELLS:
- if not fmt_info: continue
- pos = unpack_cell_range_address_list_update_pos(
- self.merged_cells, data, 0, bv, addr_size=8)
- if blah:
- fprintf(self.logfile,
- "MERGEDCELLS: %d ranges\n", int_floor_div(pos - 2, 8))
- assert pos == data_len, \
- "MERGEDCELLS: pos=%d data_len=%d" % (pos, data_len)
- elif rc == XL_WINDOW2:
- if bv >= 80:
- (options,
- self.first_visible_rowx, self.first_visible_colx,
- self.gridline_colour_index,
- self.cached_page_break_preview_mag_factor,
- self.cached_normal_view_mag_factor
- ) = unpack("<HHHHxxHH", data[:14])
- else: # BIFF3-7
- (options,
- self.first_visible_rowx, self.first_visible_colx,
- ) = unpack("<HHH", data[:6])
- self.gridline_colour_rgb = unpack("<BBB", data[6:9])
- self.gridline_colour_index = \
- nearest_colour_index(
- self.book.colour_map,
- self.gridline_colour_rgb,
- debug=0)
- self.cached_page_break_preview_mag_factor = 0 # default (60%)
- self.cached_normal_view_mag_factor = 0 # default (100%)
- # options -- Bit, Mask, Contents:
- # 0 0001H 0 = Show formula results 1 = Show formulas
- # 1 0002H 0 = Do not show grid lines 1 = Show grid lines
- # 2 0004H 0 = Do not show sheet headers 1 = Show sheet headers
- # 3 0008H 0 = Panes are not frozen 1 = Panes are frozen (freeze)
- # 4 0010H 0 = Show zero values as empty cells 1 = Show zero values
- # 5 0020H 0 = Manual grid line colour 1 = Automatic grid line colour
- # 6 0040H 0 = Columns from left to right 1 = Columns from right to left
- # 7 0080H 0 = Do not show outline symbols 1 = Show outline symbols
- # 8 0100H 0 = Keep splits if pane freeze is removed 1 = Remove splits if pane freeze is removed
- # 9 0200H 0 = Sheet not selected 1 = Sheet selected (BIFF5-BIFF8)
- # 10 0400H 0 = Sheet not visible 1 = Sheet visible (BIFF5-BIFF8)
- # 11 0800H 0 = Show in normal view 1 = Show in page break preview (BIFF8)
- # The freeze flag specifies, if a following PANE record (6.71) describes unfrozen or frozen panes.
- for attr, _unused_defval in _WINDOW2_options:
- setattr(self, attr, options & 1)
- options >>= 1
- # print "WINDOW2: visible=%d selected=%d" \
- # % (self.sheet_visible, self.sheet_selected)
- #### all of the following are for BIFF <= 4W
- elif bv <= 45:
- if rc == XL_FORMAT or rc == XL_FORMAT2:
- bk.handle_format(data, rc)
- elif rc == XL_FONT or rc == XL_FONT_B3B4:
- bk.handle_font(data)
- elif rc == XL_STYLE:
- if not self.book._xf_epilogue_done:
- self.book.xf_epilogue()
- bk.handle_style(data)
- elif rc == XL_PALETTE:
- bk.handle_palette(data)
- elif rc == XL_BUILTINFMTCOUNT:
- bk.handle_builtinfmtcount(data)
- elif rc == XL_XF4 or rc == XL_XF3 or rc == XL_XF2: #### N.B. not XL_XF
- bk.handle_xf(data)
- elif rc == XL_DATEMODE:
- bk.handle_datemode(data)
- elif rc == XL_CODEPAGE:
- bk.handle_codepage(data)
- elif rc == XL_FILEPASS:
- bk.handle_filepass(data)
- elif rc == XL_WRITEACCESS:
- bk.handle_writeaccess(data)
- elif rc == XL_IXFE:
- self._ixfe = local_unpack('<H', data)[0]
- elif rc == XL_NUMBER_B2:
- rowx, colx, cell_attr, d = local_unpack('<HH3sd', data)
- self_put_number_cell(rowx, colx, d, self.fixed_BIFF2_xfindex(cell_attr, rowx, colx))
- elif rc == XL_INTEGER:
- rowx, colx, cell_attr, d = local_unpack('<HH3sH', data)
- self_put_number_cell(rowx, colx, float(d), self.fixed_BIFF2_xfindex(cell_attr, rowx, colx))
- elif rc == XL_LABEL_B2:
- rowx, colx, cell_attr = local_unpack('<HH3s', data[0:7])
- strg = unpack_string(data, 7, bk.encoding or bk.derive_encoding(), lenlen=1)
- self_put_cell(rowx, colx, XL_CELL_TEXT, strg, self.fixed_BIFF2_xfindex(cell_attr, rowx, colx))
- elif rc == XL_BOOLERR_B2:
- rowx, colx, cell_attr, value, is_err = local_unpack('<HH3sBB', data)
- cellty = (XL_CELL_BOOLEAN, XL_CELL_ERROR)[is_err]
- # if DEBUG: print "XL_BOOLERR_B2", rowx, colx, cell_attr, value, is_err
- self.put_cell(rowx, colx, cellty, value, self.fixed_BIFF2_xfindex(cell_attr, rowx, colx))
- elif rc == XL_BLANK_B2:
- if not fmt_info: continue
- rowx, colx, cell_attr = local_unpack('<HH3s', data[:7])
- self_put_blank_cell(rowx, colx, self.fixed_BIFF2_xfindex(cell_attr, rowx, colx))
- elif rc == XL_EFONT:
- bk.handle_efont(data)
- elif rc == XL_ROW_B2:
- if not fmt_info: continue
- rowx, bits1, has_defaults = local_unpack('<H4xH2xB', data[0:11])
- if not(0 <= rowx < self.utter_max_rows):
- print >> self.logfile, \
- "*** NOTE: ROW_B2 record has row index %d; " \
- "should have 0 <= rowx < %d -- record ignored!" \
- % (rowx, self.utter_max_rows)
- continue
- r = Rowinfo()
- r.height = bits1 & 0x7fff
- r.has_default_height = (bits1 >> 15) & 1
- r.outline_level = 0
- r.outline_group_starts_ends = 0
- r.hidden = 0
- r.height_mismatch = 0
- r.has_default_xf_index = has_defaults & 1
- r.additional_space_above = 0
- r.additional_space_below = 0
- if not r.has_default_xf_index:
- r.xf_index = -1
- elif data_len == 18:
- # Seems the XF index in the cell_attr is dodgy
- xfx = local_unpack('<H', data[16:18])[0]
- r.xf_index = self.fixed_BIFF2_xfindex(cell_attr=None, rowx=rowx, colx=-1, true_xfx=xfx)
- else:
- cell_attr = data[13:16]
- r.xf_index = self.fixed_BIFF2_xfindex(cell_attr, rowx, colx=-1)
- self.rowinfo_map[rowx] = r
- if 0 and r.xf_index > -1:
- fprintf(self.logfile,
- "**ROW %d %d %d\n",
- self.number, rowx, r.xf_index)
- if blah_rows:
- print >> self.logfile, 'ROW_B2', rowx, bits1, has_defaults
- r.dump(self.logfile,
- header="--- sh #%d, rowx=%d ---" % (self.number, rowx))
- elif rc == XL_COLWIDTH: # BIFF2 only
- if not fmt_info: continue
- first_colx, last_colx, width\
- = local_unpack("<BBH", data[:4])
- if not(first_colx <= last_colx):
- print >> self.logfile, \
- "*** NOTE: COLWIDTH record has first col index %d, last %d; " \
- "should have first <= last -- record ignored!" \
- % (first_colx, last_colx)
- continue
- for colx in xrange(first_colx, last_colx+1):
- if self.colinfo_map.has_key(colx):
- c = self.colinfo_map[colx]
- else:
- c = Colinfo()
- self.colinfo_map[colx] = c
- c.width = width
- if blah:
- fprintf(
- self.logfile,
- "COLWIDTH sheet #%d cols %d-%d: wid=%d\n",
- self.number, first_colx, last_colx, width
- )
- elif rc == XL_COLUMNDEFAULT: # BIFF2 only
- if not fmt_info: continue
- first_colx, last_colx = local_unpack("<HH", data[:4])
- #### Warning OOo docs wrong; first_colx <= colx < last_colx
- if blah:
- fprintf(
- self.logfile,
- "COLUMNDEFAULT sheet #%d cols in range(%d, %d)\n",
- self.number, first_colx, last_colx
- )
- if not(0 <= first_colx < last_colx <= 256):
- print >> self.logfile, \
- "*** NOTE: COLUMNDEFAULT record has first col index %d, last %d; " \
- "should have 0 <= first < last <= 256" \
- % (first_colx, last_colx)
- last_colx = min(last_colx, 256)
- for colx in xrange(first_colx, last_colx):
- offset = 4 + 3 * (colx - first_colx)
- cell_attr = data[offset:offset+3]
- xf_index = self.fixed_BIFF2_xfindex(cell_attr, rowx=-1, colx=colx)
- if self.colinfo_map.has_key(colx):
- c = self.colinfo_map[colx]
- else:
- c = Colinfo()
- self.colinfo_map[colx] = c
- c.xf_index = xf_index
- else:
- # if DEBUG: print "SHEET.READ: Unhandled record type %02x %d bytes %r" % (rc, data_len, data)
- pass
- if not eof_found:
- raise XLRDError("Sheet %d (%r) missing EOF record" \
- % (self.number, self.name))
- self.tidy_dimensions()
- bk._position = oldpos
- return 1
-
- def fixed_BIFF2_xfindex(self, cell_attr, rowx, colx, true_xfx=None):
- DEBUG = 0
- blah = DEBUG or self.verbosity >= 2
- if self.biff_version == 21:
- if self._xf_index_to_xl_type_map:
- if true_xfx is not None:
- xfx = true_xfx
- else:
- xfx = ord(cell_attr[0]) & 0x3F
- if xfx == 0x3F:
- if self._ixfe is None:
- raise XLRDError("BIFF2 cell record has XF index 63 but no preceding IXFE record.")
- xfx = self._ixfe
- # OOo docs are capable of interpretation that each
- # cell record is preceded immediately by its own IXFE record.
- # Empirical evidence is that (sensibly) an IXFE record applies to all
- # following cell records until another IXFE comes along.
- return xfx
- # Have either Excel 2.0, or broken 2.1 w/o XF records -- same effect.
- self.biff_version = self.book.biff_version = 20
- #### check that XF slot in cell_attr is zero
- xfx_slot = ord(cell_attr[0]) & 0x3F
- assert xfx_slot == 0
- xfx = self._cell_attr_to_xfx.get(cell_attr)
- if xfx is not None:
- return xfx
- if blah:
- fprintf(self.logfile, "New cell_attr %r at (%r, %r)\n", cell_attr, rowx, colx)
- book = self.book
- xf = self.fake_XF_from_BIFF20_cell_attr(cell_attr)
- xfx = len(book.xf_list)
- xf.xf_index = xfx
- book.xf_list.append(xf)
- if blah:
- xf.dump(self.logfile, header="=== Faked XF %d ===" % xfx, footer="======")
- if not book.format_map.has_key(xf.format_key):
- msg = "ERROR *** XF[%d] unknown format key (%d, 0x%04x)\n"
- fprintf(self.logfile, msg,
- xf.xf_index, xf.format_key, xf.format_key)
- fmt = Format(xf.format_key, FUN, u"General")
- book.format_map[xf.format_key] = fmt
- while len(book.format_list) <= xf.format_key:
- book.format_list.append(fmt)
- cellty_from_fmtty = {
- FNU: XL_CELL_NUMBER,
- FUN: XL_CELL_NUMBER,
- FGE: XL_CELL_NUMBER,
- FDT: XL_CELL_DATE,
- FTX: XL_CELL_NUMBER, # Yes, a number can be formatted as text.
- }
- fmt = book.format_map[xf.format_key]
- cellty = cellty_from_fmtty[fmt.type]
- self._xf_index_to_xl_type_map[xf.xf_index] = cellty
- self._cell_attr_to_xfx[cell_attr] = xfx
- return xfx
-
- def fake_XF_from_BIFF20_cell_attr(self, cell_attr):
- from formatting import XF, XFAlignment, XFBorder, XFBackground, XFProtection
- xf = XF()
- xf.alignment = XFAlignment()
- xf.alignment.indent_level = 0
- xf.alignment.shrink_to_fit = 0
- xf.alignment.text_direction = 0
- xf.border = XFBorder()
- xf.border.diag_up = 0
- xf.border.diag_down = 0
- xf.border.diag_colour_index = 0
- xf.border.diag_line_style = 0 # no line
- xf.background = XFBackground()
- xf.protection = XFProtection()
- (prot_bits, font_and_format, halign_etc) = unpack('<BBB', cell_attr)
- xf.format_key = font_and_format & 0x3F
- xf.font_index = (font_and_format & 0xC0) >> 6
- upkbits(xf.protection, prot_bits, (
- (6, 0x40, 'cell_locked'),
- (7, 0x80, 'formula_hidden'),
- ))
- xf.alignment.hor_align = halign_etc & 0x07
- for mask, side in ((0x08, 'left'), (0x10, 'right'), (0x20, 'top'), (0x40, 'bottom')):
- if halign_etc & mask:
- colour_index, line_style = 8, 1 # black, thin
- else:
- colour_index, line_style = 0, 0 # none, none
- setattr(xf.border, side + '_colour_index', colour_index)
- setattr(xf.border, side + '_line_style', line_style)
- bg = xf.background
- if halign_etc & 0x80:
- bg.fill_pattern = 17
- else:
- bg.fill_pattern = 0
- bg.background_colour_index = 9 # white
- bg.pattern_colour_index = 8 # black
- xf.parent_style_index = 0 # ???????????
- xf.alignment.vert_align = 2 # bottom
- xf.alignment.rotation = 0
- for attr_stem in \
- "format font alignment border background protection".split():
- attr = "_" + attr_stem + "_flag"
- setattr(xf, attr, 1)
- return xf
-
- def req_fmt_info(self):
- if not self.formatting_info:
- raise XLRDError("Feature requires open_workbook(..., formatting_info=True)")
-
- ##
- # Determine column display width.
- # <br /> -- New in version 0.6.1
- # <br />
- # @param colx Index of the queried column, range 0 to 255.
- # Note that it is possible to find out the width that will be used to display
- # columns with no cell information e.g. column IV (colx=255).
- # @return The column width that will be used for displaying
- # the given column by Excel, in units of 1/256th of the width of a
- # standard character (the digit zero in the first font).
-
- def computed_column_width(self, colx):
- self.req_fmt_info()
- if self.biff_version >= 80:
- colinfo = self.colinfo_map.get(colx, None)
- if colinfo is not None:
- return colinfo.width
- if self.standardwidth is not None:
- return self.standardwidth
- elif self.biff_version >= 40:
- if self.gcw[colx]:
- if self.standardwidth is not None:
- return self.standardwidth
- else:
- colinfo = self.colinfo_map.get(colx, None)
- if colinfo is not None:
- return colinfo.width
- elif self.biff_version == 30:
- colinfo = self.colinfo_map.get(colx, None)
- if colinfo is not None:
- return colinfo.width
- # All roads lead to Rome and the DEFCOLWIDTH ...
- if self.defcolwidth is not None:
- return self.defcolwidth * 256
- return 8 * 256 # 8 is what Excel puts in a DEFCOLWIDTH record
-
- def handle_msodrawingetc(self, recid, data_len, data):
- if not OBJ_MSO_DEBUG:
- return
- DEBUG = 1
- if self.biff_version < 80:
- return
- o = MSODrawing()
- pos = 0
- while pos < data_len:
- tmp, fbt, cb = unpack('<HHI', data[pos:pos+8])
- ver = tmp & 0xF
- inst = (tmp >> 4) & 0xFFF
- if ver == 0xF:
- ndb = 0 # container
- else:
- ndb = cb
- if DEBUG:
- hex_char_dump(data, pos, ndb + 8, base=0, fout=self.logfile)
- fprintf(self.logfile,
- "fbt:0x%04X inst:%d ver:0x%X cb:%d (0x%04X)\n",
- fbt, inst, ver, cb, cb)
- if fbt == 0xF010: # Client Anchor
- assert ndb == 18
- (o.anchor_unk,
- o.anchor_colx_lo, o.anchor_rowx_lo,
- o.anchor_colx_hi, o.anchor_rowx_hi) = unpack('<Hiiii', data[pos+8:pos+8+ndb])
- elif fbt == 0xF011: # Client Data
- # must be followed by an OBJ record
- assert cb == 0
- assert pos + 8 == data_len
- else:
- pass
- pos += ndb + 8
- else:
- # didn't break out of while loop
- assert pos == data_len
- if DEBUG:
- o.dump(self.logfile, header="=== MSODrawing ===", footer= " ")
-
-
- def handle_obj(self, data):
- if not OBJ_MSO_DEBUG:
- return
- DEBUG = 1
- if self.biff_version < 80:
- return
- o = MSObj()
- data_len = len(data)
- pos = 0
- if DEBUG:
- fprintf(self.logfile, "... OBJ record ...\n")
- while pos < data_len:
- ft, cb = unpack('<HH', data[pos:pos+4])
- if DEBUG:
- hex_char_dump(data, pos, cb, base=0, fout=self.logfile)
- if ft == 0x15: # ftCmo ... s/b first
- assert pos == 0
- o.type, o.id, option_flags = unpack('<HHH', data[pos+4:pos+10])
- upkbits(o, option_flags, (
- ( 0, 0x0001, 'locked'),
- ( 4, 0x0010, 'printable'),
- ( 8, 0x0100, 'autofilter'), # not documented in Excel 97 dev kit
- ( 9, 0x0200, 'scrollbar_flag'), # not documented in Excel 97 dev kit
- (13, 0x2000, 'autofill'),
- (14, 0x4000, 'autoline'),
- ))
- elif ft == 0x00:
- assert cb == 0
- assert pos + 4 == data_len
- elif ft == 0x0C: # Scrollbar
- values = unpack('<5H', data[pos+8:pos+18])
- for value, tag in zip(values, ('value', 'min', 'max', 'inc', 'page')):
- setattr(o, 'scrollbar_' + tag, value)
- elif ft == 0x0D: # "Notes structure" [used for cell comments]
- pass ############## not documented in Excel 97 dev kit
- elif ft == 0x13: # list box data
- if o.autofilter: # non standard exit. NOT documented
- break
- else:
- pass
- pos += cb + 4
- else:
- # didn't break out of while loop
- assert pos == data_len
- if DEBUG:
- o.dump(self.logfile, header="=== MSOBj ===", footer= " ")
-
- def handle_note(self, data):
- if not OBJ_MSO_DEBUG:
- return
- DEBUG = 1
- if self.biff_version < 80:
- return
- if DEBUG:
- fprintf(self.logfile, '... NOTE record ...\n')
- hex_char_dump(data, 0, len(data), base=0, fout=self.logfile)
- o = MSNote()
- data_len = len(data)
- o.rowx, o.colx, option_flags, o.object_id = unpack('<4H', data[:8])
- o.show = (option_flags >> 1) & 1
- # Docs say NULL [sic] bytes padding between string count and string data
- # to ensure that string is word-aligned. Appears to be nonsense.
- # There also seems to be a random(?) byte after the string (not counted in the
- # string length.
- o.original_author, endpos = unpack_unicode_update_pos(data, 8, lenlen=2)
- assert endpos == data_len - 1
- o.last_byte = data[-1]
- if DEBUG:
- o.dump(self.logfile, header="=== MSNote ===", footer= " ")
-
- def handle_txo(self, data):
- if not OBJ_MSO_DEBUG:
- return
- DEBUG = 1
- if self.biff_version < 80:
- return
- o = MSTxo()
- data_len = len(data)
- option_flags, o.rot, cchText, cbRuns = unpack('<HH6xHH4x', data)
- upkbits(o, option_flags, (
- (3, 0x000E, 'horz_align'),
- (6, 0x0070, 'vert_align'),
- (9, 0x0200, 'lock_text'),
- ))
- rc2, data2_len, data2 = self.book.get_record_parts()
- assert rc2 == XL_CONTINUE
- o.text, endpos = unpack_unicode_update_pos(data2, 0, known_len=cchText)
- assert endpos == data2_len
- rc3, data3_len, data3 = self.book.get_record_parts()
- assert rc3 == XL_CONTINUE
- # ignore the formatting runs for the moment
- if DEBUG:
- o.dump(self.logfile, header="=== MSTxo ===", footer= " ")
-
- def handle_feat11(self, data):
- if not OBJ_MSO_DEBUG:
- return
- # rt: Record type; this matches the BIFF rt in the first two bytes of the record; =0872h
- # grbitFrt: FRT cell reference flag (see table below for details)
- # Ref0: Range reference to a worksheet cell region if grbitFrt=1 (bitFrtRef). Otherwise blank.
- # isf: Shared feature type index =5 for Table
- # fHdr: =0 since this is for feat not feat header
- # reserved0: Reserved for future use =0 for Table
- # cref: Count of ref ranges this feature is on
- # cbFeatData: Count of byte for the current feature data.
- # reserved1: =0 currently not used
- # Ref1: Repeat of Ref0. UNDOCUMENTED
- rt, grbitFrt, Ref0, isf, fHdr, reserved0, cref, cbFeatData, reserved1, Ref1 = unpack('<HH8sHBiHiH8s', data[0:35])
- assert reserved0 == 0
- assert reserved1 == 0
- assert isf == 5
- assert rt == 0x872
- assert fHdr == 0
- assert Ref1 == Ref0
- print "FEAT11: grbitFrt=%d Ref0=%r cref=%d cbFeatData=%d" % (grbitFrt, Ref0, cref, cbFeatData)
- # lt: Table data source type:
- # =0 for Excel Worksheet Table =1 for read-write SharePoint linked List
- # =2 for XML mapper Table =3 for Query Table
- # idList: The ID of the Table (unique per worksheet)
- # crwHeader: How many header/title rows the Table has at the top
- # crwTotals: How many total rows the Table has at the bottom
- # idFieldNext: Next id to try when assigning a unique id to a new field
- # cbFSData: The size of the Fixed Data portion of the Table data structure.
- # rupBuild: the rupBuild that generated the record
- # unusedShort: UNUSED short that can be used later. The value is reserved during round-tripping.
- # listFlags: Collection of bit flags: (see listFlags' bit setting table below for detail.)
- # lPosStmCache: Table data stream position of cached data
- # cbStmCache: Count of bytes of cached data
- # cchStmCache: Count of characters of uncompressed cached data in the stream
- # lem: Table edit mode (see List (Table) Editing Mode (lem) setting table below for details.)
- # rgbHashParam: Hash value for SharePoint Table
- # cchName: Count of characters in the Table name string rgbName
- (lt, idList, crwHeader, crwTotals, idFieldNext, cbFSData,
- rupBuild, unusedShort, listFlags, lPosStmCache, cbStmCache,
- cchStmCache, lem, rgbHashParam, cchName) = unpack('<iiiiiiHHiiiii16sH', data[35:35+66])
- print "lt=%d idList=%d crwHeader=%d crwTotals=%d idFieldNext=%d cbFSData=%d\n"\
- "rupBuild=%d unusedShort=%d listFlags=%04X lPosStmCache=%d cbStmCache=%d\n"\
- "cchStmCache=%d lem=%d rgbHashParam=%r cchName=%d" % (
- lt, idList, crwHeader, crwTotals, idFieldNext, cbFSData,
- rupBuild, unusedShort,listFlags, lPosStmCache, cbStmCache,
- cchStmCache, lem, rgbHashParam, cchName)
-
-class MSODrawing(BaseObject):
- pass
-
-class MSObj(BaseObject):
- pass
-
-class MSTxo(BaseObject):
- pass
-
-class MSNote(BaseObject):
- pass
-
-# === helpers ===
-
-def unpack_RK(rk_str):
- flags = ord(rk_str[0])
- if flags & 2:
- # There's a SIGNED 30-bit integer in there!
- i, = unpack('<i', rk_str)
- i >>= 2 # div by 4 to drop the 2 flag bits
- if flags & 1:
- return i / 100.0
- return float(i)
- else:
- # It's the most significant 30 bits of an IEEE 754 64-bit FP number
- d, = unpack('<d', '\0\0\0\0' + chr(flags & 252) + rk_str[1:4])
- if flags & 1:
- return d / 100.0
- return d
-
-##### =============== Cell ======================================== #####
-
-cellty_from_fmtty = {
- FNU: XL_CELL_NUMBER,
- FUN: XL_CELL_NUMBER,
- FGE: XL_CELL_NUMBER,
- FDT: XL_CELL_DATE,
- FTX: XL_CELL_NUMBER, # Yes, a number can be formatted as text.
- }
-
-ctype_text = {
- XL_CELL_EMPTY: 'empty',
- XL_CELL_TEXT: 'text',
- XL_CELL_NUMBER: 'number',
- XL_CELL_DATE: 'xldate',
- XL_CELL_BOOLEAN: 'bool',
- XL_CELL_ERROR: 'error',
- XL_CELL_BLANK: 'blank',
- }
-
-##
-# <p>Contains the data for one cell.</p>
-#
-# <p>WARNING: You don't call this class yourself. You access Cell objects
-# via methods of the Sheet object(s) that you found in the Book object that
-# was returned when you called xlrd.open_workbook("myfile.xls").</p>
-# <p> Cell objects have three attributes: <i>ctype</i> is an int, <i>value</i>
-# (which depends on <i>ctype</i>) and <i>xf_index</i>.
-# If "formatting_info" is not enabled when the workbook is opened, xf_index will be None.
-# The following table describes the types of cells and how their values
-# are represented in Python.</p>
-#
-# <table border="1" cellpadding="7">
-# <tr>
-# <th>Type symbol</th>
-# <th>Type number</th>
-# <th>Python value</th>
-# </tr>
-# <tr>
-# <td>XL_CELL_EMPTY</td>
-# <td align="center">0</td>
-# <td>empty string u''</td>
-# </tr>
-# <tr>
-# <td>XL_CELL_TEXT</td>
-# <td align="center">1</td>
-# <td>a Unicode string</td>
-# </tr>
-# <tr>
-# <td>XL_CELL_NUMBER</td>
-# <td align="center">2</td>
-# <td>float</td>
-# </tr>
-# <tr>
-# <td>XL_CELL_DATE</td>
-# <td align="center">3</td>
-# <td>float</td>
-# </tr>
-# <tr>
-# <td>XL_CELL_BOOLEAN</td>
-# <td align="center">4</td>
-# <td>int; 1 means TRUE, 0 means FALSE</td>
-# </tr>
-# <tr>
-# <td>XL_CELL_ERROR</td>
-# <td align="center">5</td>
-# <td>int representing internal Excel codes; for a text representation,
-# refer to the supplied dictionary error_text_from_code</td>
-# </tr>
-# <tr>
-# <td>XL_CELL_BLANK</td>
-# <td align="center">6</td>
-# <td>empty string u''. Note: this type will appear only when
-# open_workbook(..., formatting_info=True) is used.</td>
-# </tr>
-# </table>
-#<p></p>
-
-class Cell(BaseObject):
-
- __slots__ = ['ctype', 'value', 'xf_index']
-
- def __init__(self, ctype, value, xf_index=None):
- self.ctype = ctype
- self.value = value
- self.xf_index = xf_index
-
- def __repr__(self):
- if self.xf_index is None:
- return "%s:%r" % (ctype_text[self.ctype], self.value)
- else:
- return "%s:%r (XF:%r)" % (ctype_text[self.ctype], self.value, self.xf_index)
-
-##
-# There is one and only one instance of an empty cell -- it's a singleton. This is it.
-# You may use a test like "acell is empty_cell".
-empty_cell = Cell(XL_CELL_EMPTY, '')
-
-##### =============== Colinfo and Rowinfo ============================== #####
-
-##
-# Width and default formatting information that applies to one or
-# more columns in a sheet. Derived from COLINFO records.
-#
-# <p> Here is the default hierarchy for width, according to the OOo docs:
-#
-# <br />"""In BIFF3, if a COLINFO record is missing for a column,
-# the width specified in the record DEFCOLWIDTH is used instead.
-#
-# <br />In BIFF4-BIFF7, the width set in this [COLINFO] record is only used,
-# if the corresponding bit for this column is cleared in the GCW
-# record, otherwise the column width set in the DEFCOLWIDTH record
-# is used (the STANDARDWIDTH record is always ignored in this case [see footnote!]).
-#
-# <br />In BIFF8, if a COLINFO record is missing for a column,
-# the width specified in the record STANDARDWIDTH is used.
-# If this [STANDARDWIDTH] record is also missing,
-# the column width of the record DEFCOLWIDTH is used instead."""
-# <br />
-#
-# Footnote: The docs on the GCW record say this:
-# """<br />
-# If a bit is set, the corresponding column uses the width set in the STANDARDWIDTH
-# record. If a bit is cleared, the corresponding column uses the width set in the
-# COLINFO record for this column.
-# <br />If a bit is set, and the worksheet does not contain the STANDARDWIDTH record, or if
-# the bit is cleared, and the worksheet does not contain the COLINFO record, the DEFCOLWIDTH
-# record of the worksheet will be used instead.
-# <br />"""<br />
-# At the moment (2007-01-17) xlrd is going with the GCW version of the story.
-# Reference to the source may be useful: see the computed_column_width(colx) method
-# of the Sheet class.
-# <br />-- New in version 0.6.1
-# </p>
-
-class Colinfo(BaseObject):
- ##
- # Width of the column in 1/256 of the width of the zero character,
- # using default font (first FONT record in the file).
- width = 0
- ##
- # XF index to be used for formatting empty cells.
- xf_index = -1
- ##
- # 1 = column is hidden
- hidden = 0
- ##
- # Value of a 1-bit flag whose purpose is unknown
- # but is often seen set to 1
- bit1_flag = 0
- ##
- # Outline level of the column, in range(7).
- # (0 = no outline)
- outline_level = 0
- ##
- # 1 = column is collapsed
- collapsed = 0
-
-##
-# Height and default formatting information that applies to a row in a sheet.
-# Derived from ROW records.
-# <br /> -- New in version 0.6.1
-
-class Rowinfo(BaseObject):
- ##
- # Height of the row, in twips. One twip == 1/20 of a point
- height = 0
- ##
- # 0 = Row has custom height; 1 = Row has default height
- has_default_height = 0
- ##
- # Outline level of the row
- outline_level = 0
- ##
- # 1 = Outline group starts or ends here (depending on where the
- # outline buttons are located, see WSBOOL record [TODO ??]),
- # <i>and</i> is collapsed
- outline_group_starts_ends = 0
- ##
- # 1 = Row is hidden (manually, or by a filter or outline group)
- hidden = 0
- ##
- # 1 = Row height and default font height do not match
- height_mismatch = 0
- ##
- # 1 = the xf_index attribute is usable; 0 = ignore it
- has_default_xf_index = 0
- ##
- # Index to default XF record for empty cells in this row.
- # Don't use this if has_default_xf_index == 0.
- xf_index = -9999
- ##
- # This flag is set, if the upper border of at least one cell in this row
- # or if the lower border of at least one cell in the row above is
- # formatted with a thick line style. Thin and medium line styles are not
- # taken into account.
- additional_space_above = 0
- ##
- # This flag is set, if the lower border of at least one cell in this row
- # or if the upper border of at least one cell in the row below is
- # formatted with a medium or thick line style. Thin line styles are not
- # taken into account.
- additional_space_below = 0
diff --git a/tablib/packages/xlrd/timemachine.py b/tablib/packages/xlrd/timemachine.py
deleted file mode 100644
index 1718c03..0000000
--- a/tablib/packages/xlrd/timemachine.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# -*- coding: cp1252 -*-
-
-##
-# <p>Copyright 2006-2008 Stephen John Machin, Lingfo Pty Ltd</p>
-# <p>This module is part of the xlrd package, which is released under a BSD-style licence.</p>
-##
-
-# timemachine.py -- adaptation for earlier Pythons e.g. 2.1
-# usage: from timemachine import *
-
-# 2008-02-08 SJM Generalised method of detecting IronPython
-
-import sys
-
-python_version = sys.version_info[:2] # e.g. version 2.4 -> (2, 4)
-
-CAN_PICKLE_ARRAY = python_version >= (2, 5)
-CAN_SUBCLASS_BUILTIN = python_version >= (2, 2)
-
-if sys.version.find("IronPython") >= 0:
- array_array = None
-else:
- from array import array as array_array
-
-if python_version < (2, 2):
- class object:
- pass
- False = 0
- True = 1
-
-def int_floor_div(x, y):
- return divmod(x, y)[0]
-
-def intbool(x):
- if x:
- return 1
- return 0
-
-if python_version < (2, 3):
- def sum(sequence, start=0):
- tot = start
- for item in aseq:
- tot += item
- return tot
diff --git a/tablib/packages/xlrd/xldate.py b/tablib/packages/xlrd/xldate.py
deleted file mode 100644
index e5f7591..0000000
--- a/tablib/packages/xlrd/xldate.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# -*- coding: cp1252 -*-
-
-# No part of the content of this file was derived from the works of David Giffin.
-
-##
-# <p>Copyright 2005-2008 Stephen John Machin, Lingfo Pty Ltd</p>
-# <p>This module is part of the xlrd package, which is released under a BSD-style licence.</p>
-#
-# <p>Provides function(s) for dealing with Microsoft Excel dates.</p>
-##
-
-# 2008-10-18 SJM Fix bug in xldate_from_date_tuple (affected some years after 2099)
-
-# The conversion from days to (year, month, day) starts with
-# an integral "julian day number" aka JDN.
-# FWIW, JDN 0 corresponds to noon on Monday November 24 in Gregorian year -4713.
-# More importantly:
-# Noon on Gregorian 1900-03-01 (day 61 in the 1900-based system) is JDN 2415080.0
-# Noon on Gregorian 1904-01-02 (day 1 in the 1904-based system) is JDN 2416482.0
-
-from timemachine import int_floor_div as ifd
-
-_JDN_delta = (2415080 - 61, 2416482 - 1)
-assert _JDN_delta[1] - _JDN_delta[0] == 1462
-
-class XLDateError(ValueError): pass
-
-class XLDateNegative(XLDateError): pass
-class XLDateAmbiguous(XLDateError): pass
-class XLDateTooLarge(XLDateError): pass
-class XLDateBadDatemode(XLDateError): pass
-class XLDateBadTuple(XLDateError): pass
-
-_XLDAYS_TOO_LARGE = (2958466, 2958466 - 1462) # This is equivalent to 10000-01-01
-
-##
-# Convert an Excel number (presumed to represent a date, a datetime or a time) into
-# a tuple suitable for feeding to datetime or mx.DateTime constructors.
-# @param xldate The Excel number
-# @param datemode 0: 1900-based, 1: 1904-based.
-# <br>WARNING: when using this function to
-# interpret the contents of a workbook, you should pass in the Book.datemode
-# attribute of that workbook. Whether
-# the workbook has ever been anywhere near a Macintosh is irrelevant.
-# @return Gregorian (year, month, day, hour, minute, nearest_second).
-# <br>Special case: if 0.0 <= xldate < 1.0, it is assumed to represent a time;
-# (0, 0, 0, hour, minute, second) will be returned.
-# <br>Note: 1904-01-01 is not regarded as a valid date in the datemode 1 system; its "serial number"
-# is zero.
-# @throws XLDateNegative xldate < 0.00
-# @throws XLDateAmbiguous The 1900 leap-year problem (datemode == 0 and 1.0 <= xldate < 61.0)
-# @throws XLDateTooLarge Gregorian year 10000 or later
-# @throws XLDateBadDatemode datemode arg is neither 0 nor 1
-# @throws XLDateError Covers the 4 specific errors
-
-def xldate_as_tuple(xldate, datemode):
- if datemode not in (0, 1):
- raise XLDateBadDatemode(datemode)
- if xldate == 0.00:
- return (0, 0, 0, 0, 0, 0)
- if xldate < 0.00:
- raise XLDateNegative(xldate)
- xldays = int(xldate)
- frac = xldate - xldays
- seconds = int(round(frac * 86400.0))
- assert 0 <= seconds <= 86400
- if seconds == 86400:
- hour = minute = second = 0
- xldays += 1
- else:
- # second = seconds % 60; minutes = seconds // 60
- minutes, second = divmod(seconds, 60)
- # minute = minutes % 60; hour = minutes // 60
- hour, minute = divmod(minutes, 60)
- if xldays >= _XLDAYS_TOO_LARGE[datemode]:
- raise XLDateTooLarge(xldate)
-
- if xldays == 0:
- return (0, 0, 0, hour, minute, second)
-
- if xldays < 61 and datemode == 0:
- raise XLDateAmbiguous(xldate)
-
- jdn = xldays + _JDN_delta[datemode]
- yreg = (ifd(ifd(jdn * 4 + 274277, 146097) * 3, 4) + jdn + 1363) * 4 + 3
- mp = ifd(yreg % 1461, 4) * 535 + 333
- d = ifd(mp % 16384, 535) + 1
- # mp /= 16384
- mp >>= 14
- if mp >= 10:
- return (ifd(yreg, 1461) - 4715, mp - 9, d, hour, minute, second)
- else:
- return (ifd(yreg, 1461) - 4716, mp + 3, d, hour, minute, second)
-
-# === conversions from date/time to xl numbers
-
-def _leap(y):
- if y % 4: return 0
- if y % 100: return 1
- if y % 400: return 0
- return 1
-
-_days_in_month = (None, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
-
-##
-# Convert a date tuple (year, month, day) to an Excel date.
-# @param year Gregorian year.
-# @param month 1 <= month <= 12
-# @param day 1 <= day <= last day of that (year, month)
-# @param datemode 0: 1900-based, 1: 1904-based.
-# @throws XLDateAmbiguous The 1900 leap-year problem (datemode == 0 and 1.0 <= xldate < 61.0)
-# @throws XLDateBadDatemode datemode arg is neither 0 nor 1
-# @throws XLDateBadTuple (year, month, day) is too early/late or has invalid component(s)
-# @throws XLDateError Covers the specific errors
-
-def xldate_from_date_tuple((year, month, day), datemode):
-
- if datemode not in (0, 1):
- raise XLDateBadDatemode(datemode)
-
- if year == 0 and month == 0 and day == 0:
- return 0.00
-
- if not (1900 <= year <= 9999):
- raise XLDateBadTuple("Invalid year: %r" % ((year, month, day),))
- if not (1 <= month <= 12):
- raise XLDateBadTuple("Invalid month: %r" % ((year, month, day),))
- if day < 1 \
- or (day > _days_in_month[month] and not(day == 29 and month == 2 and _leap(year))):
- raise XLDateBadTuple("Invalid day: %r" % ((year, month, day),))
-
- Yp = year + 4716
- M = month
- if M <= 2:
- Yp = Yp - 1
- Mp = M + 9
- else:
- Mp = M - 3
- jdn = ifd(1461 * Yp, 4) + ifd(979 * Mp + 16, 32) + \
- day - 1364 - ifd(ifd(Yp + 184, 100) * 3, 4)
- xldays = jdn - _JDN_delta[datemode]
- if xldays <= 0:
- raise XLDateBadTuple("Invalid (year, month, day): %r" % ((year, month, day),))
- if xldays < 61 and datemode == 0:
- raise XLDateAmbiguous("Before 1900-03-01: %r" % ((year, month, day),))
- return float(xldays)
-
-##
-# Convert a time tuple (hour, minute, second) to an Excel "date" value (fraction of a day).
-# @param hour 0 <= hour < 24
-# @param minute 0 <= minute < 60
-# @param second 0 <= second < 60
-# @throws XLDateBadTuple Out-of-range hour, minute, or second
-
-def xldate_from_time_tuple((hour, minute, second)):
- if 0 <= hour < 24 and 0 <= minute < 60 and 0 <= second < 60:
- return ((second / 60.0 + minute) / 60.0 + hour) / 24.0
- raise XLDateBadTuple("Invalid (hour, minute, second): %r" % ((hour, minute, second),))
-
-##
-# Convert a datetime tuple (year, month, day, hour, minute, second) to an Excel date value.
-# For more details, refer to other xldate_from_*_tuple functions.
-# @param datetime_tuple (year, month, day, hour, minute, second)
-# @param datemode 0: 1900-based, 1: 1904-based.
-
-def xldate_from_datetime_tuple(datetime_tuple, datemode):
- return (
- xldate_from_date_tuple(datetime_tuple[:3], datemode)
- +
- xldate_from_time_tuple(datetime_tuple[3:])
- )
diff --git a/tablib/packages/xlrd3/__init__.py b/tablib/packages/xlrd3/__init__.py
deleted file mode 100644
index 98f322b..0000000
--- a/tablib/packages/xlrd3/__init__.py
+++ /dev/null
@@ -1,1642 +0,0 @@
-# Copyright © 2005-2009 Stephen John Machin, Lingfo Pty Ltd
-# This module is part of the xlrd3 package, which is released under a
-# BSD-style licence.
-#
-# xlrd3, the Python 3 port of xlrd v0.7.1
-#
-# A Python module for extracting data from MS Excel spreadsheet files.
-#
-# General information
-#
-# Acknowledgements
-#
-# Development of this module would not have been possible without the document
-# "OpenOffice.org's Documentation of the Microsoft Excel File Format"
-# ("OOo docs" for short).
-# The latest version is available from OpenOffice.org in
-# http://sc.openoffice.org/excelfileformat.pdf PDF format
-# and
-# http://sc.openoffice.org/excelfileformat.odt ODT format.
-# Small portions of the OOo docs are reproduced in this
-# document. A study of the OOo docs is recommended for those who wish a
-# deeper understanding of the Excel file layout than the xlrd docs can provide.
-#
-# Provision of formatting information in version 0.6.1 was funded by
-# http://www.simplistix.co.uk Simplistix Ltd.
-#
-# Unicode
-#
-# This module presents all text strings as Python unicode objects.
-# From Excel 97 onwards, text in Excel spreadsheets has been stored as Unicode.
-# Older files (Excel 95 and earlier) don't keep strings in Unicode;
-# a CODEPAGE record provides a codepage number (for example, 1252) which is
-# used by xlrd to derive the encoding (for same example: "cp1252") which is
-# used to translate to Unicode.
-#
-# If the CODEPAGE record is missing (possible if the file was created
-# by third-party software), xlrd will assume that the encoding is ascii, and keep going.
-# If the actual encoding is not ascii, a UnicodeDecodeError exception will be raised and
-# you will need to determine the encoding yourself, and tell xlrd::
-#
-# book = xlrd.open_workbook(..., encoding_override="cp1252")
-#
-# If the CODEPAGE record exists but is wrong (for example, the codepage
-# number is 1251, but the strings are actually encoded in koi8_r),
-# it can be overridden using the same mechanism.
-# The supplied runxlrd.py has a corresponding command-line argument, which
-# may be used for experimentation::
-#
-# runxlrd.py -e koi8_r 3rows myfile.xls
-#
-# The first place to look for an encoding ("codec name") is
-# http://docs.python.org/lib/standard-encodings.html
-# the Python documentation.
-#
-# Dates in Excel spreadsheets
-#
-# In reality, there are no such things. What you have are floating point
-# numbers and pious hope.
-# There are several problems with Excel dates:
-#
-# (1) Dates are not stored as a separate data type; they are stored as
-# floating point numbers and you have to rely on
-# (a) the "number format" applied to them in Excel and/or
-# (b) knowing which cells are supposed to have dates in them.
-# This module helps with (a) by inspecting the
-# format that has been applied to each number cell;
-# if it appears to be a date format, the cell
-# is classified as a date rather than a number. Feedback on this feature,
-# especially from non-English-speaking locales, would be appreciated.
-#
-# (2) Excel for Windows stores dates by default as the number of
-# days (or fraction thereof) since 1899-12-31T00:00:00. Excel for
-# Macintosh uses a default start date of 1904-01-01T00:00:00. The date
-# system can be changed in Excel on a per-workbook basis (for example:
-# Tools -> Options -> Calculation, tick the "1904 date system" box).
-# This is of course a bad idea if there are already dates in the
-# workbook. There is no good reason to change it even if there are no
-# dates in the workbook. Which date system is in use is recorded in the
-# workbook. A workbook transported from Windows to Macintosh (or vice
-# versa) will work correctly with the host Excel. When using this
-# module's xldate_as_tuple function to convert numbers from a workbook,
-# you must use the datemode attribute of the Book object. If you guess,
-# or make a judgement depending on where you believe the workbook was
-# created, you run the risk of being 1462 days out of kilter.
-#
-# Reference:
-# http://support.microsoft.com/default.aspx?scid=KB;EN-US;q180162
-#
-# (3) The Excel implementation of the Windows-default 1900-based date system works on the
-# incorrect premise that 1900 was a leap year. It interprets the number 60 as meaning 1900-02-29,
-# which is not a valid date. Consequently any number less than 61 is ambiguous. Example: is 59 the
-# result of 1900-02-28 entered directly, or is it 1900-03-01 minus 2 days? The OpenOffice.org Calc
-# program "corrects" the Microsoft problem; entering 1900-02-27 causes the number 59 to be stored.
-# Save as an XLS file, then open the file with Excel -- you'll see 1900-02-28 displayed.
-#
-# Reference: http://support.microsoft.com/default.aspx?scid=kb;en-us;214326
-#
-# (4) The Macintosh-default 1904-based date system counts 1904-01-02 as day 1 and 1904-01-01 as day zero.
-# Thus any number such that (0.0 <= number < 1.0) is ambiguous. Is 0.625 a time of day (15:00:00),
-# independent of the calendar,
-# or should it be interpreted as an instant on a particular day (1904-01-01T15:00:00)?
-# The xldate_* functions in this module
-# take the view that such a number is a calendar-independent time of day (like Python's datetime.time type) for both
-# date systems. This is consistent with more recent Microsoft documentation
-# (for example, the help file for Excel 2002 which says that the first day
-# in the 1904 date system is 1904-01-02).
-#
-# (5) Usage of the Excel DATE() function may leave strange dates in a spreadsheet. Quoting the help file,
-# in respect of the 1900 date system: "If year is between 0 (zero) and 1899 (inclusive),
-# Excel adds that value to 1900 to calculate the year. For example, DATE(108,1,2) returns January 2, 2008 (1900+108)."
-# This gimmick, semi-defensible only for arguments up to 99 and only in the pre-Y2K-awareness era,
-# means that DATE(1899, 12, 31) is interpreted as 3799-12-31.
-#
-# For further information, please refer to the documentation for the xldate_* functions.
-#
-# Named references, constants, formulas, and macros
-#
-# A name is used to refer to a cell, a group of cells, a constant
-# value, a formula, or a macro. Usually the scope of a name is global
-# across the whole workbook. However it can be local to a worksheet.
-# For example, if the sales figures are in different cells in
-# different sheets, the user may define the name "Sales" in each
-# sheet. There are built-in names, like "Print_Area" and
-# "Print_Titles"; these two are naturally local to a sheet.
-#
-# To inspect the names with a user interface like MS Excel, OOo Calc,
-# or Gnumeric, click on Insert/Names/Define. This will show the global
-# names, plus those local to the currently selected sheet.
-#
-# A Book object provides two dictionaries (name_map and
-# name_and_scope_map) and a list (name_obj_list) which allow various
-# ways of accessing the Name objects. There is one Name object for
-# each NAME record found in the workbook. Name objects have many
-# attributes, several of which are relevant only when obj.macro is 1.
-#
-# In the examples directory you will find namesdemo.xls which
-# showcases the many different ways that names can be used, and
-# xlrdnamesAPIdemo.py which offers 3 different queries for inspecting
-# the names in your files, and shows how to extract whatever a name is
-# referring to. There is currently one "convenience method",
-# Name.cell(), which extracts the value in the case where the name
-# refers to a single cell. More convenience methods are planned. The
-# source code for Name.cell (in __init__.py) is an extra source of
-# information on how the Name attributes hang together.
-#
-# Name information is **not** extracted from files older than
-# Excel 5.0 (Book.biff_version < 50)
-#
-# Formatting
-#
-# Introduction
-#
-# This collection of features, new in xlrd version 0.6.1, is intended
-# to provide the information needed to (1) display/render spreadsheet contents
-# (say) on a screen or in a PDF file, and (2) copy spreadsheet data to another
-# file without losing the ability to display/render it.
-#
-# The Palette; Colour Indexes
-#
-# A colour is represented in Excel as a (red, green, blue) ("RGB") tuple
-# with each component in range(256). However it is not possible to access an
-# unlimited number of colours; each spreadsheet is limited to a palette of 64 different
-# colours (24 in Excel 3.0 and 4.0, 8 in Excel 2.0). Colours are referenced by an index
-# ("colour index") into this palette.
-#
-# Colour indexes 0 to 7 represent 8 fixed built-in colours: black, white, red, green, blue,
-# yellow, magenta, and cyan.
-#
-# The remaining colours in the palette (8 to 63 in Excel 5.0 and later)
-# can be changed by the user. In the Excel 2003 UI, Tools/Options/Color presents a palette
-# of 7 rows of 8 colours. The last two rows are reserved for use in charts.
-# The correspondence between this grid and the assigned
-# colour indexes is NOT left-to-right top-to-bottom.
-# Indexes 8 to 15 correspond to changeable
-# parallels of the 8 fixed colours -- for example, index 7 is forever cyan;
-# index 15 starts off being cyan but can be changed by the user.
-#
-# The default colour for each index depends on the file version; tables of the defaults
-# are available in the source code. If the user changes one or more colours,
-# a PALETTE record appears in the XLS file -- it gives the RGB values for *all* changeable
-# indexes.
-# Note that colours can be used in "number formats": "[CYAN]...." and "[COLOR8]...." refer
-# to colour index 7; "[COLOR16]...." will produce cyan
-# unless the user changes colour index 15 to something else.
-#
-# In addition, there are several "magic" colour indexes used by Excel:
-# 0x18 (BIFF3-BIFF4), 0x40 (BIFF5-BIFF8): System window text colour for border lines
-# (used in XF, CF, and WINDOW2 records)
-# 0x19 (BIFF3-BIFF4), 0x41 (BIFF5-BIFF8): System window background colour for pattern background
-# (used in XF and CF records )
-# 0x43: System face colour (dialogue background colour)
-# 0x4D: System window text colour for chart border lines
-# 0x4E: System window background colour for chart areas
-# 0x4F: Automatic colour for chart border lines (seems to be always Black)
-# 0x50: System ToolTip background colour (used in note objects)
-# 0x51: System ToolTip text colour (used in note objects)
-# 0x7FFF: System window text colour for fonts (used in FONT and CF records)
-# Note 0x7FFF appears to be the *default* colour index. It appears quite often in FONT
-# records.
-#
-# Default Formatting
-#
-# Default formatting is applied to all empty cells (those not described by a cell record).
-# Firstly row default information (ROW record, Rowinfo class) is used if available.
-# Failing that, column default information (COLINFO record, Colinfo class) is used if available.
-# As a last resort the worksheet/workbook default cell format will be used; this
-# should always be present in an Excel file,
-# described by the XF record with the fixed index 15 (0-based). By default, it uses the
-# worksheet/workbook default cell style, described by the very first XF record (index 0).
-#
-# Formatting features not included in xlrd version 0.6.1
-#
-# - Rich text i.e. strings containing partial bold, italic
-# and underlined text, change of font inside a string, etc.
-# See OOo docs s3.4 and s3.2
-# - Asian phonetic text (known as "ruby"), used for Japanese furigana. See OOo docs
-# s3.4.2 (p15)
-# - Conditional formatting. See OOo docs
-# s5.12, s6.21 (CONDFMT record), s6.16 (CF record)
-# - Miscellaneous sheet-level and book-level items e.g. printing layout, screen panes.
-# - Modern Excel file versions don't keep most of the built-in
-# "number formats" in the file; Excel loads formats according to the
-# user's locale. Currently xlrd's emulation of this is limited to
-# a hard-wired table that applies to the US English locale. This may mean
-# that currency symbols, date order, thousands separator, decimals separator, etc
-# are inappropriate. Note that this does not affect users who are copying XLS
-# files, only those who are visually rendering cells.
-#
-# Loading worksheets on demand
-#
-# This feature, new in version 0.7.1, is governed by the on_demand argument
-# to the open_workbook() function and allows saving memory and time by loading
-# only those sheets that the caller is interested in, and releasing sheets
-# when no longer required.
-#
-# on_demand=False (default): No change. open_workbook() loads global data
-# and all sheets, releases resources no longer required (principally the
-# str or mmap object containing the Workbook stream), and returns.
-#
-# on_demand=True and BIFF version < 5.0: A warning message is emitted,
-# on_demand is recorded as False, and the old process is followed.
-#
-# on_demand=True and BIFF version >= 5.0: open_workbook() loads global
-# data and returns without releasing resources. At this stage, the only
-# information available about sheets is Book.nsheets and Book.sheet_names().
-#
-# Book.sheet_by_name() and Book.sheet_by_index() will load the requested
-# sheet if it is not already loaded.
-#
-# Book.sheets() will load all/any unloaded sheets.
-#
-# The caller may save memory by calling
-# Book.unload_sheet(sheet_name_or_index) when finished with the sheet.
-# This applies irrespective of the state of on_demand.
-#
-# The caller may re-load an unloaded sheet by calling Book.sheet_by_xxxx()
-# -- except if those required resources have been released (which will
-# have happened automatically when on_demand is false). This is the only
-# case where an exception will be raised.
-#
-# The caller may query the state of a sheet:
-# Book.sheet_loaded(sheet_name_or_index) -> a bool
-#
-# 2010-12-03 mozman start xlrd3, for changes see NEWS.txt
-#
-# 2009-04-27 SJM Integrated on_demand patch by Armando Serrano Lombillo
-# 2008-11-23 SJM Support dumping FILEPASS and EXTERNNAME records; extra info from SUPBOOK records
-# 2008-11-23 SJM colname utility function now supports more than 256 columns
-# 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.
-# 2008-02-08 SJM Preparation for Excel 2.0 support
-# 2008-02-03 SJM Minor tweaks for IronPython support
-# 2008-02-02 SJM Previous change stopped dump() and count_records() ... fixed
-# 2007-12-25 SJM Decouple Book initialisation & loading -- to allow for multiple loaders.
-# 2007-12-20 SJM Better error message for unsupported file format.
-# 2007-12-04 SJM Added support for Excel 2.x (BIFF2) files.
-# 2007-11-20 SJM Wasn't handling EXTERNSHEET record that needed CONTINUE record(s)
-# 2007-07-07 SJM Version changed to 0.7.0 (alpha 1)
-# 2007-07-07 SJM Logfile arg wasn't being passed from open_workbook to compdoc.CompDoc
-# 2007-05-21 SJM If no CODEPAGE record in pre-8.0 file, assume ascii and keep going.
-# 2007-04-22 SJM Removed antique undocumented Book.get_name_dict method.
-
-import sys
-import time
-from struct import unpack
-import mmap
-
-from . import sheet
-from . import compdoc
-from . import formatting
-from .biffh import *
-from .xldate import xldate_as_tuple, XLDateError
-from .formula import *
-from .xfcell import XFCell
-
-empty_cell = sheet.empty_cell # for exposure to the world ...
-
-DEBUG = False
-USE_FANCY_CD = 1
-
-MY_EOF = 0xF00BAAA # not a 16-bit number
-
-SUPBOOK_UNK = 0
-SUPBOOK_INTERNAL = 1
-SUPBOOK_EXTERNAL = 2
-SUPBOOK_ADDIN = 3
-SUPBOOK_DDEOLE = 4
-
-SUPPORTED_VERSIONS = (80, 70, 50, 45, 40, 30, 21, 20)
-
-code_from_builtin_name = {
- "Consolidate_Area": "\x00",
- "Auto_Open": "\x01",
- "Auto_Close": "\x02",
- "Extract": "\x03",
- "Database": "\x04",
- "Criteria": "\x05",
- "Print_Area": "\x06",
- "Print_Titles": "\x07",
- "Recorder": "\x08",
- "Data_Form": "\x09",
- "Auto_Activate": "\x0A",
- "Auto_Deactivate": "\x0B",
- "Sheet_Title": "\x0C",
- "_FilterDatabase": "\x0D",
- }
-
-builtin_name_from_code = {}
-for _bin, _bic in code_from_builtin_name.items():
- builtin_name_from_code[_bic] = _bin
-
-#
-# Open a spreadsheet file for data extraction.
-#
-# @param filename The path to the spreadsheet file to be opened.
-#
-# @param logfile An open file to which messages and diagnostics are written.
-#
-# @param verbosity Increases the volume of trace material written to the logfile.
-#
-# @param pickleable Default is true. In Python 2.4 or earlier, setting to false
-# will cause use of array.array objects which save some memory but can't be pickled.
-# In Python 2.5, array.arrays are used unconditionally. Note: if you have large files that
-# you need to read multiple times, it can be much faster to cPickle.dump() the xlrd.Book object
-# once, and use cPickle.load() multiple times.
-# @param use_mmap Whether to use the mmap module is determined heuristically.
-# Use this arg to override the result. Current heuristic: mmap is used if it exists.
-#
-# @param file_contents ... as a string or an mmap.mmap object or some other behave-alike object.
-# If file_contents is supplied, filename will not be used, except (possibly) in messages.
-#
-# @param encoding_override Used to overcome missing or bad codepage information
-# in older-version files. Refer to discussion in the <b>Unicode</b> section above.
-# - New in version 0.6.0
-#
-# @param formatting_info Governs provision of a reference to an XF (eXtended Format) object
-# for each cell in the worksheet.
-# Default is <i>False</i>. This is backwards compatible and saves memory.
-# "Blank" cells (those with their own formatting information but no data) are treated as empty
-# (by ignoring the file's BLANK and MULBLANK records).
-# It cuts off any bottom "margin" of rows of empty (and blank) cells and
-# any right "margin" of columns of empty (and blank) cells.
-# Only cell_value and cell_type are available.
-# `True` provides all cells, including empty and blank cells.
-# XF information is available for each cell.
-# - New in version 0.6.1
-#
-# @param on_demand Governs whether sheets are all loaded initially or when demanded
-# by the caller. Please refer back to the section "Loading worksheets on demand" for details.
-# - New in version 0.7.1
-#
-# @return An instance of the Book class.
-
-def open_workbook(filename=None,
- logfile=sys.stdout,
- verbosity=0,
- pickleable=True,
- use_mmap=True,
- file_contents=None,
- encoding_override=None,
- formatting_info=False,
- on_demand=False):
- t0 = time.clock()
- workbook = Book()
- workbook.biff2_8_load(filename=filename,
- file_contents=file_contents,
- logfile=logfile,
- verbosity=verbosity,
- pickleable=pickleable,
- use_mmap=use_mmap,
- encoding_override=encoding_override,
- formatting_info=formatting_info,
- on_demand=on_demand)
- t1 = time.clock()
- workbook.load_time_stage_1 = t1 - t0
- biff_version = workbook.getbof(XL_WORKBOOK_GLOBALS)
- if not biff_version:
- raise XLRDError("Can't determine file's BIFF version")
-
- if biff_version not in SUPPORTED_VERSIONS:
- raise XLRDError( "BIFF version %s is not supported" % \
- biff_text_from_num[biff_version])
-
- workbook.biff_version = biff_version
-
- if biff_version <= 40:
- # no workbook globals, only 1 worksheet
- if on_demand:
- fprintf(workbook.logfile,
- "*** WARNING: on_demand is not supported for this Excel version.\n" \
- "*** Setting on_demand to False.\n")
- workbook.on_demand = on_demand = False
- workbook.fake_globals_get_sheet()
- elif biff_version == 45:
- # worksheet(s) embedded in global stream
- workbook.parse_globals()
- if on_demand:
- fprintf(workbook.logfile,
- "*** WARNING: on_demand is not supported for this Excel version.\n" \
- "*** Setting on_demand to False.\n")
- workbook.on_demand = on_demand = False
- else:
- workbook.parse_globals()
- workbook._sheet_list = [None for sh in workbook._sheet_names]
- if not on_demand:
- workbook.get_sheets()
-
- workbook.nsheets = len(workbook._sheet_list)
- if biff_version == 45 and workbook.nsheets > 1:
- fprintf(workbook.logfile,
- "*** WARNING: Excel 4.0 workbook (.XLW) file contains %d worksheets.\n" \
- "*** Book-level data will be that of the last worksheet.\n",
- workbook.nsheets)
-
- if not on_demand:
- workbook.release_resources()
- t2 = time.clock()
- workbook.load_time_stage_2 = t2 - t1
- return workbook
-
-# For debugging: dump the file's BIFF records in char & hex.
-# @param filename The path to the file to be dumped.
-# @param outfile An open file, to which the dump is written.
-# @param unnumbered If true, omit offsets (for meaningful diffs).
-
-def dump(filename, outfile=sys.stdout, unnumbered=False):
- workbook = Book()
- workbook.biff2_8_load(filename=filename, logfile=outfile, )
- biff_dump(workbook.mem, workbook.base, workbook.stream_len, 0, outfile, unnumbered)
-
-# For debugging and analysis: summarise the file's BIFF records.
-# I.e. produce a sorted file of (record_name, count).
-# @param filename The path to the file to be summarised.
-# @param outfile An open file, to which the summary is written.
-
-def count_records(filename, outfile=sys.stdout):
- workbook = Book()
- workbook.biff2_8_load(filename=filename, logfile=outfile, )
- biff_count_records(workbook.mem, workbook.base, workbook.stream_len, outfile)
-
-# Information relating to a named reference, formula, macro, etc.
-# - New in version 0.6.0
-# - Name information is **not** extracted from files older than
-# Excel 5.0 (Book.biff_version < 50)
-
-class Name(BaseObject):
-
- _repr_these = ['stack']
- book = None # parent
-
- # 0 = Visible; 1 = Hidden
- hidden = 0
-
- # 0 = Command macro; 1 = Function macro. Relevant only if macro == 1
- func = 0
-
- # 0 = Sheet macro; 1 = VisualBasic macro. Relevant only if macro == 1
- vbasic = 0
-
- # 0 = Standard name; 1 = Macro name
- macro = 0
-
- # 0 = Simple formula; 1 = Complex formula (array formula or user defined)
- # ´No examples have been sighted.´
- complex = 0
-
- # 0 = User-defined name; 1 = Built-in name
- # (common examples: Print_Area, Print_Titles; see OOo docs for full list)
- builtin = 0
-
- # Function group. Relevant only if macro == 1; see OOo docs for values.
- funcgroup = 0
-
- # 0 = Formula definition; 1 = Binary data ´No examples have been sighted.´
- binary = 0
-
- # The index of this object in book.name_obj_list
- name_index = 0
-
- # A Unicode string. If builtin, decoded as per OOo docs.
- name = ""
-
- # An 8-bit string.
- raw_formula = ""
-
- # -1: The name is global (visible in all calculation sheets).
- # -2: The name belongs to a macro sheet or VBA sheet.
- # -3: The name is invalid.
- # 0 <= scope < book.nsheets: The name is local to the sheet whose index is scope.
- scope = -1
-
- # The result of evaluating the formula, if any.
- # If no formula, or evaluation of the formula encountered problems,
- # the result is None. Otherwise the result is a single instance of the
- # Operand class.
- result = None
-
- # This is a convenience method for the frequent use case where the name
- # refers to a single cell.
- # @return An instance of the Cell class.
- # @throws XLRDError The name is not a constant absolute reference
- # to a single cell.
- def cell(self):
- res = self.result
- if res:
- # result should be an instance of the Operand class
- kind = res.kind
- value = res.value
- if kind == oREF and len(value) == 1:
- ref3d = value[0]
- if (0 <= ref3d.shtxlo == ref3d.shtxhi - 1
- and ref3d.rowxlo == ref3d.rowxhi - 1
- and ref3d.colxlo == ref3d.colxhi - 1):
- sh = self.book.sheet_by_index(ref3d.shtxlo)
- return sh.cell(ref3d.rowxlo, ref3d.colxlo)
- self.dump(self.book.logfile,
- header="=== Dump of Name object ===",
- footer="======= End of dump =======")
- raise XLRDError("Not a constant absolute reference to a single cell")
-
- # This is a convenience method for the use case where the name
- # refers to one rectangular area in one worksheet.
- # @param clipped If true (the default), the returned rectangle is clipped
- # to fit in (0, sheet.nrows, 0, sheet.ncols) -- it is guaranteed that
- # 0 <= rowxlo <= rowxhi <= sheet.nrows and that the number of usable rows
- # in the area (which may be zero) is rowxhi - rowxlo; likewise for columns.
- # @return a tuple (sheet_object, rowxlo, rowxhi, colxlo, colxhi).
- # @throws XLRDError The name is not a constant absolute reference
- # to a single area in a single sheet.
- def area2d(self, clipped=True):
- res = self.result
- if res:
- # result should be an instance of the Operand class
- kind = res.kind
- value = res.value
- if kind == oREF and len(value) == 1: # only 1 reference
- ref3d = value[0]
- if 0 <= ref3d.shtxlo == ref3d.shtxhi - 1: # only 1 usable sheet
- sh = self.book.sheet_by_index(ref3d.shtxlo)
- if not clipped:
- return sh, ref3d.rowxlo, ref3d.rowxhi, ref3d.colxlo, ref3d.colxhi
- rowxlo = min(ref3d.rowxlo, sh.nrows)
- rowxhi = max(rowxlo, min(ref3d.rowxhi, sh.nrows))
- colxlo = min(ref3d.colxlo, sh.ncols)
- colxhi = max(colxlo, min(ref3d.colxhi, sh.ncols))
- assert 0 <= rowxlo <= rowxhi <= sh.nrows
- assert 0 <= colxlo <= colxhi <= sh.ncols
- return sh, rowxlo, rowxhi, colxlo, colxhi
- self.dump(self.book.logfile,
- header="=== Dump of Name object ===",
- footer="======= End of dump =======",
- )
- raise XLRDError("Not a constant absolute reference to a single area in a single sheet")
-
-# Contents of a "workbook".
-# WARNING: You don't call this class yourself. You use the Book object that
-# was returned when you called xlrd.open_workbook("myfile.xls").
-
-class Book(BaseObject):
-
- # The number of worksheets present in the workbook file.
- # This information is available even when no sheets have yet been loaded.
- nsheets = 0
-
- # Which date system was in force when this file was last saved.
- # 0 => 1900 system (the Excel for Windows default).
- # 1 => 1904 system (the Excel for Macintosh default).
- datemode = 0 # In case it's not specified in the file.
-
- # Version of BIFF (Binary Interchange File Format) used to create the file.
- # Latest is 8.0 (represented here as 80), introduced with Excel 97.
- # Earliest supported by this module: 2.0 (represented as 20).
- biff_version = 0
-
- # List containing a Name object for each NAME record in the workbook.
- # - New in version 0.6.0
- name_obj_list = []
-
- # An integer denoting the character set used for strings in this file.
- # For BIFF 8 and later, this will be 1200, meaning Unicode; more precisely, UTF_16_LE.
- # For earlier versions, this is used to derive the appropriate Python encoding
- # to be used to convert to Unicode.
- # Examples: 1252 -> 'cp1252', 10000 -> 'mac_roman'
- codepage = None
-
- # The encoding that was derived from the codepage.
- encoding = None
-
- # A tuple containing the (telephone system) country code for:
- # [0]: the user-interface setting when the file was created.
- # [1]: the regional settings.
- # Example: (1, 61) meaning (USA, Australia).
- # This information may give a clue to the correct encoding for an unknown codepage.
- # For a long list of observed values, refer to the OpenOffice.org documentation for
- # the COUNTRY record.
- countries = (0, 0)
-
- # What (if anything) is recorded as the name of the last user to save the file.
- user_name = ''
-
- # A list of Font class instances, each corresponding to a FONT record.
- # - New in version 0.6.1
- font_list = []
-
- # A list of XF class instances, each corresponding to an XF record.
- # - New in version 0.6.1
- xf_list = []
-
- # A list of Format objects, each corresponding to a FORMAT record, in
- # the order that they appear in the input file.
- # It does <i>not</i> contain builtin formats.
- # If you are creating an output file using (for example) pyExcelerator,
- # use this list.
- # The collection to be used for all visual rendering purposes is format_map.
- # - New in version 0.6.1
- format_list = []
-
- # The mapping from XF.format_key to Format object.
- # - New in version 0.6.1
- format_map = {}
-
- # This provides access via name to the extended format information for
- # both built-in styles and user-defined styles.
- # It maps <i>name</i> to (<i>built_in</i>, <i>xf_index</i>), where:
- # <i>name</i> is either the name of a user-defined style,
- # or the name of one of the built-in styles. Known built-in names are
- # Normal, RowLevel_1 to RowLevel_7,
- # ColLevel_1 to ColLevel_7, Comma, Currency, Percent, "Comma [0]",
- # "Currency [0]", Hyperlink, and "Followed Hyperlink".
- # ´built_in´ 1 = built-in style, 0 = user-defined
- # ´xf_index´ is an index into Book.xf_list.
- # References: OOo docs s6.99 (STYLE record); Excel UI Format/Style
- # - New in version 0.6.1
- style_name_map = {}
-
- # This provides definitions for colour indexes. Please refer to the
- # above section "The Palette; Colour Indexes" for an explanation
- # of how colours are represented in Excel.
- # Colour indexes into the palette map into (red, green, blue) tuples.
- # "Magic" indexes e.g. 0x7FFF map to None.
- # ´colour_map´ is what you need if you want to render cells on screen or in a PDF
- # file. If you are writing an output XLS file, use <i>palette_record</i>.
- # - New in version 0.6.1. Extracted only if open_workbook(..., formatting_info=True)
- colour_map = {}
-
- # If the user has changed any of the colours in the standard palette, the XLS
- # file will contain a PALETTE record with 56 (16 for Excel 4.0 and earlier)
- # RGB values in it, and this list will be e.g. [(r0, b0, g0), ..., (r55, b55, g55)].
- # Otherwise this list will be empty. This is what you need if you are
- # writing an output XLS file. If you want to render cells on screen or in a PDF
- # file, use colour_map.
- # - New in version 0.6.1. Extracted only if open_workbook(..., formatting_info=True)
- palette_record = []
-
- # Time in seconds to extract the XLS image as a contiguous string (or mmap equivalent).
- load_time_stage_1 = -1.0
-
- # Time in seconds to parse the data from the contiguous string (or mmap equivalent).
- load_time_stage_2 = -1.0
-
- # @return A list of all sheets in the book.
- # All sheets not already loaded will be loaded.
- def sheets(self):
- for sheetx in range(self.nsheets):
- if not self._sheet_list[sheetx]:
- self.get_sheet(sheetx)
- return self._sheet_list[:]
-
- # @param sheetx Sheet index in range(nsheets)
- # @return An object of the Sheet class
- def sheet_by_index(self, sheetx):
- return self._sheet_list[sheetx] or self.get_sheet(sheetx)
-
- # @param sheet_name Name of sheet required
- # @return An object of the Sheet class
- def sheet_by_name(self, sheet_name):
- try:
- sheetx = self._sheet_names.index(sheet_name)
- except ValueError:
- raise XLRDError('No sheet named <%r>' % sheet_name)
- return self.sheet_by_index(sheetx)
-
- # @return A list of the names of all the worksheets in the workbook file.
- # This information is available even when no sheets have yet been loaded.
- def sheet_names(self):
- return self._sheet_names[:]
-
- # @param sheet_name_or_index Name or index of sheet enquired upon
- # @return true if sheet is loaded, false otherwise
- # -- New in version 0.7.1
- def sheet_loaded(self, sheet_name_or_index):
- # using type(1) because int won't work with Python 2.1
- if isinstance(sheet_name_or_index, type(1)):
- sheetx = sheet_name_or_index
- else:
- try:
- sheetx = self._sheet_names.index(sheet_name_or_index)
- except ValueError:
- raise XLRDError('No sheet named <%r>' % sheet_name_or_index)
- return self._sheet_list[sheetx] and True or False # Python 2.1 again
-
- # @param sheet_name_or_index Name or index of sheet to be unloaded.
- # - New in version 0.7.1
- def unload_sheet(self, sheet_name_or_index):
- # using type(1) because int won't work with Python 2.1
- if isinstance(sheet_name_or_index, type(1)):
- sheetx = sheet_name_or_index
- else:
- try:
- sheetx = self._sheet_names.index(sheet_name_or_index)
- except ValueError:
- raise XLRDError('No sheet named <%r>' % sheet_name_or_index)
- self._sheet_list[sheetx] = None
-
- # A mapping from (lower_case_name, scope) to a single Name object.
- # - New in version 0.6.0
- name_and_scope_map = {}
-
- # A mapping from lower_case_name to a list of Name objects. The list is
- # sorted in scope order. Typically there will be one item (of global scope)
- # in the list.
- # - New in version 0.6.0
- name_map = {}
-
- def __init__(self):
- self._sheet_list = []
- self._sheet_names = []
- self._sheet_visibility = [] # from BOUNDSHEET record
- self.nsheets = 0
- self._sh_abs_posn = [] # sheet's absolute position in the stream
- self._sharedstrings = []
- self.raw_user_name = False
- self._sheethdr_count = 0 # BIFF 4W only
- self.builtinfmtcount = -1 # unknown as yet. BIFF 3, 4S, 4W
- self.initialise_format_info()
- self._all_sheets_count = 0 # includes macro & VBA sheets
- self._supbook_count = 0
- self._supbook_locals_inx = None
- self._supbook_addins_inx = None
-
- # maps an all_sheets index to a calc-sheets index (or -1)
- self._all_sheets_map = []
- self._externsheet_info = []
- self._externsheet_type_b57 = []
- self._extnsht_name_from_num = {}
- self._sheet_num_from_name = {}
- self._extnsht_count = 0
- self._supbook_types = []
- self._resources_released = 0
- self.addin_func_names = []
- self.name_obj_list = []
- self.colour_map = {}
- self.palette_record = []
- self.xf_list = []
- self.style_name_map = {}
-
- def biff2_8_load(self, filename=None,
- file_contents=None,
- logfile=sys.stdout,
- verbosity=0,
- pickleable=True,
- use_mmap=True,
- encoding_override=None,
- formatting_info=False,
- on_demand=False):
-
- self.logfile = logfile
- self.verbosity = verbosity
- self.pickleable = pickleable
- self.use_mmap = use_mmap
- self.encoding_override = encoding_override
- self.formatting_info = formatting_info
- self.on_demand = on_demand
-
- need_close_filestr = 0
- if not file_contents:
- if self.use_mmap:
- open_mode = "r+b"
- else:
- open_mode = "rb"
- retry = False
- try:
- f = open(filename, open_mode)
- except IOError:
- e, v = sys.exc_info()[:2]
- if open_mode == "r+b" and \
- (v.errno == 13 or v.strerror == "Permission denied"):
- # Maybe the file is read-only
- retry = True
- self.use_mmap = False
- else:
- raise
- if retry:
- f = open(filename, "rb")
- if self.use_mmap:
- f.seek(0, 2) # EOF
- size = f.tell()
- f.seek(0, 0) # BOF
- filestr = mmap.mmap(f.fileno(), size, access=mmap.ACCESS_READ)
- need_close_filestr = 1
- self.stream_len = size
- else:
- filestr = f.read()
- self.stream_len = len(filestr)
- f.close()
- else:
- filestr = file_contents
- self.stream_len = len(file_contents)
-
- self.base = 0
- if filestr[:8] != compdoc.SIGNATURE:
- # got this one at the antique store
- self.mem = filestr
- else:
- cd = compdoc.CompDoc(filestr, logfile=self.logfile)
- if USE_FANCY_CD:
- for qname in ['Workbook', 'Book']:
- self.mem, self.base, self.stream_len = cd.locate_named_stream(qname)
- if self.mem: break
- else:
- raise XLRDError("Can't find workbook in OLE2 compound document")
- else:
- for qname in ['Workbook', 'Book']:
- self.mem = cd.get_named_stream(qname)
- if self.mem: break
- else:
- raise XLRDError("Can't find workbook in OLE2 compound document")
- self.stream_len = len(self.mem)
- del cd
- if self.mem is not filestr:
- if need_close_filestr:
- filestr.close()
- del filestr
- self._position = self.base
- if DEBUG:
- print("mem: %s, base: %d, len: %d" % (type(self.mem), self.base, self.stream_len), file=self.logfile)
-
- def initialise_format_info(self):
- # needs to be done once per sheet for BIFF 4W :-(
- self.format_map = {}
- self.format_list = []
- self.xfcount = 0
- self.actualfmtcount = 0 # number of FORMAT records seen so far
- self._xf_index_to_xl_type_map = {}
- self._xf_epilogue_done = 0
- self.xf_list = []
- self.font_list = []
-
- def release_resources(self):
- self._resources_released = 1
- del self.mem
- del self._sharedstrings
-
- def get2bytes(self):
- pos = self._position
- buff_two = self.mem[pos:pos+2]
- lenbuff = len(buff_two)
- self._position += lenbuff
- if lenbuff < 2:
- return MY_EOF
- lo, hi = buff_two
- return (hi << 8) | lo #(to_py3):
-
- def get_record_parts(self):
- pos = self._position
- mem = self.mem
- code, length = unpack('<HH', mem[pos:pos+4])
- pos += 4
- data = mem[pos:pos+length]
- self._position = pos + length
- return (code, length, data)
-
- def get_record_parts_conditional(self, reqd_record):
- pos = self._position
- mem = self.mem
- code, length = unpack('<HH', mem[pos:pos+4])
- if code != reqd_record:
- return (None, 0, '')
- pos += 4
- data = mem[pos:pos+length]
- self._position = pos + length
- return (code, length, data)
-
- def get_sheet(self, sh_number, update_pos=True):
- if self._resources_released:
- raise XLRDError("Can't load sheets after releasing resources.")
- if update_pos:
- self._position = self._sh_abs_posn[sh_number]
- _unused_biff_version = self.getbof(XL_WORKSHEET)
- # assert biff_version == self.biff_version ### FAILS
- # Have an example where book is v7 but sheet reports v8!!!
- # It appears to work OK if the sheet version is ignored.
- # Confirmed by Daniel Rentz: happens when Excel does "save as"
- # creating an old version file; ignore version details on sheet BOF.
- sh = sheet.Sheet(self,
- self._position,
- self._sheet_names[sh_number],
- sh_number)
- sh.read(self)
- self._sheet_list[sh_number] = sh
- return sh
-
- def get_sheets(self):
- if DEBUG:
- print("GET_SHEETS:", self._sheet_names, self._sh_abs_posn,
- file=self.logfile)
- for sheetno in range(len(self._sheet_names)):
- if DEBUG:
- print("GET_SHEETS: sheetno =", sheetno, self._sheet_names,
- self._sh_abs_posn, file=self.logfile)
- self.get_sheet(sheetno)
-
- def fake_globals_get_sheet(self): # for BIFF 4.0 and earlier
- formatting.initialise_book(self)
- fake_sheet_name = 'Sheet 1'
- self._sheet_names = [fake_sheet_name]
- self._sh_abs_posn = [0]
- self._sheet_visibility = [0] # one sheet, visible
- self._sheet_list.append(None) # get_sheet updates _sheet_list but needs a None beforehand
- self.get_sheets()
-
- def handle_boundsheet(self, data):
- self.derive_encoding()
- if DEBUG:
- fprintf(self.logfile, "BOUNDSHEET: bv=%d data %r\n", self.biff_version, data)
- if self.biff_version == 45: # BIFF4W
- #### Not documented in OOo docs ...
- # In fact, the *only* data is the name of the sheet.
- sheet_name = unpack_string(data, 0, self.encoding, lenlen=1)
- visibility = 0
- sheet_type = XL_BOUNDSHEET_WORKSHEET # guess, patch later
- if len(self._sh_abs_posn) == 0:
- abs_posn = self._sheetsoffset + self.base
- # Note (a) this won't be used
- # (b) it's the position of the SHEETHDR record
- # (c) add 11 to get to the worksheet BOF record
- else:
- abs_posn = -1 # unknown
- else:
- offset, visibility, sheet_type = unpack('<iBB', data[0:6])
- abs_posn = offset + self.base # because global BOF is always at posn 0 in the stream
- if self.biff_version < BIFF_FIRST_UNICODE:
- sheet_name = unpack_string(data, 6, self.encoding, lenlen=1)
- else:
- sheet_name = unpack_unicode(data, 6, lenlen=1)
-
- if DEBUG or self.verbosity >= 2:
- fprintf(self.logfile,
- "BOUNDSHEET: inx=%d vis=%r sheet_name=%r abs_posn=%d sheet_type=0x%02x\n",
- self._all_sheets_count, visibility, sheet_name, abs_posn, sheet_type)
- self._all_sheets_count += 1
- if sheet_type != XL_BOUNDSHEET_WORKSHEET:
- self._all_sheets_map.append(-1)
- descr = {
- 1: 'Macro sheet',
- 2: 'Chart',
- 6: 'Visual Basic module',
- }.get(sheet_type, 'UNKNOWN')
-
- fprintf(self.logfile,
- "NOTE *** Ignoring non-worksheet data named %r (type 0x%02x = %s)\n",
- sheet_name, sheet_type, descr)
- else:
- snum = len(self._sheet_names)
- self._all_sheets_map.append(snum)
- self._sheet_names.append(sheet_name)
- self._sh_abs_posn.append(abs_posn)
- self._sheet_visibility.append(visibility)
- self._sheet_num_from_name[sheet_name] = snum
-
- def handle_builtinfmtcount(self, data):
- # N.B. This count appears to be utterly useless.
- builtinfmtcount = unpack('<H', data[0:2])[0]
- if DEBUG:
- fprintf(self.logfile, "BUILTINFMTCOUNT: %r\n", builtinfmtcount)
- self.builtinfmtcount = builtinfmtcount
-
- def derive_encoding(self):
- if self.encoding_override:
- self.encoding = self.encoding_override
- elif self.codepage is None:
- if self.biff_version < 80:
- fprintf(self.logfile,
- "*** No CODEPAGE record, no encoding_override: will use 'ascii'\n")
- self.encoding = 'ascii'
- else:
- self.codepage = 1200 # utf16le
- if self.verbosity >= 2:
- fprintf(self.logfile, "*** No CODEPAGE record; assuming 1200 (utf_16_le)\n")
- else:
- codepage = self.codepage
- if codepage in encoding_from_codepage:
- encoding = encoding_from_codepage[codepage]
- elif 300 <= codepage <= 1999:
- encoding = 'cp' + str(codepage)
- else:
- encoding = 'unknown_codepage_' + str(codepage)
- if DEBUG or (self.verbosity and encoding != self.encoding) :
- fprintf(self.logfile, "CODEPAGE: codepage %r -> encoding %r\n",
- codepage, encoding)
- self.encoding = encoding
- if self.codepage != 1200: # utf_16_le
- # If we don't have a codec that can decode ASCII into Unicode,
- # we're well & truly stuffed -- let the punter know ASAP.
- try:
- _unused = str(b'trial', self.encoding)
- except:
- ei = sys.exc_info()[:2]
- fprintf(self.logfile,
- "ERROR *** codepage %r -> encoding %r -> %s: %s\n",
- self.codepage, self.encoding, ei[0].__name__.split(".")[-1], ei[1])
- raise
- if self.raw_user_name:
- strg = unpack_string(self.user_name, 0, self.encoding, lenlen=1)
- strg = strg.rstrip()
- self.user_name = strg
- self.raw_user_name = False
- return self.encoding
-
- def handle_codepage(self, data):
- codepage = unpack('<H', data[0:2])[0]
- self.codepage = codepage
- self.derive_encoding()
-
- def handle_country(self, data):
- countries = unpack('<HH', data[0:4])
- if self.verbosity:
- print("Countries:", countries, file=self.logfile)
- # Note: in BIFF7 and earlier, country record was put (redundantly?) in each worksheet.
- assert self.countries == (0, 0) or self.countries == countries
- self.countries = countries
-
- def handle_datemode(self, data):
- datemode = unpack('<H', data[0:2])[0]
- if DEBUG or self.verbosity:
- fprintf(self.logfile, "DATEMODE: datemode %r\n", datemode)
- assert datemode in (0, 1)
- self.datemode = datemode
-
- def handle_externname(self, data):
- verbose = DEBUG or self.verbosity >= 2
- if self.biff_version >= 80:
- option_flags, other_info =unpack("<HI", data[:6])
- pos = 6
- name, pos = unpack_unicode_update_pos(data, pos, lenlen=1)
- extra = data[pos:]
- if self._supbook_types[-1] == SUPBOOK_ADDIN:
- self.addin_func_names.append(name)
- if verbose:
- fprintf(self.logfile,
- "EXTERNNAME: sbktype=%d oflags=0x%04x oinfo=0x%08x name=%r extra=%r\n",
- self._supbook_types[-1], option_flags, other_info, name, extra)
-
- def handle_externsheet(self, data):
- self.derive_encoding() # in case CODEPAGE record missing/out of order/wrong
- self._extnsht_count += 1 # for use as a 1-based index
- verbose1 = DEBUG or self.verbosity >= 1
- verbose2 = DEBUG or self.verbosity >= 2
- if self.biff_version >= 80:
- num_refs = unpack("<H", data[0:2])[0]
- bytes_reqd = num_refs * 6 + 2
- while len(data) < bytes_reqd:
- if verbose1:
- fprintf(
- self.logfile,
- "INFO: EXTERNSHEET needs %d bytes, have %d\n",
- bytes_reqd, len(data))
- code2, length2, data2 = self.get_record_parts()
- if code2 != XL_CONTINUE:
- raise XLRDError("Missing CONTINUE after EXTERNSHEET record")
- data += data2
- pos = 2
- for k in range(num_refs):
- info = unpack("<HHH", data[pos:pos+6])
- ref_recordx, ref_first_sheetx, ref_last_sheetx = info
- self._externsheet_info.append(info)
- pos += 6
- if verbose2:
- fprintf(
- self.logfile,
- "EXTERNSHEET(b8): k = %2d, record = %2d, first_sheet = %5d, last sheet = %5d\n",
- k, ref_recordx, ref_first_sheetx, ref_last_sheetx)
- else:
- nc, ty = unpack("<BB", data[:2])
- if verbose2:
- print("EXTERNSHEET(b7-):")
- hex_char_dump(data, 0, len(data))
- msg = {
- 1: "Encoded URL",
- 2: "Current sheet!!",
- 3: "Specific sheet in own doc't",
- 4: "Nonspecific sheet in own doc't!!",
- }.get(ty, "Not encoded")
- print(" %3d chars, type is %d (%s)" % (nc, ty, msg))
- if ty == 3:
- sheet_name = str(data[2:nc+2], self.encoding)
- self._extnsht_name_from_num[self._extnsht_count] = sheet_name
- if verbose2: print(self._extnsht_name_from_num)
- if not (1 <= ty <= 4):
- ty = 0
- self._externsheet_type_b57.append(ty)
-
- def handle_filepass(self, data):
- if self.verbosity >= 2:
- logf = self.logfile
- fprintf(logf, "FILEPASS:\n")
- hex_char_dump(data, 0, len(data), base=0, fout=logf)
- if self.biff_version >= 80:
- kind1, = unpack('<H', data[:2])
- if kind1 == 0: # weak XOR encryption
- key, hash_value = unpack('<HH', data[2:])
- fprintf(logf,
- 'weak XOR: key=0x%04x hash=0x%04x\n',
- key, hash_value)
- elif kind1 == 1:
- kind2, = unpack('<H', data[4:6])
- if kind2 == 1: # BIFF8 standard encryption
- caption = "BIFF8 std"
- elif kind2 == 2:
- caption = "BIFF8 strong"
- else:
- caption = "** UNKNOWN ENCRYPTION METHOD **"
- fprintf(logf, "%s\n", caption)
- raise XLRDError("Workbook is encrypted")
-
- def handle_name(self, data):
- verbose = DEBUG or self.verbosity >= 2
- if self.biff_version < 50:
- return
- self.derive_encoding()
-
- # unpack
- (option_flags,
- kb_shortcut,
- name_len,
- fmla_len,
- extsht_index,
- sheet_index,
- menu_text_len,
- description_text_len,
- help_topic_text_len,
- status_bar_text_len) = unpack("<HBBHHH4B", data[0:14])
-
- nobj = Name()
- nobj.book = self ### CIRCULAR ###
- name_index = len(self.name_obj_list)
- nobj.name_index = name_index
- self.name_obj_list.append(nobj)
- nobj.option_flags = option_flags
- for attr, mask, nshift in (
- ('hidden', 1, 0),
- ('func', 2, 1),
- ('vbasic', 4, 2),
- ('macro', 8, 3),
- ('complex', 0x10, 4),
- ('builtin', 0x20, 5),
- ('funcgroup', 0xFC0, 6),
- ('binary', 0x1000, 12),
- ):
- setattr(nobj, attr, (option_flags & mask) >> nshift)
-
- macro_flag = " M"[nobj.macro]
- if self.biff_version < 80:
- internal_name, pos = unpack_string_update_pos(data, 14, self.encoding, known_len=name_len)
- else:
- internal_name, pos = unpack_unicode_update_pos(data, 14, known_len=name_len)
- nobj.extn_sheet_num = extsht_index
- nobj.excel_sheet_index = sheet_index
- nobj.scope = None # patched up in the names_epilogue() method
- if verbose:
- print("NAME[%d]:%s oflags=%d, name_len=%d, fmla_len=%d, extsht_index=%d, sheet_index=%d, name=%r" \
- % (name_index, macro_flag, option_flags, name_len,
- fmla_len, extsht_index, sheet_index, internal_name))
- name = internal_name
- if nobj.builtin:
- name = builtin_name_from_code.get(name, "??Unknown??")
- if verbose: print(" builtin: %s" % name)
- nobj.name = name
- nobj.raw_formula = data[pos:]
- nobj.basic_formula_len = fmla_len
- nobj.evaluated = 0
- if verbose:
- nobj.dump(self.logfile,
- header="--- handle_name: name[%d] ---" % name_index,
- footer="-------------------")
-
- def names_epilogue(self):
- verbose = self.verbosity >= 2
- f = self.logfile
- if verbose:
- print("+++++ names_epilogue +++++", file=f)
- print("_all_sheets_map", self._all_sheets_map, file=f)
- print("_extnsht_name_from_num", self._extnsht_name_from_num, file=f)
- print("_sheet_num_from_name", self._sheet_num_from_name, file=f)
- num_names = len(self.name_obj_list)
- for namex in range(num_names):
- nobj = self.name_obj_list[namex]
- # Convert from excel_sheet_index to scope.
- # This is done here because in BIFF7 and earlier, the
- # BOUNDSHEET records (from which _all_sheets_map is derived)
- # come after the NAME records.
- if self.biff_version >= 80:
- sheet_index = nobj.excel_sheet_index
- if sheet_index == 0:
- intl_sheet_index = -1 # global
- elif 1 <= sheet_index <= len(self._all_sheets_map):
- intl_sheet_index = self._all_sheets_map[sheet_index-1]
- if intl_sheet_index == -1: # maps to a macro or VBA sheet
- intl_sheet_index = -2 # valid sheet reference but not useful
- else:
- # huh?
- intl_sheet_index = -3 # invalid
- elif 50 <= self.biff_version <= 70:
- sheet_index = nobj.extn_sheet_num
- if sheet_index == 0:
- intl_sheet_index = -1 # global
- else:
- sheet_name = self._extnsht_name_from_num[sheet_index]
- intl_sheet_index = self._sheet_num_from_name.get(sheet_name, -2)
- nobj.scope = intl_sheet_index
-
- for namex in range(num_names):
- nobj = self.name_obj_list[namex]
- # Parse the formula ...
- if nobj.macro or nobj.binary: continue
- if nobj.evaluated: continue
- evaluate_name_formula(self, nobj, namex, verbose=verbose)
-
- if self.verbosity >= 2:
- print("---------- name object dump ----------", file=f)
- for namex in range(num_names):
- nobj = self.name_obj_list[namex]
- nobj.dump(f, header="--- name[%d] ---" % namex)
- print("--------------------------------------", file=f)
- #
- # Build some dicts for access to the name objects
- #
- name_and_scope_map = {}
- name_map = {}
- for namex in range(num_names):
- nobj = self.name_obj_list[namex]
- name_lcase = nobj.name.lower()
- key = (name_lcase, nobj.scope)
- if key in name_and_scope_map:
- msg = 'Duplicate entry %r in name_and_scope_map' % (key, )
- if 0:
- raise XLRDError(msg)
- else:
- if self.verbosity:
- print(msg, file=f)
- name_and_scope_map[key] = nobj
- if name_lcase in name_map:
- name_map[name_lcase].append((nobj.scope, nobj))
- else:
- name_map[name_lcase] = [(nobj.scope, nobj)]
- for key in list(name_map.keys()):
- alist = name_map[key]
- alist.sort()
- name_map[key] = [x[1] for x in alist]
- self.name_and_scope_map = name_and_scope_map
- self.name_map = name_map
-
- def handle_obj(self, data):
- # Not doing much handling at all.
- # Worrying about embedded (BOF ... EOF) substreams is done elsewhere.
- obj_type, obj_id = unpack('<HI', data[4:10])
-
- def handle_supbook(self, data):
- self._supbook_types.append(None)
- verbose = DEBUG or self.verbosity >= 2
- num_sheets = unpack("<H", data[0:2])[0]
- sbn = self._supbook_count
- self._supbook_count += 1
- if data[2:4] == b"\x01\x04":
- self._supbook_types[-1] = SUPBOOK_INTERNAL
- self._supbook_locals_inx = self._supbook_count - 1
- if verbose:
- print("SUPBOOK[%d]: internal 3D refs; %d sheets" % (sbn, num_sheets))
- print(" _all_sheets_map", self._all_sheets_map)
- return
-
- if data[0:4] == b"\x01\x00\x01\x3A":
- self._supbook_types[-1] = SUPBOOK_ADDIN
- self._supbook_addins_inx = self._supbook_count - 1
- if verbose:
- print("SUPBOOK[%d]: add-in functions" % sbn)
- return
-
- url, pos = unpack_unicode_update_pos(data, 2, lenlen=2)
- if num_sheets == 0:
- self._supbook_types[-1] = SUPBOOK_DDEOLE
- if verbose:
- print("SUPBOOK[%d]: DDE/OLE document = %r" % (sbn, url))
- return
-
- self._supbook_types[-1] = SUPBOOK_EXTERNAL
- if verbose:
- print("SUPBOOK[%d]: url = %r" % (sbn, url))
- sheet_names = []
- for x in range(num_sheets):
- shname, pos = unpack_unicode_update_pos(data, pos, lenlen=2)
- sheet_names.append(shname)
- if verbose:
- print(" sheet %d: %r" % (x, shname))
-
- def handle_sheethdr(self, data):
- # This a BIFF 4W special.
- # The SHEETHDR record is followed by a (BOF ... EOF) substream containing
- # a worksheet.
- self.derive_encoding()
- sheet_len = unpack('<i', data[:4])[0]
- sheet_name = unpack_string(data, 4, self.encoding, lenlen=1)
- sheetno = self._sheethdr_count
- assert sheet_name == self._sheet_names[sheetno]
- self._sheethdr_count += 1
- BOF_posn = self._position
- posn = BOF_posn - 4 - len(data)
- if DEBUG:
- print('SHEETHDR %d at posn %d: len=%d name=%r' % (sheetno, posn, sheet_len, sheet_name), file=self.logfile)
- self.initialise_format_info()
- if DEBUG:
- print('SHEETHDR: xf epilogue flag is %d' % self._xf_epilogue_done, file=self.logfile)
- self._sheet_list.append(None) # get_sheet updates _sheet_list but needs a None beforehand
- self.get_sheet(sheetno, update_pos=False)
- if DEBUG:
- print('SHEETHDR: posn after get_sheet() =', self._position, file=self.logfile)
- self._position = BOF_posn + sheet_len
-
- def handle_sheetsoffset(self, data):
- posn = unpack('<i', data)[0]
- if DEBUG:
- print('SHEETSOFFSET:', posn, file=self.logfile)
- self._sheetsoffset = posn
-
- def handle_sst(self, data):
- if DEBUG:
- print("SST Processing", file=self.logfile)
- t0 = time.time()
- nbt = len(data)
- strlist = [data]
- uniquestrings = unpack('<i', data[4:8])[0]
- if DEBUG or self.verbosity >= 2:
- fprintf(self.logfile, "SST: unique strings: %d\n", uniquestrings)
- while True:
- code, nb, data = self.get_record_parts_conditional(XL_CONTINUE)
- if code is None:
- break
- nbt += nb
- if DEBUG:
- fprintf(self.logfile, "CONTINUE: adding %d bytes to SST -> %d\n", nb, nbt)
- strlist.append(data)
- self._sharedstrings = unpack_SST_table(strlist, uniquestrings)
- if DEBUG:
- t1 = time.time()
- print("SST processing took %.2f seconds" % (t1 - t0, ), file=self.logfile)
-
- def handle_writeaccess(self, data):
- if self.biff_version < 80:
- if not self.encoding:
- self.raw_user_name = True
- self.user_name = data
- return
- strg = unpack_string(data, 0, self.encoding, lenlen=1)
- else:
- strg = unpack_unicode(data, 0, lenlen=2)
- if DEBUG:
- print("WRITEACCESS: %d bytes; raw=%d %r" % (len(data), self.raw_user_name, strg), file=self.logfile)
- strg = strg.rstrip()
- self.user_name = strg
-
- def parse_globals(self):
- # no need to position, just start reading (after the BOF)
- formatting.initialise_book(self)
- while True:
- rc, length, data = self.get_record_parts()
- if DEBUG:
- print("parse_globals: record code is 0x%04x" % rc)
- if rc == XL_SST:
- self.handle_sst(data)
- elif rc == XL_FONT or rc == XL_FONT_B3B4:
- self.handle_font(data)
- elif rc == XL_FORMAT: # XL_FORMAT2 is BIFF <= 3.0, can't appear in globals
- self.handle_format(data)
- elif rc == XL_XF:
- self.handle_xf(data)
- elif rc == XL_BOUNDSHEET:
- self.handle_boundsheet(data)
- elif rc == XL_DATEMODE:
- self.handle_datemode(data)
- elif rc == XL_CODEPAGE:
- self.handle_codepage(data)
- elif rc == XL_COUNTRY:
- self.handle_country(data)
- elif rc == XL_EXTERNNAME:
- self.handle_externname(data)
- elif rc == XL_EXTERNSHEET:
- self.handle_externsheet(data)
- elif rc == XL_FILEPASS:
- self.handle_filepass(data)
- elif rc == XL_WRITEACCESS:
- self.handle_writeaccess(data)
- elif rc == XL_SHEETSOFFSET:
- self.handle_sheetsoffset(data)
- elif rc == XL_SHEETHDR:
- self.handle_sheethdr(data)
- elif rc == XL_SUPBOOK:
- self.handle_supbook(data)
- elif rc == XL_NAME:
- self.handle_name(data)
- elif rc == XL_PALETTE:
- self.handle_palette(data)
- elif rc == XL_STYLE:
- self.handle_style(data)
- elif rc & 0xff == 9:
- print("*** Unexpected BOF at posn %d: 0x%04x len=%d data=%r" \
- % (self._position - length - 4, rc, length, data), file=self.logfile)
- elif rc == XL_EOF:
- self.xf_epilogue()
- self.names_epilogue()
- self.palette_epilogue()
- if not self.encoding:
- self.derive_encoding()
- if self.biff_version == 45:
- if DEBUG:
- print("global EOF: position", self._position)
- return
-
- def read(self, pos, length):
- data = self.mem[pos:pos+length]
- self._position = pos + len(data)
- return data
-
- def getbof(self, rqd_stream):
- def bof_error(msg):
- raise XLRDError('Unsupported format, or corrupt file: ' + msg)
-
- if DEBUG:
- print("reqd: 0x%04x" % rqd_stream, file=self.logfile)
-
- savpos = self._position
- opcode = self.get2bytes()
-
- if opcode == MY_EOF:
- bof_error('Expected BOF record; met end of file')
-
- if opcode not in bofcodes:
- bof_error('Expected BOF record; found %r' % self.mem[savpos:savpos+8])
-
- length = self.get2bytes()
- if length == MY_EOF:
- bof_error('Incomplete BOF record[1]; met end of file')
-
- if length < boflen[opcode] or length > 20:
- bof_error('Invalid length (%d) for BOF record type 0x%04x' % (length, opcode))
-
- data = self.read(self._position, length);
- if DEBUG: print("\ngetbof(): data=%r" % data, file=self.logfile)
- if len(data) < length:
- bof_error('Incomplete BOF record[2]; met end of file')
- version1 = opcode >> 8
- version2, streamtype = unpack('<HH', data[0:4])
- if DEBUG:
- print("getbof(): op=0x%04x version2=0x%04x streamtype=0x%04x" \
- % (opcode, version2, streamtype), file=self.logfile)
- bof_offset = self._position - 4 - length
- if DEBUG:
- print("getbof(): BOF found at offset %d; savpos=%d" \
- % (bof_offset, savpos), file=self.logfile)
- version = build = year = 0
- if version1 == 0x08:
- build, year = unpack('<HH', data[4:8])
- if version2 == 0x0600:
- version = 80
- elif version2 == 0x0500:
- if year < 1994 or build in (2412, 3218, 3321):
- version = 50
- else:
- version = 70
- else:
- # dodgy one, created by a 3rd-party tool
- version = {
- 0x0000: 21,
- 0x0007: 21,
- 0x0200: 21,
- 0x0300: 30,
- 0x0400: 40,
- }.get(version2, 0)
- elif version1 in (0x04, 0x02, 0x00):
- version = {0x04: 40, 0x02: 30, 0x00: 21}[version1]
-
- if version == 40 and streamtype == XL_WORKBOOK_GLOBALS_4W:
- version = 45 # i.e. 4W
-
- if DEBUG or self.verbosity >= 2:
- print("BOF: op=0x%04x vers=0x%04x stream=0x%04x buildid=%d buildyr=%d -> BIFF%d" \
- % (opcode, version2, streamtype, build, year, version), file=self.logfile)
- got_globals = streamtype == XL_WORKBOOK_GLOBALS or (
- version == 45 and streamtype == XL_WORKBOOK_GLOBALS_4W)
- if (rqd_stream == XL_WORKBOOK_GLOBALS and got_globals) or streamtype == rqd_stream:
- return version
- if version < 50 and streamtype == XL_WORKSHEET:
- return version
- if version >= 50 and streamtype == 0x0100:
- bof_error("Workspace file -- no spreadsheet data")
- bof_error(
- 'BOF not workbook/worksheet: op=0x%04x vers=0x%04x strm=0x%04x build=%d year=%d -> BIFF%d' \
- % (opcode, version2, streamtype, build, year, version))
-
-# === helper functions
-
-def expand_cell_address(inrow, incol):
- # Ref : OOo docs, "4.3.4 Cell Addresses in BIFF8"
- outrow = inrow
- if incol & 0x8000:
- if outrow >= 32768:
- outrow -= 65536
- relrow = 1
- else:
- relrow = 0
- outcol = incol & 0xFF
- if incol & 0x4000:
- if outcol >= 128:
- outcol -= 256
- relcol = 1
- else:
- relcol = 0
- return outrow, outcol, relrow, relcol
-
-def colname(colx, _A2Z="ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
- assert colx >= 0
- name = ''
- while True:
- quot, rem = divmod(colx, 26)
- name = _A2Z[rem] + name
- if not quot:
- return name
- colx = quot - 1
-
-def display_cell_address(rowx, colx, relrow, relcol):
- if relrow:
- rowpart = "(*%s%d)" % ("+-"[rowx < 0], abs(rowx))
- else:
- rowpart = "$%d" % (rowx+1,)
- if relcol:
- colpart = "(*%s%d)" % ("+-"[colx < 0], abs(colx))
- else:
- colpart = "$" + colname(colx)
- return colpart + rowpart
-
-def unpack_SST_table(datatab, nstrings):
- """ Return list of strings """
- datainx = 0
- ndatas = len(datatab)
- data = datatab[0]
- datalen = len(data)
- pos = 8
- strings = []
- strappend = strings.append
- local_unpack = unpack
- local_min = min
- #(to_py3): local_ord = ord
- latin_1 = "latin_1"
- for _unused_i in range(nstrings):
- nchars = local_unpack('<H', data[pos:pos+2])[0]
- pos += 2
- #(to_py3): options = local_ord(data[pos])
- options = data[pos]
- pos += 1
- rtsz = 0
- if options & 0x08: # richtext
- rtsz = 4 * local_unpack('<H', data[pos:pos+2])[0]
- pos += 2
- if options & 0x04: # phonetic
- rtsz += local_unpack('<i', data[pos:pos+4])[0]
- pos += 4
- accstrg = ''
- charsgot = 0
- while True:
- charsneed = nchars - charsgot
- if options & 0x01:
- # Uncompressed UTF-16
- charsavail = local_min((datalen - pos) >> 1, charsneed)
- rawstrg = data[pos:pos+2*charsavail]
- try:
- #(to_py3) accstrg += unicode(rawstrg, "utf_16_le")
- accstrg += str(rawstrg, "utf_16_le")
- except:
- # print "SST U16: nchars=%d pos=%d rawstrg=%r" % (nchars, pos, rawstrg)
- # Probable cause: dodgy data e.g. unfinished surrogate pair.
- # E.g. file unicode2.xls in pyExcelerator's examples has cells containing
- # unichr(i) for i in range(0x100000)
- # so this will include 0xD800 etc
- raise
- pos += (2 * charsavail)
- else:
- # Note: this is COMPRESSED (not ASCII!) encoding!!!
- charsavail = local_min(datalen - pos, charsneed)
- rawstrg = data[pos:pos+charsavail]
- #(to_py3) accstrg += unicode(rawstrg, latin_1)
- accstrg += str(rawstrg, latin_1)
- pos += charsavail
- charsgot += charsavail
- if charsgot == nchars:
- break
- datainx += 1
- data = datatab[datainx]
- datalen = len(data)
- #(to_py3): options = local_ord(data[0])
- options = data[0]
- pos = 1
- pos += rtsz # size of richtext & phonetic stuff to skip
- # also allow for the rich text etc being split ...
- if pos >= datalen:
- # adjust to correct position in next record
- pos = pos - datalen
- datainx += 1
- if datainx < ndatas:
- data = datatab[datainx]
- datalen = len(data)
- else:
- assert _unused_i == nstrings - 1
- strappend(accstrg)
- return strings
diff --git a/tablib/packages/xlrd3/biffh.py b/tablib/packages/xlrd3/biffh.py
deleted file mode 100644
index d99e3a3..0000000
--- a/tablib/packages/xlrd3/biffh.py
+++ /dev/null
@@ -1,620 +0,0 @@
-# Support module for the xlrd3 package.
-#
-# Portions copyright (c) 2005-2008 Stephen John Machin, Lingfo Pty Ltd
-# This module is part of the xlrd package, which is released under a
-# BSD-style licence.
-#
-# 2010-12-08 mozman refactoring for python 3
-# 2008-02-10 SJM BIFF2 BLANK record
-# 2008-02-08 SJM Preparation for Excel 2.0 support
-# 2008-02-02 SJM Added suffixes (_B2, _B2_ONLY, etc) on record names for
-# biff_dump & biff_count
-# 2007-12-04 SJM Added support for Excel 2.x (BIFF2) files.
-# 2007-09-08 SJM Avoid crash when zero-length Unicode string missing options byte.
-# 2007-04-22 SJM Remove experimental "trimming" facility.
-
-import sys
-from struct import unpack
-
-encoding_from_codepage = {
- 1200 : 'utf_16_le',
- 10000: 'mac_roman',
- 10006: 'mac_greek', # guess
- 10007: 'mac_cyrillic', # guess
- 10029: 'mac_latin2', # guess
- 10079: 'mac_iceland', # guess
- 10081: 'mac_turkish', # guess
- 32768: 'mac_roman',
- 32769: 'cp1252',
- }
-
-# some more guessing, for Indic scripts
-# codepage 57000 range:
-# 2 Devanagari [0]
-# 3 Bengali [1]
-# 4 Tamil [5]
-# 5 Telegu [6]
-# 6 Assamese [1] c.f. Bengali
-# 7 Oriya [4]
-# 8 Kannada [7]
-# 9 Malayalam [8]
-# 10 Gujarati [3]
-# 11 Gurmukhi [2]
-
-FUN = 0 # unknown
-FDT = 1 # date
-FNU = 2 # number
-FGE = 3 # general
-FTX = 4 # text
-
-DATEFORMAT = FDT
-NUMBERFORMAT = FNU
-
-XL_CELL_EMPTY = 0
-XL_CELL_TEXT = 1
-XL_CELL_NUMBER = 2
-XL_CELL_DATE = 3
-XL_CELL_BOOLEAN = 4
-XL_CELL_ERROR = 5
-XL_CELL_BLANK = 6 # for use in debugging, gathering stats, etc
-
-biff_text_from_num = {
- 0: "(not BIFF)",
- 20: "2.0",
- 21: "2.1",
- 30: "3",
- 40: "4S",
- 45: "4W",
- 50: "5",
- 70: "7",
- 80: "8",
- 85: "8X",
-}
-
-# This dictionary can be used to produce a text version of the internal codes
-# that Excel uses for error cells. Here are its contents:
-error_text_from_code = {
- 0x00: '#NULL!', # Intersection of two cell ranges is empty
- 0x07: '#DIV/0!', # Division by zero
- 0x0F: '#VALUE!', # Wrong type of operand
- 0x17: '#REF!', # Illegal or deleted cell reference
- 0x1D: '#NAME?', # Wrong function or range name
- 0x24: '#NUM!', # Value range overflow
- 0x2A: '#N/A!', # Argument or function not available
-}
-
-BIFF_FIRST_UNICODE = 80
-
-XL_WORKBOOK_GLOBALS = WBKBLOBAL = 0x5
-XL_WORKBOOK_GLOBALS_4W = 0x100
-XL_WORKSHEET = WRKSHEET = 0x10
-
-XL_BOUNDSHEET_WORKSHEET = 0x00
-XL_BOUNDSHEET_CHART = 0x02
-XL_BOUNDSHEET_VB_MODULE = 0x06
-
-# XL_RK2 = 0x7e
-XL_ARRAY = 0x0221
-XL_ARRAY2 = 0x0021
-XL_BLANK = 0x0201
-XL_BLANK_B2 = 0x01
-XL_BOF = 0x809
-XL_BOOLERR = 0x205
-XL_BOOLERR_B2 = 0x5
-XL_BOUNDSHEET = 0x85
-XL_BUILTINFMTCOUNT = 0x56
-XL_CF = 0x01B1
-XL_CODEPAGE = 0x42
-XL_COLINFO = 0x7D
-XL_COLUMNDEFAULT = 0x20 # BIFF2 only
-XL_COLWIDTH = 0x24 # BIFF2 only
-XL_CONDFMT = 0x01B0
-XL_CONTINUE = 0x3c
-XL_COUNTRY = 0x8C
-XL_DATEMODE = 0x22
-XL_DEFAULTROWHEIGHT = 0x0225
-XL_DEFCOLWIDTH = 0x55
-XL_DIMENSION = 0x200
-XL_DIMENSION2 = 0x0
-XL_EFONT = 0x45
-XL_EOF = 0x0a
-XL_EXTERNNAME = 0x23
-XL_EXTERNSHEET = 0x17
-XL_EXTSST = 0xff
-XL_FEAT11 = 0x872
-XL_FILEPASS = 0x2f
-XL_FONT = 0x31
-XL_FONT_B3B4 = 0x231
-XL_FORMAT = 0x41e
-XL_FORMAT2 = 0x1E # BIFF2, BIFF3
-XL_FORMULA = 0x6
-XL_FORMULA3 = 0x206
-XL_FORMULA4 = 0x406
-XL_GCW = 0xab
-XL_INDEX = 0x20b
-XL_INTEGER = 0x2 # BIFF2 only
-XL_IXFE = 0x44 # BIFF2 only
-XL_LABEL = 0x204
-XL_LABEL_B2 = 0x04
-XL_LABELRANGES = 0x15f
-XL_LABELSST = 0xfd
-XL_MERGEDCELLS = 0xE5
-XL_MSO_DRAWING = 0x00EC
-XL_MSO_DRAWING_GROUP = 0x00EB
-XL_MSO_DRAWING_SELECTION = 0x00ED
-XL_MULRK = 0xbd
-XL_MULBLANK = 0xbe
-XL_NAME = 0x18
-XL_NOTE = 0x1c
-XL_NUMBER = 0x203
-XL_NUMBER_B2 = 0x3
-XL_OBJ = 0x5D
-XL_PALETTE = 0x92
-XL_RK = 0x27e
-XL_ROW = 0x208
-XL_ROW_B2 = 0x08
-XL_RSTRING = 0xd6
-XL_SHEETHDR = 0x8F # BIFF4W only
-XL_SHEETSOFFSET = 0x8E # BIFF4W only
-XL_SHRFMLA = 0x04bc
-XL_SST = 0xfc
-XL_STANDARDWIDTH = 0x99
-XL_STRING = 0x207
-XL_STRING_B2 = 0x7
-XL_STYLE = 0x293
-XL_SUPBOOK = 0x1AE
-XL_TABLEOP = 0x236
-XL_TABLEOP2 = 0x37
-XL_TABLEOP_B2 = 0x36
-XL_TXO = 0x1b6
-XL_UNCALCED = 0x5e
-XL_UNKNOWN = 0xffff
-XL_WINDOW2 = 0x023E
-XL_WRITEACCESS = 0x5C
-XL_XF = 0xe0
-XL_XF2 = 0x0043 # BIFF2 version of XF record
-XL_XF3 = 0x0243 # BIFF3 version of XF record
-XL_XF4 = 0x0443 # BIFF4 version of XF record
-
-boflen = {
- 0x0809: 8,
- 0x0409: 6,
- 0x0209: 6,
- 0x0009: 4,
-}
-
-bofcodes = (0x0809, 0x0409, 0x0209, 0x0009)
-
-XL_FORMULA_OPCODES = (0x0006, 0x0406, 0x0206)
-
-_cell_opcode_list = (
- XL_BOOLERR,
- XL_FORMULA,
- XL_FORMULA3,
- XL_FORMULA4,
- XL_LABEL,
- XL_LABELSST,
- XL_MULRK,
- XL_NUMBER,
- XL_RK,
- XL_RSTRING,
-)
-
-biff_rec_name_dict = {
- 0x0000: 'DIMENSIONS_B2',
- 0x0001: 'BLANK_B2',
- 0x0002: 'INTEGER_B2_ONLY',
- 0x0003: 'NUMBER_B2',
- 0x0004: 'LABEL_B2',
- 0x0005: 'BOOLERR_B2',
- 0x0006: 'FORMULA',
- 0x0007: 'STRING_B2',
- 0x0008: 'ROW_B2',
- 0x0009: 'BOF_B2',
- 0x000A: 'EOF',
- 0x000B: 'INDEX_B2_ONLY',
- 0x000C: 'CALCCOUNT',
- 0x000D: 'CALCMODE',
- 0x000E: 'PRECISION',
- 0x000F: 'REFMODE',
- 0x0010: 'DELTA',
- 0x0011: 'ITERATION',
- 0x0012: 'PROTECT',
- 0x0013: 'PASSWORD',
- 0x0014: 'HEADER',
- 0x0015: 'FOOTER',
- 0x0016: 'EXTERNCOUNT',
- 0x0017: 'EXTERNSHEET',
- 0x0018: 'NAME_B2,5+',
- 0x0019: 'WINDOWPROTECT',
- 0x001A: 'VERTICALPAGEBREAKS',
- 0x001B: 'HORIZONTALPAGEBREAKS',
- 0x001C: 'NOTE',
- 0x001D: 'SELECTION',
- 0x001E: 'FORMAT_B2-3',
- 0x001F: 'BUILTINFMTCOUNT_B2',
- 0x0020: 'COLUMNDEFAULT_B2_ONLY',
- 0x0021: 'ARRAY_B2_ONLY',
- 0x0022: 'DATEMODE',
- 0x0023: 'EXTERNNAME',
- 0x0024: 'COLWIDTH_B2_ONLY',
- 0x0025: 'DEFAULTROWHEIGHT_B2_ONLY',
- 0x0026: 'LEFTMARGIN',
- 0x0027: 'RIGHTMARGIN',
- 0x0028: 'TOPMARGIN',
- 0x0029: 'BOTTOMMARGIN',
- 0x002A: 'PRINTHEADERS',
- 0x002B: 'PRINTGRIDLINES',
- 0x002F: 'FILEPASS',
- 0x0031: 'FONT',
- 0x0032: 'FONT2_B2_ONLY',
- 0x0036: 'TABLEOP_B2',
- 0x0037: 'TABLEOP2_B2',
- 0x003C: 'CONTINUE',
- 0x003D: 'WINDOW1',
- 0x003E: 'WINDOW2_B2',
- 0x0040: 'BACKUP',
- 0x0041: 'PANE',
- 0x0042: 'CODEPAGE',
- 0x0043: 'XF_B2',
- 0x0044: 'IXFE_B2_ONLY',
- 0x0045: 'EFONT_B2_ONLY',
- 0x004D: 'PLS',
- 0x0051: 'DCONREF',
- 0x0055: 'DEFCOLWIDTH',
- 0x0056: 'BUILTINFMTCOUNT_B3-4',
- 0x0059: 'XCT',
- 0x005A: 'CRN',
- 0x005B: 'FILESHARING',
- 0x005C: 'WRITEACCESS',
- 0x005D: 'OBJECT',
- 0x005E: 'UNCALCED',
- 0x005F: 'SAVERECALC',
- 0x0063: 'OBJECTPROTECT',
- 0x007D: 'COLINFO',
- 0x007E: 'RK2_mythical_?',
- 0x0080: 'GUTS',
- 0x0081: 'WSBOOL',
- 0x0082: 'GRIDSET',
- 0x0083: 'HCENTER',
- 0x0084: 'VCENTER',
- 0x0085: 'BOUNDSHEET',
- 0x0086: 'WRITEPROT',
- 0x008C: 'COUNTRY',
- 0x008D: 'HIDEOBJ',
- 0x008E: 'SHEETSOFFSET',
- 0x008F: 'SHEETHDR',
- 0x0090: 'SORT',
- 0x0092: 'PALETTE',
- 0x0099: 'STANDARDWIDTH',
- 0x009B: 'FILTERMODE',
- 0x009C: 'FNGROUPCOUNT',
- 0x009D: 'AUTOFILTERINFO',
- 0x009E: 'AUTOFILTER',
- 0x00A0: 'SCL',
- 0x00A1: 'SETUP',
- 0x00AB: 'GCW',
- 0x00BD: 'MULRK',
- 0x00BE: 'MULBLANK',
- 0x00C1: 'MMS',
- 0x00D6: 'RSTRING',
- 0x00D7: 'DBCELL',
- 0x00DA: 'BOOKBOOL',
- 0x00DD: 'SCENPROTECT',
- 0x00E0: 'XF',
- 0x00E1: 'INTERFACEHDR',
- 0x00E2: 'INTERFACEEND',
- 0x00E5: 'MERGEDCELLS',
- 0x00E9: 'BITMAP',
- 0x00EB: 'MSO_DRAWING_GROUP',
- 0x00EC: 'MSO_DRAWING',
- 0x00ED: 'MSO_DRAWING_SELECTION',
- 0x00EF: 'PHONETIC',
- 0x00FC: 'SST',
- 0x00FD: 'LABELSST',
- 0x00FF: 'EXTSST',
- 0x013D: 'TABID',
- 0x015F: 'LABELRANGES',
- 0x0160: 'USESELFS',
- 0x0161: 'DSF',
- 0x01AE: 'SUPBOOK',
- 0x01AF: 'PROTECTIONREV4',
- 0x01B0: 'CONDFMT',
- 0x01B1: 'CF',
- 0x01B2: 'DVAL',
- 0x01B6: 'TXO',
- 0x01B7: 'REFRESHALL',
- 0x01B8: 'HLINK',
- 0x01BC: 'PASSWORDREV4',
- 0x01BE: 'DV',
- 0x01C0: 'XL9FILE',
- 0x01C1: 'RECALCID',
- 0x0200: 'DIMENSIONS',
- 0x0201: 'BLANK',
- 0x0203: 'NUMBER',
- 0x0204: 'LABEL',
- 0x0205: 'BOOLERR',
- 0x0206: 'FORMULA_B3',
- 0x0207: 'STRING',
- 0x0208: 'ROW',
- 0x0209: 'BOF',
- 0x020B: 'INDEX_B3+',
- 0x0218: 'NAME',
- 0x0221: 'ARRAY',
- 0x0223: 'EXTERNNAME_B3-4',
- 0x0225: 'DEFAULTROWHEIGHT',
- 0x0231: 'FONT_B3B4',
- 0x0236: 'TABLEOP',
- 0x023E: 'WINDOW2',
- 0x0243: 'XF_B3',
- 0x027E: 'RK',
- 0x0293: 'STYLE',
- 0x0406: 'FORMULA_B4',
- 0x0409: 'BOF',
- 0x041E: 'FORMAT',
- 0x0443: 'XF_B4',
- 0x04BC: 'SHRFMLA',
- 0x0800: 'QUICKTIP',
- 0x0809: 'BOF',
- 0x0862: 'SHEETLAYOUT',
- 0x0867: 'SHEETPROTECTION',
- 0x0868: 'RANGEPROTECTION',
-}
-
-class XLRDError(Exception):
- pass
-
-class BaseObject:
- """
- Parent of almost all other classes in the package. Defines a common
- 'dump' method for debugging.
- """
- _repr_these = []
-
- def dump(self, f=None, header=None, footer=None, indent=0):
- """
- :param f: open file object, to which the dump is written
- :param header: text to write before the dump
- :param footer: text to write after the dump
- :param indent: number of leading spaces (for recursive calls)
- """
- if f is None:
- f = sys.stderr
- pad = " " * indent
-
- if header is not None:
- print(header, file=f)
-
- for attr, value in sorted(self.__dict__.items()):
- if getattr(value, 'dump', None) and attr != 'book':
- value.dump(f,
- header="%s%s (%s object):" % (pad, attr, value.__class__.__name__),
- indent=indent+4)
- elif attr not in self._repr_these and \
- (isinstance(value, list) or
- isinstance(value, dict)):
- print("%s%s: %s, len = %d" % (pad, attr, type(value), len(value)), file=f)
- else:
- print("%s%s: %r" % (pad, attr, value), file=f)
- if footer is not None:
- print(footer, file=f)
-
-def fprintf(f, fmt, *vargs):
- print(fmt.rstrip('\n') % vargs, file=f)
-
-def upkbits(tgt_obj, src, manifest, local_setattr=setattr):
- for n, mask, attr in manifest:
- local_setattr(tgt_obj, attr, (src & mask) >> n)
-
-def upkbitsL(tgt_obj, src, manifest, local_setattr=setattr, local_int=int):
- for n, mask, attr in manifest:
- local_setattr(tgt_obj, attr, local_int((src & mask) >> n))
-
-def unpack_string(data, pos, encoding, lenlen=1):
- nchars = unpack('<' + 'BH'[lenlen-1], data[pos:pos+lenlen])[0]
- pos += lenlen
- return str(data[pos:pos+nchars], encoding)
-
-def unpack_string_update_pos(data, pos, encoding, lenlen=1, known_len=None):
- if known_len is not None:
- # On a NAME record, the length byte is detached from the front of the string.
- nchars = known_len
- else:
- nchars = unpack('<' + 'BH'[lenlen-1], data[pos:pos+lenlen])[0]
- pos += lenlen
-
- newpos = pos + nchars
- return (str(data[pos:newpos], encoding), newpos)
-
-def unpack_unicode(data, pos, lenlen=2):
- """ Return unicode_strg """
- nchars = unpack('<' + 'BH'[lenlen-1], data[pos:pos+lenlen])[0]
- if not nchars:
- # Ambiguous whether 0-length string should have an "options" byte.
- # Avoid crash if missing.
- return ""
- pos += lenlen
- options = data[pos]
- pos += 1
-
- if options & 0x08: # richtext
- pos += 2
-
- if options & 0x04: # phonetic
- pos += 4
-
- if options & 0x01:
- # Uncompressed UTF-16-LE
- rawstrg = data[pos:pos+2*nchars]
- strg = str(rawstrg, 'utf_16_le')
- else:
- # Note: this is COMPRESSED (not ASCII!) encoding!!!
- # Merely returning the raw bytes would work OK 99.99% of the time
- # if the local codepage was cp1252 -- however this would rapidly go pear-shaped
- # for other codepages so we grit our Anglocentric teeth and return Unicode :-)
- strg = str(data[pos:pos+nchars], "latin_1")
- return strg
-
-def unpack_unicode_update_pos(data, pos, lenlen=2, known_len=None):
- """ Return (unicode_strg, updated value of pos) """
- if known_len is not None:
- # On a NAME record, the length byte is detached from the front of the string.
- nchars = known_len
- else:
- nchars = unpack('<' + 'BH'[lenlen-1], data[pos:pos+lenlen])[0]
- pos += lenlen
-
- if not nchars and not data[pos:]:
- # Zero-length string with no options byte
- return ("", pos)
-
- options = data[pos]
- pos += 1
- phonetic = options & 0x04
- richtext = options & 0x08
-
- if richtext:
- rt = unpack('<H', data[pos:pos+2])[0]
- pos += 2
-
- if phonetic:
- sz = unpack('<i', data[pos:pos+4])[0]
- pos += 4
-
- if options & 0x01:
- # Uncompressed UTF-16-LE
- strg = str(data[pos:pos+2*nchars], 'utf_16_le')
- pos += 2*nchars
- else:
- # Note: this is COMPRESSED (not ASCII!) encoding!!!
- strg = str(data[pos:pos+nchars], "latin_1")
- pos += nchars
-
- if richtext:
- pos += 4 * rt
-
- if phonetic:
- pos += sz
-
- return (strg, pos)
-
-def unpack_cell_range_address_list_update_pos(
- output_list, data, pos, biff_version, addr_size=6):
- # output_list is updated in situ
- if biff_version < 80:
- assert addr_size == 6
- else:
- assert addr_size in (6, 8)
- n, = unpack("<H", data[pos:pos+2])
- pos += 2
- if n:
- fmt = "<HHBB" if addr_size == 6 else "<HHHH"
- for _unused in range(n):
- ra, rb, ca, cb = unpack(fmt, data[pos:pos+addr_size])
- output_list.append((ra, rb+1, ca, cb+1))
- pos += addr_size
- return pos
-
-def hex_char_dump(strg, ofs, dlen, base=0, fout=sys.stdout, unnumbered=False):
- endpos = min(ofs + dlen, len(strg))
- pos = ofs
- numbered = not unnumbered
- num_prefix = ''
- while pos < endpos:
- endsub = min(pos + 16, endpos)
- substrg = strg[pos:endsub]
- lensub = endsub - pos
- if lensub <= 0 or lensub != len(substrg):
- fprintf(
- sys.stdout,
- '??? hex_char_dump: ofs=%d dlen=%d base=%d -> endpos=%d pos=%d endsub=%d substrg=%r\n',
- ofs, dlen, base, endpos, pos, endsub, substrg)
- break
- hexd = ''.join(["%02x " % c for c in substrg])
- chard = ''
- for c in substrg:
- if c == ord('\0'):
- c = '~'
- elif not (' ' <= chr(c) <= '~'):
- c = '?'
- if isinstance(c, int):
- c = chr(c)
- chard += c
- if numbered:
- num_prefix = "%5d: " % (base+pos-ofs)
- fprintf(fout, "%s %-48s %s\n", num_prefix, hexd, chard)
- pos = endsub
-
-def biff_dump(mem, stream_offset, stream_len, base=0, fout=sys.stdout,
- unnumbered=False):
- pos = stream_offset
- stream_end = stream_offset + stream_len
- adj = base - stream_offset
- dummies = 0
- numbered = not unnumbered
- num_prefix = ''
- while stream_end - pos >= 4:
- rc, length = unpack('<HH', mem[pos:pos+4])
- if rc == 0 and length == 0:
- if mem[pos:] == '\0' * (stream_end - pos):
- dummies = stream_end - pos
- savpos = pos
- pos = stream_end
- break
-
- if dummies:
- dummies += 4
- else:
- savpos = pos
- dummies = 4
- pos += 4
- else:
- if dummies:
- if numbered:
- num_prefix = "%5d: " % (adj + savpos)
- fprintf(fout, "%s---- %d zero bytes skipped ----\n",
- num_prefix, dummies)
- dummies = 0
-
- recname = biff_rec_name_dict.get(rc, '<UNKNOWN>')
- if numbered:
- num_prefix = "%5d: " % (adj + pos)
- fprintf(fout, "%s%04x %s len = %04x (%d)\n",
- num_prefix, rc, recname, length, length)
- pos += 4
- hex_char_dump(mem, pos, length, adj+pos, fout, unnumbered)
- pos += length
- if dummies:
- if numbered:
- num_prefix = "%5d: " % (adj + savpos)
- fprintf(fout, "%s---- %d zero bytes skipped ----\n", num_prefix, dummies)
-
- if pos < stream_end:
- if numbered:
- num_prefix = "%5d: " % (adj + pos)
- fprintf(fout, "%s---- Misc bytes at end ----\n", num_prefix)
- hex_char_dump(mem, pos, stream_end-pos, adj + pos, fout, unnumbered)
- elif pos > stream_end:
- fprintf(fout, "Last dumped record has length (%d) that is too large\n", length)
-
-def biff_count_records(mem, stream_offset, stream_len, fout=sys.stdout):
- pos = stream_offset
- stream_end = stream_offset + stream_len
- tally = {}
- while stream_end - pos >= 4:
- rc, length = unpack('<HH', mem[pos:pos+4])
- if rc == 0 and length == 0:
- if mem[pos:] == '\0' * (stream_end - pos):
- break
- recname = "<Dummy (zero)>"
- else:
- recname = biff_rec_name_dict.get(rc, None)
- if recname is None:
- recname = "Unknown_0x%04X" % rc
- if recname in tally:
- tally[recname] += 1
- else:
- tally[recname] = 1
- pos += length + 4
- for recname, count in sorted(tally.items()):
- fprintf(fout, "%8d %s", count, recname)
diff --git a/tablib/packages/xlrd3/compdoc.py b/tablib/packages/xlrd3/compdoc.py
deleted file mode 100644
index c2ce764..0000000
--- a/tablib/packages/xlrd3/compdoc.py
+++ /dev/null
@@ -1,346 +0,0 @@
-# Implements the minimal functionality required
-# to extract a "Workbook" or "Book" stream (as one big string)
-# from an OLE2 Compound Document file.
-#
-# Copyright © 2005-2008 Stephen John Machin, Lingfo Pty Ltd
-# This module is part of the xlrd3 package, which is released under a BSD-style licence.
-
-# No part of the content of this file was derived from the works of David Giffin.
-
-# 2008-11-04 SJM Avoid assertion error when -1 used instead of -2 for first_SID of empty SCSS [Frank Hoffsuemmer]
-# 2007-09-08 SJM Warning message if sector sizes are extremely large.
-# 2007-05-07 SJM Meaningful exception instead of IndexError if a SAT (sector allocation table) is corrupted.
-# 2007-04-22 SJM Missing "<" in a struct.unpack call => can't open files on bigendian platforms.
-
-
-import sys
-from struct import unpack
-
-# Magic cookie that should appear in the first 8 bytes of the file.
-SIGNATURE = b"\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"
-
-EOCSID = -2
-FREESID = -1
-SATSID = -3
-MSATSID = -4
-
-def int_floor_div(x, y):
- return divmod(x, y)[0]
-
-class CompDocError(Exception):
- pass
-
-class DirNode(object):
-
- def __init__(self, DID, dent, DEBUG=0):
- # dent is the 128-byte directory entry
- self.DID = DID
- # (cbufsize, self.etype, self.colour, self.left_DID, self.right_DID,
- # self.root_DID,
- # self.first_SID,
- # self.tot_size) = \
- # unpack('<HBBiii16x4x8x8xii4x', dent[64:128])
- (cbufsize, self.etype, self.colour, self.left_DID, self.right_DID,
- self.root_DID) = \
- unpack('<HBBiii', dent[64:80])
- (self.first_SID, self.tot_size) = \
- unpack('<ii', dent[116:124])
- if cbufsize == 0:
- self.name = ''
- else:
- self.name = str(dent[0:cbufsize-2], 'utf_16_le') # omit the trailing U+0000
- self.children = [] # filled in later
- self.parent = -1 # indicates orphan; fixed up later
- self.tsinfo = unpack('<IIII', dent[100:116])
- if DEBUG:
- self.dump(DEBUG)
-
- def dump(self, DEBUG=1):
- print("DID=%d name=%r etype=%d DIDs(left=%d right=%d root=%d parent=%d kids=%r) first_SID=%d tot_size=%d" \
- % (self.DID, self.name, self.etype, self.left_DID,
- self.right_DID, self.root_DID, self.parent, self.children, self.first_SID, self.tot_size))
- if DEBUG == 2:
- # cre_lo, cre_hi, mod_lo, mod_hi = tsinfo
- print("timestamp info", self.tsinfo)
-
-def _build_family_tree(dirlist, parent_DID, child_DID):
- if child_DID < 0: return
- _build_family_tree(dirlist, parent_DID, dirlist[child_DID].left_DID)
- dirlist[parent_DID].children.append(child_DID)
- dirlist[child_DID].parent = parent_DID
- _build_family_tree(dirlist, parent_DID, dirlist[child_DID].right_DID)
- if dirlist[child_DID].etype == 1: # storage
- _build_family_tree(dirlist, child_DID, dirlist[child_DID].root_DID)
-
-# Compound document handler.
-# @param mem The raw contents of the file, as a string, or as an mmap.mmap() object. The
-# only operation it needs to support is slicing.
-
-class CompDoc(object):
-
- def __init__(self, mem, logfile=sys.stdout, DEBUG=0):
- self.logfile = logfile
- if mem[0:8] != SIGNATURE:
- raise CompDocError('Not an OLE2 compound document')
- if mem[28:30] != b'\xFE\xFF':
- raise CompDocError('Expected "little-endian" marker, found %r' % mem[28:30])
- revision, version = unpack('<HH', mem[24:28])
- if DEBUG:
- print("\nCompDoc format: version=0x%04x revision=0x%04x" % (version, revision), file=logfile)
- self.mem = mem
- ssz, sssz = unpack('<HH', mem[30:34])
- if ssz > 20: # allows for 2**20 bytes i.e. 1MB
- print("WARNING: sector size (2**%d) is preposterous; assuming 512 and continuing ..." \
- % ssz, file=logfile)
- ssz = 9
- if sssz > ssz:
- print("WARNING: short stream sector size (2**%d) is preposterous; assuming 64 and continuing ..." \
- % sssz, file=logfile)
- sssz = 6
- self.sec_size = sec_size = 1 << ssz
- self.short_sec_size = 1 << sssz
- (
- SAT_tot_secs, self.dir_first_sec_sid, _unused, self.min_size_std_stream,
- SSAT_first_sec_sid, SSAT_tot_secs,
- MSAT_first_sec_sid, MSAT_tot_secs,
- # ) = unpack('<ii4xiiiii', mem[44:76])
- ) = unpack('<iiiiiiii', mem[44:76])
- mem_data_len = len(mem) - 512
- mem_data_secs, left_over = divmod(mem_data_len, sec_size)
- if left_over:
- #### raise CompDocError("Not a whole number of sectors")
- print("WARNING *** file size (%d) not 512 + multiple of sector size (%d)" \
- % (len(mem), sec_size), file=logfile)
- if DEBUG:
- print('sec sizes', ssz, sssz, sec_size, self.short_sec_size, file=logfile)
- print("mem data: %d bytes == %d sectors" % (mem_data_len, mem_data_secs), file=logfile)
- print("SAT_tot_secs=%d, dir_first_sec_sid=%d, min_size_std_stream=%d" \
- % (SAT_tot_secs, self.dir_first_sec_sid, self.min_size_std_stream,), file=logfile)
- print("SSAT_first_sec_sid=%d, SSAT_tot_secs=%d" % (SSAT_first_sec_sid, SSAT_tot_secs,), file=logfile)
- print("MSAT_first_sec_sid=%d, MSAT_tot_secs=%d" % (MSAT_first_sec_sid, MSAT_tot_secs,), file=logfile)
- nent = int_floor_div(sec_size, 4) # number of SID entries in a sector
- fmt = "<%di" % nent
- trunc_warned = 0
- #
- # === build the MSAT ===
- #
- MSAT = list(unpack('<109i', mem[76:512]))
- sid = MSAT_first_sec_sid
- while sid >= 0:
- if sid >= mem_data_secs:
- raise CompDocError(
- "MSAT extension: accessing sector %d but only %d in file" % (sid, mem_data_secs)
- )
- offset = 512 + sec_size * sid
- news = list(unpack(fmt, mem[offset:offset+sec_size]))
- sid = news.pop()
- MSAT.extend(news)
- if DEBUG:
- print("MSAT: len =", len(MSAT), file=logfile)
- print(MSAT, file=logfile)
- #
- # === build the SAT ===
- #
- self.SAT = []
- for msid in MSAT:
- if msid == FREESID: continue
- if msid >= mem_data_secs:
- if not trunc_warned:
- print("WARNING *** File is truncated, or OLE2 MSAT is corrupt!!", file=logfile)
- print("INFO: Trying to access sector %d but only %d available" \
- % (msid, mem_data_secs), file=logfile)
- trunc_warned = 1
- continue
- offset = 512 + sec_size * msid
- news = list(unpack(fmt, mem[offset:offset+sec_size]))
- self.SAT.extend(news)
- if DEBUG:
- print("SAT: len =", len(self.SAT), file=logfile)
- print(self.SAT, file=logfile)
- # print >> logfile, "SAT ",
- # for i, s in enumerate(self.SAT):
- # print >> logfile, "entry: %4d offset: %6d, next entry: %4d" % (i, 512 + sec_size * i, s)
- # print >> logfile, "%d:%d " % (i, s),
- print()
-
- # === build the directory ===
- #
- dbytes = self._get_stream(
- self.mem, 512, self.SAT, self.sec_size, self.dir_first_sec_sid,
- name="directory")
- dirlist = []
- did = -1
- for pos in range(0, len(dbytes), 128):
- did += 1
- dirlist.append(DirNode(did, dbytes[pos:pos+128], 0))
- self.dirlist = dirlist
- _build_family_tree(dirlist, 0, dirlist[0].root_DID) # and stand well back ...
- if DEBUG:
- for d in dirlist:
- d.dump(DEBUG)
- #
- # === get the SSCS ===
- #
- sscs_dir = self.dirlist[0]
- assert sscs_dir.etype == 5 # root entry
- if sscs_dir.first_SID < 0 and sscs_dir.tot_size == 0:
- # Problem reported by Frank Hoffsuemmer: some software was
- # writing -1 instead of -2 (EOCSID) for the first_SID
- # when the SCCS was empty. Not having EOCSID caused assertion
- # failure in _get_stream.
- # Solution: avoid calling _get_stream in any case when the
- # SCSS appears to be empty.
- self.SSCS = ""
- else:
- self.SSCS = self._get_stream(
- self.mem, 512, self.SAT, sec_size, sscs_dir.first_SID,
- sscs_dir.tot_size, name="SSCS")
- # if DEBUG: print >> logfile, "SSCS", repr(self.SSCS)
- #
- # === build the SSAT ===
- #
- self.SSAT = []
- if SSAT_tot_secs > 0 and sscs_dir.tot_size == 0:
- print("WARNING *** OLE2 inconsistency: SSCS size is 0 but SSAT size is non-zero", file=logfile)
- if sscs_dir.tot_size > 0:
- sid = SSAT_first_sec_sid
- nsecs = SSAT_tot_secs
- while sid >= 0 and nsecs > 0:
- nsecs -= 1
- start_pos = 512 + sid * sec_size
- news = list(unpack(fmt, mem[start_pos:start_pos+sec_size]))
- self.SSAT.extend(news)
- sid = self.SAT[sid]
- # assert SSAT_tot_secs == 0 or sid == EOCSID
- if DEBUG: print("SSAT last sid %d; remaining sectors %d" % (sid, nsecs), file=logfile)
- assert nsecs == 0 and sid == EOCSID
- if DEBUG: print("SSAT", self.SSAT, file=logfile)
-
- def _get_stream(self, mem, base, sat, sec_size, start_sid, size=None, name=''):
- # print >> self.logfile, "_get_stream", base, sec_size, start_sid, size
- sectors = []
- s = start_sid
- if size is None:
- # nothing to check against
- while s >= 0:
- start_pos = base + s * sec_size
- sectors.append(mem[start_pos:start_pos+sec_size])
- try:
- s = sat[s]
- except IndexError:
- raise CompDocError(
- "OLE2 stream %r: sector allocation table invalid entry (%d)" %
- (name, s)
- )
- assert s == EOCSID
- else:
- todo = size
- while s >= 0:
- start_pos = base + s * sec_size
- grab = sec_size
- if grab > todo:
- grab = todo
- todo -= grab
- sectors.append(mem[start_pos:start_pos+grab])
- try:
- s = sat[s]
- except IndexError:
- raise CompDocError(
- "OLE2 stream %r: sector allocation table invalid entry (%d)" %
- (name, s)
- )
- assert s == EOCSID
- if todo != 0:
- print("WARNING *** OLE2 stream %r: expected size %d, actual size %d" \
- % (name, size, size - todo), file=self.logfile)
- return b''.join(sectors)
-
- def _dir_search(self, path, storage_DID=0):
- # Return matching DirNode instance, or None
- head = path[0]
- tail = path[1:]
- dl = self.dirlist
- for child in dl[storage_DID].children:
- if dl[child].name.lower() == head.lower():
- et = dl[child].etype
- if et == 2:
- return dl[child]
- if et == 1:
- if not tail:
- raise CompDocError("Requested component is a 'storage'")
- return self._dir_search(tail, child)
- dl[child].dump(1)
- raise CompDocError("Requested stream is not a 'user stream'")
- return None
-
- ##
- # Interrogate the compound document's directory; return the stream as a string if found, otherwise
- # return None.
- # @param qname Name of the desired stream e.g. u'Workbook'. Should be in Unicode or convertible thereto.
-
- def get_named_stream(self, qname):
- d = self._dir_search(qname.split("/"))
- if d is None:
- return None
- if d.tot_size >= self.min_size_std_stream:
- return self._get_stream(
- self.mem, 512, self.SAT, self.sec_size, d.first_SID,
- d.tot_size, name=qname)
- else:
- return self._get_stream(
- self.SSCS, 0, self.SSAT, self.short_sec_size, d.first_SID,
- d.tot_size, name=qname + " (from SSCS)")
-
- # Interrogate the compound document's directory.
- # If the named stream is not found, (None, 0, 0) will be returned.
- # If the named stream is found and is contiguous within the original byte sequence ("mem")
- # used when the document was opened,
- # then (mem, offset_to_start_of_stream, length_of_stream) is returned.
- # Otherwise a new string is built from the fragments and (new_string, 0, length_of_stream) is returned.
- # @param qname Name of the desired stream e.g. u'Workbook'. Should be in Unicode or convertible thereto.
-
- def locate_named_stream(self, qname):
- d = self._dir_search(qname.split("/"))
- if d is None:
- return (None, 0, 0)
- if d.tot_size >= self.min_size_std_stream:
- return self._locate_stream(self.mem, 512, self.SAT, self.sec_size, d.first_SID, d.tot_size)
- else:
- return (
- self._get_stream(
- self.SSCS, 0, self.SSAT, self.short_sec_size, d.first_SID,
- d.tot_size, qname + " (from SSCS)"),
- 0,
- d.tot_size
- )
- return (None, 0, 0) # not found
-
- def _locate_stream(self, mem, base, sat, sec_size, start_sid, size):
- # print >> self.logfile, "_locate_stream", base, sec_size, start_sid, size
- s = start_sid
- if s < 0:
- raise CompDocError("_locate_stream: start_sid (%d) is -ve" % start_sid)
- p = -99 # dummy previous SID
- start_pos = -9999
- end_pos = -8888
- slices = []
- while s >= 0:
- if s == p+1:
- # contiguous sectors
- end_pos += sec_size
- else:
- # start new slice
- if p >= 0:
- # not first time
- slices.append((start_pos, end_pos))
- start_pos = base + s * sec_size
- end_pos = start_pos + sec_size
- p = s
- s = sat[s]
- assert s == EOCSID
- # print >> self.logfile, len(slices) + 1, "slices"
- if not slices:
- # The stream is contiguous ... just what we like!
- return (mem, start_pos, size)
- slices.append((start_pos, end_pos))
- return (b''.join([mem[start_pos:end_pos] for start_pos, end_pos in slices]), 0, size)
diff --git a/tablib/packages/xlrd3/formatting.py b/tablib/packages/xlrd3/formatting.py
deleted file mode 100644
index 85484da..0000000
--- a/tablib/packages/xlrd3/formatting.py
+++ /dev/null
@@ -1,1186 +0,0 @@
-# Module for formatting information.
-#
-# Copyright © 2005-2008 Stephen John Machin, Lingfo Pty Ltd
-# Copyright © 2005-2009 Stephen John Machin, Lingfo Pty Ltd
-# This module is part of the xlrd3 package, which is released under
-# a BSD-style licence.
-
-# No part of the content of this file was derived from the works of David Giffin.
-
-# 2009-05-31 SJM Fixed problem with non-zero reserved bits in some STYLE records in Mac Excel files
-# 2008-08-03 SJM Ignore PALETTE record when Book.formatting_info is false
-# 2008-08-03 SJM Tolerate up to 4 bytes trailing junk on PALETTE record
-# 2008-05-10 SJM Do some XF checks only when Book.formatting_info is true
-# 2008-02-08 SJM Preparation for Excel 2.0 support
-# 2008-02-03 SJM Another tweak to is_date_format_string()
-# 2007-12-04 SJM Added support for Excel 2.x (BIFF2) files.
-# 2007-10-13 SJM Warning: style XF whose parent XF index != 0xFFF
-# 2007-09-08 SJM Work around corrupt STYLE record
-# 2007-07-11 SJM Allow for BIFF2/3-style FORMAT record in BIFF4/8 file
-
-DEBUG = False
-import copy
-import re
-from struct import unpack
-
-from .biffh import BaseObject, unpack_unicode, unpack_string, \
- upkbits, upkbitsL, fprintf, \
- FUN, FDT, FNU, FGE, FTX, XL_CELL_NUMBER, XL_CELL_DATE, \
- XL_FORMAT, XL_FORMAT2, \
- XLRDError
-
-
-excel_default_palette_b5 = (
- ( 0, 0, 0), (255, 255, 255), (255, 0, 0), ( 0, 255, 0),
- ( 0, 0, 255), (255, 255, 0), (255, 0, 255), ( 0, 255, 255),
- (128, 0, 0), ( 0, 128, 0), ( 0, 0, 128), (128, 128, 0),
- (128, 0, 128), ( 0, 128, 128), (192, 192, 192), (128, 128, 128),
- (153, 153, 255), (153, 51, 102), (255, 255, 204), (204, 255, 255),
- (102, 0, 102), (255, 128, 128), ( 0, 102, 204), (204, 204, 255),
- ( 0, 0, 128), (255, 0, 255), (255, 255, 0), ( 0, 255, 255),
- (128, 0, 128), (128, 0, 0), ( 0, 128, 128), ( 0, 0, 255),
- ( 0, 204, 255), (204, 255, 255), (204, 255, 204), (255, 255, 153),
- (153, 204, 255), (255, 153, 204), (204, 153, 255), (227, 227, 227),
- ( 51, 102, 255), ( 51, 204, 204), (153, 204, 0), (255, 204, 0),
- (255, 153, 0), (255, 102, 0), (102, 102, 153), (150, 150, 150),
- ( 0, 51, 102), ( 51, 153, 102), ( 0, 51, 0), ( 51, 51, 0),
- (153, 51, 0), (153, 51, 102), ( 51, 51, 153), ( 51, 51, 51),
- )
-
-excel_default_palette_b2 = excel_default_palette_b5[:16]
-
-# Following two tables borrowed from Gnumeric 1.4 source.
-excel_default_palette_b5_gnumeric_14 = (
- #### dodgy; didn't match Excel results
- ( 0, 0, 0), (255,255,255), (255, 0, 0), ( 0,255, 0),
- ( 0, 0,255), (255,255, 0), (255, 0,255), ( 0,255,255),
- (128, 0, 0), ( 0,128, 0), ( 0, 0,128), (128,128, 0),
- (128, 0,128), ( 0,128,128), (192,192,192), (128,128,128),
- (128,128,255), (128, 32, 96), (255,255,192), (160,224,224),
- ( 96, 0,128), (255,128,128), ( 0,128,192), (192,192,255),
- ( 0, 0,128), (255, 0,255), (255,255, 0), ( 0,255,255),
- (128, 0,128), (128, 0, 0), ( 0,128,128), ( 0, 0,255),
- ( 0,204,255), (105,255,255), (204,255,204), (255,255,153),
- (166,202,240), (204,156,204), (204,153,255), (227,227,227),
- ( 51,102,255), ( 51,204,204), ( 51,153, 51), (153,153, 51),
- (153,102, 51), (153,102,102), (102,102,153), (150,150,150),
- ( 51, 51,204), ( 51,102,102), ( 0, 51, 0), ( 51, 51, 0),
- (102, 51, 0), (153, 51,102), ( 51, 51,153), ( 66, 66, 66),
- )
-excel_default_palette_b8 = ( # (red, green, blue)
- ( 0, 0, 0), (255,255,255), (255, 0, 0), ( 0,255, 0),
- ( 0, 0,255), (255,255, 0), (255, 0,255), ( 0,255,255),
- (128, 0, 0), ( 0,128, 0), ( 0, 0,128), (128,128, 0),
- (128, 0,128), ( 0,128,128), (192,192,192), (128,128,128),
- (153,153,255), (153, 51,102), (255,255,204), (204,255,255),
- (102, 0,102), (255,128,128), ( 0,102,204), (204,204,255),
- ( 0, 0,128), (255, 0,255), (255,255, 0), ( 0,255,255),
- (128, 0,128), (128, 0, 0), ( 0,128,128), ( 0, 0,255),
- ( 0,204,255), (204,255,255), (204,255,204), (255,255,153),
- (153,204,255), (255,153,204), (204,153,255), (255,204,153),
- ( 51,102,255), ( 51,204,204), (153,204, 0), (255,204, 0),
- (255,153, 0), (255,102, 0), (102,102,153), (150,150,150),
- ( 0, 51,102), ( 51,153,102), ( 0, 51, 0), ( 51, 51, 0),
- (153, 51, 0), (153, 51,102), ( 51, 51,153), ( 51, 51, 51),
- )
-
-default_palette = {
- 80: excel_default_palette_b8,
- 70: excel_default_palette_b5,
- 50: excel_default_palette_b5,
- 45: excel_default_palette_b2,
- 40: excel_default_palette_b2,
- 30: excel_default_palette_b2,
- 21: excel_default_palette_b2,
- 20: excel_default_palette_b2,
- }
-
-"""
-00H = Normal
-01H = RowLevel_lv (see next field)
-02H = ColLevel_lv (see next field)
-03H = Comma
-04H = Currency
-05H = Percent
-06H = Comma [0] (BIFF4-BIFF8)
-07H = Currency [0] (BIFF4-BIFF8)
-08H = Hyperlink (BIFF8)
-09H = Followed Hyperlink (BIFF8)
-"""
-built_in_style_names = [
- "Normal",
- "RowLevel_",
- "ColLevel_",
- "Comma",
- "Currency",
- "Percent",
- "Comma [0]",
- "Currency [0]",
- "Hyperlink",
- "Followed Hyperlink",
- ]
-
-def initialise_colour_map(book):
- book.colour_map = {}
- book.colour_indexes_used = {}
- if not book.formatting_info:
- return
- # Add the 8 invariant colours
- for i in range(8):
- book.colour_map[i] = excel_default_palette_b8[i]
- # Add the default palette depending on the version
- dpal = default_palette[book.biff_version]
- ndpal = len(dpal)
- for i in range(ndpal):
- book.colour_map[i+8] = dpal[i]
- # Add the specials -- None means the RGB value is not known
- # System window text colour for border lines
- book.colour_map[ndpal+8] = None
- # System window background colour for pattern background
- book.colour_map[ndpal+8+1] = None #
- for ci in (
- 0x51, # System ToolTip text colour (used in note objects)
- 0x7FFF, # 32767, system window text colour for fonts
- ):
- book.colour_map[ci] = None
-
-def nearest_colour_index(colour_map, rgb, debug=0):
- # General purpose function. Uses Euclidean distance.
- # So far used only for pre-BIFF8 WINDOW2 record.
- # Doesn't have to be fast.
- # Doesn't have to be fancy.
- best_metric = 3 * 256 * 256
- best_colourx = 0
- for colourx, cand_rgb in list(colour_map.items()):
- if cand_rgb is None:
- continue
- metric = 0
- for v1, v2 in zip(rgb, cand_rgb):
- metric += (v1 - v2) * (v1 - v2)
- if metric < best_metric:
- best_metric = metric
- best_colourx = colourx
- if metric == 0:
- break
- if debug:
- print("nearest_colour_index for %r is %r -> %r; best_metric is %d" \
- % (rgb, best_colourx, colour_map[best_colourx], best_metric))
- return best_colourx
-
-# This mixin class exists solely so that Format, Font, and XF.... objects
-# can be compared by value of their attributes.
-class EqNeAttrs(object):
-
- def __eq__(self, other):
- return self.__dict__ == other.__dict__
-
- def __ne__(self, other):
- return self.__dict__ != other.__dict__
-
-# An Excel "font" contains the details of not only what is normally
-# considered a font, but also several other display attributes.
-# Items correspond to those in the Excel UI's Format/Cells/Font tab.
-# - New in version 0.6.1
-class Font(BaseObject, EqNeAttrs):
- # 1 = Characters are bold. Redundant; see "weight" attribute.
- bold = 0
-
- # Values: 0 = ANSI Latin, 1 = System default, 2 = Symbol,
- # 77 = Apple Roman,
- # 128 = ANSI Japanese Shift-JIS,
- # 129 = ANSI Korean (Hangul),
- # 130 = ANSI Korean (Johab),
- # 134 = ANSI Chinese Simplified GBK,
- # 136 = ANSI Chinese Traditional BIG5,
- # 161 = ANSI Greek,
- # 162 = ANSI Turkish,
- # 163 = ANSI Vietnamese,
- # 177 = ANSI Hebrew,
- # 178 = ANSI Arabic,
- # 186 = ANSI Baltic,
- # 204 = ANSI Cyrillic,
- # 222 = ANSI Thai,
- # 238 = ANSI Latin II (Central European),
- # 255 = OEM Latin I
- character_set = 0
- # An explanation of "colour index" is given in the Formatting
- # section at the start of this document.
- colour_index = 0
- # 1 = Superscript, 2 = Subscript.
- escapement = 0
- # 0 = None (unknown or don't care)<br />
- # 1 = Roman (variable width, serifed)<br />
- # 2 = Swiss (variable width, sans-serifed)<br />
- # 3 = Modern (fixed width, serifed or sans-serifed)<br />
- # 4 = Script (cursive)<br />
- # 5 = Decorative (specialised, for example Old English, Fraktur)
- family = 0
- # The 0-based index used to refer to this Font() instance.
- # Note that index 4 is never used; xlrd supplies a dummy place-holder.
- font_index = 0
- # Height of the font (in twips). A twip = 1/20 of a point.
- height = 0
- # 1 = Characters are italic.
- italic = 0
- # The name of the font. Example: u"Arial"
- name = ""
- # 1 = Characters are struck out.
- struck_out = 0
- # 0 = None<br />
- # 1 = Single; 0x21 (33) = Single accounting<br />
- # 2 = Double; 0x22 (34) = Double accounting
- underline_type = 0
- # 1 = Characters are underlined. Redundant; see "underline_type" attribute.
- underlined = 0
- # Font weight (100-1000). Standard values are 400 for normal text
- # and 700 for bold text.
- weight = 400
- # 1 = Font is outline style (Macintosh only)
- outline = 0
- # 1 = Font is shadow style (Macintosh only)
- shadow = 0
-
- # No methods ...
-
-def handle_efont(book, data): # BIFF2 only
- if not book.formatting_info:
- return
- book.font_list[-1].colour_index = unpack('<H', data)[0]
-
-def handle_font(book, data):
- if not book.formatting_info:
- return
- if not book.encoding:
- book.derive_encoding()
- verbose = DEBUG or book.verbosity >= 2
- bv = book.biff_version
- k = len(book.font_list)
- if k == 4:
- f = Font()
- f.name = 'Dummy Font'
- f.font_index = k
- book.font_list.append(f)
- k += 1
- f = Font()
- f.font_index = k
- book.font_list.append(f)
- if bv >= 50:
- (
- f.height, option_flags, f.colour_index, f.weight,
- f.escapement_type, f.underline_type, f.family,
- f.character_set,
- ) = unpack('<HHHHHBBB', data[0:13])
- f.bold = option_flags & 1
- f.italic = (option_flags & 2) >> 1
- f.underlined = (option_flags & 4) >> 2
- f.struck_out = (option_flags & 8) >> 3
- f.outline = (option_flags & 16) >> 4
- f.shadow = (option_flags & 32) >> 5
- if bv >= 80:
- f.name = unpack_unicode(data, 14, lenlen=1)
- else:
- f.name = unpack_string(data, 14, book.encoding, lenlen=1)
- elif bv >= 30:
- f.height, option_flags, f.colour_index = unpack('<HHH', data[0:6])
- f.bold = option_flags & 1
- f.italic = (option_flags & 2) >> 1
- f.underlined = (option_flags & 4) >> 2
- f.struck_out = (option_flags & 8) >> 3
- f.outline = (option_flags & 16) >> 4
- f.shadow = (option_flags & 32) >> 5
- f.name = unpack_string(data, 6, book.encoding, lenlen=1)
- # Now cook up the remaining attributes ...
- f.weight = [400, 700][f.bold]
- f.escapement_type = 0 # None
- f.underline_type = f.underlined # None or Single
- f.family = 0 # Unknown / don't care
- f.character_set = 1 # System default (0 means "ANSI Latin")
- else: # BIFF2
- f.height, option_flags = unpack('<HH', data[0:4])
- f.colour_index = 0x7FFF # "system window text colour"
- f.bold = option_flags & 1
- f.italic = (option_flags & 2) >> 1
- f.underlined = (option_flags & 4) >> 2
- f.struck_out = (option_flags & 8) >> 3
- f.outline = 0
- f.shadow = 0
- f.name = unpack_string(data, 4, book.encoding, lenlen=1)
- # Now cook up the remaining attributes ...
- f.weight = [400, 700][f.bold]
- f.escapement_type = 0 # None
- f.underline_type = f.underlined # None or Single
- f.family = 0 # Unknown / don't care
- f.character_set = 1 # System default (0 means "ANSI Latin")
- if verbose:
- f.dump(
- book.logfile,
- header="--- handle_font: font[%d] ---" % f.font_index,
- footer="-------------------",
- )
-
-# === "Number formats" ===
-
-# "Number format" information from a FORMAT record.
-# - New in version 0.6.1
-class Format(BaseObject, EqNeAttrs):
-
- # The key into Book.format_map
- format_key = 0
-
- # A classification that has been inferred from the format string.
- # Currently, this is used only to distinguish between numbers and dates.
- # Values:
- # FUN = 0 # unknown
- # FDT = 1 # date
- # FNU = 2 # number
- # FGE = 3 # general
- # FTX = 4 # text
- type = FUN
-
- # The format string
- format_str = ''
-
- def __init__(self, format_key, ty, format_str):
- self.format_key = format_key
- self.type = ty
- self.format_str = format_str
-
-std_format_strings = {
- # "std" == "standard for US English locale"
- # #### TODO ... a lot of work to tailor these to the user's locale.
- # See e.g. gnumeric-1.x.y/src/formats.c
- 0x00: "General",
- 0x01: "0",
- 0x02: "0.00",
- 0x03: "#,##0",
- 0x04: "#,##0.00",
- 0x05: "$#,##0_);($#,##0)",
- 0x06: "$#,##0_);[Red]($#,##0)",
- 0x07: "$#,##0.00_);($#,##0.00)",
- 0x08: "$#,##0.00_);[Red]($#,##0.00)",
- 0x09: "0%",
- 0x0a: "0.00%",
- 0x0b: "0.00E+00",
- 0x0c: "# ?/?",
- 0x0d: "# ??/??",
- 0x0e: "m/d/yy",
- 0x0f: "d-mmm-yy",
- 0x10: "d-mmm",
- 0x11: "mmm-yy",
- 0x12: "h:mm AM/PM",
- 0x13: "h:mm:ss AM/PM",
- 0x14: "h:mm",
- 0x15: "h:mm:ss",
- 0x16: "m/d/yy h:mm",
- 0x25: "#,##0_);(#,##0)",
- 0x26: "#,##0_);[Red](#,##0)",
- 0x27: "#,##0.00_);(#,##0.00)",
- 0x28: "#,##0.00_);[Red](#,##0.00)",
- 0x29: "_(* #,##0_);_(* (#,##0);_(* \"-\"_);_(@_)",
- 0x2a: "_($* #,##0_);_($* (#,##0);_($* \"-\"_);_(@_)",
- 0x2b: "_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);_(@_)",
- 0x2c: "_($* #,##0.00_);_($* (#,##0.00);_($* \"-\"??_);_(@_)",
- 0x2d: "mm:ss",
- 0x2e: "[h]:mm:ss",
- 0x2f: "mm:ss.0",
- 0x30: "##0.0E+0",
- 0x31: "@",
- }
-
-fmt_code_ranges = [ # both-inclusive ranges of "standard" format codes
- # Source: the openoffice.org doc't
- ( 0, 0, FGE),
- ( 1, 13, FNU),
- (14, 22, FDT),
- #### (27, 36, FDT), # Japanese dates -- not sure of reliability of this
- (37, 44, FNU),
- (45, 47, FDT),
- (48, 48, FNU),
- (49, 49, FTX),
- ####(50, 58, FDT), # Japanese dates -- but Gnumeric assumes
- # built-in formats finish at 49, not at 163
- ]
-
-std_format_code_types = {}
-for lo, hi, ty in fmt_code_ranges:
- for x in range(lo, hi+1):
- std_format_code_types[x] = ty
-del lo, hi, ty, x
-
-date_chars = 'ymdhs' # year, month/minute, day, hour, second
-date_char_dict = {}
-for _c in date_chars + date_chars.upper():
- date_char_dict[_c] = 5
-del _c, date_chars
-
-#(to_py3):
-skip_char_dict = frozenset('$-+/(): ')
-
-num_char_dict = {
- '0': 5,
- '#': 5,
- '?': 5,
- }
-
-non_date_formats = {
- '0.00E+00':1,
- '##0.0E+0':1,
- 'General' :1,
- 'GENERAL' :1, # OOo Calc 1.1.4 does this.
- 'general' :1, # pyExcelerator 0.6.3 does this.
- '@' :1,
- }
-
-fmt_bracketed_sub = re.compile(r'\[[^]]*\]').sub
-
-# Boolean format strings (actual cases)
-# u'"Yes";"Yes";"No"'
-# u'"True";"True";"False"'
-# u'"On";"On";"Off"'
-
-def is_date_format_string(book, fmt):
- # Heuristics:
- # Ignore "text" and [stuff in square brackets (aarrgghh -- see below)].
- # Handle backslashed-escaped chars properly.
- # E.g. hh\hmm\mss\s should produce a display like 23h59m59s
- # Date formats have one or more of ymdhs (caseless) in them.
- # Numeric formats have # and 0.
- # N.B. u'General"."' hence get rid of "text" first.
- # TODO: Find where formats are interpreted in Gnumeric
- # TODO: u'[h]\\ \\h\\o\\u\\r\\s' ([h] means don't care about hours > 23)
- state = 0
- s = ''
- # (to_py3): ignorable = skip_char_dict.has_key
- for c in fmt:
- if state == 0:
- if c == '"':
- state = 1
- elif c in r"\_*":
- state = 2
- elif c in skip_char_dict: # (to_py3):
- pass
- else:
- s += c
- elif state == 1:
- if c == '"':
- state = 0
- elif state == 2:
- # Ignore char after backslash, underscore or asterisk
- state = 0
- assert 0 <= state <= 2
- if book.verbosity >= 4:
- print("is_date_format_string: reduced format is %r" % s)
- s = fmt_bracketed_sub('', s)
- if s in non_date_formats:
- return False
- state = 0
- separator = ";"
- got_sep = 0
- date_count = num_count = 0
- for c in s:
- if c in date_char_dict:
- date_count += date_char_dict[c]
- elif c in num_char_dict:
- num_count += num_char_dict[c]
- elif c == separator:
- got_sep = 1
- # print num_count, date_count, repr(fmt)
- if date_count and not num_count:
- return True
- if num_count and not date_count:
- return False
- if date_count:
- fprintf(book.logfile,
- 'WARNING *** is_date_format: ambiguous d=%d n=%d fmt=%r\n',
- date_count, num_count, fmt)
- elif not got_sep:
- fprintf(book.logfile,
- "WARNING *** format %r produces constant result\n",
- fmt)
- return date_count > num_count
-
-def handle_format(self, data, rectype=XL_FORMAT):
- DEBUG = 0
- bv = self.biff_version
- if rectype == XL_FORMAT2:
- bv = min(bv, 30)
- if not self.encoding:
- self.derive_encoding()
- strpos = 2
- if bv >= 50:
- fmtkey = unpack('<H', data[0:2])[0]
- else:
- fmtkey = self.actualfmtcount
- if bv <= 30:
- strpos = 0
- self.actualfmtcount += 1
- if bv >= 80:
- unistrg = unpack_unicode(data, 2)
- else:
- unistrg = unpack_string(data, strpos, self.encoding, lenlen=1)
- verbose = DEBUG or self.verbosity >= 3
- if verbose:
- fprintf(self.logfile,
- "FORMAT: count=%d fmtkey=0x%04x (%d) s=%r\n",
- self.actualfmtcount, fmtkey, fmtkey, unistrg)
- is_date_s = self.is_date_format_string(unistrg)
- ty = [FGE, FDT][is_date_s]
- if not(fmtkey > 163 or bv < 50):
- # user_defined if fmtkey > 163
- # N.B. Gnumeric incorrectly starts these at 50 instead of 164 :-(
- # if earlier than BIFF 5, standard info is useless
- std_ty = std_format_code_types.get(fmtkey, FUN)
- # print "std ty", std_ty
- is_date_c = std_ty == FDT
- if 0 < fmtkey < 50 and (is_date_c ^ is_date_s):
- DEBUG = 2
- fprintf(self.logfile,
- "WARNING *** Conflict between "
- "std format key %d and its format string %r\n",
- fmtkey, unistrg)
- if DEBUG == 2:
- fprintf(self.logfile,
- "ty: %d; is_date_c: %r; is_date_s: %r; fmt_strg: %r",
- ty, is_date_c, is_date_s, unistrg)
- fmtobj = Format(fmtkey, ty, unistrg)
- if verbose:
- fmtobj.dump(self.logfile,
- header="--- handle_format [%d] ---" % (self.actualfmtcount-1, ))
- self.format_map[fmtkey] = fmtobj
- self.format_list.append(fmtobj)
-
-# =============================================================================
-
-def handle_palette(book, data):
- if not book.formatting_info:
- return
- verbose = DEBUG or book.verbosity >= 2
- n_colours, = unpack('<H', data[:2])
- expected_n_colours = (16, 56)[book.biff_version >= 50]
- if ((DEBUG or book.verbosity >= 1)
- and n_colours != expected_n_colours):
- fprintf(book.logfile,
- "NOTE *** Expected %d colours in PALETTE record, found %d\n",
- expected_n_colours, n_colours)
- elif verbose:
- fprintf(book.logfile,
- "PALETTE record with %d colours\n", n_colours)
- fmt = '<xx%di' % n_colours # use i to avoid long integers
- expected_size = 4 * n_colours + 2
- actual_size = len(data)
- tolerance = 4
- if not expected_size <= actual_size <= expected_size + tolerance:
- raise XLRDError('PALETTE record: expected size %d, actual size %d' % (expected_size, actual_size))
- colours = unpack(fmt, data[:expected_size])
- assert book.palette_record == [] # There should be only 1 PALETTE record
- # a colour will be 0xbbggrr
- # IOW, red is at the little end
- for i in range(n_colours):
- c = colours[i]
- red = c & 0xff
- green = (c >> 8) & 0xff
- blue = (c >> 16) & 0xff
- old_rgb = book.colour_map[8+i]
- new_rgb = (red, green, blue)
- book.palette_record.append(new_rgb)
- book.colour_map[8+i] = new_rgb
- if verbose:
- if new_rgb != old_rgb:
- print("%2d: %r -> %r" % (i, old_rgb, new_rgb), file=book.logfile)
-
-def palette_epilogue(book):
- # Check colour indexes in fonts etc.
- # This must be done here as FONT records
- # come *before* the PALETTE record :-(
- for font in book.font_list:
- if font.font_index == 4: # the missing font record
- continue
- cx = font.colour_index
- if cx == 0x7fff: # system window text colour
- continue
- if cx in book.colour_map:
- book.colour_indexes_used[cx] = 1
- else:
- print("Size of colour table:", len(book.colour_map))
- print("*** Font #%d (%r): colour index 0x%04x is unknown" \
- % (font.font_index, font.name, cx), file=book.logfile)
- if book.verbosity >= 1:
- used = list(book.colour_indexes_used.keys())
- used.sort()
- print("\nColour indexes used:\n%r\n" % used, file=book.logfile)
-
-def handle_style(book, data):
- verbose = DEBUG or book.verbosity >= 2
- bv = book.biff_version
- flag_and_xfx, built_in_id, level = unpack('<HBB', data[:4])
- xf_index = flag_and_xfx & 0x0fff
- if (data == "\0\0\0\0"
- and "Normal" not in book.style_name_map):
- # Erroneous record (doesn't have built-in bit set).
- # Example file supplied by Jeff Bell.
- built_in = 1
- built_in_id = 0
- xf_index = 0
- name = "Normal"
- level = 255
- elif flag_and_xfx & 0x8000:
- # built-in style
- built_in = 1
- name = built_in_style_names[built_in_id]
- if 1 <= built_in_id <= 2:
- name += str(level + 1)
- else:
- # user-defined style
- if bv >= 80:
- name = unpack_unicode(data, 2, lenlen=2)
- else:
- name = unpack_string(data, 2, book.encoding, lenlen=1)
- if verbose and not name:
- print("WARNING *** A user-defined style has a zero-length name", file=book.logfile)
- built_in = 0
- built_in_id = 0
- level = 0
- book.style_name_map[name] = (built_in, xf_index)
- if verbose:
- print("STYLE: built_in=%d xf_index=%d built_in_id=%d level=%d name=%r" \
- % (built_in, xf_index, built_in_id, level, name), file=book.logfile)
-
-def check_colour_indexes_in_obj(book, obj, orig_index):
- alist = list(obj.__dict__.items())
- alist.sort()
- for attr, nobj in alist:
- if hasattr(nobj, 'dump'):
- check_colour_indexes_in_obj(book, nobj, orig_index)
- elif attr.find('colour_index') >= 0:
- if nobj in book.colour_map:
- book.colour_indexes_used[nobj] = 1
- continue
- oname = obj.__class__.__name__
- print("*** xf #%d : %s.%s = 0x%04x (unknown)" \
- % (orig_index, oname, attr, nobj), file=book.logfile)
-
-def handle_xf(self, data):
- ### self is a Book instance
- # DEBUG = 0
- verbose = DEBUG or self.verbosity >= 3
- bv = self.biff_version
- xf = XF()
- xf.alignment = XFAlignment()
- xf.alignment.indent_level = 0
- xf.alignment.shrink_to_fit = 0
- xf.alignment.text_direction = 0
- xf.border = XFBorder()
- xf.border.diag_up = 0
- xf.border.diag_down = 0
- xf.border.diag_colour_index = 0
- xf.border.diag_line_style = 0 # no line
- xf.background = XFBackground()
- xf.protection = XFProtection()
- # fill in the known standard formats
- if bv >= 50 and not self.xfcount:
- # i.e. do this once before we process the first XF record
- for x in list(std_format_code_types.keys()):
- if x not in self.format_map:
- ty = std_format_code_types[x]
- fmt_str = std_format_strings[x]
- fmtobj = Format(x, ty, fmt_str)
- self.format_map[x] = fmtobj
- if bv >= 80:
- unpack_fmt = '<HHHBBBBIiH'
- (xf.font_index, xf.format_key, pkd_type_par,
- pkd_align1, xf.alignment.rotation, pkd_align2,
- pkd_used, pkd_brdbkg1, pkd_brdbkg2, pkd_brdbkg3,
- ) = unpack(unpack_fmt, data[0:20])
- upkbits(xf.protection, pkd_type_par, (
- (0, 0x01, 'cell_locked'),
- (1, 0x02, 'formula_hidden'),
- ))
- upkbits(xf, pkd_type_par, (
- (2, 0x0004, 'is_style'),
- # Following is not in OOo docs, but is mentioned
- # in Gnumeric source and also in (deep breath)
- # org.apache.poi.hssf.record.ExtendedFormatRecord.java
- (3, 0x0008, 'lotus_123_prefix'), # Meaning is not known.
- (4, 0xFFF0, 'parent_style_index'),
- ))
- upkbits(xf.alignment, pkd_align1, (
- (0, 0x07, 'hor_align'),
- (3, 0x08, 'text_wrapped'),
- (4, 0x70, 'vert_align'),
- ))
- upkbits(xf.alignment, pkd_align2, (
- (0, 0x0f, 'indent_level'),
- (4, 0x10, 'shrink_to_fit'),
- (6, 0xC0, 'text_direction'),
- ))
- reg = pkd_used >> 2
- for attr_stem in \
- "format font alignment border background protection".split():
- attr = "_" + attr_stem + "_flag"
- setattr(xf, attr, reg & 1)
- reg >>= 1
- upkbitsL(xf.border, pkd_brdbkg1, (
- (0, 0x0000000f, 'left_line_style'),
- (4, 0x000000f0, 'right_line_style'),
- (8, 0x00000f00, 'top_line_style'),
- (12, 0x0000f000, 'bottom_line_style'),
- (16, 0x007f0000, 'left_colour_index'),
- (23, 0x3f800000, 'right_colour_index'),
- (30, 0x40000000, 'diag_down'),
- (31, 0x80000000, 'diag_up'),
- ))
- upkbits(xf.border, pkd_brdbkg2, (
- (0, 0x0000007F, 'top_colour_index'),
- (7, 0x00003F80, 'bottom_colour_index'),
- (14, 0x001FC000, 'diag_colour_index'),
- (21, 0x01E00000, 'diag_line_style'),
- ))
- upkbitsL(xf.background, pkd_brdbkg2, (
- (26, 0xFC000000, 'fill_pattern'),
- ))
- upkbits(xf.background, pkd_brdbkg3, (
- (0, 0x007F, 'pattern_colour_index'),
- (7, 0x3F80, 'background_colour_index'),
- ))
- elif bv >= 50:
- unpack_fmt = '<HHHBBIi'
- (xf.font_index, xf.format_key, pkd_type_par,
- pkd_align1, pkd_orient_used,
- pkd_brdbkg1, pkd_brdbkg2,
- ) = unpack(unpack_fmt, data[0:16])
- upkbits(xf.protection, pkd_type_par, (
- (0, 0x01, 'cell_locked'),
- (1, 0x02, 'formula_hidden'),
- ))
- upkbits(xf, pkd_type_par, (
- (2, 0x0004, 'is_style'),
- (3, 0x0008, 'lotus_123_prefix'), # Meaning is not known.
- (4, 0xFFF0, 'parent_style_index'),
- ))
- upkbits(xf.alignment, pkd_align1, (
- (0, 0x07, 'hor_align'),
- (3, 0x08, 'text_wrapped'),
- (4, 0x70, 'vert_align'),
- ))
- orientation = pkd_orient_used & 0x03
- xf.alignment.rotation = [0, 255, 90, 180][orientation]
- reg = pkd_orient_used >> 2
- for attr_stem in \
- "format font alignment border background protection".split():
- attr = "_" + attr_stem + "_flag"
- setattr(xf, attr, reg & 1)
- reg >>= 1
- upkbitsL(xf.background, pkd_brdbkg1, (
- ( 0, 0x0000007F, 'pattern_colour_index'),
- ( 7, 0x00003F80, 'background_colour_index'),
- (16, 0x003F0000, 'fill_pattern'),
- ))
- upkbitsL(xf.border, pkd_brdbkg1, (
- (22, 0x01C00000, 'bottom_line_style'),
- (25, 0xFE000000, 'bottom_colour_index'),
- ))
- upkbits(xf.border, pkd_brdbkg2, (
- ( 0, 0x00000007, 'top_line_style'),
- ( 3, 0x00000038, 'left_line_style'),
- ( 6, 0x000001C0, 'right_line_style'),
- ( 9, 0x0000FE00, 'top_colour_index'),
- (16, 0x007F0000, 'left_colour_index'),
- (23, 0x3F800000, 'right_colour_index'),
- ))
- elif bv >= 40:
- unpack_fmt = '<BBHBBHI'
- (xf.font_index, xf.format_key, pkd_type_par,
- pkd_align_orient, pkd_used,
- pkd_bkg_34, pkd_brd_34,
- ) = unpack(unpack_fmt, data[0:12])
- upkbits(xf.protection, pkd_type_par, (
- (0, 0x01, 'cell_locked'),
- (1, 0x02, 'formula_hidden'),
- ))
- upkbits(xf, pkd_type_par, (
- (2, 0x0004, 'is_style'),
- (3, 0x0008, 'lotus_123_prefix'), # Meaning is not known.
- (4, 0xFFF0, 'parent_style_index'),
- ))
- upkbits(xf.alignment, pkd_align_orient, (
- (0, 0x07, 'hor_align'),
- (3, 0x08, 'text_wrapped'),
- (4, 0x30, 'vert_align'),
- ))
- orientation = (pkd_align_orient & 0xC0) >> 6
- xf.alignment.rotation = [0, 255, 90, 180][orientation]
- reg = pkd_used >> 2
- for attr_stem in \
- "format font alignment border background protection".split():
- attr = "_" + attr_stem + "_flag"
- setattr(xf, attr, reg & 1)
- reg >>= 1
- upkbits(xf.background, pkd_bkg_34, (
- ( 0, 0x003F, 'fill_pattern'),
- ( 6, 0x07C0, 'pattern_colour_index'),
- (11, 0xF800, 'background_colour_index'),
- ))
- upkbitsL(xf.border, pkd_brd_34, (
- ( 0, 0x00000007, 'top_line_style'),
- ( 3, 0x000000F8, 'top_colour_index'),
- ( 8, 0x00000700, 'left_line_style'),
- (11, 0x0000F800, 'left_colour_index'),
- (16, 0x00070000, 'bottom_line_style'),
- (19, 0x00F80000, 'bottom_colour_index'),
- (24, 0x07000000, 'right_line_style'),
- (27, 0xF8000000, 'right_colour_index'),
- ))
- elif bv == 30:
- unpack_fmt = '<BBBBHHI'
- (xf.font_index, xf.format_key, pkd_type_prot,
- pkd_used, pkd_align_par,
- pkd_bkg_34, pkd_brd_34,
- ) = unpack(unpack_fmt, data[0:12])
- upkbits(xf.protection, pkd_type_prot, (
- (0, 0x01, 'cell_locked'),
- (1, 0x02, 'formula_hidden'),
- ))
- upkbits(xf, pkd_type_prot, (
- (2, 0x0004, 'is_style'),
- (3, 0x0008, 'lotus_123_prefix'), # Meaning is not known.
- ))
- upkbits(xf.alignment, pkd_align_par, (
- (0, 0x07, 'hor_align'),
- (3, 0x08, 'text_wrapped'),
- ))
- upkbits(xf, pkd_align_par, (
- (4, 0xFFF0, 'parent_style_index'),
- ))
- reg = pkd_used >> 2
- for attr_stem in \
- "format font alignment border background protection".split():
- attr = "_" + attr_stem + "_flag"
- setattr(xf, attr, reg & 1)
- reg >>= 1
- upkbits(xf.background, pkd_bkg_34, (
- ( 0, 0x003F, 'fill_pattern'),
- ( 6, 0x07C0, 'pattern_colour_index'),
- (11, 0xF800, 'background_colour_index'),
- ))
- upkbitsL(xf.border, pkd_brd_34, (
- ( 0, 0x00000007, 'top_line_style'),
- ( 3, 0x000000F8, 'top_colour_index'),
- ( 8, 0x00000700, 'left_line_style'),
- (11, 0x0000F800, 'left_colour_index'),
- (16, 0x00070000, 'bottom_line_style'),
- (19, 0x00F80000, 'bottom_colour_index'),
- (24, 0x07000000, 'right_line_style'),
- (27, 0xF8000000, 'right_colour_index'),
- ))
- xf.alignment.vert_align = 2 # bottom
- xf.alignment.rotation = 0
- elif bv == 21:
- #### Warning: incomplete treatment; formatting_info not fully supported.
- #### Probably need to offset incoming BIFF2 XF[n] to BIFF8-like XF[n+16],
- #### and create XF[0:16] like the standard ones in BIFF8
- #### *AND* add 16 to all XF references in cell records :-(
- (xf.font_index, format_etc, halign_etc) = unpack('<BxBB', data)
- xf.format_key = format_etc & 0x3F
- upkbits(xf.protection, format_etc, (
- (6, 0x40, 'cell_locked'),
- (7, 0x80, 'formula_hidden'),
- ))
- upkbits(xf.alignment, halign_etc, (
- (0, 0x07, 'hor_align'),
- ))
- for mask, side in ((0x08, 'left'), (0x10, 'right'), (0x20, 'top'), (0x40, 'bottom')):
- if halign_etc & mask:
- colour_index, line_style = 8, 1 # black, thin
- else:
- colour_index, line_style = 0, 0 # none, none
- setattr(xf.border, side + '_colour_index', colour_index)
- setattr(xf.border, side + '_line_style', line_style)
- bg = xf.background
- if halign_etc & 0x80:
- bg.fill_pattern = 17
- else:
- bg.fill_pattern = 0
- bg.background_colour_index = 9 # white
- bg.pattern_colour_index = 8 # black
- xf.parent_style_index = 0 # ???????????
- xf.alignment.vert_align = 2 # bottom
- xf.alignment.rotation = 0
- for attr_stem in \
- "format font alignment border background protection".split():
- attr = "_" + attr_stem + "_flag"
- setattr(xf, attr, 1)
- else:
- raise XLRDError('programmer stuff-up: bv=%d' % bv)
-
- xf.xf_index = len(self.xf_list)
- self.xf_list.append(xf)
- self.xfcount += 1
- if verbose:
- xf.dump(
- self.logfile,
- header="--- handle_xf: xf[%d] ---" % xf.xf_index,
- footer=" ",
- )
- # Now for some assertions ...
- if self.formatting_info:
- if xf.is_style and xf.parent_style_index != 0x0FFF:
- msg = "WARNING *** XF[%d] is a style XF but parent_style_index is 0x%04x, not 0x0fff\n"
- fprintf(self.logfile, msg, xf.xf_index, xf.parent_style_index)
- check_colour_indexes_in_obj(self, xf, xf.xf_index)
- if xf.format_key not in self.format_map:
- msg = "WARNING *** XF[%d] unknown (raw) format key (%d, 0x%04x)\n"
- fprintf(self.logfile, msg,
- xf.xf_index, xf.format_key, xf.format_key)
- xf.format_key = 0
-
-def xf_epilogue(self):
- # self is a Book instance.
- self._xf_epilogue_done = 1
- num_xfs = len(self.xf_list)
- verbose = DEBUG or self.verbosity >= 3
- verbose1 = DEBUG or self.verbosity >= 1
- if verbose:
- fprintf(self.logfile, "xf_epilogue called ...\n")
-
- def check_same(book_arg, xf_arg, parent_arg, attr):
- # the _arg caper is to avoid a Warning msg from Python 2.1 :-(
- if getattr(xf_arg, attr) != getattr(parent_arg, attr):
- fprintf(book_arg.logfile,
- "NOTE !!! XF[%d] parent[%d] %s different\n",
- xf_arg.xf_index, parent_arg.xf_index, attr)
-
- for xfx in range(num_xfs):
- xf = self.xf_list[xfx]
- if xf.format_key not in self.format_map:
- msg = "ERROR *** XF[%d] unknown format key (%d, 0x%04x)\n"
- fprintf(self.logfile, msg,
- xf.xf_index, xf.format_key, xf.format_key)
- xf.format_key = 0
- cellty_from_fmtty = {
- FNU: XL_CELL_NUMBER,
- FUN: XL_CELL_NUMBER,
- FGE: XL_CELL_NUMBER,
- FDT: XL_CELL_DATE,
- FTX: XL_CELL_NUMBER, # Yes, a number can be formatted as text.
- }
- fmt = self.format_map[xf.format_key]
- cellty = cellty_from_fmtty[fmt.type]
- self._xf_index_to_xl_type_map[xf.xf_index] = cellty
- # Now for some assertions etc
- if not self.formatting_info:
- continue
- if xf.is_style:
- continue
- if not(0 <= xf.parent_style_index < num_xfs):
- fprintf(self.logfile,
- "WARNING *** XF[%d]: is_style=%d but parent_style_index=%d\n",
- xf.xf_index, xf.is_style, xf.parent_style_index)
- # make it conform
- xf.parent_style_index = 0
- if self.biff_version >= 30:
- assert xf.parent_style_index != xf.xf_index
- assert self.xf_list[xf.parent_style_index].is_style
- if verbose1 and xf.parent_style_index > xf.xf_index:
- fprintf(self.logfile,
- "NOTE !!! XF[%d]: parent_style_index is %d; out of order?\n",
- xf.xf_index, xf.parent_style_index)
- parent = self.xf_list[xf.parent_style_index]
- if not xf._alignment_flag and not parent._alignment_flag:
- if verbose1: check_same(self, xf, parent, 'alignment')
- if not xf._background_flag and not parent._background_flag:
- if verbose1: check_same(self, xf, parent, 'background')
- if not xf._border_flag and not parent._border_flag:
- if verbose1: check_same(self, xf, parent, 'border')
- if not xf._protection_flag and not parent._protection_flag:
- if verbose1: check_same(self, xf, parent, 'protection')
- if not xf._format_flag and not parent._format_flag:
- if verbose1 and xf.format_key != parent.format_key:
- fprintf(self.logfile,
- "NOTE !!! XF[%d] fmtk=%d, parent[%d] fmtk=%r\n%r / %r\n",
- xf.xf_index, xf.format_key, parent.xf_index, parent.format_key,
- self.format_map[xf.format_key].format_str,
- self.format_map[parent.format_key].format_str)
- if not xf._font_flag and not parent._font_flag:
- if verbose1 and xf.font_index != parent.font_index:
- fprintf(self.logfile,
- "NOTE !!! XF[%d] fontx=%d, parent[%d] fontx=%r\n",
- xf.xf_index, xf.font_index, parent.xf_index, parent.font_index)
-
-def initialise_book(book):
- initialise_colour_map(book)
- book._xf_epilogue_done = 0
- methods = (
- handle_font,
- handle_efont,
- handle_format,
- is_date_format_string,
- handle_palette,
- palette_epilogue,
- handle_style,
- handle_xf,
- xf_epilogue,
- )
- for method in methods:
- setattr(book.__class__, method.__name__, method)
-
-class XFBorder(BaseObject, EqNeAttrs):
- """ A collection of the border-related attributes of an XF record.
-
- Items correspond to those in the Excel UI's Format/Cells/Border tab.
- An explanations of "colour index" is given in the Formatting
- section at the start of this document.
- There are five line style attributes; possible values and the
- associated meanings are:
-
- 0 = No line,
- 1 = Thin,
- 2 = Medium,
- 3 = Dashed,
- 4 = Dotted,
- 5 = Thick,
- 6 = Double,
- 7 = Hair,
- 8 = Medium dashed,
- 9 = Thin dash-dotted,
- 10 = Medium dash-dotted,
- 11 = Thin dash-dot-dotted,
- 12 = Medium dash-dot-dotted,
- 13 = Slanted medium dash-dotted.
- The line styles 8 to 13 appear in BIFF8 files (Excel 97 and later) only.
- For pictures of the line styles, refer to OOo docs s3.10 (p22)
- "Line Styles for Cell Borders (BIFF3-BIFF8)".</p>
- - New in version 0.6.1
- """
-
- # The colour index for the cell's top line
- top_colour_index = 0
- # The colour index for the cell's bottom line
- bottom_colour_index = 0
- # The colour index for the cell's left line
- left_colour_index = 0
- # The colour index for the cell's right line
- right_colour_index = 0
- # The colour index for the cell's diagonal lines, if any
- diag_colour_index = 0
- # The line style for the cell's top line
- top_line_style = 0
- # The line style for the cell's bottom line
- bottom_line_style = 0
- # The line style for the cell's left line
- left_line_style = 0
- # The line style for the cell's right line
- right_line_style = 0
- # The line style for the cell's diagonal lines, if any
- diag_line_style = 0
- # 1 = draw a diagonal from top left to bottom right
- diag_down = 0
- # 1 = draw a diagonal from bottom left to top right
- diag_up = 0
-
-# New in version 0.6.1
-class XFBackground(BaseObject, EqNeAttrs):
- """ A collection of the background-related attributes of an XF record.
-
- Items correspond to those in the Excel UI's Format/Cells/Patterns tab.
- An explanation of "colour index" is given in the Formatting
- section at the start of this document.
-
- """
- # See section 3.11 of the OOo docs.
- fill_pattern = 0
- # See section 3.11 of the OOo docs.
- background_colour_index = 0
- # See section 3.11 of the OOo docs.
- pattern_colour_index = 0
-
-# New in version 0.6.1
-class XFAlignment(BaseObject, EqNeAttrs):
- """ A collection of the alignment and similar attributes of an XF record.
-
- Items correspond to those in the Excel UI's Format/Cells/Alignment tab.
- """
- # Values: section 5.115 (p 219) of OOo docs
- hor_align = 0
- # Values: section 5.115 (p 220) of OOo docs
- vert_align = 0
- # Values: section 5.115 (p 220) of OOo docs.
- # Note: file versions BIFF7 and earlier use the documented
- # "orientation" attribute; this will be mapped (without loss)
- # into "rotation".
- rotation = 0
- # 1 = text is wrapped at right margin
- text_wrapped = 0
- # A number in range(15).
- indent_level = 0
- # 1 = shrink font size to fit text into cell.
- shrink_to_fit = 0
- # 0 = according to context; 1 = left-to-right; 2 = right-to-left
- text_direction = 0
-
-# New in version 0.6.1
-class XFProtection(BaseObject, EqNeAttrs):
- """ A collection of the protection-related attributes of an XF record.
-
- Items correspond to those in the Excel UI's Format/Cells/Protection tab.
- Note the OOo docs include the "cell or style" bit
- in this bundle of attributes.
- This is incorrect; the bit is used in determining which bundles to use.
-
- """
- # 1 = Cell is prevented from being changed, moved, resized, or deleted
- # (only if the sheet is protected).
- cell_locked = 0
- # 1 = Hide formula so that it doesn't appear in the formula bar when
- # the cell is selected (only if the sheet is protected).
- formula_hidden = 0
-
-# New in version 0.6.1
-class XF(BaseObject):
- """ eXtended Formatting information for cells, rows, columns and styles.
-
- Each of the 6 flags below describes the validity of
- a specific group of attributes.
-
- In cell XFs, flag==0 means the attributes of the parent style XF are used,
- (but only if the attributes are valid there); flag==1 means the attributes
- of this XF are used.
- In style XFs, flag==0 means the attribute setting is valid; flag==1 means
- the attribute should be ignored.
- Note that the API
- provides both "raw" XFs and "computed" XFs -- in the latter case, cell XFs
- have had the above inheritance mechanism applied.
- """
- # 0 = cell XF, 1 = style XF
- is_style = 0
- # cell XF: Index into Book.xf_list
- # of this XF's style XF
- # style XF: 0xFFF
- parent_style_index = 0
- _format_flag = 0
- _font_flag = 0
- _alignment_flag = 0
- _border_flag = 0
- _background_flag = 0
- _protection_flag = 0
- # Index into Book.xf_list
- xf_index = 0
- # Index into Book.font_list
- font_index = 0
- # Key into Book.format_map
- #
- # Warning: OOo docs on the XF record call this "Index to FORMAT record".
- # It is not an index in the Python sense. It is a key to a map.
- # It is true **only** for Excel 4.0 and earlier files
- # that the key into format_map from an XF instance
- # is the same as the index into format_list, and **only**
- # if the index is less than 164.
- #
- format_key = 0
- # An instance of an XFProtection object.
- protection = None
- # An instance of an XFBackground object.
- background = None
- # An instance of an XFAlignment object.
- alignment = None
- # An instance of an XFBorder object.
- border = None
diff --git a/tablib/packages/xlrd3/formula.py b/tablib/packages/xlrd3/formula.py
deleted file mode 100644
index 445d761..0000000
--- a/tablib/packages/xlrd3/formula.py
+++ /dev/null
@@ -1,2083 +0,0 @@
-# Module for parsing/evaluating Microsoft Excel formulas.
-#
-# Copyright © 2005-2009 Stephen John Machin, Lingfo Pty Ltd
-# This module is part of the xlrd3 package, which is released under
-# a BSD-style licence.
-
-# No part of the content of this file was derived from the works of David Giffin.
-
-import copy
-from struct import unpack
-
-from .biffh import unpack_unicode_update_pos, unpack_string_update_pos, \
- XLRDError, hex_char_dump, error_text_from_code, BaseObject
-
-__all__ = [
- 'oBOOL', 'oERR', 'oNUM', 'oREF', 'oREL', 'oSTRG', 'oUNK',
- 'decompile_formula',
- 'dump_formula',
- 'evaluate_name_formula',
- 'okind_dict',
- 'rangename3d', 'rangename3drel', 'cellname', 'cellnameabs', 'colname',
- ]
-
-# sztabN[opcode] -> the number of bytes to consume.
-# -1 means variable
-# -2 means this opcode not implemented in this version.
-# Which N to use? Depends on biff_version; see szdict.
-sztab0 = [-2, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -2, -1, 8, 4, 2, 2, 3, 9, 8, 2, 3, 8, 4, 7, 5, 5, 5, 2, 4, 7, 4, 7, 2, 2, -2, -2, -2, -2, -2, -2, -2, -2, 3, -2, -2, -2, -2, -2, -2, -2]
-sztab1 = [-2, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -2, -1, 11, 5, 2, 2, 3, 9, 9, 2, 3, 11, 4, 7, 7, 7, 7, 3, 4, 7, 4, 7, 3, 3, -2, -2, -2, -2, -2, -2, -2, -2, 3, -2, -2, -2, -2, -2, -2, -2]
-sztab2 = [-2, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -2, -1, 11, 5, 2, 2, 3, 9, 9, 3, 4, 11, 4, 7, 7, 7, 7, 3, 4, 7, 4, 7, 3, 3, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2]
-sztab3 = [-2, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -2, -1, -2, -2, 2, 2, 3, 9, 9, 3, 4, 15, 4, 7, 7, 7, 7, 3, 4, 7, 4, 7, 3, 3, -2, -2, -2, -2, -2, -2, -2, -2, -2, 25, 18, 21, 18, 21, -2, -2]
-sztab4 = [-2, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -2, -2, 2, 2, 3, 9, 9, 3, 4, 5, 5, 9, 7, 7, 7, 3, 5, 9, 5, 9, 3, 3, -2, -2, -2, -2, -2, -2, -2, -2, -2, 7, 7, 11, 7, 11, -2, -2]
-
-szdict = {
- 20 : sztab0,
- 21 : sztab0, # Suppose 21 is same as 20....
- 30 : sztab1,
- 40 : sztab2,
- 45 : sztab2,
- 50 : sztab3,
- 70 : sztab3,
- 80 : sztab4,
- }
-
-# For debugging purposes ... the name for each opcode
-# (without the prefix "t" used on OOo docs)
-onames = ['Unk00', 'Exp', 'Tbl', 'Add', 'Sub', 'Mul', 'Div', 'Power', 'Concat', 'LT', 'LE', 'EQ', 'GE', 'GT', 'NE', 'Isect', 'List', 'Range', 'Uplus', 'Uminus', 'Percent', 'Paren', 'MissArg', 'Str', 'Extended', 'Attr', 'Sheet', 'EndSheet', 'Err', 'Bool', 'Int', 'Num', 'Array', 'Func', 'FuncVar', 'Name', 'Ref', 'Area', 'MemArea', 'MemErr', 'MemNoMem', 'MemFunc', 'RefErr', 'AreaErr', 'RefN', 'AreaN', 'MemAreaN', 'MemNoMemN', '', '', '', '', '', '', '', '', 'FuncCE', 'NameX', 'Ref3d', 'Area3d', 'RefErr3d', 'AreaErr3d', '', '']
-
-func_defs = {
- # index: (name, min#args, max#args, flags, #known_args, return_type, kargs)
- 0 : ('COUNT', 0, 30, 0x04, 1, 'V', 'R'),
- 1 : ('IF', 2, 3, 0x04, 3, 'V', 'VRR'),
- 2 : ('ISNA', 1, 1, 0x02, 1, 'V', 'V'),
- 3 : ('ISERROR', 1, 1, 0x02, 1, 'V', 'V'),
- 4 : ('SUM', 0, 30, 0x04, 1, 'V', 'R'),
- 5 : ('AVERAGE', 1, 30, 0x04, 1, 'V', 'R'),
- 6 : ('MIN', 1, 30, 0x04, 1, 'V', 'R'),
- 7 : ('MAX', 1, 30, 0x04, 1, 'V', 'R'),
- 8 : ('ROW', 0, 1, 0x04, 1, 'V', 'R'),
- 9 : ('COLUMN', 0, 1, 0x04, 1, 'V', 'R'),
- 10 : ('NA', 0, 0, 0x02, 0, 'V', ''),
- 11 : ('NPV', 2, 30, 0x04, 2, 'V', 'VR'),
- 12 : ('STDEV', 1, 30, 0x04, 1, 'V', 'R'),
- 13 : ('DOLLAR', 1, 2, 0x04, 1, 'V', 'V'),
- 14 : ('FIXED', 2, 3, 0x04, 3, 'V', 'VVV'),
- 15 : ('SIN', 1, 1, 0x02, 1, 'V', 'V'),
- 16 : ('COS', 1, 1, 0x02, 1, 'V', 'V'),
- 17 : ('TAN', 1, 1, 0x02, 1, 'V', 'V'),
- 18 : ('ATAN', 1, 1, 0x02, 1, 'V', 'V'),
- 19 : ('PI', 0, 0, 0x02, 0, 'V', ''),
- 20 : ('SQRT', 1, 1, 0x02, 1, 'V', 'V'),
- 21 : ('EXP', 1, 1, 0x02, 1, 'V', 'V'),
- 22 : ('LN', 1, 1, 0x02, 1, 'V', 'V'),
- 23 : ('LOG10', 1, 1, 0x02, 1, 'V', 'V'),
- 24 : ('ABS', 1, 1, 0x02, 1, 'V', 'V'),
- 25 : ('INT', 1, 1, 0x02, 1, 'V', 'V'),
- 26 : ('SIGN', 1, 1, 0x02, 1, 'V', 'V'),
- 27 : ('ROUND', 2, 2, 0x02, 2, 'V', 'VV'),
- 28 : ('LOOKUP', 2, 3, 0x04, 2, 'V', 'VR'),
- 29 : ('INDEX', 2, 4, 0x0c, 4, 'R', 'RVVV'),
- 30 : ('REPT', 2, 2, 0x02, 2, 'V', 'VV'),
- 31 : ('MID', 3, 3, 0x02, 3, 'V', 'VVV'),
- 32 : ('LEN', 1, 1, 0x02, 1, 'V', 'V'),
- 33 : ('VALUE', 1, 1, 0x02, 1, 'V', 'V'),
- 34 : ('TRUE', 0, 0, 0x02, 0, 'V', ''),
- 35 : ('FALSE', 0, 0, 0x02, 0, 'V', ''),
- 36 : ('AND', 1, 30, 0x04, 1, 'V', 'R'),
- 37 : ('OR', 1, 30, 0x04, 1, 'V', 'R'),
- 38 : ('NOT', 1, 1, 0x02, 1, 'V', 'V'),
- 39 : ('MOD', 2, 2, 0x02, 2, 'V', 'VV'),
- 40 : ('DCOUNT', 3, 3, 0x02, 3, 'V', 'RRR'),
- 41 : ('DSUM', 3, 3, 0x02, 3, 'V', 'RRR'),
- 42 : ('DAVERAGE', 3, 3, 0x02, 3, 'V', 'RRR'),
- 43 : ('DMIN', 3, 3, 0x02, 3, 'V', 'RRR'),
- 44 : ('DMAX', 3, 3, 0x02, 3, 'V', 'RRR'),
- 45 : ('DSTDEV', 3, 3, 0x02, 3, 'V', 'RRR'),
- 46 : ('VAR', 1, 30, 0x04, 1, 'V', 'R'),
- 47 : ('DVAR', 3, 3, 0x02, 3, 'V', 'RRR'),
- 48 : ('TEXT', 2, 2, 0x02, 2, 'V', 'VV'),
- 49 : ('LINEST', 1, 4, 0x04, 4, 'A', 'RRVV'),
- 50 : ('TREND', 1, 4, 0x04, 4, 'A', 'RRRV'),
- 51 : ('LOGEST', 1, 4, 0x04, 4, 'A', 'RRVV'),
- 52 : ('GROWTH', 1, 4, 0x04, 4, 'A', 'RRRV'),
- 56 : ('PV', 3, 5, 0x04, 5, 'V', 'VVVVV'),
- 57 : ('FV', 3, 5, 0x04, 5, 'V', 'VVVVV'),
- 58 : ('NPER', 3, 5, 0x04, 5, 'V', 'VVVVV'),
- 59 : ('PMT', 3, 5, 0x04, 5, 'V', 'VVVVV'),
- 60 : ('RATE', 3, 6, 0x04, 6, 'V', 'VVVVVV'),
- 61 : ('MIRR', 3, 3, 0x02, 3, 'V', 'RVV'),
- 62 : ('IRR', 1, 2, 0x04, 2, 'V', 'RV'),
- 63 : ('RAND', 0, 0, 0x0a, 0, 'V', ''),
- 64 : ('MATCH', 2, 3, 0x04, 3, 'V', 'VRR'),
- 65 : ('DATE', 3, 3, 0x02, 3, 'V', 'VVV'),
- 66 : ('TIME', 3, 3, 0x02, 3, 'V', 'VVV'),
- 67 : ('DAY', 1, 1, 0x02, 1, 'V', 'V'),
- 68 : ('MONTH', 1, 1, 0x02, 1, 'V', 'V'),
- 69 : ('YEAR', 1, 1, 0x02, 1, 'V', 'V'),
- 70 : ('WEEKDAY', 1, 2, 0x04, 2, 'V', 'VV'),
- 71 : ('HOUR', 1, 1, 0x02, 1, 'V', 'V'),
- 72 : ('MINUTE', 1, 1, 0x02, 1, 'V', 'V'),
- 73 : ('SECOND', 1, 1, 0x02, 1, 'V', 'V'),
- 74 : ('NOW', 0, 0, 0x0a, 0, 'V', ''),
- 75 : ('AREAS', 1, 1, 0x02, 1, 'V', 'R'),
- 76 : ('ROWS', 1, 1, 0x02, 1, 'V', 'R'),
- 77 : ('COLUMNS', 1, 1, 0x02, 1, 'V', 'R'),
- 78 : ('OFFSET', 3, 5, 0x04, 5, 'R', 'RVVVV'),
- 82 : ('SEARCH', 2, 3, 0x04, 3, 'V', 'VVV'),
- 83 : ('TRANSPOSE', 1, 1, 0x02, 1, 'A', 'A'),
- 86 : ('TYPE', 1, 1, 0x02, 1, 'V', 'V'),
- 92 : ('SERIESSUM', 4, 4, 0x02, 4, 'V', 'VVVA'),
- 97 : ('ATAN2', 2, 2, 0x02, 2, 'V', 'VV'),
- 98 : ('ASIN', 1, 1, 0x02, 1, 'V', 'V'),
- 99 : ('ACOS', 1, 1, 0x02, 1, 'V', 'V'),
- 100: ('CHOOSE', 2, 30, 0x04, 2, 'V', 'VR'),
- 101: ('HLOOKUP', 3, 4, 0x04, 4, 'V', 'VRRV'),
- 102: ('VLOOKUP', 3, 4, 0x04, 4, 'V', 'VRRV'),
- 105: ('ISREF', 1, 1, 0x02, 1, 'V', 'R'),
- 109: ('LOG', 1, 2, 0x04, 2, 'V', 'VV'),
- 111: ('CHAR', 1, 1, 0x02, 1, 'V', 'V'),
- 112: ('LOWER', 1, 1, 0x02, 1, 'V', 'V'),
- 113: ('UPPER', 1, 1, 0x02, 1, 'V', 'V'),
- 114: ('PROPER', 1, 1, 0x02, 1, 'V', 'V'),
- 115: ('LEFT', 1, 2, 0x04, 2, 'V', 'VV'),
- 116: ('RIGHT', 1, 2, 0x04, 2, 'V', 'VV'),
- 117: ('EXACT', 2, 2, 0x02, 2, 'V', 'VV'),
- 118: ('TRIM', 1, 1, 0x02, 1, 'V', 'V'),
- 119: ('REPLACE', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 120: ('SUBSTITUTE', 3, 4, 0x04, 4, 'V', 'VVVV'),
- 121: ('CODE', 1, 1, 0x02, 1, 'V', 'V'),
- 124: ('FIND', 2, 3, 0x04, 3, 'V', 'VVV'),
- 125: ('CELL', 1, 2, 0x0c, 2, 'V', 'VR'),
- 126: ('ISERR', 1, 1, 0x02, 1, 'V', 'V'),
- 127: ('ISTEXT', 1, 1, 0x02, 1, 'V', 'V'),
- 128: ('ISNUMBER', 1, 1, 0x02, 1, 'V', 'V'),
- 129: ('ISBLANK', 1, 1, 0x02, 1, 'V', 'V'),
- 130: ('T', 1, 1, 0x02, 1, 'V', 'R'),
- 131: ('N', 1, 1, 0x02, 1, 'V', 'R'),
- 140: ('DATEVALUE', 1, 1, 0x02, 1, 'V', 'V'),
- 141: ('TIMEVALUE', 1, 1, 0x02, 1, 'V', 'V'),
- 142: ('SLN', 3, 3, 0x02, 3, 'V', 'VVV'),
- 143: ('SYD', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 144: ('DDB', 4, 5, 0x04, 5, 'V', 'VVVVV'),
- 148: ('INDIRECT', 1, 2, 0x0c, 2, 'R', 'VV'),
- 162: ('CLEAN', 1, 1, 0x02, 1, 'V', 'V'),
- 163: ('MDETERM', 1, 1, 0x02, 1, 'V', 'A'),
- 164: ('MINVERSE', 1, 1, 0x02, 1, 'A', 'A'),
- 165: ('MMULT', 2, 2, 0x02, 2, 'A', 'AA'),
- 167: ('IPMT', 4, 6, 0x04, 6, 'V', 'VVVVVV'),
- 168: ('PPMT', 4, 6, 0x04, 6, 'V', 'VVVVVV'),
- 169: ('COUNTA', 0, 30, 0x04, 1, 'V', 'R'),
- 183: ('PRODUCT', 0, 30, 0x04, 1, 'V', 'R'),
- 184: ('FACT', 1, 1, 0x02, 1, 'V', 'V'),
- 189: ('DPRODUCT', 3, 3, 0x02, 3, 'V', 'RRR'),
- 190: ('ISNONTEXT', 1, 1, 0x02, 1, 'V', 'V'),
- 193: ('STDEVP', 1, 30, 0x04, 1, 'V', 'R'),
- 194: ('VARP', 1, 30, 0x04, 1, 'V', 'R'),
- 195: ('DSTDEVP', 3, 3, 0x02, 3, 'V', 'RRR'),
- 196: ('DVARP', 3, 3, 0x02, 3, 'V', 'RRR'),
- 197: ('TRUNC', 1, 2, 0x04, 2, 'V', 'VV'),
- 198: ('ISLOGICAL', 1, 1, 0x02, 1, 'V', 'V'),
- 199: ('DCOUNTA', 3, 3, 0x02, 3, 'V', 'RRR'),
- 204: ('USDOLLAR', 1, 2, 0x04, 2, 'V', 'VV'),
- 205: ('FINDB', 2, 3, 0x04, 3, 'V', 'VVV'),
- 206: ('SEARCHB', 2, 3, 0x04, 3, 'V', 'VVV'),
- 207: ('REPLACEB', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 208: ('LEFTB', 1, 2, 0x04, 2, 'V', 'VV'),
- 209: ('RIGHTB', 1, 2, 0x04, 2, 'V', 'VV'),
- 210: ('MIDB', 3, 3, 0x02, 3, 'V', 'VVV'),
- 211: ('LENB', 1, 1, 0x02, 1, 'V', 'V'),
- 212: ('ROUNDUP', 2, 2, 0x02, 2, 'V', 'VV'),
- 213: ('ROUNDDOWN', 2, 2, 0x02, 2, 'V', 'VV'),
- 214: ('ASC', 1, 1, 0x02, 1, 'V', 'V'),
- 215: ('DBCS', 1, 1, 0x02, 1, 'V', 'V'),
- 216: ('RANK', 2, 3, 0x04, 3, 'V', 'VRV'),
- 219: ('ADDRESS', 2, 5, 0x04, 5, 'V', 'VVVVV'),
- 220: ('DAYS360', 2, 3, 0x04, 3, 'V', 'VVV'),
- 221: ('TODAY', 0, 0, 0x0a, 0, 'V', ''),
- 222: ('VDB', 5, 7, 0x04, 7, 'V', 'VVVVVVV'),
- 227: ('MEDIAN', 1, 30, 0x04, 1, 'V', 'R'),
- 228: ('SUMPRODUCT', 1, 30, 0x04, 1, 'V', 'A'),
- 229: ('SINH', 1, 1, 0x02, 1, 'V', 'V'),
- 230: ('COSH', 1, 1, 0x02, 1, 'V', 'V'),
- 231: ('TANH', 1, 1, 0x02, 1, 'V', 'V'),
- 232: ('ASINH', 1, 1, 0x02, 1, 'V', 'V'),
- 233: ('ACOSH', 1, 1, 0x02, 1, 'V', 'V'),
- 234: ('ATANH', 1, 1, 0x02, 1, 'V', 'V'),
- 235: ('DGET', 3, 3, 0x02, 3, 'V', 'RRR'),
- 244: ('INFO', 1, 1, 0x02, 1, 'V', 'V'),
- 247: ('DB', 4, 5, 0x04, 5, 'V', 'VVVVV'),
- 252: ('FREQUENCY', 2, 2, 0x02, 2, 'A', 'RR'),
- 261: ('ERROR.TYPE', 1, 1, 0x02, 1, 'V', 'V'),
- 269: ('AVEDEV', 1, 30, 0x04, 1, 'V', 'R'),
- 270: ('BETADIST', 3, 5, 0x04, 1, 'V', 'V'),
- 271: ('GAMMALN', 1, 1, 0x02, 1, 'V', 'V'),
- 272: ('BETAINV', 3, 5, 0x04, 1, 'V', 'V'),
- 273: ('BINOMDIST', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 274: ('CHIDIST', 2, 2, 0x02, 2, 'V', 'VV'),
- 275: ('CHIINV', 2, 2, 0x02, 2, 'V', 'VV'),
- 276: ('COMBIN', 2, 2, 0x02, 2, 'V', 'VV'),
- 277: ('CONFIDENCE', 3, 3, 0x02, 3, 'V', 'VVV'),
- 278: ('CRITBINOM', 3, 3, 0x02, 3, 'V', 'VVV'),
- 279: ('EVEN', 1, 1, 0x02, 1, 'V', 'V'),
- 280: ('EXPONDIST', 3, 3, 0x02, 3, 'V', 'VVV'),
- 281: ('FDIST', 3, 3, 0x02, 3, 'V', 'VVV'),
- 282: ('FINV', 3, 3, 0x02, 3, 'V', 'VVV'),
- 283: ('FISHER', 1, 1, 0x02, 1, 'V', 'V'),
- 284: ('FISHERINV', 1, 1, 0x02, 1, 'V', 'V'),
- 285: ('FLOOR', 2, 2, 0x02, 2, 'V', 'VV'),
- 286: ('GAMMADIST', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 287: ('GAMMAINV', 3, 3, 0x02, 3, 'V', 'VVV'),
- 288: ('CEILING', 2, 2, 0x02, 2, 'V', 'VV'),
- 289: ('HYPGEOMDIST', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 290: ('LOGNORMDIST', 3, 3, 0x02, 3, 'V', 'VVV'),
- 291: ('LOGINV', 3, 3, 0x02, 3, 'V', 'VVV'),
- 292: ('NEGBINOMDIST', 3, 3, 0x02, 3, 'V', 'VVV'),
- 293: ('NORMDIST', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 294: ('NORMSDIST', 1, 1, 0x02, 1, 'V', 'V'),
- 295: ('NORMINV', 3, 3, 0x02, 3, 'V', 'VVV'),
- 296: ('NORMSINV', 1, 1, 0x02, 1, 'V', 'V'),
- 297: ('STANDARDIZE', 3, 3, 0x02, 3, 'V', 'VVV'),
- 298: ('ODD', 1, 1, 0x02, 1, 'V', 'V'),
- 299: ('PERMUT', 2, 2, 0x02, 2, 'V', 'VV'),
- 300: ('POISSON', 3, 3, 0x02, 3, 'V', 'VVV'),
- 301: ('TDIST', 3, 3, 0x02, 3, 'V', 'VVV'),
- 302: ('WEIBULL', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 303: ('SUMXMY2', 2, 2, 0x02, 2, 'V', 'AA'),
- 304: ('SUMX2MY2', 2, 2, 0x02, 2, 'V', 'AA'),
- 305: ('SUMX2PY2', 2, 2, 0x02, 2, 'V', 'AA'),
- 306: ('CHITEST', 2, 2, 0x02, 2, 'V', 'AA'),
- 307: ('CORREL', 2, 2, 0x02, 2, 'V', 'AA'),
- 308: ('COVAR', 2, 2, 0x02, 2, 'V', 'AA'),
- 309: ('FORECAST', 3, 3, 0x02, 3, 'V', 'VAA'),
- 310: ('FTEST', 2, 2, 0x02, 2, 'V', 'AA'),
- 311: ('INTERCEPT', 2, 2, 0x02, 2, 'V', 'AA'),
- 312: ('PEARSON', 2, 2, 0x02, 2, 'V', 'AA'),
- 313: ('RSQ', 2, 2, 0x02, 2, 'V', 'AA'),
- 314: ('STEYX', 2, 2, 0x02, 2, 'V', 'AA'),
- 315: ('SLOPE', 2, 2, 0x02, 2, 'V', 'AA'),
- 316: ('TTEST', 4, 4, 0x02, 4, 'V', 'AAVV'),
- 317: ('PROB', 3, 4, 0x04, 3, 'V', 'AAV'),
- 318: ('DEVSQ', 1, 30, 0x04, 1, 'V', 'R'),
- 319: ('GEOMEAN', 1, 30, 0x04, 1, 'V', 'R'),
- 320: ('HARMEAN', 1, 30, 0x04, 1, 'V', 'R'),
- 321: ('SUMSQ', 0, 30, 0x04, 1, 'V', 'R'),
- 322: ('KURT', 1, 30, 0x04, 1, 'V', 'R'),
- 323: ('SKEW', 1, 30, 0x04, 1, 'V', 'R'),
- 324: ('ZTEST', 2, 3, 0x04, 2, 'V', 'RV'),
- 325: ('LARGE', 2, 2, 0x02, 2, 'V', 'RV'),
- 326: ('SMALL', 2, 2, 0x02, 2, 'V', 'RV'),
- 327: ('QUARTILE', 2, 2, 0x02, 2, 'V', 'RV'),
- 328: ('PERCENTILE', 2, 2, 0x02, 2, 'V', 'RV'),
- 329: ('PERCENTRANK', 2, 3, 0x04, 2, 'V', 'RV'),
- 330: ('MODE', 1, 30, 0x04, 1, 'V', 'A'),
- 331: ('TRIMMEAN', 2, 2, 0x02, 2, 'V', 'RV'),
- 332: ('TINV', 2, 2, 0x02, 2, 'V', 'VV'),
- 336: ('CONCATENATE', 0, 30, 0x04, 1, 'V', 'V'),
- 337: ('POWER', 2, 2, 0x02, 2, 'V', 'VV'),
- 342: ('RADIANS', 1, 1, 0x02, 1, 'V', 'V'),
- 343: ('DEGREES', 1, 1, 0x02, 1, 'V', 'V'),
- 344: ('SUBTOTAL', 2, 30, 0x04, 2, 'V', 'VR'),
- 345: ('SUMIF', 2, 3, 0x04, 3, 'V', 'RVR'),
- 346: ('COUNTIF', 2, 2, 0x02, 2, 'V', 'RV'),
- 347: ('COUNTBLANK', 1, 1, 0x02, 1, 'V', 'R'),
- 350: ('ISPMT', 4, 4, 0x02, 4, 'V', 'VVVV'),
- 351: ('DATEDIF', 3, 3, 0x02, 3, 'V', 'VVV'),
- 352: ('DATESTRING', 1, 1, 0x02, 1, 'V', 'V'),
- 353: ('NUMBERSTRING', 2, 2, 0x02, 2, 'V', 'VV'),
- 354: ('ROMAN', 1, 2, 0x04, 2, 'V', 'VV'),
- 358: ('GETPIVOTDATA', 2, 2, 0x02, 2, 'V', 'RV'),
- 359: ('HYPERLINK', 1, 2, 0x04, 2, 'V', 'VV'),
- 360: ('PHONETIC', 1, 1, 0x02, 1, 'V', 'V'),
- 361: ('AVERAGEA', 1, 30, 0x04, 1, 'V', 'R'),
- 362: ('MAXA', 1, 30, 0x04, 1, 'V', 'R'),
- 363: ('MINA', 1, 30, 0x04, 1, 'V', 'R'),
- 364: ('STDEVPA', 1, 30, 0x04, 1, 'V', 'R'),
- 365: ('VARPA', 1, 30, 0x04, 1, 'V', 'R'),
- 366: ('STDEVA', 1, 30, 0x04, 1, 'V', 'R'),
- 367: ('VARA', 1, 30, 0x04, 1, 'V', 'R'),
- 368: ('BAHTTEXT', 1, 1, 0x02, 1, 'V', 'V'),
- 369: ('THAIDAYOFWEEK', 1, 1, 0x02, 1, 'V', 'V'),
- 370: ('THAIDIGIT', 1, 1, 0x02, 1, 'V', 'V'),
- 371: ('THAIMONTHOFYEAR', 1, 1, 0x02, 1, 'V', 'V'),
- 372: ('THAINUMSOUND', 1, 1, 0x02, 1, 'V', 'V'),
- 373: ('THAINUMSTRING', 1, 1, 0x02, 1, 'V', 'V'),
- 374: ('THAISTRINGLENGTH', 1, 1, 0x02, 1, 'V', 'V'),
- 375: ('ISTHAIDIGIT', 1, 1, 0x02, 1, 'V', 'V'),
- 376: ('ROUNDBAHTDOWN', 1, 1, 0x02, 1, 'V', 'V'),
- 377: ('ROUNDBAHTUP', 1, 1, 0x02, 1, 'V', 'V'),
- 378: ('THAIYEAR', 1, 1, 0x02, 1, 'V', 'V'),
- 379: ('RTD', 2, 5, 0x04, 1, 'V', 'V'),
- }
-
-tAttrNames = {
- 0x00: "Skip??", # seen in SAMPLES.XLS which shipped with Excel 5.0
- 0x01: "Volatile",
- 0x02: "If",
- 0x04: "Choose",
- 0x08: "Skip",
- 0x10: "Sum",
- 0x20: "Assign",
- 0x40: "Space",
- 0x41: "SpaceVolatile",
- }
-
-_error_opcodes = frozenset([0x07, 0x08, 0x0A, 0x0B, 0x1C, 0x1D, 0x2F])
-
-tRangeFuncs = (min, max, min, max, min, max)
-tIsectFuncs = (max, min, max, min, max, min)
-
-def do_box_funcs(box_funcs, boxa, boxb):
- return tuple([
- func(numa, numb)
- for func, numa, numb in zip(box_funcs, boxa.coords, boxb.coords)
- ])
-
-def adjust_cell_addr_biff8(rowval, colval, reldelta, browx=None, bcolx=None):
- row_rel = (colval >> 15) & 1
- col_rel = (colval >> 14) & 1
- rowx = rowval
- colx = colval & 0xff
- if reldelta:
- if row_rel and rowx >= 32768:
- rowx -= 65536
- if col_rel and colx >= 128:
- colx -= 256
- else:
- if row_rel:
- rowx -= browx
- if col_rel:
- colx -= bcolx
- return rowx, colx, row_rel, col_rel
-
-def adjust_cell_addr_biff_le7(
- rowval, colval, reldelta, browx=None, bcolx=None):
- row_rel = (rowval >> 15) & 1
- col_rel = (rowval >> 14) & 1
- rowx = rowval & 0x3fff
- colx = colval
- if reldelta:
- if row_rel and rowx >= 8192:
- rowx -= 16384
- if col_rel and colx >= 128:
- colx -= 256
- else:
- if row_rel:
- rowx -= browx
- if col_rel:
- colx -= bcolx
- return rowx, colx, row_rel, col_rel
-
-def get_cell_addr(data, pos, bv, reldelta, browx=None, bcolx=None):
- if bv >= 80:
- rowval, colval = unpack("<HH", data[pos:pos+4])
- # print " rv=%04xh cv=%04xh" % (rowval, colval)
- return adjust_cell_addr_biff8(rowval, colval, reldelta, browx, bcolx)
- else:
- rowval, colval = unpack("<HB", data[pos:pos+3])
- # print " rv=%04xh cv=%04xh" % (rowval, colval)
- return adjust_cell_addr_biff_le7(
- rowval, colval, reldelta, browx, bcolx)
-
-def get_cell_range_addr(data, pos, bv, reldelta, browx=None, bcolx=None):
- if bv >= 80:
- row1val, row2val, col1val, col2val = unpack("<HHHH", data[pos:pos+8])
- # print " rv=%04xh cv=%04xh" % (row1val, col1val)
- # print " rv=%04xh cv=%04xh" % (row2val, col2val)
- res1 = adjust_cell_addr_biff8(row1val, col1val, reldelta, browx, bcolx)
- res2 = adjust_cell_addr_biff8(row2val, col2val, reldelta, browx, bcolx)
- return res1, res2
- else:
- row1val, row2val, col1val, col2val = unpack("<HHBB", data[pos:pos+6])
- # print " rv=%04xh cv=%04xh" % (row1val, col1val)
- # print " rv=%04xh cv=%04xh" % (row2val, col2val)
- res1 = adjust_cell_addr_biff_le7(
- row1val, col1val, reldelta, browx, bcolx)
- res2 = adjust_cell_addr_biff_le7(
- row2val, col2val, reldelta, browx, bcolx)
- return res1, res2
-
-def get_externsheet_local_range(bk, refx, verbose=0):
- try:
- info = bk._externsheet_info[refx]
- except IndexError:
- print("!!! get_externsheet_local_range: refx=%d, not in range(%d)" \
- % (refx, len(bk._externsheet_info)))
- return (-101, -101)
- ref_recordx, ref_first_sheetx, ref_last_sheetx = info
- if ref_recordx == bk._supbook_addins_inx:
- if verbose:
- print("/// get_externsheet_local_range(refx=%d) -> addins %r" % (refx, info))
- assert ref_first_sheetx == 0xFFFE == ref_last_sheetx
- return (-5, -5)
- if ref_recordx != bk._supbook_locals_inx:
- if verbose:
- print("/// get_externsheet_local_range(refx=%d) -> external %r" % (refx, info))
- return (-4, -4) # external reference
- if ref_first_sheetx == 0xFFFE == ref_last_sheetx:
- if verbose:
- print("/// get_externsheet_local_range(refx=%d) -> unspecified sheet %r" % (refx, info))
- return (-1, -1) # internal reference, any sheet
- if ref_first_sheetx == 0xFFFF == ref_last_sheetx:
- if verbose:
- print("/// get_externsheet_local_range(refx=%d) -> deleted sheet(s)" % (refx, ))
- return (-2, -2) # internal reference, deleted sheet(s)
- nsheets = len(bk._all_sheets_map)
- if not(0 <= ref_first_sheetx <= ref_last_sheetx < nsheets):
- if verbose:
- print("/// get_externsheet_local_range(refx=%d) -> %r" % (refx, info))
- print("--- first/last sheet not in range(%d)" % nsheets)
- return (-102, -102) # stuffed up somewhere :-(
- xlrd_sheetx1 = bk._all_sheets_map[ref_first_sheetx]
- xlrd_sheetx2 = bk._all_sheets_map[ref_last_sheetx]
- if not(0 <= xlrd_sheetx1 <= xlrd_sheetx2):
- return (-3, -3) # internal reference, but to a macro sheet
- return xlrd_sheetx1, xlrd_sheetx2
-
-def get_externsheet_local_range_b57(
- bk, raw_extshtx, ref_first_sheetx, ref_last_sheetx, verbose=0):
- if raw_extshtx > 0:
- if verbose:
- print("/// get_externsheet_local_range_b57(raw_extshtx=%d) -> external" % raw_extshtx)
- return (-4, -4) # external reference
- if ref_first_sheetx == -1 and ref_last_sheetx == -1:
- return (-2, -2) # internal reference, deleted sheet(s)
- nsheets = len(bk._all_sheets_map)
- if not(0 <= ref_first_sheetx <= ref_last_sheetx < nsheets):
- if verbose:
- print("/// get_externsheet_local_range_b57(%d, %d, %d) -> ???" \
- % (raw_extshtx, ref_first_sheetx, ref_last_sheetx))
- print("--- first/last sheet not in range(%d)" % nsheets)
- return (-103, -103) # stuffed up somewhere :-(
- xlrd_sheetx1 = bk._all_sheets_map[ref_first_sheetx]
- xlrd_sheetx2 = bk._all_sheets_map[ref_last_sheetx]
- if not(0 <= xlrd_sheetx1 <= xlrd_sheetx2):
- return (-3, -3) # internal reference, but to a macro sheet
- return xlrd_sheetx1, xlrd_sheetx2
-
-class FormulaError(Exception):
- pass
-
-oBOOL = 3
-oERR = 4
-oMSNG = 5 # tMissArg
-oNUM = 2
-oREF = -1
-oREL = -2
-oSTRG = 1
-oUNK = 0
-
-okind_dict = {
- -2: "oREL",
- -1: "oREF",
- 0 : "oUNK",
- 1 : "oSTRG",
- 2 : "oNUM",
- 3 : "oBOOL",
- 4 : "oERR",
- 5 : "oMSNG",
- }
-
-listsep = ',' #### probably should depend on locale
-
-##
-# Used in evaluating formulas.
-# The following table describes the kinds and how their values
-# are represented.</p>
-#
-# <table border="1" cellpadding="7">
-# <tr>
-# <th>Kind symbol</th>
-# <th>Kind number</th>
-# <th>Value representation</th>
-# </tr>
-# <tr>
-# <td>oBOOL</td>
-# <td align="center">3</td>
-# <td>integer: 0 => False; 1 => True</td>
-# </tr>
-# <tr>
-# <td>oERR</td>
-# <td align="center">4</td>
-# <td>None, or an int error code (same as XL_CELL_ERROR in the Cell class).
-# </td>
-# </tr>
-# <tr>
-# <td>oMSNG</td>
-# <td align="center">5</td>
-# <td>Used by Excel as a placeholder for a missing (not supplied) function
-# argument. Should *not* appear as a final formula result. Value is None.</td>
-# </tr>
-# <tr>
-# <td>oNUM</td>
-# <td align="center">2</td>
-# <td>A float. Note that there is no way of distinguishing dates.</td>
-# </tr>
-# <tr>
-# <td>oREF</td>
-# <td align="center">-1</td>
-# <td>The value is either None or a non-empty list of
-# absolute Ref3D instances.<br>
-# </td>
-# </tr>
-# <tr>
-# <td>oREL</td>
-# <td align="center">-2</td>
-# <td>The value is None or a non-empty list of
-# fully or partially relative Ref3D instances.
-# </td>
-# </tr>
-# <tr>
-# <td>oSTRG</td>
-# <td align="center">1</td>
-# <td>A Unicode string.</td>
-# </tr>
-# <tr>
-# <td>oUNK</td>
-# <td align="center">0</td>
-# <td>The kind is unknown or ambiguous. The value is None</td>
-# </tr>
-# </table>
-#<p></p>
-
-class Operand(object):
-
- ##
- # None means that the actual value of the operand is a variable
- # (depends on cell data), not a constant.
- value = None
- ##
- # oUNK means that the kind of operand is not known unambiguously.
- kind = oUNK
- ##
- # The reconstituted text of the original formula. Function names will be
- # in English irrespective of the original language, which doesn't seem
- # to be recorded anywhere. The separator is ",", not ";" or whatever else
- # might be more appropriate for the end-user's locale; patches welcome.
- text = '?'
-
- def __init__(self, akind=None, avalue=None, arank=0, atext='?'):
- if akind is not None:
- self.kind = akind
- if avalue is not None:
- self.value = avalue
- self.rank = arank
- # rank is an internal gizmo (operator precedence);
- # it's used in reconstructing formula text.
- self.text = atext
-
- def __repr__(self):
- kind_text = okind_dict.get(self.kind, "?Unknown kind?")
- return "Operand(kind=%s, value=%r, text=%r)" \
- % (kind_text, self.value, self.text)
-
-#(to_py3) if CAN_SUBCLASS_BUILTIN:
-# _ref3d_base = tuple
-
-# Represents an absolute or relative 3-dimensional reference to a box
-# of one or more cells.
-# - New in version 0.6.0
-#
-# The `coords` attribute is a tuple of the form:
-# (shtxlo, shtxhi, rowxlo, rowxhi, colxlo, colxhi)
-# where 0 <= thingxlo <= thingx < thingxhi.
-# Note that it is quite possible to have thingx > nthings; for example
-# Print_Titles could have colxhi == 256 and/or rowxhi == 65536
-# irrespective of how many columns/rows are actually used in the worksheet.
-# The caller will need to decide how to handle this situation.
-# Keyword: IndexError :-)
-#
-# The components of the coords attribute are also available as individual
-# attributes: shtxlo, shtxhi, rowxlo, rowxhi, colxlo, and colxhi.
-#
-# The `relflags` attribute is a 6-tuple of flags which indicate whether
-# the corresponding (sheet|row|col)(lo|hi) is relative (1) or absolute (0).
-# Note that there is necessarily no information available as to what cell(s)
-# the reference could possibly be relative to. The caller must decide what if
-# any use to make of oREL operands. Note also that a partially relative
-# reference may well be a typo.
-# For example, define name A1Z10 as $a$1:$z10 (missing $ after z)
-# while the cursor is on cell Sheet3!A27.<br>
-# The resulting Ref3D instance will have coords = (2, 3, 0, -16, 0, 26)
-# and relflags = (0, 0, 0, 1, 0, 0).<br>
-# So far, only one possibility of a sheet-relative component in
-# a reference has been noticed: a 2D reference located in the "current sheet".
-# This will appear as coords = (0, 1, ...) and relflags = (1, 1, ...).
-
-class Ref3D(tuple):
-
- def __init__(self, atuple):
- self.coords = atuple[0:6]
- self.relflags = atuple[6:12]
- if not self.relflags:
- self.relflags = (0, 0, 0, 0, 0, 0)
- (self.shtxlo, self.shtxhi,
- self.rowxlo, self.rowxhi,
- self.colxlo, self.colxhi) = self.coords
-
- def __repr__(self):
- if not self.relflags or self.relflags == (0, 0, 0, 0, 0, 0):
- return "Ref3D(coords=%r)" % (self.coords, )
- else:
- return "Ref3D(coords=%r, relflags=%r)" \
- % (self.coords, self.relflags)
-
-tAdd = 0x03
-tSub = 0x04
-tMul = 0x05
-tDiv = 0x06
-tPower = 0x07
-tConcat = 0x08
-tLT, tLE, tEQ, tGE, tGT, tNE = list(range(0x09, 0x0F))
-
-import operator as opr
-
-def nop(x):
- return x
-
-def _opr_pow(x, y): return x ** y
-
-def _opr_lt(x, y): return x < y
-def _opr_le(x, y): return x <= y
-def _opr_eq(x, y): return x == y
-def _opr_ge(x, y): return x >= y
-def _opr_gt(x, y): return x > y
-def _opr_ne(x, y): return x != y
-
-def num2strg(num):
- """Attempt to emulate Excel's default conversion
- from number to string.
- """
- s = str(num)
- if s.endswith(".0"):
- s = s[:-2]
- return s
-
-_arith_argdict = {oNUM: nop, oSTRG: float}
-_cmp_argdict = {oNUM: nop, oSTRG: nop}
-# Seems no conversions done on relops; in Excel, "1" > 9 produces TRUE.
-_strg_argdict = {oNUM:num2strg, oSTRG:nop}
-binop_rules = {
- tAdd: (_arith_argdict, oNUM, opr.add, 30, '+'),
- tSub: (_arith_argdict, oNUM, opr.sub, 30, '-'),
- tMul: (_arith_argdict, oNUM, opr.mul, 40, '*'),
- tDiv: (_arith_argdict, oNUM, opr.truediv, 40, '/'),
- tPower: (_arith_argdict, oNUM, _opr_pow, 50, '^',),
- tConcat:(_strg_argdict, oSTRG, opr.add, 20, '&'),
- tLT: (_cmp_argdict, oBOOL, _opr_lt, 10, '<'),
- tLE: (_cmp_argdict, oBOOL, _opr_le, 10, '<='),
- tEQ: (_cmp_argdict, oBOOL, _opr_eq, 10, '='),
- tGE: (_cmp_argdict, oBOOL, _opr_ge, 10, '>='),
- tGT: (_cmp_argdict, oBOOL, _opr_gt, 10, '>'),
- tNE: (_cmp_argdict, oBOOL, _opr_ne, 10, '<>'),
- }
-
-unop_rules = {
- 0x13: (lambda x: -x, 70, '-', ''), # unary minus
- 0x12: (lambda x: x, 70, '+', ''), # unary plus
- 0x14: (lambda x: x / 100.0, 60, '', '%'),# percent
- }
-
-LEAF_RANK = 90
-FUNC_RANK = 90
-
-STACK_ALARM_LEVEL = 5
-STACK_PANIC_LEVEL = 10
-
-def evaluate_name_formula(bk, nobj, namex, verbose=0, level=0):
- if level > STACK_ALARM_LEVEL:
- verbose = 1
- data = nobj.raw_formula
- fmlalen = nobj.basic_formula_len
- bv = bk.biff_version
- reldelta = 1 # All defined name formulas use "Method B" [OOo docs]
- if verbose:
- print("::: evaluate_name_formula %r %r %d %d %r level=%d" \
- % (namex, nobj.name, fmlalen, bv, data, level))
- hex_char_dump(data, 0, fmlalen)
- if level > STACK_PANIC_LEVEL:
- raise XLRDError("Excessive indirect references in NAME formula")
- sztab = szdict[bv]
- pos = 0
- stack = []
- any_rel = 0
- any_err = 0
- any_external = 0
- unk_opnd = Operand(oUNK, None)
- error_opnd = Operand(oERR, None)
- spush = stack.append
-
- def do_binop(opcd, stk):
- assert len(stk) >= 2
- bop = stk.pop()
- aop = stk.pop()
- argdict, result_kind, func, rank, sym = binop_rules[opcd]
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- resop = Operand(result_kind, None, rank, otext)
- try:
- bconv = argdict[bop.kind]
- aconv = argdict[aop.kind]
- except KeyError:
- stk.append(resop)
- return
- if bop.value is None or aop.value is None:
- stk.append(resop)
- return
- bval = bconv(bop.value)
- aval = aconv(aop.value)
- result = func(aval, bval)
- if result_kind == oBOOL:
- result = 1 if result else 0 # (to_py3)
- resop.value = result
- stk.append(resop)
-
- def do_unaryop(opcode, arglist, result_kind, stk):
- assert len(stk) >= 1
- aop = stk.pop()
- assert aop.kind in arglist
- val = aop.value
- func, rank, sym1, sym2 = unop_rules[opcode]
- otext = ''.join([
- sym1,
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym2,
- ])
- if val is not None:
- val = func(val)
- stk.append(Operand(result_kind, val, rank, otext))
-
- def not_in_name_formula(op_arg, oname_arg):
- msg = "ERROR *** Token 0x%02x (%s) found in NAME formula" \
- % (op_arg, oname_arg)
- raise FormulaError(msg)
-
- if fmlalen == 0:
- stack = [unk_opnd]
-
- while 0 <= pos < fmlalen:
- op = data[pos]
- opcode = op & 0x1f
- optype = (op & 0x60) >> 5
- if optype:
- opx = opcode + 32
- else:
- opx = opcode
- oname = onames[opx] # + [" RVA"][optype]
- sz = sztab[opx]
- if verbose:
- print("Pos:%d Op:0x%02x Name:t%s Sz:%d opcode:%02xh optype:%02xh" \
- % (pos, op, oname, sz, opcode, optype))
- print("Stack =", stack)
- if sz == -2:
- msg = 'ERROR *** Unexpected token 0x%02x ("%s"); biff_version=%d' \
- % (op, oname, bv)
- raise FormulaError(msg)
- if not optype:
- if 0x00 <= opcode <= 0x02: # unk_opnd, tExp, tTbl
- not_in_name_formula(op, oname)
- elif 0x03 <= opcode <= 0x0E:
- # Add, Sub, Mul, Div, Power
- # tConcat
- # tLT, ..., tNE
- do_binop(opcode, stack)
- elif opcode == 0x0F: # tIsect
- if verbose: print("tIsect pre", stack, file=bk.logfile)
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- sym = ' '
- rank = 80 ########## check #######
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- res = Operand(oREF)
- res.text = otext
- if bop.kind == oERR or aop.kind == oERR:
- res.kind = oERR
- elif bop.kind == oUNK or aop.kind == oUNK:
- # This can happen with undefined
- # (go search in the current sheet) labels.
- # For example =Bob Sales
- # Each label gets a NAME record with an empty formula (!)
- # Evaluation of the tName token classifies it as oUNK
- # res.kind = oREF
- pass
- elif bop.kind == oREF == aop.kind:
- if aop.value is not None and bop.value is not None:
- assert len(aop.value) == 1
- assert len(bop.value) == 1
- coords = do_box_funcs(
- tIsectFuncs, aop.value[0], bop.value[0])
- res.value = [Ref3D(coords)]
- elif bop.kind == oREL == aop.kind:
- res.kind = oREL
- if aop.value is not None and bop.value is not None:
- assert len(aop.value) == 1
- assert len(bop.value) == 1
- coords = do_box_funcs(
- tIsectFuncs, aop.value[0], bop.value[0])
- relfa = aop.value[0].relflags
- relfb = bop.value[0].relflags
- if relfa == relfb:
- res.value = [Ref3D(coords + relfa)]
- else:
- pass
- spush(res)
- if verbose: print("tIsect post", stack, file=bk.logfile)
- elif opcode == 0x10: # tList
- if verbose: print("tList pre", stack, file=bk.logfile)
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- sym = ','
- rank = 80 ########## check #######
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- res = Operand(oREF, None, rank, otext)
- if bop.kind == oERR or aop.kind == oERR:
- res.kind = oERR
- elif bop.kind in (oREF, oREL) and aop.kind in (oREF, oREL):
- res.kind = oREF
- if aop.kind == oREL or bop.kind == oREL:
- res.kind = oREL
- if aop.value is not None and bop.value is not None:
- assert len(aop.value) >= 1
- assert len(bop.value) == 1
- res.value = aop.value + bop.value
- else:
- pass
- spush(res)
- if verbose: print("tList post", stack, file=bk.logfile)
- elif opcode == 0x11: # tRange
- if verbose: print("tRange pre", stack, file=bk.logfile)
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- sym = ':'
- rank = 80 ########## check #######
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- res = Operand(oREF, None, rank, otext)
- if bop.kind == oERR or aop.kind == oERR:
- res = oERR
- elif bop.kind == oREF == aop.kind:
- if aop.value is not None and bop.value is not None:
- assert len(aop.value) == 1
- assert len(bop.value) == 1
- coords = do_box_funcs(
- tRangeFuncs, aop.value[0], bop.value[0])
- res.value = [Ref3D(coords)]
- elif bop.kind == oREL == aop.kind:
- res.kind = oREL
- if aop.value is not None and bop.value is not None:
- assert len(aop.value) == 1
- assert len(bop.value) == 1
- coords = do_box_funcs(
- tRangeFuncs, aop.value[0], bop.value[0])
- relfa = aop.value[0].relflags
- relfb = bop.value[0].relflags
- if relfa == relfb:
- res.value = [Ref3D(coords + relfa)]
- else:
- pass
- spush(res)
- if verbose: print("tRange post", stack, file=bk.logfile)
- elif 0x12 <= opcode <= 0x14: # tUplus, tUminus, tPercent
- do_unaryop(opcode, (oUNK, oNUM,), oNUM, stack)
- elif opcode == 0x15: # tParen
- # source cosmetics
- pass
- elif opcode == 0x16: # tMissArg
- spush(Operand(oMSNG, None, LEAF_RANK, ''))
- elif opcode == 0x17: # tStr
- if bv <= 70:
- strg, newpos = unpack_string_update_pos(
- data, pos+1, bk.encoding, lenlen=1)
- else:
- strg, newpos = unpack_unicode_update_pos(
- data, pos+1, lenlen=1)
- sz = newpos - pos
- if verbose: print(" sz=%d strg=%r" % (sz, strg), file=bk.logfile)
- text = '"' + strg.replace('"', '""') + '"'
- spush(Operand(oSTRG, strg, LEAF_RANK, text))
- elif opcode == 0x18: # tExtended
- # new with BIFF 8
- assert bv >= 80
- # not in OOo docs
- raise FormulaError("tExtended token not implemented")
- elif opcode == 0x19: # tAttr
- subop, nc = unpack("<BH", data[pos+1:pos+4])
- subname = tAttrNames.get(subop, "??Unknown??")
- if subop == 0x04: # Choose
- sz = nc * 2 + 6
- elif subop == 0x10: # Sum (single arg)
- sz = 4
- if verbose: print("tAttrSum", stack, file=bk.logfile)
- assert len(stack) >= 1
- aop = stack[-1]
- otext = 'SUM(%s)' % aop.text
- stack[-1] = Operand(oNUM, None, FUNC_RANK, otext)
- else:
- sz = 4
- if verbose:
- print(" subop=%02xh subname=t%s sz=%d nc=%02xh" \
- % (subop, subname, sz, nc))
- elif 0x1A <= opcode <= 0x1B: # tSheet, tEndSheet
- assert bv < 50
- raise FormulaError("tSheet & tEndsheet tokens not implemented")
- elif 0x1C <= opcode <= 0x1F: # tErr, tBool, tInt, tNum
- inx = opcode - 0x1C
- nb = [1, 1, 2, 8][inx]
- kind = [oERR, oBOOL, oNUM, oNUM][inx]
- value, = unpack("<" + "BBHd"[inx], data[pos+1:pos+1+nb])
- if inx == 2: # tInt
- value = float(value)
- text = str(value)
- elif inx == 3: # tNum
- text = str(value)
- elif inx == 1: # tBool
- text = ('FALSE', 'TRUE')[value]
- else:
- text = '"' +error_text_from_code[value] + '"'
- spush(Operand(kind, value, LEAF_RANK, text))
- else:
- raise FormulaError("Unhandled opcode: 0x%02x" % opcode)
- if sz <= 0:
- raise FormulaError("Size not set for opcode 0x%02x" % opcode)
- pos += sz
- continue
- if opcode == 0x00: # tArray
- spush(unk_opnd)
- elif opcode == 0x01: # tFunc
- nb = 1 + int(bv >= 40)
- funcx = unpack("<" + " BH"[nb], data[pos+1:pos+1+nb])[0]
- func_attrs = func_defs.get(funcx, None)
- if not func_attrs:
- print("*** formula/tFunc unknown FuncID:%d" \
- % funcx, file=bk.logfile)
- spush(unk_opnd)
- else:
- func_name, nargs = func_attrs[:2]
- if verbose:
- print(" FuncID=%d name=%s nargs=%d" \
- % (funcx, func_name, nargs))
- assert len(stack) >= nargs
- argtext = listsep.join([arg.text for arg in stack[-nargs:]])
- otext = "%s(%s)" % (func_name, argtext)
- del stack[-nargs:]
- res = Operand(oUNK, None, FUNC_RANK, otext)
- spush(res)
- elif opcode == 0x02: #tFuncVar
- nb = 1 + int(bv >= 40)
- nargs, funcx = unpack("<B" + " BH"[nb], data[pos+1:pos+2+nb])
- prompt, nargs = divmod(nargs, 128)
- macro, funcx = divmod(funcx, 32768)
- if verbose:
- print(" FuncID=%d nargs=%d macro=%d prompt=%d" \
- % (funcx, nargs, macro, prompt))
- func_attrs = func_defs.get(funcx, None)
- if not func_attrs:
- print("*** formula/tFuncVar unknown FuncID:%d" \
- % funcx, file=bk.logfile)
- spush(unk_opnd)
- else:
- func_name, minargs, maxargs = func_attrs[:3]
- if verbose:
- print(" name: %r, min~max args: %d~%d" \
- % (func_name, minargs, maxargs))
- assert minargs <= nargs <= maxargs
- assert len(stack) >= nargs
- assert len(stack) >= nargs
- argtext = listsep.join([arg.text for arg in stack[-nargs:]])
- otext = "%s(%s)" % (func_name, argtext)
- res = Operand(oUNK, None, FUNC_RANK, otext)
- if funcx == 1: # IF
- testarg = stack[-nargs]
- if testarg.kind not in (oNUM, oBOOL):
- if verbose and testarg.kind != oUNK:
- print("IF testarg kind?")
- elif testarg.value not in (0, 1):
- if verbose and testarg.value is not None:
- print("IF testarg value?")
- else:
- if nargs == 2 and not testarg.value:
- # IF(FALSE, tv) => FALSE
- res.kind, res.value = oBOOL, 0
- else:
- respos = -nargs + 2 - int(testarg.value)
- chosen = stack[respos]
- if chosen.kind == oMSNG:
- res.kind, res.value = oNUM, 0
- else:
- res.kind, res.value = chosen.kind, chosen.value
- if verbose:
- print("$$$$$$ IF => constant")
- elif funcx == 100: # CHOOSE
- testarg = stack[-nargs]
- if testarg.kind == oNUM:
- if 1 <= testarg.value < nargs:
- chosen = stack[-nargs + int(testarg.value)]
- if chosen.kind == oMSNG:
- res.kind, res.value = oNUM, 0
- else:
- res.kind, res.value = chosen.kind, chosen.value
- del stack[-nargs:]
- spush(res)
- elif opcode == 0x03: #tName
- tgtnamex = unpack("<H", data[pos+1:pos+3])[0] - 1
- # Only change with BIFF version is number of trailing UNUSED bytes!
- if verbose: print(" tgtnamex=%d" % tgtnamex, file=bk.logfile)
- tgtobj = bk.name_obj_list[tgtnamex]
- if not tgtobj.evaluated:
- ### recursive ###
- evaluate_name_formula(bk, tgtobj, tgtnamex, verbose, level+1)
- if tgtobj.macro or tgtobj.binary \
- or tgtobj.any_err:
- if verbose:
- tgtobj.dump(
- bk.logfile,
- header="!!! tgtobj has problems!!!",
- footer="----------- --------",
- )
- res = Operand(oUNK, None)
- any_err = any_err or tgtobj.macro or tgtobj.binary or tgtobj.any_err
- any_rel = any_rel or tgtobj.any_rel
- else:
- assert len(tgtobj.stack) == 1
- res = copy.deepcopy(tgtobj.stack[0])
- res.rank = LEAF_RANK
- if tgtobj.scope == -1:
- res.text = tgtobj.name
- else:
- res.text = "%s!%s" \
- % (bk._sheet_names[tgtobj.scope], tgtobj.name)
- if verbose:
- print(" tName: setting text to", repr(res.text), file=bk.logfile)
- spush(res)
- elif opcode == 0x04: # tRef
- # not_in_name_formula(op, oname)
- res = get_cell_addr(data, pos+1, bv, reldelta)
- if verbose: print(" ", res, file=bk.logfile)
- rowx, colx, row_rel, col_rel = res
- shx1 = shx2 = 0 ####### N.B. relative to the CURRENT SHEET
- any_rel = 1
- coords = (shx1, shx2+1, rowx, rowx+1, colx, colx+1)
- if verbose: print(" ", coords, file=bk.logfile)
- res = Operand(oUNK, None)
- if optype == 1:
- relflags = (1, 1, row_rel, row_rel, col_rel, col_rel)
- res = Operand(oREL, [Ref3D(coords + relflags)])
- spush(res)
- elif opcode == 0x05: # tArea
- # not_in_name_formula(op, oname)
- res1, res2 = get_cell_range_addr(data, pos+1, bv, reldelta)
- if verbose: print(" ", res1, res2, file=bk.logfile)
- rowx1, colx1, row_rel1, col_rel1 = res1
- rowx2, colx2, row_rel2, col_rel2 = res2
- shx1 = shx2 = 0 ####### N.B. relative to the CURRENT SHEET
- any_rel = 1
- coords = (shx1, shx2+1, rowx1, rowx2+1, colx1, colx2+1)
- if verbose: print(" ", coords, file=bk.logfile)
- res = Operand(oUNK, None)
- if optype == 1:
- relflags = (1, 1, row_rel1, row_rel2, col_rel1, col_rel2)
- res = Operand(oREL, [Ref3D(coords + relflags)])
- spush(res)
- elif opcode == 0x06: # tMemArea
- not_in_name_formula(op, oname)
- elif opcode == 0x09: # tMemFunc
- nb = unpack("<H", data[pos+1:pos+3])[0]
- if verbose: print(" %d bytes of cell ref formula" % nb, file=bk.logfile)
- # no effect on stack
- elif opcode == 0x0C: #tRefN
- not_in_name_formula(op, oname)
- # res = get_cell_addr(data, pos+1, bv, reldelta=1)
- # # note *ALL* tRefN usage has signed offset for relative addresses
- # any_rel = 1
- # if verbose: print >> bk.logfile, " ", res
- # spush(res)
- elif opcode == 0x0D: #tAreaN
- not_in_name_formula(op, oname)
- # res = get_cell_range_addr(data, pos+1, bv, reldelta=1)
- # # note *ALL* tAreaN usage has signed offset for relative addresses
- # any_rel = 1
- # if verbose: print >> bk.logfile, " ", res
- elif opcode == 0x1A: # tRef3d
- if bv >= 80:
- res = get_cell_addr(data, pos+3, bv, reldelta)
- refx = unpack("<H", data[pos+1:pos+3])[0]
- shx1, shx2 = get_externsheet_local_range(bk, refx, verbose)
- else:
- res = get_cell_addr(data, pos+15, bv, reldelta)
- raw_extshtx, raw_shx1, raw_shx2 = \
- unpack("<hxxxxxxxxhh", data[pos+1:pos+15])
- if verbose:
- print("tRef3d", raw_extshtx, raw_shx1, raw_shx2, file=bk.logfile)
- shx1, shx2 = get_externsheet_local_range_b57(
- bk, raw_extshtx, raw_shx1, raw_shx2, verbose)
- rowx, colx, row_rel, col_rel = res
- is_rel = row_rel or col_rel
- any_rel = any_rel or is_rel
- coords = (shx1, shx2+1, rowx, rowx+1, colx, colx+1)
- any_err |= shx1 < -1
- if verbose: print(" ", coords, file=bk.logfile)
- res = Operand(oUNK, None)
- if is_rel:
- relflags = (0, 0, row_rel, row_rel, col_rel, col_rel)
- ref3d = Ref3D(coords + relflags)
- res.kind = oREL
- res.text = rangename3drel(bk, ref3d)
- else:
- ref3d = Ref3D(coords)
- res.kind = oREF
- res.text = rangename3d(bk, ref3d)
- res.rank = LEAF_RANK
- if optype == 1:
- res.value = [ref3d]
- spush(res)
- elif opcode == 0x1B: # tArea3d
- if bv >= 80:
- res1, res2 = get_cell_range_addr(data, pos+3, bv, reldelta)
- refx = unpack("<H", data[pos+1:pos+3])[0]
- shx1, shx2 = get_externsheet_local_range(bk, refx, verbose)
- else:
- res1, res2 = get_cell_range_addr(data, pos+15, bv, reldelta)
- raw_extshtx, raw_shx1, raw_shx2 = \
- unpack("<hxxxxxxxxhh", data[pos+1:pos+15])
- if verbose:
- print("tArea3d", raw_extshtx, raw_shx1, raw_shx2, file=bk.logfile)
- shx1, shx2 = get_externsheet_local_range_b57(
- bk, raw_extshtx, raw_shx1, raw_shx2, verbose)
- any_err |= shx1 < -1
- rowx1, colx1, row_rel1, col_rel1 = res1
- rowx2, colx2, row_rel2, col_rel2 = res2
- is_rel = row_rel1 or col_rel1 or row_rel2 or col_rel2
- any_rel = any_rel or is_rel
- coords = (shx1, shx2+1, rowx1, rowx2+1, colx1, colx2+1)
- if verbose: print(" ", coords, file=bk.logfile)
- res = Operand(oUNK, None)
- if is_rel:
- relflags = (0, 0, row_rel1, row_rel2, col_rel1, col_rel2)
- ref3d = Ref3D(coords + relflags)
- res.kind = oREL
- res.text = rangename3drel(bk, ref3d)
- else:
- ref3d = Ref3D(coords)
- res.kind = oREF
- res.text = rangename3d(bk, ref3d)
- res.rank = LEAF_RANK
- if optype == 1:
- res.value = [ref3d]
-
- spush(res)
- elif opcode == 0x19: # tNameX
- dodgy = 0
- res = Operand(oUNK, None)
- if bv >= 80:
- refx, tgtnamex = unpack("<HH", data[pos+1:pos+5])
- tgtnamex -= 1
- origrefx = refx
- else:
- refx, tgtnamex = unpack("<hxxxxxxxxH", data[pos+1:pos+13])
- tgtnamex -= 1
- origrefx = refx
- if refx > 0:
- refx -= 1
- elif refx < 0:
- refx = -refx - 1
- else:
- dodgy = 1
- if verbose:
- print(" origrefx=%d refx=%d tgtnamex=%d dodgy=%d" \
- % (origrefx, refx, tgtnamex, dodgy), file=bk.logfile)
- if tgtnamex == namex:
- if verbose: print("!!!! Self-referential !!!!", file=bk.logfile)
- dodgy = any_err = 1
- if not dodgy:
- if bv >= 80:
- shx1, shx2 = get_externsheet_local_range(bk, refx, verbose)
- elif origrefx > 0:
- shx1, shx2 = (-4, -4) # external ref
- else:
- exty = bk._externsheet_type_b57[refx]
- if exty == 4: # non-specific sheet in own doc't
- shx1, shx2 = (-1, -1) # internal, any sheet
- else:
- shx1, shx2 = (-666, -666)
- if dodgy or shx1 < -1:
- otext = "<<Name #%d in external(?) file #%d>>" \
- % (tgtnamex, origrefx)
- res = Operand(oUNK, None, LEAF_RANK, otext)
- else:
- tgtobj = bk.name_obj_list[tgtnamex]
- if not tgtobj.evaluated:
- ### recursive ###
- evaluate_name_formula(bk, tgtobj, tgtnamex, verbose, level+1)
- if tgtobj.macro or tgtobj.binary \
- or tgtobj.any_err:
- if verbose:
- tgtobj.dump(
- bk.logfile,
- header="!!! bad tgtobj !!!",
- footer="------------------",
- )
- res = Operand(oUNK, None)
- any_err = any_err or tgtobj.macro or tgtobj.binary or tgtobj.any_err
- any_rel = any_rel or tgtobj.any_rel
- else:
- assert len(tgtobj.stack) == 1
- res = copy.deepcopy(tgtobj.stack[0])
- res.rank = LEAF_RANK
- if tgtobj.scope == -1:
- res.text = tgtobj.name
- else:
- res.text = "%s!%s" \
- % (bk._sheet_names[tgtobj.scope], tgtobj.name)
- if verbose:
- print(" tNameX: setting text to", repr(res.text), file=bk.logfile)
- spush(res)
- elif opcode in _error_opcodes:
- any_err = 1
- spush(error_opnd)
- else:
- if verbose:
- print("FORMULA: /// Not handled yet: t" + oname, file=bk.logfile)
- any_err = 1
- if sz <= 0:
- raise FormulaError("Fatal: token size is not positive")
- pos += sz
- any_rel = not not any_rel
- if verbose:
- print("End of formula. level=%d any_rel=%d any_err=%d stack=%r" % \
- (level, not not any_rel, any_err, stack))
- if len(stack) >= 2:
- print("*** Stack has unprocessed args")
- print()
- nobj.stack = stack
- if len(stack) != 1:
- nobj.result = None
- else:
- nobj.result = stack[0]
- nobj.any_rel = any_rel
- nobj.any_err = any_err
- nobj.any_external = any_external
- nobj.evaluated = 1
-
-#### under construction ####
-def decompile_formula(bk, fmla, fmlalen,
- reldelta, browx=None, bcolx=None,
- # browx & bcolx are required when reldelta == 0
- verbose=0, level=0):
- if level > STACK_ALARM_LEVEL:
- verbose = 1
- data = fmla
- bv = bk.biff_version
- if verbose:
- print("::: decompile_formula len=%d reldelta=%d %r level=%d" \
- % (fmlalen, reldelta, data, level))
- hex_char_dump(data, 0, fmlalen)
- if level > STACK_PANIC_LEVEL:
- raise XLRDError("Excessive indirect references in formula")
- sztab = szdict[bv]
- pos = 0
- stack = []
- any_rel = 0
- any_err = 0
- any_external = 0
- unk_opnd = Operand(oUNK, None)
- error_opnd = Operand(oERR, None)
- spush = stack.append
-
- def do_binop(opcd, stk):
- assert len(stk) >= 2
- bop = stk.pop()
- aop = stk.pop()
- argdict, result_kind, func, rank, sym = binop_rules[opcd]
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- resop = Operand(result_kind, None, rank, otext)
- stk.append(resop)
-
- def do_unaryop(opcode, arglist, result_kind, stk):
- assert len(stk) >= 1
- aop = stk.pop()
- assert aop.kind in arglist
- func, rank, sym1, sym2 = unop_rules[opcode]
- otext = ''.join([
- sym1,
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym2,
- ])
- stk.append(Operand(result_kind, None, rank, otext))
-
- def not_in_name_formula(op_arg, oname_arg):
- msg = "ERROR *** Unexpected token 0x%02x (%s) found in formula" \
- % (op_arg, oname_arg)
- # print msg
- raise FormulaError(msg)
-
- if fmlalen == 0:
- stack = [unk_opnd]
-
- while 0 <= pos < fmlalen:
- op = data[pos]
- opcode = op & 0x1f
- optype = (op & 0x60) >> 5
- if optype:
- opx = opcode + 32
- else:
- opx = opcode
- oname = onames[opx] # + [" RVA"][optype]
- sz = sztab[opx]
- if verbose:
- print("Pos:%d Op:0x%02x opname:t%s Sz:%d opcode:%02xh optype:%02xh" \
- % (pos, op, oname, sz, opcode, optype))
- print("Stack =", stack)
- if sz == -2:
- msg = 'ERROR *** Unexpected token 0x%02x ("%s"); biff_version=%d' \
- % (op, oname, bv)
- raise FormulaError(msg)
- if not optype:
- if 0x00 <= opcode <= 0x02: # unk_opnd, tExp, tTbl
- not_in_name_formula(op, oname)
- elif 0x03 <= opcode <= 0x0E:
- # Add, Sub, Mul, Div, Power
- # tConcat
- # tLT, ..., tNE
- do_binop(opcode, stack)
- elif opcode == 0x0F: # tIsect
- if verbose: print("tIsect pre", stack, file=bk.logfile)
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- sym = ' '
- rank = 80 ########## check #######
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- res = Operand(oREF)
- res.text = otext
- if bop.kind == oERR or aop.kind == oERR:
- res.kind = oERR
- elif bop.kind == oUNK or aop.kind == oUNK:
- # This can happen with undefined
- # (go search in the current sheet) labels.
- # For example =Bob Sales
- # Each label gets a NAME record with an empty formula (!)
- # Evaluation of the tName token classifies it as oUNK
- # res.kind = oREF
- pass
- elif bop.kind == oREF == aop.kind:
- pass
- elif bop.kind == oREL == aop.kind:
- res.kind = oREL
- else:
- pass
- spush(res)
- if verbose: print("tIsect post", stack, file=bk.logfile)
- elif opcode == 0x10: # tList
- if verbose: print("tList pre", stack, file=bk.logfile)
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- sym = ','
- rank = 80 ########## check #######
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- res = Operand(oREF, None, rank, otext)
- if bop.kind == oERR or aop.kind == oERR:
- res.kind = oERR
- elif bop.kind in (oREF, oREL) and aop.kind in (oREF, oREL):
- res.kind = oREF
- if aop.kind == oREL or bop.kind == oREL:
- res.kind = oREL
- else:
- pass
- spush(res)
- if verbose: print("tList post", stack, file=bk.logfile)
- elif opcode == 0x11: # tRange
- if verbose: print("tRange pre", stack, file=bk.logfile)
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- sym = ':'
- rank = 80 ########## check #######
- otext = ''.join([
- '('[:aop.rank < rank],
- aop.text,
- ')'[:aop.rank < rank],
- sym,
- '('[:bop.rank < rank],
- bop.text,
- ')'[:bop.rank < rank],
- ])
- res = Operand(oREF, None, rank, otext)
- if bop.kind == oERR or aop.kind == oERR:
- res = oERR
- elif bop.kind == oREF == aop.kind:
- pass
- else:
- pass
- spush(res)
- if verbose: print("tRange post", stack, file=bk.logfile)
- elif 0x12 <= opcode <= 0x14: # tUplus, tUminus, tPercent
- do_unaryop(opcode, (oUNK, oNUM,), oNUM, stack)
- elif opcode == 0x15: # tParen
- # source cosmetics
- pass
- elif opcode == 0x16: # tMissArg
- spush(Operand(oMSNG, None, LEAF_RANK, ''))
- elif opcode == 0x17: # tStr
- if bv <= 70:
- strg, newpos = unpack_string_update_pos(
- data, pos+1, bk.encoding, lenlen=1)
- else:
- strg, newpos = unpack_unicode_update_pos(
- data, pos+1, lenlen=1)
- sz = newpos - pos
- if verbose: print(" sz=%d strg=%r" % (sz, strg), file=bk.logfile)
- text = '"' + strg.replace('"', '""') + '"'
- spush(Operand(oSTRG, None, LEAF_RANK, text))
- elif opcode == 0x18: # tExtended
- # new with BIFF 8
- assert bv >= 80
- # not in OOo docs
- raise FormulaError("tExtended token not implemented")
- elif opcode == 0x19: # tAttr
- subop, nc = unpack("<BH", data[pos+1:pos+4])
- subname = tAttrNames.get(subop, "??Unknown??")
- if subop == 0x04: # Choose
- sz = nc * 2 + 6
- elif subop == 0x10: # Sum (single arg)
- sz = 4
- if verbose: print("tAttrSum", stack, file=bk.logfile)
- assert len(stack) >= 1
- aop = stack[-1]
- otext = 'SUM(%s)' % aop.text
- stack[-1] = Operand(oNUM, None, FUNC_RANK, otext)
- else:
- sz = 4
- if verbose:
- print(" subop=%02xh subname=t%s sz=%d nc=%02xh" \
- % (subop, subname, sz, nc))
- elif 0x1A <= opcode <= 0x1B: # tSheet, tEndSheet
- assert bv < 50
- raise FormulaError("tSheet & tEndsheet tokens not implemented")
- elif 0x1C <= opcode <= 0x1F: # tErr, tBool, tInt, tNum
- inx = opcode - 0x1C
- nb = [1, 1, 2, 8][inx]
- kind = [oERR, oBOOL, oNUM, oNUM][inx]
- value, = unpack("<" + "BBHd"[inx], data[pos+1:pos+1+nb])
- if inx == 2: # tInt
- value = float(value)
- text = str(value)
- elif inx == 3: # tNum
- text = str(value)
- elif inx == 1: # tBool
- text = ('FALSE', 'TRUE')[value]
- else:
- text = '"' +error_text_from_code[value] + '"'
- spush(Operand(kind, None, LEAF_RANK, text))
- else:
- raise FormulaError("Unhandled opcode: 0x%02x" % opcode)
- if sz <= 0:
- raise FormulaError("Size not set for opcode 0x%02x" % opcode)
- pos += sz
- continue
- if opcode == 0x00: # tArray
- spush(unk_opnd)
- elif opcode == 0x01: # tFunc
- nb = 1 + int(bv >= 40)
- funcx = unpack("<" + " BH"[nb], data[pos+1:pos+1+nb])[0]
- func_attrs = func_defs.get(funcx, None)
- if not func_attrs:
- print("*** formula/tFunc unknown FuncID:%d" % funcx, file=bk.logfile)
- spush(unk_opnd)
- else:
- func_name, nargs = func_attrs[:2]
- if verbose:
- print(" FuncID=%d name=%s nargs=%d" \
- % (funcx, func_name, nargs))
- assert len(stack) >= nargs
- argtext = listsep.join([arg.text for arg in stack[-nargs:]])
- otext = "%s(%s)" % (func_name, argtext)
- del stack[-nargs:]
- res = Operand(oUNK, None, FUNC_RANK, otext)
- spush(res)
- elif opcode == 0x02: #tFuncVar
- nb = 1 + int(bv >= 40)
- nargs, funcx = unpack("<B" + " BH"[nb], data[pos+1:pos+2+nb])
- prompt, nargs = divmod(nargs, 128)
- macro, funcx = divmod(funcx, 32768)
- if verbose:
- print(" FuncID=%d nargs=%d macro=%d prompt=%d" \
- % (funcx, nargs, macro, prompt))
- #### TODO #### if funcx == 255: # call add-in function
- if funcx == 255:
- func_attrs = ("CALL_ADDIN", 1, 30)
- else:
- func_attrs = func_defs.get(funcx, None)
- if not func_attrs:
- print("*** formula/tFuncVar unknown FuncID:%d" \
- % funcx, file=bk.logfile)
- spush(unk_opnd)
- else:
- func_name, minargs, maxargs = func_attrs[:3]
- if verbose:
- print(" name: %r, min~max args: %d~%d" \
- % (func_name, minargs, maxargs))
- assert minargs <= nargs <= maxargs
- assert len(stack) >= nargs
- assert len(stack) >= nargs
- argtext = listsep.join([arg.text for arg in stack[-nargs:]])
- otext = "%s(%s)" % (func_name, argtext)
- res = Operand(oUNK, None, FUNC_RANK, otext)
- del stack[-nargs:]
- spush(res)
- elif opcode == 0x03: #tName
- tgtnamex = unpack("<H", data[pos+1:pos+3])[0] - 1
- # Only change with BIFF version is number of trailing UNUSED bytes!
- if verbose: print(" tgtnamex=%d" % tgtnamex, file=bk.logfile)
- tgtobj = bk.name_obj_list[tgtnamex]
- if tgtobj.scope == -1:
- otext = tgtobj.name
- else:
- otext = "%s!%s" % (bk._sheet_names[tgtobj.scope], tgtobj.name)
- if verbose:
- print(" tName: setting text to", repr(otext), file=bk.logfile)
- res = Operand(oUNK, None, LEAF_RANK, otext)
- spush(res)
- elif opcode == 0x04: # tRef
- res = get_cell_addr(data, pos+1, bv, reldelta, browx, bcolx)
- if verbose: print(" ", res, file=bk.logfile)
- rowx, colx, row_rel, col_rel = res
- is_rel = row_rel or col_rel
- if is_rel:
- okind = oREL
- else:
- okind = oREF
- otext = cellnamerel(rowx, colx, row_rel, col_rel)
- res = Operand(okind, None, LEAF_RANK, otext)
- spush(res)
- elif opcode == 0x05: # tArea
- res1, res2 = get_cell_range_addr(
- data, pos+1, bv, reldelta, browx, bcolx)
- if verbose: print(" ", res1, res2, file=bk.logfile)
- rowx1, colx1, row_rel1, col_rel1 = res1
- rowx2, colx2, row_rel2, col_rel2 = res2
- coords = (rowx1, rowx2+1, colx1, colx2+1)
- relflags = (row_rel1, row_rel2, col_rel1, col_rel2)
- is_rel = 1 if sum(relflags) else 0 # (to_py3)
- if is_rel:
- okind = oREL
- else:
- okind = oREF
- if verbose: print(" ", coords, relflags, file=bk.logfile)
- otext = rangename2drel(coords, relflags)
- res = Operand(okind, None, LEAF_RANK, otext)
- spush(res)
- elif opcode == 0x06: # tMemArea
- not_in_name_formula(op, oname)
- elif opcode == 0x09: # tMemFunc
- nb = unpack("<H", data[pos+1:pos+3])[0]
- if verbose: print(" %d bytes of cell ref formula" % nb, file=bk.logfile)
- # no effect on stack
- elif opcode == 0x0C: #tRefN
- not_in_name_formula(op, oname)
- # res = get_cell_addr(data, pos+1, bv, reldelta=1)
- # # note *ALL* tRefN usage has signed offset for relative addresses
- # any_rel = 1
- # if verbose: print >> bk.logfile, " ", res
- # spush(res)
- elif opcode == 0x0D: #tAreaN
- not_in_name_formula(op, oname)
- # res = get_cell_range_addr(data, pos+1, bv, reldelta=1)
- # # note *ALL* tAreaN usage has signed offset for relative addresses
- # any_rel = 1
- # if verbose: print >> bk.logfile, " ", res
- elif opcode == 0x1A: # tRef3d
- if bv >= 80:
- res = get_cell_addr(data, pos+3, bv, reldelta, browx, bcolx)
- refx = unpack("<H", data[pos+1:pos+3])[0]
- shx1, shx2 = get_externsheet_local_range(bk, refx, verbose)
- else:
- res = get_cell_addr(data, pos+15, bv, reldelta, browx, bcolx)
- raw_extshtx, raw_shx1, raw_shx2 = \
- unpack("<hxxxxxxxxhh", data[pos+1:pos+15])
- if verbose:
- print("tRef3d", raw_extshtx, raw_shx1, raw_shx2, file=bk.logfile)
- shx1, shx2 = get_externsheet_local_range_b57(
- bk, raw_extshtx, raw_shx1, raw_shx2, verbose)
- rowx, colx, row_rel, col_rel = res
- is_rel = row_rel or col_rel
- any_rel = any_rel or is_rel
- coords = (shx1, shx2+1, rowx, rowx+1, colx, colx+1)
- any_err |= shx1 < -1
- if verbose: print(" ", coords, file=bk.logfile)
- res = Operand(oUNK, None)
- if is_rel:
- relflags = (0, 0, row_rel, row_rel, col_rel, col_rel)
- ref3d = Ref3D(coords + relflags)
- res.kind = oREL
- res.text = rangename3drel(bk, ref3d)
- else:
- ref3d = Ref3D(coords)
- res.kind = oREF
- res.text = rangename3d(bk, ref3d)
- res.rank = LEAF_RANK
- res.value = None
- spush(res)
- elif opcode == 0x1B: # tArea3d
- if bv >= 80:
- res1, res2 = get_cell_range_addr(data, pos+3, bv, reldelta)
- refx = unpack("<H", data[pos+1:pos+3])[0]
- shx1, shx2 = get_externsheet_local_range(bk, refx, verbose)
- else:
- res1, res2 = get_cell_range_addr(data, pos+15, bv, reldelta)
- raw_extshtx, raw_shx1, raw_shx2 = \
- unpack("<hxxxxxxxxhh", data[pos+1:pos+15])
- if verbose:
- print("tArea3d", raw_extshtx, raw_shx1, raw_shx2, file=bk.logfile)
- shx1, shx2 = get_externsheet_local_range_b57(
- bk, raw_extshtx, raw_shx1, raw_shx2, verbose)
- any_err |= shx1 < -1
- rowx1, colx1, row_rel1, col_rel1 = res1
- rowx2, colx2, row_rel2, col_rel2 = res2
- is_rel = row_rel1 or col_rel1 or row_rel2 or col_rel2
- any_rel = any_rel or is_rel
- coords = (shx1, shx2+1, rowx1, rowx2+1, colx1, colx2+1)
- if verbose: print(" ", coords, file=bk.logfile)
- res = Operand(oUNK, None)
- if is_rel:
- relflags = (0, 0, row_rel1, row_rel2, col_rel1, col_rel2)
- ref3d = Ref3D(coords + relflags)
- res.kind = oREL
- res.text = rangename3drel(bk, ref3d)
- else:
- ref3d = Ref3D(coords)
- res.kind = oREF
- res.text = rangename3d(bk, ref3d)
- res.rank = LEAF_RANK
- spush(res)
- elif opcode == 0x19: # tNameX
- dodgy = 0
- res = Operand(oUNK, None)
- if bv >= 80:
- refx, tgtnamex = unpack("<HH", data[pos+1:pos+5])
- tgtnamex -= 1
- origrefx = refx
- else:
- refx, tgtnamex = unpack("<hxxxxxxxxH", data[pos+1:pos+13])
- tgtnamex -= 1
- origrefx = refx
- if refx > 0:
- refx -= 1
- elif refx < 0:
- refx = -refx - 1
- else:
- dodgy = 1
- if verbose:
- print(" origrefx=%d refx=%d tgtnamex=%d dodgy=%d" \
- % (origrefx, refx, tgtnamex, dodgy), file=bk.logfile)
- # if tgtnamex == namex:
- # if verbose: print >> bk.logfile, "!!!! Self-referential !!!!"
- # dodgy = any_err = 1
- if not dodgy:
- if bv >= 80:
- shx1, shx2 = get_externsheet_local_range(bk, refx, verbose)
- elif origrefx > 0:
- shx1, shx2 = (-4, -4) # external ref
- else:
- exty = bk._externsheet_type_b57[refx]
- if exty == 4: # non-specific sheet in own doc't
- shx1, shx2 = (-1, -1) # internal, any sheet
- else:
- shx1, shx2 = (-666, -666)
- okind = oUNK
- ovalue = None
- if shx1 == -5: # addin func name
- okind = oSTRG
- ovalue = bk.addin_func_names[tgtnamex]
- otext = '"' + ovalue.replace('"', '""') + '"'
- elif dodgy or shx1 < -1:
- otext = "<<Name #%d in external(?) file #%d>>" \
- % (tgtnamex, origrefx)
- else:
- tgtobj = bk.name_obj_list[tgtnamex]
- if tgtobj.scope == -1:
- otext = tgtobj.name
- else:
- otext = "%s!%s" \
- % (bk._sheet_names[tgtobj.scope], tgtobj.name)
- if verbose:
- print(" tNameX: setting text to", repr(res.text), file=bk.logfile)
- res = Operand(okind, ovalue, LEAF_RANK, otext)
- spush(res)
- elif opcode in _error_opcodes:
- any_err = 1
- spush(error_opnd)
- else:
- if verbose:
- print("FORMULA: /// Not handled yet: t" + oname, file=bk.logfile)
- any_err = 1
- if sz <= 0:
- raise FormulaError("Fatal: token size is not positive")
- pos += sz
- any_rel = not not any_rel
- if verbose:
- print("End of formula. level=%d any_rel=%d any_err=%d stack=%r" % \
- (level, not not any_rel, any_err, stack))
- if len(stack) >= 2:
- print("*** Stack has unprocessed args")
- print()
-
- if len(stack) != 1:
- result = None
- else:
- result = stack[0].text
- return result
-
-#### under deconstruction ###
-def dump_formula(bk, data, fmlalen, bv, reldelta, verbose=0, isname=0):
- if verbose:
- print("dump_formula", fmlalen, bv, len(data))
- hex_char_dump(data, 0, fmlalen)
- assert bv >= 80 #### this function needs updating ####
- sztab = szdict[bv]
- pos = 0
- stack = []
- any_rel = 0
- any_err = 0
- spush = stack.append
- while 0 <= pos < fmlalen:
- op = data[pos]
- opcode = op & 0x1f
- optype = (op & 0x60) >> 5
- if optype:
- opx = opcode + 32
- else:
- opx = opcode
- oname = onames[opx] # + [" RVA"][optype]
-
- sz = sztab[opx]
- if verbose:
- print("Pos:%d Op:0x%02x Name:t%s Sz:%d opcode:%02xh optype:%02xh" \
- % (pos, op, oname, sz, opcode, optype))
- if not optype:
- if 0x01 <= opcode <= 0x02: # tExp, tTbl
- # reference to a shared formula or table record
- rowx, colx = unpack("<HH", data[pos+1:pos+5])
- if verbose: print(" ", (rowx, colx), file=bk.logfile)
- elif opcode == 0x10: # tList
- if verbose: print("tList pre", stack, file=bk.logfile)
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- spush(aop + bop)
- if verbose: print("tlist post", stack, file=bk.logfile)
- elif opcode == 0x11: # tRange
- if verbose: print("tRange pre", stack, file=bk.logfile)
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- assert len(aop) == 1
- assert len(bop) == 1
- result = do_box_funcs(tRangeFuncs, aop[0], bop[0])
- spush(result)
- if verbose: print("tRange post", stack, file=bk.logfile)
- elif opcode == 0x0F: # tIsect
- if verbose: print("tIsect pre", stack, file=bk.logfile)
- assert len(stack) >= 2
- bop = stack.pop()
- aop = stack.pop()
- assert len(aop) == 1
- assert len(bop) == 1
- result = do_box_funcs(tIsectFuncs, aop[0], bop[0])
- spush(result)
- if verbose: print("tIsect post", stack, file=bk.logfile)
- elif opcode == 0x19: # tAttr
- subop, nc = unpack("<BH", data[pos+1:pos+4])
- subname = tAttrNames.get(subop, "??Unknown??")
- if subop == 0x04: # Choose
- sz = nc * 2 + 6
- else:
- sz = 4
- if verbose: print(" subop=%02xh subname=t%s sz=%d nc=%02xh" % (subop, subname, sz, nc), file=bk.logfile)
- elif opcode == 0x17: # tStr
- if bv <= 70:
- nc = data[pos+1]
- strg = data[pos+2:pos+2+nc] # left in 8-bit encoding
- sz = nc + 2
- else:
- strg, newpos = unpack_unicode_update_pos(data, pos+1, lenlen=1)
- sz = newpos - pos
- if verbose: print(" sz=%d strg=%r" % (sz, strg), file=bk.logfile)
- else:
- if sz <= 0:
- print("**** Dud size; exiting ****")
- return
- pos += sz
- continue
- if opcode == 0x00: # tArray
- pass
- elif opcode == 0x01: # tFunc
- nb = 1 + int(bv >= 40)
- funcx = unpack("<" + " BH"[nb], data[pos+1:pos+1+nb])
- if verbose: print(" FuncID=%d" % funcx, file=bk.logfile)
- elif opcode == 0x02: #tFuncVar
- nb = 1 + int(bv >= 40)
- nargs, funcx = unpack("<B" + " BH"[nb], data[pos+1:pos+2+nb])
- prompt, nargs = divmod(nargs, 128)
- macro, funcx = divmod(funcx, 32768)
- if verbose: print(" FuncID=%d nargs=%d macro=%d prompt=%d" % (funcx, nargs, macro, prompt), file=bk.logfile)
- elif opcode == 0x03: #tName
- namex = unpack("<H", data[pos+1:pos+3])
- # Only change with BIFF version is the number of trailing UNUSED bytes!!!
- if verbose: print(" namex=%d" % namex, file=bk.logfile)
- elif opcode == 0x04: # tRef
- res = get_cell_addr(data, pos+1, bv, reldelta)
- if verbose: print(" ", res, file=bk.logfile)
- elif opcode == 0x05: # tArea
- res = get_cell_range_addr(data, pos+1, bv, reldelta)
- if verbose: print(" ", res, file=bk.logfile)
- elif opcode == 0x09: # tMemFunc
- nb = unpack("<H", data[pos+1:pos+3])[0]
- if verbose: print(" %d bytes of cell ref formula" % nb, file=bk.logfile)
- elif opcode == 0x0C: #tRefN
- res = get_cell_addr(data, pos+1, bv, reldelta=1)
- # note *ALL* tRefN usage has signed offset for relative addresses
- any_rel = 1
- if verbose: print(" ", res, file=bk.logfile)
- elif opcode == 0x0D: #tAreaN
- res = get_cell_range_addr(data, pos+1, bv, reldelta=1)
- # note *ALL* tAreaN usage has signed offset for relative addresses
- any_rel = 1
- if verbose: print(" ", res, file=bk.logfile)
- elif opcode == 0x1A: # tRef3d
- refx = unpack("<H", data[pos+1:pos+3])[0]
- res = get_cell_addr(data, pos+3, bv, reldelta)
- if verbose: print(" ", refx, res, file=bk.logfile)
- rowx, colx, row_rel, col_rel = res
- any_rel = any_rel or row_rel or col_rel
- shx1, shx2 = get_externsheet_local_range(bk, refx, verbose)
- any_err |= shx1 < -1
- coords = (shx1, shx2+1, rowx, rowx+1, colx, colx+1)
- if verbose: print(" ", coords, file=bk.logfile)
- if optype == 1: spush([coords])
- elif opcode == 0x1B: # tArea3d
- refx = unpack("<H", data[pos+1:pos+3])[0]
- res1, res2 = get_cell_range_addr(data, pos+3, bv, reldelta)
- if verbose: print(" ", refx, res1, res2, file=bk.logfile)
- rowx1, colx1, row_rel1, col_rel1 = res1
- rowx2, colx2, row_rel2, col_rel2 = res2
- any_rel = any_rel or row_rel1 or col_rel1 or row_rel2 or col_rel2
- shx1, shx2 = get_externsheet_local_range(bk, refx, verbose)
- any_err |= shx1 < -1
- coords = (shx1, shx2+1, rowx1, rowx2+1, colx1, colx2+1)
- if verbose: print(" ", coords, file=bk.logfile)
- if optype == 1: spush([coords])
- elif opcode == 0x19: # tNameX
- refx, namex = unpack("<HH", data[pos+1:pos+5])
- if verbose: print(" refx=%d namex=%d" % (refx, namex), file=bk.logfile)
- elif opcode in _error_opcodes:
- any_err = 1
- else:
- if verbose: print("FORMULA: /// Not handled yet: t" + oname, file=bk.logfile)
- any_err = 1
- if sz <= 0:
- print("**** Dud size; exiting ****")
- return
- pos += sz
- if verbose:
- print("End of formula. any_rel=%d any_err=%d stack=%r" % \
- (not not any_rel, any_err, stack), file=bk.logfile)
- if len(stack) >= 2:
- print("*** Stack has unprocessed args", file=bk.logfile)
-
-# === Some helper functions for displaying cell references ===
-
-# Note that a "non-standard" syntax is used in row and column
-# components in relative references.
-# For example, consider a relative reference: up two rows, right 3 columns.
-# On screen, with cursor in cell D10, this would appear as G8.
-# On screen, with cursor in cell Z100, this would appear as AC98.
-# On screen, with cursor in cell A1, this would appear as D65535.
-# These functions will display such a reference as [@+3,#-2].
-# "@" refers to the unknown base column.
-# "#" refers to the unknown base row.
-#
-# I'm aware of only one possibility of a sheet-relative component in
-# a reference: a 2D reference located in the "current sheet".
-# xlrd stores this internally with bounds of (0, 1, ...) and
-# relative flags of (1, 1, ...). These functions display the
-# sheet component as empty, just like Excel etc.
-
-def rownamerel(rowx, rowxrel):
- if not rowxrel:
- return "$%d" % rowx
- if rowx > 0:
- return "#+%d" % rowx
- if rowx < 0:
- return "#-%d" % (-rowx)
- return "#"
-
-def colnamerel(colx, colxrel):
- if not colxrel:
- return "$" + colname(colx)
- if colx > 0:
- return "@+%d" % colx
- if colx < 0:
- return "@-%d" % (-colx)
- return "@"
-##
-# Utility function: (5, 7) => 'H6'
-def cellname(rowx, colx):
- """ (5, 7) => 'H6' """
- return "%s%d" % (colname(colx), rowx+1)
-
-##
-# Utility function: (5, 7) => '$H$6'
-def cellnameabs(rowx, colx):
- """ (5, 7) => '$H$6' """
- return "$%s$%d" % (colname(colx), rowx+1)
-
-def cellnamerel(rowx, colx, rowxrel, colxrel):
- if not rowxrel and not colxrel:
- return cellnameabs(rowx, colx)
- return "[%s,%s]" % (
- colnamerel(colx, colxrel),
- rownamerel(rowx, rowxrel))
-##
-# Utility function: 7 => 'H', 27 => 'AB'
-def colname(colx):
- """ 7 => 'H', 27 => 'AB' """
- alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- if colx <= 25:
- return alphabet[colx]
- else:
- xdiv26, xmod26 = divmod(colx, 26)
- return alphabet[xdiv26 - 1] + alphabet[xmod26]
-
-def rangename2d(rlo, rhi, clo, chi):
- """ (5, 20, 7, 10) => '$H$6:$J$20' """
- if rhi == rlo+1 and chi == clo+1:
- return cellnameabs(rlo, clo)
- return "%s:%s" % (cellnameabs(rlo, clo), cellnameabs(rhi-1, chi-1))
-
-def rangename2drel(xxx_todo_changeme, xxx_todo_changeme1):
- (rlo, rhi, clo, chi) = xxx_todo_changeme
- (rlorel, rhirel, clorel, chirel) = xxx_todo_changeme1
- return "%s:%s" % (
- cellnamerel(rlo, clo, rlorel, clorel),
- cellnamerel(rhi-1, chi-1, rhirel, chirel)
- )
-##
-# Utility function:
-# <br /> Ref3D((1, 4, 5, 20, 7, 10)) => 'Sheet2:Sheet3!$H$6:$J$20'
-def rangename3d(book, ref3d):
- """ Ref3D(1, 4, 5, 20, 7, 10) => 'Sheet2:Sheet3!$H$6:$J$20'
- (assuming Excel's default sheetnames) """
- coords = ref3d.coords
- return "%s!%s" % (
- sheetrange(book, *coords[:2]),
- rangename2d(*coords[2:6]))
-
-##
-# Utility function:
-# <br /> Ref3D(coords=(0, 1, -32, -22, -13, 13), relflags=(0, 0, 1, 1, 1, 1))
-# => 'Sheet1![@-13,#-32]:[@+12,#-23]'
-# where '@' refers to the current or base column and '#'
-# refers to the current or base row.
-def rangename3drel(book, ref3d):
- coords = ref3d.coords
- relflags = ref3d.relflags
- shdesc = sheetrangerel(book, coords[:2], relflags[:2])
- rngdesc = rangename2drel(coords[2:6], relflags[2:6])
- if not shdesc:
- return rngdesc
- return "%s!%s" % (shdesc, rngdesc)
-
-def quotedsheetname(shnames, shx):
- if shx >= 0:
- shname = shnames[shx]
- else:
- shname = {
- -1: "?internal; any sheet?",
- -2: "internal; deleted sheet",
- -3: "internal; macro sheet",
- -4: "<<external>>",
- }.get(shx, "?error %d?" % shx)
- if "'" in shname:
- return "'" + shname.replace("'", "''") + "'"
- if " " in shname:
- return "'" + shname + "'"
- return shname
-
-def sheetrange(book, slo, shi):
- shnames = book.sheet_names()
- shdesc = quotedsheetname(shnames, slo)
- if slo != shi-1:
- shdesc += ":" + quotedsheetname(shnames, shi-1)
- return shdesc
-
-def sheetrangerel(book, xxx_todo_changeme2, xxx_todo_changeme3):
- (slo, shi) = xxx_todo_changeme2
- (slorel, shirel) = xxx_todo_changeme3
- if not slorel and not shirel:
- return sheetrange(book, slo, shi)
- assert (slo == 0 == shi-1) and slorel and shirel
- return ""
-
-# ==============================================================
diff --git a/tablib/packages/xlrd3/sheet.py b/tablib/packages/xlrd3/sheet.py
deleted file mode 100644
index 5911fb0..0000000
--- a/tablib/packages/xlrd3/sheet.py
+++ /dev/null
@@ -1,1611 +0,0 @@
-# Portions copyright © 2005-2009 Stephen John Machin, Lingfo Pty Ltd
-# This module is part of the xlrd3 package, which is released under a
-# BSD-style licence.
-
-# 2009-05-31 SJM Fixed problem with no CODEPAGE record on extremely minimal BIFF2.x 3rd-party file
-# 2009-04-27 SJM Integrated on_demand patch by Armando Serrano Lombillo
-# 2008-02-09 SJM Excel 2.0: build XFs on the fly from cell attributes
-# 2007-12-04 SJM Added support for Excel 2.x (BIFF2) files.
-# 2007-10-11 SJM Added missing entry for blank cell type to ctype_text
-# 2007-07-11 SJM Allow for BIFF2/3-style FORMAT record in BIFF4/8 file
-# 2007-04-22 SJM Remove experimental "trimming" facility.
-
-#for debugging only
-from math import isnan
-
-import time
-from struct import unpack
-from array import array
-
-from .biffh import *
-from .formula import dump_formula, decompile_formula, rangename2d
-from .formatting import nearest_colour_index, Format
-from .xfcell import XFCell
-
-DEBUG = 0
-OBJ_MSO_DEBUG = 0
-
-_WINDOW2_options = (
- # Attribute names and initial values to use in case
- # a WINDOW2 record is not written.
- ("show_formulas", 0),
- ("show_grid_lines", 1),
- ("show_sheet_headers", 1),
- ("panes_are_frozen", 0),
- ("show_zero_values", 1),
- ("automatic_grid_line_colour", 1),
- ("columns_from_right_to_left", 0),
- ("show_outline_symbols", 1),
- ("remove_splits_if_pane_freeze_is_removed", 0),
- ("sheet_selected", 0),
- # "sheet_visible" appears to be merely a clone of "sheet_selected".
- # The real thing is the visibility attribute from the BOUNDSHEET record.
- ("sheet_visible", 0),
- ("show_in_page_break_preview", 0),
- )
-
-def int_floor_div(x, y):
- return divmod(x, y)[0]
-
-class Sheet(BaseObject):
- """Contains the data for one worksheet.
-
- In the cell access functions, "rowx" is a row index, counting from zero,
- and "colx" is a column index, counting from zero.
- Negative values for row/column indexes and slice positions are supported in
- the expected fashion.
-
- For information about cell types and cell values, refer to the documentation
- of the Cell class.
-
- WARNING: You don't call this class yourself. You access Sheet objects via
- the Book object that was returned when you called xlrd.open_workbook("myfile.xls").
- """
-
- # Name of sheet.
- name = ''
-
- # Number of rows in sheet. A row index is in range(thesheet.nrows).
- nrows = 0
-
- # Number of columns in sheet. A column index is in range(thesheet.ncols).
- ncols = 0
-
- # The map from a column index to a Colinfo object. Often there is an entry
- # in COLINFO records for all column indexes in range(257).
- # Note that xlrd ignores the entry for the non-existent
- # 257th column. On the other hand, there may be no entry for unused columns.
- # - New in version 0.6.1
- colinfo_map = {}
-
- # The map from a row index to a Rowinfo object. Note that it is possible
- # to have missing entries -- at least one source of XLS files doesn't
- # bother writing ROW records.
- # - New in version 0.6.1
- rowinfo_map = {}
-
- # List of address ranges of cells containing column labels.
- # These are set up in Excel by Insert > Name > Labels > Columns.
- # - New in version 0.6.0
- # How to deconstruct the list::
- #
- # for crange in thesheet.col_label_ranges:
- # rlo, rhi, clo, chi = crange
- # for rx in xrange(rlo, rhi):
- # for cx in xrange(clo, chi):
- # print "Column label at (rowx=%d, colx=%d) is %r" \
- # (rx, cx, thesheet.cell_value(rx, cx))
- #
- col_label_ranges = []
-
- # List of address ranges of cells containing row labels.
- # For more details, see <i>col_label_ranges</i> above.
- # - New in version 0.6.0
- row_label_ranges = []
-
- # List of address ranges of cells which have been merged.
- # These are set up in Excel by Format > Cells > Alignment, then ticking
- # the "Merge cells" box.
- # - New in version 0.6.1. Extracted only if open_workbook(..., formatting_info=True)
- # How to deconstruct the list::
- #
- # for crange in thesheet.merged_cells:
- # rlo, rhi, clo, chi = crange
- # for rowx in xrange(rlo, rhi):
- # for colx in xrange(clo, chi):
- # # cell (rlo, clo) (the top left one) will carry the data
- # # and formatting info; the remainder will be recorded as
- # # blank cells, but a renderer will apply the formatting info
- # # for the top left cell (e.g. border, pattern) to all cells in
- # # the range.
- #
- merged_cells = []
-
- # Default column width from DEFCOLWIDTH record, else None.
- # From the OOo docs:
- # """Column width in characters, using the width of the zero character
- # from default font (first FONT record in the file). Excel adds some
- # extra space to the default width, depending on the default font and
- # default font size. The algorithm how to exactly calculate the resulting
- # column width is not known.
- # Example: The default width of 8 set in this record results in a column
- # width of 8.43 using Arial font with a size of 10 points."""
- # For the default hierarchy, refer to the Colinfo class above.
- # - New in version 0.6.1
- defcolwidth = None
-
- # Default column width from STANDARDWIDTH record, else None.
- # From the OOo docs:
- # """Default width of the columns in 1/256 of the width of the zero
- # character, using default font (first FONT record in the file)."""
- # For the default hierarchy, refer to the Colinfo class above.
- # - New in version 0.6.1
- standardwidth = None
-
- # Default value to be used for a row if there is
- # no ROW record for that row.
- # From the <i>optional</i> DEFAULTROWHEIGHT record.
- default_row_height = None
-
- # Default value to be used for a row if there is
- # no ROW record for that row.
- # From the ´optional´ DEFAULTROWHEIGHT record.
- default_row_height_mismatch = None
-
- # Default value to be used for a row if there is
- # no ROW record for that row.
- # From the ´optional´ DEFAULTROWHEIGHT record.
- default_row_hidden = None
-
- # Default value to be used for a row if there is
- # no ROW record for that row.
- # From the <i>optional</i> DEFAULTROWHEIGHT record.
- default_additional_space_above = None
-
- # Default value to be used for a row if there is
- # no ROW record for that row.
- # From the <i>optional</i> DEFAULTROWHEIGHT record.
- default_additional_space_below = None
-
- # Visibility of the sheet. 0 = visible, 1 = hidden (can be unhidden
- # by user -- Format/Sheet/Unhide), 2 = "very hidden" (can be unhidden
- # only by VBA macro).
- visibility = 0
-
- # A 256-element tuple corresponding to the contents of the GCW record for this sheet.
- # If no such record, treat as all bits zero.
- # Applies to BIFF4-7 only. See docs of Colinfo class for discussion.
- gcw = (0, ) * 256
-
- def __init__(self, book, position, name, number):
- self.book = book
- self.biff_version = book.biff_version
- self._position = position
- self.logfile = book.logfile
- self.pickleable = book.pickleable
- # (to_py3) self.dont_use_array = not(array_array and (CAN_PICKLE_ARRAY or not book.pickleable))
- self.name = name
- self.number = number
- self.verbosity = book.verbosity
- self.formatting_info = book.formatting_info
- self._xf_index_to_xl_type_map = book._xf_index_to_xl_type_map
- self.nrows = 0 # actual, including possibly empty cells
- self.ncols = 0
- self._maxdatarowx = -1 # highest rowx containing a non-empty cell
- self._maxdatacolx = -1 # highest colx containing a non-empty cell
- self._dimnrows = 0 # as per DIMENSIONS record
- self._dimncols = 0
- self._cell_values = []
- self._cell_types = []
- self._cell_xf_indexes = []
- self._need_fix_ragged_rows = 0
- self.defcolwidth = None
- self.standardwidth = None
- self.default_row_height = None
- self.default_row_height_mismatch = 0
- self.default_row_hidden = 0
- self.default_additional_space_above = 0
- self.default_additional_space_below = 0
- self.colinfo_map = {}
- self.rowinfo_map = {}
- self.col_label_ranges = []
- self.row_label_ranges = []
- self.merged_cells = []
- self._xf_index_stats = [0, 0, 0, 0]
- self.visibility = book._sheet_visibility[number] # from BOUNDSHEET record
- for attr, defval in _WINDOW2_options:
- setattr(self, attr, defval)
- self.first_visible_rowx = 0
- self.first_visible_colx = 0
- self.gridline_colour_index = 0x40
- self.gridline_colour_rgb = None # pre-BIFF8
- self.cached_page_break_preview_mag_factor = 0
- self.cached_normal_view_mag_factor = 0
- self._ixfe = None # BIFF2 only
- self._cell_attr_to_xfx = {} # BIFF2.0 only
-
- #### Don't initialise this here, use class attribute initialisation.
- #### self.gcw = (0, ) * 256 ####
-
- if self.biff_version >= 80:
- self.utter_max_rows = 65536
- else:
- self.utter_max_rows = 16384
- self.utter_max_cols = 256
-
- def cell(self, rowx, colx):
- """ Get the XFCell() object in the given row and column. """
- if self.formatting_info:
- xf_index = self.cell_xf_index(rowx, colx)
- else:
- xf_index = None
- ctype = self.cell_type(rowx, colx)
- value = self.cell_value(rowx, colx)
- return Cell(ctype, value, xf_index, self)
-
- def cell_value(self, rowx, colx):
- """ Value of the cell in the given row and column. """
- return self._cell_values[rowx][colx]
-
- def cell_type(self, rowx, colx):
- """ Type of the cell in the given row and column.
- Refer to the documentation of the Cell class.
- """
- return self._cell_types[rowx][colx]
-
- # New in version 0.6.1
- def cell_xf_index(self, rowx, colx):
- """ XF index of the cell in the given row and column.
- This is an index into Book.xf_list.
- """
- self.req_fmt_info()
- xfx = self._cell_xf_indexes[rowx][colx]
- if xfx > -1:
- self._xf_index_stats[0] += 1
- return xfx
- # Check for a row xf_index
- try:
- xfx = self.rowinfo_map[rowx].xf_index
- if xfx > -1:
- self._xf_index_stats[1] += 1
- return xfx
- except KeyError:
- pass
- # Check for a column xf_index
- try:
- xfx = self.colinfo_map[colx].xf_index
- assert xfx > -1
- self._xf_index_stats[2] += 1
- return xfx
- except KeyError:
- # If all else fails, 15 is used as hardwired global default xf_index.
- self._xf_index_stats[3] += 1
- return 15
-
-
- def row(self, rowx):
- """ Returns a sequence of the Cell objects in the given row. """
- return [self.cell(rowx, colx) for colx in range(self.ncols)]
-
- def row_types(self, rowx, start_colx=0, end_colx=None):
- """ Returns a slice of the types of the cells in the given row. """
- if end_colx is None:
- return self._cell_types[rowx][start_colx:]
- return self._cell_types[rowx][start_colx:end_colx]
-
- def row_values(self, rowx, start_colx=0, end_colx=None):
- """ Returns a slice of the values of the cells in the given row. """
- if end_colx is None:
- return self._cell_values[rowx][start_colx:]
- return self._cell_values[rowx][start_colx:end_colx]
-
- def row_slice(self, rowx, start_colx=0, end_colx=None):
- """ Returns a slice of the Cell objects in the given row. """
- nc = self.ncols
- if start_colx < 0:
- start_colx += nc
- if start_colx < 0:
- start_colx = 0
- if end_colx is None or end_colx > nc:
- end_colx = nc
- elif end_colx < 0:
- end_colx += nc
- return [self.cell(rowx, colx) for colx in range(start_colx, end_colx)]
-
- def col_slice(self, colx, start_rowx=0, end_rowx=None):
- """ Returns a slice of the Cell objects in the given column. """
- nr = self.nrows
- if start_rowx < 0:
- start_rowx += nr
- if start_rowx < 0:
- start_rowx = 0
- if end_rowx is None or end_rowx > nr:
- end_rowx = nr
- elif end_rowx < 0:
- end_rowx += nr
- return [self.cell(rowx, colx) for rowx in range(start_rowx, end_rowx)]
-
- col = col_slice
- """ Returns a sequence of the Cell objects in the given column. """
-
- def col_values(self, colx, start_rowx=0, end_rowx=None):
- """ Returns a slice of the values of the cells in the given column. """
- nr = self.nrows
- if start_rowx < 0:
- start_rowx += nr
- if start_rowx < 0:
- start_rowx = 0
- if end_rowx is None or end_rowx > nr:
- end_rowx = nr
- elif end_rowx < 0:
- end_rowx += nr
- return [self._cell_values[rowx][colx] for rowx in range(start_rowx, end_rowx)]
-
- def col_types(self, colx, start_rowx=0, end_rowx=None):
- """ Returns a slice of the types of the cells in the given column. """
- nr = self.nrows
- if start_rowx < 0:
- start_rowx += nr
- if start_rowx < 0:
- start_rowx = 0
- if end_rowx is None or end_rowx > nr:
- end_rowx = nr
- elif end_rowx < 0:
- end_rowx += nr
- return [self._cell_types[rowx][colx] for rowx in range(start_rowx, end_rowx)]
-
- # Following methods are used in building the worksheet.
- # They are not part of the API.
-
- def extend_cells(self, nr, nc):
- assert 1 <= nc <= self.utter_max_cols
- assert 1 <= nr <= self.utter_max_rows
- if nr <= self.nrows:
- # New cell is in an existing row, so extend that row (if necessary).
- # Note that nr < self.nrows means that the cell data
- # is not in ascending row order!!
- self._need_fix_ragged_rows = 1
- nrx = nr - 1
- trow = self._cell_types[nrx]
- tlen = len(trow)
- nextra = max(nc, self.ncols) - tlen
- if nextra > 0:
- xce = XL_CELL_EMPTY
- #(to_py3) if self.dont_use_array: ... removed
- trow.extend(array('B', [xce]) * nextra)
- if self.formatting_info:
- self._cell_xf_indexes[nrx].extend(array('h', [-1]) * nextra)
- self._cell_values[nrx].extend([''] * nextra)
- if nc > self.ncols:
- self.ncols = nc
- self._need_fix_ragged_rows = 1
- if nr > self.nrows:
- scta = self._cell_types.append
- scva = self._cell_values.append
- scxa = self._cell_xf_indexes.append
- fmt_info = self.formatting_info
- xce = XL_CELL_EMPTY
- nc = self.ncols
-
- #(to_py3) if self.dont_use_array: ... removed
- for _unused in range(self.nrows, nr):
- scta(array('B', [xce]) * nc)
- scva([''] * nc)
- if fmt_info:
- scxa(array('h', [-1]) * nc)
- self.nrows = nr
-
- def fix_ragged_rows(self):
- t0 = time.time()
- ncols = self.ncols
- xce = XL_CELL_EMPTY
- s_cell_types = self._cell_types
- s_cell_values = self._cell_values
- s_cell_xf_indexes = self._cell_xf_indexes
- s_fmt_info = self.formatting_info
- totrowlen = 0
- for rowx in range(self.nrows):
- trow = s_cell_types[rowx]
- rlen = len(trow)
- totrowlen += rlen
- nextra = ncols - rlen
- if nextra > 0:
- s_cell_values[rowx][rlen:] = [''] * nextra
- trow.extend(array('B', [xce]) * nextra)
- if s_fmt_info:
- s_cell_xf_indexes[rowx][rlen:] = array('h', [-1]) * nextra
- self._fix_ragged_rows_time = time.time() - t0
-
- def tidy_dimensions(self):
- if self.verbosity >= 3:
- fprintf(self.logfile,
- "tidy_dimensions: nrows=%d ncols=%d _need_fix_ragged_rows=%d\n",
- self.nrows, self.ncols, self._need_fix_ragged_rows)
- if self.merged_cells:
- nr = nc = 0
- umaxrows = self.utter_max_rows
- umaxcols = self.utter_max_cols
- for crange in self.merged_cells:
- rlo, rhi, clo, chi = crange
- if not (0 <= rlo < rhi <= umaxrows) \
- or not (0 <= clo < chi <= umaxcols):
- fprintf(self.logfile,
- "*** WARNING: sheet #%d (%r), MERGEDCELLS bad range %r\n",
- self.number, self.name, crange)
- if rhi > nr: nr = rhi
- if chi > nc: nc = chi
- self.extend_cells(nr, nc)
- if self.verbosity >= 1 and \
- (self.nrows != self._dimnrows or self.ncols != self._dimncols):
- fprintf(self.logfile,
- "NOTE *** sheet %d (%r): DIMENSIONS R,C = %d,%d should be %d,%d\n",
- self.number,
- self.name,
- self._dimnrows,
- self._dimncols,
- self.nrows,
- self.ncols,
- )
- if self._need_fix_ragged_rows:
- self.fix_ragged_rows()
-
- def put_cell(self, rowx, colx, ctype, value, xf_index):
- try:
- self._cell_types[rowx][colx] = ctype
- self._cell_values[rowx][colx] = value
- if self.formatting_info:
- self._cell_xf_indexes[rowx][colx] = xf_index
- except IndexError:
- self.extend_cells(rowx+1, colx+1)
- try:
- self._cell_types[rowx][colx] = ctype
- self._cell_values[rowx][colx] = value
- if self.formatting_info:
- self._cell_xf_indexes[rowx][colx] = xf_index
- except:
- print("put_cell", rowx, colx, file=self.logfile)
- raise
- except:
- print("put_cell", rowx, colx, file=self.logfile)
- raise
-
- def put_blank_cell(self, rowx, colx, xf_index):
- # This is used for cells from BLANK and MULBLANK records
- ctype = XL_CELL_BLANK
- value = ''
- try:
- self._cell_types[rowx][colx] = ctype
- self._cell_values[rowx][colx] = value
- self._cell_xf_indexes[rowx][colx] = xf_index
- except IndexError:
- self.extend_cells(rowx+1, colx+1)
- try:
- self._cell_types[rowx][colx] = ctype
- self._cell_values[rowx][colx] = value
- self._cell_xf_indexes[rowx][colx] = xf_index
- except:
- print("put_cell", rowx, colx, file=self.logfile)
- raise
- except:
- print("put_cell", rowx, colx, file=self.logfile)
- raise
-
- def put_number_cell(self, rowx, colx, value, xf_index):
- # for debugging
- if type(value) == float and isnan(value):
- pass
- ctype = self._xf_index_to_xl_type_map[xf_index]
- try:
- self._cell_types[rowx][colx] = ctype
- self._cell_values[rowx][colx] = value
- if self.formatting_info:
- self._cell_xf_indexes[rowx][colx] = xf_index
- except IndexError:
- self.extend_cells(rowx+1, colx+1)
- try:
- self._cell_types[rowx][colx] = ctype
- self._cell_values[rowx][colx] = value
- if self.formatting_info:
- self._cell_xf_indexes[rowx][colx] = xf_index
- except:
- print("put_number_cell", rowx, colx, file=self.logfile)
- raise
- except:
- print("put_number_cell", rowx, colx, file=self.logfile)
- raise
-
- # === Methods after this line neither know nor care about how cells are stored.
-
- def read(self, bk):
- global rc_stats
- DEBUG = 0
- verbose = DEBUG or self.verbosity >= 2
- verbose_rows = DEBUG or self.verbosity >= 4
- verbose_formulas = 1 and verbose
- oldpos = bk._position
- bk._position = self._position
- XL_SHRFMLA_ETC_ETC = (
- XL_SHRFMLA, XL_ARRAY, XL_TABLEOP, XL_TABLEOP2,
- XL_ARRAY2, XL_TABLEOP_B2,
- )
- self_put_number_cell = self.put_number_cell
- self_put_cell = self.put_cell
- self_put_blank_cell = self.put_blank_cell
- local_unpack = unpack
- bk_get_record_parts = bk.get_record_parts
- bv = self.biff_version
- fmt_info = self.formatting_info
- eof_found = 0
- while 1:
- rc, data_len, data = bk_get_record_parts()
- if rc == XL_NUMBER:
- rowx, colx, xf_index, d = local_unpack('<HHHd', data)
- self_put_number_cell(rowx, colx, d, xf_index)
- elif rc == XL_LABELSST:
- rowx, colx, xf_index, sstindex = local_unpack('<HHHi', data)
- self_put_cell(rowx, colx, XL_CELL_TEXT, bk._sharedstrings[sstindex], xf_index)
- elif rc == XL_LABEL or rc == XL_RSTRING:
- rowx, colx, xf_index = local_unpack('<HHH', data[0:6])
- if bv < BIFF_FIRST_UNICODE:
- strg = unpack_string(data, 6, bk.encoding or bk.derive_encoding, lenlen=2)
- else:
- strg = unpack_unicode(data, 6, lenlen=2)
- self_put_cell(rowx, colx, XL_CELL_TEXT, strg, xf_index)
- elif rc == XL_RK:
- rowx, colx, xf_index = local_unpack('<HHH', data[:6])
- d = unpack_RK(data[6:10])
- self_put_number_cell(rowx, colx, d, xf_index)
- elif rc == XL_MULRK:
- mulrk_row, mulrk_first = local_unpack('<HH', data[0:4])
- mulrk_last, = local_unpack('<H', data[-2:])
- pos = 4
- for colx in range(mulrk_first, mulrk_last+1):
- xf_index, = local_unpack('<H', data[pos:pos+2])
- d = unpack_RK(data[pos+2:pos+6])
- pos += 6
- self_put_number_cell(mulrk_row, colx, d, xf_index)
- elif rc == XL_ROW:
- # Version 0.6.0a3: ROW records are just not worth using (for memory allocation).
- # Version 0.6.1: now used for formatting info.
- if not fmt_info: continue
- rowx, bits1, bits2 = local_unpack('<H4xH4xi', data[0:16])
- if not(0 <= rowx < self.utter_max_rows):
- print("*** NOTE: ROW record has row index %d; " \
- "should have 0 <= rowx < %d -- record ignored!" \
- % (rowx, self.utter_max_rows), file=self.logfile)
- continue
- r = Rowinfo()
- # Using upkbits() is far too slow on a file
- # with 30 sheets each with 10K rows :-(
- # upkbits(r, bits1, (
- # ( 0, 0x7FFF, 'height'),
- # (15, 0x8000, 'has_default_height'),
- # ))
- # upkbits(r, bits2, (
- # ( 0, 0x00000007, 'outline_level'),
- # ( 4, 0x00000010, 'outline_group_starts_ends'),
- # ( 5, 0x00000020, 'hidden'),
- # ( 6, 0x00000040, 'height_mismatch'),
- # ( 7, 0x00000080, 'has_default_xf_index'),
- # (16, 0x0FFF0000, 'xf_index'),
- # (28, 0x10000000, 'additional_space_above'),
- # (29, 0x20000000, 'additional_space_below'),
- # ))
- # So:
- r.height = bits1 & 0x7fff
- r.has_default_height = (bits1 >> 15) & 1
- r.outline_level = bits2 & 7
- r.outline_group_starts_ends = (bits2 >> 4) & 1
- r.hidden = (bits2 >> 5) & 1
- r.height_mismatch = (bits2 >> 6) & 1
- r.has_default_xf_index = (bits2 >> 7) & 1
- r.xf_index = (bits2 >> 16) & 0xfff
- r.additional_space_above = (bits2 >> 28) & 1
- r.additional_space_below = (bits2 >> 29) & 1
- if not r.has_default_xf_index:
- r.xf_index = -1
- self.rowinfo_map[rowx] = r
- if 0 and r.xf_index > -1:
- fprintf(self.logfile,
- "**ROW %d %d %d\n",
- self.number, rowx, r.xf_index)
- if verbose_rows:
- print('ROW', rowx, bits1, bits2, file=self.logfile)
- r.dump(self.logfile,
- header="--- sh #%d, rowx=%d ---" % (self.number, rowx))
- elif rc in XL_FORMULA_OPCODES: # 06, 0206, 0406
- if bv >= 50:
- # IMPORTANT result_str is bytes
- rowx, colx, xf_index, result_str, flags = local_unpack('<HHH8sH', data[0:16])
- lenlen = 2
- tkarr_offset = 20
- elif bv >= 30:
- rowx, colx, xf_index, result_str, flags = local_unpack('<HHH8sH', data[0:16])
- lenlen = 2
- tkarr_offset = 16
- else: # BIFF2
- rowx, colx, cell_attr, result_str, flags = local_unpack('<HH3s8sB', data[0:16])
- xf_index = self.fixed_BIFF2_xfindex(cell_attr, rowx, colx)
- lenlen = 1
- tkarr_offset = 16
- if verbose_formulas: # testing formula dumper
- #### XXXX FIXME
- fprintf(self.logfile, "FORMULA: rowx=%d colx=%d\n", rowx, colx)
- fmlalen = local_unpack("<H", data[20:22])[0]
- decompile_formula(bk, data[22:], fmlalen,
- reldelta=0, browx=rowx, bcolx=colx, verbose=1)
- if result_str[6:8] == b'\xFF\xFF':
- if result_str[0] == 0: #b'\x00':
- # need to read next record (STRING)
- gotstring = 0
- # if flags & 8:
- if 1: # "flags & 8" applies only to SHRFMLA
- # actually there's an optional SHRFMLA or ARRAY etc record to skip over
- rc2, data2_len, data2 = bk.get_record_parts()
- if rc2 == XL_STRING or rc2 == XL_STRING_B2:
- gotstring = 1
- elif rc2 == XL_ARRAY:
- row1x, rownx, col1x, colnx, array_flags, tokslen = \
- local_unpack("<HHBBBxxxxxH", data2[:14])
- if verbose_formulas:
- fprintf(self.logfile, "ARRAY: %d %d %d %d %d\n",
- row1x, rownx, col1x, colnx, array_flags)
- dump_formula(bk, data2[14:], tokslen, bv, reldelta=0, verbose=1)
- elif rc2 == XL_SHRFMLA:
- row1x, rownx, col1x, colnx, nfmlas, tokslen = \
- local_unpack("<HHBBxBH", data2[:10])
- if verbose_formulas:
- fprintf(self.logfile, "SHRFMLA (sub): %d %d %d %d %d\n",
- row1x, rownx, col1x, colnx, nfmlas)
- decompile_formula(bk, data2[10:], tokslen, reldelta=1, verbose=1)
- elif rc2 not in XL_SHRFMLA_ETC_ETC:
- raise XLRDError(
- "Expected SHRFMLA, ARRAY, TABLEOP* or STRING record; found 0x%04x" % rc2)
- # if DEBUG: print "gotstring:", gotstring
- # now for the STRING record
- if not gotstring:
- rc2, _unused_len, data2 = bk.get_record_parts()
- if rc2 not in (XL_STRING, XL_STRING_B2):
- raise XLRDError("Expected STRING record; found 0x%04x" % rc2)
- # if DEBUG: print "STRING: data=%r BIFF=%d cp=%d" % (data2, self.biff_version, bk.encoding)
- if self.biff_version < BIFF_FIRST_UNICODE:
- strg = unpack_string(data2, 0, bk.encoding or bk.derive_encoding, lenlen=1 + int(bv > 20))
- else:
- strg = unpack_unicode(data2, 0, lenlen=2)
- self.put_cell(rowx, colx, XL_CELL_TEXT, strg, xf_index)
- # if DEBUG: print "FORMULA strg %r" % strg
- elif result_str[0] == 1: #b'\x01':
- # boolean formula result
- value = result_str[2]
- self.put_cell(rowx, colx, XL_CELL_BOOLEAN, value, xf_index)
- elif result_str[0] == 2: #b'\x02':
- # Error in cell
- value = result_str[2]
- self.put_cell(rowx, colx, XL_CELL_ERROR, value, xf_index)
- elif result_str[0] == 3:#b'\x03':
- # empty ... i.e. empty (zero-length) string, NOT an empty cell.
- self.put_cell(rowx, colx, XL_CELL_TEXT, "", xf_index)
- else:
- raise XLRDError("unexpected special case (0x%02x) in FORMULA" % result_str[0])
- else:
- # it is a number
- d = local_unpack('<d', result_str)[0]
- self_put_number_cell(rowx, colx, d, xf_index)
- elif rc == XL_BOOLERR:
- rowx, colx, xf_index, value, is_err = local_unpack('<HHHBB', data[:8])
- # Note OOo Calc 2.0 writes 9-byte BOOLERR records.
- # OOo docs say 8. Excel writes 8.
- cellty = (XL_CELL_BOOLEAN, XL_CELL_ERROR)[is_err]
- # if DEBUG: print "XL_BOOLERR", rowx, colx, xf_index, value, is_err
- self.put_cell(rowx, colx, cellty, value, xf_index)
- elif rc == XL_COLINFO:
- if not fmt_info: continue
- c = Colinfo()
- first_colx, last_colx, c.width, c.xf_index, flags \
- = local_unpack("<HHHHH", data[:10])
- #### Colinfo.width is denominated in 256ths of a character,
- #### *not* in characters.
- if not(0 <= first_colx <= last_colx <= 256):
- # Note: 256 instead of 255 is a common mistake.
- # We silently ignore the non-existing 257th column in that case.
- print("*** NOTE: COLINFO record has first col index %d, last %d; " \
- "should have 0 <= first <= last <= 255 -- record ignored!" \
- % (first_colx, last_colx), file=self.logfile)
- del c
- continue
- upkbits(c, flags, (
- ( 0, 0x0001, 'hidden'),
- ( 1, 0x0002, 'bit1_flag'),
- # *ALL* colinfos created by Excel in "default" cases are 0x0002!!
- # Maybe it's "locked" by analogy with XFProtection data.
- ( 8, 0x0700, 'outline_level'),
- (12, 0x1000, 'collapsed'),
- ))
- for colx in range(first_colx, last_colx+1):
- if colx > 255: break # Excel does 0 to 256 inclusive
- self.colinfo_map[colx] = c
- if 0:
- fprintf(self.logfile,
- "**COL %d %d %d\n",
- self.number, colx, c.xf_index)
- if verbose:
- fprintf(
- self.logfile,
- "COLINFO sheet #%d cols %d-%d: wid=%d xf_index=%d flags=0x%04x\n",
- self.number, first_colx, last_colx, c.width, c.xf_index, flags,
- )
- c.dump(self.logfile, header='===')
- elif rc == XL_DEFCOLWIDTH:
- self.defcolwidth, = local_unpack("<H", data[:2])
- if 0: print('DEFCOLWIDTH', self.defcolwidth, file=self.logfile)
- elif rc == XL_STANDARDWIDTH:
- if data_len != 2:
- print('*** ERROR *** STANDARDWIDTH', data_len, repr(data), file=self.logfile)
- self.standardwidth, = local_unpack("<H", data[:2])
- if 0: print('STANDARDWIDTH', self.standardwidth, file=self.logfile)
- elif rc == XL_GCW:
- if not fmt_info: continue # useless w/o COLINFO
- assert data_len == 34
- assert data[0:2] == "\x20\x00"
- iguff = unpack("<8i", data[2:34])
- gcw = []
- for bits in iguff:
- for j in range(32):
- gcw.append(bits & 1)
- bits >>= 1
- self.gcw = tuple(gcw)
- if 0:
- showgcw = "".join(["F "[x] for x in gcw]).rstrip().replace(' ', '.')
- print("GCW:", showgcw)
- elif rc == XL_BLANK:
- if not fmt_info: continue
- rowx, colx, xf_index = local_unpack('<HHH', data[:6])
- if 0: print("BLANK", rowx, colx, xf_index, file=self.logfile)
- self_put_blank_cell(rowx, colx, xf_index)
- elif rc == XL_MULBLANK: # 00BE
- if not fmt_info: continue
- mul_row, mul_first = local_unpack('<HH', data[0:4])
- mul_last, = local_unpack('<H', data[-2:])
- if 0:
- print("MULBLANK", mul_row, mul_first, mul_last, file=self.logfile)
- pos = 4
- for colx in range(mul_first, mul_last+1):
- xf_index, = local_unpack('<H', data[pos:pos+2])
- pos += 2
- self_put_blank_cell(mul_row, colx, xf_index)
- elif rc == XL_DIMENSION or rc == XL_DIMENSION2:
- # if data_len == 10:
- # Was crashing on BIFF 4.0 file w/o the two trailing unused bytes.
- # Reported by Ralph Heimburger.
- if bv < 80:
- dim_tuple = local_unpack('<HxxH', data[2:8])
- else:
- dim_tuple = local_unpack('<ixxH', data[4:12])
- self.nrows, self.ncols = 0, 0
- self._dimnrows, self._dimncols = dim_tuple
- if not self.book._xf_epilogue_done:
- # Needed for bv <= 40
- self.book.xf_epilogue()
- if verbose:
- fprintf(self.logfile,
- "sheet %d(%r) DIMENSIONS: ncols=%d nrows=%d\n",
- self.number, self.name, self._dimncols, self._dimnrows
- )
- elif rc == XL_EOF:
- DEBUG = 0
- if DEBUG: print("SHEET.READ: EOF", file=self.logfile)
- eof_found = 1
- break
- elif rc == XL_OBJ:
- # handle SHEET-level objects; note there's a separate Book.handle_obj
- self.handle_obj(data)
- elif rc == XL_MSO_DRAWING:
- self.handle_msodrawingetc(rc, data_len, data)
- elif rc == XL_TXO:
- self.handle_txo(data)
- elif rc == XL_NOTE:
- self.handle_note(data)
- elif rc == XL_FEAT11:
- self.handle_feat11(data)
- elif rc in bofcodes: ##### EMBEDDED BOF #####
- version, boftype = local_unpack('<HH', data[0:4])
- if boftype != 0x20: # embedded chart
- print("*** Unexpected embedded BOF (0x%04x) at offset %d: version=0x%04x type=0x%04x" \
- % (rc, bk._position - data_len - 4, version, boftype), file=self.logfile)
- while 1:
- code, data_len, data = bk.get_record_parts()
- if code == XL_EOF:
- break
- if DEBUG: print("---> found EOF", file=self.logfile)
- elif rc == XL_COUNTRY:
- bk.handle_country(data)
- elif rc == XL_LABELRANGES:
- pos = 0
- pos = unpack_cell_range_address_list_update_pos(
- self.row_label_ranges, data, pos, bv, addr_size=8,
- )
- pos = unpack_cell_range_address_list_update_pos(
- self.col_label_ranges, data, pos, bv, addr_size=8,
- )
- assert pos == data_len
- elif rc == XL_ARRAY:
- row1x, rownx, col1x, colnx, array_flags, tokslen = \
- local_unpack("<HHBBBxxxxxH", data[:14])
- if verbose_formulas:
- print("ARRAY:", row1x, rownx, col1x, colnx, array_flags)
- dump_formula(bk, data[14:], tokslen, bv, reldelta=0, verbose=1)
- elif rc == XL_SHRFMLA:
- row1x, rownx, col1x, colnx, nfmlas, tokslen = \
- local_unpack("<HHBBxBH", data[:10])
- if verbose_formulas:
- print("SHRFMLA (main):", row1x, rownx, col1x, colnx, nfmlas)
- decompile_formula(bk, data[10:], tokslen, reldelta=0, verbose=1)
- elif rc == XL_CONDFMT:
- if not fmt_info: continue
- assert bv >= 80
- num_CFs, needs_recalc, browx1, browx2, bcolx1, bcolx2 = \
- unpack("<6H", data[0:12])
- if self.verbosity >= 1:
- fprintf(self.logfile,
- "\n*** WARNING: Ignoring CONDFMT (conditional formatting) record\n" \
- "*** in Sheet %d (%r).\n" \
- "*** %d CF record(s); needs_recalc_or_redraw = %d\n" \
- "*** Bounding box is %s\n",
- self.number, self.name, num_CFs, needs_recalc,
- rangename2d(browx1, browx2+1, bcolx1, bcolx2+1),
- )
- olist = [] # updated by the function
- pos = unpack_cell_range_address_list_update_pos(
- olist, data, 12, bv, addr_size=8)
- # print >> self.logfile, repr(result), len(result)
- if self.verbosity >= 1:
- fprintf(self.logfile,
- "*** %d individual range(s):\n" \
- "*** %s\n",
- len(olist),
- ", ".join([rangename2d(*coords) for coords in olist]),
- )
- elif rc == XL_CF:
- if not fmt_info: continue
- cf_type, cmp_op, sz1, sz2, flags = unpack("<BBHHi", data[0:10])
- font_block = (flags >> 26) & 1
- bord_block = (flags >> 28) & 1
- patt_block = (flags >> 29) & 1
- if self.verbosity >= 1:
- fprintf(self.logfile,
- "\n*** WARNING: Ignoring CF (conditional formatting) sub-record.\n" \
- "*** cf_type=%d, cmp_op=%d, sz1=%d, sz2=%d, flags=0x%08x\n" \
- "*** optional data blocks: font=%d, border=%d, pattern=%d\n",
- cf_type, cmp_op, sz1, sz2, flags,
- font_block, bord_block, patt_block,
- )
- # hex_char_dump(data, 0, data_len)
- pos = 12
- if font_block:
- (font_height, font_options, weight, escapement, underline,
- font_colour_index, two_bits, font_esc, font_underl) = \
- unpack("<64x i i H H B 3x i 4x i i i 18x", data[pos:pos+118])
- font_style = (two_bits > 1) & 1
- posture = (font_options > 1) & 1
- font_canc = (two_bits > 7) & 1
- cancellation = (font_options > 7) & 1
- if self.verbosity >= 1:
- fprintf(self.logfile,
- "*** Font info: height=%d, weight=%d, escapement=%d,\n" \
- "*** underline=%d, colour_index=%d, esc=%d, underl=%d,\n" \
- "*** style=%d, posture=%d, canc=%d, cancellation=%d\n",
- font_height, weight, escapement, underline,
- font_colour_index, font_esc, font_underl,
- font_style, posture, font_canc, cancellation,
- )
- pos += 118
- if bord_block:
- pos += 8
- if patt_block:
- pos += 4
- fmla1 = data[pos:pos+sz1]
- pos += sz1
- if verbose and sz1:
- fprintf(self.logfile,
- "*** formula 1:\n",
- )
- dump_formula(bk, fmla1, sz1, bv, reldelta=0, verbose=1)
- fmla2 = data[pos:pos+sz2]
- pos += sz2
- assert pos == data_len
- if verbose and sz2:
- fprintf(self.logfile,
- "*** formula 2:\n",
- )
- dump_formula(bk, fmla2, sz2, bv, reldelta=0, verbose=1)
- elif rc == XL_DEFAULTROWHEIGHT:
- if data_len == 4:
- bits, self.default_row_height = unpack("<HH", data[:4])
- elif data_len == 2:
- self.default_row_height, = unpack("<H", data)
- bits = 0
- fprintf(self.logfile,
- "*** WARNING: DEFAULTROWHEIGHT record len is 2, " \
- "should be 4; assuming BIFF2 format\n")
- else:
- bits = 0
- fprintf(self.logfile,
- "*** WARNING: DEFAULTROWHEIGHT record len is %d, " \
- "should be 4; ignoring this record\n",
- data_len)
- self.default_row_height_mismatch = bits & 1
- self.default_row_hidden = (bits >> 1) & 1
- self.default_additional_space_above = (bits >> 2) & 1
- self.default_additional_space_below = (bits >> 3) & 1
- elif rc == XL_MERGEDCELLS:
- if not fmt_info: continue
- pos = unpack_cell_range_address_list_update_pos(
- self.merged_cells, data, 0, bv, addr_size=8)
- if verbose:
- fprintf(self.logfile,
- "MERGEDCELLS: %d ranges\n", int_floor_div(pos - 2, 8))
- assert pos == data_len, \
- "MERGEDCELLS: pos=%d data_len=%d" % (pos, data_len)
- elif rc == XL_WINDOW2:
- if bv >= 80:
- (options,
- self.first_visible_rowx, self.first_visible_colx,
- self.gridline_colour_index,
- self.cached_page_break_preview_mag_factor,
- self.cached_normal_view_mag_factor
- ) = unpack("<HHHHxxHH", data[:14])
- else: # BIFF3-7
- (options,
- self.first_visible_rowx, self.first_visible_colx,
- ) = unpack("<HHH", data[:6])
- self.gridline_colour_rgb = unpack("<BBB", data[6:9])
- self.gridline_colour_index = \
- nearest_colour_index(
- self.book.colour_map,
- self.gridline_colour_rgb,
- debug=0)
- self.cached_page_break_preview_mag_factor = 0 # default (60%)
- self.cached_normal_view_mag_factor = 0 # default (100%)
- # options -- Bit, Mask, Contents:
- # 0 0001H 0 = Show formula results 1 = Show formulas
- # 1 0002H 0 = Do not show grid lines 1 = Show grid lines
- # 2 0004H 0 = Do not show sheet headers 1 = Show sheet headers
- # 3 0008H 0 = Panes are not frozen 1 = Panes are frozen (freeze)
- # 4 0010H 0 = Show zero values as empty cells 1 = Show zero values
- # 5 0020H 0 = Manual grid line colour 1 = Automatic grid line colour
- # 6 0040H 0 = Columns from left to right 1 = Columns from right to left
- # 7 0080H 0 = Do not show outline symbols 1 = Show outline symbols
- # 8 0100H 0 = Keep splits if pane freeze is removed 1 = Remove splits if pane freeze is removed
- # 9 0200H 0 = Sheet not selected 1 = Sheet selected (BIFF5-BIFF8)
- # 10 0400H 0 = Sheet not visible 1 = Sheet visible (BIFF5-BIFF8)
- # 11 0800H 0 = Show in normal view 1 = Show in page break preview (BIFF8)
- # The freeze flag specifies, if a following PANE record (6.71) describes unfrozen or frozen panes.
- for attr, _unused_defval in _WINDOW2_options:
- setattr(self, attr, options & 1)
- options >>= 1
- # print "WINDOW2: visible=%d selected=%d" \
- # % (self.sheet_visible, self.sheet_selected)
- #### all of the following are for BIFF <= 4W
- elif bv <= 45:
- if rc == XL_FORMAT or rc == XL_FORMAT2:
- bk.handle_format(data, rc)
- elif rc == XL_FONT or rc == XL_FONT_B3B4:
- bk.handle_font(data)
- elif rc == XL_STYLE:
- if not self.book._xf_epilogue_done:
- self.book.xf_epilogue()
- bk.handle_style(data)
- elif rc == XL_PALETTE:
- bk.handle_palette(data)
- elif rc == XL_BUILTINFMTCOUNT:
- bk.handle_builtinfmtcount(data)
- elif rc == XL_XF4 or rc == XL_XF3 or rc == XL_XF2: #### N.B. not XL_XF
- bk.handle_xf(data)
- elif rc == XL_DATEMODE:
- bk.handle_datemode(data)
- elif rc == XL_CODEPAGE:
- bk.handle_codepage(data)
- elif rc == XL_FILEPASS:
- bk.handle_filepass(data)
- elif rc == XL_WRITEACCESS:
- bk.handle_writeaccess(data)
- elif rc == XL_IXFE:
- self._ixfe = local_unpack('<H', data)[0]
- elif rc == XL_NUMBER_B2:
- rowx, colx, cell_attr, d = local_unpack('<HH3sd', data)
- self_put_number_cell(rowx, colx, d, self.fixed_BIFF2_xfindex(cell_attr, rowx, colx))
- elif rc == XL_INTEGER:
- rowx, colx, cell_attr, d = local_unpack('<HH3sH', data)
- self_put_number_cell(rowx, colx, float(d), self.fixed_BIFF2_xfindex(cell_attr, rowx, colx))
- elif rc == XL_LABEL_B2:
- rowx, colx, cell_attr = local_unpack('<HH3s', data[0:7])
- strg = unpack_string(data, 7, bk.encoding or bk.derive_encoding(), lenlen=1)
- self_put_cell(rowx, colx, XL_CELL_TEXT, strg, self.fixed_BIFF2_xfindex(cell_attr, rowx, colx))
- elif rc == XL_BOOLERR_B2:
- rowx, colx, cell_attr, value, is_err = local_unpack('<HH3sBB', data)
- cellty = (XL_CELL_BOOLEAN, XL_CELL_ERROR)[is_err]
- # if DEBUG: print "XL_BOOLERR_B2", rowx, colx, cell_attr, value, is_err
- self.put_cell(rowx, colx, cellty, value, self.fixed_BIFF2_xfindex(cell_attr, rowx, colx))
- elif rc == XL_BLANK_B2:
- if not fmt_info: continue
- rowx, colx, cell_attr = local_unpack('<HH3s', data[:7])
- self_put_blank_cell(rowx, colx, self.fixed_BIFF2_xfindex(cell_attr, rowx, colx))
- elif rc == XL_EFONT:
- bk.handle_efont(data)
- elif rc == XL_ROW_B2:
- if not fmt_info: continue
- rowx, bits1, has_defaults = local_unpack('<H4xH2xB', data[0:11])
- if not(0 <= rowx < self.utter_max_rows):
- print("*** NOTE: ROW_B2 record has row index %d; " \
- "should have 0 <= rowx < %d -- record ignored!" \
- % (rowx, self.utter_max_rows), file=self.logfile)
- continue
- r = Rowinfo()
- r.height = bits1 & 0x7fff
- r.has_default_height = (bits1 >> 15) & 1
- r.outline_level = 0
- r.outline_group_starts_ends = 0
- r.hidden = 0
- r.height_mismatch = 0
- r.has_default_xf_index = has_defaults & 1
- r.additional_space_above = 0
- r.additional_space_below = 0
- if not r.has_default_xf_index:
- r.xf_index = -1
- elif data_len == 18:
- # Seems the XF index in the cell_attr is dodgy
- xfx = local_unpack('<H', data[16:18])[0]
- r.xf_index = self.fixed_BIFF2_xfindex(cell_attr=None, rowx=rowx, colx=-1, true_xfx=xfx)
- else:
- cell_attr = data[13:16]
- r.xf_index = self.fixed_BIFF2_xfindex(cell_attr, rowx, colx=-1)
- self.rowinfo_map[rowx] = r
- if 0 and r.xf_index > -1:
- fprintf(self.logfile,
- "**ROW %d %d %d\n",
- self.number, rowx, r.xf_index)
- if verbose_rows:
- print('ROW_B2', rowx, bits1, has_defaults, file=self.logfile)
- r.dump(self.logfile,
- header="--- sh #%d, rowx=%d ---" % (self.number, rowx))
- elif rc == XL_COLWIDTH: # BIFF2 only
- if not fmt_info: continue
- first_colx, last_colx, width\
- = local_unpack("<BBH", data[:4])
- if not(first_colx <= last_colx):
- print("*** NOTE: COLWIDTH record has first col index %d, last %d; " \
- "should have first <= last -- record ignored!" \
- % (first_colx, last_colx), file=self.logfile)
- continue
- for colx in range(first_colx, last_colx+1):
- if colx in self.colinfo_map:
- c = self.colinfo_map[colx]
- else:
- c = Colinfo()
- self.colinfo_map[colx] = c
- c.width = width
- if verbose:
- fprintf(
- self.logfile,
- "COLWIDTH sheet #%d cols %d-%d: wid=%d\n",
- self.number, first_colx, last_colx, width
- )
- elif rc == XL_COLUMNDEFAULT: # BIFF2 only
- if not fmt_info: continue
- first_colx, last_colx = local_unpack("<HH", data[:4])
- #### Warning OOo docs wrong; first_colx <= colx < last_colx
- if verbose:
- fprintf(
- self.logfile,
- "COLUMNDEFAULT sheet #%d cols in range(%d, %d)\n",
- self.number, first_colx, last_colx
- )
- if not(0 <= first_colx < last_colx <= 256):
- print("*** NOTE: COLUMNDEFAULT record has first col index %d, last %d; " \
- "should have 0 <= first < last <= 256" \
- % (first_colx, last_colx), file=self.logfile)
- last_colx = min(last_colx, 256)
- for colx in range(first_colx, last_colx):
- offset = 4 + 3 * (colx - first_colx)
- cell_attr = data[offset:offset+3]
- xf_index = self.fixed_BIFF2_xfindex(cell_attr, rowx=-1, colx=colx)
- if colx in self.colinfo_map:
- c = self.colinfo_map[colx]
- else:
- c = Colinfo()
- self.colinfo_map[colx] = c
- c.xf_index = xf_index
- if not eof_found:
- raise XLRDError("Sheet %d (%r) missing EOF record" \
- % (self.number, self.name))
- self.tidy_dimensions()
- bk._position = oldpos
- return 1
-
- def fixed_BIFF2_xfindex(self, cell_attr, rowx, colx, true_xfx=None):
- DEBUG = 0
- verbose = DEBUG or self.verbosity >= 2
- if self.biff_version == 21:
- if self._xf_index_to_xl_type_map:
- if true_xfx is not None:
- xfx = true_xfx
- else:
- xfx = cell_attr[0] & 0x3F
- if xfx == 0x3F:
- if self._ixfe is None:
- raise XLRDError("BIFF2 cell record has XF index 63 but no preceding IXFE record.")
- xfx = self._ixfe
- # OOo docs are capable of interpretation that each
- # cell record is preceded immediately by its own IXFE record.
- # Empirical evidence is that (sensibly) an IXFE record applies to all
- # following cell records until another IXFE comes along.
- return xfx
- # Have either Excel 2.0, or broken 2.1 w/o XF records -- same effect.
- self.biff_version = self.book.biff_version = 20
- #### check that XF slot in cell_attr is zero
- xfx_slot = cell_attr[0] & 0x3F
- assert xfx_slot == 0
- xfx = self._cell_attr_to_xfx.get(cell_attr)
- if xfx is not None:
- return xfx
- if verbose:
- fprintf(self.logfile, "New cell_attr %r at (%r, %r)\n", cell_attr, rowx, colx)
- book = self.book
- xf = self.fake_XF_from_BIFF20_cell_attr(cell_attr)
- xfx = len(book.xf_list)
- xf.xf_index = xfx
- book.xf_list.append(xf)
- if verbose:
- xf.dump(self.logfile, header="=== Faked XF %d ===" % xfx, footer="======")
- if xf.format_key not in book.format_map:
- msg = "ERROR *** XF[%d] unknown format key (%d, 0x%04x)\n"
- fprintf(self.logfile, msg,
- xf.xf_index, xf.format_key, xf.format_key)
- fmt = Format(xf.format_key, FUN, "General")
- book.format_map[xf.format_key] = fmt
- while len(book.format_list) <= xf.format_key:
- book.format_list.append(fmt)
- cellty_from_fmtty = {
- FNU: XL_CELL_NUMBER,
- FUN: XL_CELL_NUMBER,
- FGE: XL_CELL_NUMBER,
- FDT: XL_CELL_DATE,
- FTX: XL_CELL_NUMBER, # Yes, a number can be formatted as text.
- }
- fmt = book.format_map[xf.format_key]
- cellty = cellty_from_fmtty[fmt.type]
- self._xf_index_to_xl_type_map[xf.xf_index] = cellty
- self._cell_attr_to_xfx[cell_attr] = xfx
- return xfx
-
- def fake_XF_from_BIFF20_cell_attr(self, cell_attr):
- from .formatting import XF, XFAlignment, XFBorder, XFBackground, XFProtection
- xf = XF()
- xf.alignment = XFAlignment()
- xf.alignment.indent_level = 0
- xf.alignment.shrink_to_fit = 0
- xf.alignment.text_direction = 0
- xf.border = XFBorder()
- xf.border.diag_up = 0
- xf.border.diag_down = 0
- xf.border.diag_colour_index = 0
- xf.border.diag_line_style = 0 # no line
- xf.background = XFBackground()
- xf.protection = XFProtection()
- (prot_bits, font_and_format, halign_etc) = unpack('<BBB', cell_attr)
- xf.format_key = font_and_format & 0x3F
- xf.font_index = (font_and_format & 0xC0) >> 6
- upkbits(xf.protection, prot_bits, (
- (6, 0x40, 'cell_locked'),
- (7, 0x80, 'formula_hidden'),
- ))
- xf.alignment.hor_align = halign_etc & 0x07
- for mask, side in ((0x08, 'left'), (0x10, 'right'), (0x20, 'top'), (0x40, 'bottom')):
- if halign_etc & mask:
- colour_index, line_style = 8, 1 # black, thin
- else:
- colour_index, line_style = 0, 0 # none, none
- setattr(xf.border, side + '_colour_index', colour_index)
- setattr(xf.border, side + '_line_style', line_style)
- bg = xf.background
- if halign_etc & 0x80:
- bg.fill_pattern = 17
- else:
- bg.fill_pattern = 0
- bg.background_colour_index = 9 # white
- bg.pattern_colour_index = 8 # black
- xf.parent_style_index = 0 # ???????????
- xf.alignment.vert_align = 2 # bottom
- xf.alignment.rotation = 0
- for attr_stem in ("format", "font", "alignment", "border", \
- "background", "protection"):
- attr = "_%s_flag" % attr_stem
- setattr(xf, attr, 1)
- return xf
-
- def req_fmt_info(self):
- if not self.formatting_info:
- raise XLRDError("Feature requires open_workbook(..., formatting_info=True)")
-
- # Determine column display width.
- # - New in version 0.6.1
- #
- # @param colx Index of the queried column, range 0 to 255.
- # Note that it is possible to find out the width that will be used to display
- # columns with no cell information e.g. column IV (colx=255).
- # @return The column width that will be used for displaying
- # the given column by Excel, in units of 1/256th of the width of a
- # standard character (the digit zero in the first font).
-
- def computed_column_width(self, colx):
- self.req_fmt_info()
- if self.biff_version >= 80:
- colinfo = self.colinfo_map.get(colx, None)
- if colinfo is not None:
- return colinfo.width
- if self.standardwidth is not None:
- return self.standardwidth
- elif self.biff_version >= 40:
- if self.gcw[colx]:
- if self.standardwidth is not None:
- return self.standardwidth
- else:
- colinfo = self.colinfo_map.get(colx, None)
- if colinfo is not None:
- return colinfo.width
- elif self.biff_version == 30:
- colinfo = self.colinfo_map.get(colx, None)
- if colinfo is not None:
- return colinfo.width
- # All roads lead to Rome and the DEFCOLWIDTH ...
- if self.defcolwidth is not None:
- return self.defcolwidth * 256
- return 8 * 256 # 8 is what Excel puts in a DEFCOLWIDTH record
-
- def handle_msodrawingetc(self, recid, data_len, data):
- if not OBJ_MSO_DEBUG:
- return
- DEBUG = 1
- if self.biff_version < 80:
- return
- o = MSODrawing()
- pos = 0
- while pos < data_len:
- tmp, fbt, cb = unpack('<HHI', data[pos:pos+8])
- ver = tmp & 0xF
- inst = (tmp >> 4) & 0xFFF
- if ver == 0xF:
- ndb = 0 # container
- else:
- ndb = cb
- if DEBUG:
- hex_char_dump(data, pos, ndb + 8, base=0, fout=self.logfile)
- fprintf(self.logfile,
- "fbt:0x%04X inst:%d ver:0x%X cb:%d (0x%04X)\n",
- fbt, inst, ver, cb, cb)
- if fbt == 0xF010: # Client Anchor
- assert ndb == 18
- (o.anchor_unk,
- o.anchor_colx_lo, o.anchor_rowx_lo,
- o.anchor_colx_hi, o.anchor_rowx_hi) = unpack('<Hiiii', data[pos+8:pos+8+ndb])
- elif fbt == 0xF011: # Client Data
- # must be followed by an OBJ record
- assert cb == 0
- assert pos + 8 == data_len
- else:
- pass
- pos += ndb + 8
- else:
- # didn't break out of while loop
- assert pos == data_len
- if DEBUG:
- o.dump(self.logfile, header="=== MSODrawing ===", footer= " ")
-
-
- def handle_obj(self, data):
- if not OBJ_MSO_DEBUG:
- return
- DEBUG = 1
- if self.biff_version < 80:
- return
- o = MSObj()
- data_len = len(data)
- pos = 0
- if DEBUG:
- fprintf(self.logfile, "... OBJ record ...\n")
- while pos < data_len:
- ft, cb = unpack('<HH', data[pos:pos+4])
- if DEBUG:
- hex_char_dump(data, pos, cb, base=0, fout=self.logfile)
- if ft == 0x15: # ftCmo ... s/b first
- assert pos == 0
- o.type, o.id, option_flags = unpack('<HHH', data[pos+4:pos+10])
- upkbits(o, option_flags, (
- ( 0, 0x0001, 'locked'),
- ( 4, 0x0010, 'printable'),
- ( 8, 0x0100, 'autofilter'), # not documented in Excel 97 dev kit
- ( 9, 0x0200, 'scrollbar_flag'), # not documented in Excel 97 dev kit
- (13, 0x2000, 'autofill'),
- (14, 0x4000, 'autoline'),
- ))
- elif ft == 0x00:
- assert cb == 0
- assert pos + 4 == data_len
- elif ft == 0x0C: # Scrollbar
- values = unpack('<5H', data[pos+8:pos+18])
- for value, tag in zip(values, ('value', 'min', 'max', 'inc', 'page')):
- setattr(o, 'scrollbar_' + tag, value)
- elif ft == 0x0D: # "Notes structure" [used for cell comments]
- pass ############## not documented in Excel 97 dev kit
- elif ft == 0x13: # list box data
- if o.autofilter: # non standard exit. NOT documented
- break
- else:
- pass
- pos += cb + 4
- else:
- # didn't break out of while loop
- assert pos == data_len
- if DEBUG:
- o.dump(self.logfile, header="=== MSOBj ===", footer= " ")
-
- def handle_note(self, data):
- if not OBJ_MSO_DEBUG:
- return
- DEBUG = 1
- if self.biff_version < 80:
- return
- if DEBUG:
- fprintf(self.logfile, '... NOTE record ...\n')
- hex_char_dump(data, 0, len(data), base=0, fout=self.logfile)
- o = MSNote()
- data_len = len(data)
- o.rowx, o.colx, option_flags, o.object_id = unpack('<4H', data[:8])
- o.show = (option_flags >> 1) & 1
- # Docs say NULL [sic] bytes padding between string count and string data
- # to ensure that string is word-aligned. Appears to be nonsense.
- # There also seems to be a random(?) byte after the string (not counted in the
- # string length.
- o.original_author, endpos = unpack_unicode_update_pos(data, 8, lenlen=2)
- assert endpos == data_len - 1
- o.last_byte = data[-1]
- if DEBUG:
- o.dump(self.logfile, header="=== MSNote ===", footer= " ")
-
- def handle_txo(self, data):
- if not OBJ_MSO_DEBUG:
- return
- DEBUG = 1
- if self.biff_version < 80:
- return
- o = MSTxo()
- data_len = len(data)
- option_flags, o.rot, cchText, cbRuns = unpack('<HH6xHH4x', data)
- upkbits(o, option_flags, (
- (3, 0x000E, 'horz_align'),
- (6, 0x0070, 'vert_align'),
- (9, 0x0200, 'lock_text'),
- ))
- rc2, data2_len, data2 = self.book.get_record_parts()
- assert rc2 == XL_CONTINUE
- o.text, endpos = unpack_unicode_update_pos(data2, 0, known_len=cchText)
- assert endpos == data2_len
- rc3, data3_len, data3 = self.book.get_record_parts()
- assert rc3 == XL_CONTINUE
- # ignore the formatting runs for the moment
- if DEBUG:
- o.dump(self.logfile, header="=== MSTxo ===", footer= " ")
-
- def handle_feat11(self, data):
- if not OBJ_MSO_DEBUG:
- return
- # rt: Record type; this matches the BIFF rt in the first two bytes of the record; =0872h
- # grbitFrt: FRT cell reference flag (see table below for details)
- # Ref0: Range reference to a worksheet cell region if grbitFrt=1 (bitFrtRef). Otherwise blank.
- # isf: Shared feature type index =5 for Table
- # fHdr: =0 since this is for feat not feat header
- # reserved0: Reserved for future use =0 for Table
- # cref: Count of ref ranges this feature is on
- # cbFeatData: Count of byte for the current feature data.
- # reserved1: =0 currently not used
- # Ref1: Repeat of Ref0. UNDOCUMENTED
- rt, grbitFrt, Ref0, isf, fHdr, reserved0, cref, cbFeatData, reserved1, Ref1 = unpack('<HH8sHBiHiH8s', data[0:35])
- assert reserved0 == 0
- assert reserved1 == 0
- assert isf == 5
- assert rt == 0x872
- assert fHdr == 0
- assert Ref1 == Ref0
- print("FEAT11: grbitFrt=%d Ref0=%r cref=%d cbFeatData=%d" % (grbitFrt, Ref0, cref, cbFeatData))
- # lt: Table data source type:
- # =0 for Excel Worksheet Table =1 for read-write SharePoint linked List
- # =2 for XML mapper Table =3 for Query Table
- # idList: The ID of the Table (unique per worksheet)
- # crwHeader: How many header/title rows the Table has at the top
- # crwTotals: How many total rows the Table has at the bottom
- # idFieldNext: Next id to try when assigning a unique id to a new field
- # cbFSData: The size of the Fixed Data portion of the Table data structure.
- # rupBuild: the rupBuild that generated the record
- # unusedShort: UNUSED short that can be used later. The value is reserved during round-tripping.
- # listFlags: Collection of bit flags: (see listFlags' bit setting table below for detail.)
- # lPosStmCache: Table data stream position of cached data
- # cbStmCache: Count of bytes of cached data
- # cchStmCache: Count of characters of uncompressed cached data in the stream
- # lem: Table edit mode (see List (Table) Editing Mode (lem) setting table below for details.)
- # rgbHashParam: Hash value for SharePoint Table
- # cchName: Count of characters in the Table name string rgbName
- (lt, idList, crwHeader, crwTotals, idFieldNext, cbFSData,
- rupBuild, unusedShort, listFlags, lPosStmCache, cbStmCache,
- cchStmCache, lem, rgbHashParam, cchName) = unpack('<iiiiiiHHiiiii16sH', data[35:35+66])
- print("lt=%d idList=%d crwHeader=%d crwTotals=%d idFieldNext=%d cbFSData=%d\n"\
- "rupBuild=%d unusedShort=%d listFlags=%04X lPosStmCache=%d cbStmCache=%d\n"\
- "cchStmCache=%d lem=%d rgbHashParam=%r cchName=%d" % (
- lt, idList, crwHeader, crwTotals, idFieldNext, cbFSData,
- rupBuild, unusedShort,listFlags, lPosStmCache, cbStmCache,
- cchStmCache, lem, rgbHashParam, cchName))
-
-class MSODrawing(BaseObject):
- pass
-
-class MSObj(BaseObject):
- pass
-
-class MSTxo(BaseObject):
- pass
-
-class MSNote(BaseObject):
- pass
-
-# === helpers ===
-
-def unpack_RK(rk_str):
- #(to_py3): flags = ord(rk_str[0])
- flags = rk_str[0]
- if flags & 2:
- # There's a SIGNED 30-bit integer in there!
- i, = unpack('<i', rk_str)
- i >>= 2 # div by 4 to drop the 2 flag bits
- if flags & 1:
- return i / 100.0
- return float(i)
- else:
- # It's the most significant 30 bits of an IEEE 754 64-bit FP number
- # (to_py3): replaced b'\0\0\0\0' + chr(flags & 252) + rk_str[1:4]
- _bytes = array('B', b'\0\0\0\0')
- _bytes.append(flags & 252)
- _bytes.extend(rk_str[1:4])
- d, = unpack('<d', _bytes)
- if flags & 1:
- d = d / 100.
- return d
-
-##### =============== Cell ======================================== #####
-
-cellty_from_fmtty = {
- FNU: XL_CELL_NUMBER,
- FUN: XL_CELL_NUMBER,
- FGE: XL_CELL_NUMBER,
- FDT: XL_CELL_DATE,
- FTX: XL_CELL_NUMBER, # Yes, a number can be formatted as text.
- }
-
-ctype_text = {
- XL_CELL_EMPTY: 'empty',
- XL_CELL_TEXT: 'text',
- XL_CELL_NUMBER: 'number',
- XL_CELL_DATE: 'xldate',
- XL_CELL_BOOLEAN: 'bool',
- XL_CELL_ERROR: 'error',
- XL_CELL_BLANK: 'blank',
- }
-
-# Contains the data for one cell -> see XFCell() class in the xfcell module.
-class Cell(XFCell):
- def __repr__(self):
- if not self.has_xf:
- return "%s:%r" % (ctype_text[self.ctype], self.value)
- else:
- return "%s:%r (XF:%r)" % (ctype_text[self.ctype], self.value, self.xf_index)
-
-# There is one and only one instance of an empty cell -- it's a singleton. This is it.
-# You may use a test like "acell is empty_cell".
-empty_cell = Cell(XL_CELL_EMPTY, '')
-
-##### =============== Colinfo and Rowinfo ============================== #####
-
-
-# Width and default formatting information that applies to one or
-# more columns in a sheet. Derived from COLINFO records.
-#
-#
-# Here is the default hierarchy for width, according to the OOo docs:
-#
-# In BIFF3, if a COLINFO record is missing for a column,
-# the width specified in the record DEFCOLWIDTH is used instead.
-#
-# In BIFF4-BIFF7, the width set in this [COLINFO] record is only used,
-# if the corresponding bit for this column is cleared in the GCW
-# record, otherwise the column width set in the DEFCOLWIDTH record
-# is used (the STANDARDWIDTH record is always ignored in this case [see footnote!]).
-#
-# In BIFF8, if a COLINFO record is missing for a column,
-# the width specified in the record STANDARDWIDTH is used.
-# If this [STANDARDWIDTH] record is also missing,
-# the column width of the record DEFCOLWIDTH is used instead.
-#
-# Footnote: The docs on the GCW record say this:
-#
-# If a bit is set, the corresponding column uses the width set in the STANDARDWIDTH
-# record. If a bit is cleared, the corresponding column uses the width set in the
-# COLINFO record for this column.
-#
-# If a bit is set, and the worksheet does not contain the STANDARDWIDTH record, or if
-# the bit is cleared, and the worksheet does not contain the COLINFO record, the DEFCOLWIDTH
-# record of the worksheet will be used instead.
-#
-# At the moment (2007-01-17) xlrd is going with the GCW version of the story.
-# Reference to the source may be useful: see the computed_column_width(colx) method
-# of the Sheet class.
-# - New in version 0.6.1
-
-class Colinfo(BaseObject):
- # Width of the column in 1/256 of the width of the zero character,
- # using default font (first FONT record in the file).
- width = 0
- # XF index to be used for formatting empty cells.
- xf_index = -1
- # 1 = column is hidden
- hidden = 0
- # Value of a 1-bit flag whose purpose is unknown
- # but is often seen set to 1
- bit1_flag = 0
- # Outline level of the column, in range(7).
- # (0 = no outline)
- outline_level = 0
- # 1 = column is collapsed
- collapsed = 0
-
-# Height and default formatting information that applies to a row in a sheet.
-# Derived from ROW records.
-# - New in version 0.6.1
-
-class Rowinfo(BaseObject):
- ##
- # Height of the row, in twips. One twip == 1/20 of a point
- height = 0
- ##
- # 0 = Row has custom height; 1 = Row has default height
- has_default_height = 0
- ##
- # Outline level of the row
- outline_level = 0
- ##
- # 1 = Outline group starts or ends here (depending on where the
- # outline buttons are located, see WSBOOL record [TODO ??]),
- # <i>and</i> is collapsed
- outline_group_starts_ends = 0
- ##
- # 1 = Row is hidden (manually, or by a filter or outline group)
- hidden = 0
- ##
- # 1 = Row height and default font height do not match
- height_mismatch = 0
- ##
- # 1 = the xf_index attribute is usable; 0 = ignore it
- has_default_xf_index = 0
- ##
- # Index to default XF record for empty cells in this row.
- # Don't use this if has_default_xf_index == 0.
- xf_index = -9999
- ##
- # This flag is set, if the upper border of at least one cell in this row
- # or if the lower border of at least one cell in the row above is
- # formatted with a thick line style. Thin and medium line styles are not
- # taken into account.
- additional_space_above = 0
- ##
- # This flag is set, if the lower border of at least one cell in this row
- # or if the upper border of at least one cell in the row below is
- # formatted with a medium or thick line style. Thin line styles are not
- # taken into account.
- additional_space_below = 0
diff --git a/tablib/packages/xlrd3/xfcell.py b/tablib/packages/xlrd3/xfcell.py
deleted file mode 100644
index 213b4bd..0000000
--- a/tablib/packages/xlrd3/xfcell.py
+++ /dev/null
@@ -1,276 +0,0 @@
-# Author: mozman <mozman@gmx.at>
-# Purpose: xfcell -- cell with convenient xf function
-# Created: 04.12.2010
-# Copyright (C) 2010, Manfred Moitzi
-# License: BSD-style licence
-
-"""
-The XFCell() object contains the data for one cell.
-
-WARNING: You don't call this class yourself. You access Cell objects
-via methods of the Sheet object(s) that you found in the Book object that
-was returned when you called xlrd.open_workbook("myfile.xls").
-
-Cell objects have four attributes: `ctype` is an int, `value` (which depends
-on `ctype`), `xf_index` and `sheet`, a reference to the containing sheet. If
-**formatting_info** is not enabled when the workbook is opened, xf_index will
-be **None**.
-
-The following table describes the types of cells and how their values
-are represented in Python.
-
-=============== ===== ============ ==========================================
-Type symbol Const Python value Note
-=============== ===== ============ ==========================================
-XL_CELL_EMPTY 0 ""
-XL_CELL_TEXT 1 str
-XL_CELL_NUMBER 2 float
-XL_CELL_DATE 3 float
-XL_CELL_BOOLEAN 4 int 1 means TRUE, 0 means FALSE
-XL_CELL_ERROR 5 int representing internal Excel codes; for a
- text representation, refer to the supplied
- dictionary error_text_from_code
-XL_CELL_BLANK 6 "" this type will appear only when
- open_workbook(..., formatting_info=True)
- is used.
-=============== ===== ============ ==========================================
-"""
-
-import datetime
-
-from .xldate import xldate_as_tuple
-from .biffh import XL_CELL_DATE, BaseObject
-
-class XFCell(BaseObject):
- """ Extended Cell() class with convenient methods for easy access of cell
- properties.
- """
- __slots__ = ['sheet', 'ctype', 'value', 'xf']
-
- def __init__(self, ctype, value, xf_index=None, sheet=None):
- self.sheet = sheet
- self.ctype = ctype
- self.value = value
-
- if xf_index is not None:
- self.xf = self.book.xf_list[xf_index]
- else:
- self.xf = None
-
- @property
- def book(self):
- return self.sheet.book
-
- @property
- def has_xf(self):
- return (self.xf is not None)
-
- @property
- def xf_index(self):
- if self.has_xf:
- return self.xf.xf_index
- else:
- return None
-
- @property
- def parent_style(self):
- return self.book.xf_list[self.xf.parent_style_index]
-
- @property
- def is_datetime(self):
- return self.ctype == XL_CELL_DATE
-
- @property
- def has_date(self):
- if self.is_datetime:
- return self.value > 1.
- return False
-
- def get_color(self, index):
- return self.book.colour_map[index]
-
- def datetime(self):
- """ Returns a datetime.datetime object if cell type is XL_CELL_DATE
- else raises a TypeError, and raises ValueError if the the cell has
- not date value (only time value is present).
- """
- if self.is_datetime:
- if self.has_date:
- date = xldate_as_tuple(self.value, self.book.datemode)
- return datetime.datetime(*date)
- else:
- raise ValueError("Cell has no date value.")
- else:
- raise TypeError("Cell is not a XL_CELL_DATE.")
-
- def date(self):
- """ Returns a datetime.date object if cell type is XL_CELL_DATE
- else raises a **TypeError**. Raises **ValueError** if the cell
- doesn't have a date value (only time value is present).
- """
- dt = self.datetime()
- return dt.date()
-
- def time(self):
- """ Returns a datetime.time object if cell type is XL_CELL_DATE else
- raises a TypeError.
- """
- if self.is_datetime:
- date = xldate_as_tuple(self.value, self.book.datemode)
- return datetime.time(date[3], date[4], date[5])
- else:
- raise TypeError("Cell is not a XL_CELL_DATE.")
-
- #
- # access the XFBackground() class
- #
-
- @property
- def background(self):
- if self.xf.is_style and \
- self.xf._background_flag == 0:
- return self.xf.background
- elif self.xf._background_flag:
- return self.xf.background
- else:
- return self.parent_style.background
-
- def background_color(self):
- """ Get cell background-color as 3-tuple. """
- color_index = self.xf.background.background_colour_index
- return self.get_color(color_index)
-
- def fill_pattern(self):
- return self.xf.background.fill_pattern
-
- def pattern_color(self):
- color_index = self.xf.background.pattern_colour_index
- return self.get_color(color_index)
-
- #
- # access the Font() class
- #
-
- @property
- def font_index(self):
- if self.xf.is_style and \
- self.xf._font_flag == 0:
- return self.xf.font_index
- elif self.xf._font_flag:
- return self.xf.font_index
- else:
- return self.parent_style.font_index
-
- @property
- def font(self):
- """ Get the Font() class. """
- return self.book.font_list[self.xf.font_index]
-
- def font_color(self):
- """ Get cell foreground-color as 3-tuple. """
- return self.get_color(self.font.colour_index)
-
- #
- # access the Format() class
- #
-
- @property
- def format_key(self):
- if self.xf.is_style and \
- self.xf._format_flag == 0:
- return self.xf.format_key
- elif self.xf._format_flag:
- return self.xf.format_key
- else:
- return self.parent_style.format_key
-
- @property
- def format(self):
- """ Get the Format() class. """
- return self.book.format_map[self.format_key]
-
- def format_str(self):
- """ Get the associated 'format_str'. """
- return self.format.format_str
-
- #
- # access the XFAligment() class
- #
-
- @property
- def alignment(self):
- if self.xf.is_style and \
- self.xf._alignment_flag == 0:
- return self.xf.alignment
- elif self.xf._alignment_flag:
- return self.xf.alignment
- else:
- return self.parent_style.alignment
-
- #
- # access the XFBorder() class
- #
-
- @property
- def border(self):
- if self.xf.is_style and \
- self.xf._border_flag == 0:
- return self.xf.border
- elif self.xf._border_flag:
- return self.xf.border
- else:
- return self.parent_style.border
-
- def bordercolors(self):
- """ Get border color as dict of rgb-color-tuples. """
- border = self.border
- return {
- 'top': self.get_color(border.top_colour_index),
- 'bottom': self.get_color(border.bottom_colour_index),
- 'left': self.get_color(border.left_colour_index),
- 'right': self.get_color(border.right_colour_index),
- 'diag': self.get_color(border.diag_colour_index),
- }
-
- def borderstyles(self):
- """ Get border styles as dict of ints. """
- border = self.border
- return {
- 'top': border.top_line_style,
- 'bottom': border.bottom_line_style,
- 'left': border.left_line_style,
- 'right': border.right_line_style,
- 'diag': border.diag_line_style,
- }
-
- @property
- def has_up_diag(self):
- """ Draw a line across the cell from bottom left to top right. """
- return bool(self.border.diag_up)
-
- @property
- def has_down_diag(self):
- """ Draw a line across the cell from top left to bottom right. """
- return bool(self.border.diag_down)
-
- #
- # access the XFProtection() class
- #
-
- @property
- def protection(self):
- if self.xf.is_style and \
- self.xf._protection_flag == 0:
- return self.xf.protection
- elif self.xf._protection_flag:
- return self.xf.protection
- else:
- return self.parent_style.protection
-
- @property
- def is_cell_locked(self):
- return bool(self.protection.cell_locked)
-
- @property
- def is_formula_hidden(self):
- return bool(self.protection.cell_locked)
diff --git a/tablib/packages/xlrd3/xfconst.py b/tablib/packages/xlrd3/xfconst.py
deleted file mode 100644
index 24f6533..0000000
--- a/tablib/packages/xlrd3/xfconst.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# Author: mozman <mozman@gmx.at>
-# Purpose: xfconst -- xf constants
-# Created: 05.12.2010
-# Copyright (C) 2010, Manfred Moitzi
-# License: BSD-style licence
-
-# excelfileformat section 5.115.1 pg. 219
-HOR_ALIGN_GENERAL = 0
-HOR_ALIGN_LEFT = 1
-HOR_ALIGN_CENTRED = 2
-HOR_ALIGN_RIGHT = 3
-HOR_ALIGN_FILLED = 4
-HOR_ALIGN_JUSTIFIED = 5
-HOR_ALIGN_CENTRED_ACROSS_SELECTION = 6
-HOR_ALIGN_DISTRIBUTED = 7
-
-# excelfileformat section 5.115.1 pg. 220
-VERT_ALIGN_TOP = 0
-VERT_ALIGN_CENTRED = 1
-VERT_ALIGN_BOTTOM = 2
-VERT_ALIGN_JUSTIFIED = 3
-VERT_ALIGN_DISTRIBUTED = 4
-
-# excelfileformat section 5.115.1 pg. 220
-ORIENTATION_NONE = 0
-ORIENTATION_STACKED = 1
-ORIENTATION_90_COUNTERCLOCKWISE = 2
-ORIENTATION_90_CLOCKWISE = 3
-
-# excelfileformat section 5.115.1 pg. 220
-ROTATION_NONE = 0
-ROTATION_STACKED = 255
-# other values:
-# Value Description
-# ======= =================================
-# 1-90 1 to 90 degrees counterclockwise
-# 91-180 1 to 90 degrees clockwise
-
-# excelfileformat section 2.5.11 Line Styles for Cell Borders pg. 24
-LS_NOLINE = 0
-
-# solid line
-LS_THIN = 1
-
-# solid line
-LS_MEDIUM = 2
-
-# - - - - - - - - -
-LS_DASHED = 3
-
-# .................
-LS_DOTTED = 4
-
-# solid line
-LS_THICK = 5
-
-# =================
-LS_DOUBLE = 6
-
-# very thin dotted
-LS_HAIR = 7
-
-# - - - - - - - - -
-LS_MEDIUM_DASHED = 8
-
-# - . - . - . - . -
-LS_THIN_DASH_DOTTED = 9
-
-# - . - . - . - . -
-LS_MEDIUM_DASH_DOTTED = 10
-
-# - .. - .. - .. - .. -
-LS_THIN_DASH_DOT_DOTTED = 11
-
-# - .. - .. - .. - .. -
-LS_MEDIUM_DASH_DOT_DOTTED = 12
-
-# \\\ . \\\ . \\\ . \\\ . \\\
-LS_SLANTED_MEDIUM_DASH_DOTTED = 13
-
-
-
-
-
diff --git a/tablib/packages/xlrd3/xldate.py b/tablib/packages/xlrd3/xldate.py
deleted file mode 100644
index 634709d..0000000
--- a/tablib/packages/xlrd3/xldate.py
+++ /dev/null
@@ -1,167 +0,0 @@
-# No part of the content of this file was derived from the works of David Giffin.
-#
-# Copyright © 2005-2008 Stephen John Machin, Lingfo Pty Ltd
-# This module is part of the xlrd3 package, which is released under a
-# BSD-style licence.
-#
-# Provides function(s) for dealing with Microsoft Excel ™ dates.
-#
-# 2008-10-18 SJM Fix bug in xldate_from_date_tuple (affected some years after 2099)
-#
-# The conversion from days to (year, month, day) starts with
-# an integral "julian day number" aka JDN.
-# FWIW, JDN 0 corresponds to noon on Monday November 24 in Gregorian year -4713.
-# More importantly:
-# Noon on Gregorian 1900-03-01 (day 61 in the 1900-based system) is JDN 2415080.0
-# Noon on Gregorian 1904-01-02 (day 1 in the 1904-based system) is JDN 2416482.0
-
-def ifd(x, y):
- return divmod(x, y)[0]
-
-_JDN_delta = (2415080 - 61, 2416482 - 1)
-assert _JDN_delta[1] - _JDN_delta[0] == 1462
-
-class XLDateError(ValueError): pass
-
-class XLDateNegative(XLDateError): pass
-class XLDateAmbiguous(XLDateError): pass
-class XLDateTooLarge(XLDateError): pass
-class XLDateBadDatemode(XLDateError): pass
-class XLDateBadTuple(XLDateError): pass
-
-_XLDAYS_TOO_LARGE = (2958466, 2958466 - 1462) # This is equivalent to 10000-01-01
-
-# Convert an Excel number (presumed to represent a date, a datetime or a time) into
-# a tuple suitable for feeding to datetime or mx.DateTime constructors.
-# @param xldate The Excel number
-# @param datemode 0: 1900-based, 1: 1904-based.
-# <br>WARNING: when using this function to
-# interpret the contents of a workbook, you should pass in the Book.datemode
-# attribute of that workbook. Whether
-# the workbook has ever been anywhere near a Macintosh is irrelevant.
-# @return Gregorian (year, month, day, hour, minute, nearest_second).
-# <br>Special case: if 0.0 <= xldate < 1.0, it is assumed to represent a time;
-# (0, 0, 0, hour, minute, second) will be returned.
-# <br>Note: 1904-01-01 is not regarded as a valid date in the datemode 1 system; its "serial number"
-# is zero.
-# @throws XLDateNegative xldate < 0.00
-# @throws XLDateAmbiguous The 1900 leap-year problem (datemode == 0 and 1.0 <= xldate < 61.0)
-# @throws XLDateTooLarge Gregorian year 10000 or later
-# @throws XLDateBadDatemode datemode arg is neither 0 nor 1
-# @throws XLDateError Covers the 4 specific errors
-
-def xldate_as_tuple(xldate, datemode):
- if datemode not in (0, 1):
- raise XLDateBadDatemode(datemode)
- if xldate == 0.00:
- return (0, 0, 0, 0, 0, 0)
- if xldate < 0.00:
- raise XLDateNegative(xldate)
- xldays = int(xldate)
- frac = xldate - xldays
- seconds = int(round(frac * 86400.0))
- assert 0 <= seconds <= 86400
- if seconds == 86400:
- hour = minute = second = 0
- xldays += 1
- else:
- # second = seconds % 60; minutes = seconds // 60
- minutes, second = divmod(seconds, 60)
- # minute = minutes % 60; hour = minutes // 60
- hour, minute = divmod(minutes, 60)
- if xldays >= _XLDAYS_TOO_LARGE[datemode]:
- raise XLDateTooLarge(xldate)
-
- if xldays == 0:
- return (0, 0, 0, hour, minute, second)
-
- if xldays < 61 and datemode == 0:
- raise XLDateAmbiguous(xldate)
-
- jdn = xldays + _JDN_delta[datemode]
- yreg = (ifd(ifd(jdn * 4 + 274277, 146097) * 3, 4) + jdn + 1363) * 4 + 3
- mp = ifd(yreg % 1461, 4) * 535 + 333
- d = ifd(mp % 16384, 535) + 1
- # mp /= 16384
- mp >>= 14
- if mp >= 10:
- return (ifd(yreg, 1461) - 4715, mp - 9, d, hour, minute, second)
- else:
- return (ifd(yreg, 1461) - 4716, mp + 3, d, hour, minute, second)
-
-# === conversions from date/time to xl numbers
-
-def _leap(y):
- if y % 4: return 0
- if y % 100: return 1
- if y % 400: return 0
- return 1
-
-_days_in_month = (None, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
-
-# Convert a date tuple (year, month, day) to an Excel date.
-# @param year Gregorian year.
-# @param month 1 <= month <= 12
-# @param day 1 <= day <= last day of that (year, month)
-# @param datemode 0: 1900-based, 1: 1904-based.
-# @throws XLDateAmbiguous The 1900 leap-year problem (datemode == 0 and 1.0 <= xldate < 61.0)
-# @throws XLDateBadDatemode datemode arg is neither 0 nor 1
-# @throws XLDateBadTuple (year, month, day) is too early/late or has invalid component(s)
-# @throws XLDateError Covers the specific errors
-
-def xldate_from_date_tuple(datetuple, datemode):
-
- (year, month, day) = datetuple
- if datemode not in (0, 1):
- raise XLDateBadDatemode(datemode)
-
- if year == 0 and month == 0 and day == 0:
- return 0.00
-
- if not (1900 <= year <= 9999):
- raise XLDateBadTuple("Invalid year: %r" % ((year, month, day),))
- if not (1 <= month <= 12):
- raise XLDateBadTuple("Invalid month: %r" % ((year, month, day),))
- if day < 1 \
- or (day > _days_in_month[month] and not(day == 29 and month == 2 and _leap(year))):
- raise XLDateBadTuple("Invalid day: %r" % ((year, month, day),))
-
- Yp = year + 4716
- M = month
- if M <= 2:
- Yp = Yp - 1
- Mp = M + 9
- else:
- Mp = M - 3
- jdn = ifd(1461 * Yp, 4) + ifd(979 * Mp + 16, 32) + \
- day - 1364 - ifd(ifd(Yp + 184, 100) * 3, 4)
- xldays = jdn - _JDN_delta[datemode]
- if xldays <= 0:
- raise XLDateBadTuple("Invalid (year, month, day): %r" % ((year, month, day),))
- if xldays < 61 and datemode == 0:
- raise XLDateAmbiguous("Before 1900-03-01: %r" % ((year, month, day),))
- return float(xldays)
-
-# Convert a time tuple (hour, minute, second) to an Excel "date" value (fraction of a day).
-# @param hour 0 <= hour < 24
-# @param minute 0 <= minute < 60
-# @param second 0 <= second < 60
-# @throws XLDateBadTuple Out-of-range hour, minute, or second
-
-def xldate_from_time_tuple(timetuple):
- (hour, minute, second) = timetuple
- if 0 <= hour < 24 and 0 <= minute < 60 and 0 <= second < 60:
- return ((second / 60.0 + minute) / 60.0 + hour) / 24.0
- raise XLDateBadTuple("Invalid (hour, minute, second): %r" % ((hour, minute, second),))
-
-# Convert a datetime tuple (year, month, day, hour, minute, second) to an Excel date value.
-# For more details, refer to other xldate_from_*_tuple functions.
-# @param datetime_tuple (year, month, day, hour, minute, second)
-# @param datemode 0: 1900-based, 1: 1904-based.
-
-def xldate_from_datetime_tuple(datetime_tuple, datemode):
- return (
- xldate_from_date_tuple(datetime_tuple[:3], datemode)
- +
- xldate_from_time_tuple(datetime_tuple[3:])
- )
diff --git a/tablib/packages/xlwt/BIFFRecords.py b/tablib/packages/xlwt/BIFFRecords.py
deleted file mode 100644
index 4660c03..0000000
--- a/tablib/packages/xlwt/BIFFRecords.py
+++ /dev/null
@@ -1,2393 +0,0 @@
-# -*- coding: cp1252 -*-
-from struct import pack
-from UnicodeUtils import upack1, upack2
-import sys
-
-class SharedStringTable(object):
- _SST_ID = 0x00FC
- _CONTINUE_ID = 0x003C
-
- def __init__(self, encoding):
- self.encoding = encoding
- self._str_indexes = {}
- self._tally = []
- self._add_calls = 0
- # Following 3 attrs are used for temporary storage in the
- # get_biff_record() method and methods called by it. The pseudo-
- # initialisation here is for documentation purposes only.
- self._sst_record = None
- self._continues = None
- self._current_piece = None
-
- def add_str(self, s):
- if self.encoding != 'ascii' and not isinstance(s, unicode):
- s = unicode(s, self.encoding)
- self._add_calls += 1
- if s not in self._str_indexes:
- idx = len(self._str_indexes)
- self._str_indexes[s] = idx
- self._tally.append(1)
- else:
- idx = self._str_indexes[s]
- self._tally[idx] += 1
- return idx
-
- def del_str(self, idx):
- # This is called when we are replacing the contents of a string cell.
- assert self._tally[idx] > 0
- self._tally[idx] -= 1
- self._add_calls -= 1
-
- def str_index(self, s):
- return self._str_indexes[s]
-
- def get_biff_record(self):
- self._sst_record = ''
- self._continues = [None, None]
- self._current_piece = pack('<II', 0, 0)
- data = [(idx, s) for s, idx in self._str_indexes.iteritems()]
- data.sort() # in index order
- for idx, s in data:
- if self._tally[idx] == 0:
- s = u''
- self._add_to_sst(s)
- del data
- self._new_piece()
- self._continues[0] = pack('<2HII', self._SST_ID, len(self._sst_record), self._add_calls, len(self._str_indexes))
- self._continues[1] = self._sst_record[8:]
- self._sst_record = None
- self._current_piece = None
- result = ''.join(self._continues)
- self._continues = None
- return result
-
-
- def _add_to_sst(self, s):
- u_str = upack2(s, self.encoding)
-
- is_unicode_str = u_str[2] == '\x01'
- if is_unicode_str:
- atom_len = 5 # 2 byte -- len,
- # 1 byte -- options,
- # 2 byte -- 1st sym
- else:
- atom_len = 4 # 2 byte -- len,
- # 1 byte -- options,
- # 1 byte -- 1st sym
-
- self._save_atom(u_str[0:atom_len])
- self._save_splitted(u_str[atom_len:], is_unicode_str)
-
- def _new_piece(self):
- if self._sst_record == '':
- self._sst_record = self._current_piece
- else:
- curr_piece_len = len(self._current_piece)
- self._continues.append(pack('<2H%ds'%curr_piece_len, self._CONTINUE_ID, curr_piece_len, self._current_piece))
- self._current_piece = ''
-
- def _save_atom(self, s):
- atom_len = len(s)
- free_space = 0x2020 - len(self._current_piece)
- if free_space < atom_len:
- self._new_piece()
- self._current_piece += s
-
- def _save_splitted(self, s, is_unicode_str):
- i = 0
- str_len = len(s)
- while i < str_len:
- piece_len = len(self._current_piece)
- free_space = 0x2020 - piece_len
- tail_len = str_len - i
- need_more_space = free_space < tail_len
-
- if not need_more_space:
- atom_len = tail_len
- else:
- if is_unicode_str:
- atom_len = free_space & 0xFFFE
- else:
- atom_len = free_space
-
- self._current_piece += s[i:i+atom_len]
-
- if need_more_space:
- self._new_piece()
- if is_unicode_str:
- self._current_piece += '\x01'
- else:
- self._current_piece += '\x00'
-
- i += atom_len
-
-
-class BiffRecord(object):
-
- _rec_data = '' # class attribute; child classes need to set this.
-
- # Sheer waste.
- # def __init__(self):
- # self._rec_data = ''
-
- def get_rec_id(self):
- return _REC_ID
-
- def get_rec_header(self):
- return pack('<2H', self._REC_ID, len(self._rec_data))
-
- # Not over-ridden by any child classes, never called (except by "get"; see below).
- # def get_rec_data(self):
- # return self._rec_data
-
- def get(self):
- # data = self.get_rec_data()
- data = self._rec_data
-
- if len(data) > 0x2020: # limit for BIFF7/8
- chunks = []
- pos = 0
- while pos < len(data):
- chunk_pos = pos + 0x2020
- chunk = data[pos:chunk_pos]
- chunks.append(chunk)
- pos = chunk_pos
- continues = pack('<2H', self._REC_ID, len(chunks[0])) + chunks[0]
- for chunk in chunks[1:]:
- continues += pack('<2H%ds'%len(chunk), 0x003C, len(chunk), chunk)
- # 0x003C -- CONTINUE record id
- return continues
- else:
- return self.get_rec_header() + data
-
-
-class Biff8BOFRecord(BiffRecord):
- """
- Offset Size Contents
- 0 2 Version, contains 0600H for BIFF8 and BIFF8X
- 2 2 Type of the following data:
- 0005H = Workbook globals
- 0006H = Visual Basic module
- 0010H = Worksheet
- 0020H = Chart
- 0040H = Macro sheet
- 0100H = Workspace file
- 4 2 Build identifier
- 6 2 Build year
- 8 4 File history flags
- 12 4 Lowest Excel version that can read all records in this file
- """
- _REC_ID = 0x0809
- # stream types
- BOOK_GLOBAL = 0x0005
- VB_MODULE = 0x0006
- WORKSHEET = 0x0010
- CHART = 0x0020
- MACROSHEET = 0x0040
- WORKSPACE = 0x0100
-
- def __init__(self, rec_type):
- version = 0x0600
- build = 0x0DBB
- year = 0x07CC
- file_hist_flags = 0x00L
- ver_can_read = 0x06L
-
- self._rec_data = pack('<4H2I', version, rec_type, build, year, file_hist_flags, ver_can_read)
-
-
-class InteraceHdrRecord(BiffRecord):
- _REC_ID = 0x00E1
-
- def __init__(self):
- self._rec_data = pack('BB', 0xB0, 0x04)
-
-
-class InteraceEndRecord(BiffRecord):
- _REC_ID = 0x00E2
-
- def __init__(self):
- self._rec_data = ''
-
-
-class MMSRecord(BiffRecord):
- _REC_ID = 0x00C1
-
- def __init__(self):
- self._rec_data = pack('<H', 0x00)
-
-
-class WriteAccessRecord(BiffRecord):
- """
- This record is part of the file protection. It contains the name of the
- user that has saved the file. The user name is always stored as an
- equal-sized string. All unused characters after the name are filled
- with space characters. It is not required to write the mentioned string
- length. Every other length will be accepted too.
- """
- _REC_ID = 0x005C
-
- def __init__(self, owner):
- uowner = owner[0:0x30]
- uowner_len = len(uowner)
- self._rec_data = pack('%ds%ds' % (uowner_len, 0x70 - uowner_len), uowner, ' '*(0x70 - uowner_len))
-
-
-class DSFRecord(BiffRecord):
- """
- This record specifies if the file contains an additional BIFF5/BIFF7
- workbook stream.
- Record DSF, BIFF8:
- Offset Size Contents
- 0 2 0 = Only the BIFF8 Workbook stream is present
- 1 = Additional BIFF5/BIFF7 Book stream is in the file
- A double stream file can be read by Excel 5.0 and Excel 95, and still
- contains all new features added to BIFF8 (which are left out in the
- BIFF5/BIFF7 Book stream).
- """
- _REC_ID = 0x0161
-
- def __init__(self):
- self._rec_data = pack('<H', 0x00)
-
-
-class TabIDRecord(BiffRecord):
- _REC_ID = 0x013D
-
- def __init__(self, sheetcount):
- for i in range(sheetcount):
- self._rec_data += pack('<H', i+1)
-
-
-class FnGroupCountRecord(BiffRecord):
- _REC_ID = 0x009C
-
- def __init__(self):
- self._rec_data = pack('BB', 0x0E, 0x00)
-
-
-class WindowProtectRecord(BiffRecord):
- """
- This record is part of the worksheet/workbook protection. It determines
- whether the window configuration of this document is protected. Window
- protection is not active, if this record is omitted.
- """
- _REC_ID = 0x0019
-
- def __init__(self, wndprotect):
- self._rec_data = pack('<H', wndprotect)
-
-
-class ObjectProtectRecord(BiffRecord):
- """
- This record is part of the worksheet/workbook protection.
- It determines whether the objects of the current sheet are protected.
- Object protection is not active, if this record is omitted.
- """
- _REC_ID = 0x0063
-
-
- def __init__(self, objprotect):
- self._rec_data = pack('<H', objprotect)
-
-
-class ScenProtectRecord(BiffRecord):
- """
- This record is part of the worksheet/workbook protection. It
- determines whether the scenarios of the current sheet are protected.
- Scenario protection is not active, if this record is omitted.
- """
- _REC_ID = 0x00DD
-
-
- def __init__(self, scenprotect):
- self._rec_data = pack('<H', scenprotect)
-
-
-class ProtectRecord(BiffRecord):
- """
- This record is part of the worksheet/workbook protection. It specifies
- whether a worksheet or a workbook is protected against modification.
- Protection is not active, if this record is omitted.
- """
-
- _REC_ID = 0x0012
-
- def __init__(self, protect):
- self._rec_data = pack('<H', protect)
-
-
-class PasswordRecord(BiffRecord):
- """
- This record is part of the worksheet/workbook protection. It
- stores a 16-bit hash value, calculated from the worksheet or workbook
- protection password.
- """
- _REC_ID = 0x0013
- def passwd_hash(self, plaintext):
- """
- Based on the algorithm provided by Daniel Rentz of OpenOffice.
- """
- if plaintext == "":
- return 0
-
- passwd_hash = 0x0000
- for i, char in enumerate(plaintext):
- c = ord(char) << (i + 1)
- low_15 = c & 0x7fff
- high_15 = c & 0x7fff << 15
- high_15 = high_15 >> 15
- c = low_15 | high_15
- passwd_hash ^= c
- passwd_hash ^= len(plaintext)
- passwd_hash ^= 0xCE4B
- return passwd_hash
-
- def __init__(self, passwd = ""):
- self._rec_data = pack('<H', self.passwd_hash(passwd))
-
-
-class Prot4RevRecord(BiffRecord):
- _REC_ID = 0x01AF
-
- def __init__(self):
- self._rec_data = pack('<H', 0x00)
-
-
-class Prot4RevPassRecord(BiffRecord):
- _REC_ID = 0x01BC
-
- def __init__(self):
- self._rec_data = pack('<H', 0x00)
-
-
-class BackupRecord(BiffRecord):
- """
- This record contains a Boolean value determining whether Excel makes
- a backup of the file while saving.
- """
- _REC_ID = 0x0040
-
- def __init__(self, backup):
- self._rec_data = pack('<H', backup)
-
-class HideObjRecord(BiffRecord):
- """
- This record specifies whether and how to show objects in the workbook.
-
- Record HIDEOBJ, BIFF3-BIFF8:
- Offset Size Contents
- 0 2 Viewing mode for objects:
- 0 = Show all objects
- 1 = Show placeholders
- 2 = Do not show objects
- """
- _REC_ID = 0x008D
-
- def __init__(self):
- self._rec_data = pack('<H', 0x00)
-
-
-
-class RefreshAllRecord(BiffRecord):
- """
- """
-
- _REC_ID = 0x01B7
-
- def __init__(self):
- self._rec_data = pack('<H', 0x00)
-
-
-class BookBoolRecord(BiffRecord):
- """
- This record contains a Boolean value determining whether to save values
- linked from external workbooks (CRN records and XCT records). In BIFF3
- and BIFF4 this option is stored in the WSBOOL record.
-
- Record BOOKBOOL, BIFF5-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Save external linked values;
- 1 = Do not save external linked values
- """
-
- _REC_ID = 0x00DA
-
- def __init__(self):
- self._rec_data = pack('<H', 0x00)
-
-
-class CountryRecord(BiffRecord):
- """
- This record stores two Windows country identifiers. The first
- represents the user interface language of the Excel version that has
- saved the file, and the second represents the system regional settings
- at the time the file was saved.
-
- Record COUNTRY, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 Windows country identifier of the user interface language of Excel
- 2 2 Windows country identifier of the system regional settings
-
- The following table shows most of the used country identifiers. Most
- of these identifiers are equal to the international country calling
- codes.
-
- 1 USA
- 2 Canada
- 7 Russia
- """
-
- _REC_ID = 0x008C
-
- def __init__(self, ui_id, sys_settings_id):
- self._rec_data = pack('<2H', ui_id, sys_settings_id)
-
-
-class UseSelfsRecord(BiffRecord):
- """
- This record specifies if the formulas in the workbook can use natural
- language formulas. This type of formula can refer to cells by its
- content or the content of the column or row header cell.
-
- Record USESELFS, BIFF8:
-
- Offset Size Contents
- 0 2 0 = Do not use natural language formulas
- 1 = Use natural language formulas
-
- """
-
- _REC_ID = 0x0160
-
- def __init__(self):
- self._rec_data = pack('<H', 0x01)
-
-
-class EOFRecord(BiffRecord):
- _REC_ID = 0x000A
-
- def __init__(self):
- self._rec_data = ''
-
-
-class DateModeRecord(BiffRecord):
- """
- This record specifies the base date for displaying date values. All
- dates are stored as count of days past this base date. In BIFF2-BIFF4
- this record is part of the Calculation Settings Block.
- In BIFF5-BIFF8 it is stored in the Workbook Globals Substream.
-
- Record DATEMODE, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Base is 1899-Dec-31 (the cell = 1 represents 1900-Jan-01)
- 1 = Base is 1904-Jan-01 (the cell = 1 represents 1904-Jan-02)
- """
- _REC_ID = 0x0022
-
- def __init__(self, from1904):
- if from1904:
- self._rec_data = pack('<H', 1)
- else:
- self._rec_data = pack('<H', 0)
-
-
-class PrecisionRecord(BiffRecord):
- """
- This record stores if formulas use the real cell values for calculation
- or the values displayed on the screen. In BIFF2- BIFF4 this record
- is part of the Calculation Settings Block. In BIFF5-BIFF8 it is stored
- in the Workbook Globals Substream.
-
- Record PRECISION, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Use displayed values;
- 1 = Use real cell values
- """
- _REC_ID = 0x000E
-
- def __init__(self, use_real_values):
- if use_real_values:
- self._rec_data = pack('<H', 1)
- else:
- self._rec_data = pack('<H', 0)
-
-
-class CodepageBiff8Record(BiffRecord):
- """
- This record stores the text encoding used to write byte strings, stored
- as MS Windows code page identifier. The CODEPAGE record in BIFF8 always
- contains the code page 1200 (UTF-16). Therefore it is not
- possible to obtain the encoding used for a protection password (it is
- not UTF-16).
-
- Record CODEPAGE, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 Code page identifier used for byte string text encoding:
- 016FH = 367 = ASCII
- 01B5H = 437 = IBM PC CP-437 (US)
- 02D0H = 720 = IBM PC CP-720 (OEM Arabic)
- 02E1H = 737 = IBM PC CP-737 (Greek)
- 0307H = 775 = IBM PC CP-775 (Baltic)
- 0352H = 850 = IBM PC CP-850 (Latin I)
- 0354H = 852 = IBM PC CP-852 (Latin II (Central European))
- 0357H = 855 = IBM PC CP-855 (Cyrillic)
- 0359H = 857 = IBM PC CP-857 (Turkish)
- 035AH = 858 = IBM PC CP-858 (Multilingual Latin I with Euro)
- 035CH = 860 = IBM PC CP-860 (Portuguese)
- 035DH = 861 = IBM PC CP-861 (Icelandic)
- 035EH = 862 = IBM PC CP-862 (Hebrew)
- 035FH = 863 = IBM PC CP-863 (Canadian (French))
- 0360H = 864 = IBM PC CP-864 (Arabic)
- 0361H = 865 = IBM PC CP-865 (Nordic)
- 0362H = 866 = IBM PC CP-866 (Cyrillic (Russian))
- 0365H = 869 = IBM PC CP-869 (Greek (Modern))
- 036AH = 874 = Windows CP-874 (Thai)
- 03A4H = 932 = Windows CP-932 (Japanese Shift-JIS)
- 03A8H = 936 = Windows CP-936 (Chinese Simplified GBK)
- 03B5H = 949 = Windows CP-949 (Korean (Wansung))
- 03B6H = 950 = Windows CP-950 (Chinese Traditional BIG5)
- 04B0H = 1200 = UTF-16 (BIFF8)
- 04E2H = 1250 = Windows CP-1250 (Latin II) (Central European)
- 04E3H = 1251 = Windows CP-1251 (Cyrillic)
- 04E4H = 1252 = Windows CP-1252 (Latin I) (BIFF4-BIFF7)
- 04E5H = 1253 = Windows CP-1253 (Greek)
- 04E6H = 1254 = Windows CP-1254 (Turkish)
- 04E7H = 1255 = Windows CP-1255 (Hebrew)
- 04E8H = 1256 = Windows CP-1256 (Arabic)
- 04E9H = 1257 = Windows CP-1257 (Baltic)
- 04EAH = 1258 = Windows CP-1258 (Vietnamese)
- 0551H = 1361 = Windows CP-1361 (Korean (Johab))
- 2710H = 10000 = Apple Roman
- 8000H = 32768 = Apple Roman
- 8001H = 32769 = Windows CP-1252 (Latin I) (BIFF2-BIFF3)
- """
- _REC_ID = 0x0042
- UTF_16 = 0x04B0
-
- def __init__(self):
- self._rec_data = pack('<H', self.UTF_16)
-
-class Window1Record(BiffRecord):
- """
- Offset Size Contents
- 0 2 Horizontal position of the document window (in twips = 1/20 of a point)
- 2 2 Vertical position of the document window (in twips = 1/20 of a point)
- 4 2 Width of the document window (in twips = 1/20 of a point)
- 6 2 Height of the document window (in twips = 1/20 of a point)
- 8 2 Option flags:
- Bits Mask Contents
- 0 0001H 0 = Window is visible 1 = Window is hidden
- 1 0002H 0 = Window is open 1 = Window is minimised
- 3 0008H 0 = Horizontal scroll bar hidden 1 = Horizontal scroll bar visible
- 4 0010H 0 = Vertical scroll bar hidden 1 = Vertical scroll bar visible
- 5 0020H 0 = Worksheet tab bar hidden 1 = Worksheet tab bar visible
- 10 2 Index to active (displayed) worksheet
- 12 2 Index of first visible tab in the worksheet tab bar
- 14 2 Number of selected worksheets (highlighted in the worksheet tab bar)
- 16 2 Width of worksheet tab bar (in 1/1000 of window width). The remaining space is used by the
- horizontal scrollbar.
- """
- _REC_ID = 0x003D
- # flags
-
- def __init__(self,
- hpos_twips, vpos_twips,
- width_twips, height_twips,
- flags,
- active_sheet,
- first_tab_index, selected_tabs, tab_width):
- self._rec_data = pack('<9H', hpos_twips, vpos_twips,
- width_twips, height_twips,
- flags,
- active_sheet,
- first_tab_index, selected_tabs, tab_width)
-
-class FontRecord(BiffRecord):
- """
- WARNING
- The font with index 4 is omitted in all BIFF versions.
- This means the first four fonts have zero-based indexes, and
- the fifth font and all following fonts are referenced with one-based
- indexes.
-
- Offset Size Contents
- 0 2 Height of the font (in twips = 1/20 of a point)
- 2 2 Option flags:
- Bit Mask Contents
- 0 0001H 1 = Characters are bold (redundant, see below)
- 1 0002H 1 = Characters are italic
- 2 0004H 1 = Characters are underlined (redundant, see below)
- 3 0008H 1 = Characters are struck out
- 0010H 1 = Outline
- 0020H 1 = Shadow
- 4 2 Colour index
- 6 2 Font weight (100-1000).
- Standard values are 0190H (400) for normal text and 02BCH
- (700) for bold text.
- 8 2 Escapement type:
- 0000H = None
- 0001H = Superscript
- 0002H = Subscript
- 10 1 Underline type:
- 00H = None
- 01H = Single
- 21H = Single accounting
- 02H = Double
- 22H = Double accounting
- 11 1 Font family:
- 00H = None (unknown or don't care)
- 01H = Roman (variable width, serifed)
- 02H = Swiss (variable width, sans-serifed)
- 03H = Modern (fixed width, serifed or sans-serifed)
- 04H = Script (cursive)
- 05H = Decorative (specialised, i.e. Old English, Fraktur)
- 12 1 Character set:
- 00H = 0 = ANSI Latin
- 01H = 1 = System default
- 02H = 2 = Symbol
- 4DH = 77 = Apple Roman
- 80H = 128 = ANSI Japanese Shift-JIS
- 81H = 129 = ANSI Korean (Hangul)
- 82H = 130 = ANSI Korean (Johab)
- 86H = 134 = ANSI Chinese Simplified GBK
- 88H = 136 = ANSI Chinese Traditional BIG5
- A1H = 161 = ANSI Greek
- A2H = 162 = ANSI Turkish
- A3H = 163 = ANSI Vietnamese
- B1H = 177 = ANSI Hebrew
- B2H = 178 = ANSI Arabic
- BAH = 186 = ANSI Baltic
- CCH = 204 = ANSI Cyrillic
- DEH = 222 = ANSI Thai
- EEH = 238 = ANSI Latin II (Central European)
- FFH = 255 = OEM Latin I
- 13 1 Not used
- 14 var. Font name:
- BIFF5/BIFF7: Byte string, 8-bit string length
- BIFF8: Unicode string, 8-bit string length
- The boldness and underline flags are still set in the options field,
- but not used on reading the font. Font weight and underline type
- are specified in separate fields instead.
- """
- _REC_ID = 0x0031
-
- def __init__(self,
- height, options, colour_index, weight, escapement,
- underline, family, charset,
- name):
- uname = upack1(name)
- uname_len = len(uname)
-
- self._rec_data = pack('<5H4B%ds' % uname_len, height, options, colour_index, weight, escapement,
- underline, family, charset, 0x00,
- uname)
-
-class NumberFormatRecord(BiffRecord):
- """
- Record FORMAT, BIFF8:
- Offset Size Contents
- 0 2 Format index used in other records
- 2 var. Number format string (Unicode string, 16-bit string length)
-
- From BIFF5 on, the built-in number formats will be omitted. The built-in
- formats are dependent on the current regional settings of the operating
- system. The following table shows which number formats are used by default
- in a US-English environment. All indexes from 0 to 163 are reserved for
- built-in formats. The first user-defined format starts at 164.
-
- The built-in number formats, BIFF5-BIFF8
-
- Index Type Format string
- 0 General General
- 1 Decimal 0
- 2 Decimal 0.00
- 3 Decimal #,##0
- 4 Decimal #,##0.00
- 5 Currency "$"#,##0_);("$"#,##
- 6 Currency "$"#,##0_);[Red]("$"#,##
- 7 Currency "$"#,##0.00_);("$"#,##
- 8 Currency "$"#,##0.00_);[Red]("$"#,##
- 9 Percent 0%
- 10 Percent 0.00%
- 11 Scientific 0.00E+00
- 12 Fraction # ?/?
- 13 Fraction # ??/??
- 14 Date M/D/YY
- 15 Date D-MMM-YY
- 16 Date D-MMM
- 17 Date MMM-YY
- 18 Time h:mm AM/PM
- 19 Time h:mm:ss AM/PM
- 20 Time h:mm
- 21 Time h:mm:ss
- 22 Date/Time M/D/YY h:mm
- 37 Account _(#,##0_);(#,##0)
- 38 Account _(#,##0_);[Red](#,##0)
- 39 Account _(#,##0.00_);(#,##0.00)
- 40 Account _(#,##0.00_);[Red](#,##0.00)
- 41 Currency _("$"* #,##0_);_("$"* (#,##0);_("$"* "-"_);_(@_)
- 42 Currency _(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)
- 43 Currency _("$"* #,##0.00_);_("$"* (#,##0.00);_("$"* "-"??_);_(@_)
- 44 Currency _(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)
- 45 Time mm:ss
- 46 Time [h]:mm:ss
- 47 Time mm:ss.0
- 48 Scientific ##0.0E+0
- 49 Text @
- """
- _REC_ID = 0x041E
-
- def __init__(self, idx, fmtstr):
- ufmtstr = upack2(fmtstr)
- ufmtstr_len = len(ufmtstr)
-
- self._rec_data = pack('<H%ds' % ufmtstr_len, idx, ufmtstr)
-
-
-class XFRecord(BiffRecord):
- """
- XF Substructures
- -------------------------------------------------------------------------
- XF_TYPE_PROT XF Type and Cell Protection (3 Bits), BIFF3-BIFF8
- These 3 bits are part of a specific data byte.
- Bit Mask Contents
- 0 01H 1 = Cell is locked
- 1 02H 1 = Formula is hidden
- 2 04H 0 = Cell XF; 1 = Style XF
-
- XF_USED_ATTRIB Attributes Used from Parent Style XF (6 Bits),
- BIFF3-BIFF8 Each bit describes the validity of a specific group
- of attributes. In cell XFs a cleared bit means the attributes of the
- parent style XF are used (but only if the attributes are valid there),
- a set bit means the attributes of this XF are used. In style XFs
- a cleared bit means the attribute setting is valid, a set bit means the
- attribute should be ignored.
- Bit Mask Contents
- 0 01H Flag for number format
- 1 02H Flag for font
- 2 04H Flag for horizontal and vertical alignment, text wrap, indentation, orientation, rotation, and
- text direction
- 3 08H Flag for border lines
- 4 10H Flag for background area style
- 5 20H Flag for cell protection (cell locked and formula hidden)
-
- XF_HOR_ALIGN Horizontal Alignment (3 Bits), BIFF2-BIFF8 The horizontal
- alignment consists of 3 bits and is part of a specific data byte.
- Value Horizontal alignment
- 00H General
- 01H Left
- 02H Centred
- 03H Right
- 04H Filled
- 05H Justified (BIFF4-BIFF8X)
- 06H Centred across selection (BIFF4-BIFF8X)
- 07H Distributed (BIFF8X)
-
- XF_VERT_ALIGN Vertical Alignment (2 or 3 Bits), BIFF4-BIFF8
- The vertical alignment consists of 2 bits (BIFF4) or 3 bits (BIFF5-BIFF8)
- and is part of a specific data byte. Vertical alignment is not available
- in BIFF2 and BIFF3.
- Value Vertical alignment
- 00H Top
- 01H Centred
- 02H Bottom
- 03H Justified (BIFF5-BIFF8X)
- 04H Distributed (BIFF8X)
-
- XF_ORIENTATION Text Orientation (2 Bits), BIFF4-BIFF7 In the BIFF
- versions BIFF4-BIFF7, text can be rotated in steps of 90 degrees
- or stacked. The orientation mode consists of 2 bits and is part of
- a specific data byte. In BIFF8 a rotation angle occurs instead of these
- flags.
- Value Text orientation
- 00H Not rotated
- 01H Letters are stacked top-to-bottom, but not rotated
- 02H Text is rotated 90 degrees counterclockwise
- 03H Text is rotated 90 degrees clockwise
-
- XF_ROTATION Text Rotation Angle (1 Byte), BIFF8
- Value Text rotation
- 0 Not rotated
- 1-90 1 to 90 degrees counterclockwise
- 91-180 1 to 90 degrees clockwise
- 255 Letters are stacked top-to-bottom, but not rotated
-
- XF_BORDER_34 Cell Border Style (4 Bytes), BIFF3-BIFF4 Cell borders
- contain a line style and a line colour for each line of the border.
- Bit Mask Contents
- 2-0 00000007H Top line style
- 7-3 000000F8H Colour index for top line colour
- 10-8 00000700H Left line style
- 15-11 0000F800H Colour index for left line colour
- 18-16 00070000H Bottom line style
- 23-19 00F80000H Colour index for bottom line colour
- 26-24 07000000H Right line style
- 31-27 F8000000H Colour index for right line colour
-
- XF_AREA_34 Cell Background Area Style (2 Bytes), BIFF3-BIFF4 A cell
- background area style contains an area pattern and a foreground and
- background colour.
- Bit Mask Contents
- 5-0 003FH Fill pattern
- 10-6 07C0H Colour index for pattern colour
- 15-11 F800H Colour index for pattern background
- ---------------------------------------------------------------------------------------------
- Record XF, BIFF8:
- Offset Size Contents
- 0 2 Index to FONT record
- 2 2 Index to FORMAT record
- 4 2 Bit Mask Contents
- 2-0 0007H XF_TYPE_PROT . XF type, cell protection (see above)
- 15-4 FFF0H Index to parent style XF (always FFFH in style XFs)
- 6 1 Bit Mask Contents
- 2-0 07H XF_HOR_ALIGN . Horizontal alignment (see above)
- 3 08H 1 = Text is wrapped at right border
- 6-4 70H XF_VERT_ALIGN . Vertical alignment (see above)
- 7 1 XF_ROTATION: Text rotation angle (see above)
- 8 1 Bit Mask Contents
- 3-0 0FH Indent level
- 4 10H 1 = Shrink content to fit into cell
- 5 merge
- 7-6 C0H Text direction (BIFF8X only)
- 00b = According to context
- 01b = Left-to-right
- 10b = Right-to-left
- 9 1 Bit Mask Contents
- 7-2 FCH XF_USED_ATTRIB . Used attributes (see above)
- 10 4 Cell border lines and background area:
- Bit Mask Contents
- 3-0 0000000FH Left line style
- 7-4 000000F0H Right line style
- 11-8 00000F00H Top line style
- 15-12 0000F000H Bottom line style
- 22-16 007F0000H Colour index for left line colour
- 29-23 3F800000H Colour index for right line colour
- 30 40000000H 1 = Diagonal line from top left to right bottom
- 31 80000000H 1 = Diagonal line from bottom left to right top
- 14 4 Bit Mask Contents
- 6-0 0000007FH Colour index for top line colour
- 13-7 00003F80H Colour index for bottom line colour
- 20-14 001FC000H Colour index for diagonal line colour
- 24-21 01E00000H Diagonal line style
- 31-26 FC000000H Fill pattern
- 18 2 Bit Mask Contents
- 6-0 007FH Colour index for pattern colour
- 13-7 3F80H Colour index for pattern background
-
- """
- _REC_ID = 0x00E0
-
- def __init__(self, xf, xftype='cell'):
- font_xf_idx, fmt_str_xf_idx, alignment, borders, pattern, protection = xf
- fnt = pack('<H', font_xf_idx)
- fmt = pack('<H', fmt_str_xf_idx)
- if xftype == 'cell':
- prt = pack('<H',
- ((protection.cell_locked & 0x01) << 0) |
- ((protection.formula_hidden & 0x01) << 1)
- )
- else:
- prt = pack('<H', 0xFFF5)
- aln = pack('B',
- ((alignment.horz & 0x07) << 0) |
- ((alignment.wrap & 0x01) << 3) |
- ((alignment.vert & 0x07) << 4)
- )
- rot = pack('B', alignment.rota)
- txt = pack('B',
- ((alignment.inde & 0x0F) << 0) |
- ((alignment.shri & 0x01) << 4) |
- ((alignment.merg & 0x01) << 5) |
- ((alignment.dire & 0x03) << 6)
- )
- if xftype == 'cell':
- used_attr = pack('B', 0xF8)
- else:
- used_attr = pack('B', 0xF4)
-
- if borders.left == borders.NO_LINE:
- borders.left_colour = 0x00
- if borders.right == borders.NO_LINE:
- borders.right_colour = 0x00
- if borders.top == borders.NO_LINE:
- borders.top_colour = 0x00
- if borders.bottom == borders.NO_LINE:
- borders.bottom_colour = 0x00
- if borders.diag == borders.NO_LINE:
- borders.diag_colour = 0x00
- brd1 = pack('<L',
- ((borders.left & 0x0F) << 0 ) |
- ((borders.right & 0x0F) << 4 ) |
- ((borders.top & 0x0F) << 8 ) |
- ((borders.bottom & 0x0F) << 12) |
- ((borders.left_colour & 0x7F) << 16) |
- ((borders.right_colour & 0x7F) << 23) |
- ((borders.need_diag1 & 0x01) << 30) |
- ((borders.need_diag2 & 0x01) << 31)
- )
- brd2 = pack('<L',
- ((borders.top_colour & 0x7F) << 0 ) |
- ((borders.bottom_colour & 0x7F) << 7 ) |
- ((borders.diag_colour & 0x7F) << 14) |
- ((borders.diag & 0x0F) << 21) |
- ((pattern.pattern & 0x3F) << 26)
- )
- pat = pack('<H',
- ((pattern.pattern_fore_colour & 0x7F) << 0 ) |
- ((pattern.pattern_back_colour & 0x7F) << 7 )
- )
- self._rec_data = fnt + fmt + prt + \
- aln + rot + txt + used_attr + \
- brd1 + brd2 + \
- pat
-
-class StyleRecord(BiffRecord):
- """
- STYLE record for user-defined cell styles, BIFF3-BIFF8:
- Offset Size Contents
- 0 2 Bit Mask Contents
- 11-0 0FFFH Index to style XF record
- 15 8000H Always 0 for user-defined styles
- 2 var. BIFF2-BIFF7: Non-empty byte string, 8-bit string length
- BIFF8: Non-empty Unicode string, 16-bit string length
- STYLE record for built-in cell styles, BIFF3-BIFF8:
- Offset Size Contents
- 0 2 Bit Mask Contents
- 11-0 0FFFH Index to style XF record
- 15 8000H Always 1 for built-in styles
- 2 1 Identifier of the built-in cell style:
- 00H = Normal
- 01H = RowLevel_lv (see next field)
- 02H = ColLevel_lv (see next field)
- 03H = Comma
- 04H = Currency
- 05H = Percent
- 06H = Comma [0] (BIFF4-BIFF8)
- 07H = Currency [0] (BIFF4-BIFF8)
- 08H = Hyperlink (BIFF8)
- 09H = Followed Hyperlink (BIFF8)
- 3 1 Level for RowLevel or ColLevel style
- (zero-based, lv), FFH otherwise
- The RowLevel and ColLevel styles specify the formatting of subtotal
- cells in a specific outline level. The level is specified by the last
- field in the STYLE record. Valid values are 0-6 for the outline levels
- 1-7.
- """
- _REC_ID = 0x0293
-
- def __init__(self):
- self._rec_data = pack('<HBB', 0x8000, 0x00, 0xFF)
- # TODO: implement user-defined styles???
-
-
-class PaletteRecord(BiffRecord):
- """
- This record contains the definition of all user-defined colours
- available for cell and object formatting.
-
- Record PALETTE, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 Number of following colours (nm). Contains 16 in BIFF3-BIFF4 and 56 in BIFF5-BIFF8.
- 2 4*nm List of nm RGB colours
-
- The following table shows how colour indexes are used in other records:
-
- Colour index Resulting colour or internal list index
- 00H Built-in Black (R = 00H, G = 00H, B = 00H)
- 01H Built-in White (R = FFH, G = FFH, B = FFH)
- 02H Built-in Red (R = FFH, G = 00H, B = 00H)
- 03H Built-in Green (R = 00H, G = FFH, B = 00H)
- 04H Built-in Blue (R = 00H, G = 00H, B = FFH)
- 05H Built-in Yellow (R = FFH, G = FFH, B = 00H)
- 06H Built-in Magenta (R = FFH, G = 00H, B = FFH)
- 07H Built-in Cyan (R = 00H, G = FFH, B = FFH)
- 08H First user-defined colour from the PALETTE record (entry 0 from record colour list)
- .........................
-
- 17H (BIFF3-BIFF4) Last user-defined colour from the PALETTE record (entry 15 or 55 from record colour list)
- 3FH (BIFF5-BIFF8)
-
- 18H (BIFF3-BIFF4) System window text colour for border lines (used in records XF, CF, and
- 40H (BIFF5-BIFF8) WINDOW2 (BIFF8 only))
-
- 19H (BIFF3-BIFF4) System window background colour for pattern background (used in records XF, and CF)
- 41H (BIFF5-BIFF8)
-
- 43H System face colour (dialogue background colour)
- 4DH System window text colour for chart border lines
- 4EH System window background colour for chart areas
- 4FH Automatic colour for chart border lines (seems to be always Black)
- 50H System ToolTip background colour (used in note objects)
- 51H System ToolTip text colour (used in note objects)
- 7FFFH System window text colour for fonts (used in records FONT, EFONT, and CF)
-
- """
- _REC_ID = 0x0092
-
-
-class BoundSheetRecord(BiffRecord):
- """
- This record is located in the workbook globals area and represents
- a sheet inside of the workbook. For each sheet a BOUNDSHEET record
- is written. It stores the sheet name and a stream offset to the BOF
- record within the workbook stream. The record is also known
- as BUNDLESHEET.
-
- Record BOUNDSHEET, BIFF5-BIFF8:
- Offset Size Contents
- 0 4 Absolute stream position of the BOF record of the sheet represented by this record. This
- field is never encrypted in protected files.
- 4 1 Visibility:
- 00H = Visible
- 01H = Hidden
- 02H = Strong hidden
- 5 1 Sheet type:
- 00H = Worksheet
- 02H = Chart
- 06H = Visual Basic module
- 6 var. Sheet name:
- BIFF5/BIFF7: Byte string, 8-bit string length
- BIFF8: Unicode string, 8-bit string length
- """
- _REC_ID = 0x0085
-
- def __init__(self, stream_pos, visibility, sheetname, encoding='ascii'):
- usheetname = upack1(sheetname, encoding)
- uusheetname_len = len(usheetname)
-
- self._rec_data = pack('<LBB%ds' % uusheetname_len, stream_pos, visibility, 0x00, usheetname)
-
-
-class ContinueRecord(BiffRecord):
- """
- Whenever the content of a record exceeds the given limits (see table),
- the record must be split. Several CONTINUE records containing the
- additional data are added after the parent record.
-
- BIFF version Maximum data size of a record
- BIFF2-BIFF7 2080 bytes (2084 bytes including record header)
- BIFF8 8224 bytes (8228 bytes including record header) (0x2020)
-
- Record CONTINUE, BIFF2-BIFF8:
- Offset Size Contents
- 0 var. Data continuation of the previous record
-
- Unicode strings are split in a special way. At the beginning of each
- CONTINUE record the option flags byte is repeated. Only the character
- size flag will be set in this flags byte, the Rich-Text flag and the
- Far-East flag are set to zero. In each CONTINUE record it is possible
- that the character size changes from 8-bit characters to 16-bit
- characters and vice versa.
-
- Never a Unicode string is split until and including the first
- character. That means, all header fields (string length, option flags,
- optional Rich-Text size, and optional Far-East data size) and the first
- character of the string have to occur together in the leading record,
- or have to be moved completely into the CONTINUE record. Formatting
- runs cannot be split between their components (character index and FONT
- record index). If a string is split between two formatting runs, the
- option flags field will not be repeated in the CONTINUE record.
- """
- _REC_ID = 0x003C
-
-
-class SSTRecord(BiffRecord):
- """
- This record contains a list of all strings used anywhere in the
- workbook. Each string occurs only once. The workbook uses indexes into
- the list to reference the strings.
-
- Record SST, BIFF8:
- Offset Size Contents
- 0 4 Total number of strings in the workbook (see below)
- 4 4 Number of following strings (nm)
- 8 var. List of nm Unicode strings, 16-bit string length
-
- The first field of the SST record counts the total occurrence
- of strings in the workbook. For instance, the string AAA is used
- 3 times and the string BBB is used 2 times. The first field contains
- 5 and the second field contains 2, followed by the two strings.
- """
- _REC_ID = 0x00FC
-
-
-class ExtSSTRecord(BiffRecord):
- """
- This record occurs in conjunction with the SST record. It is used
- by Excel to create a hash table with stream offsets to the SST record
- to optimise string search operations. Excel may not shorten this record
- if strings are deleted from the shared string table, so the last part
- might contain invalid data. The stream indexes in this record divide
- the SST into portions containing a constant number of strings.
-
- Record EXTSST, BIFF8:
-
- Offset Size Contents
- 0 2 Number of strings in a portion, this number is >=8
- 2 var. List of OFFSET structures for all portions. Each OFFSET contains the following data:
- Offset Size Contents
- 0 4 Absolute stream position of first string of the portion
- 4 2 Position of first string of the portion inside of current record,
- including record header. This counter restarts at zero, if the SST
- record is continued with a CONTINUE record.
- 6 2 Not used
- """
- _REC_ID = 0x00FF
-
- def __init__(self, sst_stream_pos, str_placement, portions_len):
- extsst = {}
- abs_stream_pos = sst_stream_pos
- str_counter = 0
- portion_counter = 0
- while str_counter < len(str_placement):
- str_chunk_num, pos_in_chunk = str_placement[str_counter]
- if str_chunk_num <> portion_counter:
- portion_counter = str_chunk_num
- abs_stream_pos += portions_len[portion_counter-1]
- #print hex(abs_stream_pos)
- str_stream_pos = abs_stream_pos + pos_in_chunk + 4 # header
- extsst[str_counter] = (pos_in_chunk, str_stream_pos)
- str_counter += 1
-
- exsst_str_count_delta = max(8, len(str_placement)*8/0x2000) # maybe smth else?
- self._rec_data = pack('<H', exsst_str_count_delta)
- str_counter = 0
- while str_counter < len(str_placement):
- self._rec_data += pack('<IHH', extsst[str_counter][1], extsst[str_counter][0], 0)
- str_counter += exsst_str_count_delta
-
-class DimensionsRecord(BiffRecord):
- """
- Record DIMENSIONS, BIFF8:
-
- Offset Size Contents
- 0 4 Index to first used row
- 4 4 Index to last used row, increased by 1
- 8 2 Index to first used column
- 10 2 Index to last used column, increased by 1
- 12 2 Not used
- """
- _REC_ID = 0x0200
- def __init__(self, first_used_row, last_used_row, first_used_col, last_used_col):
- if first_used_row > last_used_row or first_used_col > last_used_col:
- # Special case: empty worksheet
- first_used_row = first_used_col = 0
- last_used_row = last_used_col = -1
- self._rec_data = pack('<2L3H',
- first_used_row, last_used_row + 1,
- first_used_col, last_used_col + 1,
- 0x00)
-
-
-class Window2Record(BiffRecord):
- """
- Record WINDOW2, BIFF8:
-
- Offset Size Contents
- 0 2 Option flags (see below)
- 2 2 Index to first visible row
- 4 2 Index to first visible column
- 6 2 Colour index of grid line colour. Note that in BIFF2-BIFF7 an RGB colour is
- written instead.
- 8 2 Not used
- 10 2 Cached magnification factor in page break preview (in percent); 0 = Default (60%)
- 12 2 Cached magnification factor in normal view (in percent); 0 = Default (100%)
- 14 4 Not used
-
- In BIFF8 this record stores used magnification factors for page break
- preview and normal view. These values are used to restore the
- magnification, when the view is changed. The real magnification of the
- currently active view is stored in the SCL record. The type of the
- active view is stored in the option flags field (see below).
-
- 0 0001H 0 = Show formula results 1 = Show formulas
- 1 0002H 0 = Do not show grid lines 1 = Show grid lines
- 2 0004H 0 = Do not show sheet headers 1 = Show sheet headers
- 3 0008H 0 = Panes are not frozen 1 = Panes are frozen (freeze)
- 4 0010H 0 = Show zero values as empty cells 1 = Show zero values
- 5 0020H 0 = Manual grid line colour 1 = Automatic grid line colour
- 6 0040H 0 = Columns from left to right 1 = Columns from right to left
- 7 0080H 0 = Do not show outline symbols 1 = Show outline symbols
- 8 0100H 0 = Keep splits if pane freeze is removed 1 = Remove splits if pane freeze is removed
- 9 0200H 0 = Sheet not selected 1 = Sheet selected (BIFF5-BIFF8)
- 10 0400H 0 = Sheet not visible 1 = Sheet visible (BIFF5-BIFF8)
- 11 0800H 0 = Show in normal view 1 = Show in page break preview (BIFF8)
-
- The freeze flag specifies, if a following PANE record describes unfrozen or frozen panes.
-
- *** This class appends the optional SCL record ***
-
- Record SCL, BIFF4-BIFF8:
-
- This record stores the magnification of the active view of the current worksheet.
- In BIFF8 this can be either the normal view or the page break preview.
- This is determined in the WINDOW2 record. The SCL record is part of the
- Sheet View Settings Block.
-
- Offset Size Contents
- 0 2 Numerator of the view magnification fraction (num)
- 2 2 Denumerator [denominator] of the view magnification fraction (den)
- The magnification is stored as reduced fraction. The magnification results from num/den.
-
- SJM note: Excel expresses (e.g.) 25% in reduced form i.e. 1/4. Reason unknown. This code
- writes 25/100, and Excel is happy with that.
-
- """
- _REC_ID = 0x023E
-
- def __init__(self, options, first_visible_row, first_visible_col,
- grid_colour, preview_magn, normal_magn, scl_magn):
- self._rec_data = pack('<7HL', options,
- first_visible_row, first_visible_col,
- grid_colour,
- 0x00,
- preview_magn, normal_magn,
- 0x00L)
- if scl_magn:
- self._scl_rec = pack('<4H', 0x00A0, 4, scl_magn, 100)
- else:
- self._scl_rec = ''
-
- def get(self):
- return self.get_rec_header() + self._rec_data + self._scl_rec
-
-
-class PanesRecord(BiffRecord):
- """
- This record stores the position of window panes. It is part of the Sheet
- View Settings Block. If the sheet does not contain any splits, this
- record will not occur.
- A sheet can be split in two different ways, with unfrozen panes or with
- frozen panes. A flag in the WINDOW2 record specifies, if the panes are
- frozen, which affects the contents of this record.
-
- Record PANE, BIFF2-BIFF8:
- Offset Size Contents
- 0 2 Position of the vertical split
- (px, 0 = No vertical split):
- Unfrozen pane: Width of the left pane(s)
- (in twips = 1/20 of a point)
- Frozen pane: Number of visible
- columns in left pane(s)
- 2 2 Position of the horizontal split
- (py, 0 = No horizontal split):
- Unfrozen pane: Height of the top pane(s)
- (in twips = 1/20 of a point)
- Frozen pane: Number of visible
- rows in top pane(s)
- 4 2 Index to first visible row
- in bottom pane(s)
- 6 2 Index to first visible column
- in right pane(s)
- 8 1 Identifier of pane with active
- cell cursor
- [9] 1 Not used (BIFF5-BIFF8 only, not written
- in BIFF2-BIFF4)
-
- If the panes are frozen, pane0 is always active, regardless
- of the cursor position. The correct identifiers for all possible
- combinations of visible panes are shown in the following pictures.
-
- px = 0, py = 0 px = 0, py > 0
- -------------------------- ------------|-------------
- | | | |
- | | | 3 |
- | | | |
- - 3 - --------------------------
- | | | |
- | | | 2 |
- | | | |
- -------------------------- ------------|-------------
-
- px > 0, py = 0 px > 0, py > 0
- ------------|------------- ------------|-------------
- | | | | | |
- | | | | 3 | 2 |
- | | | | | |
- - 3 | 1 - --------------------------
- | | | | | |
- | | | | 1 | 0 |
- | | | | | |
- ------------|------------- ------------|-------------
- """
- _REC_ID = 0x0041
- def __init__(self, px, py, first_row_bottom, first_col_right, active_pane):
- self._rec_data = pack('<5H',
- px, py,
- first_row_bottom, first_col_right,
- active_pane)
-
-
-class RowRecord(BiffRecord):
- """
- This record contains the properties of a single row in a sheet. Rows
- and cells in a sheet are divided into blocks of 32 rows.
-
- Record ROW, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 Index of this row
- 2 2 Index to column of the first cell which is described by a cell record
- 4 2 Index to column of the last cell which is described by a cell record,
- increased by 1
- 6 2 Bit Mask Contents
- 14-0 7FFFH Height of the row, in twips = 1/20 of a point
- 15 8000H 0 = Row has custom height; 1 = Row has default height
- 8 2 Not used
- 10 2 In BIFF3-BIFF4 this field contains a relative offset
- to calculate stream position of the first cell record
- for this row. In BIFF5-BIFF8 this field is not used
- anymore, but the DBCELL record instead.
- 12 4 Option flags and default row formatting:
- Bit Mask Contents
- 2-0 00000007H Outline level of the row
- 4 00000010H 1 = Outline group starts or ends here (depending
- on where the outline buttons are located,
- see WSBOOL record), and is collapsed
- 5 00000020H 1 = Row is hidden (manually, or by a filter or outline group)
- 6 00000040H 1 = Row height and default font height do not match
- 7 00000080H 1 = Row has explicit default format (fl)
- 8 00000100H Always 1
- 27-16 0FFF0000H If fl=1: Index to default XF record
- 28 10000000H 1 = Additional space above the row. This flag is set,
- if the upper border of at least one cell in this row
- or if the lower border of at least one cell in the row
- above is formatted with a thick line style.
- Thin and medium line styles are not taken into account.
- 29 20000000H 1 = Additional space below the row. This flag is set,
- if the lower border of at least one cell in this row
- or if the upper border of at least one cell in the row
- below is formatted with a medium or thick line style.
- Thin line styles are not taken into account.
- """
-
- _REC_ID = 0x0208
-
- def __init__(self, index, first_col, last_col, height_options, options):
- self._rec_data = pack('<6HL', index, first_col, last_col + 1,
- height_options,
- 0x00, 0x00,
- options)
-
-class LabelSSTRecord(BiffRecord):
- """
- This record represents a cell that contains a string. It replaces the
- LABEL record and RSTRING record used in BIFF2-BIFF7.
- """
- _REC_ID = 0x00FD
-
- def __init__(self, row, col, xf_idx, sst_idx):
- self._rec_data = pack('<3HL', row, col, xf_idx, sst_idx)
-
-
-class MergedCellsRecord(BiffRecord):
- """
- This record contains all merged cell ranges of the current sheet.
-
- Record MERGEDCELLS, BIFF8:
-
- Offset Size Contents
- 0 var. Cell range address list with all merged ranges
-
- ------------------------------------------------------------------
-
- A cell range address list consists of a field with the number of ranges
- and the list of the range addresses.
-
- Cell range address list, BIFF8:
-
- Offset Size Contents
- 0 2 Number of following cell range addresses (nm)
- 2 8*nm List of nm cell range addresses
-
- ---------------------------------------------------------------------
- Cell range address, BIFF8:
-
- Offset Size Contents
- 0 2 Index to first row
- 2 2 Index to last row
- 4 2 Index to first column
- 6 2 Index to last column
-
- """
- _REC_ID = 0x00E5
-
- def __init__(self, merged_list):
- i = len(merged_list) - 1
- while i >= 0:
- j = 0
- merged = ''
- while (i >= 0) and (j < 0x403):
- r1, r2, c1, c2 = merged_list[i]
- merged += pack('<4H', r1, r2, c1, c2)
- i -= 1
- j += 1
- self._rec_data += pack('<3H', self._REC_ID, len(merged) + 2, j) + \
- merged
-
- # for some reason Excel doesn't use CONTINUE
- def get(self):
- return self._rec_data
-
-class MulBlankRecord(BiffRecord):
- """
- This record represents a cell range of empty cells. All cells are
- located in the same row.
-
- Record MULBLANK, BIFF5-BIFF8:
-
- Offset Size Contents
- 0 2 Index to row
- 2 2 Index to first column (fc)
- 4 2*nc List of nc=lc-fc+1 16-bit indexes to XF records
- 4+2*nc 2 Index to last column (lc)
- """
- _REC_ID = 0x00BE
-
- def __init__(self, row, first_col, last_col, xf_index):
- blanks_count = last_col-first_col+1
- self._rec_data = pack('%dH' % blanks_count, *([xf_index]*blanks_count))
- self._rec_data = pack('<2H', row, first_col) + self._rec_data + pack('<H', last_col)
-
-
-class BlankRecord(BiffRecord):
- """
- This record represents an empty cell.
-
- Record BLANK, BIFF5-BIFF8:
-
- Offset Size Contents
- 0 2 Index to row
- 2 2 Index to first column (fc)
- 4 2 indexes to XF record
- """
- _REC_ID = 0x0201
-
- def __init__(self, row, col, xf_index):
- self._rec_data = pack('<3H', row, col, xf_index)
-
-
-class RKRecord(BiffRecord):
- """
- This record represents a cell that contains an RK value (encoded integer or
- floating-point value). If a floating-point value cannot be encoded to an RK value,
- a NUMBER record will be written.
- """
- _REC_ID = 0x027E
-
- def __init__(self, row, col, xf_index, rk_encoded):
- self._rec_data = pack('<3Hi', row, col, xf_index, rk_encoded)
-
-
-class NumberRecord(BiffRecord):
- """
- This record represents a cell that contains an IEEE-754 floating-point value.
- """
- _REC_ID = 0x0203
-
- def __init__(self, row, col, xf_index, number):
- self._rec_data = pack('<3Hd', row, col, xf_index, number)
-
-class BoolErrRecord(BiffRecord):
- """
- This record represents a cell that contains a boolean or error value.
- """
- _REC_ID = 0x0205
-
- def __init__(self, row, col, xf_index, number, is_error):
- self._rec_data = pack('<3HBB', row, col, xf_index, number, is_error)
-
-
-class FormulaRecord(BiffRecord):
- """
- Offset Size Contents
- 0 2 Index to row
- 2 2 Index to column
- 4 2 Index to XF record
- 6 8 Result of the formula
- 14 2 Option flags:
- Bit Mask Contents
- 0 0001H 1 = Recalculate always
- 1 0002H 1 = Calculate on open
- 3 0008H 1 = Part of a shared formula
- 16 4 Not used
- 20 var. Formula data (RPN token array)
-
- """
- _REC_ID = 0x0006
-
- def __init__(self, row, col, xf_index, rpn, calc_flags=0):
- self._rec_data = pack('<3HQHL', row, col, xf_index, 0xFFFF000000000003, calc_flags & 3, 0) + rpn
-
-
-class GutsRecord(BiffRecord):
- """
- This record contains information about the layout of outline symbols.
-
- Record GUTS, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 Width of the area to display row outlines (left of the sheet), in pixel
- 2 2 Height of the area to display column outlines (above the sheet), in pixel
- 4 2 Number of visible row outline levels (used row levels + 1; or 0, if not used)
- 6 2 Number of visible column outline levels (used column levels + 1; or 0, if not used)
-
- """
-
- _REC_ID = 0x0080
-
- def __init__(self, row_gut_width, col_gut_height, row_visible_levels, col_visible_levels):
- self._rec_data = pack('<4H', row_gut_width, col_gut_height, row_visible_levels, col_visible_levels)
-
-class WSBoolRecord(BiffRecord):
- """
- This record stores a 16 bit value with Boolean options for the current
- sheet. From BIFF5 on the "Save external linked values" option is moved
- to the record BOOKBOOL.
-
- Option flags of record WSBOOL, BIFF3-BIFF8:
-
- Bit Mask Contents
- 0 0001H 0 = Do not show automatic page breaks
- 1 = Show automatic page breaks
- 4 0010H 0 = Standard sheet
- 1 = Dialogue sheet (BIFF5-BIFF8)
- 5 0020H 0 = No automatic styles in outlines
- 1 = Apply automatic styles to outlines
- 6 0040H 0 = Outline buttons above outline group
- 1 = Outline buttons below outline group
- 7 0080H 0 = Outline buttons left of outline group
- 1 = Outline buttons right of outline group
- 8 0100H 0 = Scale printout in percent
- 1 = Fit printout to number of pages
- 9 0200H 0 = Save external linked values (BIFF3?BIFF4 only)
- 1 = Do not save external linked values (BIFF3?BIFF4 only)
- 10 0400H 0 = Do not show row outline symbols
- 1 = Show row outline symbols
- 11 0800H 0 = Do not show column outline symbols
- 1 = Show column outline symbols
- 13-12 3000H These flags specify the arrangement of windows.
- They are stored in BIFF4 only.
- 00 = Arrange windows tiled
- 01 = Arrange windows horizontal
- 10 = Arrange windows vertical112 = Arrange windows cascaded
- The following flags are valid for BIFF4-BIFF8 only:
- 14 4000H 0 = Standard expression evaluation
- 1 = Alternative expression evaluation
- 15 8000H 0 = Standard formula entries
- 1 = Alternative formula entries
-
- """
- _REC_ID = 0x0081
-
- def __init__(self, options):
- self._rec_data = pack('<H', options)
-
-class ColInfoRecord(BiffRecord):
- """
- This record specifies the width for a given range of columns.
- If a column does not have a corresponding COLINFO record,
- the width specified in the record STANDARDWIDTH is used. If
- this record is also not present, the contents of the record
- DEFCOLWIDTH is used instead.
- This record also specifies a default XF record to use for
- cells in the columns that are not described by any cell record
- (which contain the XF index for that cell). Additionally,
- the option flags field contains hidden, outline, and collapsed
- options applied at the columns.
-
- Record COLINFO, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 Index to first column in the range
- 2 2 Index to last column in the range
- 4 2 Width of the columns in 1/256 of the width of the zero character, using default font
- (first FONT record in the file)
- 6 2 Index to XF record for default column formatting
- 8 2 Option flags:
- Bits Mask Contents
- 0 0001H 1 = Columns are hidden
- 10-8 0700H Outline level of the columns (0 = no outline)
- 12 1000H 1 = Columns are collapsed
- 10 2 Not used
-
- """
- _REC_ID = 0x007D
-
- def __init__(self, first_col, last_col, width, xf_index, options):
- self._rec_data = pack('<6H', first_col, last_col, width, xf_index, options, 0)
-
-class CalcModeRecord(BiffRecord):
- """
- This record is part of the Calculation Settings Block.
- It specifies whether to calculate formulas manually,
- automatically or automatically except for multiple table operations.
-
- Record CALCMODE, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 FFFFH = automatic except for multiple table operations
- 0000H = manually
- 0001H = automatically (default)
- """
- _REC_ID = 0x000D
-
- def __init__(self, calc_mode):
- self._rec_data = pack('<h', calc_mode)
-
-
-class CalcCountRecord(BiffRecord):
- """
- This record is part of the Calculation Settings Block. It specifies the maximum
- number of times the formulas should be iteratively calculated. This is a fail-safe
- against mutually recursive formulas locking up a spreadsheet application.
-
- Record CALCCOUNT, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 Maximum number of iterations allowed in circular references
- """
-
- _REC_ID = 0x000C
-
- def __init__(self, calc_count):
- self._rec_data = pack('<H', calc_count)
-
-class RefModeRecord(BiffRecord):
- """
- This record is part of the Calculation Settings Block.
- It stores which method is used to show cell addresses in formulas.
- The RC mode uses numeric indexes for rows and columns,
- i.e. R(1)C(-1), or R1C1:R2C2.
- The A1 mode uses characters for columns and numbers for rows,
- i.e. B1, or $A$1:$B$2.
-
- Record REFMODE, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 0 = RC mode; 1 = A1 mode
-
- """
- _REC_ID = 0x00F
-
- def __init__(self, ref_mode):
- self._rec_data = pack('<H', ref_mode)
-
-class IterationRecord(BiffRecord):
- """
- This record is part of the Calculation Settings Block.
- It stores if iterations are allowed while calculating recursive formulas.
-
- Record ITERATION, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Iterations off; 1 = Iterations on
- """
- _REC_ID = 0x011
-
- def __init__(self, iterations_on):
- self._rec_data = pack('<H', iterations_on)
-
-class DeltaRecord(BiffRecord):
- """
- This record is part of the Calculation Settings Block.
- It stores the maximum change of the result to exit an iteration.
-
- Record DELTA, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 8 Maximum change in iteration
- (IEEE 754 floating-point value,
- 64bit double precision)
- """
- _REC_ID = 0x010
-
- def __init__(self, delta):
- self._rec_data = pack('<d', delta)
-
-class SaveRecalcRecord(BiffRecord):
- """
- This record is part of the Calculation Settings Block.
- It contains the Recalculate before save option in
- Excel's calculation settings dialogue.
-
- Record SAVERECALC, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Do not recalculate;
- 1 = Recalculate before saving the document
-
- """
- _REC_ID = 0x05F
-
- def __init__(self, recalc):
- self._rec_data = pack('<H', recalc)
-
-class PrintHeadersRecord(BiffRecord):
- """
- This record stores if the row and column headers
- (the areas with row numbers and column letters) will be printed.
-
- Record PRINTHEADERS, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Do not print row/column headers;
- 1 = Print row/column headers
- """
- _REC_ID = 0x02A
-
- def __init__(self, print_headers):
- self._rec_data = pack('<H', print_headers)
-
-
-class PrintGridLinesRecord(BiffRecord):
- """
- This record stores if sheet grid lines will be printed.
-
- Record PRINTGRIDLINES, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Do not print sheet grid lines;
- 1 = Print sheet grid lines
-
- """
- _REC_ID = 0x02B
-
- def __init__(self, print_grid):
- self._rec_data = pack('<H', print_grid)
-
-
-class GridSetRecord(BiffRecord):
- """
- This record specifies if the option to print sheet grid lines
- (record PRINTGRIDLINES) has ever been changed.
-
- Record GRIDSET, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Print grid lines option never changed
- 1 = Print grid lines option changed
- """
- _REC_ID = 0x082
-
- def __init__(self, print_grid_changed):
- self._rec_data = pack('<H', print_grid_changed)
-
-
-class DefaultRowHeightRecord(BiffRecord):
- """
- This record specifies the default height and default flags
- for rows that do not have a corresponding ROW record.
-
- Record DEFAULTROWHEIGHT, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 Option flags:
- Bit Mask Contents
- 0 0001H 1 = Row height and default font height do not match
- 1 0002H 1 = Row is hidden
- 2 0004H 1 = Additional space above the row
- 3 0008H 1 = Additional space below the row
- 2 2 Default height for unused rows, in twips = 1/20 of a point
-
- """
- _REC_ID = 0x0225
-
- def __init__(self, options, def_height):
- self._rec_data = pack('<2H', options, def_height)
-
-
-class DefColWidthRecord(BiffRecord):
- """
- This record specifies the default column width for columns that
- do not have a specific width set using the record COLINFO or COLWIDTH.
- This record has no effect, if a STANDARDWIDTH record is present in the file.
-
- Record DEFCOLWIDTH, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 Column width in characters, using the width of the zero
- character from default font (first FONT record in the file)
- """
- _REC_ID = 0x0055
-
- def __init__(self, def_width):
- self._rec_data = pack('<H', options, def_width)
-
-class HorizontalPageBreaksRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It contains all
- horizontal manual page breaks.
-
- Record HORIZONTALPAGEBREAKS, BIFF8:
- Offset Size Contents
- 0 2 Number of following row index structures (nm)
- 2 6nm List of nm row index structures. Each row index
- structure contains:
- Offset Size Contents
- 0 2 Index to first row below the page break
- 2 2 Index to first column of this page break
- 4 2 Index to last column of this page break
-
- The row indexes in the lists must be ordered ascending.
- If in BIFF8 a row contains several page breaks, they must be ordered
- ascending by start column index.
- """
- _REC_ID = 0x001B
-
- def __init__(self, breaks_list):
- self._rec_data = pack('<H', len(breaks_list))
- for r, c1, c2 in breaks_list:
- self._rec_data += pack('<3H', r, c1, c2)
-
-class VerticalPageBreaksRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It contains all
- vertical manual page breaks.
-
- Record VERTICALPAGEBREAKS, BIFF8:
- Offset Size Contents
- 0 2 Number of following column index structures (nm)
- 2 6nm List of nm column index structures. Each column index
- structure contains:
- Offset Size Contents
- 0 2 Index to first column following the page
- break
- 2 2 Index to first row of this page break
- 4 2 Index to last row of this page break
-
- The column indexes in the lists must be ordered ascending.
- If in BIFF8 a column contains several page breaks, they must be ordered
- ascending by start row index.
- """
- _REC_ID = 0x001A
-
- def __init__(self, breaks_list):
- self._rec_data = pack('<H', len(breaks_list))
- for r, c1, c2 in breaks_list:
- self._rec_data += pack('<3H', r, c1, c2)
-
-class HeaderRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It specifies the
- page header string for the current worksheet. If this record is not
- present or completely empty (record size is 0), the sheet does not
- contain a page header.
-
- Record HEADER for non-empty page header, BIFF2-BIFF8:
- Offset Size Contents
- 0 var. Page header string
- BIFF2-BIFF7: Non-empty byte string, 8bit string
- length
- BIFF8: Non-empty Unicode string, 16bit string length
- The header string may contain special commands, i.e. placeholders for
- the page number, current date, or text formatting attributes. These
- fields are represented by single letters (exception: font name and
- size, see below) with a leading ampersand ("&"). If the ampersand
- is part of the regular header text, it will be duplicated ("&&"). The
- page header is divided into 3 sections: the left, the centred, and the
- right section. Each section is introduced by a special command. All
- text and all commands following are part of the selected section. Each
- section starts with the text formatting specified in the default font
- (first FONT record in the file). Active formatting attributes from
- a previous section do not go into the next section.
-
- The following table shows all available commands:
-
- Command Contents
- && The "&" character itself
- &L Start of the left section
- &C Start of the centred section
- &R Start of the right section
- &P Current page number
- &N Page count
- &D Current date
- &T Current time
- &A Sheet name (BIFF5-BIFF8)
- &F File name without path
- &Z File path without file name (BIFF8X)
- &G Picture (BIFF8X)
- &B Bold on/off (BIFF2-BIFF4)
- &I Italic on/off (BIFF2-BIFF4)
- &U Underlining on/off
- &E Double underlining on/off (BIFF5-BIFF8)
- &S Strikeout on/off
- &X Superscript on/off (BIFF5-BIFF8)
- &Y Subscript on/off (BIFF5-BIFF8)
- &"<fontname>" Set new font <fontname>
- &"<fontname>,<fontstyle>"
- Set new font with specified style <fontstyle>.
- The style <fontstyle> is in most cases one of
- "Regular", "Bold", "Italic", or "Bold Italic".
- But this setting is dependent on the used font,
- it may differ (localised style names, or "Standard",
- "Oblique", ...). (BIFF5-BIFF8)
- &<fontheight> Set font height in points (<fontheight> is a decimal value).
- If this command is followed by a plain number to be printed
- in the header, it will be separated from the font height
- with a space character.
-
- """
- _REC_ID = 0x0014
-
- def __init__(self, header_str):
- self._rec_data = upack2(header_str)
-
-class FooterRecord(BiffRecord):
- """
- Semantic is equal to HEADER record
- """
- _REC_ID = 0x0015
-
- def __init__(self, footer_str):
- self._rec_data = upack2(footer_str)
-
-
-class HCenterRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It specifies if the
- sheet is centred horizontally when printed.
-
- Record HCENTER, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Print sheet left aligned
- 1 = Print sheet centred horizontally
-
- """
- _REC_ID = 0x0083
-
- def __init__(self, is_horz_center):
- self._rec_data = pack('<H', is_horz_center)
-
-
-class VCenterRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It specifies if the
- sheet is centred vertically when printed.
-
- Record VCENTER, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Print sheet aligned at top page border
- 1 = Print sheet vertically centred
-
- """
- _REC_ID = 0x0084
-
- def __init__(self, is_vert_center):
- self._rec_data = pack('<H', is_vert_center)
-
-
-class LeftMarginRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It contains the left
- page margin of the current worksheet.
-
- Record LEFTMARGIN, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 8 Left page margin in inches
- (IEEE 754 floating-point value, 64bit double precision)
-
- """
- _REC_ID = 0x0026
-
- def __init__(self, margin):
- self._rec_data = pack('<d', margin)
-
-
-class RightMarginRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It contains the right
- page margin of the current worksheet.
-
- Offset Size Contents
- 0 8 Right page margin in inches
- (IEEE 754 floating-point value, 64?bit double precision)
-
- """
- _REC_ID = 0x0027
-
- def __init__(self, margin):
- self._rec_data = pack('<d', margin)
-
-class TopMarginRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It contains the top
- page margin of the current worksheet.
-
- Offset Size Contents
- 0 8 Top page margin in inches
- (IEEE 754 floating-point value, 64?bit double precision)
-
- """
- _REC_ID = 0x0028
-
- def __init__(self, margin):
- self._rec_data = pack('<d', margin)
-
-
-class BottomMarginRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It contains the bottom
- page margin of the current worksheet.
-
- Offset Size Contents
- 0 8 Bottom page margin in inches
- (IEEE 754 floating-point value, 64?bit double precision)
-
- """
- _REC_ID = 0x0029
-
- def __init__(self, margin):
- self._rec_data = pack('<d', margin)
-
-class SetupPageRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It stores the page
- format settings of the current sheet. The pages may be scaled in
- percent or by using an absolute number of pages. This setting is
- located in the WSBOOL record. If pages are scaled in percent,
- the scaling factor in this record is used, otherwise the "Fit to
- pages" values. One of the "Fit to pages" values may be 0. In this case
- the sheet is scaled to fit only to the other value.
-
- Record SETUP, BIFF5-BIFF8:
-
- Offset Size Contents
- 0 2 Paper size (see below)
- 2 2 Scaling factor in percent
- 4 2 Start page number
- 6 2 Fit worksheet width to this number of pages
- (0 = use as many as needed)
- 8 2 Fit worksheet height to this number of pages
- (0 = use as many as needed)
- 10 2 Option flags:
- Bit Mask Contents
- 0 0001H 0 = Print pages in columns
- 1 = Print pages in rows
- 1 0002H 0 = Landscape
- 1 = Portrait
- 2 0004H 1 = Paper size, scaling factor,
- paper orientation (portrait/landscape),
- print resolution and number of copies
- are not initialised
- 3 0008H 0 = Print coloured
- 1 = Print black and white
- 4 0010H 0 = Default print quality
- 1 = Draft quality
- 5 0020H 0 = Do not print cell notes
- 1 = Print cell notes
- 6 0040H 0 = Paper orientation setting is valid
- 1 = Paper orientation setting not
- initialised
- 7 0080H 0 = Automatic page numbers
- 1 = Use start page number
- The following flags are valid for BIFF8 only:
- 9 0200H 0 = Print notes as displayed
- 1 = Print notes at end of sheet
- 11-10 0C00H 00 = Print errors as displayed
- 01 = Do not print errors
- 10 = Print errors as "--"
- 11 = Print errors as "#N/A!"
- 12 2 Print resolution in dpi
- 14 2 Vertical print resolution in dpi
- 16 8 Header margin (IEEE 754 floating-point value,
- 64bit double precision)
- 24 8 Footer margin (IEEE 754 floating-point value,
- 64bit double precision)
- 32 2 Number of copies to print
-
-
- PAPER TYPES:
-
- Index Paper type Paper size
- 0 Undefined
- 1 Letter 8 1/2" x 11"
- 2 Letter small 8 1/2" x 11"
- 3 Tabloid 11" x 17"
- 4 Ledger 17" x 11"
- 5 Legal 8 1/2" x 14"
- 6 Statement 5 1/2" x 8 1/2"
- 7 Executive 7 1/4" x 10 1/2"
- 8 A3 297mm x 420mm
- 9 A4 210mm x 297mm
- 10 A4 small 210mm x 297mm
- 11 A5 148mm x 210mm
- 12 B4 (JIS) 257mm x 364mm
- 13 B5 (JIS) 182mm x 257mm
- 14 Folio 8 1/2" x 13"
- 15 Quarto 215mm x 275mm
- 16 10x14 10" x 14"
- 17 11x17 11" x 17"
- 18 Note 8 1/2" x 11"
- 19 Envelope #9 3 7/8" x 8 7/8"
- 20 Envelope #10 4 1/8" x 9 1/2"
- 21 Envelope #11 4 1/2" x 10 3/8"
- 22 Envelope #12 4 3/4" x 11"
- 23 Envelope #14 5" x 11 1/2"
- 24 C 17" x 22"
- 25 D 22" x 34"
- 26 E 34" x 44"
- 27 Envelope DL 110mm x 220mm
- 28 Envelope C5 162mm x 229mm
- 29 Envelope C3 324mm x 458mm
- 30 Envelope C4 229mm x 324mm
- 31 Envelope C6 114mm x 162mm
- 32 Envelope C6/C5 114mm x 229mm
- 33 B4 (ISO) 250mm x 353mm
- 34 B5 (ISO) 176mm x 250mm
- 35 B6 (ISO) 125mm x 176mm
- 36 Envelope Italy 110mm x 230mm
- 37 Envelope Monarch 3 7/8" x 7 1/2"
- 38 63/4 Envelope 3 5/8" x 6 1/2"
- 39 US Standard Fanfold 14 7/8" x 11"
- 40 German Std. Fanfold 8 1/2" x 12"
- 41 German Legal Fanfold 8 1/2" x 13"
- 42 B4 (ISO) 250mm x 353mm
- 43 Japanese Postcard 100mm x 148mm
- 44 9x11 9" x 11"
- 45 10x11 10" x 11"
- 46 15x11 15" x 11"
- 47 Envelope Invite 220mm x 220mm
- 48 Undefined
- 49 Undefined
- 50 Letter Extra 9 1/2" x 12"
- 51 Legal Extra 9 1/2" x 15"
- 52 Tabloid Extra 11 11/16" x 18"
- 53 A4 Extra 235mm x 322mm
- 54 Letter Transverse 8 1/2" x 11"
- 55 A4 Transverse 210mm x 297mm
- 56 Letter Extra Transv. 9 1/2" x 12"
- 57 Super A/A4 227mm x 356mm
- 58 Super B/A3 305mm x 487mm
- 59 Letter Plus 8 1/2" x 12 11/16"
- 60 A4 Plus 210mm x 330mm
- 61 A5 Transverse 148mm x 210mm
- 62 B5 (JIS) Transverse 182mm x 257mm
- 63 A3 Extra 322mm x 445mm
- 64 A5 Extra 174mm x 235mm
- 65 B5 (ISO) Extra 201mm x 276mm
- 66 A2 420mm x 594mm
- 67 A3 Transverse 297mm x 420mm
- 68 A3 Extra Transverse 322mm x 445mm
- 69 Dbl. Japanese Postcard 200mm x 148mm
- 70 A6 105mm x 148mm
- 71
- 72
- 73
- 74
- 75 Letter Rotated 11" x 8 1/2"
- 76 A3 Rotated 420mm x 297mm
- 77 A4 Rotated 297mm x 210mm
- 78 A5 Rotated 210mm x 148mm
- 79 B4 (JIS) Rotated 364mm x 257mm
- 80 B5 (JIS) Rotated 257mm x 182mm
- 81 Japanese Postcard Rot. 148mm x 100mm
- 82 Dbl. Jap. Postcard Rot. 148mm x 200mm
- 83 A6 Rotated 148mm x 105mm
- 84
- 85
- 86
- 87
- 88 B6 (JIS) 128mm x 182mm
- 89 B6 (JIS) Rotated 182mm x 128mm
- 90 12x11 12" x 11"
-
- """
- _REC_ID = 0x00A1
- def __init__(self, paper, scaling, start_num, fit_width_to, fit_height_to,
- options,
- hres, vres,
- header_margin, footer_margin,
- num_copies):
- self._rec_data = pack('<8H2dH', paper, scaling, start_num,
- fit_width_to, fit_height_to, \
- options,
- hres, vres,
- header_margin, footer_margin,
- num_copies)
-
-class NameRecord(BiffRecord):
- """
- This record is part of a Link Table. It contains the name and the token
- array of an internal defined name. Token arrays of defined names
- contain tokens with aberrant token classes.
-
- Record NAME, BIFF5/BIFF7:
- Offset Size Contents
- 0 2 Option flags, see below
- 2 1 Keyboard shortcut (only for command macro names, see below)
- 3 1 Length of the name (character count, ln)
- 4 2 Size of the formula data (sz)
- 6 2 0 = Global name, otherwise index to EXTERNSHEET record (one-based)
- 8 2 0 = Global name, otherwise index to sheet (one-based)
- 10 1 Length of menu text (character count, lm)
- 11 1 Length of description text (character count, ld)
- 12 1 Length of help topic text (character count, lh)
- 13 1 Length of status bar text (character count, ls)
- 14 ln Character array of the name
- 14+ln sz Formula data (RPN token array without size field, 4)
- 14+ln+sz lm Character array of menu text
- var. ld Character array of description text
- var. lh Character array of help topic text
- var. ls Character array of status bar text
-
- Record NAME, BIFF8:
- Offset Size Contents
- 0 2 Option flags, see below
- 2 1 Keyboard shortcut (only for command macro names, see below)
- 3 1 Length of the name (character count, ln)
- 4 2 Size of the formula data (sz)
- 6 2 Not used
- 8 2 0 = Global name, otherwise index to sheet (one-based)
- 10 1 Length of menu text (character count, lm)
- 11 1 Length of description text (character count, ld)
- 12 1 Length of help topic text (character count, lh)
- 13 1 Length of status bar text (character count, ls)
- 14 var. Name (Unicode string without length field, 3.4)
- var. sz Formula data (RPN token array without size field, 4)
- [var.] var. (optional, only if lm > 0) Menu text (Unicode string without length field, 3.4)
- [var.] var. (optional, only if ld > 0) Description text (Unicode string without length field, 3.4)
- [var.] var. (optional, only if lh > 0) Help topic text (Unicode string without length field, 3.4)
- [var.] var. (optional, only if ls > 0) Status bar text (Unicode string without length field, 3.4)
- """
- _REC_ID = 0x0018
-
- def __init__(self, options, keyboard_shortcut, name, sheet_index, rpn, menu_text='', desc_text='', help_text='', status_text=''):
- if type(name) == int:
- uname = chr(name)
- else:
- uname = upack1(name)[1:]
- uname_len = len(uname)
-
- #~ self._rec_data = pack('<HBBHHHBBBB%ds%ds' % (uname_len, len(rpn)), options, keyboard_shortcut, uname_len, len(rpn), 0x0000, sheet_index, len(menu_text), len(desc_text), len(help_text), len(status_text), uname, rpn) + menu_text + desc_text + help_text + status_text
- self._rec_data = pack('<HBBHHHBBBBB%ds%ds' % (uname_len, len(rpn)), options, keyboard_shortcut, uname_len, len(rpn), 0x0000, sheet_index, 0x00, len(menu_text), len(desc_text), len(help_text), len(status_text), uname, rpn) + menu_text + desc_text + help_text + status_text
-
-# Excel (both 2003 and 2007) don't like refs
-# split over a record boundary, which is what the
-# standard BiffRecord.get method does.
-
-# 8224 max data bytes in a BIFF record
-# 6 bytes per ref
-# 1370 = floor((8224 - 2) / 6.0) max refs in a record
-
-_maxRefPerRecord = 1370
-
-class ExternSheetRecord(BiffRecord):
- """
- In BIFF8 the record stores a list with indexes to SUPBOOK
- records (list of REF structures, 6.100). See 5.10.3 for
- details about external references in BIFF8.
-
- Record EXTERNSHEET, BIFF8:
- Offset Size Contents
- 0 2 Number of following REF structures (nm)
- 2 6nm List of nm REF structures. Each REF contains the following data:
- Offset Size Contents
- 0 2 Index to SUPBOOK record
- 2 2 Index to first SUPBOOK sheet
- 4 2 Index to last SUPBOOK sheet
- """
- _REC_ID = 0x0017
-
- def __init__(self, refs):
-
- # do we always need this ref? or only if there are no refs?
- # (I believe that if there are no refs then we should not generate the link table - Ruben)
- #refs.insert(0, (0,0,0))
-
- self.refs = refs
-
- def get(self):
- res = []
- nrefs = len(self.refs)
- for idx in xrange(0, nrefs, _maxRefPerRecord):
- chunk = self.refs[idx:idx+_maxRefPerRecord]
- krefs = len(chunk)
- if idx: # CONTINUE record
- header = pack("<HH", 0x003C, 6 * krefs)
- else: # ExternSheetRecord
- header = pack("<HHH", self._REC_ID, 6 * krefs + 2, nrefs)
- res.append(header)
- res.extend([pack("<HHH", *r) for r in chunk])
- return ''.join(res)
-
-class SupBookRecord(BiffRecord):
- """
- This record mainly stores the URL of an external document
- and a list of sheet names inside this document. Furthermore
- it is used to store DDE and OLE object links, or to indicate
- an internal 3D reference or an add-in function. See 5.10.3
- for details about external references in BIFF8.
-
- """
- _REC_ID = 0x01AE
-
-class InternalReferenceSupBookRecord(SupBookRecord):
- """
- In each file occurs a SUPBOOK that is used for internal 3D
- references. It stores the number of sheets of the own document.
-
- Record SUPBOOK for 3D references, BIFF8:
- Offset Size Contents
- 0 2 Number of sheets in this document
- 2 2 01H 04H (relict of BIFF5/BIFF7, the byte string "<04H>", see 3.9.1)
-
- """
-
- def __init__(self, num_sheets):
- self._rec_data = pack('<HBB', num_sheets, 0x01, 0x04)
-
-class XcallSupBookRecord(SupBookRecord):
- """
- Add-in function names are stored in EXTERNNAME records following this record.
-
- Offset Size Contents
- 0 2 0001H
- 2 2 01H 3AH (relict of BIFF5, the byte string ':', see EXTERNSHEET record, 5.41)
-
- """
-
- def __init__(self):
- self._rec_data = pack('<HBB', 1, 0x01, 0x3A)
-
-
-class ExternnameRecord(BiffRecord):
- """
- Record EXTERNNAME for external names and Analysis add-in functions, BIFF5-BIFF8:
- Offset Size Contents
- 0 2 Option flags (see below)
- 2 2 0 for global names, or:
- BIFF5: One-based index to EXTERNSHEET record containing the sheet name,
- BIFF8: One-based index to sheet list in preceding EXTERNALBOOK record.
- 4 2 Not used
- 6 var. BIFF5: Name (byte string, 8-bit string length, ?2.5.2).
- BIFF8: Name (Unicode string, 8-bit string length, ?2.5.3).
- See DEFINEDNAME record (?5.33) for a list of built-in names, if the built-in flag is set
- in the option flags above.
- var. var. Formula data (RPN token array, ?3)
-
- Option flags for external names (BIFF5-BIFF8)
- Bit Mask Contents
- 0 0001H 0 = Standard name; 1 = Built-in name
- 1 0002H 0 = Manual link; 1 = Automatic link (DDE links and OLE links only)
- 2 0004H 1 = Picture link (DDE links and OLE links only)
- 3 0008H 1 = This is the StdDocumentName identifier (DDE links only)
- 4 0010H 1 = OLE link
- 14-5 7FE0H Clipboard format of last successful update (DDE links and OLE links only)
- 15 8000H 1 = Iconified picture link (BIFF8 OLE links only)
- """
- _REC_ID = 0x0023
-
- def __init__(self, options=0, index=0, name=None, fmla=None):
- self._rec_data = pack('<HHH', options, index, 0) + upack1(name) + fmla
-
diff --git a/tablib/packages/xlwt/Bitmap.py b/tablib/packages/xlwt/Bitmap.py
deleted file mode 100644
index d271665..0000000
--- a/tablib/packages/xlwt/Bitmap.py
+++ /dev/null
@@ -1,262 +0,0 @@
-# -*- coding: windows-1251 -*-
-
-# Portions are Copyright (C) 2005 Roman V. Kiseliov
-# Portions are Copyright (c) 2004 Evgeny Filatov <fufff@users.sourceforge.net>
-# Portions are Copyright (c) 2002-2004 John McNamara (Perl Spreadsheet::WriteExcel)
-
-from BIFFRecords import BiffRecord
-from struct import *
-
-
-def _size_col(sheet, col):
- return sheet.col_width(col)
-
-
-def _size_row(sheet, row):
- return sheet.row_height(row)
-
-
-def _position_image(sheet, row_start, col_start, x1, y1, width, height):
- """Calculate the vertices that define the position of the image as required by
- the OBJ record.
-
- +------------+------------+
- | A | B |
- +-----+------------+------------+
- | |(x1,y1) | |
- | 1 |(A1)._______|______ |
- | | | | |
- | | | | |
- +-----+----| BITMAP |-----+
- | | | | |
- | 2 | |______________. |
- | | | (B2)|
- | | | (x2,y2)|
- +---- +------------+------------+
-
- Example of a bitmap that covers some of the area from cell A1 to cell B2.
-
- Based on the width and height of the bitmap we need to calculate 8 vars:
- col_start, row_start, col_end, row_end, x1, y1, x2, y2.
- The width and height of the cells are also variable and have to be taken into
- account.
- The values of col_start and row_start are passed in from the calling
- function. The values of col_end and row_end are calculated by subtracting
- the width and height of the bitmap from the width and height of the
- underlying cells.
- The vertices are expressed as a percentage of the underlying cell width as
- follows (rhs values are in pixels):
-
- x1 = X / W *1024
- y1 = Y / H *256
- x2 = (X-1) / W *1024
- y2 = (Y-1) / H *256
-
- Where: X is distance from the left side of the underlying cell
- Y is distance from the top of the underlying cell
- W is the width of the cell
- H is the height of the cell
-
- Note: the SDK incorrectly states that the height should be expressed as a
- percentage of 1024.
-
- col_start - Col containing upper left corner of object
- row_start - Row containing top left corner of object
- x1 - Distance to left side of object
- y1 - Distance to top of object
- width - Width of image frame
- height - Height of image frame
-
- """
- # Adjust start column for offsets that are greater than the col width
- while x1 >= _size_col(sheet, col_start):
- x1 -= _size_col(sheet, col_start)
- col_start += 1
- # Adjust start row for offsets that are greater than the row height
- while y1 >= _size_row(sheet, row_start):
- y1 -= _size_row(sheet, row_start)
- row_start += 1
- # Initialise end cell to the same as the start cell
- row_end = row_start # Row containing bottom right corner of object
- col_end = col_start # Col containing lower right corner of object
- width = width + x1 - 1
- height = height + y1 - 1
- # Subtract the underlying cell widths to find the end cell of the image
- while (width >= _size_col(sheet, col_end)):
- width -= _size_col(sheet, col_end)
- col_end += 1
- # Subtract the underlying cell heights to find the end cell of the image
- while (height >= _size_row(sheet, row_end)):
- height -= _size_row(sheet, row_end)
- row_end += 1
- # Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell
- # with zero height or width.
- if ((_size_col(sheet, col_start) == 0) or (_size_col(sheet, col_end) == 0)
- or (_size_row(sheet, row_start) == 0) or (_size_row(sheet, row_end) == 0)):
- return
- # Convert the pixel values to the percentage value expected by Excel
- x1 = int(float(x1) / _size_col(sheet, col_start) * 1024)
- y1 = int(float(y1) / _size_row(sheet, row_start) * 256)
- # Distance to right side of object
- x2 = int(float(width) / _size_col(sheet, col_end) * 1024)
- # Distance to bottom of object
- y2 = int(float(height) / _size_row(sheet, row_end) * 256)
- return (col_start, x1, row_start, y1, col_end, x2, row_end, y2)
-
-
-class ObjBmpRecord(BiffRecord):
- _REC_ID = 0x005D # Record identifier
-
- def __init__(self, row, col, sheet, im_data_bmp, x, y, scale_x, scale_y):
- # Scale the frame of the image.
- width = im_data_bmp.width * scale_x
- height = im_data_bmp.height * scale_y
-
- # Calculate the vertices of the image and write the OBJ record
- coordinates = _position_image(sheet, row, col, x, y, width, height)
- # print coordinates
- col_start, x1, row_start, y1, col_end, x2, row_end, y2 = coordinates
-
- """Store the OBJ record that precedes an IMDATA record. This could be generalise
- to support other Excel objects.
-
- """
- cObj = 0x0001 # Count of objects in file (set to 1)
- OT = 0x0008 # Object type. 8 = Picture
- id = 0x0001 # Object ID
- grbit = 0x0614 # Option flags
- colL = col_start # Col containing upper left corner of object
- dxL = x1 # Distance from left side of cell
- rwT = row_start # Row containing top left corner of object
- dyT = y1 # Distance from top of cell
- colR = col_end # Col containing lower right corner of object
- dxR = x2 # Distance from right of cell
- rwB = row_end # Row containing bottom right corner of object
- dyB = y2 # Distance from bottom of cell
- cbMacro = 0x0000 # Length of FMLA structure
- Reserved1 = 0x0000 # Reserved
- Reserved2 = 0x0000 # Reserved
- icvBack = 0x09 # Background colour
- icvFore = 0x09 # Foreground colour
- fls = 0x00 # Fill pattern
- fAuto = 0x00 # Automatic fill
- icv = 0x08 # Line colour
- lns = 0xff # Line style
- lnw = 0x01 # Line weight
- fAutoB = 0x00 # Automatic border
- frs = 0x0000 # Frame style
- cf = 0x0009 # Image format, 9 = bitmap
- Reserved3 = 0x0000 # Reserved
- cbPictFmla = 0x0000 # Length of FMLA structure
- Reserved4 = 0x0000 # Reserved
- grbit2 = 0x0001 # Option flags
- Reserved5 = 0x0000 # Reserved
-
- data = pack("<L", cObj)
- data += pack("<H", OT)
- data += pack("<H", id)
- data += pack("<H", grbit)
- data += pack("<H", colL)
- data += pack("<H", dxL)
- data += pack("<H", rwT)
- data += pack("<H", dyT)
- data += pack("<H", colR)
- data += pack("<H", dxR)
- data += pack("<H", rwB)
- data += pack("<H", dyB)
- data += pack("<H", cbMacro)
- data += pack("<L", Reserved1)
- data += pack("<H", Reserved2)
- data += pack("<B", icvBack)
- data += pack("<B", icvFore)
- data += pack("<B", fls)
- data += pack("<B", fAuto)
- data += pack("<B", icv)
- data += pack("<B", lns)
- data += pack("<B", lnw)
- data += pack("<B", fAutoB)
- data += pack("<H", frs)
- data += pack("<L", cf)
- data += pack("<H", Reserved3)
- data += pack("<H", cbPictFmla)
- data += pack("<H", Reserved4)
- data += pack("<H", grbit2)
- data += pack("<L", Reserved5)
-
- self._rec_data = data
-
-def _process_bitmap(bitmap):
- """Convert a 24 bit bitmap into the modified internal format used by Windows.
- This is described in BITMAPCOREHEADER and BITMAPCOREINFO structures in the
- MSDN library.
-
- """
- # Open file and binmode the data in case the platform needs it.
- fh = file(bitmap, "rb")
- try:
- # Slurp the file into a string.
- data = fh.read()
- finally:
- fh.close()
- # Check that the file is big enough to be a bitmap.
- if len(data) <= 0x36:
- raise Exception("bitmap doesn't contain enough data.")
- # The first 2 bytes are used to identify the bitmap.
- if (data[:2] != "BM"):
- raise Exception("bitmap doesn't appear to to be a valid bitmap image.")
- # Remove bitmap data: ID.
- data = data[2:]
- # Read and remove the bitmap size. This is more reliable than reading
- # the data size at offset 0x22.
- #
- size = unpack("<L", data[:4])[0]
- size -= 0x36 # Subtract size of bitmap header.
- size += 0x0C # Add size of BIFF header.
- data = data[4:]
- # Remove bitmap data: reserved, offset, header length.
- data = data[12:]
- # Read and remove the bitmap width and height. Verify the sizes.
- width, height = unpack("<LL", data[:8])
- data = data[8:]
- if (width > 0xFFFF):
- raise Exception("bitmap: largest image width supported is 65k.")
- if (height > 0xFFFF):
- raise Exception("bitmap: largest image height supported is 65k.")
- # Read and remove the bitmap planes and bpp data. Verify them.
- planes, bitcount = unpack("<HH", data[:4])
- data = data[4:]
- if (bitcount != 24):
- raise Exception("bitmap isn't a 24bit true color bitmap.")
- if (planes != 1):
- raise Exception("bitmap: only 1 plane supported in bitmap image.")
- # Read and remove the bitmap compression. Verify compression.
- compression = unpack("<L", data[:4])[0]
- data = data[4:]
- if (compression != 0):
- raise Exception("bitmap: compression not supported in bitmap image.")
- # Remove bitmap data: data size, hres, vres, colours, imp. colours.
- data = data[20:]
- # Add the BITMAPCOREHEADER data
- header = pack("<LHHHH", 0x000c, width, height, 0x01, 0x18)
- data = header + data
- return (width, height, size, data)
-
-
-class ImDataBmpRecord(BiffRecord):
- _REC_ID = 0x007F
-
- def __init__(self, filename):
- """Insert a 24bit bitmap image in a worksheet. The main record required is
- IMDATA but it must be proceeded by a OBJ record to define its position.
-
- """
- BiffRecord.__init__(self)
-
- self.width, self.height, self.size, data = _process_bitmap(filename)
- # Write the IMDATA record to store the bitmap data
- cf = 0x09
- env = 0x01
- lcb = self.size
- self._rec_data = pack("<HHL", cf, env, lcb) + data
-
-
diff --git a/tablib/packages/xlwt/Cell.py b/tablib/packages/xlwt/Cell.py
deleted file mode 100644
index 23adf8a..0000000
--- a/tablib/packages/xlwt/Cell.py
+++ /dev/null
@@ -1,243 +0,0 @@
-# -*- coding: windows-1252 -*-
-
-from struct import unpack, pack
-import BIFFRecords
-
-class StrCell(object):
- __slots__ = ["rowx", "colx", "xf_idx", "sst_idx"]
-
- def __init__(self, rowx, colx, xf_idx, sst_idx):
- self.rowx = rowx
- self.colx = colx
- self.xf_idx = xf_idx
- self.sst_idx = sst_idx
-
- def get_biff_data(self):
- # return BIFFRecords.LabelSSTRecord(self.rowx, self.colx, self.xf_idx, self.sst_idx).get()
- return pack('<5HL', 0x00FD, 10, self.rowx, self.colx, self.xf_idx, self.sst_idx)
-
-class BlankCell(object):
- __slots__ = ["rowx", "colx", "xf_idx"]
-
- def __init__(self, rowx, colx, xf_idx):
- self.rowx = rowx
- self.colx = colx
- self.xf_idx = xf_idx
-
- def get_biff_data(self):
- # return BIFFRecords.BlankRecord(self.rowx, self.colx, self.xf_idx).get()
- return pack('<5H', 0x0201, 6, self.rowx, self.colx, self.xf_idx)
-
-class MulBlankCell(object):
- __slots__ = ["rowx", "colx1", "colx2", "xf_idx"]
-
- def __init__(self, rowx, colx1, colx2, xf_idx):
- self.rowx = rowx
- self.colx1 = colx1
- self.colx2 = colx2
- self.xf_idx = xf_idx
-
- def get_biff_data(self):
- return BIFFRecords.MulBlankRecord(self.rowx,
- self.colx1, self.colx2, self.xf_idx).get()
-
-class NumberCell(object):
- __slots__ = ["rowx", "colx", "xf_idx", "number"]
-
- def __init__(self, rowx, colx, xf_idx, number):
- self.rowx = rowx
- self.colx = colx
- self.xf_idx = xf_idx
- self.number = float(number)
-
- def get_encoded_data(self):
- rk_encoded = 0
- num = self.number
-
- # The four possible kinds of RK encoding are *not* mutually exclusive.
- # The 30-bit integer variety picks up the most.
- # In the code below, the four varieties are checked in descending order
- # of bangs per buck, or not at all.
- # SJM 2007-10-01
-
- if -0x20000000 <= num < 0x20000000: # fits in 30-bit *signed* int
- inum = int(num)
- if inum == num: # survives round-trip
- # print "30-bit integer RK", inum, hex(inum)
- rk_encoded = 2 | (inum << 2)
- return 1, rk_encoded
-
- temp = num * 100
-
- if -0x20000000 <= temp < 0x20000000:
- # That was step 1: the coded value will fit in
- # a 30-bit signed integer.
- itemp = int(round(temp, 0))
- # That was step 2: "itemp" is the best candidate coded value.
- # Now for step 3: simulate the decoding,
- # to check for round-trip correctness.
- if itemp / 100.0 == num:
- # print "30-bit integer RK*100", itemp, hex(itemp)
- rk_encoded = 3 | (itemp << 2)
- return 1, rk_encoded
-
- if 0: # Cost of extra pack+unpack not justified by tiny yield.
- packed = pack('<d', num)
- w01, w23 = unpack('<2i', packed)
- if not w01 and not(w23 & 3):
- # 34 lsb are 0
- # print "float RK", w23, hex(w23)
- return 1, w23
-
- packed100 = pack('<d', temp)
- w01, w23 = unpack('<2i', packed100)
- if not w01 and not(w23 & 3):
- # 34 lsb are 0
- # print "float RK*100", w23, hex(w23)
- return 1, w23 | 1
-
- #print "Number"
- #print
- return 0, pack('<5Hd', 0x0203, 14, self.rowx, self.colx, self.xf_idx, num)
-
- def get_biff_data(self):
- isRK, value = self.get_encoded_data()
- if isRK:
- return pack('<5Hi', 0x27E, 10, self.rowx, self.colx, self.xf_idx, value)
- return value # NUMBER record already packed
-
-class BooleanCell(object):
- __slots__ = ["rowx", "colx", "xf_idx", "number"]
-
- def __init__(self, rowx, colx, xf_idx, number):
- self.rowx = rowx
- self.colx = colx
- self.xf_idx = xf_idx
- self.number = number
-
- def get_biff_data(self):
- return BIFFRecords.BoolErrRecord(self.rowx,
- self.colx, self.xf_idx, self.number, 0).get()
-
-error_code_map = {
- 0x00: 0, # Intersection of two cell ranges is empty
- 0x07: 7, # Division by zero
- 0x0F: 15, # Wrong type of operand
- 0x17: 23, # Illegal or deleted cell reference
- 0x1D: 29, # Wrong function or range name
- 0x24: 36, # Value range overflow
- 0x2A: 42, # Argument or function not available
- '#NULL!' : 0, # Intersection of two cell ranges is empty
- '#DIV/0!': 7, # Division by zero
- '#VALUE!': 36, # Wrong type of operand
- '#REF!' : 23, # Illegal or deleted cell reference
- '#NAME?' : 29, # Wrong function or range name
- '#NUM!' : 36, # Value range overflow
- '#N/A!' : 42, # Argument or function not available
-}
-
-class ErrorCell(object):
- __slots__ = ["rowx", "colx", "xf_idx", "number"]
-
- def __init__(self, rowx, colx, xf_idx, error_string_or_code):
- self.rowx = rowx
- self.colx = colx
- self.xf_idx = xf_idx
- try:
- self.number = error_code_map[error_string_or_code]
- except KeyError:
- raise Exception('Illegal error value (%r)' % error_string_or_code)
-
- def get_biff_data(self):
- return BIFFRecords.BoolErrRecord(self.rowx,
- self.colx, self.xf_idx, self.number, 1).get()
-
-class FormulaCell(object):
- __slots__ = ["rowx", "colx", "xf_idx", "frmla", "calc_flags"]
-
- def __init__(self, rowx, colx, xf_idx, frmla, calc_flags=0):
- self.rowx = rowx
- self.colx = colx
- self.xf_idx = xf_idx
- self.frmla = frmla
- self.calc_flags = calc_flags
-
- def get_biff_data(self):
- return BIFFRecords.FormulaRecord(self.rowx,
- self.colx, self.xf_idx, self.frmla.rpn(), self.calc_flags).get()
-
-# module-level function for *internal* use by the Row module
-
-def _get_cells_biff_data_mul(rowx, cell_items):
- # Return the BIFF data for all cell records in the row.
- # Adjacent BLANK|RK records are combined into MUL(BLANK|RK) records.
- pieces = []
- nitems = len(cell_items)
- i = 0
- while i < nitems:
- icolx, icell = cell_items[i]
- if isinstance(icell, NumberCell):
- isRK, value = icell.get_encoded_data()
- if not isRK:
- pieces.append(value) # pre-packed NUMBER record
- i += 1
- continue
- muldata = [(value, icell.xf_idx)]
- target = NumberCell
- elif isinstance(icell, BlankCell):
- muldata = [icell.xf_idx]
- target = BlankCell
- else:
- pieces.append(icell.get_biff_data())
- i += 1
- continue
- lastcolx = icolx
- j = i
- packed_record = ''
- for j in xrange(i+1, nitems):
- jcolx, jcell = cell_items[j]
- if jcolx != lastcolx + 1:
- nexti = j
- break
- if not isinstance(jcell, target):
- nexti = j
- break
- if target == NumberCell:
- isRK, value = jcell.get_encoded_data()
- if not isRK:
- packed_record = value
- nexti = j + 1
- break
- muldata.append((value, jcell.xf_idx))
- else:
- muldata.append(jcell.xf_idx)
- lastcolx = jcolx
- else:
- nexti = j + 1
- if target == NumberCell:
- if lastcolx == icolx:
- # RK record
- value, xf_idx = muldata[0]
- pieces.append(pack('<5Hi', 0x027E, 10, rowx, icolx, xf_idx, value))
- else:
- # MULRK record
- nc = lastcolx - icolx + 1
- pieces.append(pack('<4H', 0x00BD, 6 * nc + 6, rowx, icolx))
- pieces.append(''.join([pack('<Hi', xf_idx, value) for value, xf_idx in muldata]))
- pieces.append(pack('<H', lastcolx))
- else:
- if lastcolx == icolx:
- # BLANK record
- xf_idx = muldata[0]
- pieces.append(pack('<5H', 0x0201, 6, rowx, icolx, xf_idx))
- else:
- # MULBLANK record
- nc = lastcolx - icolx + 1
- pieces.append(pack('<4H', 0x00BE, 2 * nc + 6, rowx, icolx))
- pieces.append(''.join([pack('<H', xf_idx) for xf_idx in muldata]))
- pieces.append(pack('<H', lastcolx))
- if packed_record:
- pieces.append(packed_record)
- i = nexti
- return ''.join(pieces)
-
diff --git a/tablib/packages/xlwt/Column.py b/tablib/packages/xlwt/Column.py
deleted file mode 100644
index aac35bf..0000000
--- a/tablib/packages/xlwt/Column.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- coding: windows-1252 -*-
-
-from BIFFRecords import ColInfoRecord
-
-class Column(object):
- def __init__(self, colx, parent_sheet):
- if not(isinstance(colx, int) and 0 <= colx <= 255):
- raise ValueError("column index (%r) not an int in range(256)" % colx)
- self._index = colx
- self._parent = parent_sheet
- self._parent_wb = parent_sheet.get_parent()
- self._xf_index = 0x0F
-
- self.width = 0x0B92
- self.hidden = 0
- self.level = 0
- self.collapse = 0
-
- def set_style(self, style):
- self._xf_index = self._parent_wb.add_style(style)
-
- def width_in_pixels(self):
- # *** Approximation ****
- return int(round(self.width * 0.0272 + 0.446, 0))
-
- def get_biff_record(self):
- options = (self.hidden & 0x01) << 0
- options |= (self.level & 0x07) << 8
- options |= (self.collapse & 0x01) << 12
-
- return ColInfoRecord(self._index, self._index, self.width, self._xf_index, options).get()
-
-
-
diff --git a/tablib/packages/xlwt/CompoundDoc.py b/tablib/packages/xlwt/CompoundDoc.py
deleted file mode 100644
index f60856b..0000000
--- a/tablib/packages/xlwt/CompoundDoc.py
+++ /dev/null
@@ -1,516 +0,0 @@
-# -*- coding: windows-1252 -*-
-
-import sys
-import struct
-
-class Reader:
- def __init__(self, filename, dump = False):
- self.dump = dump
- self.STREAMS = {}
-
- doc = file(filename, 'rb').read()
- self.header, self.data = doc[0:512], doc[512:]
- del doc
-
- self.__build_header()
- self.__build_MSAT()
- self.__build_SAT()
- self.__build_directory()
- self.__build_short_sectors_data()
-
- if len(self.short_sectors_data) > 0:
- self.__build_SSAT()
- else:
- if self.dump and (self.total_ssat_sectors != 0 or self.ssat_start_sid != -2):
- print 'NOTE: header says that must be', self.total_ssat_sectors, 'short sectors'
- print 'NOTE: starting at', self.ssat_start_sid, 'sector'
- print 'NOTE: but file does not contains data in short sectors'
- self.ssat_start_sid = -2
- self.total_ssat_sectors = 0
- self.SSAT = [-2]
-
- for dentry in self.dir_entry_list[1:]:
- (did,
- sz, name,
- t, c,
- did_left, did_right, did_root,
- dentry_start_sid,
- stream_size
- ) = dentry
- stream_data = ''
- if stream_size > 0:
- if stream_size >= self.min_stream_size:
- args = (self.data, self.SAT, dentry_start_sid, self.sect_size)
- else:
- args = (self.short_sectors_data, self.SSAT, dentry_start_sid, self.short_sect_size)
- stream_data = self.get_stream_data(*args)
-
- if name != '':
- # BAD IDEA: names may be equal. NEED use full paths...
- self.STREAMS[name] = stream_data
-
-
- def __build_header(self):
- self.doc_magic = self.header[0:8]
-
- if self.doc_magic != '\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1':
- raise Exception, 'Not an OLE file.'
-
- self.file_uid = self.header[8:24]
- self.rev_num = self.header[24:26]
- self.ver_num = self.header[26:28]
- self.byte_order = self.header[28:30]
- self.log2_sect_size, = struct.unpack('<H', self.header[30:32])
- self.log2_short_sect_size, = struct.unpack('<H', self.header[32:34])
- self.total_sat_sectors, = struct.unpack('<L', self.header[44:48])
- self.dir_start_sid, = struct.unpack('<l', self.header[48:52])
- self.min_stream_size, = struct.unpack('<L', self.header[56:60])
- self.ssat_start_sid, = struct.unpack('<l', self.header[60:64])
- self.total_ssat_sectors, = struct.unpack('<L', self.header[64:68])
- self.msat_start_sid, = struct.unpack('<l', self.header[68:72])
- self.total_msat_sectors, = struct.unpack('<L', self.header[72:76])
-
- self.sect_size = 1 << self.log2_sect_size
- self.short_sect_size = 1 << self.log2_short_sect_size
-
- if self.dump:
- print 'file magic: '
- print_bin_data(self.doc_magic)
-
- print 'file uid: '
- print_bin_data(self.file_uid)
-
- print 'revision number: '
- print_bin_data(self.rev_num)
-
- print 'version number: '
- print_bin_data(self.ver_num)
-
- print 'byte order: '
- print_bin_data(self.byte_order)
-
- print 'sector size :', hex(self.sect_size), self.sect_size
- #print 'total sectors in file :', hex(self.total_sectors), self.total_sectors
- print 'short sector size :', hex(self.short_sect_size), self.short_sect_size
- print 'Total number of sectors used for the SAT :', hex(self.total_sat_sectors), self.total_sat_sectors
- print 'SID of first sector of the directory stream:', hex(self.dir_start_sid), self.dir_start_sid
- print 'Minimum size of a standard stream :', hex(self.min_stream_size), self.min_stream_size
- print 'SID of first sector of the SSAT :', hex(self.ssat_start_sid), self.ssat_start_sid
- print 'Total number of sectors used for the SSAT :', hex(self.total_ssat_sectors), self.total_ssat_sectors
- print 'SID of first additional sector of the MSAT :', hex(self.msat_start_sid), self.msat_start_sid
- print 'Total number of sectors used for the MSAT :', hex(self.total_msat_sectors), self.total_msat_sectors
-
-
- def __build_MSAT(self):
- self.MSAT = list(struct.unpack('<109l', self.header[76:]))
-
- next = self.msat_start_sid
- while next > 0:
- msat_sector = struct.unpack('<128l', self.data[next*self.sect_size:(next+1)*self.sect_size])
- self.MSAT.extend(msat_sector[:127])
- next = msat_sector[-1]
-
- if self.dump:
- print 'MSAT (header part): \n', self.MSAT[:109]
- print 'additional MSAT sectors: \n', self.MSAT[109:]
-
-
- def __build_SAT(self):
- sat_stream = ''.join([self.data[i*self.sect_size:(i+1)*self.sect_size] for i in self.MSAT if i >= 0])
-
- sat_sids_count = len(sat_stream) >> 2
- self.SAT = struct.unpack('<%dl' % sat_sids_count, sat_stream) # SIDs tuple
-
- if self.dump:
- print 'SAT sid count:\n', sat_sids_count
- print 'SAT content:\n', self.SAT
-
-
- def __build_SSAT(self):
- ssat_stream = self.get_stream_data(self.data, self.SAT, self.ssat_start_sid, self.sect_size)
-
- ssids_count = len(ssat_stream) >> 2
- self.SSAT = struct.unpack('<%dl' % ssids_count, ssat_stream)
-
- if self.dump:
- print 'SSID count:', ssids_count
- print 'SSAT content:\n', self.SSAT
-
-
- def __build_directory(self):
- dir_stream = self.get_stream_data(self.data, self.SAT, self.dir_start_sid, self.sect_size)
-
- self.dir_entry_list = []
-
- i = 0
- while i < len(dir_stream):
- dentry = dir_stream[i:i+128] # 128 -- dir entry size
- i += 128
-
- did = len(self.dir_entry_list)
- sz, = struct.unpack('<H', dentry[64:66])
- if sz > 0 :
- name = dentry[0:sz-2].decode('utf_16_le', 'replace')
- else:
- name = u''
- t, = struct.unpack('B', dentry[66])
- c, = struct.unpack('B', dentry[67])
- did_left , = struct.unpack('<l', dentry[68:72])
- did_right , = struct.unpack('<l', dentry[72:76])
- did_root , = struct.unpack('<l', dentry[76:80])
- dentry_start_sid , = struct.unpack('<l', dentry[116:120])
- stream_size , = struct.unpack('<L', dentry[120:124])
-
- self.dir_entry_list.extend([(did, sz, name, t, c,
- did_left, did_right, did_root,
- dentry_start_sid, stream_size)])
-
- if self.dump:
- dentry_types = {
- 0x00: 'Empty',
- 0x01: 'User storage',
- 0x02: 'User stream',
- 0x03: 'LockBytes',
- 0x04: 'Property',
- 0x05: 'Root storage'
- }
- node_colours = {
- 0x00: 'Red',
- 0x01: 'Black'
- }
- print 'total directory entries:', len(self.dir_entry_list)
-
- for dentry in self.dir_entry_list:
- (did, sz, name, t, c,
- did_left, did_right, did_root,
- dentry_start_sid, stream_size) = dentry
- print 'DID', did
- print 'Size of the used area of the character buffer of the name:', sz
- print 'dir entry name:', repr(name)
- print 'type of entry:', t, dentry_types[t]
- print 'entry colour:', c, node_colours[c]
- print 'left child DID :', did_left
- print 'right child DID:', did_right
- print 'root DID :', did_root
- print 'start SID :', dentry_start_sid
- print 'stream size :', stream_size
- if stream_size == 0:
- print 'stream is empty'
- elif stream_size >= self.min_stream_size:
- print 'stream stored as normal stream'
- else:
- print 'stream stored as short-stream'
-
-
- def __build_short_sectors_data(self):
- (did, sz, name, t, c,
- did_left, did_right, did_root,
- dentry_start_sid, stream_size) = self.dir_entry_list[0]
- assert t == 0x05 # Short-Stream Container Stream (SSCS) resides in Root Storage
- if stream_size == 0:
- self.short_sectors_data = ''
- else:
- self.short_sectors_data = self.get_stream_data(self.data, self.SAT, dentry_start_sid, self.sect_size)
-
-
- def get_stream_data(self, data, SAT, start_sid, sect_size):
- sid = start_sid
- chunks = [(sid, sid)]
- stream_data = ''
-
- while SAT[sid] >= 0:
- next_in_chain = SAT[sid]
- last_chunk_start, last_chunk_finish = chunks[-1]
- if next_in_chain == last_chunk_finish + 1:
- chunks[-1] = last_chunk_start, next_in_chain
- else:
- chunks.extend([(next_in_chain, next_in_chain)])
- sid = next_in_chain
- for s, f in chunks:
- stream_data += data[s*sect_size:(f+1)*sect_size]
- #print chunks
- return stream_data
-
-
-def print_bin_data(data):
- i = 0
- while i < len(data):
- j = 0
- while (i < len(data)) and (j < 16):
- c = '0x%02X' % ord(data[i])
- sys.stdout.write(c)
- sys.stdout.write(' ')
- i += 1
- j += 1
- print
- if i == 0:
- print '<NO DATA>'
-
-
-
-# This implementation writes only 'Root Entry', 'Workbook' streams
-# and 2 empty streams for aligning directory stream on sector boundary
-#
-# LAYOUT:
-# 0 header
-# 76 MSAT (1st part: 109 SID)
-# 512 workbook stream
-# ... additional MSAT sectors if streams' size > about 7 Mb == (109*512 * 128)
-# ... SAT
-# ... directory stream
-#
-# NOTE: this layout is "ad hoc". It can be more general. RTFM
-
-class XlsDoc:
- SECTOR_SIZE = 0x0200
- MIN_LIMIT = 0x1000
-
- SID_FREE_SECTOR = -1
- SID_END_OF_CHAIN = -2
- SID_USED_BY_SAT = -3
- SID_USED_BY_MSAT = -4
-
- def __init__(self):
- #self.book_stream = '' # padded
- self.book_stream_sect = []
-
- self.dir_stream = ''
- self.dir_stream_sect = []
-
- self.packed_SAT = ''
- self.SAT_sect = []
-
- self.packed_MSAT_1st = ''
- self.packed_MSAT_2nd = ''
- self.MSAT_sect_2nd = []
-
- self.header = ''
-
- def __build_directory(self): # align on sector boundary
- self.dir_stream = ''
-
- dentry_name = '\x00'.join('Root Entry\x00') + '\x00'
- dentry_name_sz = len(dentry_name)
- dentry_name_pad = '\x00'*(64 - dentry_name_sz)
- dentry_type = 0x05 # root storage
- dentry_colour = 0x01 # black
- dentry_did_left = -1
- dentry_did_right = -1
- dentry_did_root = 1
- dentry_start_sid = -2
- dentry_stream_sz = 0
-
- self.dir_stream += struct.pack('<64s H 2B 3l 9L l L L',
- dentry_name + dentry_name_pad,
- dentry_name_sz,
- dentry_type,
- dentry_colour,
- dentry_did_left,
- dentry_did_right,
- dentry_did_root,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,
- dentry_start_sid,
- dentry_stream_sz,
- 0
- )
-
- dentry_name = '\x00'.join('Workbook\x00') + '\x00'
- dentry_name_sz = len(dentry_name)
- dentry_name_pad = '\x00'*(64 - dentry_name_sz)
- dentry_type = 0x02 # user stream
- dentry_colour = 0x01 # black
- dentry_did_left = -1
- dentry_did_right = -1
- dentry_did_root = -1
- dentry_start_sid = 0
- dentry_stream_sz = self.book_stream_len
-
- self.dir_stream += struct.pack('<64s H 2B 3l 9L l L L',
- dentry_name + dentry_name_pad,
- dentry_name_sz,
- dentry_type,
- dentry_colour,
- dentry_did_left,
- dentry_did_right,
- dentry_did_root,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,
- dentry_start_sid,
- dentry_stream_sz,
- 0
- )
-
- # padding
- dentry_name = ''
- dentry_name_sz = len(dentry_name)
- dentry_name_pad = '\x00'*(64 - dentry_name_sz)
- dentry_type = 0x00 # empty
- dentry_colour = 0x01 # black
- dentry_did_left = -1
- dentry_did_right = -1
- dentry_did_root = -1
- dentry_start_sid = -2
- dentry_stream_sz = 0
-
- self.dir_stream += struct.pack('<64s H 2B 3l 9L l L L',
- dentry_name + dentry_name_pad,
- dentry_name_sz,
- dentry_type,
- dentry_colour,
- dentry_did_left,
- dentry_did_right,
- dentry_did_root,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,
- dentry_start_sid,
- dentry_stream_sz,
- 0
- ) * 2
-
- def __build_sat(self):
- # Build SAT
- book_sect_count = self.book_stream_len >> 9
- dir_sect_count = len(self.dir_stream) >> 9
-
- total_sect_count = book_sect_count + dir_sect_count
- SAT_sect_count = 0
- MSAT_sect_count = 0
- SAT_sect_count_limit = 109
- while total_sect_count > 128*SAT_sect_count or SAT_sect_count > SAT_sect_count_limit:
- SAT_sect_count += 1
- total_sect_count += 1
- if SAT_sect_count > SAT_sect_count_limit:
- MSAT_sect_count += 1
- total_sect_count += 1
- SAT_sect_count_limit += 127
-
-
- SAT = [self.SID_FREE_SECTOR]*128*SAT_sect_count
-
- sect = 0
- while sect < book_sect_count - 1:
- self.book_stream_sect.append(sect)
- SAT[sect] = sect + 1
- sect += 1
- self.book_stream_sect.append(sect)
- SAT[sect] = self.SID_END_OF_CHAIN
- sect += 1
-
- while sect < book_sect_count + MSAT_sect_count:
- self.MSAT_sect_2nd.append(sect)
- SAT[sect] = self.SID_USED_BY_MSAT
- sect += 1
-
- while sect < book_sect_count + MSAT_sect_count + SAT_sect_count:
- self.SAT_sect.append(sect)
- SAT[sect] = self.SID_USED_BY_SAT
- sect += 1
-
- while sect < book_sect_count + MSAT_sect_count + SAT_sect_count + dir_sect_count - 1:
- self.dir_stream_sect.append(sect)
- SAT[sect] = sect + 1
- sect += 1
- self.dir_stream_sect.append(sect)
- SAT[sect] = self.SID_END_OF_CHAIN
- sect += 1
-
- self.packed_SAT = struct.pack('<%dl' % (SAT_sect_count*128), *SAT)
-
- MSAT_1st = [self.SID_FREE_SECTOR]*109
- for i, SAT_sect_num in zip(range(0, 109), self.SAT_sect):
- MSAT_1st[i] = SAT_sect_num
- self.packed_MSAT_1st = struct.pack('<109l', *MSAT_1st)
-
- MSAT_2nd = [self.SID_FREE_SECTOR]*128*MSAT_sect_count
- if MSAT_sect_count > 0:
- MSAT_2nd[- 1] = self.SID_END_OF_CHAIN
-
- i = 109
- msat_sect = 0
- sid_num = 0
- while i < SAT_sect_count:
- if (sid_num + 1) % 128 == 0:
- #print 'link: ',
- msat_sect += 1
- if msat_sect < len(self.MSAT_sect_2nd):
- MSAT_2nd[sid_num] = self.MSAT_sect_2nd[msat_sect]
- else:
- #print 'sid: ',
- MSAT_2nd[sid_num] = self.SAT_sect[i]
- i += 1
- #print sid_num, MSAT_2nd[sid_num]
- sid_num += 1
-
- self.packed_MSAT_2nd = struct.pack('<%dl' % (MSAT_sect_count*128), *MSAT_2nd)
-
- #print vars()
- #print zip(range(0, sect), SAT)
- #print self.book_stream_sect
- #print self.MSAT_sect_2nd
- #print MSAT_2nd
- #print self.SAT_sect
- #print self.dir_stream_sect
-
-
- def __build_header(self):
- doc_magic = '\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1'
- file_uid = '\x00'*16
- rev_num = '\x3E\x00'
- ver_num = '\x03\x00'
- byte_order = '\xFE\xFF'
- log_sect_size = struct.pack('<H', 9)
- log_short_sect_size = struct.pack('<H', 6)
- not_used0 = '\x00'*10
- total_sat_sectors = struct.pack('<L', len(self.SAT_sect))
- dir_start_sid = struct.pack('<l', self.dir_stream_sect[0])
- not_used1 = '\x00'*4
- min_stream_size = struct.pack('<L', 0x1000)
- ssat_start_sid = struct.pack('<l', -2)
- total_ssat_sectors = struct.pack('<L', 0)
-
- if len(self.MSAT_sect_2nd) == 0:
- msat_start_sid = struct.pack('<l', -2)
- else:
- msat_start_sid = struct.pack('<l', self.MSAT_sect_2nd[0])
-
- total_msat_sectors = struct.pack('<L', len(self.MSAT_sect_2nd))
-
- self.header = ''.join([ doc_magic,
- file_uid,
- rev_num,
- ver_num,
- byte_order,
- log_sect_size,
- log_short_sect_size,
- not_used0,
- total_sat_sectors,
- dir_start_sid,
- not_used1,
- min_stream_size,
- ssat_start_sid,
- total_ssat_sectors,
- msat_start_sid,
- total_msat_sectors
- ])
-
-
- def save(self, file_name_or_filelike_obj, stream):
- # 1. Align stream on 0x1000 boundary (and therefore on sector boundary)
- padding = '\x00' * (0x1000 - (len(stream) % 0x1000))
- self.book_stream_len = len(stream) + len(padding)
-
- self.__build_directory()
- self.__build_sat()
- self.__build_header()
-
- f = file_name_or_filelike_obj
- we_own_it = not hasattr(f, 'write')
- if we_own_it:
- f = open(file_name_or_filelike_obj, 'wb')
- f.write(self.header)
- f.write(self.packed_MSAT_1st)
- f.write(stream)
- f.write(padding)
- f.write(self.packed_MSAT_2nd)
- f.write(self.packed_SAT)
- f.write(self.dir_stream)
- if we_own_it:
- f.close()
diff --git a/tablib/packages/xlwt/ExcelFormula.py b/tablib/packages/xlwt/ExcelFormula.py
deleted file mode 100644
index 698d970..0000000
--- a/tablib/packages/xlwt/ExcelFormula.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# -*- coding: windows-1252 -*-
-
-import ExcelFormulaParser, ExcelFormulaLexer
-import struct
-from antlr import ANTLRException
-
-
-class Formula(object):
- __slots__ = ["__init__", "__s", "__parser", "__sheet_refs", "__xcall_refs"]
-
-
- def __init__(self, s):
- try:
- self.__s = s
- lexer = ExcelFormulaLexer.Lexer(s)
- self.__parser = ExcelFormulaParser.Parser(lexer)
- self.__parser.formula()
- self.__sheet_refs = self.__parser.sheet_references
- self.__xcall_refs = self.__parser.xcall_references
- except ANTLRException, e:
- # print e
- raise ExcelFormulaParser.FormulaParseException, "can't parse formula " + s
-
- def get_references(self):
- return self.__sheet_refs, self.__xcall_refs
-
- def patch_references(self, patches):
- for offset, idx in patches:
- self.__parser.rpn = self.__parser.rpn[:offset] + struct.pack('<H', idx) + self.__parser.rpn[offset+2:]
-
- def text(self):
- return self.__s
-
- def rpn(self):
- '''
- Offset Size Contents
- 0 2 Size of the following formula data (sz)
- 2 sz Formula data (RPN token array)
- [2+sz] var. (optional) Additional data for specific tokens
-
- '''
- return struct.pack("<H", len(self.__parser.rpn)) + self.__parser.rpn
-
diff --git a/tablib/packages/xlwt/ExcelFormulaLexer.py b/tablib/packages/xlwt/ExcelFormulaLexer.py
deleted file mode 100644
index 5004d8e..0000000
--- a/tablib/packages/xlwt/ExcelFormulaLexer.py
+++ /dev/null
@@ -1,128 +0,0 @@
-# -*- coding: windows-1252 -*-
-
-import sys
-from antlr import EOF, CommonToken as Tok, TokenStream, TokenStreamException
-import struct
-import ExcelFormulaParser
-from re import compile as recompile, match, UNICODE, IGNORECASE, VERBOSE
-
-
-int_const_pattern = r"\d+\b"
-flt_const_pattern = r"""
- (?:
- (?: \d* \. \d+ ) # .1 .12 .123 etc 9.1 etc 98.1 etc
- |
- (?: \d+ \. ) # 1. 12. 123. etc
- )
- # followed by optional exponent part
- (?: [Ee] [+-]? \d+ ) ?
- """
-str_const_pattern = r'"(?:[^"]|"")*"'
-#range2d_pattern = recompile(r"\$?[A-I]?[A-Z]\$?\d+:\$?[A-I]?[A-Z]\$?\d+"
-ref2d_r1c1_pattern = r"[Rr]0*[1-9][0-9]*[Cc]0*[1-9][0-9]*"
-ref2d_pattern = r"\$?[A-I]?[A-Z]\$?0*[1-9][0-9]*"
-true_pattern = r"TRUE\b"
-false_pattern = r"FALSE\b"
-if_pattern = r"IF\b"
-choose_pattern = r"CHOOSE\b"
-name_pattern = r"\w[\.\w]*"
-quotename_pattern = r"'(?:[^']|'')*'" #### It's essential that this bracket be non-grouping.
-ne_pattern = r"<>"
-ge_pattern = r">="
-le_pattern = r"<="
-
-pattern_type_tuples = (
- (flt_const_pattern, ExcelFormulaParser.NUM_CONST),
- (int_const_pattern, ExcelFormulaParser.INT_CONST),
- (str_const_pattern, ExcelFormulaParser.STR_CONST),
-# (range2d_pattern , ExcelFormulaParser.RANGE2D),
- (ref2d_r1c1_pattern, ExcelFormulaParser.REF2D_R1C1),
- (ref2d_pattern , ExcelFormulaParser.REF2D),
- (true_pattern , ExcelFormulaParser.TRUE_CONST),
- (false_pattern , ExcelFormulaParser.FALSE_CONST),
- (if_pattern , ExcelFormulaParser.FUNC_IF),
- (choose_pattern , ExcelFormulaParser.FUNC_CHOOSE),
- (name_pattern , ExcelFormulaParser.NAME),
- (quotename_pattern, ExcelFormulaParser.QUOTENAME),
- (ne_pattern, ExcelFormulaParser.NE),
- (ge_pattern, ExcelFormulaParser.GE),
- (le_pattern, ExcelFormulaParser.LE),
-)
-
-_re = recompile(
- '(' + ')|('.join([i[0] for i in pattern_type_tuples]) + ')',
- VERBOSE+IGNORECASE)
-
-_toktype = [None] + [i[1] for i in pattern_type_tuples]
-# need dummy at start because re.MatchObject.lastindex counts from 1
-
-single_char_lookup = {
- '=': ExcelFormulaParser.EQ,
- '<': ExcelFormulaParser.LT,
- '>': ExcelFormulaParser.GT,
- '+': ExcelFormulaParser.ADD,
- '-': ExcelFormulaParser.SUB,
- '*': ExcelFormulaParser.MUL,
- '/': ExcelFormulaParser.DIV,
- ':': ExcelFormulaParser.COLON,
- ';': ExcelFormulaParser.SEMICOLON,
- ',': ExcelFormulaParser.COMMA,
- '(': ExcelFormulaParser.LP,
- ')': ExcelFormulaParser.RP,
- '&': ExcelFormulaParser.CONCAT,
- '%': ExcelFormulaParser.PERCENT,
- '^': ExcelFormulaParser.POWER,
- '!': ExcelFormulaParser.BANG,
- }
-
-class Lexer(TokenStream):
- def __init__(self, text):
- self._text = text[:]
- self._pos = 0
- self._line = 0
-
- def isEOF(self):
- return len(self._text) <= self._pos
-
- def curr_ch(self):
- return self._text[self._pos]
-
- def next_ch(self, n = 1):
- self._pos += n
-
- def is_whitespace(self):
- return self.curr_ch() in " \t\n\r\f\v"
-
- def match_pattern(self):
- m = _re.match(self._text, self._pos)
- if not m:
- return None
- self._pos = m.end(0)
- return Tok(type = _toktype[m.lastindex], text = m.group(0), col = m.start(0) + 1)
-
- def nextToken(self):
- # skip whitespace
- while not self.isEOF() and self.is_whitespace():
- self.next_ch()
- if self.isEOF():
- return Tok(type = EOF)
- # first, try to match token with 2 or more chars
- t = self.match_pattern()
- if t:
- return t
- # second, we want 1-char tokens
- te = self.curr_ch()
- try:
- ty = single_char_lookup[te]
- except KeyError:
- raise TokenStreamException(
- "Unexpected char %r in column %u." % (self.curr_ch(), self._pos))
- self.next_ch()
- return Tok(type=ty, text=te, col=self._pos)
-
-if __name__ == '__main__':
- try:
- for t in Lexer(""" 1.23 456 "abcd" R2C2 a1 iv65536 true false if choose a_name 'qname' <> >= <= """):
- print t
- except TokenStreamException, e:
- print "error:", e
diff --git a/tablib/packages/xlwt/ExcelFormulaParser.py b/tablib/packages/xlwt/ExcelFormulaParser.py
deleted file mode 100644
index 000a8a0..0000000
--- a/tablib/packages/xlwt/ExcelFormulaParser.py
+++ /dev/null
@@ -1,677 +0,0 @@
-### $ANTLR 2.7.7 (20060930): "xlwt/excel-formula.g" -> "ExcelFormulaParser.py"$
-### import antlr and other modules ..
-import sys
-import antlr
-
-version = sys.version.split()[0]
-if version < '2.2.1':
- False = 0
-if version < '2.3':
- True = not False
-### header action >>>
-import struct
-import Utils
-from UnicodeUtils import upack1
-from ExcelMagic import *
-
-_RVAdelta = {"R": 0, "V": 0x20, "A": 0x40}
-_RVAdeltaRef = {"R": 0, "V": 0x20, "A": 0x40, "D": 0x20}
-_RVAdeltaArea = {"R": 0, "V": 0x20, "A": 0x40, "D": 0}
-
-
-class FormulaParseException(Exception):
- """
- An exception indicating that a Formula could not be successfully parsed.
- """
-### header action <<<
-### preamble action>>>
-
-### preamble action <<<
-
-### import antlr.Token
-from antlr import Token
-### >>>The Known Token Types <<<
-SKIP = antlr.SKIP
-INVALID_TYPE = antlr.INVALID_TYPE
-EOF_TYPE = antlr.EOF_TYPE
-EOF = antlr.EOF
-NULL_TREE_LOOKAHEAD = antlr.NULL_TREE_LOOKAHEAD
-MIN_USER_TYPE = antlr.MIN_USER_TYPE
-TRUE_CONST = 4
-FALSE_CONST = 5
-STR_CONST = 6
-NUM_CONST = 7
-INT_CONST = 8
-FUNC_IF = 9
-FUNC_CHOOSE = 10
-NAME = 11
-QUOTENAME = 12
-EQ = 13
-NE = 14
-GT = 15
-LT = 16
-GE = 17
-LE = 18
-ADD = 19
-SUB = 20
-MUL = 21
-DIV = 22
-POWER = 23
-PERCENT = 24
-LP = 25
-RP = 26
-LB = 27
-RB = 28
-COLON = 29
-COMMA = 30
-SEMICOLON = 31
-REF2D = 32
-REF2D_R1C1 = 33
-BANG = 34
-CONCAT = 35
-
-class Parser(antlr.LLkParser):
- ### user action >>>
- ### user action <<<
-
- def __init__(self, *args, **kwargs):
- antlr.LLkParser.__init__(self, *args, **kwargs)
- self.tokenNames = _tokenNames
- ### __init__ header action >>>
- self.rpn = ""
- self.sheet_references = []
- self.xcall_references = []
- ### __init__ header action <<<
-
- def formula(self):
-
- pass
- self.expr("V")
-
- def expr(self,
- arg_type
- ):
-
- pass
- self.prec0_expr(arg_type)
- while True:
- if ((self.LA(1) >= EQ and self.LA(1) <= LE)):
- pass
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [EQ]:
- pass
- self.match(EQ)
- op = struct.pack('B', ptgEQ)
- elif la1 and la1 in [NE]:
- pass
- self.match(NE)
- op = struct.pack('B', ptgNE)
- elif la1 and la1 in [GT]:
- pass
- self.match(GT)
- op = struct.pack('B', ptgGT)
- elif la1 and la1 in [LT]:
- pass
- self.match(LT)
- op = struct.pack('B', ptgLT)
- elif la1 and la1 in [GE]:
- pass
- self.match(GE)
- op = struct.pack('B', ptgGE)
- elif la1 and la1 in [LE]:
- pass
- self.match(LE)
- op = struct.pack('B', ptgLE)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- self.prec0_expr(arg_type)
- self.rpn += op
- else:
- break
-
-
- def prec0_expr(self,
- arg_type
- ):
-
- pass
- self.prec1_expr(arg_type)
- while True:
- if (self.LA(1)==CONCAT):
- pass
- pass
- self.match(CONCAT)
- op = struct.pack('B', ptgConcat)
- self.prec1_expr(arg_type)
- self.rpn += op
- else:
- break
-
-
- def prec1_expr(self,
- arg_type
- ):
-
- pass
- self.prec2_expr(arg_type)
- while True:
- if (self.LA(1)==ADD or self.LA(1)==SUB):
- pass
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [ADD]:
- pass
- self.match(ADD)
- op = struct.pack('B', ptgAdd)
- elif la1 and la1 in [SUB]:
- pass
- self.match(SUB)
- op = struct.pack('B', ptgSub)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- self.prec2_expr(arg_type)
- self.rpn += op;
- # print "**prec1_expr4 %s" % arg_type
- else:
- break
-
-
- def prec2_expr(self,
- arg_type
- ):
-
- pass
- self.prec3_expr(arg_type)
- while True:
- if (self.LA(1)==MUL or self.LA(1)==DIV):
- pass
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [MUL]:
- pass
- self.match(MUL)
- op = struct.pack('B', ptgMul)
- elif la1 and la1 in [DIV]:
- pass
- self.match(DIV)
- op = struct.pack('B', ptgDiv)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- self.prec3_expr(arg_type)
- self.rpn += op
- else:
- break
-
-
- def prec3_expr(self,
- arg_type
- ):
-
- pass
- self.prec4_expr(arg_type)
- while True:
- if (self.LA(1)==POWER):
- pass
- pass
- self.match(POWER)
- op = struct.pack('B', ptgPower)
- self.prec4_expr(arg_type)
- self.rpn += op
- else:
- break
-
-
- def prec4_expr(self,
- arg_type
- ):
-
- pass
- self.prec5_expr(arg_type)
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [PERCENT]:
- pass
- self.match(PERCENT)
- self.rpn += struct.pack('B', ptgPercent)
- elif la1 and la1 in [EOF,EQ,NE,GT,LT,GE,LE,ADD,SUB,MUL,DIV,POWER,RP,COMMA,SEMICOLON,CONCAT]:
- pass
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
-
- def prec5_expr(self,
- arg_type
- ):
-
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,FUNC_IF,FUNC_CHOOSE,NAME,QUOTENAME,LP,REF2D]:
- pass
- self.primary(arg_type)
- elif la1 and la1 in [SUB]:
- pass
- self.match(SUB)
- self.primary(arg_type)
- self.rpn += struct.pack('B', ptgUminus)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
-
- def primary(self,
- arg_type
- ):
-
- str_tok = None
- int_tok = None
- num_tok = None
- ref2d_tok = None
- ref2d1_tok = None
- ref2d2_tok = None
- ref3d_ref2d = None
- ref3d_ref2d2 = None
- name_tok = None
- func_tok = None
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [TRUE_CONST]:
- pass
- self.match(TRUE_CONST)
- self.rpn += struct.pack("2B", ptgBool, 1)
- elif la1 and la1 in [FALSE_CONST]:
- pass
- self.match(FALSE_CONST)
- self.rpn += struct.pack("2B", ptgBool, 0)
- elif la1 and la1 in [STR_CONST]:
- pass
- str_tok = self.LT(1)
- self.match(STR_CONST)
- self.rpn += struct.pack("B", ptgStr) + upack1(str_tok.text[1:-1].replace("\"\"", "\""))
- elif la1 and la1 in [NUM_CONST]:
- pass
- num_tok = self.LT(1)
- self.match(NUM_CONST)
- self.rpn += struct.pack("<Bd", ptgNum, float(num_tok.text))
- elif la1 and la1 in [FUNC_IF]:
- pass
- self.match(FUNC_IF)
- self.match(LP)
- self.expr("V")
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [SEMICOLON]:
- pass
- self.match(SEMICOLON)
- elif la1 and la1 in [COMMA]:
- pass
- self.match(COMMA)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- self.rpn += struct.pack("<BBH", ptgAttr, 0x02, 0) # tAttrIf
- pos0 = len(self.rpn) - 2
- self.expr(arg_type)
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [SEMICOLON]:
- pass
- self.match(SEMICOLON)
- elif la1 and la1 in [COMMA]:
- pass
- self.match(COMMA)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- self.rpn += struct.pack("<BBH", ptgAttr, 0x08, 0) # tAttrSkip
- pos1 = len(self.rpn) - 2
- self.rpn = self.rpn[:pos0] + struct.pack("<H", pos1-pos0) + self.rpn[pos0+2:]
- self.expr(arg_type)
- self.match(RP)
- self.rpn += struct.pack("<BBH", ptgAttr, 0x08, 3) # tAttrSkip
- self.rpn += struct.pack("<BBH", ptgFuncVarR, 3, 1) # 3 = nargs, 1 = IF func
- pos2 = len(self.rpn)
- self.rpn = self.rpn[:pos1] + struct.pack("<H", pos2-(pos1+2)-1) + self.rpn[pos1+2:]
- elif la1 and la1 in [FUNC_CHOOSE]:
- pass
- self.match(FUNC_CHOOSE)
- arg_type = "R"
- rpn_chunks = []
- self.match(LP)
- self.expr("V")
- rpn_start = len(self.rpn)
- ref_markers = [len(self.sheet_references)]
- while True:
- if (self.LA(1)==COMMA or self.LA(1)==SEMICOLON):
- pass
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [SEMICOLON]:
- pass
- self.match(SEMICOLON)
- elif la1 and la1 in [COMMA]:
- pass
- self.match(COMMA)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- mark = len(self.rpn)
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,FUNC_IF,FUNC_CHOOSE,NAME,QUOTENAME,SUB,LP,REF2D]:
- pass
- self.expr(arg_type)
- elif la1 and la1 in [RP,COMMA,SEMICOLON]:
- pass
- self.rpn += struct.pack("B", ptgMissArg)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- rpn_chunks.append(self.rpn[mark:])
- ref_markers.append(len(self.sheet_references))
- else:
- break
-
- self.match(RP)
- self.rpn = self.rpn[:rpn_start]
- nc = len(rpn_chunks)
- chunklens = [len(chunk) for chunk in rpn_chunks]
- skiplens = [0] * nc
- skiplens[-1] = 3
- for ic in xrange(nc-1, 0, -1):
- skiplens[ic-1] = skiplens[ic] + chunklens[ic] + 4
- jump_pos = [2 * nc + 2]
- for ic in xrange(nc):
- jump_pos.append(jump_pos[-1] + chunklens[ic] + 4)
- chunk_shift = 2 * nc + 6 # size of tAttrChoose
- for ic in xrange(nc):
- for refx in xrange(ref_markers[ic], ref_markers[ic+1]):
- ref = self.sheet_references[refx]
- self.sheet_references[refx] = (ref[0], ref[1], ref[2] + chunk_shift)
- chunk_shift += 4 # size of tAttrSkip
- choose_rpn = []
- choose_rpn.append(struct.pack("<BBH", ptgAttr, 0x04, nc)) # 0x04 is tAttrChoose
- choose_rpn.append(struct.pack("<%dH" % (nc+1), *jump_pos))
- for ic in xrange(nc):
- choose_rpn.append(rpn_chunks[ic])
- choose_rpn.append(struct.pack("<BBH", ptgAttr, 0x08, skiplens[ic])) # 0x08 is tAttrSkip
- choose_rpn.append(struct.pack("<BBH", ptgFuncVarV, nc+1, 100)) # 100 is CHOOSE fn
- self.rpn += "".join(choose_rpn)
- elif la1 and la1 in [LP]:
- pass
- self.match(LP)
- self.expr(arg_type)
- self.match(RP)
- self.rpn += struct.pack("B", ptgParen)
- else:
- if (self.LA(1)==INT_CONST) and (_tokenSet_0.member(self.LA(2))):
- pass
- int_tok = self.LT(1)
- self.match(INT_CONST)
- # print "**int_const", int_tok.text
- int_value = int(int_tok.text)
- if int_value <= 65535:
- self.rpn += struct.pack("<BH", ptgInt, int_value)
- else:
- self.rpn += struct.pack("<Bd", ptgNum, float(int_value))
- elif (self.LA(1)==REF2D) and (_tokenSet_0.member(self.LA(2))):
- pass
- ref2d_tok = self.LT(1)
- self.match(REF2D)
- # print "**ref2d %s %s" % (ref2d_tok.text, arg_type)
- r, c = Utils.cell_to_packed_rowcol(ref2d_tok.text)
- ptg = ptgRefR + _RVAdeltaRef[arg_type]
- self.rpn += struct.pack("<B2H", ptg, r, c)
- elif (self.LA(1)==REF2D) and (self.LA(2)==COLON):
- pass
- ref2d1_tok = self.LT(1)
- self.match(REF2D)
- self.match(COLON)
- ref2d2_tok = self.LT(1)
- self.match(REF2D)
- r1, c1 = Utils.cell_to_packed_rowcol(ref2d1_tok.text)
- r2, c2 = Utils.cell_to_packed_rowcol(ref2d2_tok.text)
- ptg = ptgAreaR + _RVAdeltaArea[arg_type]
- self.rpn += struct.pack("<B4H", ptg, r1, r2, c1, c2)
- elif (self.LA(1)==INT_CONST or self.LA(1)==NAME or self.LA(1)==QUOTENAME) and (self.LA(2)==COLON or self.LA(2)==BANG):
- pass
- sheet1=self.sheet()
- sheet2 = sheet1
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [COLON]:
- pass
- self.match(COLON)
- sheet2=self.sheet()
- elif la1 and la1 in [BANG]:
- pass
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- self.match(BANG)
- ref3d_ref2d = self.LT(1)
- self.match(REF2D)
- ptg = ptgRef3dR + _RVAdeltaRef[arg_type]
- rpn_ref2d = ""
- r1, c1 = Utils.cell_to_packed_rowcol(ref3d_ref2d.text)
- rpn_ref2d = struct.pack("<3H", 0x0000, r1, c1)
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [COLON]:
- pass
- self.match(COLON)
- ref3d_ref2d2 = self.LT(1)
- self.match(REF2D)
- ptg = ptgArea3dR + _RVAdeltaArea[arg_type]
- r2, c2 = Utils.cell_to_packed_rowcol(ref3d_ref2d2.text)
- rpn_ref2d = struct.pack("<5H", 0x0000, r1, r2, c1, c2)
- elif la1 and la1 in [EOF,EQ,NE,GT,LT,GE,LE,ADD,SUB,MUL,DIV,POWER,PERCENT,RP,COMMA,SEMICOLON,CONCAT]:
- pass
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- self.rpn += struct.pack("<B", ptg)
- self.sheet_references.append((sheet1, sheet2, len(self.rpn)))
- self.rpn += rpn_ref2d
- elif (self.LA(1)==NAME) and (_tokenSet_0.member(self.LA(2))):
- pass
- name_tok = self.LT(1)
- self.match(NAME)
- raise Exception("[formula] found unexpected NAME token (%r)" % name_tok.txt)
- # #### TODO: handle references to defined names here
- elif (self.LA(1)==NAME) and (self.LA(2)==LP):
- pass
- func_tok = self.LT(1)
- self.match(NAME)
- func_toku = func_tok.text.upper()
- if func_toku in all_funcs_by_name:
- (opcode,
- min_argc,
- max_argc,
- func_type,
- arg_type_str) = all_funcs_by_name[func_toku]
- arg_type_list = list(arg_type_str)
- else:
- raise Exception("[formula] unknown function (%s)" % func_tok.text)
- # print "**func_tok1 %s %s" % (func_toku, func_type)
- xcall = opcode < 0
- if xcall:
- # The name of the add-in function is passed as the 1st arg
- # of the hidden XCALL function
- self.xcall_references.append((func_toku, len(self.rpn) + 1))
- self.rpn += struct.pack("<BHHH",
- ptgNameXR,
- 0xadde, # ##PATCHME## index to REF entry in EXTERNSHEET record
- 0xefbe, # ##PATCHME## one-based index to EXTERNNAME record
- 0x0000) # unused
- self.match(LP)
- arg_count=self.expr_list(arg_type_list, min_argc, max_argc)
- self.match(RP)
- if arg_count > max_argc or arg_count < min_argc:
- raise Exception, "%d parameters for function: %s" % (arg_count, func_tok.text)
- if xcall:
- func_ptg = ptgFuncVarR + _RVAdelta[func_type]
- self.rpn += struct.pack("<2BH", func_ptg, arg_count + 1, 255) # 255 is magic XCALL function
- elif min_argc == max_argc:
- func_ptg = ptgFuncR + _RVAdelta[func_type]
- self.rpn += struct.pack("<BH", func_ptg, opcode)
- elif arg_count == 1 and func_tok.text.upper() == "SUM":
- self.rpn += struct.pack("<BBH", ptgAttr, 0x10, 0) # tAttrSum
- else:
- func_ptg = ptgFuncVarR + _RVAdelta[func_type]
- self.rpn += struct.pack("<2BH", func_ptg, arg_count, opcode)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
-
- def sheet(self):
- ref = None
-
- sheet_ref_name = None
- sheet_ref_int = None
- sheet_ref_quote = None
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [NAME]:
- pass
- sheet_ref_name = self.LT(1)
- self.match(NAME)
- ref = sheet_ref_name.text
- elif la1 and la1 in [INT_CONST]:
- pass
- sheet_ref_int = self.LT(1)
- self.match(INT_CONST)
- ref = sheet_ref_int.text
- elif la1 and la1 in [QUOTENAME]:
- pass
- sheet_ref_quote = self.LT(1)
- self.match(QUOTENAME)
- ref = sheet_ref_quote.text[1:-1].replace("''", "'")
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- return ref
-
- def expr_list(self,
- arg_type_list, min_argc, max_argc
- ):
- arg_cnt = None
-
- arg_cnt = 0
- arg_type = arg_type_list[arg_cnt]
- # print "**expr_list1[%d] req=%s" % (arg_cnt, arg_type)
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,FUNC_IF,FUNC_CHOOSE,NAME,QUOTENAME,SUB,LP,REF2D]:
- pass
- self.expr(arg_type)
- arg_cnt += 1
- while True:
- if (self.LA(1)==COMMA or self.LA(1)==SEMICOLON):
- pass
- if arg_cnt < len(arg_type_list):
- arg_type = arg_type_list[arg_cnt]
- else:
- arg_type = arg_type_list[-1]
- if arg_type == "+":
- arg_type = arg_type_list[-2]
- # print "**expr_list2[%d] req=%s" % (arg_cnt, arg_type)
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [SEMICOLON]:
- pass
- self.match(SEMICOLON)
- elif la1 and la1 in [COMMA]:
- pass
- self.match(COMMA)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,FUNC_IF,FUNC_CHOOSE,NAME,QUOTENAME,SUB,LP,REF2D]:
- pass
- self.expr(arg_type)
- elif la1 and la1 in [RP,COMMA,SEMICOLON]:
- pass
- self.rpn += struct.pack("B", ptgMissArg)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- arg_cnt += 1
- else:
- break
-
- elif la1 and la1 in [RP]:
- pass
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- return arg_cnt
-
-
-_tokenNames = [
- "<0>",
- "EOF",
- "<2>",
- "NULL_TREE_LOOKAHEAD",
- "TRUE_CONST",
- "FALSE_CONST",
- "STR_CONST",
- "NUM_CONST",
- "INT_CONST",
- "FUNC_IF",
- "FUNC_CHOOSE",
- "NAME",
- "QUOTENAME",
- "EQ",
- "NE",
- "GT",
- "LT",
- "GE",
- "LE",
- "ADD",
- "SUB",
- "MUL",
- "DIV",
- "POWER",
- "PERCENT",
- "LP",
- "RP",
- "LB",
- "RB",
- "COLON",
- "COMMA",
- "SEMICOLON",
- "REF2D",
- "REF2D_R1C1",
- "BANG",
- "CONCAT"
-]
-
-
-### generate bit set
-def mk_tokenSet_0():
- ### var1
- data = [ 37681618946L, 0L]
- return data
-_tokenSet_0 = antlr.BitSet(mk_tokenSet_0())
-
diff --git a/tablib/packages/xlwt/ExcelMagic.py b/tablib/packages/xlwt/ExcelMagic.py
deleted file mode 100644
index a49ae1f..0000000
--- a/tablib/packages/xlwt/ExcelMagic.py
+++ /dev/null
@@ -1,862 +0,0 @@
-# -*- coding: ascii -*-
-"""
-lots of Excel Magic Numbers
-"""
-
-# Boundaries BIFF8+
-
-MAX_ROW = 65536
-MAX_COL = 256
-
-
-biff_records = {
- 0x0000: "DIMENSIONS",
- 0x0001: "BLANK",
- 0x0002: "INTEGER",
- 0x0003: "NUMBER",
- 0x0004: "LABEL",
- 0x0005: "BOOLERR",
- 0x0006: "FORMULA",
- 0x0007: "STRING",
- 0x0008: "ROW",
- 0x0009: "BOF",
- 0x000A: "EOF",
- 0x000B: "INDEX",
- 0x000C: "CALCCOUNT",
- 0x000D: "CALCMODE",
- 0x000E: "PRECISION",
- 0x000F: "REFMODE",
- 0x0010: "DELTA",
- 0x0011: "ITERATION",
- 0x0012: "PROTECT",
- 0x0013: "PASSWORD",
- 0x0014: "HEADER",
- 0x0015: "FOOTER",
- 0x0016: "EXTERNCOUNT",
- 0x0017: "EXTERNSHEET",
- 0x0018: "NAME",
- 0x0019: "WINDOWPROTECT",
- 0x001A: "VERTICALPAGEBREAKS",
- 0x001B: "HORIZONTALPAGEBREAKS",
- 0x001C: "NOTE",
- 0x001D: "SELECTION",
- 0x001E: "FORMAT",
- 0x001F: "FORMATCOUNT",
- 0x0020: "COLUMNDEFAULT",
- 0x0021: "ARRAY",
- 0x0022: "1904",
- 0x0023: "EXTERNNAME",
- 0x0024: "COLWIDTH",
- 0x0025: "DEFAULTROWHEIGHT",
- 0x0026: "LEFTMARGIN",
- 0x0027: "RIGHTMARGIN",
- 0x0028: "TOPMARGIN",
- 0x0029: "BOTTOMMARGIN",
- 0x002A: "PRINTHEADERS",
- 0x002B: "PRINTGRIDLINES",
- 0x002F: "FILEPASS",
- 0x0031: "FONT",
- 0x0036: "TABLE",
- 0x003C: "CONTINUE",
- 0x003D: "WINDOW1",
- 0x003E: "WINDOW2",
- 0x0040: "BACKUP",
- 0x0041: "PANE",
- 0x0042: "CODEPAGE",
- 0x0043: "XF",
- 0x0044: "IXFE",
- 0x0045: "EFONT",
- 0x004D: "PLS",
- 0x0050: "DCON",
- 0x0051: "DCONREF",
- 0x0053: "DCONNAME",
- 0x0055: "DEFCOLWIDTH",
- 0x0056: "BUILTINFMTCNT",
- 0x0059: "XCT",
- 0x005A: "CRN",
- 0x005B: "FILESHARING",
- 0x005C: "WRITEACCESS",
- 0x005D: "OBJ",
- 0x005E: "UNCALCED",
- 0x005F: "SAFERECALC",
- 0x0060: "TEMPLATE",
- 0x0063: "OBJPROTECT",
- 0x007D: "COLINFO",
- 0x007E: "RK",
- 0x007F: "IMDATA",
- 0x0080: "GUTS",
- 0x0081: "WSBOOL",
- 0x0082: "GRIDSET",
- 0x0083: "HCENTER",
- 0x0084: "VCENTER",
- 0x0085: "BOUNDSHEET",
- 0x0086: "WRITEPROT",
- 0x0087: "ADDIN",
- 0x0088: "EDG",
- 0x0089: "PUB",
- 0x008C: "COUNTRY",
- 0x008D: "HIDEOBJ",
- 0x008E: "BUNDLESOFFSET",
- 0x008F: "BUNDLEHEADER",
- 0x0090: "SORT",
- 0x0091: "SUB",
- 0x0092: "PALETTE",
- 0x0093: "STYLE",
- 0x0094: "LHRECORD",
- 0x0095: "LHNGRAPH",
- 0x0096: "SOUND",
- 0x0098: "LPR",
- 0x0099: "STANDARDWIDTH",
- 0x009A: "FNGROUPNAME",
- 0x009B: "FILTERMODE",
- 0x009C: "FNGROUPCOUNT",
- 0x009D: "AUTOFILTERINFO",
- 0x009E: "AUTOFILTER",
- 0x00A0: "SCL",
- 0x00A1: "SETUP",
- 0x00A9: "COORDLIST",
- 0x00AB: "GCW",
- 0x00AE: "SCENMAN",
- 0x00AF: "SCENARIO",
- 0x00B0: "SXVIEW",
- 0x00B1: "SXVD",
- 0x00B2: "SXVI",
- 0x00B4: "SXIVD",
- 0x00B5: "SXLI",
- 0x00B6: "SXPI",
- 0x00B8: "DOCROUTE",
- 0x00B9: "RECIPNAME",
- 0x00BC: "SHRFMLA",
- 0x00BD: "MULRK",
- 0x00BE: "MULBLANK",
- 0x00C1: "MMS",
- 0x00C2: "ADDMENU",
- 0x00C3: "DELMENU",
- 0x00C5: "SXDI",
- 0x00C6: "SXDB",
- 0x00C7: "SXFIELD",
- 0x00C8: "SXINDEXLIST",
- 0x00C9: "SXDOUBLE",
- 0x00CD: "SXSTRING",
- 0x00CE: "SXDATETIME",
- 0x00D0: "SXTBL",
- 0x00D1: "SXTBRGITEM",
- 0x00D2: "SXTBPG",
- 0x00D3: "OBPROJ",
- 0x00D5: "SXIDSTM",
- 0x00D6: "RSTRING",
- 0x00D7: "DBCELL",
- 0x00DA: "BOOKBOOL",
- 0x00DC: "SXEXT|PARAMQRY",
- 0x00DD: "SCENPROTECT",
- 0x00DE: "OLESIZE",
- 0x00DF: "UDDESC",
- 0x00E0: "XF",
- 0x00E1: "INTERFACEHDR",
- 0x00E2: "INTERFACEEND",
- 0x00E3: "SXVS",
- 0x00E5: "MERGEDCELLS",
- 0x00E9: "BITMAP",
- 0x00EB: "MSODRAWINGGROUP",
- 0x00EC: "MSODRAWING",
- 0x00ED: "MSODRAWINGSELECTION",
- 0x00F0: "SXRULE",
- 0x00F1: "SXEX",
- 0x00F2: "SXFILT",
- 0x00F6: "SXNAME",
- 0x00F7: "SXSELECT",
- 0x00F8: "SXPAIR",
- 0x00F9: "SXFMLA",
- 0x00FB: "SXFORMAT",
- 0x00FC: "SST",
- 0x00FD: "LABELSST",
- 0x00FF: "EXTSST",
- 0x0100: "SXVDEX",
- 0x0103: "SXFORMULA",
- 0x0122: "SXDBEX",
- 0x0137: "CHTRINSERT",
- 0x0138: "CHTRINFO",
- 0x013B: "CHTRCELLCONTENT",
- 0x013D: "TABID",
- 0x0140: "CHTRMOVERANGE",
- 0x014D: "CHTRINSERTTAB",
- 0x015F: "LABELRANGES",
- 0x0160: "USESELFS",
- 0x0161: "DSF",
- 0x0162: "XL5MODIFY",
- 0x0196: "CHTRHEADER",
- 0x01A9: "USERBVIEW",
- 0x01AA: "USERSVIEWBEGIN",
- 0x01AB: "USERSVIEWEND",
- 0x01AD: "QSI",
- 0x01AE: "SUPBOOK",
- 0x01AF: "PROT4REV",
- 0x01B0: "CONDFMT",
- 0x01B1: "CF",
- 0x01B2: "DVAL",
- 0x01B5: "DCONBIN",
- 0x01B6: "TXO",
- 0x01B7: "REFRESHALL",
- 0x01B8: "HLINK",
- 0x01BA: "CODENAME",
- 0x01BB: "SXFDBTYPE",
- 0x01BC: "PROT4REVPASS",
- 0x01BE: "DV",
- 0x01C0: "XL9FILE",
- 0x01C1: "RECALCID",
- 0x0200: "DIMENSIONS",
- 0x0201: "BLANK",
- 0x0203: "NUMBER",
- 0x0204: "LABEL",
- 0x0205: "BOOLERR",
- 0x0206: "FORMULA",
- 0x0207: "STRING",
- 0x0208: "ROW",
- 0x0209: "BOF",
- 0x020B: "INDEX",
- 0x0218: "NAME",
- 0x0221: "ARRAY",
- 0x0223: "EXTERNNAME",
- 0x0225: "DEFAULTROWHEIGHT",
- 0x0231: "FONT",
- 0x0236: "TABLE",
- 0x023E: "WINDOW2",
- 0x0243: "XF",
- 0x027E: "RK",
- 0x0293: "STYLE",
- 0x0406: "FORMULA",
- 0x0409: "BOF",
- 0x041E: "FORMAT",
- 0x0443: "XF",
- 0x04BC: "SHRFMLA",
- 0x0800: "SCREENTIP",
- 0x0803: "WEBQRYSETTINGS",
- 0x0804: "WEBQRYTABLES",
- 0x0809: "BOF",
- 0x0862: "SHEETLAYOUT",
- 0x0867: "SHEETPROTECTION",
- 0x1001: "UNITS",
- 0x1002: "ChartChart",
- 0x1003: "ChartSeries",
- 0x1006: "ChartDataformat",
- 0x1007: "ChartLineformat",
- 0x1009: "ChartMarkerformat",
- 0x100A: "ChartAreaformat",
- 0x100B: "ChartPieformat",
- 0x100C: "ChartAttachedlabel",
- 0x100D: "ChartSeriestext",
- 0x1014: "ChartChartformat",
- 0x1015: "ChartLegend",
- 0x1016: "ChartSerieslist",
- 0x1017: "ChartBar",
- 0x1018: "ChartLine",
- 0x1019: "ChartPie",
- 0x101A: "ChartArea",
- 0x101B: "ChartScatter",
- 0x101C: "ChartChartline",
- 0x101D: "ChartAxis",
- 0x101E: "ChartTick",
- 0x101F: "ChartValuerange",
- 0x1020: "ChartCatserrange",
- 0x1021: "ChartAxislineformat",
- 0x1022: "ChartFormatlink",
- 0x1024: "ChartDefaulttext",
- 0x1025: "ChartText",
- 0x1026: "ChartFontx",
- 0x1027: "ChartObjectLink",
- 0x1032: "ChartFrame",
- 0x1033: "BEGIN",
- 0x1034: "END",
- 0x1035: "ChartPlotarea",
- 0x103A: "Chart3D",
- 0x103C: "ChartPicf",
- 0x103D: "ChartDropbar",
- 0x103E: "ChartRadar",
- 0x103F: "ChartSurface",
- 0x1040: "ChartRadararea",
- 0x1041: "ChartAxisparent",
- 0x1043: "ChartLegendxn",
- 0x1044: "ChartShtprops",
- 0x1045: "ChartSertocrt",
- 0x1046: "ChartAxesused",
- 0x1048: "ChartSbaseref",
- 0x104A: "ChartSerparent",
- 0x104B: "ChartSerauxtrend",
- 0x104E: "ChartIfmt",
- 0x104F: "ChartPos",
- 0x1050: "ChartAlruns",
- 0x1051: "ChartAI",
- 0x105B: "ChartSerauxerrbar",
- 0x105D: "ChartSerfmt",
- 0x105F: "Chart3DDataFormat",
- 0x1060: "ChartFbi",
- 0x1061: "ChartBoppop",
- 0x1062: "ChartAxcext",
- 0x1063: "ChartDat",
- 0x1064: "ChartPlotgrowth",
- 0x1065: "ChartSiindex",
- 0x1066: "ChartGelframe",
- 0x1067: "ChartBoppcustom",
- 0xFFFF: ""
-}
-
-
-all_funcs_by_name = {
- # Includes Analysis ToolPak aka ATP aka add-in aka xcall functions,
- # distinguished by -ve opcode.
- # name: (opcode, min # args, max # args, func return type, func arg types)
- # + in func arg types means more of the same.
- 'ABS' : ( 24, 1, 1, 'V', 'V'),
- 'ACCRINT' : ( -1, 6, 7, 'V', 'VVVVVVV'),
- 'ACCRINTM' : ( -1, 3, 5, 'V', 'VVVVV'),
- 'ACOS' : ( 99, 1, 1, 'V', 'V'),
- 'ACOSH' : (233, 1, 1, 'V', 'V'),
- 'ADDRESS' : (219, 2, 5, 'V', 'VVVVV'),
- 'AMORDEGRC' : ( -1, 7, 7, 'V', 'VVVVVVV'),
- 'AMORLINC' : ( -1, 7, 7, 'V', 'VVVVVVV'),
- 'AND' : ( 36, 1, 30, 'V', 'D+'),
- 'AREAS' : ( 75, 1, 1, 'V', 'R'),
- 'ASC' : (214, 1, 1, 'V', 'V'),
- 'ASIN' : ( 98, 1, 1, 'V', 'V'),
- 'ASINH' : (232, 1, 1, 'V', 'V'),
- 'ATAN' : ( 18, 1, 1, 'V', 'V'),
- 'ATAN2' : ( 97, 2, 2, 'V', 'VV'),
- 'ATANH' : (234, 1, 1, 'V', 'V'),
- 'AVEDEV' : (269, 1, 30, 'V', 'D+'),
- 'AVERAGE' : ( 5, 1, 30, 'V', 'D+'),
- 'AVERAGEA' : (361, 1, 30, 'V', 'D+'),
- 'BAHTTEXT' : (368, 1, 1, 'V', 'V'),
- 'BESSELI' : ( -1, 2, 2, 'V', 'VV'),
- 'BESSELJ' : ( -1, 2, 2, 'V', 'VV'),
- 'BESSELK' : ( -1, 2, 2, 'V', 'VV'),
- 'BESSELY' : ( -1, 2, 2, 'V', 'VV'),
- 'BETADIST' : (270, 3, 5, 'V', 'VVVVV'),
- 'BETAINV' : (272, 3, 5, 'V', 'VVVVV'),
- 'BIN2DEC' : ( -1, 1, 1, 'V', 'V'),
- 'BIN2HEX' : ( -1, 1, 2, 'V', 'VV'),
- 'BIN2OCT' : ( -1, 1, 2, 'V', 'VV'),
- 'BINOMDIST' : (273, 4, 4, 'V', 'VVVV'),
- 'CEILING' : (288, 2, 2, 'V', 'VV'),
- 'CELL' : (125, 1, 2, 'V', 'VR'),
- 'CHAR' : (111, 1, 1, 'V', 'V'),
- 'CHIDIST' : (274, 2, 2, 'V', 'VV'),
- 'CHIINV' : (275, 2, 2, 'V', 'VV'),
- 'CHITEST' : (306, 2, 2, 'V', 'AA'),
- 'CHOOSE' : (100, 2, 30, 'R', 'VR+'),
- 'CLEAN' : (162, 1, 1, 'V', 'V'),
- 'CODE' : (121, 1, 1, 'V', 'V'),
- 'COLUMN' : ( 9, 0, 1, 'V', 'R'),
- 'COLUMNS' : ( 77, 1, 1, 'V', 'R'),
- 'COMBIN' : (276, 2, 2, 'V', 'VV'),
- 'COMPLEX' : ( -1, 2, 3, 'V', 'VVV'),
- 'CONCATENATE' : (336, 1, 30, 'V', 'V+'),
- 'CONFIDENCE' : (277, 3, 3, 'V', 'VVV'),
- 'CONVERT' : ( -1, 3, 3, 'V', 'VVV'),
- 'CORREL' : (307, 2, 2, 'V', 'AA'),
- 'COS' : ( 16, 1, 1, 'V', 'V'),
- 'COSH' : (230, 1, 1, 'V', 'V'),
- 'COUNT' : ( 0, 1, 30, 'V', 'D+'),
- 'COUNTA' : (169, 1, 30, 'V', 'D+'),
- 'COUNTBLANK' : (347, 1, 1, 'V', 'R'),
- 'COUNTIF' : (346, 2, 2, 'V', 'RV'),
- 'COUPDAYBS' : ( -1, 3, 5, 'V', 'VVVVV'),
- 'COUPDAYS' : ( -1, 3, 5, 'V', 'VVVVV'),
- 'COUPDAYSNC' : ( -1, 3, 5, 'V', 'VVVVV'),
- 'COUPNCD' : ( -1, 3, 5, 'V', 'VVVVV'),
- 'COUPNUM' : ( -1, 3, 5, 'V', 'VVVVV'),
- 'COUPPCD' : ( -1, 3, 5, 'V', 'VVVVV'),
- 'COVAR' : (308, 2, 2, 'V', 'AA'),
- 'CRITBINOM' : (278, 3, 3, 'V', 'VVV'),
- 'CUMIPMT' : ( -1, 6, 6, 'V', 'VVVVVV'),
- 'CUMPRINC' : ( -1, 6, 6, 'V', 'VVVVVV'),
- 'DATE' : ( 65, 3, 3, 'V', 'VVV'),
- 'DATEDIF' : (351, 3, 3, 'V', 'VVV'),
- 'DATEVALUE' : (140, 1, 1, 'V', 'V'),
- 'DAVERAGE' : ( 42, 3, 3, 'V', 'RRR'),
- 'DAY' : ( 67, 1, 1, 'V', 'V'),
- 'DAYS360' : (220, 2, 3, 'V', 'VVV'),
- 'DB' : (247, 4, 5, 'V', 'VVVVV'),
- 'DBCS' : (215, 1, 1, 'V', 'V'),
- 'DCOUNT' : ( 40, 3, 3, 'V', 'RRR'),
- 'DCOUNTA' : (199, 3, 3, 'V', 'RRR'),
- 'DDB' : (144, 4, 5, 'V', 'VVVVV'),
- 'DEC2BIN' : ( -1, 1, 2, 'V', 'VV'),
- 'DEC2HEX' : ( -1, 1, 2, 'V', 'VV'),
- 'DEC2OCT' : ( -1, 1, 2, 'V', 'VV'),
- 'DEGREES' : (343, 1, 1, 'V', 'V'),
- 'DELTA' : ( -1, 1, 2, 'V', 'VV'),
- 'DEVSQ' : (318, 1, 30, 'V', 'D+'),
- 'DGET' : (235, 3, 3, 'V', 'RRR'),
- 'DISC' : ( -1, 4, 5, 'V', 'VVVVV'),
- 'DMAX' : ( 44, 3, 3, 'V', 'RRR'),
- 'DMIN' : ( 43, 3, 3, 'V', 'RRR'),
- 'DOLLAR' : ( 13, 1, 2, 'V', 'VV'),
- 'DOLLARDE' : ( -1, 2, 2, 'V', 'VV'),
- 'DOLLARFR' : ( -1, 2, 2, 'V', 'VV'),
- 'DPRODUCT' : (189, 3, 3, 'V', 'RRR'),
- 'DSTDEV' : ( 45, 3, 3, 'V', 'RRR'),
- 'DSTDEVP' : (195, 3, 3, 'V', 'RRR'),
- 'DSUM' : ( 41, 3, 3, 'V', 'RRR'),
- 'DURATION' : ( -1, 5, 6, 'V', 'VVVVVV'),
- 'DVAR' : ( 47, 3, 3, 'V', 'RRR'),
- 'DVARP' : (196, 3, 3, 'V', 'RRR'),
- 'EDATE' : ( -1, 2, 2, 'V', 'VV'),
- 'EFFECT' : ( -1, 2, 2, 'V', 'VV'),
- 'EOMONTH' : ( -1, 1, 2, 'V', 'VV'),
- 'ERF' : ( -1, 1, 2, 'V', 'VV'),
- 'ERFC' : ( -1, 1, 1, 'V', 'V'),
- 'ERROR.TYPE' : (261, 1, 1, 'V', 'V'),
- 'EVEN' : (279, 1, 1, 'V', 'V'),
- 'EXACT' : (117, 2, 2, 'V', 'VV'),
- 'EXP' : ( 21, 1, 1, 'V', 'V'),
- 'EXPONDIST' : (280, 3, 3, 'V', 'VVV'),
- 'FACT' : (184, 1, 1, 'V', 'V'),
- 'FACTDOUBLE' : ( -1, 1, 1, 'V', 'V'),
- 'FALSE' : ( 35, 0, 0, 'V', '-'),
- 'FDIST' : (281, 3, 3, 'V', 'VVV'),
- 'FIND' : (124, 2, 3, 'V', 'VVV'),
- 'FINDB' : (205, 2, 3, 'V', 'VVV'),
- 'FINV' : (282, 3, 3, 'V', 'VVV'),
- 'FISHER' : (283, 1, 1, 'V', 'V'),
- 'FISHERINV' : (284, 1, 1, 'V', 'V'),
- 'FIXED' : ( 14, 2, 3, 'V', 'VVV'),
- 'FLOOR' : (285, 2, 2, 'V', 'VV'),
- 'FORECAST' : (309, 3, 3, 'V', 'VAA'),
- 'FREQUENCY' : (252, 2, 2, 'A', 'RR'),
- 'FTEST' : (310, 2, 2, 'V', 'AA'),
- 'FV' : ( 57, 3, 5, 'V', 'VVVVV'),
- 'FVSCHEDULE' : ( -1, 2, 2, 'V', 'VA'),
- 'GAMMADIST' : (286, 4, 4, 'V', 'VVVV'),
- 'GAMMAINV' : (287, 3, 3, 'V', 'VVV'),
- 'GAMMALN' : (271, 1, 1, 'V', 'V'),
- 'GCD' : ( -1, 1, 29, 'V', 'V+'),
- 'GEOMEAN' : (319, 1, 30, 'V', 'D+'),
- 'GESTEP' : ( -1, 1, 2, 'V', 'VV'),
- 'GETPIVOTDATA': (358, 2, 30, 'A', 'VAV+'),
- 'GROWTH' : ( 52, 1, 4, 'A', 'RRRV'),
- 'HARMEAN' : (320, 1, 30, 'V', 'D+'),
- 'HEX2BIN' : ( -1, 1, 2, 'V', 'VV'),
- 'HEX2DEC' : ( -1, 1, 1, 'V', 'V'),
- 'HEX2OCT' : ( -1, 1, 2, 'V', 'VV'),
- 'HLOOKUP' : (101, 3, 4, 'V', 'VRRV'),
- 'HOUR' : ( 71, 1, 1, 'V', 'V'),
- 'HYPERLINK' : (359, 1, 2, 'V', 'VV'),
- 'HYPGEOMDIST' : (289, 4, 4, 'V', 'VVVV'),
- 'IF' : ( 1, 2, 3, 'R', 'VRR'),
- 'IMABS' : ( -1, 1, 1, 'V', 'V'),
- 'IMAGINARY' : ( -1, 1, 1, 'V', 'V'),
- 'IMARGUMENT' : ( -1, 1, 1, 'V', 'V'),
- 'IMCONJUGATE' : ( -1, 1, 1, 'V', 'V'),
- 'IMCOS' : ( -1, 1, 1, 'V', 'V'),
- 'IMDIV' : ( -1, 2, 2, 'V', 'VV'),
- 'IMEXP' : ( -1, 1, 1, 'V', 'V'),
- 'IMLN' : ( -1, 1, 1, 'V', 'V'),
- 'IMLOG10' : ( -1, 1, 1, 'V', 'V'),
- 'IMLOG2' : ( -1, 1, 1, 'V', 'V'),
- 'IMPOWER' : ( -1, 2, 2, 'V', 'VV'),
- 'IMPRODUCT' : ( -1, 2, 2, 'V', 'VV'),
- 'IMREAL' : ( -1, 1, 1, 'V', 'V'),
- 'IMSIN' : ( -1, 1, 1, 'V', 'V'),
- 'IMSQRT' : ( -1, 1, 1, 'V', 'V'),
- 'IMSUB' : ( -1, 2, 2, 'V', 'VV'),
- 'IMSUM' : ( -1, 1, 29, 'V', 'V+'),
- 'INDEX' : ( 29, 2, 4, 'R', 'RVVV'),
- 'INDIRECT' : (148, 1, 2, 'R', 'VV'),
- 'INFO' : (244, 1, 1, 'V', 'V'),
- 'INT' : ( 25, 1, 1, 'V', 'V'),
- 'INTERCEPT' : (311, 2, 2, 'V', 'AA'),
- 'INTRATE' : ( -1, 4, 5, 'V', 'VVVVV'),
- 'IPMT' : (167, 4, 6, 'V', 'VVVVVV'),
- 'IRR' : ( 62, 1, 2, 'V', 'RV'),
- 'ISBLANK' : (129, 1, 1, 'V', 'V'),
- 'ISERR' : (126, 1, 1, 'V', 'V'),
- 'ISERROR' : ( 3, 1, 1, 'V', 'V'),
- 'ISEVEN' : ( -1, 1, 1, 'V', 'V'),
- 'ISLOGICAL' : (198, 1, 1, 'V', 'V'),
- 'ISNA' : ( 2, 1, 1, 'V', 'V'),
- 'ISNONTEXT' : (190, 1, 1, 'V', 'V'),
- 'ISNUMBER' : (128, 1, 1, 'V', 'V'),
- 'ISODD' : ( -1, 1, 1, 'V', 'V'),
- 'ISPMT' : (350, 4, 4, 'V', 'VVVV'),
- 'ISREF' : (105, 1, 1, 'V', 'R'),
- 'ISTEXT' : (127, 1, 1, 'V', 'V'),
- 'KURT' : (322, 1, 30, 'V', 'D+'),
- 'LARGE' : (325, 2, 2, 'V', 'RV'),
- 'LCM' : ( -1, 1, 29, 'V', 'V+'),
- 'LEFT' : (115, 1, 2, 'V', 'VV'),
- 'LEFTB' : (208, 1, 2, 'V', 'VV'),
- 'LEN' : ( 32, 1, 1, 'V', 'V'),
- 'LENB' : (211, 1, 1, 'V', 'V'),
- 'LINEST' : ( 49, 1, 4, 'A', 'RRVV'),
- 'LN' : ( 22, 1, 1, 'V', 'V'),
- 'LOG' : (109, 1, 2, 'V', 'VV'),
- 'LOG10' : ( 23, 1, 1, 'V', 'V'),
- 'LOGEST' : ( 51, 1, 4, 'A', 'RRVV'),
- 'LOGINV' : (291, 3, 3, 'V', 'VVV'),
- 'LOGNORMDIST' : (290, 3, 3, 'V', 'VVV'),
- 'LOOKUP' : ( 28, 2, 3, 'V', 'VRR'),
- 'LOWER' : (112, 1, 1, 'V', 'V'),
- 'MATCH' : ( 64, 2, 3, 'V', 'VRR'),
- 'MAX' : ( 7, 1, 30, 'V', 'D+'),
- 'MAXA' : (362, 1, 30, 'V', 'D+'),
- 'MDETERM' : (163, 1, 1, 'V', 'A'),
- 'MDURATION' : ( -1, 5, 6, 'V', 'VVVVVV'),
- 'MEDIAN' : (227, 1, 30, 'V', 'D+'),
- 'MID' : ( 31, 3, 3, 'V', 'VVV'),
- 'MIDB' : (210, 3, 3, 'V', 'VVV'),
- 'MIN' : ( 6, 1, 30, 'V', 'D+'),
- 'MINA' : (363, 1, 30, 'V', 'D+'),
- 'MINUTE' : ( 72, 1, 1, 'V', 'V'),
- 'MINVERSE' : (164, 1, 1, 'A', 'A'),
- 'MIRR' : ( 61, 3, 3, 'V', 'RVV'),
- 'MMULT' : (165, 2, 2, 'A', 'AA'),
- 'MOD' : ( 39, 2, 2, 'V', 'VV'),
- 'MODE' : (330, 1, 30, 'V', 'A+'), ################ weird #################
- 'MONTH' : ( 68, 1, 1, 'V', 'V'),
- 'MROUND' : ( -1, 2, 2, 'V', 'VV'),
- 'MULTINOMIAL' : ( -1, 1, 29, 'V', 'V+'),
- 'N' : (131, 1, 1, 'V', 'R'),
- 'NA' : ( 10, 0, 0, 'V', '-'),
- 'NEGBINOMDIST': (292, 3, 3, 'V', 'VVV'),
- 'NETWORKDAYS' : ( -1, 2, 3, 'V', 'VVR'),
- 'NOMINAL' : ( -1, 2, 2, 'V', 'VV'),
- 'NORMDIST' : (293, 4, 4, 'V', 'VVVV'),
- 'NORMINV' : (295, 3, 3, 'V', 'VVV'),
- 'NORMSDIST' : (294, 1, 1, 'V', 'V'),
- 'NORMSINV' : (296, 1, 1, 'V', 'V'),
- 'NOT' : ( 38, 1, 1, 'V', 'V'),
- 'NOW' : ( 74, 0, 0, 'V', '-'),
- 'NPER' : ( 58, 3, 5, 'V', 'VVVVV'),
- 'NPV' : ( 11, 2, 30, 'V', 'VD+'),
- 'OCT2BIN' : ( -1, 1, 2, 'V', 'VV'),
- 'OCT2DEC' : ( -1, 1, 1, 'V', 'V'),
- 'OCT2HEX' : ( -1, 1, 2, 'V', 'VV'),
- 'ODD' : (298, 1, 1, 'V', 'V'),
- 'ODDFPRICE' : ( -1, 9, 9, 'V', 'VVVVVVVVV'),
- 'ODDFYIELD' : ( -1, 9, 9, 'V', 'VVVVVVVVV'),
- 'ODDLPRICE' : ( -1, 8, 8, 'V', 'VVVVVVVV'),
- 'ODDLYIELD' : ( -1, 8, 8, 'V', 'VVVVVVVV'),
- 'OFFSET' : ( 78, 3, 5, 'R', 'RVVVV'),
- 'OR' : ( 37, 1, 30, 'V', 'D+'),
- 'PEARSON' : (312, 2, 2, 'V', 'AA'),
- 'PERCENTILE' : (328, 2, 2, 'V', 'RV'),
- 'PERCENTRANK' : (329, 2, 3, 'V', 'RVV'),
- 'PERMUT' : (299, 2, 2, 'V', 'VV'),
- 'PHONETIC' : (360, 1, 1, 'V', 'R'),
- 'PI' : ( 19, 0, 0, 'V', '-'),
- 'PMT' : ( 59, 3, 5, 'V', 'VVVVV'),
- 'POISSON' : (300, 3, 3, 'V', 'VVV'),
- 'POWER' : (337, 2, 2, 'V', 'VV'),
- 'PPMT' : (168, 4, 6, 'V', 'VVVVVV'),
- 'PRICE' : ( -1, 6, 7, 'V', 'VVVVVVV'),
- 'PRICEDISC' : ( -1, 4, 5, 'V', 'VVVVV'),
- 'PRICEMAT' : ( -1, 5, 6, 'V', 'VVVVVV'),
- 'PROB' : (317, 3, 4, 'V', 'AAVV'),
- 'PRODUCT' : (183, 1, 30, 'V', 'D+'),
- 'PROPER' : (114, 1, 1, 'V', 'V'),
- 'PV' : ( 56, 3, 5, 'V', 'VVVVV'),
- 'QUARTILE' : (327, 2, 2, 'V', 'RV'),
- 'QUOTIENT' : ( -1, 2, 2, 'V', 'VV'),
- 'RADIANS' : (342, 1, 1, 'V', 'V'),
- 'RAND' : ( 63, 0, 0, 'V', '-'),
- 'RANDBETWEEN' : ( -1, 2, 2, 'V', 'VV'),
- 'RANK' : (216, 2, 3, 'V', 'VRV'),
- 'RATE' : ( 60, 3, 6, 'V', 'VVVVVV'),
- 'RECEIVED' : ( -1, 4, 5, 'V', 'VVVVV'),
- 'REPLACE' : (119, 4, 4, 'V', 'VVVV'),
- 'REPLACEB' : (207, 4, 4, 'V', 'VVVV'),
- 'REPT' : ( 30, 2, 2, 'V', 'VV'),
- 'RIGHT' : (116, 1, 2, 'V', 'VV'),
- 'RIGHTB' : (209, 1, 2, 'V', 'VV'),
- 'ROMAN' : (354, 1, 2, 'V', 'VV'),
- 'ROUND' : ( 27, 2, 2, 'V', 'VV'),
- 'ROUNDDOWN' : (213, 2, 2, 'V', 'VV'),
- 'ROUNDUP' : (212, 2, 2, 'V', 'VV'),
- 'ROW' : ( 8, 0, 1, 'V', 'R'),
- 'ROWS' : ( 76, 1, 1, 'V', 'R'),
- 'RSQ' : (313, 2, 2, 'V', 'AA'),
- 'RTD' : (379, 3, 30, 'A', 'VVV+'),
- 'SEARCH' : ( 82, 2, 3, 'V', 'VVV'),
- 'SEARCHB' : (206, 2, 3, 'V', 'VVV'),
- 'SECOND' : ( 73, 1, 1, 'V', 'V'),
- 'SERIESSUM' : ( -1, 4, 4, 'V', 'VVVA'),
- 'SIGN' : ( 26, 1, 1, 'V', 'V'),
- 'SIN' : ( 15, 1, 1, 'V', 'V'),
- 'SINH' : (229, 1, 1, 'V', 'V'),
- 'SKEW' : (323, 1, 30, 'V', 'D+'),
- 'SLN' : (142, 3, 3, 'V', 'VVV'),
- 'SLOPE' : (315, 2, 2, 'V', 'AA'),
- 'SMALL' : (326, 2, 2, 'V', 'RV'),
- 'SQRT' : ( 20, 1, 1, 'V', 'V'),
- 'SQRTPI' : ( -1, 1, 1, 'V', 'V'),
- 'STANDARDIZE' : (297, 3, 3, 'V', 'VVV'),
- 'STDEV' : ( 12, 1, 30, 'V', 'D+'),
- 'STDEVA' : (366, 1, 30, 'V', 'D+'),
- 'STDEVP' : (193, 1, 30, 'V', 'D+'),
- 'STDEVPA' : (364, 1, 30, 'V', 'D+'),
- 'STEYX' : (314, 2, 2, 'V', 'AA'),
- 'SUBSTITUTE' : (120, 3, 4, 'V', 'VVVV'),
- 'SUBTOTAL' : (344, 2, 30, 'V', 'VR+'),
- 'SUM' : ( 4, 1, 30, 'V', 'D+'),
- 'SUMIF' : (345, 2, 3, 'V', 'RVR'),
- 'SUMPRODUCT' : (228, 1, 30, 'V', 'A+'),
- 'SUMSQ' : (321, 1, 30, 'V', 'D+'),
- 'SUMX2MY2' : (304, 2, 2, 'V', 'AA'),
- 'SUMX2PY2' : (305, 2, 2, 'V', 'AA'),
- 'SUMXMY2' : (303, 2, 2, 'V', 'AA'),
- 'SYD' : (143, 4, 4, 'V', 'VVVV'),
- 'T' : (130, 1, 1, 'V', 'R'),
- 'TAN' : ( 17, 1, 1, 'V', 'V'),
- 'TANH' : (231, 1, 1, 'V', 'V'),
- 'TBILLEQ' : ( -1, 3, 3, 'V', 'VVV'),
- 'TBILLPRICE' : ( -1, 3, 3, 'V', 'VVV'),
- 'TBILLYIELD' : ( -1, 3, 3, 'V', 'VVV'),
- 'TDIST' : (301, 3, 3, 'V', 'VVV'),
- 'TEXT' : ( 48, 2, 2, 'V', 'VV'),
- 'TIME' : ( 66, 3, 3, 'V', 'VVV'),
- 'TIMEVALUE' : (141, 1, 1, 'V', 'V'),
- 'TINV' : (332, 2, 2, 'V', 'VV'),
- 'TODAY' : (221, 0, 0, 'V', '-'),
- 'TRANSPOSE' : ( 83, 1, 1, 'A', 'A'),
- 'TREND' : ( 50, 1, 4, 'A', 'RRRV'),
- 'TRIM' : (118, 1, 1, 'V', 'V'),
- 'TRIMMEAN' : (331, 2, 2, 'V', 'RV'),
- 'TRUE' : ( 34, 0, 0, 'V', '-'),
- 'TRUNC' : (197, 1, 2, 'V', 'VV'),
- 'TTEST' : (316, 4, 4, 'V', 'AAVV'),
- 'TYPE' : ( 86, 1, 1, 'V', 'V'),
- 'UPPER' : (113, 1, 1, 'V', 'V'),
- 'USDOLLAR' : (204, 1, 2, 'V', 'VV'),
- 'VALUE' : ( 33, 1, 1, 'V', 'V'),
- 'VAR' : ( 46, 1, 30, 'V', 'D+'),
- 'VARA' : (367, 1, 30, 'V', 'D+'),
- 'VARP' : (194, 1, 30, 'V', 'D+'),
- 'VARPA' : (365, 1, 30, 'V', 'D+'),
- 'VDB' : (222, 5, 7, 'V', 'VVVVVVV'),
- 'VLOOKUP' : (102, 3, 4, 'V', 'VRRV'),
- 'WEEKDAY' : ( 70, 1, 2, 'V', 'VV'),
- 'WEEKNUM' : ( -1, 1, 2, 'V', 'VV'),
- 'WEIBULL' : (302, 4, 4, 'V', 'VVVV'),
- 'WORKDAY' : ( -1, 2, 3, 'V', 'VVR'),
- 'XIRR' : ( -1, 2, 3, 'V', 'AAV'),
- 'XNPV' : ( -1, 3, 3, 'V', 'VAA'),
- 'YEAR' : ( 69, 1, 1, 'V', 'V'),
- 'YEARFRAC' : ( -1, 2, 3, 'V', 'VVV'),
- 'YIELD' : ( -1, 6, 7, 'V', 'VVVVVVV'),
- 'YIELDDISC' : ( -1, 4, 5, 'V', 'VVVVV'),
- 'YIELDMAT' : ( -1, 5, 6, 'V', 'VVVVVV'),
- 'ZTEST' : (324, 2, 3, 'V', 'RVV'),
- }
-
-# Formulas Parse things
-
-ptgExp = 0x01
-ptgTbl = 0x02
-ptgAdd = 0x03
-ptgSub = 0x04
-ptgMul = 0x05
-ptgDiv = 0x06
-ptgPower = 0x07
-ptgConcat = 0x08
-ptgLT = 0x09
-ptgLE = 0x0a
-ptgEQ = 0x0b
-ptgGE = 0x0c
-ptgGT = 0x0d
-ptgNE = 0x0e
-ptgIsect = 0x0f
-ptgUnion = 0x10
-ptgRange = 0x11
-ptgUplus = 0x12
-ptgUminus = 0x13
-ptgPercent = 0x14
-ptgParen = 0x15
-ptgMissArg = 0x16
-ptgStr = 0x17
-ptgExtend = 0x18
-ptgAttr = 0x19
-ptgSheet = 0x1a
-ptgEndSheet = 0x1b
-ptgErr = 0x1c
-ptgBool = 0x1d
-ptgInt = 0x1e
-ptgNum = 0x1f
-
-ptgArrayR = 0x20
-ptgFuncR = 0x21
-ptgFuncVarR = 0x22
-ptgNameR = 0x23
-ptgRefR = 0x24
-ptgAreaR = 0x25
-ptgMemAreaR = 0x26
-ptgMemErrR = 0x27
-ptgMemNoMemR = 0x28
-ptgMemFuncR = 0x29
-ptgRefErrR = 0x2a
-ptgAreaErrR = 0x2b
-ptgRefNR = 0x2c
-ptgAreaNR = 0x2d
-ptgMemAreaNR = 0x2e
-ptgMemNoMemNR = 0x2f
-ptgNameXR = 0x39
-ptgRef3dR = 0x3a
-ptgArea3dR = 0x3b
-ptgRefErr3dR = 0x3c
-ptgAreaErr3dR = 0x3d
-
-ptgArrayV = 0x40
-ptgFuncV = 0x41
-ptgFuncVarV = 0x42
-ptgNameV = 0x43
-ptgRefV = 0x44
-ptgAreaV = 0x45
-ptgMemAreaV = 0x46
-ptgMemErrV = 0x47
-ptgMemNoMemV = 0x48
-ptgMemFuncV = 0x49
-ptgRefErrV = 0x4a
-ptgAreaErrV = 0x4b
-ptgRefNV = 0x4c
-ptgAreaNV = 0x4d
-ptgMemAreaNV = 0x4e
-ptgMemNoMemNV = 0x4f
-ptgFuncCEV = 0x58
-ptgNameXV = 0x59
-ptgRef3dV = 0x5a
-ptgArea3dV = 0x5b
-ptgRefErr3dV = 0x5c
-ptgAreaErr3dV = 0x5d
-
-ptgArrayA = 0x60
-ptgFuncA = 0x61
-ptgFuncVarA = 0x62
-ptgNameA = 0x63
-ptgRefA = 0x64
-ptgAreaA = 0x65
-ptgMemAreaA = 0x66
-ptgMemErrA = 0x67
-ptgMemNoMemA = 0x68
-ptgMemFuncA = 0x69
-ptgRefErrA = 0x6a
-ptgAreaErrA = 0x6b
-ptgRefNA = 0x6c
-ptgAreaNA = 0x6d
-ptgMemAreaNA = 0x6e
-ptgMemNoMemNA = 0x6f
-ptgFuncCEA = 0x78
-ptgNameXA = 0x79
-ptgRef3dA = 0x7a
-ptgArea3dA = 0x7b
-ptgRefErr3dA = 0x7c
-ptgAreaErr3dA = 0x7d
-
-
-PtgNames = {
- ptgExp : "ptgExp",
- ptgTbl : "ptgTbl",
- ptgAdd : "ptgAdd",
- ptgSub : "ptgSub",
- ptgMul : "ptgMul",
- ptgDiv : "ptgDiv",
- ptgPower : "ptgPower",
- ptgConcat : "ptgConcat",
- ptgLT : "ptgLT",
- ptgLE : "ptgLE",
- ptgEQ : "ptgEQ",
- ptgGE : "ptgGE",
- ptgGT : "ptgGT",
- ptgNE : "ptgNE",
- ptgIsect : "ptgIsect",
- ptgUnion : "ptgUnion",
- ptgRange : "ptgRange",
- ptgUplus : "ptgUplus",
- ptgUminus : "ptgUminus",
- ptgPercent : "ptgPercent",
- ptgParen : "ptgParen",
- ptgMissArg : "ptgMissArg",
- ptgStr : "ptgStr",
- ptgExtend : "ptgExtend",
- ptgAttr : "ptgAttr",
- ptgSheet : "ptgSheet",
- ptgEndSheet : "ptgEndSheet",
- ptgErr : "ptgErr",
- ptgBool : "ptgBool",
- ptgInt : "ptgInt",
- ptgNum : "ptgNum",
- ptgArrayR : "ptgArrayR",
- ptgFuncR : "ptgFuncR",
- ptgFuncVarR : "ptgFuncVarR",
- ptgNameR : "ptgNameR",
- ptgRefR : "ptgRefR",
- ptgAreaR : "ptgAreaR",
- ptgMemAreaR : "ptgMemAreaR",
- ptgMemErrR : "ptgMemErrR",
- ptgMemNoMemR : "ptgMemNoMemR",
- ptgMemFuncR : "ptgMemFuncR",
- ptgRefErrR : "ptgRefErrR",
- ptgAreaErrR : "ptgAreaErrR",
- ptgRefNR : "ptgRefNR",
- ptgAreaNR : "ptgAreaNR",
- ptgMemAreaNR : "ptgMemAreaNR",
- ptgMemNoMemNR : "ptgMemNoMemNR",
- ptgNameXR : "ptgNameXR",
- ptgRef3dR : "ptgRef3dR",
- ptgArea3dR : "ptgArea3dR",
- ptgRefErr3dR : "ptgRefErr3dR",
- ptgAreaErr3dR : "ptgAreaErr3dR",
- ptgArrayV : "ptgArrayV",
- ptgFuncV : "ptgFuncV",
- ptgFuncVarV : "ptgFuncVarV",
- ptgNameV : "ptgNameV",
- ptgRefV : "ptgRefV",
- ptgAreaV : "ptgAreaV",
- ptgMemAreaV : "ptgMemAreaV",
- ptgMemErrV : "ptgMemErrV",
- ptgMemNoMemV : "ptgMemNoMemV",
- ptgMemFuncV : "ptgMemFuncV",
- ptgRefErrV : "ptgRefErrV",
- ptgAreaErrV : "ptgAreaErrV",
- ptgRefNV : "ptgRefNV",
- ptgAreaNV : "ptgAreaNV",
- ptgMemAreaNV : "ptgMemAreaNV",
- ptgMemNoMemNV : "ptgMemNoMemNV",
- ptgFuncCEV : "ptgFuncCEV",
- ptgNameXV : "ptgNameXV",
- ptgRef3dV : "ptgRef3dV",
- ptgArea3dV : "ptgArea3dV",
- ptgRefErr3dV : "ptgRefErr3dV",
- ptgAreaErr3dV : "ptgAreaErr3dV",
- ptgArrayA : "ptgArrayA",
- ptgFuncA : "ptgFuncA",
- ptgFuncVarA : "ptgFuncVarA",
- ptgNameA : "ptgNameA",
- ptgRefA : "ptgRefA",
- ptgAreaA : "ptgAreaA",
- ptgMemAreaA : "ptgMemAreaA",
- ptgMemErrA : "ptgMemErrA",
- ptgMemNoMemA : "ptgMemNoMemA",
- ptgMemFuncA : "ptgMemFuncA",
- ptgRefErrA : "ptgRefErrA",
- ptgAreaErrA : "ptgAreaErrA",
- ptgRefNA : "ptgRefNA",
- ptgAreaNA : "ptgAreaNA",
- ptgMemAreaNA : "ptgMemAreaNA",
- ptgMemNoMemNA : "ptgMemNoMemNA",
- ptgFuncCEA : "ptgFuncCEA",
- ptgNameXA : "ptgNameXA",
- ptgRef3dA : "ptgRef3dA",
- ptgArea3dA : "ptgArea3dA",
- ptgRefErr3dA : "ptgRefErr3dA",
- ptgAreaErr3dA : "ptgAreaErr3dA"
-}
-
-
-error_msg_by_code = {
- 0x00: u"#NULL!", # intersection of two cell ranges is empty
- 0x07: u"#DIV/0!", # division by zero
- 0x0F: u"#VALUE!", # wrong type of operand
- 0x17: u"#REF!", # illegal or deleted cell reference
- 0x1D: u"#NAME?", # wrong function or range name
- 0x24: u"#NUM!", # value range overflow
- 0x2A: u"#N/A!" # argument or function not available
-}
diff --git a/tablib/packages/xlwt/Formatting.py b/tablib/packages/xlwt/Formatting.py
deleted file mode 100644
index 76b8e8f..0000000
--- a/tablib/packages/xlwt/Formatting.py
+++ /dev/null
@@ -1,261 +0,0 @@
-#!/usr/bin/env python
-'''
-The XF record is able to store explicit cell formatting attributes or the
-attributes of a cell style. Explicit formatting includes the reference to
-a cell style XF record. This allows to extend a defined cell style with
-some explicit attributes. The formatting attributes are divided into
-6 groups:
-
-Group Attributes
--------------------------------------
-Number format Number format index (index to FORMAT record)
-Font Font index (index to FONT record)
-Alignment Horizontal and vertical alignment, text wrap, indentation,
- orientation/rotation, text direction
-Border Border line styles and colours
-Background Background area style and colours
-Protection Cell locked, formula hidden
-
-For each group a flag in the cell XF record specifies whether to use the
-attributes contained in that XF record or in the referenced style
-XF record. In style XF records, these flags specify whether the attributes
-will overwrite explicit cell formatting when the style is applied to
-a cell. Changing a cell style (without applying this style to a cell) will
-change all cells which already use that style and do not contain explicit
-cell attributes for the changed style attributes. If a cell XF record does
-not contain explicit attributes in a group (if the attribute group flag
-is not set), it repeats the attributes of its style XF record.
-
-'''
-
-import BIFFRecords
-
-class Font(object):
-
- ESCAPEMENT_NONE = 0x00
- ESCAPEMENT_SUPERSCRIPT = 0x01
- ESCAPEMENT_SUBSCRIPT = 0x02
-
- UNDERLINE_NONE = 0x00
- UNDERLINE_SINGLE = 0x01
- UNDERLINE_SINGLE_ACC = 0x21
- UNDERLINE_DOUBLE = 0x02
- UNDERLINE_DOUBLE_ACC = 0x22
-
- FAMILY_NONE = 0x00
- FAMILY_ROMAN = 0x01
- FAMILY_SWISS = 0x02
- FAMILY_MODERN = 0x03
- FAMILY_SCRIPT = 0x04
- FAMILY_DECORATIVE = 0x05
-
- CHARSET_ANSI_LATIN = 0x00
- CHARSET_SYS_DEFAULT = 0x01
- CHARSET_SYMBOL = 0x02
- CHARSET_APPLE_ROMAN = 0x4D
- CHARSET_ANSI_JAP_SHIFT_JIS = 0x80
- CHARSET_ANSI_KOR_HANGUL = 0x81
- CHARSET_ANSI_KOR_JOHAB = 0x82
- CHARSET_ANSI_CHINESE_GBK = 0x86
- CHARSET_ANSI_CHINESE_BIG5 = 0x88
- CHARSET_ANSI_GREEK = 0xA1
- CHARSET_ANSI_TURKISH = 0xA2
- CHARSET_ANSI_VIETNAMESE = 0xA3
- CHARSET_ANSI_HEBREW = 0xB1
- CHARSET_ANSI_ARABIC = 0xB2
- CHARSET_ANSI_BALTIC = 0xBA
- CHARSET_ANSI_CYRILLIC = 0xCC
- CHARSET_ANSI_THAI = 0xDE
- CHARSET_ANSI_LATIN_II = 0xEE
- CHARSET_OEM_LATIN_I = 0xFF
-
- def __init__(self):
- # twip = 1/20 of a point = 1/1440 of a inch
- # usually resolution == 96 pixels per 1 inch
- # (rarely 120 pixels per 1 inch or another one)
-
- self.height = 0x00C8 # 200: this is font with height 10 points
- self.italic = False
- self.struck_out = False
- self.outline = False
- self.shadow = False
- self.colour_index = 0x7FFF
- self.bold = False
- self._weight = 0x0190 # 0x02BC gives bold font
- self.escapement = self.ESCAPEMENT_NONE
- self.underline = self.UNDERLINE_NONE
- self.family = self.FAMILY_NONE
- self.charset = self.CHARSET_SYS_DEFAULT
- self.name = 'Arial'
-
- def get_biff_record(self):
- height = self.height
-
- options = 0x00
- if self.bold:
- options |= 0x01
- self._weight = 0x02BC
- if self.italic:
- options |= 0x02
- if self.underline != self.UNDERLINE_NONE:
- options |= 0x04
- if self.struck_out:
- options |= 0x08
- if self.outline:
- options |= 0x010
- if self.shadow:
- options |= 0x020
-
- colour_index = self.colour_index
- weight = self._weight
- escapement = self.escapement
- underline = self.underline
- family = self.family
- charset = self.charset
- name = self.name
-
- return BIFFRecords.FontRecord(height, options, colour_index, weight, escapement,
- underline, family, charset,
- name)
-
- def _search_key(self):
- return (
- self.height,
- self.italic,
- self.struck_out,
- self.outline,
- self.shadow,
- self.colour_index,
- self.bold,
- self._weight,
- self.escapement,
- self.underline,
- self.family,
- self.charset,
- self.name,
- )
-
-class Alignment(object):
- HORZ_GENERAL = 0x00
- HORZ_LEFT = 0x01
- HORZ_CENTER = 0x02
- HORZ_RIGHT = 0x03
- HORZ_FILLED = 0x04
- HORZ_JUSTIFIED = 0x05 # BIFF4-BIFF8X
- HORZ_CENTER_ACROSS_SEL = 0x06 # Centred across selection (BIFF4-BIFF8X)
- HORZ_DISTRIBUTED = 0x07 # Distributed (BIFF8X)
-
- VERT_TOP = 0x00
- VERT_CENTER = 0x01
- VERT_BOTTOM = 0x02
- VERT_JUSTIFIED = 0x03 # Justified (BIFF5-BIFF8X)
- VERT_DISTRIBUTED = 0x04 # Distributed (BIFF8X)
-
- DIRECTION_GENERAL = 0x00 # BIFF8X
- DIRECTION_LR = 0x01
- DIRECTION_RL = 0x02
-
- ORIENTATION_NOT_ROTATED = 0x00
- ORIENTATION_STACKED = 0x01
- ORIENTATION_90_CC = 0x02
- ORIENTATION_90_CW = 0x03
-
- ROTATION_0_ANGLE = 0x00
- ROTATION_STACKED = 0xFF
-
- WRAP_AT_RIGHT = 0x01
- NOT_WRAP_AT_RIGHT = 0x00
-
- SHRINK_TO_FIT = 0x01
- NOT_SHRINK_TO_FIT = 0x00
-
- def __init__(self):
- self.horz = self.HORZ_GENERAL
- self.vert = self.VERT_BOTTOM
- self.dire = self.DIRECTION_GENERAL
- self.orie = self.ORIENTATION_NOT_ROTATED
- self.rota = self.ROTATION_0_ANGLE
- self.wrap = self.NOT_WRAP_AT_RIGHT
- self.shri = self.NOT_SHRINK_TO_FIT
- self.inde = 0
- self.merg = 0
-
- def _search_key(self):
- return (
- self.horz, self.vert, self.dire, self.orie, self.rota,
- self.wrap, self.shri, self.inde, self.merg,
- )
-
-class Borders(object):
- NO_LINE = 0x00
- THIN = 0x01
- MEDIUM = 0x02
- DASHED = 0x03
- DOTTED = 0x04
- THICK = 0x05
- DOUBLE = 0x06
- HAIR = 0x07
- #The following for BIFF8
- MEDIUM_DASHED = 0x08
- THIN_DASH_DOTTED = 0x09
- MEDIUM_DASH_DOTTED = 0x0A
- THIN_DASH_DOT_DOTTED = 0x0B
- MEDIUM_DASH_DOT_DOTTED = 0x0C
- SLANTED_MEDIUM_DASH_DOTTED = 0x0D
-
- NEED_DIAG1 = 0x01
- NEED_DIAG2 = 0x01
- NO_NEED_DIAG1 = 0x00
- NO_NEED_DIAG2 = 0x00
-
- def __init__(self):
- self.left = self.NO_LINE
- self.right = self.NO_LINE
- self.top = self.NO_LINE
- self.bottom = self.NO_LINE
- self.diag = self.NO_LINE
-
- self.left_colour = 0x40
- self.right_colour = 0x40
- self.top_colour = 0x40
- self.bottom_colour = 0x40
- self.diag_colour = 0x40
-
- self.need_diag1 = self.NO_NEED_DIAG1
- self.need_diag2 = self.NO_NEED_DIAG2
-
- def _search_key(self):
- return (
- self.left, self.right, self.top, self.bottom, self.diag,
- self.left_colour, self.right_colour, self.top_colour,
- self.bottom_colour, self.diag_colour,
- self.need_diag1, self.need_diag2,
- )
-
-class Pattern(object):
- # patterns 0x00 - 0x12
- NO_PATTERN = 0x00
- SOLID_PATTERN = 0x01
-
- def __init__(self):
- self.pattern = self.NO_PATTERN
- self.pattern_fore_colour = 0x40
- self.pattern_back_colour = 0x41
-
- def _search_key(self):
- return (
- self.pattern,
- self.pattern_fore_colour,
- self.pattern_back_colour,
- )
-
-class Protection(object):
- def __init__(self):
- self.cell_locked = 1
- self.formula_hidden = 0
-
- def _search_key(self):
- return (
- self.cell_locked,
- self.formula_hidden,
- )
diff --git a/tablib/packages/xlwt/Row.py b/tablib/packages/xlwt/Row.py
deleted file mode 100644
index a834ea1..0000000
--- a/tablib/packages/xlwt/Row.py
+++ /dev/null
@@ -1,253 +0,0 @@
-# -*- coding: windows-1252 -*-
-
-import BIFFRecords
-import Style
-from Cell import StrCell, BlankCell, NumberCell, FormulaCell, MulBlankCell, BooleanCell, ErrorCell, \
- _get_cells_biff_data_mul
-import ExcelFormula
-import datetime as dt
-try:
- from decimal import Decimal
-except ImportError:
- # Python 2.3: decimal not supported; create dummy Decimal class
- class Decimal(object):
- pass
-
-
-class Row(object):
- __slots__ = [# private variables
- "__idx",
- "__parent",
- "__parent_wb",
- "__cells",
- "__min_col_idx",
- "__max_col_idx",
- "__xf_index",
- "__has_default_xf_index",
- "__height_in_pixels",
- # public variables
- "height",
- "has_default_height",
- "height_mismatch",
- "level",
- "collapse",
- "hidden",
- "space_above",
- "space_below"]
-
- def __init__(self, rowx, parent_sheet):
- if not (isinstance(rowx, int) and 0 <= rowx <= 65535):
- raise ValueError("row index (%r) not an int in range(65536)" % rowx)
- self.__idx = rowx
- self.__parent = parent_sheet
- self.__parent_wb = parent_sheet.get_parent()
- self.__cells = {}
- self.__min_col_idx = 0
- self.__max_col_idx = 0
- self.__xf_index = 0x0F
- self.__has_default_xf_index = 0
- self.__height_in_pixels = 0x11
-
- self.height = 0x00FF
- self.has_default_height = 0x00
- self.height_mismatch = 0
- self.level = 0
- self.collapse = 0
- self.hidden = 0
- self.space_above = 0
- self.space_below = 0
-
-
- def __adjust_height(self, style):
- twips = style.font.height
- points = float(twips)/20.0
- # Cell height in pixels can be calcuted by following approx. formula:
- # cell height in pixels = font height in points * 83/50 + 2/5
- # It works when screen resolution is 96 dpi
- pix = int(round(points*83.0/50.0 + 2.0/5.0))
- if pix > self.__height_in_pixels:
- self.__height_in_pixels = pix
-
-
- def __adjust_bound_col_idx(self, *args):
- for arg in args:
- iarg = int(arg)
- if not ((0 <= iarg <= 255) and arg == iarg):
- raise ValueError("column index (%r) not an int in range(256)" % arg)
- sheet = self.__parent
- if iarg < self.__min_col_idx:
- self.__min_col_idx = iarg
- if iarg > self.__max_col_idx:
- self.__max_col_idx = iarg
- if iarg < sheet.first_used_col:
- sheet.first_used_col = iarg
- if iarg > sheet.last_used_col:
- sheet.last_used_col = iarg
-
- def __excel_date_dt(self, date):
- if isinstance(date, dt.date) and (not isinstance(date, dt.datetime)):
- epoch = dt.date(1899, 12, 31)
- elif isinstance(date, dt.time):
- date = dt.datetime.combine(dt.datetime(1900, 1, 1), date)
- epoch = dt.datetime(1900, 1, 1, 0, 0, 0)
- else:
- epoch = dt.datetime(1899, 12, 31, 0, 0, 0)
- delta = date - epoch
- xldate = delta.days + float(delta.seconds) / (24*60*60)
- # Add a day for Excel's missing leap day in 1900
- if xldate > 59:
- xldate += 1
- return xldate
-
- def get_height_in_pixels(self):
- return self.__height_in_pixels
-
-
- def set_style(self, style):
- self.__adjust_height(style)
- self.__xf_index = self.__parent_wb.add_style(style)
- self.__has_default_xf_index = 1
-
-
- def get_xf_index(self):
- return self.__xf_index
-
-
- def get_cells_count(self):
- return len(self.__cells)
-
-
- def get_min_col(self):
- return self.__min_col_idx
-
-
- def get_max_col(self):
- return self.__max_col_idx
-
-
- def get_row_biff_data(self):
- height_options = (self.height & 0x07FFF)
- height_options |= (self.has_default_height & 0x01) << 15
-
- options = (self.level & 0x07) << 0
- options |= (self.collapse & 0x01) << 4
- options |= (self.hidden & 0x01) << 5
- options |= (self.height_mismatch & 0x01) << 6
- options |= (self.__has_default_xf_index & 0x01) << 7
- options |= (0x01 & 0x01) << 8
- options |= (self.__xf_index & 0x0FFF) << 16
- options |= (self.space_above & 1) << 28
- options |= (self.space_below & 1) << 29
-
- return BIFFRecords.RowRecord(self.__idx, self.__min_col_idx,
- self.__max_col_idx, height_options, options).get()
-
- def insert_cell(self, col_index, cell_obj):
- if col_index in self.__cells:
- if not self.__parent._cell_overwrite_ok:
- msg = "Attempt to overwrite cell: sheetname=%r rowx=%d colx=%d" \
- % (self.__parent.name, self.__idx, col_index)
- raise Exception(msg)
- prev_cell_obj = self.__cells[col_index]
- sst_idx = getattr(prev_cell_obj, 'sst_idx', None)
- if sst_idx is not None:
- self.__parent_wb.del_str(sst_idx)
- self.__cells[col_index] = cell_obj
-
- def insert_mulcells(self, colx1, colx2, cell_obj):
- self.insert_cell(colx1, cell_obj)
- for col_index in xrange(colx1+1, colx2+1):
- self.insert_cell(col_index, None)
-
- def get_cells_biff_data(self):
- cell_items = [item for item in self.__cells.iteritems() if item[1] is not None]
- cell_items.sort() # in column order
- return _get_cells_biff_data_mul(self.__idx, cell_items)
- # previously:
- # return ''.join([cell.get_biff_data() for colx, cell in cell_items])
-
- def get_index(self):
- return self.__idx
-
- def set_cell_text(self, colx, value, style=Style.default_style):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(colx)
- xf_index = self.__parent_wb.add_style(style)
- self.insert_cell(colx, StrCell(self.__idx, colx, xf_index, self.__parent_wb.add_str(value)))
-
- def set_cell_blank(self, colx, style=Style.default_style):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(colx)
- xf_index = self.__parent_wb.add_style(style)
- self.insert_cell(colx, BlankCell(self.__idx, colx, xf_index))
-
- def set_cell_mulblanks(self, first_colx, last_colx, style=Style.default_style):
- assert 0 <= first_colx <= last_colx <= 255
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(first_colx, last_colx)
- xf_index = self.__parent_wb.add_style(style)
- # ncols = last_colx - first_colx + 1
- self.insert_mulcells(first_colx, last_colx, MulBlankCell(self.__idx, first_colx, last_colx, xf_index))
-
- def set_cell_number(self, colx, number, style=Style.default_style):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(colx)
- xf_index = self.__parent_wb.add_style(style)
- self.insert_cell(colx, NumberCell(self.__idx, colx, xf_index, number))
-
- def set_cell_date(self, colx, datetime_obj, style=Style.default_style):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(colx)
- xf_index = self.__parent_wb.add_style(style)
- self.insert_cell(colx,
- NumberCell(self.__idx, colx, xf_index, self.__excel_date_dt(datetime_obj)))
-
- def set_cell_formula(self, colx, formula, style=Style.default_style, calc_flags=0):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(colx)
- xf_index = self.__parent_wb.add_style(style)
- self.__parent_wb.add_sheet_reference(formula)
- self.insert_cell(colx, FormulaCell(self.__idx, colx, xf_index, formula, calc_flags=0))
-
- def set_cell_boolean(self, colx, value, style=Style.default_style):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(colx)
- xf_index = self.__parent_wb.add_style(style)
- self.insert_cell(colx, BooleanCell(self.__idx, colx, xf_index, bool(value)))
-
- def set_cell_error(self, colx, error_string_or_code, style=Style.default_style):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(colx)
- xf_index = self.__parent_wb.add_style(style)
- self.insert_cell(colx, ErrorCell(self.__idx, colx, xf_index, error_string_or_code))
-
- def write(self, col, label, style=Style.default_style):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(col)
- style_index = self.__parent_wb.add_style(style)
- if isinstance(label, basestring):
- if len(label) > 0:
- self.insert_cell(col,
- StrCell(self.__idx, col, style_index, self.__parent_wb.add_str(label))
- )
- else:
- self.insert_cell(col, BlankCell(self.__idx, col, style_index))
- elif isinstance(label, bool): # bool is subclass of int; test bool first
- self.insert_cell(col, BooleanCell(self.__idx, col, style_index, label))
- elif isinstance(label, (float, int, long, Decimal)):
- self.insert_cell(col, NumberCell(self.__idx, col, style_index, label))
- elif isinstance(label, (dt.datetime, dt.date, dt.time)):
- date_number = self.__excel_date_dt(label)
- self.insert_cell(col, NumberCell(self.__idx, col, style_index, date_number))
- elif label is None:
- self.insert_cell(col, BlankCell(self.__idx, col, style_index))
- elif isinstance(label, ExcelFormula.Formula):
- self.__parent_wb.add_sheet_reference(label)
- self.insert_cell(col, FormulaCell(self.__idx, col, style_index, label))
- else:
- raise Exception("Unexpected data type %r" % type(label))
-
- write_blanks = set_cell_mulblanks
-
-
-
diff --git a/tablib/packages/xlwt/Style.py b/tablib/packages/xlwt/Style.py
deleted file mode 100644
index bf5fb4c..0000000
--- a/tablib/packages/xlwt/Style.py
+++ /dev/null
@@ -1,592 +0,0 @@
-# -*- coding: windows-1252 -*-
-
-import Formatting
-from BIFFRecords import *
-
-FIRST_USER_DEFINED_NUM_FORMAT_IDX = 164
-
-class XFStyle(object):
-
- def __init__(self):
- self.num_format_str = 'General'
- self.font = Formatting.Font()
- self.alignment = Formatting.Alignment()
- self.borders = Formatting.Borders()
- self.pattern = Formatting.Pattern()
- self.protection = Formatting.Protection()
-
-default_style = XFStyle()
-
-class StyleCollection(object):
- _std_num_fmt_list = [
- 'general',
- '0',
- '0.00',
- '#,##0',
- '#,##0.00',
- '"$"#,##0_);("$"#,##',
- '"$"#,##0_);[Red]("$"#,##',
- '"$"#,##0.00_);("$"#,##',
- '"$"#,##0.00_);[Red]("$"#,##',
- '0%',
- '0.00%',
- '0.00E+00',
- '# ?/?',
- '# ??/??',
- 'M/D/YY',
- 'D-MMM-YY',
- 'D-MMM',
- 'MMM-YY',
- 'h:mm AM/PM',
- 'h:mm:ss AM/PM',
- 'h:mm',
- 'h:mm:ss',
- 'M/D/YY h:mm',
- '_(#,##0_);(#,##0)',
- '_(#,##0_);[Red](#,##0)',
- '_(#,##0.00_);(#,##0.00)',
- '_(#,##0.00_);[Red](#,##0.00)',
- '_("$"* #,##0_);_("$"* (#,##0);_("$"* "-"_);_(@_)',
- '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)',
- '_("$"* #,##0.00_);_("$"* (#,##0.00);_("$"* "-"??_);_(@_)',
- '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)',
- 'mm:ss',
- '[h]:mm:ss',
- 'mm:ss.0',
- '##0.0E+0',
- '@'
- ]
-
- def __init__(self, style_compression=0):
- self.style_compression = style_compression
- self.stats = [0, 0, 0, 0, 0, 0]
- self._font_id2x = {}
- self._font_x2id = {}
- self._font_val2x = {}
-
- for x in (0, 1, 2, 3, 5): # The font with index 4 is omitted in all BIFF versions
- font = Formatting.Font()
- search_key = font._search_key()
- self._font_id2x[font] = x
- self._font_x2id[x] = font
- self._font_val2x[search_key] = x
-
- self._xf_id2x = {}
- self._xf_x2id = {}
- self._xf_val2x = {}
-
- self._num_formats = {}
- for fmtidx, fmtstr in zip(range(0, 23), StyleCollection._std_num_fmt_list[0:23]):
- self._num_formats[fmtstr] = fmtidx
- for fmtidx, fmtstr in zip(range(37, 50), StyleCollection._std_num_fmt_list[23:]):
- self._num_formats[fmtstr] = fmtidx
-
- self.default_style = XFStyle()
- self._default_xf = self._add_style(self.default_style)[0]
-
- def add(self, style):
- if style == None:
- return 0x10
- return self._add_style(style)[1]
-
- def _add_style(self, style):
- num_format_str = style.num_format_str
- if num_format_str in self._num_formats:
- num_format_idx = self._num_formats[num_format_str]
- else:
- num_format_idx = (
- FIRST_USER_DEFINED_NUM_FORMAT_IDX
- + len(self._num_formats)
- - len(StyleCollection._std_num_fmt_list)
- )
- self._num_formats[num_format_str] = num_format_idx
-
- font = style.font
- if font in self._font_id2x:
- font_idx = self._font_id2x[font]
- self.stats[0] += 1
- elif self.style_compression:
- search_key = font._search_key()
- font_idx = self._font_val2x.get(search_key)
- if font_idx is not None:
- self._font_id2x[font] = font_idx
- self.stats[1] += 1
- else:
- font_idx = len(self._font_x2id) + 1 # Why plus 1? Font 4 is missing
- self._font_id2x[font] = font_idx
- self._font_val2x[search_key] = font_idx
- self._font_x2id[font_idx] = font
- self.stats[2] += 1
- else:
- font_idx = len(self._font_id2x) + 1
- self._font_id2x[font] = font_idx
- self.stats[2] += 1
-
- gof = (style.alignment, style.borders, style.pattern, style.protection)
- xf = (font_idx, num_format_idx) + gof
- if xf in self._xf_id2x:
- xf_index = self._xf_id2x[xf]
- self.stats[3] += 1
- elif self.style_compression == 2:
- xf_key = (font_idx, num_format_idx) + tuple([obj._search_key() for obj in gof])
- xf_index = self._xf_val2x.get(xf_key)
- if xf_index is not None:
- self._xf_id2x[xf] = xf_index
- self.stats[4] += 1
- else:
- xf_index = 0x10 + len(self._xf_x2id)
- self._xf_id2x[xf] = xf_index
- self._xf_val2x[xf_key] = xf_index
- self._xf_x2id[xf_index] = xf
- self.stats[5] += 1
- else:
- xf_index = 0x10 + len(self._xf_id2x)
- self._xf_id2x[xf] = xf_index
- self.stats[5] += 1
-
- if xf_index >= 0xFFF:
- # 12 bits allowed, 0xFFF is a sentinel value
- raise ValueError("More than 4094 XFs (styles)")
-
- return xf, xf_index
-
- def get_biff_data(self):
- result = ''
- result += self._all_fonts()
- result += self._all_num_formats()
- result += self._all_cell_styles()
- result += self._all_styles()
- return result
-
- def _all_fonts(self):
- result = ''
- if self.style_compression:
- alist = self._font_x2id.items()
- else:
- alist = [(x, o) for o, x in self._font_id2x.items()]
- alist.sort()
- for font_idx, font in alist:
- result += font.get_biff_record().get()
- return result
-
- def _all_num_formats(self):
- result = ''
- alist = [
- (v, k)
- for k, v in self._num_formats.items()
- if v >= FIRST_USER_DEFINED_NUM_FORMAT_IDX
- ]
- alist.sort()
- for fmtidx, fmtstr in alist:
- result += NumberFormatRecord(fmtidx, fmtstr).get()
- return result
-
- def _all_cell_styles(self):
- result = ''
- for i in range(0, 16):
- result += XFRecord(self._default_xf, 'style').get()
- if self.style_compression == 2:
- alist = self._xf_x2id.items()
- else:
- alist = [(x, o) for o, x in self._xf_id2x.items()]
- alist.sort()
- for xf_idx, xf in alist:
- result += XFRecord(xf).get()
- return result
-
- def _all_styles(self):
- return StyleRecord().get()
-
-# easyxf and its supporting objects ###################################
-
-class EasyXFException(Exception):
- pass
-
-class EasyXFCallerError(EasyXFException):
- pass
-
-class EasyXFAuthorError(EasyXFException):
- pass
-
-class IntULim(object):
- # If astring represents a valid unsigned integer ('123', '0xabcd', etc)
- # and it is <= limit, return the int value; otherwise return None.
-
- def __init__(self, limit):
- self.limit = limit
-
- def __call__(self, astring):
- try:
- value = int(astring, 0)
- except ValueError:
- return None
- if not 0 <= value <= self.limit:
- return None
- return value
-
-bool_map = {
- # Text values for all Boolean attributes
- '1': 1, 'yes': 1, 'true': 1, 'on': 1,
- '0': 0, 'no': 0, 'false': 0, 'off': 0,
- }
-
-border_line_map = {
- # Text values for these borders attributes:
- # left, right, top, bottom and diag
- 'no_line': 0x00,
- 'thin': 0x01,
- 'medium': 0x02,
- 'dashed': 0x03,
- 'dotted': 0x04,
- 'thick': 0x05,
- 'double': 0x06,
- 'hair': 0x07,
- 'medium_dashed': 0x08,
- 'thin_dash_dotted': 0x09,
- 'medium_dash_dotted': 0x0a,
- 'thin_dash_dot_dotted': 0x0b,
- 'medium_dash_dot_dotted': 0x0c,
- 'slanted_medium_dash_dotted': 0x0d,
- }
-
-charset_map = {
- # Text values for font.charset
- 'ansi_latin': 0x00,
- 'sys_default': 0x01,
- 'symbol': 0x02,
- 'apple_roman': 0x4d,
- 'ansi_jap_shift_jis': 0x80,
- 'ansi_kor_hangul': 0x81,
- 'ansi_kor_johab': 0x82,
- 'ansi_chinese_gbk': 0x86,
- 'ansi_chinese_big5': 0x88,
- 'ansi_greek': 0xa1,
- 'ansi_turkish': 0xa2,
- 'ansi_vietnamese': 0xa3,
- 'ansi_hebrew': 0xb1,
- 'ansi_arabic': 0xb2,
- 'ansi_baltic': 0xba,
- 'ansi_cyrillic': 0xcc,
- 'ansi_thai': 0xde,
- 'ansi_latin_ii': 0xee,
- 'oem_latin_i': 0xff,
- }
-
-
-# Text values for colour indices. "grey" is a synonym of "gray".
-# The names are those given by Microsoft Excel 2003 to the colours
-# in the default palette. There is no great correspondence with
-# any W3C name-to-RGB mapping.
-_colour_map_text = """\
-aqua 0x31
-black 0x08
-blue 0x0C
-blue_gray 0x36
-bright_green 0x0B
-brown 0x3C
-coral 0x1D
-cyan_ega 0x0F
-dark_blue 0x12
-dark_blue_ega 0x12
-dark_green 0x3A
-dark_green_ega 0x11
-dark_purple 0x1C
-dark_red 0x10
-dark_red_ega 0x10
-dark_teal 0x38
-dark_yellow 0x13
-gold 0x33
-gray_ega 0x17
-gray25 0x16
-gray40 0x37
-gray50 0x17
-gray80 0x3F
-green 0x11
-ice_blue 0x1F
-indigo 0x3E
-ivory 0x1A
-lavender 0x2E
-light_blue 0x30
-light_green 0x2A
-light_orange 0x34
-light_turquoise 0x29
-light_yellow 0x2B
-lime 0x32
-magenta_ega 0x0E
-ocean_blue 0x1E
-olive_ega 0x13
-olive_green 0x3B
-orange 0x35
-pale_blue 0x2C
-periwinkle 0x18
-pink 0x0E
-plum 0x3D
-purple_ega 0x14
-red 0x0A
-rose 0x2D
-sea_green 0x39
-silver_ega 0x16
-sky_blue 0x28
-tan 0x2F
-teal 0x15
-teal_ega 0x15
-turquoise 0x0F
-violet 0x14
-white 0x09
-yellow 0x0D"""
-
-colour_map = {}
-for _line in _colour_map_text.splitlines():
- _name, _num = _line.split()
- _num = int(_num, 0)
- colour_map[_name] = _num
- if 'gray' in _name:
- colour_map[_name.replace('gray', 'grey')] = _num
-del _colour_map_text, _line, _name, _num
-
-
-pattern_map = {
- # Text values for pattern.pattern
- # xlwt/doc/pattern_examples.xls showcases all of these patterns.
- 'no_fill': 0,
- 'none': 0,
- 'solid': 1,
- 'solid_fill': 1,
- 'solid_pattern': 1,
- 'fine_dots': 2,
- 'alt_bars': 3,
- 'sparse_dots': 4,
- 'thick_horz_bands': 5,
- 'thick_vert_bands': 6,
- 'thick_backward_diag': 7,
- 'thick_forward_diag': 8,
- 'big_spots': 9,
- 'bricks': 10,
- 'thin_horz_bands': 11,
- 'thin_vert_bands': 12,
- 'thin_backward_diag': 13,
- 'thin_forward_diag': 14,
- 'squares': 15,
- 'diamonds': 16,
- }
-
-def any_str_func(s):
- return s.strip()
-
-def colour_index_func(s, maxval=0x7F):
- try:
- value = int(s, 0)
- except ValueError:
- return None
- if not (0 <= value <= maxval):
- return None
- return value
-
-colour_index_func_7 = colour_index_func
-
-def colour_index_func_15(s):
- return colour_index_func(s, maxval=0x7FFF)
-
-def rotation_func(s):
- try:
- value = int(s, 0)
- except ValueError:
- return None
- if not (-90 <= value <= 90):
- raise EasyXFCallerError("rotation %d: should be -90 to +90 degrees" % value)
- if value < 0:
- value = 90 - value # encode as 91 to 180 (clockwise)
- return value
-
-xf_dict = {
- 'align': 'alignment', # synonym
- 'alignment': {
- 'dire': {
- 'general': 0,
- 'lr': 1,
- 'rl': 2,
- },
- 'direction': 'dire',
- 'horiz': 'horz',
- 'horizontal': 'horz',
- 'horz': {
- 'general': 0,
- 'left': 1,
- 'center': 2,
- 'centre': 2, # "align: horiz centre" means xf.alignment.horz is set to 2
- 'right': 3,
- 'filled': 4,
- 'justified': 5,
- 'center_across_selection': 6,
- 'centre_across_selection': 6,
- 'distributed': 7,
- },
- 'inde': IntULim(15), # restriction: 0 <= value <= 15
- 'indent': 'inde',
- 'rota': [{'stacked': 255, 'none': 0, }, rotation_func],
- 'rotation': 'rota',
- 'shri': bool_map,
- 'shrink': 'shri',
- 'shrink_to_fit': 'shri',
- 'vert': {
- 'top': 0,
- 'center': 1,
- 'centre': 1,
- 'bottom': 2,
- 'justified': 3,
- 'distributed': 4,
- },
- 'vertical': 'vert',
- 'wrap': bool_map,
- },
- 'border': 'borders',
- 'borders': {
- 'left': [border_line_map, IntULim(0x0d)],
- 'right': [border_line_map, IntULim(0x0d)],
- 'top': [border_line_map, IntULim(0x0d)],
- 'bottom': [border_line_map, IntULim(0x0d)],
- 'diag': [border_line_map, IntULim(0x0d)],
- 'top_colour': [colour_map, colour_index_func_7],
- 'bottom_colour': [colour_map, colour_index_func_7],
- 'left_colour': [colour_map, colour_index_func_7],
- 'right_colour': [colour_map, colour_index_func_7],
- 'diag_colour': [colour_map, colour_index_func_7],
- 'top_color': 'top_colour',
- 'bottom_color': 'bottom_colour',
- 'left_color': 'left_colour',
- 'right_color': 'right_colour',
- 'diag_color': 'diag-colour',
- 'need_diag_1': bool_map,
- 'need_diag_2': bool_map,
- },
- 'font': {
- 'bold': bool_map,
- 'charset': charset_map,
- 'color': 'colour_index',
- 'color_index': 'colour_index',
- 'colour': 'colour_index',
- 'colour_index': [colour_map, colour_index_func_15],
- 'escapement': {'none': 0, 'superscript': 1, 'subscript': 2},
- 'family': {'none': 0, 'roman': 1, 'swiss': 2, 'modern': 3, 'script': 4, 'decorative': 5, },
- 'height': IntULim(0xFFFF), # practical limits are much narrower e.g. 160 to 1440 (8pt to 72pt)
- 'italic': bool_map,
- 'name': any_str_func,
- 'outline': bool_map,
- 'shadow': bool_map,
- 'struck_out': bool_map,
- 'underline': [bool_map, {'none': 0, 'single': 1, 'single_acc': 0x21, 'double': 2, 'double_acc': 0x22, }],
- },
- 'pattern': {
- 'back_color': 'pattern_back_colour',
- 'back_colour': 'pattern_back_colour',
- 'fore_color': 'pattern_fore_colour',
- 'fore_colour': 'pattern_fore_colour',
- 'pattern': [pattern_map, IntULim(16)],
- 'pattern_back_color': 'pattern_back_colour',
- 'pattern_back_colour': [colour_map, colour_index_func_7],
- 'pattern_fore_color': 'pattern_fore_colour',
- 'pattern_fore_colour': [colour_map, colour_index_func_7],
- },
- 'protection': {
- 'cell_locked' : bool_map,
- 'formula_hidden': bool_map,
- },
- }
-
-def _esplit(s, split_char, esc_char="\\"):
- escaped = False
- olist = ['']
- for c in s:
- if escaped:
- olist[-1] += c
- escaped = False
- elif c == esc_char:
- escaped = True
- elif c == split_char:
- olist.append('')
- else:
- olist[-1] += c
- return olist
-
-def _parse_strg_to_obj(strg, obj, parse_dict,
- field_sep=",", line_sep=";", intro_sep=":", esc_char="\\", debug=False):
- for line in _esplit(strg, line_sep, esc_char):
- line = line.strip()
- if not line:
- break
- split_line = _esplit(line, intro_sep, esc_char)
- if len(split_line) != 2:
- raise EasyXFCallerError('line %r should have exactly 1 "%c"' % (line, intro_sep))
- section, item_str = split_line
- section = section.strip().lower()
- for counter in range(2):
- result = parse_dict.get(section)
- if result is None:
- raise EasyXFCallerError('section %r is unknown' % section)
- if isinstance(result, dict):
- break
- if not isinstance(result, str):
- raise EasyXFAuthorError(
- 'section %r should map to dict or str object; found %r' % (section, type(result)))
- # synonym
- old_section = section
- section = result
- else:
- raise EasyXFAuthorError('Attempt to define synonym of synonym (%r: %r)' % (old_section, result))
- section_dict = result
- section_obj = getattr(obj, section, None)
- if section_obj is None:
- raise EasyXFAuthorError('instance of %s class has no attribute named %s' % (obj.__class__.__name__, section))
- for kv_str in _esplit(item_str, field_sep, esc_char):
- guff = kv_str.split()
- if not guff:
- continue
- k = guff[0].lower().replace('-', '_')
- v = ' '.join(guff[1:])
- if not v:
- raise EasyXFCallerError("no value supplied for %s.%s" % (section, k))
- for counter in xrange(2):
- result = section_dict.get(k)
- if result is None:
- raise EasyXFCallerError('%s.%s is not a known attribute' % (section, k))
- if not isinstance(result, basestring):
- break
- # synonym
- old_k = k
- k = result
- else:
- raise EasyXFAuthorError('Attempt to define synonym of synonym (%r: %r)' % (old_k, result))
- value_info = result
- if not isinstance(value_info, list):
- value_info = [value_info]
- for value_rule in value_info:
- if isinstance(value_rule, dict):
- # dict maps strings to integer field values
- vl = v.lower().replace('-', '_')
- if vl in value_rule:
- value = value_rule[vl]
- break
- elif callable(value_rule):
- value = value_rule(v)
- if value is not None:
- break
- else:
- raise EasyXFAuthorError("unknown value rule for attribute %r: %r" % (k, value_rule))
- else:
- raise EasyXFCallerError("unexpected value %r for %s.%s" % (v, section, k))
- try:
- orig = getattr(section_obj, k)
- except AttributeError:
- raise EasyXFAuthorError('%s.%s in dictionary but not in supplied object' % (section, k))
- if debug: print "+++ %s.%s = %r # %s; was %r" % (section, k, value, v, orig)
- setattr(section_obj, k, value)
-
-def easyxf(strg_to_parse="", num_format_str=None,
- field_sep=",", line_sep=";", intro_sep=":", esc_char="\\", debug=False):
- xfobj = XFStyle()
- if num_format_str is not None:
- xfobj.num_format_str = num_format_str
- if strg_to_parse:
- _parse_strg_to_obj(strg_to_parse, xfobj, xf_dict,
- field_sep=field_sep, line_sep=line_sep, intro_sep=intro_sep, esc_char=esc_char, debug=debug)
- return xfobj
diff --git a/tablib/packages/xlwt/UnicodeUtils.py b/tablib/packages/xlwt/UnicodeUtils.py
deleted file mode 100644
index 630c259..0000000
--- a/tablib/packages/xlwt/UnicodeUtils.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# -*- coding: windows-1252 -*-
-
-'''
-From BIFF8 on, strings are always stored using UTF-16LE text encoding. The
-character array is a sequence of 16-bit values4. Additionally it is
-possible to use a compressed format, which omits the high bytes of all
-characters, if they are all zero.
-
-The following tables describe the standard format of the entire string, but
-in many records the strings differ from this format. This will be mentioned
-separately. It is possible (but not required) to store Rich-Text formatting
-information and Asian phonetic information inside a Unicode string. This
-results in four different ways to store a string. The character array
-is not zero-terminated.
-
-The string consists of the character count (as usual an 8-bit value or
-a 16-bit value), option flags, the character array and optional formatting
-information. If the string is empty, sometimes the option flags field will
-not occur. This is mentioned at the respective place.
-
-Offset Size Contents
-0 1 or 2 Length of the string (character count, ln)
-1 or 2 1 Option flags:
- Bit Mask Contents
- 0 01H Character compression (ccompr):
- 0 = Compressed (8-bit characters)
- 1 = Uncompressed (16-bit characters)
- 2 04H Asian phonetic settings (phonetic):
- 0 = Does not contain Asian phonetic settings
- 1 = Contains Asian phonetic settings
- 3 08H Rich-Text settings (richtext):
- 0 = Does not contain Rich-Text settings
- 1 = Contains Rich-Text settings
-[2 or 3] 2 (optional, only if richtext=1) Number of Rich-Text formatting runs (rt)
-[var.] 4 (optional, only if phonetic=1) Size of Asian phonetic settings block (in bytes, sz)
-var. ln or
- 2ln Character array (8-bit characters or 16-bit characters, dependent on ccompr)
-[var.] 4rt (optional, only if richtext=1) List of rt formatting runs
-[var.] sz (optional, only if phonetic=1) Asian Phonetic Settings Block
-'''
-
-
-from struct import pack
-
-def upack2(s, encoding='ascii'):
- # If not unicode, make it so.
- if isinstance(s, unicode):
- us = s
- else:
- us = unicode(s, encoding)
- # Limit is based on number of content characters
- # (not on number of bytes in packed result)
- len_us = len(us)
- if len_us > 65535:
- raise Exception('String longer than 65535 characters')
- try:
- encs = us.encode('latin1')
- # Success here means all chars are in U+0000 to U+00FF
- # inclusive, meaning that we can use "compressed format".
- flag = 0
- except UnicodeEncodeError:
- encs = us.encode('utf_16_le')
- flag = 1
- return pack('<HB', len_us, flag) + encs
-
-def upack1(s, encoding='ascii'):
- # Same as upack2(), but with a one-byte length field.
- if isinstance(s, unicode):
- us = s
- else:
- us = unicode(s, encoding)
- len_us = len(us)
- if len_us > 255:
- raise Exception('String longer than 255 characters')
- try:
- encs = us.encode('latin1')
- flag = 0
- except UnicodeEncodeError:
- encs = us.encode('utf_16_le')
- flag = 1
- return pack('<BB', len_us, flag) + encs
diff --git a/tablib/packages/xlwt/Utils.py b/tablib/packages/xlwt/Utils.py
deleted file mode 100644
index 19e8d21..0000000
--- a/tablib/packages/xlwt/Utils.py
+++ /dev/null
@@ -1,196 +0,0 @@
-# pyXLWriter: A library for generating Excel Spreadsheets
-# Copyright (c) 2004 Evgeny Filatov <fufff@users.sourceforge.net>
-# Copyright (c) 2002-2004 John McNamara (Perl Spreadsheet::WriteExcel)
-#
-# This library is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
-# General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this library; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#----------------------------------------------------------------------------
-# This module was written/ported from PERL Spreadsheet::WriteExcel module
-# The author of the PERL Spreadsheet::WriteExcel module is John McNamara
-# <jmcnamara@cpan.org>
-#----------------------------------------------------------------------------
-# See the README.txt distributed with pyXLWriter for more details.
-
-# Portions are (C) Roman V. Kiseliov, 2005
-
-
-# Utilities for work with reference to cells and with sheetnames
-
-
-__rev_id__ = """$Id: Utils.py 3844 2009-05-20 01:02:54Z sjmachin $"""
-
-import re
-from struct import pack
-from ExcelMagic import MAX_ROW, MAX_COL
-
-
-_re_cell_ex = re.compile(r"(\$?)([A-I]?[A-Z])(\$?)(\d+)", re.IGNORECASE)
-_re_row_range = re.compile(r"\$?(\d+):\$?(\d+)")
-_re_col_range = re.compile(r"\$?([A-I]?[A-Z]):\$?([A-I]?[A-Z])", re.IGNORECASE)
-_re_cell_range = re.compile(r"\$?([A-I]?[A-Z]\$?\d+):\$?([A-I]?[A-Z]\$?\d+)", re.IGNORECASE)
-_re_cell_ref = re.compile(r"\$?([A-I]?[A-Z]\$?\d+)", re.IGNORECASE)
-
-
-def col_by_name(colname):
- """
- """
- col = 0
- pow = 1
- for i in xrange(len(colname)-1, -1, -1):
- ch = colname[i]
- col += (ord(ch) - ord('A') + 1) * pow
- pow *= 26
- return col - 1
-
-
-def cell_to_rowcol(cell):
- """Convert an Excel cell reference string in A1 notation
- to numeric row/col notation.
-
- Returns: row, col, row_abs, col_abs
-
- """
- m = _re_cell_ex.match(cell)
- if not m:
- raise Exception("Ill-formed single_cell reference: %s" % cell)
- col_abs, col, row_abs, row = m.groups()
- row_abs = bool(row_abs)
- col_abs = bool(col_abs)
- row = int(row) - 1
- col = col_by_name(col.upper())
- return row, col, row_abs, col_abs
-
-
-def cell_to_rowcol2(cell):
- """Convert an Excel cell reference string in A1 notation
- to numeric row/col notation.
-
- Returns: row, col
-
- """
- m = _re_cell_ex.match(cell)
- if not m:
- raise Exception("Error in cell format")
- col_abs, col, row_abs, row = m.groups()
- # Convert base26 column string to number
- # All your Base are belong to us.
- row = int(row) - 1
- col = col_by_name(col.upper())
- return row, col
-
-
-def rowcol_to_cell(row, col, row_abs=False, col_abs=False):
- """Convert numeric row/col notation to an Excel cell reference string in
- A1 notation.
-
- """
- assert 0 <= row < MAX_ROW # MAX_ROW counts from 1
- assert 0 <= col < MAX_COL # MAX_COL counts from 1
- d = col // 26
- m = col % 26
- chr1 = "" # Most significant character in AA1
- if row_abs:
- row_abs = '$'
- else:
- row_abs = ''
- if col_abs:
- col_abs = '$'
- else:
- col_abs = ''
- if d > 0:
- chr1 = chr(ord('A') + d - 1)
- chr2 = chr(ord('A') + m)
- # Zero index to 1-index
- return col_abs + chr1 + chr2 + row_abs + str(row + 1)
-
-def rowcol_pair_to_cellrange(row1, col1, row2, col2,
- row1_abs=False, col1_abs=False, row2_abs=False, col2_abs=False):
- """Convert two (row,column) pairs
- into a cell range string in A1:B2 notation.
-
- Returns: cell range string
- """
- assert row1 <= row2
- assert col1 <= col2
- return (
- rowcol_to_cell(row1, col1, row1_abs, col1_abs)
- + ":"
- + rowcol_to_cell(row2, col2, row2_abs, col2_abs)
- )
-
-def cellrange_to_rowcol_pair(cellrange):
- """Convert cell range string in A1 notation to numeric row/col
- pair.
-
- Returns: row1, col1, row2, col2
-
- """
- cellrange = cellrange.upper()
- # Convert a row range: '1:3'
- res = _re_row_range.match(cellrange)
- if res:
- row1 = int(res.group(1)) - 1
- col1 = 0
- row2 = int(res.group(2)) - 1
- col2 = -1
- return row1, col1, row2, col2
- # Convert a column range: 'A:A' or 'B:G'.
- # A range such as A:A is equivalent to A1:A16384, so add rows as required
- res = _re_col_range.match(cellrange)
- if res:
- col1 = col_by_name(res.group(1).upper())
- row1 = 0
- col2 = col_by_name(res.group(2).upper())
- row2 = -1
- return row1, col1, row2, col2
- # Convert a cell range: 'A1:B7'
- res = _re_cell_range.match(cellrange)
- if res:
- row1, col1 = cell_to_rowcol2(res.group(1))
- row2, col2 = cell_to_rowcol2(res.group(2))
- return row1, col1, row2, col2
- # Convert a cell reference: 'A1' or 'AD2000'
- res = _re_cell_ref.match(cellrange)
- if res:
- row1, col1 = cell_to_rowcol2(res.group(1))
- return row1, col1, row1, col1
- raise Exception("Unknown cell reference %s" % (cell))
-
-
-def cell_to_packed_rowcol(cell):
- """ pack row and column into the required 4 byte format """
- row, col, row_abs, col_abs = cell_to_rowcol(cell)
- if col >= MAX_COL:
- raise Exception("Column %s greater than IV in formula" % cell)
- if row >= MAX_ROW: # this for BIFF8. for BIFF7 available 2^14
- raise Exception("Row %s greater than %d in formula" % (cell, MAX_ROW))
- col |= int(not row_abs) << 15
- col |= int(not col_abs) << 14
- return row, col
-
-# === sheetname functions ===
-
-def valid_sheet_name(sheet_name):
- if sheet_name == u"" or sheet_name[0] == u"'" or len(sheet_name) > 31:
- return False
- for c in sheet_name:
- if c in u"[]:\\?/*\x00":
- return False
- return True
-
-def quote_sheet_name(unquoted_sheet_name):
- if not valid_sheet_name(unquoted_sheet_name):
- raise Exception(
- 'attempt to quote an invalid worksheet name %r' % unquoted_sheet_name)
- return u"'" + unquoted_sheet_name.replace(u"'", u"''") + u"'"
diff --git a/tablib/packages/xlwt/Workbook.py b/tablib/packages/xlwt/Workbook.py
deleted file mode 100644
index b24282b..0000000
--- a/tablib/packages/xlwt/Workbook.py
+++ /dev/null
@@ -1,636 +0,0 @@
-# -*- coding: windows-1252 -*-
-'''
-Record Order in BIFF8
- Workbook Globals Substream
- BOF Type = workbook globals
- Interface Header
- MMS
- Interface End
- WRITEACCESS
- CODEPAGE
- DSF
- TABID
- FNGROUPCOUNT
- Workbook Protection Block
- WINDOWPROTECT
- PROTECT
- PASSWORD
- PROT4REV
- PROT4REVPASS
- BACKUP
- HIDEOBJ
- WINDOW1
- DATEMODE
- PRECISION
- REFRESHALL
- BOOKBOOL
- FONT +
- FORMAT *
- XF +
- STYLE +
- ? PALETTE
- USESELFS
-
- BOUNDSHEET +
-
- COUNTRY
- ? Link Table
- SST
- ExtSST
- EOF
-'''
-
-import BIFFRecords
-import Style
-
-class Workbook(object):
-
- #################################################################
- ## Constructor
- #################################################################
- def __init__(self, encoding='ascii', style_compression=0):
- self.encoding = encoding
- self.__owner = 'None'
- self.__country_code = None # 0x07 is Russia :-)
- self.__wnd_protect = 0
- self.__obj_protect = 0
- self.__protect = 0
- self.__backup_on_save = 0
- # for WINDOW1 record
- self.__hpos_twips = 0x01E0
- self.__vpos_twips = 0x005A
- self.__width_twips = 0x3FCF
- self.__height_twips = 0x2A4E
-
- self.__active_sheet = 0
- self.__first_tab_index = 0
- self.__selected_tabs = 0x01
- self.__tab_width_twips = 0x0258
-
- self.__wnd_hidden = 0
- self.__wnd_mini = 0
- self.__hscroll_visible = 1
- self.__vscroll_visible = 1
- self.__tabs_visible = 1
-
- self.__styles = Style.StyleCollection(style_compression)
-
- self.__dates_1904 = 0
- self.__use_cell_values = 1
-
- self.__sst = BIFFRecords.SharedStringTable(self.encoding)
-
- self.__worksheets = []
- self.__worksheet_idx_from_name = {}
- self.__sheet_refs = {}
- self._supbook_xref = {}
- self._xcall_xref = {}
- self._ownbook_supbookx = None
- self._ownbook_supbook_ref = None
- self._xcall_supbookx = None
- self._xcall_supbook_ref = None
-
-
-
- #################################################################
- ## Properties, "getters", "setters"
- #################################################################
-
- def get_style_stats(self):
- return self.__styles.stats[:]
-
- def set_owner(self, value):
- self.__owner = value
-
- def get_owner(self):
- return self.__owner
-
- owner = property(get_owner, set_owner)
-
- #################################################################
-
- def set_country_code(self, value):
- self.__country_code = value
-
- def get_country_code(self):
- return self.__country_code
-
- country_code = property(get_country_code, set_country_code)
-
- #################################################################
-
- def set_wnd_protect(self, value):
- self.__wnd_protect = int(value)
-
- def get_wnd_protect(self):
- return bool(self.__wnd_protect)
-
- wnd_protect = property(get_wnd_protect, set_wnd_protect)
-
- #################################################################
-
- def set_obj_protect(self, value):
- self.__obj_protect = int(value)
-
- def get_obj_protect(self):
- return bool(self.__obj_protect)
-
- obj_protect = property(get_obj_protect, set_obj_protect)
-
- #################################################################
-
- def set_protect(self, value):
- self.__protect = int(value)
-
- def get_protect(self):
- return bool(self.__protect)
-
- protect = property(get_protect, set_protect)
-
- #################################################################
-
- def set_backup_on_save(self, value):
- self.__backup_on_save = int(value)
-
- def get_backup_on_save(self):
- return bool(self.__backup_on_save)
-
- backup_on_save = property(get_backup_on_save, set_backup_on_save)
-
- #################################################################
-
- def set_hpos(self, value):
- self.__hpos_twips = value & 0xFFFF
-
- def get_hpos(self):
- return self.__hpos_twips
-
- hpos = property(get_hpos, set_hpos)
-
- #################################################################
-
- def set_vpos(self, value):
- self.__vpos_twips = value & 0xFFFF
-
- def get_vpos(self):
- return self.__vpos_twips
-
- vpos = property(get_vpos, set_vpos)
-
- #################################################################
-
- def set_width(self, value):
- self.__width_twips = value & 0xFFFF
-
- def get_width(self):
- return self.__width_twips
-
- width = property(get_width, set_width)
-
- #################################################################
-
- def set_height(self, value):
- self.__height_twips = value & 0xFFFF
-
- def get_height(self):
- return self.__height_twips
-
- height = property(get_height, set_height)
-
- #################################################################
-
- def set_active_sheet(self, value):
- self.__active_sheet = value & 0xFFFF
- self.__first_tab_index = self.__active_sheet
-
- def get_active_sheet(self):
- return self.__active_sheet
-
- active_sheet = property(get_active_sheet, set_active_sheet)
-
- #################################################################
-
- def set_tab_width(self, value):
- self.__tab_width_twips = value & 0xFFFF
-
- def get_tab_width(self):
- return self.__tab_width_twips
-
- tab_width = property(get_tab_width, set_tab_width)
-
- #################################################################
-
- def set_wnd_visible(self, value):
- self.__wnd_hidden = int(not value)
-
- def get_wnd_visible(self):
- return not bool(self.__wnd_hidden)
-
- wnd_visible = property(get_wnd_visible, set_wnd_visible)
-
- #################################################################
-
- def set_wnd_mini(self, value):
- self.__wnd_mini = int(value)
-
- def get_wnd_mini(self):
- return bool(self.__wnd_mini)
-
- wnd_mini = property(get_wnd_mini, set_wnd_mini)
-
- #################################################################
-
- def set_hscroll_visible(self, value):
- self.__hscroll_visible = int(value)
-
- def get_hscroll_visible(self):
- return bool(self.__hscroll_visible)
-
- hscroll_visible = property(get_hscroll_visible, set_hscroll_visible)
-
- #################################################################
-
- def set_vscroll_visible(self, value):
- self.__vscroll_visible = int(value)
-
- def get_vscroll_visible(self):
- return bool(self.__vscroll_visible)
-
- vscroll_visible = property(get_vscroll_visible, set_vscroll_visible)
-
- #################################################################
-
- def set_tabs_visible(self, value):
- self.__tabs_visible = int(value)
-
- def get_tabs_visible(self):
- return bool(self.__tabs_visible)
-
- tabs_visible = property(get_tabs_visible, set_tabs_visible)
-
- #################################################################
-
- def set_dates_1904(self, value):
- self.__dates_1904 = int(value)
-
- def get_dates_1904(self):
- return bool(self.__dates_1904)
-
- dates_1904 = property(get_dates_1904, set_dates_1904)
-
- #################################################################
-
- def set_use_cell_values(self, value):
- self.__use_cell_values = int(value)
-
- def get_use_cell_values(self):
- return bool(self.__use_cell_values)
-
- use_cell_values = property(get_use_cell_values, set_use_cell_values)
-
- #################################################################
-
- def get_default_style(self):
- return self.__styles.default_style
-
- default_style = property(get_default_style)
-
- ##################################################################
- ## Methods
- ##################################################################
-
- def add_style(self, style):
- return self.__styles.add(style)
-
- def add_str(self, s):
- return self.__sst.add_str(s)
-
- def del_str(self, sst_idx):
- self.__sst.del_str(sst_idx)
-
- def str_index(self, s):
- return self.__sst.str_index(s)
-
- def add_sheet(self, sheetname, cell_overwrite_ok=False):
- import Worksheet, Utils
- if not isinstance(sheetname, unicode):
- sheetname = sheetname.decode(self.encoding)
- if not Utils.valid_sheet_name(sheetname):
- raise Exception("invalid worksheet name %r" % sheetname)
- lower_name = sheetname.lower()
- if lower_name in self.__worksheet_idx_from_name:
- raise Exception("duplicate worksheet name %r" % sheetname)
- self.__worksheet_idx_from_name[lower_name] = len(self.__worksheets)
- self.__worksheets.append(Worksheet.Worksheet(sheetname, self, cell_overwrite_ok))
- return self.__worksheets[-1]
-
- def get_sheet(self, sheetnum):
- return self.__worksheets[sheetnum]
-
- def raise_bad_sheetname(self, sheetname):
- raise Exception("Formula: unknown sheet name %s" % sheetname)
-
- def convert_sheetindex(self, strg_ref, n_sheets):
- idx = int(strg_ref)
- if 0 <= idx < n_sheets:
- return idx
- msg = "Formula: sheet index (%s) >= number of sheets (%d)" % (strg_ref, n_sheets)
- raise Exception(msg)
-
- def _get_supbook_index(self, tag):
- if tag in self._supbook_xref:
- return self._supbook_xref[tag]
- self._supbook_xref[tag] = idx = len(self._supbook_xref)
- return idx
-
- def setup_ownbook(self):
- self._ownbook_supbookx = self._get_supbook_index(('ownbook', 0))
- self._ownbook_supbook_ref = None
- reference = (self._ownbook_supbookx, 0xFFFE, 0xFFFE)
- if reference in self.__sheet_refs:
- raise Exception("can't happen")
- self.__sheet_refs[reference] = self._ownbook_supbook_ref = len(self.__sheet_refs)
-
- def setup_xcall(self):
- self._xcall_supbookx = self._get_supbook_index(('xcall', 0))
- self._xcall_supbook_ref = None
- reference = (self._xcall_supbookx, 0xFFFE, 0xFFFE)
- if reference in self.__sheet_refs:
- raise Exception("can't happen")
- self.__sheet_refs[reference] = self._xcall_supbook_ref = len(self.__sheet_refs)
-
- def add_sheet_reference(self, formula):
- patches = []
- n_sheets = len(self.__worksheets)
- sheet_refs, xcall_refs = formula.get_references()
-
- for ref0, ref1, offset in sheet_refs:
- if not ref0.isdigit():
- try:
- ref0n = self.__worksheet_idx_from_name[ref0.lower()]
- except KeyError:
- self.raise_bad_sheetname(ref0)
- else:
- ref0n = self.convert_sheetindex(ref0, n_sheets)
- if ref1 == ref0:
- ref1n = ref0n
- elif not ref1.isdigit():
- try:
- ref1n = self.__worksheet_idx_from_name[ref1.lower()]
- except KeyError:
- self.raise_bad_sheetname(ref1)
- else:
- ref1n = self.convert_sheetindex(ref1, n_sheets)
- if ref1n < ref0n:
- msg = "Formula: sheets out of order; %r:%r -> (%d, %d)" \
- % (ref0, ref1, ref0n, ref1n)
- raise Exception(msg)
- if self._ownbook_supbookx is None:
- self.setup_ownbook()
- reference = (self._ownbook_supbookx, ref0n, ref1n)
- if reference in self.__sheet_refs:
- patches.append((offset, self.__sheet_refs[reference]))
- else:
- nrefs = len(self.__sheet_refs)
- if nrefs > 65535:
- raise Exception('More than 65536 inter-sheet references')
- self.__sheet_refs[reference] = nrefs
- patches.append((offset, nrefs))
-
- for funcname, offset in xcall_refs:
- if self._ownbook_supbookx is None:
- self.setup_ownbook()
- if self._xcall_supbookx is None:
- self.setup_xcall()
- # print funcname, self._supbook_xref
- patches.append((offset, self._xcall_supbook_ref))
- if not isinstance(funcname, unicode):
- funcname = funcname.decode(self.encoding)
- if funcname in self._xcall_xref:
- idx = self._xcall_xref[funcname]
- else:
- self._xcall_xref[funcname] = idx = len(self._xcall_xref)
- patches.append((offset + 2, idx + 1))
-
- formula.patch_references(patches)
-
- ##################################################################
- ## BIFF records generation
- ##################################################################
-
- def __bof_rec(self):
- return BIFFRecords.Biff8BOFRecord(BIFFRecords.Biff8BOFRecord.BOOK_GLOBAL).get()
-
- def __eof_rec(self):
- return BIFFRecords.EOFRecord().get()
-
- def __intf_hdr_rec(self):
- return BIFFRecords.InteraceHdrRecord().get()
-
- def __intf_end_rec(self):
- return BIFFRecords.InteraceEndRecord().get()
-
- def __intf_mms_rec(self):
- return BIFFRecords.MMSRecord().get()
-
- def __write_access_rec(self):
- return BIFFRecords.WriteAccessRecord(self.__owner).get()
-
- def __wnd_protect_rec(self):
- return BIFFRecords.WindowProtectRecord(self.__wnd_protect).get()
-
- def __obj_protect_rec(self):
- return BIFFRecords.ObjectProtectRecord(self.__obj_protect).get()
-
- def __protect_rec(self):
- return BIFFRecords.ProtectRecord(self.__protect).get()
-
- def __password_rec(self):
- return BIFFRecords.PasswordRecord().get()
-
- def __prot4rev_rec(self):
- return BIFFRecords.Prot4RevRecord().get()
-
- def __prot4rev_pass_rec(self):
- return BIFFRecords.Prot4RevPassRecord().get()
-
- def __backup_rec(self):
- return BIFFRecords.BackupRecord(self.__backup_on_save).get()
-
- def __hide_obj_rec(self):
- return BIFFRecords.HideObjRecord().get()
-
- def __window1_rec(self):
- flags = 0
- flags |= (self.__wnd_hidden) << 0
- flags |= (self.__wnd_mini) << 1
- flags |= (self.__hscroll_visible) << 3
- flags |= (self.__vscroll_visible) << 4
- flags |= (self.__tabs_visible) << 5
-
- return BIFFRecords.Window1Record(self.__hpos_twips, self.__vpos_twips,
- self.__width_twips, self.__height_twips,
- flags,
- self.__active_sheet, self.__first_tab_index,
- self.__selected_tabs, self.__tab_width_twips).get()
-
- def __codepage_rec(self):
- return BIFFRecords.CodepageBiff8Record().get()
-
- def __country_rec(self):
- if not self.__country_code:
- return ''
- return BIFFRecords.CountryRecord(self.__country_code, self.__country_code).get()
-
- def __dsf_rec(self):
- return BIFFRecords.DSFRecord().get()
-
- def __tabid_rec(self):
- return BIFFRecords.TabIDRecord(len(self.__worksheets)).get()
-
- def __fngroupcount_rec(self):
- return BIFFRecords.FnGroupCountRecord().get()
-
- def __datemode_rec(self):
- return BIFFRecords.DateModeRecord(self.__dates_1904).get()
-
- def __precision_rec(self):
- return BIFFRecords.PrecisionRecord(self.__use_cell_values).get()
-
- def __refresh_all_rec(self):
- return BIFFRecords.RefreshAllRecord().get()
-
- def __bookbool_rec(self):
- return BIFFRecords.BookBoolRecord().get()
-
- def __all_fonts_num_formats_xf_styles_rec(self):
- return self.__styles.get_biff_data()
-
- def __palette_rec(self):
- result = ''
- return result
-
- def __useselfs_rec(self):
- return BIFFRecords.UseSelfsRecord().get()
-
- def __boundsheets_rec(self, data_len_before, data_len_after, sheet_biff_lens):
- # .................................
- # BOUNDSEHEET0
- # BOUNDSEHEET1
- # BOUNDSEHEET2
- # ..................................
- # WORKSHEET0
- # WORKSHEET1
- # WORKSHEET2
- boundsheets_len = 0
- for sheet in self.__worksheets:
- boundsheets_len += len(BIFFRecords.BoundSheetRecord(
- 0x00L, sheet.visibility, sheet.name, self.encoding
- ).get())
-
- start = data_len_before + boundsheets_len + data_len_after
-
- result = ''
- for sheet_biff_len, sheet in zip(sheet_biff_lens, self.__worksheets):
- result += BIFFRecords.BoundSheetRecord(
- start, sheet.visibility, sheet.name, self.encoding
- ).get()
- start += sheet_biff_len
- return result
-
- def __all_links_rec(self):
- pieces = []
- temp = [(idx, tag) for tag, idx in self._supbook_xref.items()]
- temp.sort()
- for idx, tag in temp:
- stype, snum = tag
- if stype == 'ownbook':
- rec = BIFFRecords.InternalReferenceSupBookRecord(len(self.__worksheets)).get()
- pieces.append(rec)
- elif stype == 'xcall':
- rec = BIFFRecords.XcallSupBookRecord().get()
- pieces.append(rec)
- temp = [(idx, name) for name, idx in self._xcall_xref.items()]
- temp.sort()
- for idx, name in temp:
- rec = BIFFRecords.ExternnameRecord(
- options=0, index=0, name=name, fmla='\x02\x00\x1c\x17').get()
- pieces.append(rec)
- else:
- raise Exception('unknown supbook stype %r' % stype)
- if len(self.__sheet_refs) > 0:
- # get references in index order
- temp = [(idx, ref) for ref, idx in self.__sheet_refs.items()]
- temp.sort()
- temp = [ref for idx, ref in temp]
- externsheet_record = BIFFRecords.ExternSheetRecord(temp).get()
- pieces.append(externsheet_record)
- return ''.join(pieces)
-
- def __sst_rec(self):
- return self.__sst.get_biff_record()
-
- def __ext_sst_rec(self, abs_stream_pos):
- return ''
- #return BIFFRecords.ExtSSTRecord(abs_stream_pos, self.sst_record.str_placement,
- #self.sst_record.portions_len).get()
-
- def get_biff_data(self):
- before = ''
- before += self.__bof_rec()
- before += self.__intf_hdr_rec()
- before += self.__intf_mms_rec()
- before += self.__intf_end_rec()
- before += self.__write_access_rec()
- before += self.__codepage_rec()
- before += self.__dsf_rec()
- before += self.__tabid_rec()
- before += self.__fngroupcount_rec()
- before += self.__wnd_protect_rec()
- before += self.__protect_rec()
- before += self.__obj_protect_rec()
- before += self.__password_rec()
- before += self.__prot4rev_rec()
- before += self.__prot4rev_pass_rec()
- before += self.__backup_rec()
- before += self.__hide_obj_rec()
- before += self.__window1_rec()
- before += self.__datemode_rec()
- before += self.__precision_rec()
- before += self.__refresh_all_rec()
- before += self.__bookbool_rec()
- before += self.__all_fonts_num_formats_xf_styles_rec()
- before += self.__palette_rec()
- before += self.__useselfs_rec()
-
- country = self.__country_rec()
- all_links = self.__all_links_rec()
-
- shared_str_table = self.__sst_rec()
- after = country + all_links + shared_str_table
-
- ext_sst = self.__ext_sst_rec(0) # need fake cause we need calc stream pos
- eof = self.__eof_rec()
-
- self.__worksheets[self.__active_sheet].selected = True
- sheets = ''
- sheet_biff_lens = []
- for sheet in self.__worksheets:
- data = sheet.get_biff_data()
- sheets += data
- sheet_biff_lens.append(len(data))
-
- bundlesheets = self.__boundsheets_rec(len(before), len(after)+len(ext_sst)+len(eof), sheet_biff_lens)
-
- sst_stream_pos = len(before) + len(bundlesheets) + len(country) + len(all_links)
- ext_sst = self.__ext_sst_rec(sst_stream_pos)
-
- return before + bundlesheets + after + ext_sst + eof + sheets
-
- def save(self, filename):
- import CompoundDoc
-
- doc = CompoundDoc.XlsDoc()
- doc.save(filename, self.get_biff_data())
-
-
diff --git a/tablib/packages/xlwt/Worksheet.py b/tablib/packages/xlwt/Worksheet.py
deleted file mode 100644
index ff36f1d..0000000
--- a/tablib/packages/xlwt/Worksheet.py
+++ /dev/null
@@ -1,1297 +0,0 @@
-# -*- coding: windows-1252 -*-
-'''
- BOF
- UNCALCED
- INDEX
- Calculation Settings Block
- PRINTHEADERS
- PRINTGRIDLINES
- GRIDSET
- GUTS
- DEFAULTROWHEIGHT
- WSBOOL
- Page Settings Block
- Worksheet Protection Block
- DEFCOLWIDTH
- COLINFO
- SORT
- DIMENSIONS
- Row Blocks
- WINDOW2
- SCL
- PANE
- SELECTION
- STANDARDWIDTH
- MERGEDCELLS
- LABELRANGES
- PHONETIC
- Conditional Formatting Table
- Hyperlink Table
- Data Validity Table
- SHEETLAYOUT (BIFF8X only)
- SHEETPROTECTION (BIFF8X only)
- RANGEPROTECTION (BIFF8X only)
- EOF
-'''
-
-import BIFFRecords
-import Bitmap
-import Formatting
-import Style
-import tempfile
-
-
-class Worksheet(object):
- from Workbook import Workbook
-
- #################################################################
- ## Constructor
- #################################################################
- def __init__(self, sheetname, parent_book, cell_overwrite_ok=False):
- import Row
- self.Row = Row.Row
-
- import Column
- self.Column = Column.Column
-
- self.__name = sheetname
- self.__parent = parent_book
- self._cell_overwrite_ok = cell_overwrite_ok
-
- self.__rows = {}
- self.__cols = {}
- self.__merged_ranges = []
- self.__bmp_rec = ''
-
- self.__show_formulas = 0
- self.__show_grid = 1
- self.__show_headers = 1
- self.__panes_frozen = 0
- ### self.__show_empty_as_zero = 1 ### deprecated with extreme prejudice 2009-05-19
- self.show_zero_values = 1
- self.__auto_colour_grid = 1
- self.__cols_right_to_left = 0
- self.__show_outline = 1
- self.__remove_splits = 0
- self.__selected = 0
- # RED HERRING ALERT: "sheet_visible" is a clone of the "selected" attribute.
- # Typically a workbook created by the Excel UI will have one sheet
- # (the sheet that was selected when the user saved it)
- # with both bits set to 1, and all other sheets will have both
- # bits set to 0. The true visibility of the sheet is found in the "visibility"
- # attribute obtained from the BOUNDSHEET record.
- self.__sheet_visible = 0
- self.__page_preview = 0
-
- self.__first_visible_row = 0
- self.__first_visible_col = 0
- self.__grid_colour = 0x40
- self.__preview_magn = 60 # percent
- self.__normal_magn = 100 # percent
-
- self.visibility = 0 # from/to BOUNDSHEET record.
-
- self.__vert_split_pos = None
- self.__horz_split_pos = None
- self.__vert_split_first_visible = None
- self.__horz_split_first_visible = None
- self.__split_active_pane = None
-
- self.__row_gut_width = 0
- self.__col_gut_height = 0
-
- self.__show_auto_page_breaks = 1
- self.__dialogue_sheet = 0
- self.__auto_style_outline = 0
- self.__outline_below = 0
- self.__outline_right = 0
- self.__fit_num_pages = 0
- self.__show_row_outline = 1
- self.__show_col_outline = 1
- self.__alt_expr_eval = 0
- self.__alt_formula_entries = 0
-
- self.__row_default_height = 0x00FF
- self.row_default_height_mismatch = 0
- self.row_default_hidden = 0
- self.row_default_space_above = 0
- self.row_default_space_below = 0
-
- self.__col_default_width = 0x0008
-
- self.__calc_mode = 1
- self.__calc_count = 0x0064
- self.__RC_ref_mode = 1
- self.__iterations_on = 0
- self.__delta = 0.001
- self.__save_recalc = 0
-
- self.__print_headers = 0
- self.__print_grid = 0
- self.__grid_set = 1
- self.__vert_page_breaks = []
- self.__horz_page_breaks = []
- self.__header_str = '&P'
- self.__footer_str = '&F'
- self.__print_centered_vert = 0
- self.__print_centered_horz = 1
- self.__left_margin = 0.3 #0.5
- self.__right_margin = 0.3 #0.5
- self.__top_margin = 0.61 #1.0
- self.__bottom_margin = 0.37 #1.0
- self.__paper_size_code = 9 # A4
- self.__print_scaling = 100
- self.__start_page_number = 1
- self.__fit_width_to_pages = 1
- self.__fit_height_to_pages = 1
- self.__print_in_rows = 1
- self.__portrait = 1
- self.__print_not_colour = 0
- self.__print_draft = 0
- self.__print_notes = 0
- self.__print_notes_at_end = 0
- self.__print_omit_errors = 0
- self.__print_hres = 0x012C # 300 dpi
- self.__print_vres = 0x012C # 300 dpi
- self.__header_margin = 0.1
- self.__footer_margin = 0.1
- self.__copies_num = 1
-
- self.__wnd_protect = 0
- self.__obj_protect = 0
- self.__protect = 0
- self.__scen_protect = 0
- self.__password = ''
-
- self.last_used_row = 0
- self.first_used_row = 65535
- self.last_used_col = 0
- self.first_used_col = 255
- self.row_tempfile = None
- self.__flushed_rows = {}
- self.__row_visible_levels = 0
-
- #################################################################
- ## Properties, "getters", "setters"
- #################################################################
-
- def set_name(self, value):
- self.__name = value
-
- def get_name(self):
- return self.__name
-
- name = property(get_name, set_name)
-
- #################################################################
-
- def get_parent(self):
- return self.__parent
-
- parent = property(get_parent)
-
- #################################################################
-
- def get_rows(self):
- return self.__rows
-
- rows = property(get_rows)
-
- #################################################################
-
- def get_cols(self):
- return self.__cols
-
- cols = property(get_cols)
-
- #################################################################
-
- def get_merged_ranges(self):
- return self.__merged_ranges
-
- merged_ranges = property(get_merged_ranges)
-
- #################################################################
-
- def get_bmp_rec(self):
- return self.__bmp_rec
-
- bmp_rec = property(get_bmp_rec)
-
- #################################################################
-
- def set_show_formulas(self, value):
- self.__show_formulas = int(value)
-
- def get_show_formulas(self):
- return bool(self.__show_formulas)
-
- show_formulas = property(get_show_formulas, set_show_formulas)
-
- #################################################################
-
- def set_show_grid(self, value):
- self.__show_grid = int(value)
-
- def get_show_grid(self):
- return bool(self.__show_grid)
-
- show_grid = property(get_show_grid, set_show_grid)
-
- #################################################################
-
- def set_show_headers(self, value):
- self.__show_headers = int(value)
-
- def get_show_headers(self):
- return bool(self.__show_headers)
-
- show_headers = property(get_show_headers, set_show_headers)
-
- #################################################################
-
- def set_panes_frozen(self, value):
- self.__panes_frozen = int(value)
-
- def get_panes_frozen(self):
- return bool(self.__panes_frozen)
-
- panes_frozen = property(get_panes_frozen, set_panes_frozen)
-
- #################################################################
-
- ### def set_show_empty_as_zero(self, value):
- ### self.__show_empty_as_zero = int(value)
-
- ### def get_show_empty_as_zero(self):
- ### return bool(self.__show_empty_as_zero)
-
- ### show_empty_as_zero = property(get_show_empty_as_zero, set_show_empty_as_zero)
-
- #################################################################
-
- def set_auto_colour_grid(self, value):
- self.__auto_colour_grid = int(value)
-
- def get_auto_colour_grid(self):
- return bool(self.__auto_colour_grid)
-
- auto_colour_grid = property(get_auto_colour_grid, set_auto_colour_grid)
-
- #################################################################
-
- def set_cols_right_to_left(self, value):
- self.__cols_right_to_left = int(value)
-
- def get_cols_right_to_left(self):
- return bool(self.__cols_right_to_left)
-
- cols_right_to_left = property(get_cols_right_to_left, set_cols_right_to_left)
-
- #################################################################
-
- def set_show_outline(self, value):
- self.__show_outline = int(value)
-
- def get_show_outline(self):
- return bool(self.__show_outline)
-
- show_outline = property(get_show_outline, set_show_outline)
-
- #################################################################
-
- def set_remove_splits(self, value):
- self.__remove_splits = int(value)
-
- def get_remove_splits(self):
- return bool(self.__remove_splits)
-
- remove_splits = property(get_remove_splits, set_remove_splits)
-
- #################################################################
-
- def set_selected(self, value):
- self.__selected = int(value)
-
- def get_selected(self):
- return bool(self.__selected)
-
- selected = property(get_selected, set_selected)
-
- #################################################################
-
- def set_sheet_visible(self, value):
- self.__sheet_visible = int(value)
-
- def get_sheet_visible(self):
- return bool(self.__sheet_visible)
-
- sheet_visible = property(get_sheet_visible, set_sheet_visible)
-
- #################################################################
-
- def set_page_preview(self, value):
- self.__page_preview = int(value)
-
- def get_page_preview(self):
- return bool(self.__page_preview)
-
- page_preview = property(get_page_preview, set_page_preview)
-
- #################################################################
-
- def set_first_visible_row(self, value):
- self.__first_visible_row = value
-
- def get_first_visible_row(self):
- return self.__first_visible_row
-
- first_visible_row = property(get_first_visible_row, set_first_visible_row)
-
- #################################################################
-
- def set_first_visible_col(self, value):
- self.__first_visible_col = value
-
- def get_first_visible_col(self):
- return self.__first_visible_col
-
- first_visible_col = property(get_first_visible_col, set_first_visible_col)
-
- #################################################################
-
- def set_grid_colour(self, value):
- self.__grid_colour = value
-
- def get_grid_colour(self):
- return self.__grid_colour
-
- grid_colour = property(get_grid_colour, set_grid_colour)
-
- #################################################################
-
- def set_preview_magn(self, value):
- self.__preview_magn = value
-
- def get_preview_magn(self):
- return self.__preview_magn
-
- preview_magn = property(get_preview_magn, set_preview_magn)
-
- #################################################################
-
- def set_normal_magn(self, value):
- self.__normal_magn = value
-
- def get_normal_magn(self):
- return self.__normal_magn
-
- normal_magn = property(get_normal_magn, set_normal_magn)
-
- #################################################################
-
- def set_vert_split_pos(self, value):
- self.__vert_split_pos = abs(value)
-
- def get_vert_split_pos(self):
- return self.__vert_split_pos
-
- vert_split_pos = property(get_vert_split_pos, set_vert_split_pos)
-
- #################################################################
-
- def set_horz_split_pos(self, value):
- self.__horz_split_pos = abs(value)
-
- def get_horz_split_pos(self):
- return self.__horz_split_pos
-
- horz_split_pos = property(get_horz_split_pos, set_horz_split_pos)
-
- #################################################################
-
- def set_vert_split_first_visible(self, value):
- self.__vert_split_first_visible = abs(value)
-
- def get_vert_split_first_visible(self):
- return self.__vert_split_first_visible
-
- vert_split_first_visible = property(get_vert_split_first_visible, set_vert_split_first_visible)
-
- #################################################################
-
- def set_horz_split_first_visible(self, value):
- self.__horz_split_first_visible = abs(value)
-
- def get_horz_split_first_visible(self):
- return self.__horz_split_first_visible
-
- horz_split_first_visible = property(get_horz_split_first_visible, set_horz_split_first_visible)
-
- #################################################################
-
- #def set_split_active_pane(self, value):
- # self.__split_active_pane = abs(value) & 0x03
- #
- #def get_split_active_pane(self):
- # return self.__split_active_pane
- #
- #split_active_pane = property(get_split_active_pane, set_split_active_pane)
-
- #################################################################
-
- #def set_row_gut_width(self, value):
- # self.__row_gut_width = value
- #
- #def get_row_gut_width(self):
- # return self.__row_gut_width
- #
- #row_gut_width = property(get_row_gut_width, set_row_gut_width)
- #
- #################################################################
- #
- #def set_col_gut_height(self, value):
- # self.__col_gut_height = value
- #
- #def get_col_gut_height(self):
- # return self.__col_gut_height
- #
- #col_gut_height = property(get_col_gut_height, set_col_gut_height)
- #
- #################################################################
-
- def set_show_auto_page_breaks(self, value):
- self.__show_auto_page_breaks = int(value)
-
- def get_show_auto_page_breaks(self):
- return bool(self.__show_auto_page_breaks)
-
- show_auto_page_breaks = property(get_show_auto_page_breaks, set_show_auto_page_breaks)
-
- #################################################################
-
- def set_dialogue_sheet(self, value):
- self.__dialogue_sheet = int(value)
-
- def get_dialogue_sheet(self):
- return bool(self.__dialogue_sheet)
-
- dialogue_sheet = property(get_dialogue_sheet, set_dialogue_sheet)
-
- #################################################################
-
- def set_auto_style_outline(self, value):
- self.__auto_style_outline = int(value)
-
- def get_auto_style_outline(self):
- return bool(self.__auto_style_outline)
-
- auto_style_outline = property(get_auto_style_outline, set_auto_style_outline)
-
- #################################################################
-
- def set_outline_below(self, value):
- self.__outline_below = int(value)
-
- def get_outline_below(self):
- return bool(self.__outline_below)
-
- outline_below = property(get_outline_below, set_outline_below)
-
- #################################################################
-
- def set_outline_right(self, value):
- self.__outline_right = int(value)
-
- def get_outline_right(self):
- return bool(self.__outline_right)
-
- outline_right = property(get_outline_right, set_outline_right)
-
- #################################################################
-
- def set_fit_num_pages(self, value):
- self.__fit_num_pages = value
-
- def get_fit_num_pages(self):
- return self.__fit_num_pages
-
- fit_num_pages = property(get_fit_num_pages, set_fit_num_pages)
-
- #################################################################
-
- def set_show_row_outline(self, value):
- self.__show_row_outline = int(value)
-
- def get_show_row_outline(self):
- return bool(self.__show_row_outline)
-
- show_row_outline = property(get_show_row_outline, set_show_row_outline)
-
- #################################################################
-
- def set_show_col_outline(self, value):
- self.__show_col_outline = int(value)
-
- def get_show_col_outline(self):
- return bool(self.__show_col_outline)
-
- show_col_outline = property(get_show_col_outline, set_show_col_outline)
-
- #################################################################
-
- def set_alt_expr_eval(self, value):
- self.__alt_expr_eval = int(value)
-
- def get_alt_expr_eval(self):
- return bool(self.__alt_expr_eval)
-
- alt_expr_eval = property(get_alt_expr_eval, set_alt_expr_eval)
-
- #################################################################
-
- def set_alt_formula_entries(self, value):
- self.__alt_formula_entries = int(value)
-
- def get_alt_formula_entries(self):
- return bool(self.__alt_formula_entries)
-
- alt_formula_entries = property(get_alt_formula_entries, set_alt_formula_entries)
-
- #################################################################
-
- def set_row_default_height(self, value):
- self.__row_default_height = value
-
- def get_row_default_height(self):
- return self.__row_default_height
-
- row_default_height = property(get_row_default_height, set_row_default_height)
-
- #################################################################
-
- def set_col_default_width(self, value):
- self.__col_default_width = value
-
- def get_col_default_width(self):
- return self.__col_default_width
-
- col_default_width = property(get_col_default_width, set_col_default_width)
-
- #################################################################
-
- def set_calc_mode(self, value):
- self.__calc_mode = value & 0x03
-
- def get_calc_mode(self):
- return self.__calc_mode
-
- calc_mode = property(get_calc_mode, set_calc_mode)
-
- #################################################################
-
- def set_calc_count(self, value):
- self.__calc_count = value
-
- def get_calc_count(self):
- return self.__calc_count
-
- calc_count = property(get_calc_count, set_calc_count)
-
- #################################################################
-
- def set_RC_ref_mode(self, value):
- self.__RC_ref_mode = int(value)
-
- def get_RC_ref_mode(self):
- return bool(self.__RC_ref_mode)
-
- RC_ref_mode = property(get_RC_ref_mode, set_RC_ref_mode)
-
- #################################################################
-
- def set_iterations_on(self, value):
- self.__iterations_on = int(value)
-
- def get_iterations_on(self):
- return bool(self.__iterations_on)
-
- iterations_on = property(get_iterations_on, set_iterations_on)
-
- #################################################################
-
- def set_delta(self, value):
- self.__delta = value
-
- def get_delta(self):
- return self.__delta
-
- delta = property(get_delta, set_delta)
-
- #################################################################
-
- def set_save_recalc(self, value):
- self.__save_recalc = int(value)
-
- def get_save_recalc(self):
- return bool(self.__save_recalc)
-
- save_recalc = property(get_save_recalc, set_save_recalc)
-
- #################################################################
-
- def set_print_headers(self, value):
- self.__print_headers = int(value)
-
- def get_print_headers(self):
- return bool(self.__print_headers)
-
- print_headers = property(get_print_headers, set_print_headers)
-
- #################################################################
-
- def set_print_grid(self, value):
- self.__print_grid = int(value)
-
- def get_print_grid(self):
- return bool(self.__print_grid)
-
- print_grid = property(get_print_grid, set_print_grid)
-
- #################################################################
- #
- #def set_grid_set(self, value):
- # self.__grid_set = int(value)
- #
- #def get_grid_set(self):
- # return bool(self.__grid_set)
- #
- #grid_set = property(get_grid_set, set_grid_set)
- #
- #################################################################
-
- def set_vert_page_breaks(self, value):
- self.__vert_page_breaks = value
-
- def get_vert_page_breaks(self):
- return self.__vert_page_breaks
-
- vert_page_breaks = property(get_vert_page_breaks, set_vert_page_breaks)
-
- #################################################################
-
- def set_horz_page_breaks(self, value):
- self.__horz_page_breaks = value
-
- def get_horz_page_breaks(self):
- return self.__horz_page_breaks
-
- horz_page_breaks = property(get_horz_page_breaks, set_horz_page_breaks)
-
- #################################################################
-
- def set_header_str(self, value):
- if isinstance(value, str):
- value = unicode(value, self.__parent.encoding)
- self.__header_str = value
-
- def get_header_str(self):
- return self.__header_str
-
- header_str = property(get_header_str, set_header_str)
-
- #################################################################
-
- def set_footer_str(self, value):
- if isinstance(value, str):
- value = unicode(value, self.__parent.encoding)
- self.__footer_str = value
-
- def get_footer_str(self):
- return self.__footer_str
-
- footer_str = property(get_footer_str, set_footer_str)
-
- #################################################################
-
- def set_print_centered_vert(self, value):
- self.__print_centered_vert = int(value)
-
- def get_print_centered_vert(self):
- return bool(self.__print_centered_vert)
-
- print_centered_vert = property(get_print_centered_vert, set_print_centered_vert)
-
- #################################################################
-
- def set_print_centered_horz(self, value):
- self.__print_centered_horz = int(value)
-
- def get_print_centered_horz(self):
- return bool(self.__print_centered_horz)
-
- print_centered_horz = property(get_print_centered_horz, set_print_centered_horz)
-
- #################################################################
-
- def set_left_margin(self, value):
- self.__left_margin = value
-
- def get_left_margin(self):
- return self.__left_margin
-
- left_margin = property(get_left_margin, set_left_margin)
-
- #################################################################
-
- def set_right_margin(self, value):
- self.__right_margin = value
-
- def get_right_margin(self):
- return self.__right_margin
-
- right_margin = property(get_right_margin, set_right_margin)
-
- #################################################################
-
- def set_top_margin(self, value):
- self.__top_margin = value
-
- def get_top_margin(self):
- return self.__top_margin
-
- top_margin = property(get_top_margin, set_top_margin)
-
- #################################################################
-
- def set_bottom_margin(self, value):
- self.__bottom_margin = value
-
- def get_bottom_margin(self):
- return self.__bottom_margin
-
- bottom_margin = property(get_bottom_margin, set_bottom_margin)
-
- #################################################################
-
- def set_paper_size_code(self, value):
- self.__paper_size_code = value
-
- def get_paper_size_code(self):
- return self.__paper_size_code
-
- paper_size_code = property(get_paper_size_code, set_paper_size_code)
-
- #################################################################
-
- def set_print_scaling(self, value):
- self.__print_scaling = value
-
- def get_print_scaling(self):
- return self.__print_scaling
-
- print_scaling = property(get_print_scaling, set_print_scaling)
-
- #################################################################
-
- def set_start_page_number(self, value):
- self.__start_page_number = value
-
- def get_start_page_number(self):
- return self.__start_page_number
-
- start_page_number = property(get_start_page_number, set_start_page_number)
-
- #################################################################
-
- def set_fit_width_to_pages(self, value):
- self.__fit_width_to_pages = value
-
- def get_fit_width_to_pages(self):
- return self.__fit_width_to_pages
-
- fit_width_to_pages = property(get_fit_width_to_pages, set_fit_width_to_pages)
-
- #################################################################
-
- def set_fit_height_to_pages(self, value):
- self.__fit_height_to_pages = value
-
- def get_fit_height_to_pages(self):
- return self.__fit_height_to_pages
-
- fit_height_to_pages = property(get_fit_height_to_pages, set_fit_height_to_pages)
-
- #################################################################
-
- def set_print_in_rows(self, value):
- self.__print_in_rows = int(value)
-
- def get_print_in_rows(self):
- return bool(self.__print_in_rows)
-
- print_in_rows = property(get_print_in_rows, set_print_in_rows)
-
- #################################################################
-
- def set_portrait(self, value):
- self.__portrait = int(value)
-
- def get_portrait(self):
- return bool(self.__portrait)
-
- portrait = property(get_portrait, set_portrait)
-
- #################################################################
-
- def set_print_colour(self, value):
- self.__print_not_colour = int(not value)
-
- def get_print_colour(self):
- return not bool(self.__print_not_colour)
-
- print_colour = property(get_print_colour, set_print_colour)
-
- #################################################################
-
- def set_print_draft(self, value):
- self.__print_draft = int(value)
-
- def get_print_draft(self):
- return bool(self.__print_draft)
-
- print_draft = property(get_print_draft, set_print_draft)
-
- #################################################################
-
- def set_print_notes(self, value):
- self.__print_notes = int(value)
-
- def get_print_notes(self):
- return bool(self.__print_notes)
-
- print_notes = property(get_print_notes, set_print_notes)
-
- #################################################################
-
- def set_print_notes_at_end(self, value):
- self.__print_notes_at_end = int(value)
-
- def get_print_notes_at_end(self):
- return bool(self.__print_notes_at_end)
-
- print_notes_at_end = property(get_print_notes_at_end, set_print_notes_at_end)
-
- #################################################################
-
- def set_print_omit_errors(self, value):
- self.__print_omit_errors = int(value)
-
- def get_print_omit_errors(self):
- return bool(self.__print_omit_errors)
-
- print_omit_errors = property(get_print_omit_errors, set_print_omit_errors)
-
- #################################################################
-
- def set_print_hres(self, value):
- self.__print_hres = value
-
- def get_print_hres(self):
- return self.__print_hres
-
- print_hres = property(get_print_hres, set_print_hres)
-
- #################################################################
-
- def set_print_vres(self, value):
- self.__print_vres = value
-
- def get_print_vres(self):
- return self.__print_vres
-
- print_vres = property(get_print_vres, set_print_vres)
-
- #################################################################
-
- def set_header_margin(self, value):
- self.__header_margin = value
-
- def get_header_margin(self):
- return self.__header_margin
-
- header_margin = property(get_header_margin, set_header_margin)
-
- #################################################################
-
- def set_footer_margin(self, value):
- self.__footer_margin = value
-
- def get_footer_margin(self):
- return self.__footer_margin
-
- footer_margin = property(get_footer_margin, set_footer_margin)
-
- #################################################################
-
- def set_copies_num(self, value):
- self.__copies_num = value
-
- def get_copies_num(self):
- return self.__copies_num
-
- copies_num = property(get_copies_num, set_copies_num)
-
- ##################################################################
-
- def set_wnd_protect(self, value):
- self.__wnd_protect = int(value)
-
- def get_wnd_protect(self):
- return bool(self.__wnd_protect)
-
- wnd_protect = property(get_wnd_protect, set_wnd_protect)
-
- #################################################################
-
- def set_obj_protect(self, value):
- self.__obj_protect = int(value)
-
- def get_obj_protect(self):
- return bool(self.__obj_protect)
-
- obj_protect = property(get_obj_protect, set_obj_protect)
-
- #################################################################
-
- def set_protect(self, value):
- self.__protect = int(value)
-
- def get_protect(self):
- return bool(self.__protect)
-
- protect = property(get_protect, set_protect)
-
- #################################################################
-
- def set_scen_protect(self, value):
- self.__scen_protect = int(value)
-
- def get_scen_protect(self):
- return bool(self.__scen_protect)
-
- scen_protect = property(get_scen_protect, set_scen_protect)
-
- #################################################################
-
- def set_password(self, value):
- self.__password = value
-
- def get_password(self):
- return self.__password
-
- password = property(get_password, set_password)
-
- ##################################################################
- ## Methods
- ##################################################################
-
- def get_parent(self):
- return self.__parent
-
- def write(self, r, c, label="", style=Style.default_style):
- self.row(r).write(c, label, style)
-
- def merge(self, r1, r2, c1, c2, style=Style.default_style):
- # Stand-alone merge of previously written cells.
- # Problems: (1) style to be used should be existing style of
- # the top-left cell, not an arg.
- # (2) should ensure that any previous data value in
- # non-top-left cells is nobbled.
- # Note: if a cell is set by a data record then later
- # is referenced by a [MUL]BLANK record, Excel will blank
- # out the cell on the screen, but OOo & Gnu will not
- # blank it out. Need to do something better than writing
- # multiple records. In the meantime, avoid this method and use
- # write_merge() instead.
- if c2 > c1:
- self.row(r1).write_blanks(c1 + 1, c2, style)
- for r in range(r1+1, r2+1):
- self.row(r).write_blanks(c1, c2, style)
- self.__merged_ranges.append((r1, r2, c1, c2))
-
- def write_merge(self, r1, r2, c1, c2, label="", style=Style.default_style):
- assert 0 <= c1 <= c2 <= 255
- assert 0 <= r1 <= r2 <= 65535
- self.write(r1, c1, label, style)
- if c2 > c1:
- self.row(r1).write_blanks(c1 + 1, c2, style) # skip (r1, c1)
- for r in range(r1+1, r2+1):
- self.row(r).write_blanks(c1, c2, style)
- self.__merged_ranges.append((r1, r2, c1, c2))
-
- def insert_bitmap(self, filename, row, col, x = 0, y = 0, scale_x = 1, scale_y = 1):
- bmp = Bitmap.ImDataBmpRecord(filename)
- obj = Bitmap.ObjBmpRecord(row, col, self, bmp, x, y, scale_x, scale_y)
-
- self.__bmp_rec += obj.get() + bmp.get()
-
- def col(self, indx):
- if indx not in self.__cols:
- self.__cols[indx] = self.Column(indx, self)
- return self.__cols[indx]
-
- def row(self, indx):
- if indx not in self.__rows:
- if indx in self.__flushed_rows:
- raise Exception("Attempt to reuse row index %d of sheet %r after flushing" % (indx, self.__name))
- self.__rows[indx] = self.Row(indx, self)
- if indx > self.last_used_row:
- self.last_used_row = indx
- if indx < self.first_used_row:
- self.first_used_row = indx
- return self.__rows[indx]
-
- def row_height(self, row): # in pixels
- if row in self.__rows:
- return self.__rows[row].get_height_in_pixels()
- else:
- return 17
-
- def col_width(self, col): # in pixels
- if col in self.__cols:
- return self.__cols[col].width_in_pixels()
- else:
- return 64
-
-
- ##################################################################
- ## BIFF records generation
- ##################################################################
-
- def __bof_rec(self):
- return BIFFRecords.Biff8BOFRecord(BIFFRecords.Biff8BOFRecord.WORKSHEET).get()
-
- def __update_row_visible_levels(self):
- if self.__rows:
- temp = max([self.__rows[r].level for r in self.__rows]) + 1
- self.__row_visible_levels = max(temp, self.__row_visible_levels)
-
- def __guts_rec(self):
- self.__update_row_visible_levels()
- col_visible_levels = 0
- if len(self.__cols) != 0:
- col_visible_levels = max([self.__cols[c].level for c in self.__cols]) + 1
- return BIFFRecords.GutsRecord(
- self.__row_gut_width, self.__col_gut_height, self.__row_visible_levels, col_visible_levels).get()
-
- def __defaultrowheight_rec(self):
- options = 0x0000
- options |= (self.row_default_height_mismatch & 1) << 0
- options |= (self.row_default_hidden & 1) << 1
- options |= (self.row_default_space_above & 1) << 2
- options |= (self.row_default_space_below & 1) << 3
- defht = self.__row_default_height
- return BIFFRecords.DefaultRowHeightRecord(options, defht).get()
-
- def __wsbool_rec(self):
- options = 0x00
- options |= (self.__show_auto_page_breaks & 0x01) << 0
- options |= (self.__dialogue_sheet & 0x01) << 4
- options |= (self.__auto_style_outline & 0x01) << 5
- options |= (self.__outline_below & 0x01) << 6
- options |= (self.__outline_right & 0x01) << 7
- options |= (self.__fit_num_pages & 0x01) << 8
- options |= (self.__show_row_outline & 0x01) << 10
- options |= (self.__show_col_outline & 0x01) << 11
- options |= (self.__alt_expr_eval & 0x01) << 14
- options |= (self.__alt_formula_entries & 0x01) << 15
-
- return BIFFRecords.WSBoolRecord(options).get()
-
- def __eof_rec(self):
- return BIFFRecords.EOFRecord().get()
-
- def __colinfo_rec(self):
- result = ''
- for col in self.__cols:
- result += self.__cols[col].get_biff_record()
- return result
-
- def __dimensions_rec(self):
- return BIFFRecords.DimensionsRecord(
- self.first_used_row, self.last_used_row,
- self.first_used_col, self.last_used_col
- ).get()
-
- def __window2_rec(self):
- # Appends SCL record.
- options = 0
- options |= (self.__show_formulas & 0x01) << 0
- options |= (self.__show_grid & 0x01) << 1
- options |= (self.__show_headers & 0x01) << 2
- options |= (self.__panes_frozen & 0x01) << 3
- options |= (self.show_zero_values & 0x01) << 4
- options |= (self.__auto_colour_grid & 0x01) << 5
- options |= (self.__cols_right_to_left & 0x01) << 6
- options |= (self.__show_outline & 0x01) << 7
- options |= (self.__remove_splits & 0x01) << 8
- options |= (self.__selected & 0x01) << 9
- options |= (self.__sheet_visible & 0x01) << 10
- options |= (self.__page_preview & 0x01) << 11
- if self.__page_preview:
- scl_magn = self.__preview_magn
- else:
- scl_magn = self.__normal_magn
- return BIFFRecords.Window2Record(
- options, self.__first_visible_row, self.__first_visible_col,
- self.__grid_colour,
- self.__preview_magn, self.__normal_magn, scl_magn).get()
-
- def __panes_rec(self):
- if self.__vert_split_pos is None and self.__horz_split_pos is None:
- return ""
-
- if self.__vert_split_pos is None:
- self.__vert_split_pos = 0
- if self.__horz_split_pos is None:
- self.__horz_split_pos = 0
-
- if self.__panes_frozen:
- if self.__vert_split_first_visible is None:
- self.__vert_split_first_visible = self.__vert_split_pos
- if self.__horz_split_first_visible is None:
- self.__horz_split_first_visible = self.__horz_split_pos
- else:
- if self.__vert_split_first_visible is None:
- self.__vert_split_first_visible = 0
- if self.__horz_split_first_visible is None:
- self.__horz_split_first_visible = 0
- # inspired by pyXLWriter
- self.__horz_split_pos = 20*self.__horz_split_pos + 255
- self.__vert_split_pos = 113.879*self.__vert_split_pos + 390
-
- if self.__vert_split_pos > 0 and self.__horz_split_pos > 0:
- self.__split_active_pane = 0
- elif self.__vert_split_pos > 0 and self.__horz_split_pos == 0:
- self.__split_active_pane = 1
- elif self.__vert_split_pos == 0 and self.__horz_split_pos > 0:
- self.__split_active_pane = 2
- else:
- self.__split_active_pane = 3
-
- result = BIFFRecords.PanesRecord(self.__vert_split_pos,
- self.__horz_split_pos,
- self.__horz_split_first_visible,
- self.__vert_split_first_visible,
- self.__split_active_pane).get()
- return result
-
- def __row_blocks_rec(self):
- result = []
- for row in self.__rows.itervalues():
- result.append(row.get_row_biff_data())
- result.append(row.get_cells_biff_data())
- return ''.join(result)
-
- def __merged_rec(self):
- return BIFFRecords.MergedCellsRecord(self.__merged_ranges).get()
-
- def __bitmaps_rec(self):
- return self.__bmp_rec
-
- def __calc_settings_rec(self):
- result = ''
- result += BIFFRecords.CalcModeRecord(self.__calc_mode & 0x01).get()
- result += BIFFRecords.CalcCountRecord(self.__calc_count & 0xFFFF).get()
- result += BIFFRecords.RefModeRecord(self.__RC_ref_mode & 0x01).get()
- result += BIFFRecords.IterationRecord(self.__iterations_on & 0x01).get()
- result += BIFFRecords.DeltaRecord(self.__delta).get()
- result += BIFFRecords.SaveRecalcRecord(self.__save_recalc & 0x01).get()
- return result
-
- def __print_settings_rec(self):
- result = ''
- result += BIFFRecords.PrintHeadersRecord(self.__print_headers).get()
- result += BIFFRecords.PrintGridLinesRecord(self.__print_grid).get()
- result += BIFFRecords.GridSetRecord(self.__grid_set).get()
- result += BIFFRecords.HorizontalPageBreaksRecord(self.__horz_page_breaks).get()
- result += BIFFRecords.VerticalPageBreaksRecord(self.__vert_page_breaks).get()
- result += BIFFRecords.HeaderRecord(self.__header_str).get()
- result += BIFFRecords.FooterRecord(self.__footer_str).get()
- result += BIFFRecords.HCenterRecord(self.__print_centered_horz).get()
- result += BIFFRecords.VCenterRecord(self.__print_centered_vert).get()
- result += BIFFRecords.LeftMarginRecord(self.__left_margin).get()
- result += BIFFRecords.RightMarginRecord(self.__right_margin).get()
- result += BIFFRecords.TopMarginRecord(self.__top_margin).get()
- result += BIFFRecords.BottomMarginRecord(self.__bottom_margin).get()
-
- setup_page_options = (self.__print_in_rows & 0x01) << 0
- setup_page_options |= (self.__portrait & 0x01) << 1
- setup_page_options |= (0x00 & 0x01) << 2
- setup_page_options |= (self.__print_not_colour & 0x01) << 3
- setup_page_options |= (self.__print_draft & 0x01) << 4
- setup_page_options |= (self.__print_notes & 0x01) << 5
- setup_page_options |= (0x00 & 0x01) << 6
- setup_page_options |= (0x01 & 0x01) << 7
- setup_page_options |= (self.__print_notes_at_end & 0x01) << 9
- setup_page_options |= (self.__print_omit_errors & 0x03) << 10
-
- result += BIFFRecords.SetupPageRecord(self.__paper_size_code,
- self.__print_scaling,
- self.__start_page_number,
- self.__fit_width_to_pages,
- self.__fit_height_to_pages,
- setup_page_options,
- self.__print_hres,
- self.__print_vres,
- self.__header_margin,
- self.__footer_margin,
- self.__copies_num).get()
- return result
-
- def __protection_rec(self):
- result = ''
- result += BIFFRecords.ProtectRecord(self.__protect).get()
- result += BIFFRecords.ScenProtectRecord(self.__scen_protect).get()
- result += BIFFRecords.WindowProtectRecord(self.__wnd_protect).get()
- result += BIFFRecords.ObjectProtectRecord(self.__obj_protect).get()
- result += BIFFRecords.PasswordRecord(self.__password).get()
- return result
-
- def get_biff_data(self):
- result = [
- self.__bof_rec(),
- self.__calc_settings_rec(),
- self.__guts_rec(),
- self.__defaultrowheight_rec(),
- self.__wsbool_rec(),
- self.__colinfo_rec(),
- self.__dimensions_rec(),
- self.__print_settings_rec(),
- self.__protection_rec(),
- ]
- if self.row_tempfile:
- self.row_tempfile.flush()
- self.row_tempfile.seek(0)
- result.append(self.row_tempfile.read())
- result.extend([
- self.__row_blocks_rec(),
- self.__merged_rec(),
- self.__bitmaps_rec(),
- self.__window2_rec(),
- self.__panes_rec(),
- self.__eof_rec(),
- ])
- return ''.join(result)
-
- def flush_row_data(self):
- if self.row_tempfile is None:
- self.row_tempfile = tempfile.TemporaryFile()
- self.row_tempfile.write(self.__row_blocks_rec())
- for rowx in self.__rows:
- self.__flushed_rows[rowx] = 1
- self.__update_row_visible_levels()
- self.__rows = {}
-
-
diff --git a/tablib/packages/xlwt/__init__.py b/tablib/packages/xlwt/__init__.py
deleted file mode 100644
index cb65687..0000000
--- a/tablib/packages/xlwt/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# -*- coding: windows-1252 -*-
-
-__VERSION__ = '0.7.2'
-
-import sys
-
-from Workbook import Workbook
-from Worksheet import Worksheet
-from Row import Row
-from Column import Column
-from Formatting import Font, Alignment, Borders, Pattern, Protection
-from Style import XFStyle, easyxf
-from ExcelFormula import *
diff --git a/tablib/packages/xlwt/antlr.py b/tablib/packages/xlwt/antlr.py
deleted file mode 100644
index aaad447..0000000
--- a/tablib/packages/xlwt/antlr.py
+++ /dev/null
@@ -1,2874 +0,0 @@
-## This file is part of PyANTLR. See LICENSE.txt for license
-## details..........Copyright (C) Wolfgang Haefelinger, 2004.
-
-## This file was copied for use with xlwt from the 2.7.7 ANTLR distribution. Yes, it
-## says 2.7.5 below. The 2.7.5 distribution version didn't have a
-## version in it.
-
-## Here is the contents of the ANTLR 2.7.7 LICENSE.txt referred to above.
-
-# SOFTWARE RIGHTS
-#
-# ANTLR 1989-2006 Developed by Terence Parr
-# Partially supported by University of San Francisco & jGuru.com
-#
-# We reserve no legal rights to the ANTLR--it is fully in the
-# public domain. An individual or company may do whatever
-# they wish with source code distributed with ANTLR or the
-# code generated by ANTLR, including the incorporation of
-# ANTLR, or its output, into commerical software.
-#
-# We encourage users to develop software with ANTLR. However,
-# we do ask that credit is given to us for developing
-# ANTLR. By "credit", we mean that if you use ANTLR or
-# incorporate any source code into one of your programs
-# (commercial product, research project, or otherwise) that
-# you acknowledge this fact somewhere in the documentation,
-# research report, etc... If you like ANTLR and have
-# developed a nice tool with the output, please mention that
-# you developed it using ANTLR. In addition, we ask that the
-# headers remain intact in our source code. As long as these
-# guidelines are kept, we expect to continue enhancing this
-# system and expect to make other tools available as they are
-# completed.
-#
-# The primary ANTLR guy:
-#
-# Terence Parr
-# parrt@cs.usfca.edu
-# parrt@antlr.org
-
-## End of contents of the ANTLR 2.7.7 LICENSE.txt ########################
-
-## get sys module
-import sys
-
-version = sys.version.split()[0]
-if version < '2.2.1':
- False = 0
-if version < '2.3':
- True = not False
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### global symbols ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-### ANTLR Standard Tokens
-SKIP = -1
-INVALID_TYPE = 0
-EOF_TYPE = 1
-EOF = 1
-NULL_TREE_LOOKAHEAD = 3
-MIN_USER_TYPE = 4
-
-### ANTLR's EOF Symbol
-EOF_CHAR = ''
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### general functions ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-## Version should be automatically derived from configure.in. For now,
-## we need to bump it ourselfs. Don't remove the <version> tags.
-## <version>
-def version():
- r = {
- 'major' : '2',
- 'minor' : '7',
- 'micro' : '5',
- 'patch' : '' ,
- 'version': '2.7.5'
- }
- return r
-## </version>
-
-def error(fmt,*args):
- if fmt:
- print "error: ", fmt % tuple(args)
-
-def ifelse(cond,_then,_else):
- if cond :
- r = _then
- else:
- r = _else
- return r
-
-def is_string_type(x):
- # return (isinstance(x,str) or isinstance(x,unicode))
- # Simplify; xlwt doesn't support Python < 2.3
- return isinstance(basestring)
-
-def assert_string_type(x):
- assert is_string_type(x)
- pass
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### ANTLR Exceptions ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class ANTLRException(Exception):
-
- def __init__(self, *args):
- Exception.__init__(self, *args)
-
-
-class RecognitionException(ANTLRException):
-
- def __init__(self, *args):
- ANTLRException.__init__(self, *args)
- self.fileName = None
- self.line = -1
- self.column = -1
- if len(args) >= 2:
- self.fileName = args[1]
- if len(args) >= 3:
- self.line = args[2]
- if len(args) >= 4:
- self.column = args[3]
-
- def __str__(self):
- buf = ['']
- if self.fileName:
- buf.append(self.fileName + ":")
- if self.line != -1:
- if not self.fileName:
- buf.append("line ")
- buf.append(str(self.line))
- if self.column != -1:
- buf.append(":" + str(self.column))
- buf.append(":")
- buf.append(" ")
- return str('').join(buf)
-
- __repr__ = __str__
-
-
-class NoViableAltException(RecognitionException):
-
- def __init__(self, *args):
- RecognitionException.__init__(self, *args)
- self.token = None
- self.node = None
- if isinstance(args[0],AST):
- self.node = args[0]
- elif isinstance(args[0],Token):
- self.token = args[0]
- else:
- raise TypeError("NoViableAltException requires Token or AST argument")
-
- def __str__(self):
- if self.token:
- line = self.token.getLine()
- col = self.token.getColumn()
- text = self.token.getText()
- return "unexpected symbol at line %s (column %s): \"%s\"" % (line,col,text)
- if self.node == ASTNULL:
- return "unexpected end of subtree"
- assert self.node
- ### hackish, we assume that an AST contains method getText
- return "unexpected node: %s" % (self.node.getText())
-
- __repr__ = __str__
-
-
-class NoViableAltForCharException(RecognitionException):
-
- def __init__(self, *args):
- self.foundChar = None
- if len(args) == 2:
- self.foundChar = args[0]
- scanner = args[1]
- RecognitionException.__init__(self, "NoViableAlt",
- scanner.getFilename(),
- scanner.getLine(),
- scanner.getColumn())
- elif len(args) == 4:
- self.foundChar = args[0]
- fileName = args[1]
- line = args[2]
- column = args[3]
- RecognitionException.__init__(self, "NoViableAlt",
- fileName, line, column)
- else:
- RecognitionException.__init__(self, "NoViableAlt",
- '', -1, -1)
-
- def __str__(self):
- mesg = "unexpected char: "
- if self.foundChar >= ' ' and self.foundChar <= '~':
- mesg += "'" + self.foundChar + "'"
- elif self.foundChar:
- mesg += "0x" + hex(ord(self.foundChar)).upper()[2:]
- else:
- mesg += "<None>"
- return mesg
-
- __repr__ = __str__
-
-
-class SemanticException(RecognitionException):
-
- def __init__(self, *args):
- RecognitionException.__init__(self, *args)
-
-
-class MismatchedCharException(RecognitionException):
-
- NONE = 0
- CHAR = 1
- NOT_CHAR = 2
- RANGE = 3
- NOT_RANGE = 4
- SET = 5
- NOT_SET = 6
-
- def __init__(self, *args):
- self.args = args
- if len(args) == 5:
- # Expected range / not range
- if args[3]:
- self.mismatchType = MismatchedCharException.NOT_RANGE
- else:
- self.mismatchType = MismatchedCharException.RANGE
- self.foundChar = args[0]
- self.expecting = args[1]
- self.upper = args[2]
- self.scanner = args[4]
- RecognitionException.__init__(self, "Mismatched char range",
- self.scanner.getFilename(),
- self.scanner.getLine(),
- self.scanner.getColumn())
- elif len(args) == 4 and is_string_type(args[1]):
- # Expected char / not char
- if args[2]:
- self.mismatchType = MismatchedCharException.NOT_CHAR
- else:
- self.mismatchType = MismatchedCharException.CHAR
- self.foundChar = args[0]
- self.expecting = args[1]
- self.scanner = args[3]
- RecognitionException.__init__(self, "Mismatched char",
- self.scanner.getFilename(),
- self.scanner.getLine(),
- self.scanner.getColumn())
- elif len(args) == 4 and isinstance(args[1], BitSet):
- # Expected BitSet / not BitSet
- if args[2]:
- self.mismatchType = MismatchedCharException.NOT_SET
- else:
- self.mismatchType = MismatchedCharException.SET
- self.foundChar = args[0]
- self.set = args[1]
- self.scanner = args[3]
- RecognitionException.__init__(self, "Mismatched char set",
- self.scanner.getFilename(),
- self.scanner.getLine(),
- self.scanner.getColumn())
- else:
- self.mismatchType = MismatchedCharException.NONE
- RecognitionException.__init__(self, "Mismatched char")
-
- ## Append a char to the msg buffer. If special,
- # then show escaped version
- #
- def appendCharName(self, sb, c):
- if not c or c == 65535:
- # 65535 = (char) -1 = EOF
- sb.append("'<EOF>'")
- elif c == '\n':
- sb.append("'\\n'")
- elif c == '\r':
- sb.append("'\\r'");
- elif c == '\t':
- sb.append("'\\t'")
- else:
- sb.append('\'' + c + '\'')
-
- ##
- # Returns an error message with line number/column information
- #
- def __str__(self):
- sb = ['']
- sb.append(RecognitionException.__str__(self))
-
- if self.mismatchType == MismatchedCharException.CHAR:
- sb.append("expecting ")
- self.appendCharName(sb, self.expecting)
- sb.append(", found ")
- self.appendCharName(sb, self.foundChar)
- elif self.mismatchType == MismatchedCharException.NOT_CHAR:
- sb.append("expecting anything but '")
- self.appendCharName(sb, self.expecting)
- sb.append("'; got it anyway")
- elif self.mismatchType in [MismatchedCharException.RANGE, MismatchedCharException.NOT_RANGE]:
- sb.append("expecting char ")
- if self.mismatchType == MismatchedCharException.NOT_RANGE:
- sb.append("NOT ")
- sb.append("in range: ")
- appendCharName(sb, self.expecting)
- sb.append("..")
- appendCharName(sb, self.upper)
- sb.append(", found ")
- appendCharName(sb, self.foundChar)
- elif self.mismatchType in [MismatchedCharException.SET, MismatchedCharException.NOT_SET]:
- sb.append("expecting ")
- if self.mismatchType == MismatchedCharException.NOT_SET:
- sb.append("NOT ")
- sb.append("one of (")
- for i in range(len(self.set)):
- self.appendCharName(sb, self.set[i])
- sb.append("), found ")
- self.appendCharName(sb, self.foundChar)
-
- return str().join(sb).strip()
-
- __repr__ = __str__
-
-
-class MismatchedTokenException(RecognitionException):
-
- NONE = 0
- TOKEN = 1
- NOT_TOKEN = 2
- RANGE = 3
- NOT_RANGE = 4
- SET = 5
- NOT_SET = 6
-
- def __init__(self, *args):
- self.args = args
- self.tokenNames = []
- self.token = None
- self.tokenText = ''
- self.node = None
- if len(args) == 6:
- # Expected range / not range
- if args[3]:
- self.mismatchType = MismatchedTokenException.NOT_RANGE
- else:
- self.mismatchType = MismatchedTokenException.RANGE
- self.tokenNames = args[0]
- self.expecting = args[2]
- self.upper = args[3]
- self.fileName = args[5]
-
- elif len(args) == 4 and isinstance(args[2], int):
- # Expected token / not token
- if args[3]:
- self.mismatchType = MismatchedTokenException.NOT_TOKEN
- else:
- self.mismatchType = MismatchedTokenException.TOKEN
- self.tokenNames = args[0]
- self.expecting = args[2]
-
- elif len(args) == 4 and isinstance(args[2], BitSet):
- # Expected BitSet / not BitSet
- if args[3]:
- self.mismatchType = MismatchedTokenException.NOT_SET
- else:
- self.mismatchType = MismatchedTokenException.SET
- self.tokenNames = args[0]
- self.set = args[2]
-
- else:
- self.mismatchType = MismatchedTokenException.NONE
- RecognitionException.__init__(self, "Mismatched Token: expecting any AST node", "<AST>", -1, -1)
-
- if len(args) >= 2:
- if isinstance(args[1],Token):
- self.token = args[1]
- self.tokenText = self.token.getText()
- RecognitionException.__init__(self, "Mismatched Token",
- self.fileName,
- self.token.getLine(),
- self.token.getColumn())
- elif isinstance(args[1],AST):
- self.node = args[1]
- self.tokenText = str(self.node)
- RecognitionException.__init__(self, "Mismatched Token",
- "<AST>",
- self.node.getLine(),
- self.node.getColumn())
- else:
- self.tokenText = "<empty tree>"
- RecognitionException.__init__(self, "Mismatched Token",
- "<AST>", -1, -1)
-
- def appendTokenName(self, sb, tokenType):
- if tokenType == INVALID_TYPE:
- sb.append("<Set of tokens>")
- elif tokenType < 0 or tokenType >= len(self.tokenNames):
- sb.append("<" + str(tokenType) + ">")
- else:
- sb.append(self.tokenNames[tokenType])
-
- ##
- # Returns an error message with line number/column information
- #
- def __str__(self):
- sb = ['']
- sb.append(RecognitionException.__str__(self))
-
- if self.mismatchType == MismatchedTokenException.TOKEN:
- sb.append("expecting ")
- self.appendTokenName(sb, self.expecting)
- sb.append(", found " + self.tokenText)
- elif self.mismatchType == MismatchedTokenException.NOT_TOKEN:
- sb.append("expecting anything but '")
- self.appendTokenName(sb, self.expecting)
- sb.append("'; got it anyway")
- elif self.mismatchType in [MismatchedTokenException.RANGE, MismatchedTokenException.NOT_RANGE]:
- sb.append("expecting token ")
- if self.mismatchType == MismatchedTokenException.NOT_RANGE:
- sb.append("NOT ")
- sb.append("in range: ")
- appendTokenName(sb, self.expecting)
- sb.append("..")
- appendTokenName(sb, self.upper)
- sb.append(", found " + self.tokenText)
- elif self.mismatchType in [MismatchedTokenException.SET, MismatchedTokenException.NOT_SET]:
- sb.append("expecting ")
- if self.mismatchType == MismatchedTokenException.NOT_SET:
- sb.append("NOT ")
- sb.append("one of (")
- for i in range(len(self.set)):
- self.appendTokenName(sb, self.set[i])
- sb.append("), found " + self.tokenText)
-
- return str().join(sb).strip()
-
- __repr__ = __str__
-
-
-class TokenStreamException(ANTLRException):
-
- def __init__(self, *args):
- ANTLRException.__init__(self, *args)
-
-
-# Wraps an Exception in a TokenStreamException
-class TokenStreamIOException(TokenStreamException):
-
- def __init__(self, *args):
- if args and isinstance(args[0], Exception):
- io = args[0]
- TokenStreamException.__init__(self, str(io))
- self.io = io
- else:
- TokenStreamException.__init__(self, *args)
- self.io = self
-
-
-# Wraps a RecognitionException in a TokenStreamException
-class TokenStreamRecognitionException(TokenStreamException):
-
- def __init__(self, *args):
- if args and isinstance(args[0], RecognitionException):
- recog = args[0]
- TokenStreamException.__init__(self, str(recog))
- self.recog = recog
- else:
- raise TypeError("TokenStreamRecognitionException requires RecognitionException argument")
-
- def __str__(self):
- return str(self.recog)
-
- __repr__ = __str__
-
-
-class TokenStreamRetryException(TokenStreamException):
-
- def __init__(self, *args):
- TokenStreamException.__init__(self, *args)
-
-
-class CharStreamException(ANTLRException):
-
- def __init__(self, *args):
- ANTLRException.__init__(self, *args)
-
-
-# Wraps an Exception in a CharStreamException
-class CharStreamIOException(CharStreamException):
-
- def __init__(self, *args):
- if args and isinstance(args[0], Exception):
- io = args[0]
- CharStreamException.__init__(self, str(io))
- self.io = io
- else:
- CharStreamException.__init__(self, *args)
- self.io = self
-
-
-class TryAgain(Exception):
- pass
-
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### Token ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class Token(object):
- SKIP = -1
- INVALID_TYPE = 0
- EOF_TYPE = 1
- EOF = 1
- NULL_TREE_LOOKAHEAD = 3
- MIN_USER_TYPE = 4
-
- def __init__(self,**argv):
- try:
- self.type = argv['type']
- except:
- self.type = INVALID_TYPE
- try:
- self.text = argv['text']
- except:
- self.text = "<no text>"
-
- def isEOF(self):
- return (self.type == EOF_TYPE)
-
- def getColumn(self):
- return 0
-
- def getLine(self):
- return 0
-
- def getFilename(self):
- return None
-
- def setFilename(self,name):
- return self
-
- def getText(self):
- return "<no text>"
-
- def setText(self,text):
- if is_string_type(text):
- pass
- else:
- raise TypeError("Token.setText requires string argument")
- return self
-
- def setColumn(self,column):
- return self
-
- def setLine(self,line):
- return self
-
- def getType(self):
- return self.type
-
- def setType(self,type):
- if isinstance(type,int):
- self.type = type
- else:
- raise TypeError("Token.setType requires integer argument")
- return self
-
- def toString(self):
- ## not optimal
- type_ = self.type
- if type_ == 3:
- tval = 'NULL_TREE_LOOKAHEAD'
- elif type_ == 1:
- tval = 'EOF_TYPE'
- elif type_ == 0:
- tval = 'INVALID_TYPE'
- elif type_ == -1:
- tval = 'SKIP'
- else:
- tval = type_
- return '["%s",<%s>]' % (self.getText(),tval)
-
- __str__ = toString
- __repr__ = toString
-
-### static attribute ..
-Token.badToken = Token( type=INVALID_TYPE, text="<no text>")
-
-if __name__ == "__main__":
- print "testing .."
- T = Token.badToken
- print T
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### CommonToken ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class CommonToken(Token):
-
- def __init__(self,**argv):
- Token.__init__(self,**argv)
- self.line = 0
- self.col = 0
- try:
- self.line = argv['line']
- except:
- pass
- try:
- self.col = argv['col']
- except:
- pass
-
- def getLine(self):
- return self.line
-
- def getText(self):
- return self.text
-
- def getColumn(self):
- return self.col
-
- def setLine(self,line):
- self.line = line
- return self
-
- def setText(self,text):
- self.text = text
- return self
-
- def setColumn(self,col):
- self.col = col
- return self
-
- def toString(self):
- ## not optimal
- type_ = self.type
- if type_ == 3:
- tval = 'NULL_TREE_LOOKAHEAD'
- elif type_ == 1:
- tval = 'EOF_TYPE'
- elif type_ == 0:
- tval = 'INVALID_TYPE'
- elif type_ == -1:
- tval = 'SKIP'
- else:
- tval = type_
- d = {
- 'text' : self.text,
- 'type' : tval,
- 'line' : self.line,
- 'colm' : self.col
- }
-
- fmt = '["%(text)s",<%(type)s>,line=%(line)s,col=%(colm)s]'
- return fmt % d
-
- __str__ = toString
- __repr__ = toString
-
-
-if __name__ == '__main__' :
- T = CommonToken()
- print T
- T = CommonToken(col=15,line=1,text="some text", type=5)
- print T
- T = CommonToken()
- T.setLine(1).setColumn(15).setText("some text").setType(5)
- print T
- print T.getLine()
- print T.getColumn()
- print T.getText()
- print T.getType()
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### CommonHiddenStreamToken ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class CommonHiddenStreamToken(CommonToken):
- def __init__(self,*args):
- CommonToken.__init__(self,*args)
- self.hiddenBefore = None
- self.hiddenAfter = None
-
- def getHiddenAfter(self):
- return self.hiddenAfter
-
- def getHiddenBefore(self):
- return self.hiddenBefore
-
- def setHiddenAfter(self,t):
- self.hiddenAfter = t
-
- def setHiddenBefore(self, t):
- self.hiddenBefore = t
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### Queue ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-## Shall be a circular buffer on tokens ..
-class Queue(object):
-
- def __init__(self):
- self.buffer = [] # empty list
-
- def append(self,item):
- self.buffer.append(item)
-
- def elementAt(self,index):
- return self.buffer[index]
-
- def reset(self):
- self.buffer = []
-
- def removeFirst(self):
- self.buffer.pop(0)
-
- def length(self):
- return len(self.buffer)
-
- def __str__(self):
- return str(self.buffer)
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### InputBuffer ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class InputBuffer(object):
- def __init__(self):
- self.nMarkers = 0
- self.markerOffset = 0
- self.numToConsume = 0
- self.queue = Queue()
-
- def __str__(self):
- return "(%s,%s,%s,%s)" % (
- self.nMarkers,
- self.markerOffset,
- self.numToConsume,
- self.queue)
-
- def __repr__(self):
- return str(self)
-
- def commit(self):
- self.nMarkers -= 1
-
- def consume(self) :
- self.numToConsume += 1
-
- ## probably better to return a list of items
- ## because of unicode. Or return a unicode
- ## string ..
- def getLAChars(self) :
- i = self.markerOffset
- n = self.queue.length()
- s = ''
- while i<n:
- s += self.queue.elementAt(i)
- return s
-
- ## probably better to return a list of items
- ## because of unicode chars
- def getMarkedChars(self) :
- s = ''
- i = 0
- n = self.markerOffset
- while i<n:
- s += self.queue.elementAt(i)
- return s
-
- def isMarked(self) :
- return self.nMarkers != 0
-
- def fill(self,k):
- ### abstract method
- raise NotImplementedError()
-
- def LA(self,k) :
- self.fill(k)
- return self.queue.elementAt(self.markerOffset + k - 1)
-
- def mark(self) :
- self.syncConsume()
- self.nMarkers += 1
- return self.markerOffset
-
- def rewind(self,mark) :
- self.syncConsume()
- self.markerOffset = mark
- self.nMarkers -= 1
-
- def reset(self) :
- self.nMarkers = 0
- self.markerOffset = 0
- self.numToConsume = 0
- self.queue.reset()
-
- def syncConsume(self) :
- while self.numToConsume > 0:
- if self.nMarkers > 0:
- # guess mode -- leave leading characters and bump offset.
- self.markerOffset += 1
- else:
- # normal mode -- remove first character
- self.queue.removeFirst()
- self.numToConsume -= 1
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### CharBuffer ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class CharBuffer(InputBuffer):
- def __init__(self,reader):
- ##assert isinstance(reader,file)
- super(CharBuffer,self).__init__()
- ## a reader is supposed to be anything that has
- ## a method 'read(int)'.
- self.input = reader
-
- def __str__(self):
- base = super(CharBuffer,self).__str__()
- return "CharBuffer{%s,%s" % (base,str(input))
-
- def fill(self,amount):
- try:
- self.syncConsume()
- while self.queue.length() < (amount + self.markerOffset) :
- ## retrieve just one char - what happend at end
- ## of input?
- c = self.input.read(1)
- ### python's behaviour is to return the empty string on
- ### EOF, ie. no exception whatsoever is thrown. An empty
- ### python string has the nice feature that it is of
- ### type 'str' and "not ''" would return true. Contrary,
- ### one can't do this: '' in 'abc'. This should return
- ### false, but all we get is then a TypeError as an
- ### empty string is not a character.
-
- ### Let's assure then that we have either seen a
- ### character or an empty string (EOF).
- assert len(c) == 0 or len(c) == 1
-
- ### And it shall be of type string (ASCII or UNICODE).
- assert is_string_type(c)
-
- ### Just append EOF char to buffer. Note that buffer may
- ### contain then just more than one EOF char ..
-
- ### use unicode chars instead of ASCII ..
- self.queue.append(c)
- except Exception,e:
- raise CharStreamIOException(e)
- ##except: # (mk) Cannot happen ...
- ##error ("unexpected exception caught ..")
- ##assert 0
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### LexerSharedInputState ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class LexerSharedInputState(object):
- def __init__(self,ibuf):
- assert isinstance(ibuf,InputBuffer)
- self.input = ibuf
- self.column = 1
- self.line = 1
- self.tokenStartColumn = 1
- self.tokenStartLine = 1
- self.guessing = 0
- self.filename = None
-
- def reset(self):
- self.column = 1
- self.line = 1
- self.tokenStartColumn = 1
- self.tokenStartLine = 1
- self.guessing = 0
- self.filename = None
- self.input.reset()
-
- def LA(self,k):
- return self.input.LA(k)
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TokenStream ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TokenStream(object):
- def nextToken(self):
- pass
-
- def __iter__(self):
- return TokenStreamIterator(self)
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TokenStreamIterator ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TokenStreamIterator(object):
- def __init__(self,inst):
- if isinstance(inst,TokenStream):
- self.inst = inst
- return
- raise TypeError("TokenStreamIterator requires TokenStream object")
-
- def next(self):
- assert self.inst
- item = self.inst.nextToken()
- if not item or item.isEOF():
- raise StopIteration()
- return item
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TokenStreamSelector ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TokenStreamSelector(TokenStream):
-
- def __init__(self):
- self._input = None
- self._stmap = {}
- self._stack = []
-
- def addInputStream(self,stream,key):
- self._stmap[key] = stream
-
- def getCurrentStream(self):
- return self._input
-
- def getStream(self,sname):
- try:
- stream = self._stmap[sname]
- except:
- raise ValueError("TokenStream " + sname + " not found");
- return stream;
-
- def nextToken(self):
- while 1:
- try:
- return self._input.nextToken()
- except TokenStreamRetryException,r:
- ### just retry "forever"
- pass
-
- def pop(self):
- stream = self._stack.pop();
- self.select(stream);
- return stream;
-
- def push(self,arg):
- self._stack.append(self._input);
- self.select(arg)
-
- def retry(self):
- raise TokenStreamRetryException()
-
- def select(self,arg):
- if isinstance(arg,TokenStream):
- self._input = arg
- return
- if is_string_type(arg):
- self._input = self.getStream(arg)
- return
- raise TypeError("TokenStreamSelector.select requires " +
- "TokenStream or string argument")
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TokenStreamBasicFilter ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TokenStreamBasicFilter(TokenStream):
-
- def __init__(self,input):
-
- self.input = input;
- self.discardMask = BitSet()
-
- def discard(self,arg):
- if isinstance(arg,int):
- self.discardMask.add(arg)
- return
- if isinstance(arg,BitSet):
- self.discardMark = arg
- return
- raise TypeError("TokenStreamBasicFilter.discard requires" +
- "integer or BitSet argument")
-
- def nextToken(self):
- tok = self.input.nextToken()
- while tok and self.discardMask.member(tok.getType()):
- tok = self.input.nextToken()
- return tok
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TokenStreamHiddenTokenFilter ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TokenStreamHiddenTokenFilter(TokenStreamBasicFilter):
-
- def __init__(self,input):
- TokenStreamBasicFilter.__init__(self,input)
- self.hideMask = BitSet()
- self.nextMonitoredToken = None
- self.lastHiddenToken = None
- self.firstHidden = None
-
- def consume(self):
- self.nextMonitoredToken = self.input.nextToken()
-
- def consumeFirst(self):
- self.consume()
-
- p = None;
- while self.hideMask.member(self.LA(1).getType()) or \
- self.discardMask.member(self.LA(1).getType()):
- if self.hideMask.member(self.LA(1).getType()):
- if not p:
- p = self.LA(1)
- else:
- p.setHiddenAfter(self.LA(1))
- self.LA(1).setHiddenBefore(p)
- p = self.LA(1)
- self.lastHiddenToken = p
- if not self.firstHidden:
- self.firstHidden = p
- self.consume()
-
- def getDiscardMask(self):
- return self.discardMask
-
- def getHiddenAfter(self,t):
- return t.getHiddenAfter()
-
- def getHiddenBefore(self,t):
- return t.getHiddenBefore()
-
- def getHideMask(self):
- return self.hideMask
-
- def getInitialHiddenToken(self):
- return self.firstHidden
-
- def hide(self,m):
- if isinstance(m,int):
- self.hideMask.add(m)
- return
- if isinstance(m.BitMask):
- self.hideMask = m
- return
-
- def LA(self,i):
- return self.nextMonitoredToken
-
- def nextToken(self):
- if not self.LA(1):
- self.consumeFirst()
-
- monitored = self.LA(1)
-
- monitored.setHiddenBefore(self.lastHiddenToken)
- self.lastHiddenToken = None
-
- self.consume()
- p = monitored
-
- while self.hideMask.member(self.LA(1).getType()) or \
- self.discardMask.member(self.LA(1).getType()):
- if self.hideMask.member(self.LA(1).getType()):
- p.setHiddenAfter(self.LA(1))
- if p != monitored:
- self.LA(1).setHiddenBefore(p)
- p = self.lastHiddenToken = self.LA(1)
- self.consume()
- return monitored
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### StringBuffer ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class StringBuffer:
- def __init__(self,string=None):
- if string:
- self.text = list(string)
- else:
- self.text = []
-
- def setLength(self,sz):
- if not sz :
- self.text = []
- return
- assert sz>0
- if sz >= self.length():
- return
- ### just reset to empty buffer
- self.text = self.text[0:sz]
-
- def length(self):
- return len(self.text)
-
- def append(self,c):
- self.text.append(c)
-
- ### return buffer as string. Arg 'a' is used as index
- ## into the buffer and 2nd argument shall be the length.
- ## If 2nd args is absent, we return chars till end of
- ## buffer starting with 'a'.
- def getString(self,a=None,length=None):
- if not a :
- a = 0
- assert a>=0
- if a>= len(self.text) :
- return ""
-
- if not length:
- ## no second argument
- L = self.text[a:]
- else:
- assert (a+length) <= len(self.text)
- b = a + length
- L = self.text[a:b]
- s = ""
- for x in L : s += x
- return s
-
- toString = getString ## alias
-
- def __str__(self):
- return str(self.text)
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### Reader ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-## When reading Japanese chars, it happens that a stream returns a
-## 'char' of length 2. This looks like a bug in the appropriate
-## codecs - but I'm rather unsure about this. Anyway, if this is
-## the case, I'm going to split this string into a list of chars
-## and put them on hold, ie. on a buffer. Next time when called
-## we read from buffer until buffer is empty.
-## wh: nov, 25th -> problem does not appear in Python 2.4.0.c1.
-
-class Reader(object):
- def __init__(self,stream):
- self.cin = stream
- self.buf = []
-
- def read(self,num):
- assert num==1
-
- if len(self.buf):
- return self.buf.pop()
-
- ## Read a char - this may return a string.
- ## Is this a bug in codecs/Python?
- c = self.cin.read(1)
-
- if not c or len(c)==1:
- return c
-
- L = list(c)
- L.reverse()
- for x in L:
- self.buf.append(x)
-
- ## read one char ..
- return self.read(1)
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### CharScanner ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class CharScanner(TokenStream):
- ## class members
- NO_CHAR = 0
- EOF_CHAR = '' ### EOF shall be the empty string.
-
- def __init__(self, *argv, **kwargs):
- super(CharScanner, self).__init__()
- self.saveConsumedInput = True
- self.tokenClass = None
- self.caseSensitive = True
- self.caseSensitiveLiterals = True
- self.literals = None
- self.tabsize = 8
- self._returnToken = None
- self.commitToPath = False
- self.traceDepth = 0
- self.text = StringBuffer()
- self.hashString = hash(self)
- self.setTokenObjectClass(CommonToken)
- self.setInput(*argv)
-
- def __iter__(self):
- return CharScannerIterator(self)
-
- def setInput(self,*argv):
- ## case 1:
- ## if there's no arg we default to read from
- ## standard input
- if not argv:
- import sys
- self.setInput(sys.stdin)
- return
-
- ## get 1st argument
- arg1 = argv[0]
-
- ## case 2:
- ## if arg1 is a string, we assume it's a file name
- ## and open a stream using 2nd argument as open
- ## mode. If there's no 2nd argument we fall back to
- ## mode '+rb'.
- if is_string_type(arg1):
- f = open(arg1,"rb")
- self.setInput(f)
- self.setFilename(arg1)
- return
-
- ## case 3:
- ## if arg1 is a file we wrap it by a char buffer (
- ## some additional checks?? No, can't do this in
- ## general).
- if isinstance(arg1,file):
- self.setInput(CharBuffer(arg1))
- return
-
- ## case 4:
- ## if arg1 is of type SharedLexerInputState we use
- ## argument as is.
- if isinstance(arg1,LexerSharedInputState):
- self.inputState = arg1
- return
-
- ## case 5:
- ## check whether argument type is of type input
- ## buffer. If so create a SharedLexerInputState and
- ## go ahead.
- if isinstance(arg1,InputBuffer):
- self.setInput(LexerSharedInputState(arg1))
- return
-
- ## case 6:
- ## check whether argument type has a method read(int)
- ## If so create CharBuffer ...
- try:
- if arg1.read:
- rd = Reader(arg1)
- cb = CharBuffer(rd)
- ss = LexerSharedInputState(cb)
- self.inputState = ss
- return
- except:
- pass
-
- ## case 7:
- ## raise wrong argument exception
- raise TypeError(argv)
-
- def setTabSize(self,size) :
- self.tabsize = size
-
- def getTabSize(self) :
- return self.tabsize
-
- def setCaseSensitive(self,t) :
- self.caseSensitive = t
-
- def setCommitToPath(self,commit) :
- self.commitToPath = commit
-
- def setFilename(self,f) :
- self.inputState.filename = f
-
- def setLine(self,line) :
- self.inputState.line = line
-
- def setText(self,s) :
- self.resetText()
- self.text.append(s)
-
- def getCaseSensitive(self) :
- return self.caseSensitive
-
- def getCaseSensitiveLiterals(self) :
- return self.caseSensitiveLiterals
-
- def getColumn(self) :
- return self.inputState.column
-
- def setColumn(self,c) :
- self.inputState.column = c
-
- def getCommitToPath(self) :
- return self.commitToPath
-
- def getFilename(self) :
- return self.inputState.filename
-
- def getInputBuffer(self) :
- return self.inputState.input
-
- def getInputState(self) :
- return self.inputState
-
- def setInputState(self,state) :
- assert isinstance(state,LexerSharedInputState)
- self.inputState = state
-
- def getLine(self) :
- return self.inputState.line
-
- def getText(self) :
- return str(self.text)
-
- def getTokenObject(self) :
- return self._returnToken
-
- def LA(self,i) :
- c = self.inputState.input.LA(i)
- if not self.caseSensitive:
- ### E0006
- c = c.__class__.lower(c)
- return c
-
- def makeToken(self,type) :
- try:
- ## dynamically load a class
- assert self.tokenClass
- tok = self.tokenClass()
- tok.setType(type)
- tok.setColumn(self.inputState.tokenStartColumn)
- tok.setLine(self.inputState.tokenStartLine)
- return tok
- except:
- self.panic("unable to create new token")
- return Token.badToken
-
- def mark(self) :
- return self.inputState.input.mark()
-
- def _match_bitset(self,b) :
- if b.member(self.LA(1)):
- self.consume()
- else:
- raise MismatchedCharException(self.LA(1), b, False, self)
-
- def _match_string(self,s) :
- for c in s:
- if self.LA(1) == c:
- self.consume()
- else:
- raise MismatchedCharException(self.LA(1), c, False, self)
-
- def match(self,item):
- if is_string_type(item):
- return self._match_string(item)
- else:
- return self._match_bitset(item)
-
- def matchNot(self,c) :
- if self.LA(1) != c:
- self.consume()
- else:
- raise MismatchedCharException(self.LA(1), c, True, self)
-
- def matchRange(self,c1,c2) :
- if self.LA(1) < c1 or self.LA(1) > c2 :
- raise MismatchedCharException(self.LA(1), c1, c2, False, self)
- else:
- self.consume()
-
- def newline(self) :
- self.inputState.line += 1
- self.inputState.column = 1
-
- def tab(self) :
- c = self.getColumn()
- nc = ( ((c-1)/self.tabsize) + 1) * self.tabsize + 1
- self.setColumn(nc)
-
- def panic(self,s='') :
- print "CharScanner: panic: " + s
- sys.exit(1)
-
- def reportError(self,ex) :
- print ex
-
- def reportError(self,s) :
- if not self.getFilename():
- print "error: " + str(s)
- else:
- print self.getFilename() + ": error: " + str(s)
-
- def reportWarning(self,s) :
- if not self.getFilename():
- print "warning: " + str(s)
- else:
- print self.getFilename() + ": warning: " + str(s)
-
- def resetText(self) :
- self.text.setLength(0)
- self.inputState.tokenStartColumn = self.inputState.column
- self.inputState.tokenStartLine = self.inputState.line
-
- def rewind(self,pos) :
- self.inputState.input.rewind(pos)
-
- def setTokenObjectClass(self,cl):
- self.tokenClass = cl
-
- def testForLiteral(self,token):
- if not token:
- return
- assert isinstance(token,Token)
-
- _type = token.getType()
-
- ## special tokens can't be literals
- if _type in [SKIP,INVALID_TYPE,EOF_TYPE,NULL_TREE_LOOKAHEAD] :
- return
-
- _text = token.getText()
- if not _text:
- return
-
- assert is_string_type(_text)
- _type = self.testLiteralsTable(_text,_type)
- token.setType(_type)
- return _type
-
- def testLiteralsTable(self,*args):
- if is_string_type(args[0]):
- s = args[0]
- i = args[1]
- else:
- s = self.text.getString()
- i = args[0]
-
- ## check whether integer has been given
- if not isinstance(i,int):
- assert isinstance(i,int)
-
- ## check whether we have a dict
- assert isinstance(self.literals,dict)
- try:
- ## E0010
- if not self.caseSensitiveLiterals:
- s = s.__class__.lower(s)
- i = self.literals[s]
- except:
- pass
- return i
-
- def toLower(self,c):
- return c.__class__.lower()
-
- def traceIndent(self):
- print ' ' * self.traceDepth
-
- def traceIn(self,rname):
- self.traceDepth += 1
- self.traceIndent()
- print "> lexer %s c== %s" % (rname,self.LA(1))
-
- def traceOut(self,rname):
- self.traceIndent()
- print "< lexer %s c== %s" % (rname,self.LA(1))
- self.traceDepth -= 1
-
- def uponEOF(self):
- pass
-
- def append(self,c):
- if self.saveConsumedInput :
- self.text.append(c)
-
- def commit(self):
- self.inputState.input.commit()
-
- def consume(self):
- if not self.inputState.guessing:
- c = self.LA(1)
- if self.caseSensitive:
- self.append(c)
- else:
- # use input.LA(), not LA(), to get original case
- # CharScanner.LA() would toLower it.
- c = self.inputState.input.LA(1)
- self.append(c)
-
- if c and c in "\t":
- self.tab()
- else:
- self.inputState.column += 1
- self.inputState.input.consume()
-
- ## Consume chars until one matches the given char
- def consumeUntil_char(self,c):
- while self.LA(1) != EOF_CHAR and self.LA(1) != c:
- self.consume()
-
- ## Consume chars until one matches the given set
- def consumeUntil_bitset(self,bitset):
- while self.LA(1) != EOF_CHAR and not self.set.member(self.LA(1)):
- self.consume()
-
- ### If symbol seen is EOF then generate and set token, otherwise
- ### throw exception.
- def default(self,la1):
- if not la1 :
- self.uponEOF()
- self._returnToken = self.makeToken(EOF_TYPE)
- else:
- self.raise_NoViableAlt(la1)
-
- def filterdefault(self,la1,*args):
- if not la1:
- self.uponEOF()
- self._returnToken = self.makeToken(EOF_TYPE)
- return
-
- if not args:
- self.consume()
- raise TryAgain()
- else:
- ### apply filter object
- self.commit();
- try:
- func=args[0]
- args=args[1:]
- apply(func,args)
- except RecognitionException, e:
- ## catastrophic failure
- self.reportError(e);
- self.consume();
- raise TryAgain()
-
- def raise_NoViableAlt(self,la1=None):
- if not la1: la1 = self.LA(1)
- fname = self.getFilename()
- line = self.getLine()
- col = self.getColumn()
- raise NoViableAltForCharException(la1,fname,line,col)
-
- def set_return_token(self,_create,_token,_ttype,_offset):
- if _create and not _token and (not _ttype == SKIP):
- string = self.text.getString(_offset)
- _token = self.makeToken(_ttype)
- _token.setText(string)
- self._returnToken = _token
- return _token
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### CharScannerIterator ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class CharScannerIterator:
-
- def __init__(self,inst):
- if isinstance(inst,CharScanner):
- self.inst = inst
- return
- raise TypeError("CharScannerIterator requires CharScanner object")
-
- def next(self):
- assert self.inst
- item = self.inst.nextToken()
- if not item or item.isEOF():
- raise StopIteration()
- return item
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### BitSet ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-### I'm assuming here that a long is 64bits. It appears however, that
-### a long is of any size. That means we can use a single long as the
-### bitset (!), ie. Python would do almost all the work (TBD).
-
-class BitSet(object):
- BITS = 64
- NIBBLE = 4
- LOG_BITS = 6
- MOD_MASK = BITS -1
-
- def __init__(self,data=None):
- if not data:
- BitSet.__init__(self,[long(0)])
- return
- if isinstance(data,int):
- BitSet.__init__(self,[long(data)])
- return
- if isinstance(data,long):
- BitSet.__init__(self,[data])
- return
- if not isinstance(data,list):
- raise TypeError("BitSet requires integer, long, or " +
- "list argument")
- for x in data:
- if not isinstance(x,long):
- raise TypeError(self,"List argument item is " +
- "not a long: %s" % (x))
- self.data = data
-
- def __str__(self):
- bits = len(self.data) * BitSet.BITS
- s = ""
- for i in xrange(0,bits):
- if self.at(i):
- s += "1"
- else:
- s += "o"
- if not ((i+1) % 10):
- s += '|%s|' % (i+1)
- return s
-
- def __repr__(self):
- return str(self)
-
- def member(self,item):
- if not item:
- return False
-
- if isinstance(item,int):
- return self.at(item)
-
- if not is_string_type(item):
- raise TypeError(self,"char or unichar expected: %s" % (item))
-
- ## char is a (unicode) string with at most lenght 1, ie.
- ## a char.
-
- if len(item) != 1:
- raise TypeError(self,"char expected: %s" % (item))
-
- ### handle ASCII/UNICODE char
- num = ord(item)
-
- ### check whether position num is in bitset
- return self.at(num)
-
- def wordNumber(self,bit):
- return bit >> BitSet.LOG_BITS
-
- def bitMask(self,bit):
- pos = bit & BitSet.MOD_MASK ## bit mod BITS
- return (1L << pos)
-
- def set(self,bit,on=True):
- # grow bitset as required (use with care!)
- i = self.wordNumber(bit)
- mask = self.bitMask(bit)
- if i>=len(self.data):
- d = i - len(self.data) + 1
- for x in xrange(0,d):
- self.data.append(0L)
- assert len(self.data) == i+1
- if on:
- self.data[i] |= mask
- else:
- self.data[i] &= (~mask)
-
- ### make add an alias for set
- add = set
-
- def off(self,bit,off=True):
- self.set(bit,not off)
-
- def at(self,bit):
- i = self.wordNumber(bit)
- v = self.data[i]
- m = self.bitMask(bit)
- return v & m
-
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### some further funcs ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-def illegalarg_ex(func):
- raise ValueError(
- "%s is only valid if parser is built for debugging" %
- (func.func_name))
-
-def runtime_ex(func):
- raise RuntimeException(
- "%s is only valid if parser is built for debugging" %
- (func.func_name))
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TokenBuffer ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TokenBuffer(object):
- def __init__(self,stream):
- self.input = stream
- self.nMarkers = 0
- self.markerOffset = 0
- self.numToConsume = 0
- self.queue = Queue()
-
- def reset(self) :
- self.nMarkers = 0
- self.markerOffset = 0
- self.numToConsume = 0
- self.queue.reset()
-
- def consume(self) :
- self.numToConsume += 1
-
- def fill(self, amount):
- self.syncConsume()
- while self.queue.length() < (amount + self.markerOffset):
- self.queue.append(self.input.nextToken())
-
- def getInput(self):
- return self.input
-
- def LA(self,k) :
- self.fill(k)
- return self.queue.elementAt(self.markerOffset + k - 1).type
-
- def LT(self,k) :
- self.fill(k)
- return self.queue.elementAt(self.markerOffset + k - 1)
-
- def mark(self) :
- self.syncConsume()
- self.nMarkers += 1
- return self.markerOffset
-
- def rewind(self,mark) :
- self.syncConsume()
- self.markerOffset = mark
- self.nMarkers -= 1
-
- def syncConsume(self) :
- while self.numToConsume > 0:
- if self.nMarkers > 0:
- # guess mode -- leave leading characters and bump offset.
- self.markerOffset += 1
- else:
- # normal mode -- remove first character
- self.queue.removeFirst()
- self.numToConsume -= 1
-
- def __str__(self):
- return "(%s,%s,%s,%s,%s)" % (
- self.input,
- self.nMarkers,
- self.markerOffset,
- self.numToConsume,
- self.queue)
-
- def __repr__(self):
- return str(self)
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### ParserSharedInputState ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class ParserSharedInputState(object):
-
- def __init__(self):
- self.input = None
- self.reset()
-
- def reset(self):
- self.guessing = 0
- self.filename = None
- if self.input:
- self.input.reset()
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### Parser ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class Parser(object):
-
- def __init__(self, *args, **kwargs):
- self.tokenNames = None
- self.returnAST = None
- self.astFactory = None
- self.tokenTypeToASTClassMap = {}
- self.ignoreInvalidDebugCalls = False
- self.traceDepth = 0
- if not args:
- self.inputState = ParserSharedInputState()
- return
- arg0 = args[0]
- assert isinstance(arg0,ParserSharedInputState)
- self.inputState = arg0
- return
-
- def getTokenTypeToASTClassMap(self):
- return self.tokenTypeToASTClassMap
-
-
- def addMessageListener(self, l):
- if not self.ignoreInvalidDebugCalls:
- illegalarg_ex(addMessageListener)
-
- def addParserListener(self,l) :
- if (not self.ignoreInvalidDebugCalls) :
- illegalarg_ex(addParserListener)
-
- def addParserMatchListener(self, l) :
- if (not self.ignoreInvalidDebugCalls) :
- illegalarg_ex(addParserMatchListener)
-
- def addParserTokenListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- illegalarg_ex(addParserTokenListener)
-
- def addSemanticPredicateListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- illegalarg_ex(addSemanticPredicateListener)
-
- def addSyntacticPredicateListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- illegalarg_ex(addSyntacticPredicateListener)
-
- def addTraceListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- illegalarg_ex(addTraceListener)
-
- def consume(self):
- raise NotImplementedError()
-
- def _consumeUntil_type(self,tokenType):
- while self.LA(1) != EOF_TYPE and self.LA(1) != tokenType:
- self.consume()
-
- def _consumeUntil_bitset(self, set):
- while self.LA(1) != EOF_TYPE and not set.member(self.LA(1)):
- self.consume()
-
- def consumeUntil(self,arg):
- if isinstance(arg,int):
- self._consumeUntil_type(arg)
- else:
- self._consumeUntil_bitset(arg)
-
- def defaultDebuggingSetup(self):
- pass
-
- def getAST(self) :
- return self.returnAST
-
- def getASTFactory(self) :
- return self.astFactory
-
- def getFilename(self) :
- return self.inputState.filename
-
- def getInputState(self) :
- return self.inputState
-
- def setInputState(self, state) :
- self.inputState = state
-
- def getTokenName(self,num) :
- return self.tokenNames[num]
-
- def getTokenNames(self) :
- return self.tokenNames
-
- def isDebugMode(self) :
- return self.false
-
- def LA(self, i):
- raise NotImplementedError()
-
- def LT(self, i):
- raise NotImplementedError()
-
- def mark(self):
- return self.inputState.input.mark()
-
- def _match_int(self,t):
- if (self.LA(1) != t):
- raise MismatchedTokenException(
- self.tokenNames, self.LT(1), t, False, self.getFilename())
- else:
- self.consume()
-
- def _match_set(self, b):
- if (not b.member(self.LA(1))):
- raise MismatchedTokenException(
- self.tokenNames,self.LT(1), b, False, self.getFilename())
- else:
- self.consume()
-
- def match(self,set) :
- if isinstance(set,int):
- self._match_int(set)
- return
- if isinstance(set,BitSet):
- self._match_set(set)
- return
- raise TypeError("Parser.match requires integer ot BitSet argument")
-
- def matchNot(self,t):
- if self.LA(1) == t:
- raise MismatchedTokenException(
- tokenNames, self.LT(1), t, True, self.getFilename())
- else:
- self.consume()
-
- def removeMessageListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(removeMessageListener)
-
- def removeParserListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(removeParserListener)
-
- def removeParserMatchListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(removeParserMatchListener)
-
- def removeParserTokenListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(removeParserTokenListener)
-
- def removeSemanticPredicateListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(removeSemanticPredicateListener)
-
- def removeSyntacticPredicateListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(removeSyntacticPredicateListener)
-
- def removeTraceListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(removeTraceListener)
-
- def reportError(self,x) :
- fmt = "syntax error:"
- f = self.getFilename()
- if f:
- fmt = ("%s:" % f) + fmt
- if isinstance(x,Token):
- line = x.getColumn()
- col = x.getLine()
- text = x.getText()
- fmt = fmt + 'unexpected symbol at line %s (column %s) : "%s"'
- print >>sys.stderr, fmt % (line,col,text)
- else:
- print >>sys.stderr, fmt,str(x)
-
- def reportWarning(self,s):
- f = self.getFilename()
- if f:
- print "%s:warning: %s" % (f,str(x))
- else:
- print "warning: %s" % (str(x))
-
- def rewind(self, pos) :
- self.inputState.input.rewind(pos)
-
- def setASTFactory(self, f) :
- self.astFactory = f
-
- def setASTNodeClass(self, cl) :
- self.astFactory.setASTNodeType(cl)
-
- def setASTNodeType(self, nodeType) :
- self.setASTNodeClass(nodeType)
-
- def setDebugMode(self, debugMode) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(setDebugMode)
-
- def setFilename(self, f) :
- self.inputState.filename = f
-
- def setIgnoreInvalidDebugCalls(self, value) :
- self.ignoreInvalidDebugCalls = value
-
- def setTokenBuffer(self, t) :
- self.inputState.input = t
-
- def traceIndent(self):
- print " " * self.traceDepth
-
- def traceIn(self,rname):
- self.traceDepth += 1
- self.trace("> ", rname)
-
- def traceOut(self,rname):
- self.trace("< ", rname)
- self.traceDepth -= 1
-
- ### wh: moved from ASTFactory to Parser
- def addASTChild(self,currentAST, child):
- if not child:
- return
- if not currentAST.root:
- currentAST.root = child
- elif not currentAST.child:
- currentAST.root.setFirstChild(child)
- else:
- currentAST.child.setNextSibling(child)
- currentAST.child = child
- currentAST.advanceChildToEnd()
-
- ### wh: moved from ASTFactory to Parser
- def makeASTRoot(self,currentAST,root) :
- if root:
- ### Add the current root as a child of new root
- root.addChild(currentAST.root)
- ### The new current child is the last sibling of the old root
- currentAST.child = currentAST.root
- currentAST.advanceChildToEnd()
- ### Set the new root
- currentAST.root = root
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### LLkParser ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class LLkParser(Parser):
-
- def __init__(self, *args, **kwargs):
- try:
- arg1 = args[0]
- except:
- arg1 = 1
-
- if isinstance(arg1,int):
- super(LLkParser,self).__init__()
- self.k = arg1
- return
-
- if isinstance(arg1,ParserSharedInputState):
- super(LLkParser,self).__init__(arg1)
- self.set_k(1,*args)
- return
-
- if isinstance(arg1,TokenBuffer):
- super(LLkParser,self).__init__()
- self.setTokenBuffer(arg1)
- self.set_k(1,*args)
- return
-
- if isinstance(arg1,TokenStream):
- super(LLkParser,self).__init__()
- tokenBuf = TokenBuffer(arg1)
- self.setTokenBuffer(tokenBuf)
- self.set_k(1,*args)
- return
-
- ### unknown argument
- raise TypeError("LLkParser requires integer, " +
- "ParserSharedInputStream or TokenStream argument")
-
- def consume(self):
- self.inputState.input.consume()
-
- def LA(self,i):
- return self.inputState.input.LA(i)
-
- def LT(self,i):
- return self.inputState.input.LT(i)
-
- def set_k(self,index,*args):
- try:
- self.k = args[index]
- except:
- self.k = 1
-
- def trace(self,ee,rname):
- print type(self)
- self.traceIndent()
- guess = ""
- if self.inputState.guessing > 0:
- guess = " [guessing]"
- print(ee + rname + guess)
- for i in xrange(1,self.k+1):
- if i != 1:
- print(", ")
- if self.LT(i) :
- v = self.LT(i).getText()
- else:
- v = "null"
- print "LA(%s) == %s" % (i,v)
- print("\n")
-
- def traceIn(self,rname):
- self.traceDepth += 1;
- self.trace("> ", rname);
-
- def traceOut(self,rname):
- self.trace("< ", rname);
- self.traceDepth -= 1;
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TreeParserSharedInputState ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TreeParserSharedInputState(object):
- def __init__(self):
- self.guessing = 0
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TreeParser ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TreeParser(object):
-
- def __init__(self, *args, **kwargs):
- self.inputState = TreeParserSharedInputState()
- self._retTree = None
- self.tokenNames = []
- self.returnAST = None
- self.astFactory = ASTFactory()
- self.traceDepth = 0
-
- def getAST(self):
- return self.returnAST
-
- def getASTFactory(self):
- return self.astFactory
-
- def getTokenName(self,num) :
- return self.tokenNames[num]
-
- def getTokenNames(self):
- return self.tokenNames
-
- def match(self,t,set) :
- assert isinstance(set,int) or isinstance(set,BitSet)
- if not t or t == ASTNULL:
- raise MismatchedTokenException(self.getTokenNames(), t,set, False)
-
- if isinstance(set,int) and t.getType() != set:
- raise MismatchedTokenException(self.getTokenNames(), t,set, False)
-
- if isinstance(set,BitSet) and not set.member(t.getType):
- raise MismatchedTokenException(self.getTokenNames(), t,set, False)
-
- def matchNot(self,t, ttype) :
- if not t or (t == ASTNULL) or (t.getType() == ttype):
- raise MismatchedTokenException(getTokenNames(), t, ttype, True)
-
- def reportError(self,ex):
- print >>sys.stderr,"error:",ex
-
- def reportWarning(self, s):
- print "warning:",s
-
- def setASTFactory(self,f):
- self.astFactory = f
-
- def setASTNodeType(self,nodeType):
- self.setASTNodeClass(nodeType)
-
- def setASTNodeClass(self,nodeType):
- self.astFactory.setASTNodeType(nodeType)
-
- def traceIndent(self):
- print " " * self.traceDepth
-
- def traceIn(self,rname,t):
- self.traceDepth += 1
- self.traceIndent()
- print("> " + rname + "(" +
- ifelse(t,str(t),"null") + ")" +
- ifelse(self.inputState.guessing>0,"[guessing]",""))
-
- def traceOut(self,rname,t):
- self.traceIndent()
- print("< " + rname + "(" +
- ifelse(t,str(t),"null") + ")" +
- ifelse(self.inputState.guessing>0,"[guessing]",""))
- self.traceDepth -= 1
-
- ### wh: moved from ASTFactory to TreeParser
- def addASTChild(self,currentAST, child):
- if not child:
- return
- if not currentAST.root:
- currentAST.root = child
- elif not currentAST.child:
- currentAST.root.setFirstChild(child)
- else:
- currentAST.child.setNextSibling(child)
- currentAST.child = child
- currentAST.advanceChildToEnd()
-
- ### wh: moved from ASTFactory to TreeParser
- def makeASTRoot(self,currentAST,root):
- if root:
- ### Add the current root as a child of new root
- root.addChild(currentAST.root)
- ### The new current child is the last sibling of the old root
- currentAST.child = currentAST.root
- currentAST.advanceChildToEnd()
- ### Set the new root
- currentAST.root = root
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### funcs to work on trees ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-def rightmost(ast):
- if ast:
- while(ast.right):
- ast = ast.right
- return ast
-
-def cmptree(s,t,partial):
- while(s and t):
- ### as a quick optimization, check roots first.
- if not s.equals(t):
- return False
-
- ### if roots match, do full list match test on children.
- if not cmptree(s.getFirstChild(),t.getFirstChild(),partial):
- return False
-
- s = s.getNextSibling()
- t = t.getNextSibling()
-
- r = ifelse(partial,not t,not s and not t)
- return r
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### AST ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class AST(object):
- def __init__(self):
- pass
-
- def addChild(self, c):
- pass
-
- def equals(self, t):
- return False
-
- def equalsList(self, t):
- return False
-
- def equalsListPartial(self, t):
- return False
-
- def equalsTree(self, t):
- return False
-
- def equalsTreePartial(self, t):
- return False
-
- def findAll(self, tree):
- return None
-
- def findAllPartial(self, subtree):
- return None
-
- def getFirstChild(self):
- return self
-
- def getNextSibling(self):
- return self
-
- def getText(self):
- return ""
-
- def getType(self):
- return INVALID_TYPE
-
- def getLine(self):
- return 0
-
- def getColumn(self):
- return 0
-
- def getNumberOfChildren(self):
- return 0
-
- def initialize(self, t, txt):
- pass
-
- def initialize(self, t):
- pass
-
- def setFirstChild(self, c):
- pass
-
- def setNextSibling(self, n):
- pass
-
- def setText(self, text):
- pass
-
- def setType(self, ttype):
- pass
-
- def toString(self):
- self.getText()
-
- __str__ = toString
-
- def toStringList(self):
- return self.getText()
-
- def toStringTree(self):
- return self.getText()
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### ASTNULLType ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-### There is only one instance of this class **/
-class ASTNULLType(AST):
- def __init__(self):
- AST.__init__(self)
- pass
-
- def getText(self):
- return "<ASTNULL>"
-
- def getType(self):
- return NULL_TREE_LOOKAHEAD
-
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### BaseAST ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class BaseAST(AST):
-
- verboseStringConversion = False
- tokenNames = None
-
- def __init__(self):
- self.down = None ## kid
- self.right = None ## sibling
-
- def addChild(self,node):
- if node:
- t = rightmost(self.down)
- if t:
- t.right = node
- else:
- assert not self.down
- self.down = node
-
- def getNumberOfChildren(self):
- t = self.down
- n = 0
- while t:
- n += 1
- t = t.right
- return n
-
- def doWorkForFindAll(self,v,target,partialMatch):
- sibling = self
-
- while sibling:
- c1 = partialMatch and sibling.equalsTreePartial(target)
- if c1:
- v.append(sibling)
- else:
- c2 = not partialMatch and sibling.equalsTree(target)
- if c2:
- v.append(sibling)
-
- ### regardless of match or not, check any children for matches
- if sibling.getFirstChild():
- sibling.getFirstChild().doWorkForFindAll(v,target,partialMatch)
-
- sibling = sibling.getNextSibling()
-
- ### Is node t equal to 'self' in terms of token type and text?
- def equals(self,t):
- if not t:
- return False
- return self.getText() == t.getText() and self.getType() == t.getType()
-
- ### Is t an exact structural and equals() match of this tree. The
- ### 'self' reference is considered the start of a sibling list.
- ###
- def equalsList(self, t):
- return cmptree(self, t, partial=False)
-
- ### Is 't' a subtree of this list?
- ### The siblings of the root are NOT ignored.
- ###
- def equalsListPartial(self,t):
- return cmptree(self,t,partial=True)
-
- ### Is tree rooted at 'self' equal to 't'? The siblings
- ### of 'self' are ignored.
- ###
- def equalsTree(self, t):
- return self.equals(t) and \
- cmptree(self.getFirstChild(), t.getFirstChild(), partial=False)
-
- ### Is 't' a subtree of the tree rooted at 'self'? The siblings
- ### of 'self' are ignored.
- ###
- def equalsTreePartial(self, t):
- if not t:
- return True
- return self.equals(t) and cmptree(
- self.getFirstChild(), t.getFirstChild(), partial=True)
-
- ### Walk the tree looking for all exact subtree matches. Return
- ### an ASTEnumerator that lets the caller walk the list
- ### of subtree roots found herein.
- def findAll(self,target):
- roots = []
-
- ### the empty tree cannot result in an enumeration
- if not target:
- return None
- # find all matches recursively
- self.doWorkForFindAll(roots, target, False)
- return roots
-
- ### Walk the tree looking for all subtrees. Return
- ### an ASTEnumerator that lets the caller walk the list
- ### of subtree roots found herein.
- def findAllPartial(self,sub):
- roots = []
-
- ### the empty tree cannot result in an enumeration
- if not sub:
- return None
-
- self.doWorkForFindAll(roots, sub, True) ### find all matches recursively
- return roots
-
- ### Get the first child of this node None if not children
- def getFirstChild(self):
- return self.down
-
- ### Get the next sibling in line after this one
- def getNextSibling(self):
- return self.right
-
- ### Get the token text for this node
- def getText(self):
- return ""
-
- ### Get the token type for this node
- def getType(self):
- return 0
-
- def getLine(self):
- return 0
-
- def getColumn(self):
- return 0
-
- ### Remove all children */
- def removeChildren(self):
- self.down = None
-
- def setFirstChild(self,c):
- self.down = c
-
- def setNextSibling(self, n):
- self.right = n
-
- ### Set the token text for this node
- def setText(self, text):
- pass
-
- ### Set the token type for this node
- def setType(self, ttype):
- pass
-
- ### static
- def setVerboseStringConversion(verbose,names):
- verboseStringConversion = verbose
- tokenNames = names
- setVerboseStringConversion = staticmethod(setVerboseStringConversion)
-
- ### Return an array of strings that maps token ID to it's text.
- ## @since 2.7.3
- def getTokenNames():
- return tokenNames
-
- def toString(self):
- return self.getText()
-
- ### return tree as lisp string - sibling included
- def toStringList(self):
- ts = self.toStringTree()
- sib = self.getNextSibling()
- if sib:
- ts += sib.toStringList()
- return ts
-
- __str__ = toStringList
-
- ### return tree as string - siblings ignored
- def toStringTree(self):
- ts = ""
- kid = self.getFirstChild()
- if kid:
- ts += " ("
- ts += " " + self.toString()
- if kid:
- ts += kid.toStringList()
- ts += " )"
- return ts
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### CommonAST ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-### Common AST node implementation
-class CommonAST(BaseAST):
- def __init__(self,token=None):
- super(CommonAST,self).__init__()
- self.ttype = INVALID_TYPE
- self.text = "<no text>"
- self.line = 0
- self.column= 0
- self.initialize(token)
- #assert self.text
-
- ### Get the token text for this node
- def getText(self):
- return self.text
-
- ### Get the token type for this node
- def getType(self):
- return self.ttype
-
- ### Get the line for this node
- def getLine(self):
- return self.line
-
- ### Get the column for this node
- def getColumn(self):
- return self.column
-
- def initialize(self,*args):
- if not args:
- return
-
- arg0 = args[0]
-
- if isinstance(arg0,int):
- arg1 = args[1]
- self.setType(arg0)
- self.setText(arg1)
- return
-
- if isinstance(arg0,AST) or isinstance(arg0,Token):
- self.setText(arg0.getText())
- self.setType(arg0.getType())
- self.line = arg0.getLine()
- self.column = arg0.getColumn()
- return
-
- ### Set the token text for this node
- def setText(self,text_):
- assert is_string_type(text_)
- self.text = text_
-
- ### Set the token type for this node
- def setType(self,ttype_):
- assert isinstance(ttype_,int)
- self.ttype = ttype_
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### CommonASTWithHiddenTokens ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class CommonASTWithHiddenTokens(CommonAST):
-
- def __init__(self,*args):
- CommonAST.__init__(self,*args)
- self.hiddenBefore = None
- self.hiddenAfter = None
-
- def getHiddenAfter(self):
- return self.hiddenAfter
-
- def getHiddenBefore(self):
- return self.hiddenBefore
-
- def initialize(self,*args):
- CommonAST.initialize(self,*args)
- if args and isinstance(args[0],Token):
- assert isinstance(args[0],CommonHiddenStreamToken)
- self.hiddenBefore = args[0].getHiddenBefore()
- self.hiddenAfter = args[0].getHiddenAfter()
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### ASTPair ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class ASTPair(object):
- def __init__(self):
- self.root = None ### current root of tree
- self.child = None ### current child to which siblings are added
-
- ### Make sure that child is the last sibling */
- def advanceChildToEnd(self):
- if self.child:
- while self.child.getNextSibling():
- self.child = self.child.getNextSibling()
-
- ### Copy an ASTPair. Don't call it clone() because we want type-safety */
- def copy(self):
- tmp = ASTPair()
- tmp.root = self.root
- tmp.child = self.child
- return tmp
-
- def toString(self):
- r = ifelse(not root,"null",self.root.getText())
- c = ifelse(not child,"null",self.child.getText())
- return "[%s,%s]" % (r,c)
-
- __str__ = toString
- __repr__ = toString
-
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### ASTFactory ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class ASTFactory(object):
- def __init__(self,table=None):
- self._class = None
- self._classmap = ifelse(table,table,None)
-
- def create(self,*args):
- if not args:
- return self.create(INVALID_TYPE)
-
- arg0 = args[0]
- arg1 = None
- arg2 = None
-
- try:
- arg1 = args[1]
- arg2 = args[2]
- except:
- pass
-
- # ctor(int)
- if isinstance(arg0,int) and not arg2:
- ### get class for 'self' type
- c = self.getASTNodeType(arg0)
- t = self.create(c)
- if t:
- t.initialize(arg0, ifelse(arg1,arg1,""))
- return t
-
- # ctor(int,something)
- if isinstance(arg0,int) and arg2:
- t = self.create(arg2)
- if t:
- t.initialize(arg0,arg1)
- return t
-
- # ctor(AST)
- if isinstance(arg0,AST):
- t = self.create(arg0.getType())
- if t:
- t.initialize(arg0)
- return t
-
- # ctor(token)
- if isinstance(arg0,Token) and not arg1:
- ttype = arg0.getType()
- assert isinstance(ttype,int)
- t = self.create(ttype)
- if t:
- t.initialize(arg0)
- return t
-
- # ctor(token,class)
- if isinstance(arg0,Token) and arg1:
- assert isinstance(arg1,type)
- assert issubclass(arg1,AST)
- # this creates instance of 'arg1' using 'arg0' as
- # argument. Wow, that's magic!
- t = arg1(arg0)
- assert t and isinstance(t,AST)
- return t
-
- # ctor(class)
- if isinstance(arg0,type):
- ### next statement creates instance of type (!)
- t = arg0()
- assert isinstance(t,AST)
- return t
-
-
- def setASTNodeClass(self,className=None):
- if not className:
- return
- assert isinstance(className,type)
- assert issubclass(className,AST)
- self._class = className
-
- ### kind of misnomer - use setASTNodeClass instead.
- setASTNodeType = setASTNodeClass
-
- def getASTNodeClass(self):
- return self._class
-
-
-
- def getTokenTypeToASTClassMap(self):
- return self._classmap
-
- def setTokenTypeToASTClassMap(self,amap):
- self._classmap = amap
-
- def error(self, e):
- import sys
- print >> sys.stderr, e
-
- def setTokenTypeASTNodeType(self, tokenType, className):
- """
- Specify a mapping between a token type and a (AST) class.
- """
- if not self._classmap:
- self._classmap = {}
-
- if not className:
- try:
- del self._classmap[tokenType]
- except:
- pass
- else:
- ### here we should also perform actions to ensure that
- ### a. class can be loaded
- ### b. class is a subclass of AST
- ###
- assert isinstance(className,type)
- assert issubclass(className,AST) ## a & b
- ### enter the class
- self._classmap[tokenType] = className
-
- def getASTNodeType(self,tokenType):
- """
- For a given token type return the AST node type. First we
- lookup a mapping table, second we try _class
- and finally we resolve to "antlr.CommonAST".
- """
-
- # first
- if self._classmap:
- try:
- c = self._classmap[tokenType]
- if c:
- return c
- except:
- pass
- # second
- if self._class:
- return self._class
-
- # default
- return CommonAST
-
- ### methods that have been moved to file scope - just listed
- ### here to be somewhat consistent with original API
- def dup(self,t):
- return antlr.dup(t,self)
-
- def dupList(self,t):
- return antlr.dupList(t,self)
-
- def dupTree(self,t):
- return antlr.dupTree(t,self)
-
- ### methods moved to other classes
- ### 1. makeASTRoot -> Parser
- ### 2. addASTChild -> Parser
-
- ### non-standard: create alias for longish method name
- maptype = setTokenTypeASTNodeType
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### ASTVisitor ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class ASTVisitor(object):
- def __init__(self,*args):
- pass
-
- def visit(self,ast):
- pass
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### static methods and variables ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-ASTNULL = ASTNULLType()
-
-### wh: moved from ASTFactory as there's nothing ASTFactory-specific
-### in this method.
-def make(*nodes):
- if not nodes:
- return None
-
- for i in xrange(0,len(nodes)):
- node = nodes[i]
- if node:
- assert isinstance(node,AST)
-
- root = nodes[0]
- tail = None
- if root:
- root.setFirstChild(None)
-
- for i in xrange(1,len(nodes)):
- if not nodes[i]:
- continue
- if not root:
- root = tail = nodes[i]
- elif not tail:
- root.setFirstChild(nodes[i])
- tail = root.getFirstChild()
- else:
- tail.setNextSibling(nodes[i])
- tail = tail.getNextSibling()
-
- ### Chase tail to last sibling
- while tail.getNextSibling():
- tail = tail.getNextSibling()
- return root
-
-def dup(t,factory):
- if not t:
- return None
-
- if factory:
- dup_t = factory.create(t.__class__)
- else:
- raise TypeError("dup function requires ASTFactory argument")
- dup_t.initialize(t)
- return dup_t
-
-def dupList(t,factory):
- result = dupTree(t,factory)
- nt = result
- while t:
- ## for each sibling of the root
- t = t.getNextSibling()
- nt.setNextSibling(dupTree(t,factory))
- nt = nt.getNextSibling()
- return result
-
-def dupTree(t,factory):
- result = dup(t,factory)
- if t:
- result.setFirstChild(dupList(t.getFirstChild(),factory))
- return result
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-### $Id: antlr.py 3750 2009-02-13 00:13:04Z sjmachin $
-
-# Local Variables: ***
-# mode: python ***
-# py-indent-offset: 4 ***
-# End: ***
diff --git a/tablib/packages/xlwt/doc/xlwt.html b/tablib/packages/xlwt/doc/xlwt.html
deleted file mode 100644
index 6efb698..0000000
--- a/tablib/packages/xlwt/doc/xlwt.html
+++ /dev/null
@@ -1,199 +0,0 @@
-<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
-<html>
-<head>
-<meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
-<title>The xlwt Module</title>
-</head>
-<body>
-<h1>The xlwt Module</h1>
-<p /><p><b>A Python package for generating Microsoft Excel &#8482; spreadsheet files.
-</b></p>
-
-<h2>General information</h2>
-
-<h3>State of Documentation</h3>
-
-<p>
-This documentation is currently incomplete. There may be methods and
-classes not included and any item marked with a <em
-style="color:red;">[NC]</em> is not complete and may have further
-parameters, methods, attributes and functionality that are not
-documented. In these cases, you'll have to refer to the source if the
-documentation provided is insufficient.
-</p>
-
-</p>
-
-<h2>Module Contents <em style="color:red;">[NC]</em></h2>
-<dl>
- <dt><b>easyxf</b> (function)</dt>
- <dd>
- <p>
- This function is used to create and configure XFStyle objects
- for use with (for example) the Worksheet.write method.
- </p>
- <dl>
- <dt><i>strg_to_parse</i></dt>
- <dd>
- <p>
- A string to be parsed to obtain attribute values for Alignment, Borders, Font,
- Pattern and Protection objects. Refer to the examples
- in the file .../examples/xlwt_easyxf_simple_demo.py and to the xf_dict
- dictionary in Style.py. Various synonyms including color/colour, center/centre and gray/grey
- are allowed. Case is irrelevant (except maybe in font names). '-' may be used instead
- of '_'.<br />
- Example: "font: bold on; align: wrap on, vert centre, horiz center"
- </p>
- </dd>
- <dt><i>num_format_str</i></dt>
- <dd>
- <p>
- To get the "number format string" of an existing cell whose format you want to reproduce,
- select the cell and click on Format/Cells/Number/Custom. Otherwise, refer to Excel help.<br />
- Examples: "#,##0.00", "dd/mm/yyyy"
- </p>
- </dd>
- <dt>Returns:</dt>
- <dd>
- An object of the XFstyle class
- </dd>
- </dl>
- <br />
-
- </dd>
-
- <dt><b>Workbook</b> (class) [<a href='#xlwt.Workbook-class'>#</a>]</dt>
- <dd>
- <p>The class to instantiate to create a workbook</p>
- <p>For more information about this class, see <a href='#xlwt.Workbook-class'><i>The Workbook Class</i></a>.</p>
- </dd>
- <dt><b>Worksheet</b> (class) [<a href='#xlwt.Worksheet-class'>#</a>]</dt>
- <dd>
- <p>A class to represent the contents of a sheet in a workbook.</p>
- <p>For more information about this class, see <a href='#xlwt.Worksheet-class'><i>The Worksheet Class</i></a>.</p>
- </dd>
-</dl>
-
-<h2><a id='xlwt.Workbook-class' name='xlwt.Workbook-class'>The Workbook Class</a><em style="color:red;">[NC]</em></h2>
-<dl>
-<dt><b>Workbook(encoding='ascii',style_compression=0)</b> (class) [<a href='#xlwt.Workbook-class'>#</a>]</dt>
-<dd>
- <p>
- This is a class representing a workbook and all its contents.
- When creating Excel files with xlwt, you will normally start by
- instantiating an object of this class.
- </p>
- <dl>
- <dt><i>encoding</i></dt>
- <dd>
- <em style="color:red;">[NC]</em>
- </dd>
- <dt><i>style_compression</i></dt>
- <dd>
- <em style="color:red;">[NC]</em>
- </dd>
- <dt>Returns:</dt>
- <dd>
- An object of the <a href="#xlwt.Workbook-class">Workbook</a> class
- </dd>
- </dl>
- <br />
-</dd>
-<dt><a id='xlwt.Workbook.add_sheet-method' name='xlwt.Workbook.add_sheet-method'><b>add_sheet(sheetname)</b></a> [<a href='#xlwt.Workbook.add_sheet-method'>#</a>]</dt>
-<dd>
- <p>
- This method is used to create Worksheets in a Workbook.
- </p>
- <dl>
- <dt><i>sheetname</i></dt>
- <dd>
- The name to use for this sheet, as it will appear in the tabs at
- the bottom of the Excel application.
- </dd>
- <dt>Returns:</dt>
- <dd>
- An object of the <a href="#xlwt.Worksheet-class">Worksheet</a> class
- </dd>
- </dl>
- <br />
-</dd>
-<dt><a id='xlwt.Workbook.save-method' name='xlwt.Workbook.save-method'><b>save(filename_or_stream)</b></a> [<a href='#xlwt.Workbook.save-method'>#</a>]</dt>
-<dd>
- <p>
- This method is used to save Workbook to a file in native Excel format.
- </p>
- <dl>
- <dt><i>filename_or_stream</i></dt>
- <dd>
- <p>
- This can be a string containing a filename of the file, in which case
- the excel file is saved to disk using the name provided.
- </p>
- <p>
- It can also be a stream object with a write method, such as a
- StringIO, in which case the data for the excel file is written
- to the stream.
- </p>
- </dd>
- </dl>
- <br />
-</dd>
-</dl>
-
-<h2><a id='xlwt.Worksheet-class' name='xlwt.Worksheet-class'>The Worksheet Class</a><em style="color:red;">[NC]</em></h2>
-<dl>
-<dt><b>Worksheet(sheetname, parent_book)</b> (class) [<a href='#xlwt.Worksheet-class'>#</a>]</dt>
-<dd>
- <p>
- This is a class representing the contents of a sheet in a workbook.
- </p>
- <p>
- WARNING: You don't normally create instances of this class
- yourself. They are returned from calls to <a href="#xlwt.Workbook.add_sheet-method">Workbook.add_sheet</a>
- </p>
-</dd>
-<dt><a id='xlwt.Worksheet.write-method'
-name='xlwt.Worksheet.write-method'><b>write(r, c, label="", style=Style.default_style)</b></a> [<a href='#xlwt.Worksheet.write-method'>#</a>]</dt>
-<dd>
- <p>
- This method is used to write a cell to a Worksheet..
- </p>
- <dl>
- <dt><i>r</i></dt>
- <dd>
- The zero-relative number of the row in the worksheet to which the cell should be written.
- </dd>
- <dt><i>c</i></dt>
- <dd>
- The zero-relative number of the column in the worksheet to which the cell should be written.
- </dd>
- <dt><i>label</i></dt>
- <dd>
- The data value to be written.
- An int, long, or decimal.Decimal instance is converted to float.
- A unicode instance is written as is.
- A str instance is converted to unicode using the encoding (default: 'ascii') specified
- when the Workbook instance was created.
- A datetime.datetime, datetime.date, or datetime.time instance is converted into Excel date format
- (a float representing the number of days since (typically) 1899-12-31T00:00:00,
- under the pretence that 1900 was a leap year).
- A bool instance will show up as TRUE or FALSE in Excel.
- None causes the cell to be blank -- no data, only formatting.
- An xlwt.Formula instance causes an Excel formula to be written.
- <em style="color:red;">[NC]</em>
- </dd>
- <dt><i>style</i></dt>
- <dd>
- A style -- also known as an XF (extended format) -- is an XFStyle object, which encapsulates
- the formatting applied to the cell and its contents. XFStyle objects are best set up using the
- <i>easyxf</i> function. They may also be set up by setting attributes in
- Alignment, Borders, Pattern, Font and Protection objects
- then setting those objects and a format string as attributes of an XFStyle object.
- <em style="color:red;">[NC]</em>
- </dd>
- </dl>
- <br />
-</dd>
-</dl>
-
-</body></html>
diff --git a/tablib/packages/xlwt/examples/big-16Mb.py b/tablib/packages/xlwt/examples/big-16Mb.py
deleted file mode 100644
index 91db123..0000000
--- a/tablib/packages/xlwt/examples/big-16Mb.py
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/env python
-# tries stress SST, SAT and MSAT
-
-from time import *
-from xlwt.Workbook import *
-from xlwt.Style import *
-
-style = XFStyle()
-
-wb = Workbook()
-ws0 = wb.add_sheet('0')
-
-colcount = 200 + 1
-rowcount = 6000 + 1
-
-t0 = time()
-print "\nstart: %s" % ctime(t0)
-
-print "Filling..."
-for col in xrange(colcount):
- print "[%d]" % col,
- for row in xrange(rowcount):
- #ws0.write(row, col, "BIG(%d, %d)" % (row, col))
- ws0.write(row, col, "BIG")
-
-t1 = time() - t0
-print "\nsince starting elapsed %.2f s" % (t1)
-
-print "Storing..."
-wb.save('big-16Mb.xls')
-
-t2 = time() - t0
-print "since starting elapsed %.2f s" % (t2)
-
-
diff --git a/tablib/packages/xlwt/examples/big-35Mb.py b/tablib/packages/xlwt/examples/big-35Mb.py
deleted file mode 100644
index 74be5a7..0000000
--- a/tablib/packages/xlwt/examples/big-35Mb.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env python
-# tries stress SST, SAT and MSAT
-
-from time import *
-from xlwt import *
-
-style = XFStyle()
-
-wb = Workbook()
-ws0 = wb.add_sheet('0')
-
-colcount = 200 + 1
-rowcount = 6000 + 1
-
-t0 = time()
-print "\nstart: %s" % ctime(t0)
-
-print "Filling..."
-for col in xrange(colcount):
- print "[%d]" % col,
- for row in xrange(rowcount):
- ws0.write(row, col, "BIG(%d, %d)" % (row, col))
- #ws0.write(row, col, "BIG")
-
-t1 = time() - t0
-print "\nsince starting elapsed %.2f s" % (t1)
-
-print "Storing..."
-wb.save('big-35Mb.xls')
-
-t2 = time() - t0
-print "since starting elapsed %.2f s" % (t2)
-
-
diff --git a/tablib/packages/xlwt/examples/blanks.py b/tablib/packages/xlwt/examples/blanks.py
deleted file mode 100644
index 056a3ec..0000000
--- a/tablib/packages/xlwt/examples/blanks.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-font0 = Font()
-font0.name = 'Times New Roman'
-font0.struck_out = True
-font0.bold = True
-
-style0 = XFStyle()
-style0.font = font0
-
-
-wb = Workbook()
-ws0 = wb.add_sheet('0')
-
-ws0.write(1, 1, 'Test', style0)
-
-for i in range(0, 0x53):
- borders = Borders()
- borders.left = i
- borders.right = i
- borders.top = i
- borders.bottom = i
-
- style = XFStyle()
- style.borders = borders
-
- ws0.write(i, 2, '', style)
- ws0.write(i, 3, hex(i), style0)
-
-ws0.write_merge(5, 8, 6, 10, "")
-
-wb.save('blanks.xls')
diff --git a/tablib/packages/xlwt/examples/col_width.py b/tablib/packages/xlwt/examples/col_width.py
deleted file mode 100644
index 6e6cb33..0000000
--- a/tablib/packages/xlwt/examples/col_width.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-__rev_id__ = """$Id: col_width.py 3315 2008-03-14 14:44:52Z chris $"""
-
-
-from xlwt import *
-
-w = Workbook()
-ws = w.add_sheet('Hey, Dude')
-
-for i in range(6, 80):
- fnt = Font()
- fnt.height = i*20
- style = XFStyle()
- style.font = fnt
- ws.write(1, i, 'Test')
- ws.col(i).width = 0x0d00 + i
-w.save('col_width.xls')
diff --git a/tablib/packages/xlwt/examples/country.py b/tablib/packages/xlwt/examples/country.py
deleted file mode 100644
index cb26e29..0000000
--- a/tablib/packages/xlwt/examples/country.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1252 -*-
-# Copyright (C) 2007 John Machin
-
-from xlwt import *
-
-w = Workbook()
-w.country_code = 61
-ws = w.add_sheet('AU')
-w.save('country.xls')
diff --git a/tablib/packages/xlwt/examples/dates.py b/tablib/packages/xlwt/examples/dates.py
deleted file mode 100644
index 389b93b..0000000
--- a/tablib/packages/xlwt/examples/dates.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-from datetime import datetime
-
-w = Workbook()
-ws = w.add_sheet('Hey, Dude')
-
-fmts = [
- 'M/D/YY',
- 'D-MMM-YY',
- 'D-MMM',
- 'MMM-YY',
- 'h:mm AM/PM',
- 'h:mm:ss AM/PM',
- 'h:mm',
- 'h:mm:ss',
- 'M/D/YY h:mm',
- 'mm:ss',
- '[h]:mm:ss',
- 'mm:ss.0',
-]
-
-i = 0
-for fmt in fmts:
- ws.write(i, 0, fmt)
-
- style = XFStyle()
- style.num_format_str = fmt
-
- ws.write(i, 4, datetime.now(), style)
-
- i += 1
-
-w.save('dates.xls')
diff --git a/tablib/packages/xlwt/examples/format.py b/tablib/packages/xlwt/examples/format.py
deleted file mode 100644
index fd49e0a..0000000
--- a/tablib/packages/xlwt/examples/format.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-font0 = Font()
-font0.name = 'Times New Roman'
-font0.struck_out = True
-font0.bold = True
-
-style0 = XFStyle()
-style0.font = font0
-
-
-wb = Workbook()
-ws0 = wb.add_sheet('0')
-
-ws0.write(1, 1, 'Test', style0)
-
-for i in range(0, 0x53):
- fnt = Font()
- fnt.name = 'Arial'
- fnt.colour_index = i
- fnt.outline = True
-
- borders = Borders()
- borders.left = i
-
- style = XFStyle()
- style.font = fnt
- style.borders = borders
-
- ws0.write(i, 2, 'colour', style)
- ws0.write(i, 3, hex(i), style0)
-
-
-wb.save('format.xls')
diff --git a/tablib/packages/xlwt/examples/formula_names.py b/tablib/packages/xlwt/examples/formula_names.py
deleted file mode 100644
index f0354bc..0000000
--- a/tablib/packages/xlwt/examples/formula_names.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-from xlwt.ExcelFormulaParser import FormulaParseException
-
-w = Workbook()
-ws = w.add_sheet('F')
-
-## This example is a little silly since the formula building is
-## so simplistic that it often fails because the generated text
-## has the wrong number of parameters for the function being
-## tested.
-
-i = 0
-succeed_count = 0
-fail_count = 0
-for n in sorted(ExcelMagic.std_func_by_name):
- ws.write(i, 0, n)
- text = n + "($A$1)"
- try:
- formula = Formula(text)
- except FormulaParseException,e:
- print "Could not parse %r: %s" % (text,e.args[0])
- fail_count += 1
- else:
- ws.write(i, 3, formula)
- succeed_count += 1
- i += 1
-
-w.save('formula_names.xls')
-
-print "succeeded with %i functions, failed with %i" % (succeed_count,fail_count)
diff --git a/tablib/packages/xlwt/examples/formulas.py b/tablib/packages/xlwt/examples/formulas.py
deleted file mode 100644
index b89f5f5..0000000
--- a/tablib/packages/xlwt/examples/formulas.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-w = Workbook()
-ws = w.add_sheet('F')
-
-ws.write(0, 0, Formula("-(1+1)"))
-ws.write(1, 0, Formula("-(1+1)/(-2-2)"))
-ws.write(2, 0, Formula("-(134.8780789+1)"))
-ws.write(3, 0, Formula("-(134.8780789e-10+1)"))
-ws.write(4, 0, Formula("-1/(1+1)+9344"))
-
-ws.write(0, 1, Formula("-(1+1)"))
-ws.write(1, 1, Formula("-(1+1)/(-2-2)"))
-ws.write(2, 1, Formula("-(134.8780789+1)"))
-ws.write(3, 1, Formula("-(134.8780789e-10+1)"))
-ws.write(4, 1, Formula("-1/(1+1)+9344"))
-
-ws.write(0, 2, Formula("A1*B1"))
-ws.write(1, 2, Formula("A2*B2"))
-ws.write(2, 2, Formula("A3*B3"))
-ws.write(3, 2, Formula("A4*B4*sin(pi()/4)"))
-ws.write(4, 2, Formula("A5%*B5*pi()/1000"))
-
-##############
-## NOTE: parameters are separated by semicolon!!!
-##############
-
-
-ws.write(5, 2, Formula("C1+C2+C3+C4+C5/(C1+C2+C3+C4/(C1+C2+C3+C4/(C1+C2+C3+C4)+C5)+C5)-20.3e-2"))
-ws.write(5, 3, Formula("C1^2"))
-ws.write(6, 2, Formula("SUM(C1;C2;;;;;C3;;;C4)"))
-ws.write(6, 3, Formula("SUM($A$1:$C$5)"))
-
-ws.write(7, 0, Formula('"lkjljllkllkl"'))
-ws.write(7, 1, Formula('"yuyiyiyiyi"'))
-ws.write(7, 2, Formula('A8 & B8 & A8'))
-ws.write(8, 2, Formula('now()'))
-
-ws.write(10, 2, Formula('TRUE'))
-ws.write(11, 2, Formula('FALSE'))
-ws.write(12, 3, Formula('IF(A1>A2;3;"hkjhjkhk")'))
-
-w.save('formulas.xls')
diff --git a/tablib/packages/xlwt/examples/hyperlinks.py b/tablib/packages/xlwt/examples/hyperlinks.py
deleted file mode 100644
index 8de611b..0000000
--- a/tablib/packages/xlwt/examples/hyperlinks.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-f = Font()
-f.height = 20*72
-f.name = 'Verdana'
-f.bold = True
-f.underline = Font.UNDERLINE_DOUBLE
-f.colour_index = 4
-
-h_style = XFStyle()
-h_style.font = f
-
-w = Workbook()
-ws = w.add_sheet('F')
-
-##############
-## NOTE: parameters are separated by semicolon!!!
-##############
-
-n = "HYPERLINK"
-ws.write_merge(1, 1, 1, 10, Formula(n + '("http://www.irs.gov/pub/irs-pdf/f1000.pdf";"f1000.pdf")'), h_style)
-ws.write_merge(2, 2, 2, 25, Formula(n + '("mailto:roman.kiseliov@gmail.com?subject=pyExcelerator-feedback&Body=Hello,%20Roman!";"pyExcelerator-feedback")'), h_style)
-
-w.save("hyperlinks.xls")
diff --git a/tablib/packages/xlwt/examples/image.py b/tablib/packages/xlwt/examples/image.py
deleted file mode 100644
index f926b8d..0000000
--- a/tablib/packages/xlwt/examples/image.py
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-w = Workbook()
-ws = w.add_sheet('Image')
-ws.insert_bitmap('python.bmp', 2, 2)
-ws.insert_bitmap('python.bmp', 10, 2)
-
-w.save('image.xls')
diff --git a/tablib/packages/xlwt/examples/merged.py b/tablib/packages/xlwt/examples/merged.py
deleted file mode 100644
index f7f9c57..0000000
--- a/tablib/packages/xlwt/examples/merged.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-fnt = Font()
-fnt.name = 'Arial'
-fnt.colour_index = 4
-fnt.bold = True
-
-borders = Borders()
-borders.left = 6
-borders.right = 6
-borders.top = 6
-borders.bottom = 6
-
-al = Alignment()
-al.horz = Alignment.HORZ_CENTER
-al.vert = Alignment.VERT_CENTER
-
-style = XFStyle()
-style.font = fnt
-style.borders = borders
-style.alignment = al
-
-
-wb = Workbook()
-ws0 = wb.add_sheet('sheet0')
-ws1 = wb.add_sheet('sheet1')
-ws2 = wb.add_sheet('sheet2')
-
-for i in range(0, 0x200, 2):
- ws0.write_merge(i, i+1, 1, 5, 'test %d' % i, style)
- ws1.write_merge(i, i, 1, 7, 'test %d' % i, style)
- ws2.write_merge(i, i+1, 1, 7 + (i%10), 'test %d' % i, style)
-
-
-wb.save('merged.xls')
diff --git a/tablib/packages/xlwt/examples/merged0.py b/tablib/packages/xlwt/examples/merged0.py
deleted file mode 100644
index 93496c6..0000000
--- a/tablib/packages/xlwt/examples/merged0.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-wb = Workbook()
-ws0 = wb.add_sheet('sheet0')
-
-
-fnt = Font()
-fnt.name = 'Arial'
-fnt.colour_index = 4
-fnt.bold = True
-
-borders = Borders()
-borders.left = 6
-borders.right = 6
-borders.top = 6
-borders.bottom = 6
-
-style = XFStyle()
-style.font = fnt
-style.borders = borders
-
-ws0.write_merge(3, 3, 1, 5, 'test1', style)
-ws0.write_merge(4, 10, 1, 5, 'test2', style)
-ws0.col(1).width = 0x0d00
-
-wb.save('merged0.xls')
diff --git a/tablib/packages/xlwt/examples/merged1.py b/tablib/packages/xlwt/examples/merged1.py
deleted file mode 100644
index 813530b..0000000
--- a/tablib/packages/xlwt/examples/merged1.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-wb = Workbook()
-ws0 = wb.add_sheet('sheet0')
-
-fnt1 = Font()
-fnt1.name = 'Verdana'
-fnt1.bold = True
-fnt1.height = 18*0x14
-
-pat1 = Pattern()
-pat1.pattern = Pattern.SOLID_PATTERN
-pat1.pattern_fore_colour = 0x16
-
-brd1 = Borders()
-brd1.left = 0x06
-brd1.right = 0x06
-brd1.top = 0x06
-brd1.bottom = 0x06
-
-fnt2 = Font()
-fnt2.name = 'Verdana'
-fnt2.bold = True
-fnt2.height = 14*0x14
-
-brd2 = Borders()
-brd2.left = 0x01
-brd2.right = 0x01
-brd2.top = 0x01
-brd2.bottom = 0x01
-
-pat2 = Pattern()
-pat2.pattern = Pattern.SOLID_PATTERN
-pat2.pattern_fore_colour = 0x01F
-
-fnt3 = Font()
-fnt3.name = 'Verdana'
-fnt3.bold = True
-fnt3.italic = True
-fnt3.height = 12*0x14
-
-brd3 = Borders()
-brd3.left = 0x07
-brd3.right = 0x07
-brd3.top = 0x07
-brd3.bottom = 0x07
-
-fnt4 = Font()
-
-al1 = Alignment()
-al1.horz = Alignment.HORZ_CENTER
-al1.vert = Alignment.VERT_CENTER
-
-al2 = Alignment()
-al2.horz = Alignment.HORZ_RIGHT
-al2.vert = Alignment.VERT_CENTER
-
-al3 = Alignment()
-al3.horz = Alignment.HORZ_LEFT
-al3.vert = Alignment.VERT_CENTER
-
-style1 = XFStyle()
-style1.font = fnt1
-style1.alignment = al1
-style1.pattern = pat1
-style1.borders = brd1
-
-style2 = XFStyle()
-style2.font = fnt2
-style2.alignment = al1
-style2.pattern = pat2
-style2.borders = brd2
-
-style3 = XFStyle()
-style3.font = fnt3
-style3.alignment = al1
-style3.pattern = pat2
-style3.borders = brd3
-
-price_style = XFStyle()
-price_style.font = fnt4
-price_style.alignment = al2
-price_style.borders = brd3
-price_style.num_format_str = '_(#,##0.00_) "money"'
-
-ware_style = XFStyle()
-ware_style.font = fnt4
-ware_style.alignment = al3
-ware_style.borders = brd3
-
-
-ws0.merge(3, 3, 1, 5, style1)
-ws0.merge(4, 10, 1, 6, style2)
-ws0.merge(14, 16, 1, 7, style3)
-ws0.col(1).width = 0x0d00
-
-
-wb.save('merged1.xls')
diff --git a/tablib/packages/xlwt/examples/mini.py b/tablib/packages/xlwt/examples/mini.py
deleted file mode 100644
index 61bb30c..0000000
--- a/tablib/packages/xlwt/examples/mini.py
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-w = Workbook()
-ws = w.add_sheet('xlwt was here')
-w.save('mini.xls')
diff --git a/tablib/packages/xlwt/examples/num_formats.py b/tablib/packages/xlwt/examples/num_formats.py
deleted file mode 100644
index 3a56f6c..0000000
--- a/tablib/packages/xlwt/examples/num_formats.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-w = Workbook()
-ws = w.add_sheet('Hey, Dude')
-
-fmts = [
- 'general',
- '0',
- '0.00',
- '#,##0',
- '#,##0.00',
- '"$"#,##0_);("$"#,##',
- '"$"#,##0_);[Red]("$"#,##',
- '"$"#,##0.00_);("$"#,##',
- '"$"#,##0.00_);[Red]("$"#,##',
- '0%',
- '0.00%',
- '0.00E+00',
- '# ?/?',
- '# ??/??',
- 'M/D/YY',
- 'D-MMM-YY',
- 'D-MMM',
- 'MMM-YY',
- 'h:mm AM/PM',
- 'h:mm:ss AM/PM',
- 'h:mm',
- 'h:mm:ss',
- 'M/D/YY h:mm',
- '_(#,##0_);(#,##0)',
- '_(#,##0_);[Red](#,##0)',
- '_(#,##0.00_);(#,##0.00)',
- '_(#,##0.00_);[Red](#,##0.00)',
- '_("$"* #,##0_);_("$"* (#,##0);_("$"* "-"_);_(@_)',
- '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)',
- '_("$"* #,##0.00_);_("$"* (#,##0.00);_("$"* "-"??_);_(@_)',
- '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)',
- 'mm:ss',
- '[h]:mm:ss',
- 'mm:ss.0',
- '##0.0E+0',
- '@'
-]
-
-i = 0
-for fmt in fmts:
- ws.write(i, 0, fmt)
-
- style = XFStyle()
- style.num_format_str = fmt
-
- ws.write(i, 4, -1278.9078, style)
-
- i += 1
-
-w.save('num_formats.xls')
diff --git a/tablib/packages/xlwt/examples/numbers.py b/tablib/packages/xlwt/examples/numbers.py
deleted file mode 100644
index 524d9fc..0000000
--- a/tablib/packages/xlwt/examples/numbers.py
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-w = Workbook()
-ws = w.add_sheet('Hey, Dude')
-
-ws.write(0, 0, 1)
-ws.write(1, 0, 1.23)
-ws.write(2, 0, 12345678)
-ws.write(3, 0, 123456.78)
-
-ws.write(0, 1, -1)
-ws.write(1, 1, -1.23)
-ws.write(2, 1, -12345678)
-ws.write(3, 1, -123456.78)
-
-ws.write(0, 2, -17867868678687.0)
-ws.write(1, 2, -1.23e-5)
-ws.write(2, 2, -12345678.90780980)
-ws.write(3, 2, -123456.78)
-
-w.save('numbers.xls')
diff --git a/tablib/packages/xlwt/examples/outline.py b/tablib/packages/xlwt/examples/outline.py
deleted file mode 100644
index 45b8df9..0000000
--- a/tablib/packages/xlwt/examples/outline.py
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-fnt = Font()
-fnt.name = 'Arial'
-fnt.colour_index = 4
-fnt.bold = True
-
-borders = Borders()
-borders.left = 6
-borders.right = 6
-borders.top = 6
-borders.bottom = 6
-
-style = XFStyle()
-style.font = fnt
-style.borders = borders
-
-wb = Workbook()
-
-ws0 = wb.add_sheet('Rows Outline')
-
-ws0.write_merge(1, 1, 1, 5, 'test 1', style)
-ws0.write_merge(2, 2, 1, 4, 'test 1', style)
-ws0.write_merge(3, 3, 1, 3, 'test 2', style)
-ws0.write_merge(4, 4, 1, 4, 'test 1', style)
-ws0.write_merge(5, 5, 1, 4, 'test 3', style)
-ws0.write_merge(6, 6, 1, 5, 'test 1', style)
-ws0.write_merge(7, 7, 1, 5, 'test 4', style)
-ws0.write_merge(8, 8, 1, 4, 'test 1', style)
-ws0.write_merge(9, 9, 1, 3, 'test 5', style)
-
-ws0.row(1).level = 1
-ws0.row(2).level = 1
-ws0.row(3).level = 2
-ws0.row(4).level = 2
-ws0.row(5).level = 2
-ws0.row(6).level = 2
-ws0.row(7).level = 2
-ws0.row(8).level = 1
-ws0.row(9).level = 1
-
-
-ws1 = wb.add_sheet('Columns Outline')
-
-ws1.write_merge(1, 1, 1, 5, 'test 1', style)
-ws1.write_merge(2, 2, 1, 4, 'test 1', style)
-ws1.write_merge(3, 3, 1, 3, 'test 2', style)
-ws1.write_merge(4, 4, 1, 4, 'test 1', style)
-ws1.write_merge(5, 5, 1, 4, 'test 3', style)
-ws1.write_merge(6, 6, 1, 5, 'test 1', style)
-ws1.write_merge(7, 7, 1, 5, 'test 4', style)
-ws1.write_merge(8, 8, 1, 4, 'test 1', style)
-ws1.write_merge(9, 9, 1, 3, 'test 5', style)
-
-ws1.col(1).level = 1
-ws1.col(2).level = 1
-ws1.col(3).level = 2
-ws1.col(4).level = 2
-ws1.col(5).level = 2
-ws1.col(6).level = 2
-ws1.col(7).level = 2
-ws1.col(8).level = 1
-ws1.col(9).level = 1
-
-
-ws2 = wb.add_sheet('Rows and Columns Outline')
-
-ws2.write_merge(1, 1, 1, 5, 'test 1', style)
-ws2.write_merge(2, 2, 1, 4, 'test 1', style)
-ws2.write_merge(3, 3, 1, 3, 'test 2', style)
-ws2.write_merge(4, 4, 1, 4, 'test 1', style)
-ws2.write_merge(5, 5, 1, 4, 'test 3', style)
-ws2.write_merge(6, 6, 1, 5, 'test 1', style)
-ws2.write_merge(7, 7, 1, 5, 'test 4', style)
-ws2.write_merge(8, 8, 1, 4, 'test 1', style)
-ws2.write_merge(9, 9, 1, 3, 'test 5', style)
-
-ws2.row(1).level = 1
-ws2.row(2).level = 1
-ws2.row(3).level = 2
-ws2.row(4).level = 2
-ws2.row(5).level = 2
-ws2.row(6).level = 2
-ws2.row(7).level = 2
-ws2.row(8).level = 1
-ws2.row(9).level = 1
-
-ws2.write_merge(1, 1, 1, 5, 'test 1', style)
-ws2.write_merge(2, 2, 1, 4, 'test 1', style)
-ws2.write_merge(3, 3, 1, 3, 'test 2', style)
-ws2.write_merge(4, 4, 1, 4, 'test 1', style)
-ws2.write_merge(5, 5, 1, 4, 'test 3', style)
-ws2.write_merge(6, 6, 1, 5, 'test 1', style)
-ws2.write_merge(7, 7, 1, 5, 'test 4', style)
-ws2.write_merge(8, 8, 1, 4, 'test 1', style)
-ws2.write_merge(9, 9, 1, 3, 'test 5', style)
-
-ws2.col(1).level = 1
-ws2.col(2).level = 1
-ws2.col(3).level = 2
-ws2.col(4).level = 2
-ws2.col(5).level = 2
-ws2.col(6).level = 2
-ws2.col(7).level = 2
-ws2.col(8).level = 1
-ws2.col(9).level = 1
-
-
-wb.save('outline.xls')
diff --git a/tablib/packages/xlwt/examples/panes.py b/tablib/packages/xlwt/examples/panes.py
deleted file mode 100644
index 9fd83b0..0000000
--- a/tablib/packages/xlwt/examples/panes.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-w = Workbook()
-ws1 = w.add_sheet('sheet 1')
-ws2 = w.add_sheet('sheet 2')
-ws3 = w.add_sheet('sheet 3')
-ws4 = w.add_sheet('sheet 4')
-ws5 = w.add_sheet('sheet 5')
-ws6 = w.add_sheet('sheet 6')
-
-for i in range(0x100):
- ws1.write(i/0x10, i%0x10, i)
-
-for i in range(0x100):
- ws2.write(i/0x10, i%0x10, i)
-
-for i in range(0x100):
- ws3.write(i/0x10, i%0x10, i)
-
-for i in range(0x100):
- ws4.write(i/0x10, i%0x10, i)
-
-for i in range(0x100):
- ws5.write(i/0x10, i%0x10, i)
-
-for i in range(0x100):
- ws6.write(i/0x10, i%0x10, i)
-
-ws1.panes_frozen = True
-ws1.horz_split_pos = 2
-
-ws2.panes_frozen = True
-ws2.vert_split_pos = 2
-
-ws3.panes_frozen = True
-ws3.horz_split_pos = 1
-ws3.vert_split_pos = 1
-
-ws4.panes_frozen = False
-ws4.horz_split_pos = 12
-ws4.horz_split_first_visible = 2
-
-ws5.panes_frozen = False
-ws5.vert_split_pos = 40
-ws4.vert_split_first_visible = 2
-
-ws6.panes_frozen = False
-ws6.horz_split_pos = 12
-ws4.horz_split_first_visible = 2
-ws6.vert_split_pos = 40
-ws4.vert_split_first_visible = 2
-
-w.save('panes.xls')
-
diff --git a/tablib/packages/xlwt/examples/parse-fmla.py b/tablib/packages/xlwt/examples/parse-fmla.py
deleted file mode 100644
index 06f68eb..0000000
--- a/tablib/packages/xlwt/examples/parse-fmla.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from xlwt import ExcelFormulaParser, ExcelFormula
-import sys
-
-f = ExcelFormula.Formula(
-""" -((1.80 + 2.898 * 1)/(1.80 + 2.898))*
-AVERAGE((1.80 + 2.898 * 1)/(1.80 + 2.898);
- (1.80 + 2.898 * 1)/(1.80 + 2.898);
- (1.80 + 2.898 * 1)/(1.80 + 2.898)) +
-SIN(PI()/4)""")
-
-#for t in f.rpn():
-# print "%15s %15s" % (ExcelFormulaParser.PtgNames[t[0]], t[1])
diff --git a/tablib/packages/xlwt/examples/protection.py b/tablib/packages/xlwt/examples/protection.py
deleted file mode 100644
index db54cb0..0000000
--- a/tablib/packages/xlwt/examples/protection.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-fnt = Font()
-fnt.name = 'Arial'
-fnt.colour_index = 4
-fnt.bold = True
-
-borders = Borders()
-borders.left = 6
-borders.right = 6
-borders.top = 6
-borders.bottom = 6
-
-style = XFStyle()
-style.font = fnt
-style.borders = borders
-
-wb = Workbook()
-
-ws0 = wb.add_sheet('Rows Outline')
-
-ws0.write_merge(1, 1, 1, 5, 'test 1', style)
-ws0.write_merge(2, 2, 1, 4, 'test 1', style)
-ws0.write_merge(3, 3, 1, 3, 'test 2', style)
-ws0.write_merge(4, 4, 1, 4, 'test 1', style)
-ws0.write_merge(5, 5, 1, 4, 'test 3', style)
-ws0.write_merge(6, 6, 1, 5, 'test 1', style)
-ws0.write_merge(7, 7, 1, 5, 'test 4', style)
-ws0.write_merge(8, 8, 1, 4, 'test 1', style)
-ws0.write_merge(9, 9, 1, 3, 'test 5', style)
-
-ws0.row(1).level = 1
-ws0.row(2).level = 1
-ws0.row(3).level = 2
-ws0.row(4).level = 2
-ws0.row(5).level = 2
-ws0.row(6).level = 2
-ws0.row(7).level = 2
-ws0.row(8).level = 1
-ws0.row(9).level = 1
-
-
-ws1 = wb.add_sheet('Columns Outline')
-
-ws1.write_merge(1, 1, 1, 5, 'test 1', style)
-ws1.write_merge(2, 2, 1, 4, 'test 1', style)
-ws1.write_merge(3, 3, 1, 3, 'test 2', style)
-ws1.write_merge(4, 4, 1, 4, 'test 1', style)
-ws1.write_merge(5, 5, 1, 4, 'test 3', style)
-ws1.write_merge(6, 6, 1, 5, 'test 1', style)
-ws1.write_merge(7, 7, 1, 5, 'test 4', style)
-ws1.write_merge(8, 8, 1, 4, 'test 1', style)
-ws1.write_merge(9, 9, 1, 3, 'test 5', style)
-
-ws1.col(1).level = 1
-ws1.col(2).level = 1
-ws1.col(3).level = 2
-ws1.col(4).level = 2
-ws1.col(5).level = 2
-ws1.col(6).level = 2
-ws1.col(7).level = 2
-ws1.col(8).level = 1
-ws1.col(9).level = 1
-
-
-ws2 = wb.add_sheet('Rows and Columns Outline')
-
-ws2.write_merge(1, 1, 1, 5, 'test 1', style)
-ws2.write_merge(2, 2, 1, 4, 'test 1', style)
-ws2.write_merge(3, 3, 1, 3, 'test 2', style)
-ws2.write_merge(4, 4, 1, 4, 'test 1', style)
-ws2.write_merge(5, 5, 1, 4, 'test 3', style)
-ws2.write_merge(6, 6, 1, 5, 'test 1', style)
-ws2.write_merge(7, 7, 1, 5, 'test 4', style)
-ws2.write_merge(8, 8, 1, 4, 'test 1', style)
-ws2.write_merge(9, 9, 1, 3, 'test 5', style)
-
-ws2.row(1).level = 1
-ws2.row(2).level = 1
-ws2.row(3).level = 2
-ws2.row(4).level = 2
-ws2.row(5).level = 2
-ws2.row(6).level = 2
-ws2.row(7).level = 2
-ws2.row(8).level = 1
-ws2.row(9).level = 1
-
-ws2.col(1).level = 1
-ws2.col(2).level = 1
-ws2.col(3).level = 2
-ws2.col(4).level = 2
-ws2.col(5).level = 2
-ws2.col(6).level = 2
-ws2.col(7).level = 2
-ws2.col(8).level = 1
-ws2.col(9).level = 1
-
-
-ws0.protect = True
-ws0.wnd_protect = True
-ws0.obj_protect = True
-ws0.scen_protect = True
-ws0.password = "123456"
-
-ws1.protect = True
-ws1.wnd_protect = True
-ws1.obj_protect = True
-ws1.scen_protect = True
-ws1.password = "abcdefghij"
-
-ws2.protect = True
-ws2.wnd_protect = True
-ws2.obj_protect = True
-ws2.scen_protect = True
-ws2.password = "ok"
-
-wb.protect = True
-wb.wnd_protect = True
-wb.obj_protect = True
-wb.save('protection.xls')
diff --git a/tablib/packages/xlwt/examples/python.bmp b/tablib/packages/xlwt/examples/python.bmp
deleted file mode 100644
index bd1ba3f..0000000
--- a/tablib/packages/xlwt/examples/python.bmp
+++ /dev/null
Binary files differ
diff --git a/tablib/packages/xlwt/examples/row_styles.py b/tablib/packages/xlwt/examples/row_styles.py
deleted file mode 100644
index dd6d494..0000000
--- a/tablib/packages/xlwt/examples/row_styles.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-w = Workbook()
-ws = w.add_sheet('Hey, Dude')
-
-for i in range(6, 80):
- fnt = Font()
- fnt.height = i*20
- style = XFStyle()
- style.font = fnt
- ws.write(i, 1, 'Test')
- ws.row(i).set_style(style)
-w.save('row_styles.xls')
diff --git a/tablib/packages/xlwt/examples/row_styles_empty.py b/tablib/packages/xlwt/examples/row_styles_empty.py
deleted file mode 100644
index cf6a65c..0000000
--- a/tablib/packages/xlwt/examples/row_styles_empty.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-__rev_id__ = """$Id: row_styles_empty.py 3309 2008-03-14 11:04:30Z chris $"""
-
-
-from pyExcelerator import *
-
-w = Workbook()
-ws = w.add_sheet('Hey, Dude')
-
-for i in range(6, 80):
- fnt = Font()
- fnt.height = i*20
- style = XFStyle()
- style.font = fnt
- ws.row(i).set_style(style)
-w.save('row_styles_empty.xls')
diff --git a/tablib/packages/xlwt/examples/simple.py b/tablib/packages/xlwt/examples/simple.py
deleted file mode 100644
index 44f7622..0000000
--- a/tablib/packages/xlwt/examples/simple.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import xlwt
-from datetime import datetime
-
-font0 = xlwt.Font()
-font0.name = 'Times New Roman'
-font0.colour_index = 2
-font0.bold = True
-
-style0 = xlwt.XFStyle()
-style0.font = font0
-
-style1 = xlwt.XFStyle()
-style1.num_format_str = 'D-MMM-YY'
-
-wb = xlwt.Workbook()
-ws = wb.add_sheet('A Test Sheet')
-
-ws.write(0, 0, 'Test', style0)
-ws.write(1, 0, datetime.now(), style1)
-ws.write(2, 0, 1)
-ws.write(2, 1, 1)
-ws.write(2, 2, xlwt.Formula("A3+B3"))
-
-wb.save('example.xls')
diff --git a/tablib/packages/xlwt/examples/sst.py b/tablib/packages/xlwt/examples/sst.py
deleted file mode 100644
index b91c2f5..0000000
--- a/tablib/packages/xlwt/examples/sst.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-font0 = Formatting.Font()
-font0.name = 'Arial'
-font1 = Formatting.Font()
-font1.name = 'Arial Cyr'
-font2 = Formatting.Font()
-font2.name = 'Times New Roman'
-font3 = Formatting.Font()
-font3.name = 'Courier New Cyr'
-
-num_format0 = '0.00000'
-num_format1 = '0.000000'
-num_format2 = '0.0000000'
-num_format3 = '0.00000000'
-
-st0 = XFStyle()
-st1 = XFStyle()
-st2 = XFStyle()
-st3 = XFStyle()
-st4 = XFStyle()
-
-st0.font = font0
-st0.num_format = num_format0
-
-st1.font = font1
-st1.num_format = num_format1
-
-st2.font = font2
-st2.num_format = num_format2
-
-st3.font = font3
-st3.num_format = num_format3
-
-wb = Workbook()
-
-wb.add_style(st0)
-wb.add_style(st1)
-wb.add_style(st2)
-wb.add_style(st3)
-
-ws0 = wb.add_sheet('0')
-ws0.write(0, 0, 'Olya'*0x4000, st0)
-
-#for i in range(0, 0x10):
-# ws0.write(i, 2, ('%d'%i)*0x4000, st1)
-
-wb.save('sst.xls')
diff --git a/tablib/packages/xlwt/examples/unicode0.py b/tablib/packages/xlwt/examples/unicode0.py
deleted file mode 100644
index 3651ec9..0000000
--- a/tablib/packages/xlwt/examples/unicode0.py
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env python
-import xlwt
-
-# Strings passed to (for example) Worksheet.write can be unicode objects,
-# or str (8-bit) objects, which are then decoded into unicode.
-# The encoding to be used defaults to 'ascii'. This can be overridden
-# when the Workbook instance is created:
-
-book = xlwt.Workbook(encoding='cp1251')
-sheet = book.add_sheet('cp1251-demo')
-sheet.write(0, 0, '\xce\xeb\xff')
-book.save('unicode0.xls')
diff --git a/tablib/packages/xlwt/examples/unicode1.py b/tablib/packages/xlwt/examples/unicode1.py
deleted file mode 100644
index 90e99cc..0000000
--- a/tablib/packages/xlwt/examples/unicode1.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-w = Workbook()
-ws1 = w.add_sheet(u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK SMALL LETTER BETA}\N{GREEK SMALL LETTER GAMMA}')
-
-ws1.write(0, 0, u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK SMALL LETTER BETA}\N{GREEK SMALL LETTER GAMMA}')
-ws1.write(1, 1, u'\N{GREEK SMALL LETTER DELTA}x = 1 + \N{GREEK SMALL LETTER DELTA}')
-
-ws1.write(2,0, u'A\u2262\u0391.') # RFC2152 example
-ws1.write(3,0, u'Hi Mom -\u263a-!') # RFC2152 example
-ws1.write(4,0, u'\u65E5\u672C\u8A9E') # RFC2152 example
-ws1.write(5,0, u'Item 3 is \u00a31.') # RFC2152 example
-ws1.write(8,0, u'\N{INTEGRAL}') # RFC2152 example
-
-w.add_sheet(u'A\u2262\u0391.') # RFC2152 example
-w.add_sheet(u'Hi Mom -\u263a-!') # RFC2152 example
-one_more_ws = w.add_sheet(u'\u65E5\u672C\u8A9E') # RFC2152 example
-w.add_sheet(u'Item 3 is \u00a31.') # RFC2152 example
-
-one_more_ws.write(0, 0, u'\u2665\u2665')
-
-w.add_sheet(u'\N{GREEK SMALL LETTER ETA WITH TONOS}')
-w.save('unicode1.xls')
-
diff --git a/tablib/packages/xlwt/examples/unicode2.py b/tablib/packages/xlwt/examples/unicode2.py
deleted file mode 100644
index 18904b0..0000000
--- a/tablib/packages/xlwt/examples/unicode2.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-
-from xlwt import *
-
-w = Workbook()
-ws1 = w.add_sheet(u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK SMALL LETTER BETA}\N{GREEK SMALL LETTER GAMMA}\u2665\u041e\u041b\u042f\u2665')
-
-fnt = Font()
-fnt.height = 26*20
-style = XFStyle()
-style.font = fnt
-
-for i in range(0x10000):
- ws1.write(i/0x10, i%0x10, unichr(i), style)
-
-w.save('unicode2.xls')
-
diff --git a/tablib/packages/xlwt/examples/wsprops.py b/tablib/packages/xlwt/examples/wsprops.py
deleted file mode 100644
index adc5a04..0000000
--- a/tablib/packages/xlwt/examples/wsprops.py
+++ /dev/null
@@ -1,155 +0,0 @@
-props = \
-[
- 'name',
- 'parent',
- 'rows',
- 'cols',
- 'merged_ranges',
- 'bmp_rec',
- 'show_formulas',
- 'show_grid',
- 'show_headers',
- 'panes_frozen',
- 'show_empty_as_zero',
- 'auto_colour_grid',
- 'cols_right_to_left',
- 'show_outline',
- 'remove_splits',
- 'selected',
- 'hidden',
- 'page_preview',
- 'first_visible_row',
- 'first_visible_col',
- 'grid_colour',
- 'preview_magn',
- 'normal_magn',
- 'row_gut_width',
- 'col_gut_height',
- 'show_auto_page_breaks',
- 'dialogue_sheet',
- 'auto_style_outline',
- 'outline_below',
- 'outline_right',
- 'fit_num_pages',
- 'show_row_outline',
- 'show_col_outline',
- 'alt_expr_eval',
- 'alt_formula_entries',
- 'row_default_height',
- 'col_default_width',
- 'calc_mode',
- 'calc_count',
- 'RC_ref_mode',
- 'iterations_on',
- 'delta',
- 'save_recalc',
- 'print_headers',
- 'print_grid',
- 'grid_set',
- 'vert_page_breaks',
- 'horz_page_breaks',
- 'header_str',
- 'footer_str',
- 'print_centered_vert',
- 'print_centered_horz',
- 'left_margin',
- 'right_margin',
- 'top_margin',
- 'bottom_margin',
- 'paper_size_code',
- 'print_scaling',
- 'start_page_number',
- 'fit_width_to_pages',
- 'fit_height_to_pages',
- 'print_in_rows',
- 'portrait',
- 'print_not_colour',
- 'print_draft',
- 'print_notes',
- 'print_notes_at_end',
- 'print_omit_errors',
- 'print_hres',
- 'print_vres',
- 'header_margin',
- 'footer_margin',
- 'copies_num',
-]
-
-from xlwt import *
-
-wb = Workbook()
-ws = wb.add_sheet('sheet')
-
-print ws.name
-print ws.parent
-print ws.rows
-print ws.cols
-print ws.merged_ranges
-print ws.bmp_rec
-print ws.show_formulas
-print ws.show_grid
-print ws.show_headers
-print ws.panes_frozen
-print ws.show_empty_as_zero
-print ws.auto_colour_grid
-print ws.cols_right_to_left
-print ws.show_outline
-print ws.remove_splits
-print ws.selected
-# print ws.hidden
-print ws.page_preview
-print ws.first_visible_row
-print ws.first_visible_col
-print ws.grid_colour
-print ws.preview_magn
-print ws.normal_magn
-#print ws.row_gut_width
-#print ws.col_gut_height
-print ws.show_auto_page_breaks
-print ws.dialogue_sheet
-print ws.auto_style_outline
-print ws.outline_below
-print ws.outline_right
-print ws.fit_num_pages
-print ws.show_row_outline
-print ws.show_col_outline
-print ws.alt_expr_eval
-print ws.alt_formula_entries
-print ws.row_default_height
-print ws.col_default_width
-print ws.calc_mode
-print ws.calc_count
-print ws.RC_ref_mode
-print ws.iterations_on
-print ws.delta
-print ws.save_recalc
-print ws.print_headers
-print ws.print_grid
-#print ws.grid_set
-print ws.vert_page_breaks
-print ws.horz_page_breaks
-print ws.header_str
-print ws.footer_str
-print ws.print_centered_vert
-print ws.print_centered_horz
-print ws.left_margin
-print ws.right_margin
-print ws.top_margin
-print ws.bottom_margin
-print ws.paper_size_code
-print ws.print_scaling
-print ws.start_page_number
-print ws.fit_width_to_pages
-print ws.fit_height_to_pages
-print ws.print_in_rows
-print ws.portrait
-print ws.print_colour
-print ws.print_draft
-print ws.print_notes
-print ws.print_notes_at_end
-print ws.print_omit_errors
-print ws.print_hres
-print ws.print_vres
-print ws.header_margin
-print ws.footer_margin
-print ws.copies_num
diff --git a/tablib/packages/xlwt/examples/xlwt_easyxf_simple_demo.py b/tablib/packages/xlwt/examples/xlwt_easyxf_simple_demo.py
deleted file mode 100644
index 2afa69f..0000000
--- a/tablib/packages/xlwt/examples/xlwt_easyxf_simple_demo.py
+++ /dev/null
@@ -1,46 +0,0 @@
-
-# Write an XLS file with a single worksheet, containing
-# a heading row and some rows of data.
-
-import xlwt
-import datetime
-ezxf = xlwt.easyxf
-
-def write_xls(file_name, sheet_name, headings, data, heading_xf, data_xfs):
- book = xlwt.Workbook()
- sheet = book.add_sheet(sheet_name)
- rowx = 0
- for colx, value in enumerate(headings):
- sheet.write(rowx, colx, value, heading_xf)
- sheet.set_panes_frozen(True) # frozen headings instead of split panes
- sheet.set_horz_split_pos(rowx+1) # in general, freeze after last heading row
- sheet.set_remove_splits(True) # if user does unfreeze, don't leave a split there
- for row in data:
- rowx += 1
- for colx, value in enumerate(row):
- sheet.write(rowx, colx, value, data_xfs[colx])
- book.save(file_name)
-
-if __name__ == '__main__':
- import sys
- mkd = datetime.date
- hdngs = ['Date', 'Stock Code', 'Quantity', 'Unit Price', 'Value', 'Message']
- kinds = 'date text int price money text'.split()
- data = [
- [mkd(2007, 7, 1), 'ABC', 1000, 1.234567, 1234.57, ''],
- [mkd(2007, 12, 31), 'XYZ', -100, 4.654321, -465.43, 'Goods returned'],
- ] + [
- [mkd(2008, 6, 30), 'PQRCD', 100, 2.345678, 234.57, ''],
- ] * 100
-
- heading_xf = ezxf('font: bold on; align: wrap on, vert centre, horiz center')
- kind_to_xf_map = {
- 'date': ezxf(num_format_str='yyyy-mm-dd'),
- 'int': ezxf(num_format_str='#,##0'),
- 'money': ezxf('font: italic on; pattern: pattern solid, fore-colour grey25',
- num_format_str='$#,##0.00'),
- 'price': ezxf(num_format_str='#0.000000'),
- 'text': ezxf(),
- }
- data_xfs = [kind_to_xf_map[k] for k in kinds]
- write_xls('xlwt_easyxf_simple_demo.xls', 'Demo', hdngs, data, heading_xf, data_xfs)
diff --git a/tablib/packages/xlwt/excel-formula.g b/tablib/packages/xlwt/excel-formula.g
deleted file mode 100644
index d98d9b9..0000000
--- a/tablib/packages/xlwt/excel-formula.g
+++ /dev/null
@@ -1,374 +0,0 @@
-header {
- import struct
- import Utils
- from UnicodeUtils import upack1
- from ExcelMagic import *
-
- _RVAdelta = {"R": 0, "V": 0x20, "A": 0x40}
- _RVAdeltaRef = {"R": 0, "V": 0x20, "A": 0x40, "D": 0x20}
- _RVAdeltaArea = {"R": 0, "V": 0x20, "A": 0x40, "D": 0}
-
-
- class FormulaParseException(Exception):
- """
- An exception indicating that a Formula could not be successfully parsed.
- """
-}
-
-header "ExcelFormulaParser.__init__" {
- self.rpn = ""
- self.sheet_references = []
- self.xcall_references = []
-}
-
-options {
- language = "Python";
-}
-
-class ExcelFormulaParser extends Parser;
-options {
- k = 2;
- defaultErrorHandler = false;
- buildAST = false;
-}
-
-
-tokens {
- TRUE_CONST;
- FALSE_CONST;
- STR_CONST;
- NUM_CONST;
- INT_CONST;
-
- FUNC_IF;
- FUNC_CHOOSE;
- NAME;
- QUOTENAME;
-
- EQ;
- NE;
- GT;
- LT;
- GE;
- LE;
-
- ADD;
- SUB;
- MUL;
- DIV;
-
- POWER;
- PERCENT;
-
- LP;
- RP;
-
- LB;
- RB;
-
- COLON;
- COMMA;
- SEMICOLON;
- REF2D;
- REF2D_R1C1;
- BANG;
-}
-
-formula
- : expr["V"]
- ;
-
-expr[arg_type]
- : // {print "\n**expr %s" % arg_type}
- prec0_expr[arg_type]
- (
- (
- EQ { op = struct.pack('B', ptgEQ) }
- | NE { op = struct.pack('B', ptgNE) }
- | GT { op = struct.pack('B', ptgGT) }
- | LT { op = struct.pack('B', ptgLT) }
- | GE { op = struct.pack('B', ptgGE) }
- | LE { op = struct.pack('B', ptgLE) }
- )
- prec0_expr[arg_type] { self.rpn += op }
- )*
- ;
-
-prec0_expr[arg_type]
- : prec1_expr[arg_type]
- (
- (
- CONCAT { op = struct.pack('B', ptgConcat) }
- )
- prec1_expr[arg_type] { self.rpn += op }
- )*
- ;
-
-prec1_expr[arg_type]
- : // {print "**prec1_expr1 %s" % arg_type}
- prec2_expr[arg_type]
- // {print "**prec1_expr2 %s" % arg_type}
- (
- (
- ADD { op = struct.pack('B', ptgAdd) }
- | SUB { op = struct.pack('B', ptgSub) }
- )
- // {print "**prec1_expr3 %s" % arg_type}
- prec2_expr[arg_type]
- { self.rpn += op;
- // print "**prec1_expr4 %s" % arg_type
- }
- )*
- ;
-
-
-prec2_expr[arg_type]
- : prec3_expr[arg_type]
- (
- (
- MUL { op = struct.pack('B', ptgMul) }
- | DIV { op = struct.pack('B', ptgDiv) }
- )
- prec3_expr[arg_type] { self.rpn += op }
- )*
- ;
-
-prec3_expr[arg_type]
- : prec4_expr[arg_type]
- (
- (
- POWER { op = struct.pack('B', ptgPower) }
- )
- prec4_expr[arg_type] { self.rpn += op }
- )*
- ;
-
-prec4_expr[arg_type]
- : prec5_expr[arg_type]
- (
- PERCENT { self.rpn += struct.pack('B', ptgPercent) }
- )?
- ;
-
-prec5_expr[arg_type]
- : primary[arg_type]
- | SUB primary[arg_type] { self.rpn += struct.pack('B', ptgUminus) }
- ;
-
-primary[arg_type]
- : TRUE_CONST
- {
- self.rpn += struct.pack("2B", ptgBool, 1)
- }
- | FALSE_CONST
- {
- self.rpn += struct.pack("2B", ptgBool, 0)
- }
- | str_tok:STR_CONST
- {
- self.rpn += struct.pack("B", ptgStr) + upack1(str_tok.text[1:-1].replace("\"\"", "\""))
- }
- | int_tok:INT_CONST
- {
- // print "**int_const", int_tok.text
- int_value = int(int_tok.text)
- if int_value <= 65535:
- self.rpn += struct.pack("<BH", ptgInt, int_value)
- else:
- self.rpn += struct.pack("<Bd", ptgNum, float(int_value))
- }
- | num_tok:NUM_CONST
- {
- self.rpn += struct.pack("<Bd", ptgNum, float(num_tok.text))
- }
- | ref2d_tok:REF2D
- {
- // print "**ref2d %s %s" % (ref2d_tok.text, arg_type)
- r, c = Utils.cell_to_packed_rowcol(ref2d_tok.text)
- ptg = ptgRefR + _RVAdeltaRef[arg_type]
- self.rpn += struct.pack("<B2H", ptg, r, c)
- }
- | ref2d1_tok:REF2D COLON ref2d2_tok:REF2D
- {
- r1, c1 = Utils.cell_to_packed_rowcol(ref2d1_tok.text)
- r2, c2 = Utils.cell_to_packed_rowcol(ref2d2_tok.text)
- ptg = ptgAreaR + _RVAdeltaArea[arg_type]
- self.rpn += struct.pack("<B4H", ptg, r1, r2, c1, c2)
- }
- | sheet1 = sheet
- {
- sheet2 = sheet1
- }
- ( COLON sheet2 = sheet )? BANG ref3d_ref2d: REF2D
- {
- ptg = ptgRef3dR + _RVAdeltaRef[arg_type]
- rpn_ref2d = ""
- r1, c1 = Utils.cell_to_packed_rowcol(ref3d_ref2d.text)
- rpn_ref2d = struct.pack("<3H", 0x0000, r1, c1)
- }
- ( COLON ref3d_ref2d2: REF2D
- {
- ptg = ptgArea3dR + _RVAdeltaArea[arg_type]
- r2, c2 = Utils.cell_to_packed_rowcol(ref3d_ref2d2.text)
- rpn_ref2d = struct.pack("<5H", 0x0000, r1, r2, c1, c2)
- }
- )?
- {
- self.rpn += struct.pack("<B", ptg)
- self.sheet_references.append((sheet1, sheet2, len(self.rpn)))
- self.rpn += rpn_ref2d
- }
- | FUNC_IF
- LP expr["V"] (SEMICOLON | COMMA)
- {
- self.rpn += struct.pack("<BBH", ptgAttr, 0x02, 0) // tAttrIf
- pos0 = len(self.rpn) - 2
- }
- expr[arg_type] (SEMICOLON | COMMA)
- {
- self.rpn += struct.pack("<BBH", ptgAttr, 0x08, 0) // tAttrSkip
- pos1 = len(self.rpn) - 2
- self.rpn = self.rpn[:pos0] + struct.pack("<H", pos1-pos0) + self.rpn[pos0+2:]
- }
- expr[arg_type] RP
- {
- self.rpn += struct.pack("<BBH", ptgAttr, 0x08, 3) // tAttrSkip
- self.rpn += struct.pack("<BBH", ptgFuncVarR, 3, 1) // 3 = nargs, 1 = IF func
- pos2 = len(self.rpn)
- self.rpn = self.rpn[:pos1] + struct.pack("<H", pos2-(pos1+2)-1) + self.rpn[pos1+2:]
- }
- | FUNC_CHOOSE
- {
- arg_type = "R"
- rpn_chunks = []
- }
- LP expr["V"] // first argument (the selector)
- {
- rpn_start = len(self.rpn)
- ref_markers = [len(self.sheet_references)]
- }
- (
- (SEMICOLON | COMMA)
- { mark = len(self.rpn) }
- (
- expr[arg_type]
- | { self.rpn += struct.pack("B", ptgMissArg) }
- )
- {
- rpn_chunks.append(self.rpn[mark:])
- ref_markers.append(len(self.sheet_references))
- }
- )*
- RP
- {
- self.rpn = self.rpn[:rpn_start]
- nc = len(rpn_chunks)
- chunklens = [len(chunk) for chunk in rpn_chunks]
- skiplens = [0] * nc
- skiplens[-1] = 3
- for ic in xrange(nc-1, 0, -1):
- skiplens[ic-1] = skiplens[ic] + chunklens[ic] + 4
- jump_pos = [2 * nc + 2]
- for ic in xrange(nc):
- jump_pos.append(jump_pos[-1] + chunklens[ic] + 4)
- chunk_shift = 2 * nc + 6 // size of tAttrChoose
- for ic in xrange(nc):
- for refx in xrange(ref_markers[ic], ref_markers[ic+1]):
- ref = self.sheet_references[refx]
- self.sheet_references[refx] = (ref[0], ref[1], ref[2] + chunk_shift)
- chunk_shift += 4 // size of tAttrSkip
- choose_rpn = []
- choose_rpn.append(struct.pack("<BBH", ptgAttr, 0x04, nc)) // 0x04 is tAttrChoose
- choose_rpn.append(struct.pack("<%dH" % (nc+1), *jump_pos))
- for ic in xrange(nc):
- choose_rpn.append(rpn_chunks[ic])
- choose_rpn.append(struct.pack("<BBH", ptgAttr, 0x08, skiplens[ic])) // 0x08 is tAttrSkip
- choose_rpn.append(struct.pack("<BBH", ptgFuncVarV, nc+1, 100)) // 100 is CHOOSE fn
- self.rpn += "".join(choose_rpn)
- }
- | name_tok:NAME
- {
- raise Exception("[formula] found unexpected NAME token (%r)" % name_tok.txt)
- // #### TODO: handle references to defined names here
- }
- | func_tok:NAME
- {
- func_toku = func_tok.text.upper()
- if func_toku in all_funcs_by_name:
- (opcode,
- min_argc,
- max_argc,
- func_type,
- arg_type_str) = all_funcs_by_name[func_toku]
- arg_type_list = list(arg_type_str)
- else:
- raise Exception("[formula] unknown function (%s)" % func_tok.text)
- // print "**func_tok1 %s %s" % (func_toku, func_type)
- xcall = opcode < 0
- if xcall:
- // The name of the add-in function is passed as the 1st arg
- // of the hidden XCALL function
- self.xcall_references.append((func_toku, len(self.rpn) + 1))
- self.rpn += struct.pack("<BHHH",
- ptgNameXR,
- 0xadde, // ##PATCHME## index to REF entry in EXTERNSHEET record
- 0xefbe, // ##PATCHME## one-based index to EXTERNNAME record
- 0x0000) // unused
- }
- LP arg_count = expr_list[arg_type_list, min_argc, max_argc] RP
- {
- if arg_count > max_argc or arg_count < min_argc:
- raise Exception, "%d parameters for function: %s" % (arg_count, func_tok.text)
- if xcall:
- func_ptg = ptgFuncVarR + _RVAdelta[func_type]
- self.rpn += struct.pack("<2BH", func_ptg, arg_count + 1, 255) // 255 is magic XCALL function
- elif min_argc == max_argc:
- func_ptg = ptgFuncR + _RVAdelta[func_type]
- self.rpn += struct.pack("<BH", func_ptg, opcode)
- elif arg_count == 1 and func_tok.text.upper() == "SUM":
- self.rpn += struct.pack("<BBH", ptgAttr, 0x10, 0) // tAttrSum
- else:
- func_ptg = ptgFuncVarR + _RVAdelta[func_type]
- self.rpn += struct.pack("<2BH", func_ptg, arg_count, opcode)
- }
- | LP expr[arg_type] RP
- {
- self.rpn += struct.pack("B", ptgParen)
- }
- ;
-
-expr_list[arg_type_list, min_argc, max_argc] returns [arg_cnt]
- {
- arg_cnt = 0
- arg_type = arg_type_list[arg_cnt]
- // print "**expr_list1[%d] req=%s" % (arg_cnt, arg_type)
- }
- : expr[arg_type] { arg_cnt += 1 }
- (
- {
- if arg_cnt < len(arg_type_list):
- arg_type = arg_type_list[arg_cnt]
- else:
- arg_type = arg_type_list[-1]
- if arg_type == "+":
- arg_type = arg_type_list[-2]
- // print "**expr_list2[%d] req=%s" % (arg_cnt, arg_type)
- }
- (SEMICOLON | COMMA)
- (
- expr[arg_type]
- | { self.rpn += struct.pack("B", ptgMissArg) }
- )
- { arg_cnt += 1 }
- )*
- |
- ;
-
-sheet returns[ref]
- : sheet_ref_name: NAME
- { ref = sheet_ref_name.text }
- | sheet_ref_int: INT_CONST
- { ref = sheet_ref_int.text }
- | sheet_ref_quote: QUOTENAME
- { ref = sheet_ref_quote.text[1:-1].replace("''", "'") }
- ;
diff --git a/tablib/packages/xlwt3/BIFFRecords.py b/tablib/packages/xlwt3/BIFFRecords.py
deleted file mode 100644
index 39a9554..0000000
--- a/tablib/packages/xlwt3/BIFFRecords.py
+++ /dev/null
@@ -1,2392 +0,0 @@
-from struct import pack
-from .UnicodeUtils import upack1, upack2
-import sys
-
-class SharedStringTable(object):
- _SST_ID = 0x00FC
- _CONTINUE_ID = 0x003C
-
- def __init__(self, encoding):
- self.encoding = encoding
- self._str_indexes = {}
- self._tally = []
- self._add_calls = 0
- # Following 3 attrs are used for temporary storage in the
- # get_biff_record() method and methods called by it. The pseudo-
- # initialisation here is for documentation purposes only.
- self._sst_record = None
- self._continues = None
- self._current_piece = None
-
- def add_str(self, s):
- if self.encoding != 'ascii' and not isinstance(s, str):
- s = str(s, self.encoding)
- self._add_calls += 1
- if s not in self._str_indexes:
- idx = len(self._str_indexes)
- self._str_indexes[s] = idx
- self._tally.append(1)
- else:
- idx = self._str_indexes[s]
- self._tally[idx] += 1
- return idx
-
- def del_str(self, idx):
- # This is called when we are replacing the contents of a string cell.
- assert self._tally[idx] > 0
- self._tally[idx] -= 1
- self._add_calls -= 1
-
- def str_index(self, s):
- return self._str_indexes[s]
-
- def get_biff_record(self):
- self._sst_record = b''
- self._continues = [None, None]
- self._current_piece = pack('<II', 0, 0)
- data = [(idx, s) for s, idx in list(self._str_indexes.items())]
- data.sort() # in index order
- for idx, s in data:
- if self._tally[idx] == 0:
- s = b''
- self._add_to_sst(s)
- del data
- self._new_piece()
- self._continues[0] = pack('<2HII', self._SST_ID, len(self._sst_record), self._add_calls, len(self._str_indexes))
- self._continues[1] = self._sst_record[8:]
- self._sst_record = None
- self._current_piece = None
- result = b''.join(self._continues)
- self._continues = None
- return result
-
-
- def _add_to_sst(self, s):
- u_str = upack2(s, self.encoding)
- # (to_py3): added b'...'
- is_unicode_str = u_str[2] == b'\x01'
- if is_unicode_str:
- atom_len = 5 # 2 byte -- len,
- # 1 byte -- options,
- # 2 byte -- 1st sym
- else:
- atom_len = 4 # 2 byte -- len,
- # 1 byte -- options,
- # 1 byte -- 1st sym
-
- self._save_atom(u_str[0:atom_len])
- self._save_splitted(u_str[atom_len:], is_unicode_str)
-
- def _new_piece(self):
- if self._sst_record == b'':
- self._sst_record = self._current_piece
- else:
- curr_piece_len = len(self._current_piece)
- self._continues.append(pack('<2H%ds'%curr_piece_len, self._CONTINUE_ID, curr_piece_len, self._current_piece))
- self._current_piece = b''
-
- def _save_atom(self, s):
- atom_len = len(s)
- free_space = 0x2020 - len(self._current_piece)
- if free_space < atom_len:
- self._new_piece()
- self._current_piece += s
-
- def _save_splitted(self, s, is_unicode_str):
- i = 0
- str_len = len(s)
- while i < str_len:
- piece_len = len(self._current_piece)
- free_space = 0x2020 - piece_len
- tail_len = str_len - i
- need_more_space = free_space < tail_len
-
- if not need_more_space:
- atom_len = tail_len
- else:
- if is_unicode_str:
- atom_len = free_space & 0xFFFE
- else:
- atom_len = free_space
-
- self._current_piece += s[i:i+atom_len]
-
- if need_more_space:
- self._new_piece()
- if is_unicode_str:
- self._current_piece += b'\x01' # (to_py3): added b'...'
- else:
- self._current_piece += b'\x00' # (to_py3): added b'...'
-
- i += atom_len
-
-
-class BiffRecord(object):
-
- _rec_data = b'' # class attribute; child classes need to set this.
-
- # Sheer waste.
- # def __init__(self):
- # self._rec_data = ''
-
- def get_rec_id(self):
- return _REC_ID
-
- def get_rec_header(self):
- return pack('<2H', self._REC_ID, len(self._rec_data))
-
- # Not over-ridden by any child classes, never called (except by "get"; see below).
- # def get_rec_data(self):
- # return self._rec_data
-
- def get(self):
- # data = self.get_rec_data()
- data = self._rec_data
-
- if len(data) > 0x2020: # limit for BIFF7/8
- chunks = []
- pos = 0
- while pos < len(data):
- chunk_pos = pos + 0x2020
- chunk = data[pos:chunk_pos]
- chunks.append(chunk)
- pos = chunk_pos
- continues = pack('<2H', self._REC_ID, len(chunks[0])) + chunks[0]
- for chunk in chunks[1:]:
- continues += pack('<2H%ds'%len(chunk), 0x003C, len(chunk), chunk)
- # 0x003C -- CONTINUE record id
- return continues
- else:
- return self.get_rec_header() + data
-
-
-class Biff8BOFRecord(BiffRecord):
- """
- Offset Size Contents
- 0 2 Version, contains 0600H for BIFF8 and BIFF8X
- 2 2 Type of the following data:
- 0005H = Workbook globals
- 0006H = Visual Basic module
- 0010H = Worksheet
- 0020H = Chart
- 0040H = Macro sheet
- 0100H = Workspace file
- 4 2 Build identifier
- 6 2 Build year
- 8 4 File history flags
- 12 4 Lowest Excel version that can read all records in this file
- """
- _REC_ID = 0x0809
- # stream types
- BOOK_GLOBAL = 0x0005
- VB_MODULE = 0x0006
- WORKSHEET = 0x0010
- CHART = 0x0020
- MACROSHEET = 0x0040
- WORKSPACE = 0x0100
-
- def __init__(self, rec_type):
- version = 0x0600
- build = 0x0DBB
- year = 0x07CC
- file_hist_flags = 0x00
- ver_can_read = 0x06
-
- self._rec_data = pack('<4H2I', version, rec_type, build, year, file_hist_flags, ver_can_read)
-
-
-class InteraceHdrRecord(BiffRecord):
- _REC_ID = 0x00E1
-
- def __init__(self):
- self._rec_data = pack('BB', 0xB0, 0x04)
-
-
-class InteraceEndRecord(BiffRecord):
- _REC_ID = 0x00E2
-
- def __init__(self):
- self._rec_data = b''
-
-
-class MMSRecord(BiffRecord):
- _REC_ID = 0x00C1
-
- def __init__(self):
- self._rec_data = pack('<H', 0x00)
-
-
-class WriteAccessRecord(BiffRecord):
- """
- This record is part of the file protection. It contains the name of the
- user that has saved the file. The user name is always stored as an
- equal-sized string. All unused characters after the name are filled
- with space characters. It is not required to write the mentioned string
- length. Every other length will be accepted too.
- """
- _REC_ID = 0x005C
-
- def __init__(self, owner):
- uowner = owner[0:0x30]
- uowner_len = len(uowner)
- self._rec_data = pack(bytes('%ds%ds' % (uowner_len, 0x70 - uowner_len), encoding='utf8'), bytes(uowner, encoding='utf8'), b' '*(0x70 - uowner_len)) # (to_py3): added b'...'
- # self._rec_data = (b'%ds%ds' % (uowner_len, 0x70 - uowner_len), uowner, b' '*(0x70 - uowner_len)) # (to_py3): added b'...'
-
-
-class DSFRecord(BiffRecord):
- """
- This record specifies if the file contains an additional BIFF5/BIFF7
- workbook stream.
- Record DSF, BIFF8:
- Offset Size Contents
- 0 2 0 = Only the BIFF8 Workbook stream is present
- 1 = Additional BIFF5/BIFF7 Book stream is in the file
- A double stream file can be read by Excel 5.0 and Excel 95, and still
- contains all new features added to BIFF8 (which are left out in the
- BIFF5/BIFF7 Book stream).
- """
- _REC_ID = 0x0161
-
- def __init__(self):
- self._rec_data = pack('<H', 0x00)
-
-
-class TabIDRecord(BiffRecord):
- _REC_ID = 0x013D
-
- def __init__(self, sheetcount):
- for i in range(sheetcount):
- self._rec_data += pack('<H', i+1)
-
-
-class FnGroupCountRecord(BiffRecord):
- _REC_ID = 0x009C
-
- def __init__(self):
- self._rec_data = pack('BB', 0x0E, 0x00)
-
-
-class WindowProtectRecord(BiffRecord):
- """
- This record is part of the worksheet/workbook protection. It determines
- whether the window configuration of this document is protected. Window
- protection is not active, if this record is omitted.
- """
- _REC_ID = 0x0019
-
- def __init__(self, wndprotect):
- self._rec_data = pack('<H', wndprotect)
-
-
-class ObjectProtectRecord(BiffRecord):
- """
- This record is part of the worksheet/workbook protection.
- It determines whether the objects of the current sheet are protected.
- Object protection is not active, if this record is omitted.
- """
- _REC_ID = 0x0063
-
-
- def __init__(self, objprotect):
- self._rec_data = pack('<H', objprotect)
-
-
-class ScenProtectRecord(BiffRecord):
- """
- This record is part of the worksheet/workbook protection. It
- determines whether the scenarios of the current sheet are protected.
- Scenario protection is not active, if this record is omitted.
- """
- _REC_ID = 0x00DD
-
-
- def __init__(self, scenprotect):
- self._rec_data = pack('<H', scenprotect)
-
-
-class ProtectRecord(BiffRecord):
- """
- This record is part of the worksheet/workbook protection. It specifies
- whether a worksheet or a workbook is protected against modification.
- Protection is not active, if this record is omitted.
- """
-
- _REC_ID = 0x0012
-
- def __init__(self, protect):
- self._rec_data = pack('<H', protect)
-
-
-class PasswordRecord(BiffRecord):
- """
- This record is part of the worksheet/workbook protection. It
- stores a 16-bit hash value, calculated from the worksheet or workbook
- protection password.
- """
- _REC_ID = 0x0013
- def passwd_hash(self, plaintext):
- """
- Based on the algorithm provided by Daniel Rentz of OpenOffice.
- """
- if plaintext == b"":
- return 0
-
- passwd_hash = 0x0000
- for i, char in enumerate(plaintext):
- c = ord(char) << (i + 1)
- low_15 = c & 0x7fff
- high_15 = c & 0x7fff << 15
- high_15 = high_15 >> 15
- c = low_15 | high_15
- passwd_hash ^= c
- passwd_hash ^= len(plaintext)
- passwd_hash ^= 0xCE4B
- return passwd_hash
-
- def __init__(self, passwd = b""):
- self._rec_data = pack('<H', self.passwd_hash(passwd))
-
-
-class Prot4RevRecord(BiffRecord):
- _REC_ID = 0x01AF
-
- def __init__(self):
- self._rec_data = pack('<H', 0x00)
-
-
-class Prot4RevPassRecord(BiffRecord):
- _REC_ID = 0x01BC
-
- def __init__(self):
- self._rec_data = pack('<H', 0x00)
-
-
-class BackupRecord(BiffRecord):
- """
- This record contains a Boolean value determining whether Excel makes
- a backup of the file while saving.
- """
- _REC_ID = 0x0040
-
- def __init__(self, backup):
- self._rec_data = pack('<H', backup)
-
-class HideObjRecord(BiffRecord):
- """
- This record specifies whether and how to show objects in the workbook.
-
- Record HIDEOBJ, BIFF3-BIFF8:
- Offset Size Contents
- 0 2 Viewing mode for objects:
- 0 = Show all objects
- 1 = Show placeholders
- 2 = Do not show objects
- """
- _REC_ID = 0x008D
-
- def __init__(self):
- self._rec_data = pack('<H', 0x00)
-
-
-
-class RefreshAllRecord(BiffRecord):
- """
- """
-
- _REC_ID = 0x01B7
-
- def __init__(self):
- self._rec_data = pack('<H', 0x00)
-
-
-class BookBoolRecord(BiffRecord):
- """
- This record contains a Boolean value determining whether to save values
- linked from external workbooks (CRN records and XCT records). In BIFF3
- and BIFF4 this option is stored in the WSBOOL record.
-
- Record BOOKBOOL, BIFF5-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Save external linked values;
- 1 = Do not save external linked values
- """
-
- _REC_ID = 0x00DA
-
- def __init__(self):
- self._rec_data = pack('<H', 0x00)
-
-
-class CountryRecord(BiffRecord):
- """
- This record stores two Windows country identifiers. The first
- represents the user interface language of the Excel version that has
- saved the file, and the second represents the system regional settings
- at the time the file was saved.
-
- Record COUNTRY, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 Windows country identifier of the user interface language of Excel
- 2 2 Windows country identifier of the system regional settings
-
- The following table shows most of the used country identifiers. Most
- of these identifiers are equal to the international country calling
- codes.
-
- 1 USA
- 2 Canada
- 7 Russia
- """
-
- _REC_ID = 0x008C
-
- def __init__(self, ui_id, sys_settings_id):
- self._rec_data = pack('<2H', ui_id, sys_settings_id)
-
-
-class UseSelfsRecord(BiffRecord):
- """
- This record specifies if the formulas in the workbook can use natural
- language formulas. This type of formula can refer to cells by its
- content or the content of the column or row header cell.
-
- Record USESELFS, BIFF8:
-
- Offset Size Contents
- 0 2 0 = Do not use natural language formulas
- 1 = Use natural language formulas
-
- """
-
- _REC_ID = 0x0160
-
- def __init__(self):
- self._rec_data = pack('<H', 0x01)
-
-
-class EOFRecord(BiffRecord):
- _REC_ID = 0x000A
-
- def __init__(self):
- self._rec_data = b''
-
-
-class DateModeRecord(BiffRecord):
- """
- This record specifies the base date for displaying date values. All
- dates are stored as count of days past this base date. In BIFF2-BIFF4
- this record is part of the Calculation Settings Block.
- In BIFF5-BIFF8 it is stored in the Workbook Globals Substream.
-
- Record DATEMODE, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Base is 1899-Dec-31 (the cell = 1 represents 1900-Jan-01)
- 1 = Base is 1904-Jan-01 (the cell = 1 represents 1904-Jan-02)
- """
- _REC_ID = 0x0022
-
- def __init__(self, from1904):
- if from1904:
- self._rec_data = pack('<H', 1)
- else:
- self._rec_data = pack('<H', 0)
-
-
-class PrecisionRecord(BiffRecord):
- """
- This record stores if formulas use the real cell values for calculation
- or the values displayed on the screen. In BIFF2- BIFF4 this record
- is part of the Calculation Settings Block. In BIFF5-BIFF8 it is stored
- in the Workbook Globals Substream.
-
- Record PRECISION, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Use displayed values;
- 1 = Use real cell values
- """
- _REC_ID = 0x000E
-
- def __init__(self, use_real_values):
- if use_real_values:
- self._rec_data = pack('<H', 1)
- else:
- self._rec_data = pack('<H', 0)
-
-
-class CodepageBiff8Record(BiffRecord):
- """
- This record stores the text encoding used to write byte strings, stored
- as MS Windows code page identifier. The CODEPAGE record in BIFF8 always
- contains the code page 1200 (UTF-16). Therefore it is not
- possible to obtain the encoding used for a protection password (it is
- not UTF-16).
-
- Record CODEPAGE, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 Code page identifier used for byte string text encoding:
- 016FH = 367 = ASCII
- 01B5H = 437 = IBM PC CP-437 (US)
- 02D0H = 720 = IBM PC CP-720 (OEM Arabic)
- 02E1H = 737 = IBM PC CP-737 (Greek)
- 0307H = 775 = IBM PC CP-775 (Baltic)
- 0352H = 850 = IBM PC CP-850 (Latin I)
- 0354H = 852 = IBM PC CP-852 (Latin II (Central European))
- 0357H = 855 = IBM PC CP-855 (Cyrillic)
- 0359H = 857 = IBM PC CP-857 (Turkish)
- 035AH = 858 = IBM PC CP-858 (Multilingual Latin I with Euro)
- 035CH = 860 = IBM PC CP-860 (Portuguese)
- 035DH = 861 = IBM PC CP-861 (Icelandic)
- 035EH = 862 = IBM PC CP-862 (Hebrew)
- 035FH = 863 = IBM PC CP-863 (Canadian (French))
- 0360H = 864 = IBM PC CP-864 (Arabic)
- 0361H = 865 = IBM PC CP-865 (Nordic)
- 0362H = 866 = IBM PC CP-866 (Cyrillic (Russian))
- 0365H = 869 = IBM PC CP-869 (Greek (Modern))
- 036AH = 874 = Windows CP-874 (Thai)
- 03A4H = 932 = Windows CP-932 (Japanese Shift-JIS)
- 03A8H = 936 = Windows CP-936 (Chinese Simplified GBK)
- 03B5H = 949 = Windows CP-949 (Korean (Wansung))
- 03B6H = 950 = Windows CP-950 (Chinese Traditional BIG5)
- 04B0H = 1200 = UTF-16 (BIFF8)
- 04E2H = 1250 = Windows CP-1250 (Latin II) (Central European)
- 04E3H = 1251 = Windows CP-1251 (Cyrillic)
- 04E4H = 1252 = Windows CP-1252 (Latin I) (BIFF4-BIFF7)
- 04E5H = 1253 = Windows CP-1253 (Greek)
- 04E6H = 1254 = Windows CP-1254 (Turkish)
- 04E7H = 1255 = Windows CP-1255 (Hebrew)
- 04E8H = 1256 = Windows CP-1256 (Arabic)
- 04E9H = 1257 = Windows CP-1257 (Baltic)
- 04EAH = 1258 = Windows CP-1258 (Vietnamese)
- 0551H = 1361 = Windows CP-1361 (Korean (Johab))
- 2710H = 10000 = Apple Roman
- 8000H = 32768 = Apple Roman
- 8001H = 32769 = Windows CP-1252 (Latin I) (BIFF2-BIFF3)
- """
- _REC_ID = 0x0042
- UTF_16 = 0x04B0
-
- def __init__(self):
- self._rec_data = pack('<H', self.UTF_16)
-
-class Window1Record(BiffRecord):
- """
- Offset Size Contents
- 0 2 Horizontal position of the document window (in twips = 1/20 of a point)
- 2 2 Vertical position of the document window (in twips = 1/20 of a point)
- 4 2 Width of the document window (in twips = 1/20 of a point)
- 6 2 Height of the document window (in twips = 1/20 of a point)
- 8 2 Option flags:
- Bits Mask Contents
- 0 0001H 0 = Window is visible 1 = Window is hidden
- 1 0002H 0 = Window is open 1 = Window is minimised
- 3 0008H 0 = Horizontal scroll bar hidden 1 = Horizontal scroll bar visible
- 4 0010H 0 = Vertical scroll bar hidden 1 = Vertical scroll bar visible
- 5 0020H 0 = Worksheet tab bar hidden 1 = Worksheet tab bar visible
- 10 2 Index to active (displayed) worksheet
- 12 2 Index of first visible tab in the worksheet tab bar
- 14 2 Number of selected worksheets (highlighted in the worksheet tab bar)
- 16 2 Width of worksheet tab bar (in 1/1000 of window width). The remaining space is used by the
- horizontal scrollbar.
- """
- _REC_ID = 0x003D
- # flags
-
- def __init__(self,
- hpos_twips, vpos_twips,
- width_twips, height_twips,
- flags,
- active_sheet,
- first_tab_index, selected_tabs, tab_width):
- self._rec_data = pack('<9H', hpos_twips, vpos_twips,
- width_twips, height_twips,
- flags,
- active_sheet,
- first_tab_index, selected_tabs, tab_width)
-
-class FontRecord(BiffRecord):
- """
- WARNING
- The font with index 4 is omitted in all BIFF versions.
- This means the first four fonts have zero-based indexes, and
- the fifth font and all following fonts are referenced with one-based
- indexes.
-
- Offset Size Contents
- 0 2 Height of the font (in twips = 1/20 of a point)
- 2 2 Option flags:
- Bit Mask Contents
- 0 0001H 1 = Characters are bold (redundant, see below)
- 1 0002H 1 = Characters are italic
- 2 0004H 1 = Characters are underlined (redundant, see below)
- 3 0008H 1 = Characters are struck out
- 0010H 1 = Outline
- 0020H 1 = Shadow
- 4 2 Colour index
- 6 2 Font weight (100-1000).
- Standard values are 0190H (400) for normal text and 02BCH
- (700) for bold text.
- 8 2 Escapement type:
- 0000H = None
- 0001H = Superscript
- 0002H = Subscript
- 10 1 Underline type:
- 00H = None
- 01H = Single
- 21H = Single accounting
- 02H = Double
- 22H = Double accounting
- 11 1 Font family:
- 00H = None (unknown or don't care)
- 01H = Roman (variable width, serifed)
- 02H = Swiss (variable width, sans-serifed)
- 03H = Modern (fixed width, serifed or sans-serifed)
- 04H = Script (cursive)
- 05H = Decorative (specialised, i.e. Old English, Fraktur)
- 12 1 Character set:
- 00H = 0 = ANSI Latin
- 01H = 1 = System default
- 02H = 2 = Symbol
- 4DH = 77 = Apple Roman
- 80H = 128 = ANSI Japanese Shift-JIS
- 81H = 129 = ANSI Korean (Hangul)
- 82H = 130 = ANSI Korean (Johab)
- 86H = 134 = ANSI Chinese Simplified GBK
- 88H = 136 = ANSI Chinese Traditional BIG5
- A1H = 161 = ANSI Greek
- A2H = 162 = ANSI Turkish
- A3H = 163 = ANSI Vietnamese
- B1H = 177 = ANSI Hebrew
- B2H = 178 = ANSI Arabic
- BAH = 186 = ANSI Baltic
- CCH = 204 = ANSI Cyrillic
- DEH = 222 = ANSI Thai
- EEH = 238 = ANSI Latin II (Central European)
- FFH = 255 = OEM Latin I
- 13 1 Not used
- 14 var. Font name:
- BIFF5/BIFF7: Byte string, 8-bit string length
- BIFF8: Unicode string, 8-bit string length
- The boldness and underline flags are still set in the options field,
- but not used on reading the font. Font weight and underline type
- are specified in separate fields instead.
- """
- _REC_ID = 0x0031
-
- def __init__(self,
- height, options, colour_index, weight, escapement,
- underline, family, charset,
- name):
- uname = upack1(name)
- uname_len = len(uname)
-
- self._rec_data = pack('<5H4B%ds' % uname_len, height, options, colour_index, weight, escapement,
- underline, family, charset, 0x00,
- uname)
-
-class NumberFormatRecord(BiffRecord):
- """
- Record FORMAT, BIFF8:
- Offset Size Contents
- 0 2 Format index used in other records
- 2 var. Number format string (Unicode string, 16-bit string length)
-
- From BIFF5 on, the built-in number formats will be omitted. The built-in
- formats are dependent on the current regional settings of the operating
- system. The following table shows which number formats are used by default
- in a US-English environment. All indexes from 0 to 163 are reserved for
- built-in formats. The first user-defined format starts at 164.
-
- The built-in number formats, BIFF5-BIFF8
-
- Index Type Format string
- 0 General General
- 1 Decimal 0
- 2 Decimal 0.00
- 3 Decimal #,##0
- 4 Decimal #,##0.00
- 5 Currency "$"#,##0_);("$"#,##
- 6 Currency "$"#,##0_);[Red]("$"#,##
- 7 Currency "$"#,##0.00_);("$"#,##
- 8 Currency "$"#,##0.00_);[Red]("$"#,##
- 9 Percent 0%
- 10 Percent 0.00%
- 11 Scientific 0.00E+00
- 12 Fraction # ?/?
- 13 Fraction # ??/??
- 14 Date M/D/YY
- 15 Date D-MMM-YY
- 16 Date D-MMM
- 17 Date MMM-YY
- 18 Time h:mm AM/PM
- 19 Time h:mm:ss AM/PM
- 20 Time h:mm
- 21 Time h:mm:ss
- 22 Date/Time M/D/YY h:mm
- 37 Account _(#,##0_);(#,##0)
- 38 Account _(#,##0_);[Red](#,##0)
- 39 Account _(#,##0.00_);(#,##0.00)
- 40 Account _(#,##0.00_);[Red](#,##0.00)
- 41 Currency _("$"* #,##0_);_("$"* (#,##0);_("$"* "-"_);_(@_)
- 42 Currency _(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)
- 43 Currency _("$"* #,##0.00_);_("$"* (#,##0.00);_("$"* "-"??_);_(@_)
- 44 Currency _(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)
- 45 Time mm:ss
- 46 Time [h]:mm:ss
- 47 Time mm:ss.0
- 48 Scientific ##0.0E+0
- 49 Text @
- """
- _REC_ID = 0x041E
-
- def __init__(self, idx, fmtstr):
- ufmtstr = upack2(fmtstr)
- ufmtstr_len = len(ufmtstr)
-
- self._rec_data = pack('<H%ds' % ufmtstr_len, idx, ufmtstr)
-
-
-class XFRecord(BiffRecord):
- """
- XF Substructures
- -------------------------------------------------------------------------
- XF_TYPE_PROT XF Type and Cell Protection (3 Bits), BIFF3-BIFF8
- These 3 bits are part of a specific data byte.
- Bit Mask Contents
- 0 01H 1 = Cell is locked
- 1 02H 1 = Formula is hidden
- 2 04H 0 = Cell XF; 1 = Style XF
-
- XF_USED_ATTRIB Attributes Used from Parent Style XF (6 Bits),
- BIFF3-BIFF8 Each bit describes the validity of a specific group
- of attributes. In cell XFs a cleared bit means the attributes of the
- parent style XF are used (but only if the attributes are valid there),
- a set bit means the attributes of this XF are used. In style XFs
- a cleared bit means the attribute setting is valid, a set bit means the
- attribute should be ignored.
- Bit Mask Contents
- 0 01H Flag for number format
- 1 02H Flag for font
- 2 04H Flag for horizontal and vertical alignment, text wrap, indentation, orientation, rotation, and
- text direction
- 3 08H Flag for border lines
- 4 10H Flag for background area style
- 5 20H Flag for cell protection (cell locked and formula hidden)
-
- XF_HOR_ALIGN Horizontal Alignment (3 Bits), BIFF2-BIFF8 The horizontal
- alignment consists of 3 bits and is part of a specific data byte.
- Value Horizontal alignment
- 00H General
- 01H Left
- 02H Centred
- 03H Right
- 04H Filled
- 05H Justified (BIFF4-BIFF8X)
- 06H Centred across selection (BIFF4-BIFF8X)
- 07H Distributed (BIFF8X)
-
- XF_VERT_ALIGN Vertical Alignment (2 or 3 Bits), BIFF4-BIFF8
- The vertical alignment consists of 2 bits (BIFF4) or 3 bits (BIFF5-BIFF8)
- and is part of a specific data byte. Vertical alignment is not available
- in BIFF2 and BIFF3.
- Value Vertical alignment
- 00H Top
- 01H Centred
- 02H Bottom
- 03H Justified (BIFF5-BIFF8X)
- 04H Distributed (BIFF8X)
-
- XF_ORIENTATION Text Orientation (2 Bits), BIFF4-BIFF7 In the BIFF
- versions BIFF4-BIFF7, text can be rotated in steps of 90 degrees
- or stacked. The orientation mode consists of 2 bits and is part of
- a specific data byte. In BIFF8 a rotation angle occurs instead of these
- flags.
- Value Text orientation
- 00H Not rotated
- 01H Letters are stacked top-to-bottom, but not rotated
- 02H Text is rotated 90 degrees counterclockwise
- 03H Text is rotated 90 degrees clockwise
-
- XF_ROTATION Text Rotation Angle (1 Byte), BIFF8
- Value Text rotation
- 0 Not rotated
- 1-90 1 to 90 degrees counterclockwise
- 91-180 1 to 90 degrees clockwise
- 255 Letters are stacked top-to-bottom, but not rotated
-
- XF_BORDER_34 Cell Border Style (4 Bytes), BIFF3-BIFF4 Cell borders
- contain a line style and a line colour for each line of the border.
- Bit Mask Contents
- 2-0 00000007H Top line style
- 7-3 000000F8H Colour index for top line colour
- 10-8 00000700H Left line style
- 15-11 0000F800H Colour index for left line colour
- 18-16 00070000H Bottom line style
- 23-19 00F80000H Colour index for bottom line colour
- 26-24 07000000H Right line style
- 31-27 F8000000H Colour index for right line colour
-
- XF_AREA_34 Cell Background Area Style (2 Bytes), BIFF3-BIFF4 A cell
- background area style contains an area pattern and a foreground and
- background colour.
- Bit Mask Contents
- 5-0 003FH Fill pattern
- 10-6 07C0H Colour index for pattern colour
- 15-11 F800H Colour index for pattern background
- ---------------------------------------------------------------------------------------------
- Record XF, BIFF8:
- Offset Size Contents
- 0 2 Index to FONT record
- 2 2 Index to FORMAT record
- 4 2 Bit Mask Contents
- 2-0 0007H XF_TYPE_PROT . XF type, cell protection (see above)
- 15-4 FFF0H Index to parent style XF (always FFFH in style XFs)
- 6 1 Bit Mask Contents
- 2-0 07H XF_HOR_ALIGN . Horizontal alignment (see above)
- 3 08H 1 = Text is wrapped at right border
- 6-4 70H XF_VERT_ALIGN . Vertical alignment (see above)
- 7 1 XF_ROTATION: Text rotation angle (see above)
- 8 1 Bit Mask Contents
- 3-0 0FH Indent level
- 4 10H 1 = Shrink content to fit into cell
- 5 merge
- 7-6 C0H Text direction (BIFF8X only)
- 00b = According to context
- 01b = Left-to-right
- 10b = Right-to-left
- 9 1 Bit Mask Contents
- 7-2 FCH XF_USED_ATTRIB . Used attributes (see above)
- 10 4 Cell border lines and background area:
- Bit Mask Contents
- 3-0 0000000FH Left line style
- 7-4 000000F0H Right line style
- 11-8 00000F00H Top line style
- 15-12 0000F000H Bottom line style
- 22-16 007F0000H Colour index for left line colour
- 29-23 3F800000H Colour index for right line colour
- 30 40000000H 1 = Diagonal line from top left to right bottom
- 31 80000000H 1 = Diagonal line from bottom left to right top
- 14 4 Bit Mask Contents
- 6-0 0000007FH Colour index for top line colour
- 13-7 00003F80H Colour index for bottom line colour
- 20-14 001FC000H Colour index for diagonal line colour
- 24-21 01E00000H Diagonal line style
- 31-26 FC000000H Fill pattern
- 18 2 Bit Mask Contents
- 6-0 007FH Colour index for pattern colour
- 13-7 3F80H Colour index for pattern background
-
- """
- _REC_ID = 0x00E0
-
- def __init__(self, xf, xftype='cell'):
- font_xf_idx, fmt_str_xf_idx, alignment, borders, pattern, protection = xf
- fnt = pack('<H', font_xf_idx)
- fmt = pack('<H', fmt_str_xf_idx)
- if xftype == 'cell':
- prt = pack('<H',
- ((protection.cell_locked & 0x01) << 0) |
- ((protection.formula_hidden & 0x01) << 1)
- )
- else:
- prt = pack('<H', 0xFFF5)
- aln = pack('B',
- ((alignment.horz & 0x07) << 0) |
- ((alignment.wrap & 0x01) << 3) |
- ((alignment.vert & 0x07) << 4)
- )
- rot = pack('B', alignment.rota)
- txt = pack('B',
- ((alignment.inde & 0x0F) << 0) |
- ((alignment.shri & 0x01) << 4) |
- ((alignment.merg & 0x01) << 5) |
- ((alignment.dire & 0x03) << 6)
- )
- if xftype == 'cell':
- used_attr = pack('B', 0xF8)
- else:
- used_attr = pack('B', 0xF4)
-
- if borders.left == borders.NO_LINE:
- borders.left_colour = 0x00
- if borders.right == borders.NO_LINE:
- borders.right_colour = 0x00
- if borders.top == borders.NO_LINE:
- borders.top_colour = 0x00
- if borders.bottom == borders.NO_LINE:
- borders.bottom_colour = 0x00
- if borders.diag == borders.NO_LINE:
- borders.diag_colour = 0x00
- brd1 = pack('<L',
- ((borders.left & 0x0F) << 0 ) |
- ((borders.right & 0x0F) << 4 ) |
- ((borders.top & 0x0F) << 8 ) |
- ((borders.bottom & 0x0F) << 12) |
- ((borders.left_colour & 0x7F) << 16) |
- ((borders.right_colour & 0x7F) << 23) |
- ((borders.need_diag1 & 0x01) << 30) |
- ((borders.need_diag2 & 0x01) << 31)
- )
- brd2 = pack('<L',
- ((borders.top_colour & 0x7F) << 0 ) |
- ((borders.bottom_colour & 0x7F) << 7 ) |
- ((borders.diag_colour & 0x7F) << 14) |
- ((borders.diag & 0x0F) << 21) |
- ((pattern.pattern & 0x3F) << 26)
- )
- pat = pack('<H',
- ((pattern.pattern_fore_colour & 0x7F) << 0 ) |
- ((pattern.pattern_back_colour & 0x7F) << 7 )
- )
- self._rec_data = fnt + fmt + prt + \
- aln + rot + txt + used_attr + \
- brd1 + brd2 + \
- pat
-
-class StyleRecord(BiffRecord):
- """
- STYLE record for user-defined cell styles, BIFF3-BIFF8:
- Offset Size Contents
- 0 2 Bit Mask Contents
- 11-0 0FFFH Index to style XF record
- 15 8000H Always 0 for user-defined styles
- 2 var. BIFF2-BIFF7: Non-empty byte string, 8-bit string length
- BIFF8: Non-empty Unicode string, 16-bit string length
- STYLE record for built-in cell styles, BIFF3-BIFF8:
- Offset Size Contents
- 0 2 Bit Mask Contents
- 11-0 0FFFH Index to style XF record
- 15 8000H Always 1 for built-in styles
- 2 1 Identifier of the built-in cell style:
- 00H = Normal
- 01H = RowLevel_lv (see next field)
- 02H = ColLevel_lv (see next field)
- 03H = Comma
- 04H = Currency
- 05H = Percent
- 06H = Comma [0] (BIFF4-BIFF8)
- 07H = Currency [0] (BIFF4-BIFF8)
- 08H = Hyperlink (BIFF8)
- 09H = Followed Hyperlink (BIFF8)
- 3 1 Level for RowLevel or ColLevel style
- (zero-based, lv), FFH otherwise
- The RowLevel and ColLevel styles specify the formatting of subtotal
- cells in a specific outline level. The level is specified by the last
- field in the STYLE record. Valid values are 0-6 for the outline levels
- 1-7.
- """
- _REC_ID = 0x0293
-
- def __init__(self):
- self._rec_data = pack('<HBB', 0x8000, 0x00, 0xFF)
- # TODO: implement user-defined styles???
-
-
-class PaletteRecord(BiffRecord):
- """
- This record contains the definition of all user-defined colours
- available for cell and object formatting.
-
- Record PALETTE, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 Number of following colours (nm). Contains 16 in BIFF3-BIFF4 and 56 in BIFF5-BIFF8.
- 2 4*nm List of nm RGB colours
-
- The following table shows how colour indexes are used in other records:
-
- Colour index Resulting colour or internal list index
- 00H Built-in Black (R = 00H, G = 00H, B = 00H)
- 01H Built-in White (R = FFH, G = FFH, B = FFH)
- 02H Built-in Red (R = FFH, G = 00H, B = 00H)
- 03H Built-in Green (R = 00H, G = FFH, B = 00H)
- 04H Built-in Blue (R = 00H, G = 00H, B = FFH)
- 05H Built-in Yellow (R = FFH, G = FFH, B = 00H)
- 06H Built-in Magenta (R = FFH, G = 00H, B = FFH)
- 07H Built-in Cyan (R = 00H, G = FFH, B = FFH)
- 08H First user-defined colour from the PALETTE record (entry 0 from record colour list)
- .........................
-
- 17H (BIFF3-BIFF4) Last user-defined colour from the PALETTE record (entry 15 or 55 from record colour list)
- 3FH (BIFF5-BIFF8)
-
- 18H (BIFF3-BIFF4) System window text colour for border lines (used in records XF, CF, and
- 40H (BIFF5-BIFF8) WINDOW2 (BIFF8 only))
-
- 19H (BIFF3-BIFF4) System window background colour for pattern background (used in records XF, and CF)
- 41H (BIFF5-BIFF8)
-
- 43H System face colour (dialogue background colour)
- 4DH System window text colour for chart border lines
- 4EH System window background colour for chart areas
- 4FH Automatic colour for chart border lines (seems to be always Black)
- 50H System ToolTip background colour (used in note objects)
- 51H System ToolTip text colour (used in note objects)
- 7FFFH System window text colour for fonts (used in records FONT, EFONT, and CF)
-
- """
- _REC_ID = 0x0092
-
-
-class BoundSheetRecord(BiffRecord):
- """
- This record is located in the workbook globals area and represents
- a sheet inside of the workbook. For each sheet a BOUNDSHEET record
- is written. It stores the sheet name and a stream offset to the BOF
- record within the workbook stream. The record is also known
- as BUNDLESHEET.
-
- Record BOUNDSHEET, BIFF5-BIFF8:
- Offset Size Contents
- 0 4 Absolute stream position of the BOF record of the sheet represented by this record. This
- field is never encrypted in protected files.
- 4 1 Visibility:
- 00H = Visible
- 01H = Hidden
- 02H = Strong hidden
- 5 1 Sheet type:
- 00H = Worksheet
- 02H = Chart
- 06H = Visual Basic module
- 6 var. Sheet name:
- BIFF5/BIFF7: Byte string, 8-bit string length
- BIFF8: Unicode string, 8-bit string length
- """
- _REC_ID = 0x0085
-
- def __init__(self, stream_pos, visibility, sheetname, encoding='ascii'):
- usheetname = upack1(sheetname, encoding)
- uusheetname_len = len(usheetname)
-
- self._rec_data = pack('<LBB%ds' % uusheetname_len, stream_pos, visibility, 0x00, usheetname)
-
-
-class ContinueRecord(BiffRecord):
- """
- Whenever the content of a record exceeds the given limits (see table),
- the record must be split. Several CONTINUE records containing the
- additional data are added after the parent record.
-
- BIFF version Maximum data size of a record
- BIFF2-BIFF7 2080 bytes (2084 bytes including record header)
- BIFF8 8224 bytes (8228 bytes including record header) (0x2020)
-
- Record CONTINUE, BIFF2-BIFF8:
- Offset Size Contents
- 0 var. Data continuation of the previous record
-
- Unicode strings are split in a special way. At the beginning of each
- CONTINUE record the option flags byte is repeated. Only the character
- size flag will be set in this flags byte, the Rich-Text flag and the
- Far-East flag are set to zero. In each CONTINUE record it is possible
- that the character size changes from 8-bit characters to 16-bit
- characters and vice versa.
-
- Never a Unicode string is split until and including the first
- character. That means, all header fields (string length, option flags,
- optional Rich-Text size, and optional Far-East data size) and the first
- character of the string have to occur together in the leading record,
- or have to be moved completely into the CONTINUE record. Formatting
- runs cannot be split between their components (character index and FONT
- record index). If a string is split between two formatting runs, the
- option flags field will not be repeated in the CONTINUE record.
- """
- _REC_ID = 0x003C
-
-
-class SSTRecord(BiffRecord):
- """
- This record contains a list of all strings used anywhere in the
- workbook. Each string occurs only once. The workbook uses indexes into
- the list to reference the strings.
-
- Record SST, BIFF8:
- Offset Size Contents
- 0 4 Total number of strings in the workbook (see below)
- 4 4 Number of following strings (nm)
- 8 var. List of nm Unicode strings, 16-bit string length
-
- The first field of the SST record counts the total occurrence
- of strings in the workbook. For instance, the string AAA is used
- 3 times and the string BBB is used 2 times. The first field contains
- 5 and the second field contains 2, followed by the two strings.
- """
- _REC_ID = 0x00FC
-
-
-class ExtSSTRecord(BiffRecord):
- """
- This record occurs in conjunction with the SST record. It is used
- by Excel to create a hash table with stream offsets to the SST record
- to optimise string search operations. Excel may not shorten this record
- if strings are deleted from the shared string table, so the last part
- might contain invalid data. The stream indexes in this record divide
- the SST into portions containing a constant number of strings.
-
- Record EXTSST, BIFF8:
-
- Offset Size Contents
- 0 2 Number of strings in a portion, this number is >=8
- 2 var. List of OFFSET structures for all portions. Each OFFSET contains the following data:
- Offset Size Contents
- 0 4 Absolute stream position of first string of the portion
- 4 2 Position of first string of the portion inside of current record,
- including record header. This counter restarts at zero, if the SST
- record is continued with a CONTINUE record.
- 6 2 Not used
- """
- _REC_ID = 0x00FF
-
- def __init__(self, sst_stream_pos, str_placement, portions_len):
- extsst = {}
- abs_stream_pos = sst_stream_pos
- str_counter = 0
- portion_counter = 0
- while str_counter < len(str_placement):
- str_chunk_num, pos_in_chunk = str_placement[str_counter]
- if str_chunk_num != portion_counter:
- portion_counter = str_chunk_num
- abs_stream_pos += portions_len[portion_counter-1]
- #print hex(abs_stream_pos)
- str_stream_pos = abs_stream_pos + pos_in_chunk + 4 # header
- extsst[str_counter] = (pos_in_chunk, str_stream_pos)
- str_counter += 1
-
- exsst_str_count_delta = max(8, len(str_placement)*8/0x2000) # maybe smth else?
- self._rec_data = pack('<H', exsst_str_count_delta)
- str_counter = 0
- while str_counter < len(str_placement):
- self._rec_data += pack('<IHH', extsst[str_counter][1], extsst[str_counter][0], 0)
- str_counter += exsst_str_count_delta
-
-class DimensionsRecord(BiffRecord):
- """
- Record DIMENSIONS, BIFF8:
-
- Offset Size Contents
- 0 4 Index to first used row
- 4 4 Index to last used row, increased by 1
- 8 2 Index to first used column
- 10 2 Index to last used column, increased by 1
- 12 2 Not used
- """
- _REC_ID = 0x0200
- def __init__(self, first_used_row, last_used_row, first_used_col, last_used_col):
- if first_used_row > last_used_row or first_used_col > last_used_col:
- # Special case: empty worksheet
- first_used_row = first_used_col = 0
- last_used_row = last_used_col = -1
- self._rec_data = pack('<2L3H',
- first_used_row, last_used_row + 1,
- first_used_col, last_used_col + 1,
- 0x00)
-
-
-class Window2Record(BiffRecord):
- """
- Record WINDOW2, BIFF8:
-
- Offset Size Contents
- 0 2 Option flags (see below)
- 2 2 Index to first visible row
- 4 2 Index to first visible column
- 6 2 Colour index of grid line colour. Note that in BIFF2-BIFF7 an RGB colour is
- written instead.
- 8 2 Not used
- 10 2 Cached magnification factor in page break preview (in percent); 0 = Default (60%)
- 12 2 Cached magnification factor in normal view (in percent); 0 = Default (100%)
- 14 4 Not used
-
- In BIFF8 this record stores used magnification factors for page break
- preview and normal view. These values are used to restore the
- magnification, when the view is changed. The real magnification of the
- currently active view is stored in the SCL record. The type of the
- active view is stored in the option flags field (see below).
-
- 0 0001H 0 = Show formula results 1 = Show formulas
- 1 0002H 0 = Do not show grid lines 1 = Show grid lines
- 2 0004H 0 = Do not show sheet headers 1 = Show sheet headers
- 3 0008H 0 = Panes are not frozen 1 = Panes are frozen (freeze)
- 4 0010H 0 = Show zero values as empty cells 1 = Show zero values
- 5 0020H 0 = Manual grid line colour 1 = Automatic grid line colour
- 6 0040H 0 = Columns from left to right 1 = Columns from right to left
- 7 0080H 0 = Do not show outline symbols 1 = Show outline symbols
- 8 0100H 0 = Keep splits if pane freeze is removed 1 = Remove splits if pane freeze is removed
- 9 0200H 0 = Sheet not selected 1 = Sheet selected (BIFF5-BIFF8)
- 10 0400H 0 = Sheet not visible 1 = Sheet visible (BIFF5-BIFF8)
- 11 0800H 0 = Show in normal view 1 = Show in page break preview (BIFF8)
-
- The freeze flag specifies, if a following PANE record describes unfrozen or frozen panes.
-
- *** This class appends the optional SCL record ***
-
- Record SCL, BIFF4-BIFF8:
-
- This record stores the magnification of the active view of the current worksheet.
- In BIFF8 this can be either the normal view or the page break preview.
- This is determined in the WINDOW2 record. The SCL record is part of the
- Sheet View Settings Block.
-
- Offset Size Contents
- 0 2 Numerator of the view magnification fraction (num)
- 2 2 Denumerator [denominator] of the view magnification fraction (den)
- The magnification is stored as reduced fraction. The magnification results from num/den.
-
- SJM note: Excel expresses (e.g.) 25% in reduced form i.e. 1/4. Reason unknown. This code
- writes 25/100, and Excel is happy with that.
-
- """
- _REC_ID = 0x023E
-
- def __init__(self, options, first_visible_row, first_visible_col,
- grid_colour, preview_magn, normal_magn, scl_magn):
- self._rec_data = pack('<7HL', options,
- first_visible_row, first_visible_col,
- grid_colour,
- 0x00,
- preview_magn, normal_magn,
- 0x00)
- if scl_magn:
- self._scl_rec = pack('<4H', 0x00A0, 4, scl_magn, 100)
- else:
- self._scl_rec = b''
-
- def get(self):
- return self.get_rec_header() + self._rec_data + self._scl_rec
-
-
-class PanesRecord(BiffRecord):
- """
- This record stores the position of window panes. It is part of the Sheet
- View Settings Block. If the sheet does not contain any splits, this
- record will not occur.
- A sheet can be split in two different ways, with unfrozen panes or with
- frozen panes. A flag in the WINDOW2 record specifies, if the panes are
- frozen, which affects the contents of this record.
-
- Record PANE, BIFF2-BIFF8:
- Offset Size Contents
- 0 2 Position of the vertical split
- (px, 0 = No vertical split):
- Unfrozen pane: Width of the left pane(s)
- (in twips = 1/20 of a point)
- Frozen pane: Number of visible
- columns in left pane(s)
- 2 2 Position of the horizontal split
- (py, 0 = No horizontal split):
- Unfrozen pane: Height of the top pane(s)
- (in twips = 1/20 of a point)
- Frozen pane: Number of visible
- rows in top pane(s)
- 4 2 Index to first visible row
- in bottom pane(s)
- 6 2 Index to first visible column
- in right pane(s)
- 8 1 Identifier of pane with active
- cell cursor
- [9] 1 Not used (BIFF5-BIFF8 only, not written
- in BIFF2-BIFF4)
-
- If the panes are frozen, pane 0 is always active, regardless
- of the cursor position. The correct identifiers for all possible
- combinations of visible panes are shown in the following pictures.
-
- px = 0, py = 0 px = 0, py > 0
- -------------------------- ------------|-------------
- | | | |
- | | | 3 |
- | | | |
- - 3 - --------------------------
- | | | |
- | | | 2 |
- | | | |
- -------------------------- ------------|-------------
-
- px > 0, py = 0 px > 0, py > 0
- ------------|------------- ------------|-------------
- | | | | | |
- | | | | 3 | 2 |
- | | | | | |
- - 3 | 1 - --------------------------
- | | | | | |
- | | | | 1 | 0 |
- | | | | | |
- ------------|------------- ------------|-------------
- """
- _REC_ID = 0x0041
- def __init__(self, px, py, first_row_bottom, first_col_right, active_pane):
- self._rec_data = pack('<5H', int(px), int(py), int(first_row_bottom),
- int(first_col_right), int(active_pane))
-
-
-class RowRecord(BiffRecord):
- """
- This record contains the properties of a single row in a sheet. Rows
- and cells in a sheet are divided into blocks of 32 rows.
-
- Record ROW, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 Index of this row
- 2 2 Index to column of the first cell which is described by a cell record
- 4 2 Index to column of the last cell which is described by a cell record,
- increased by 1
- 6 2 Bit Mask Contents
- 14-0 7FFFH Height of the row, in twips = 1/20 of a point
- 15 8000H 0 = Row has custom height; 1 = Row has default height
- 8 2 Not used
- 10 2 In BIFF3-BIFF4 this field contains a relative offset
- to calculate stream position of the first cell record
- for this row. In BIFF5-BIFF8 this field is not used
- anymore, but the DBCELL record instead.
- 12 4 Option flags and default row formatting:
- Bit Mask Contents
- 2-0 00000007H Outline level of the row
- 4 00000010H 1 = Outline group starts or ends here (depending
- on where the outline buttons are located,
- see WSBOOL record), and is collapsed
- 5 00000020H 1 = Row is hidden (manually, or by a filter or outline group)
- 6 00000040H 1 = Row height and default font height do not match
- 7 00000080H 1 = Row has explicit default format (fl)
- 8 00000100H Always 1
- 27-16 0FFF0000H If fl=1: Index to default XF record
- 28 10000000H 1 = Additional space above the row. This flag is set,
- if the upper border of at least one cell in this row
- or if the lower border of at least one cell in the row
- above is formatted with a thick line style.
- Thin and medium line styles are not taken into account.
- 29 20000000H 1 = Additional space below the row. This flag is set,
- if the lower border of at least one cell in this row
- or if the upper border of at least one cell in the row
- below is formatted with a medium or thick line style.
- Thin line styles are not taken into account.
- """
-
- _REC_ID = 0x0208
-
- def __init__(self, index, first_col, last_col, height_options, options):
- self._rec_data = pack('<6HL', index, first_col, last_col + 1,
- height_options,
- 0x00, 0x00,
- options)
-
-class LabelSSTRecord(BiffRecord):
- """
- This record represents a cell that contains a string. It replaces the
- LABEL record and RSTRING record used in BIFF2-BIFF7.
- """
- _REC_ID = 0x00FD
-
- def __init__(self, row, col, xf_idx, sst_idx):
- self._rec_data = pack('<3HL', row, col, xf_idx, sst_idx)
-
-
-class MergedCellsRecord(BiffRecord):
- """
- This record contains all merged cell ranges of the current sheet.
-
- Record MERGEDCELLS, BIFF8:
-
- Offset Size Contents
- 0 var. Cell range address list with all merged ranges
-
- ------------------------------------------------------------------
-
- A cell range address list consists of a field with the number of ranges
- and the list of the range addresses.
-
- Cell range address list, BIFF8:
-
- Offset Size Contents
- 0 2 Number of following cell range addresses (nm)
- 2 8*nm List of nm cell range addresses
-
- ---------------------------------------------------------------------
- Cell range address, BIFF8:
-
- Offset Size Contents
- 0 2 Index to first row
- 2 2 Index to last row
- 4 2 Index to first column
- 6 2 Index to last column
-
- """
- _REC_ID = 0x00E5
-
- def __init__(self, merged_list):
- i = len(merged_list) - 1
- while i >= 0:
- j = 0
- merged = b''
- while (i >= 0) and (j < 0x403):
- r1, r2, c1, c2 = merged_list[i]
- merged += pack('<4H', r1, r2, c1, c2)
- i -= 1
- j += 1
- self._rec_data += pack('<3H', self._REC_ID, len(merged) + 2, j) + \
- merged
-
- # for some reason Excel doesn't use CONTINUE
- def get(self):
- return self._rec_data
-
-class MulBlankRecord(BiffRecord):
- """
- This record represents a cell range of empty cells. All cells are
- located in the same row.
-
- Record MULBLANK, BIFF5-BIFF8:
-
- Offset Size Contents
- 0 2 Index to row
- 2 2 Index to first column (fc)
- 4 2*nc List of nc=lc-fc+1 16-bit indexes to XF records
- 4+2*nc 2 Index to last column (lc)
- """
- _REC_ID = 0x00BE
-
- def __init__(self, row, first_col, last_col, xf_index):
- blanks_count = last_col-first_col+1
- self._rec_data = pack('%dH' % blanks_count, *([xf_index]*blanks_count))
- self._rec_data = pack('<2H', row, first_col) + self._rec_data + pack('<H', last_col)
-
-
-class BlankRecord(BiffRecord):
- """
- This record represents an empty cell.
-
- Record BLANK, BIFF5-BIFF8:
-
- Offset Size Contents
- 0 2 Index to row
- 2 2 Index to first column (fc)
- 4 2 indexes to XF record
- """
- _REC_ID = 0x0201
-
- def __init__(self, row, col, xf_index):
- self._rec_data = pack('<3H', row, col, xf_index)
-
-
-class RKRecord(BiffRecord):
- """
- This record represents a cell that contains an RK value (encoded integer or
- floating-point value). If a floating-point value cannot be encoded to an RK value,
- a NUMBER record will be written.
- """
- _REC_ID = 0x027E
-
- def __init__(self, row, col, xf_index, rk_encoded):
- self._rec_data = pack('<3Hi', row, col, xf_index, rk_encoded)
-
-
-class NumberRecord(BiffRecord):
- """
- This record represents a cell that contains an IEEE-754 floating-point value.
- """
- _REC_ID = 0x0203
-
- def __init__(self, row, col, xf_index, number):
- self._rec_data = pack('<3Hd', row, col, xf_index, number)
-
-class BoolErrRecord(BiffRecord):
- """
- This record represents a cell that contains a boolean or error value.
- """
- _REC_ID = 0x0205
-
- def __init__(self, row, col, xf_index, number, is_error):
- self._rec_data = pack('<3HBB', row, col, xf_index, number, is_error)
-
-
-class FormulaRecord(BiffRecord):
- """
- Offset Size Contents
- 0 2 Index to row
- 2 2 Index to column
- 4 2 Index to XF record
- 6 8 Result of the formula
- 14 2 Option flags:
- Bit Mask Contents
- 0 0001H 1 = Recalculate always
- 1 0002H 1 = Calculate on open
- 3 0008H 1 = Part of a shared formula
- 16 4 Not used
- 20 var. Formula data (RPN token array)
-
- """
- _REC_ID = 0x0006
-
- def __init__(self, row, col, xf_index, rpn, calc_flags=0):
- self._rec_data = pack('<3HQHL', row, col, xf_index, 0xFFFF000000000003, calc_flags & 3, 0) + rpn
-
-
-class GutsRecord(BiffRecord):
- """
- This record contains information about the layout of outline symbols.
-
- Record GUTS, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 Width of the area to display row outlines (left of the sheet), in pixel
- 2 2 Height of the area to display column outlines (above the sheet), in pixel
- 4 2 Number of visible row outline levels (used row levels + 1; or 0, if not used)
- 6 2 Number of visible column outline levels (used column levels + 1; or 0, if not used)
-
- """
-
- _REC_ID = 0x0080
-
- def __init__(self, row_gut_width, col_gut_height, row_visible_levels, col_visible_levels):
- self._rec_data = pack('<4H', row_gut_width, col_gut_height, row_visible_levels, col_visible_levels)
-
-class WSBoolRecord(BiffRecord):
- """
- This record stores a 16 bit value with Boolean options for the current
- sheet. From BIFF5 on the "Save external linked values" option is moved
- to the record BOOKBOOL.
-
- Option flags of record WSBOOL, BIFF3-BIFF8:
-
- Bit Mask Contents
- 0 0001H 0 = Do not show automatic page breaks
- 1 = Show automatic page breaks
- 4 0010H 0 = Standard sheet
- 1 = Dialogue sheet (BIFF5-BIFF8)
- 5 0020H 0 = No automatic styles in outlines
- 1 = Apply automatic styles to outlines
- 6 0040H 0 = Outline buttons above outline group
- 1 = Outline buttons below outline group
- 7 0080H 0 = Outline buttons left of outline group
- 1 = Outline buttons right of outline group
- 8 0100H 0 = Scale printout in percent
- 1 = Fit printout to number of pages
- 9 0200H 0 = Save external linked values (BIFF3?BIFF4 only)
- 1 = Do not save external linked values (BIFF3?BIFF4 only)
- 10 0400H 0 = Do not show row outline symbols
- 1 = Show row outline symbols
- 11 0800H 0 = Do not show column outline symbols
- 1 = Show column outline symbols
- 13-12 3000H These flags specify the arrangement of windows.
- They are stored in BIFF4 only.
- 00 = Arrange windows tiled
- 01 = Arrange windows horizontal
- 10 = Arrange windows vertical112 = Arrange windows cascaded
- The following flags are valid for BIFF4-BIFF8 only:
- 14 4000H 0 = Standard expression evaluation
- 1 = Alternative expression evaluation
- 15 8000H 0 = Standard formula entries
- 1 = Alternative formula entries
-
- """
- _REC_ID = 0x0081
-
- def __init__(self, options):
- self._rec_data = pack('<H', options)
-
-class ColInfoRecord(BiffRecord):
- """
- This record specifies the width for a given range of columns.
- If a column does not have a corresponding COLINFO record,
- the width specified in the record STANDARDWIDTH is used. If
- this record is also not present, the contents of the record
- DEFCOLWIDTH is used instead.
- This record also specifies a default XF record to use for
- cells in the columns that are not described by any cell record
- (which contain the XF index for that cell). Additionally,
- the option flags field contains hidden, outline, and collapsed
- options applied at the columns.
-
- Record COLINFO, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 Index to first column in the range
- 2 2 Index to last column in the range
- 4 2 Width of the columns in 1/256 of the width of the zero character, using default font
- (first FONT record in the file)
- 6 2 Index to XF record for default column formatting
- 8 2 Option flags:
- Bits Mask Contents
- 0 0001H 1 = Columns are hidden
- 10-8 0700H Outline level of the columns (0 = no outline)
- 12 1000H 1 = Columns are collapsed
- 10 2 Not used
-
- """
- _REC_ID = 0x007D
-
- def __init__(self, first_col, last_col, width, xf_index, options):
- self._rec_data = pack('<6H', first_col, last_col, width, xf_index, options, 0)
-
-class CalcModeRecord(BiffRecord):
- """
- This record is part of the Calculation Settings Block.
- It specifies whether to calculate formulas manually,
- automatically or automatically except for multiple table operations.
-
- Record CALCMODE, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 FFFFH = automatic except for multiple table operations
- 0000H = manually
- 0001H = automatically (default)
- """
- _REC_ID = 0x000D
-
- def __init__(self, calc_mode):
- self._rec_data = pack('<h', calc_mode)
-
-
-class CalcCountRecord(BiffRecord):
- """
- This record is part of the Calculation Settings Block. It specifies the maximum
- number of times the formulas should be iteratively calculated. This is a fail-safe
- against mutually recursive formulas locking up a spreadsheet application.
-
- Record CALCCOUNT, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 Maximum number of iterations allowed in circular references
- """
-
- _REC_ID = 0x000C
-
- def __init__(self, calc_count):
- self._rec_data = pack('<H', calc_count)
-
-class RefModeRecord(BiffRecord):
- """
- This record is part of the Calculation Settings Block.
- It stores which method is used to show cell addresses in formulas.
- The “RC” mode uses numeric indexes for rows and columns,
- i.e. “R(1)C(-1)”, or “R1C1:R2C2”.
- The “A1” mode uses characters for columns and numbers for rows,
- i.e. “B1”, or “$A$1:$B$2”.
-
- Record REFMODE, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 0 = RC mode; 1 = A1 mode
-
- """
- _REC_ID = 0x00F
-
- def __init__(self, ref_mode):
- self._rec_data = pack('<H', ref_mode)
-
-class IterationRecord(BiffRecord):
- """
- This record is part of the Calculation Settings Block.
- It stores if iterations are allowed while calculating recursive formulas.
-
- Record ITERATION, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Iterations off; 1 = Iterations on
- """
- _REC_ID = 0x011
-
- def __init__(self, iterations_on):
- self._rec_data = pack('<H', iterations_on)
-
-class DeltaRecord(BiffRecord):
- """
- This record is part of the Calculation Settings Block.
- It stores the maximum change of the result to exit an iteration.
-
- Record DELTA, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 8 Maximum change in iteration
- (IEEE 754 floating-point value,
- 64bit double precision)
- """
- _REC_ID = 0x010
-
- def __init__(self, delta):
- self._rec_data = pack('<d', delta)
-
-class SaveRecalcRecord(BiffRecord):
- """
- This record is part of the Calculation Settings Block.
- It contains the “Recalculate before save” option in
- Excel's calculation settings dialogue.
-
- Record SAVERECALC, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Do not recalculate;
- 1 = Recalculate before saving the document
-
- """
- _REC_ID = 0x05F
-
- def __init__(self, recalc):
- self._rec_data = pack('<H', recalc)
-
-class PrintHeadersRecord(BiffRecord):
- """
- This record stores if the row and column headers
- (the areas with row numbers and column letters) will be printed.
-
- Record PRINTHEADERS, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Do not print row/column headers;
- 1 = Print row/column headers
- """
- _REC_ID = 0x02A
-
- def __init__(self, print_headers):
- self._rec_data = pack('<H', print_headers)
-
-
-class PrintGridLinesRecord(BiffRecord):
- """
- This record stores if sheet grid lines will be printed.
-
- Record PRINTGRIDLINES, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Do not print sheet grid lines;
- 1 = Print sheet grid lines
-
- """
- _REC_ID = 0x02B
-
- def __init__(self, print_grid):
- self._rec_data = pack('<H', print_grid)
-
-
-class GridSetRecord(BiffRecord):
- """
- This record specifies if the option to print sheet grid lines
- (record PRINTGRIDLINES) has ever been changed.
-
- Record GRIDSET, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Print grid lines option never changed
- 1 = Print grid lines option changed
- """
- _REC_ID = 0x082
-
- def __init__(self, print_grid_changed):
- self._rec_data = pack('<H', print_grid_changed)
-
-
-class DefaultRowHeightRecord(BiffRecord):
- """
- This record specifies the default height and default flags
- for rows that do not have a corresponding ROW record.
-
- Record DEFAULTROWHEIGHT, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 Option flags:
- Bit Mask Contents
- 0 0001H 1 = Row height and default font height do not match
- 1 0002H 1 = Row is hidden
- 2 0004H 1 = Additional space above the row
- 3 0008H 1 = Additional space below the row
- 2 2 Default height for unused rows, in twips = 1/20 of a point
-
- """
- _REC_ID = 0x0225
-
- def __init__(self, options, def_height):
- self._rec_data = pack('<2H', options, def_height)
-
-
-class DefColWidthRecord(BiffRecord):
- """
- This record specifies the default column width for columns that
- do not have a specific width set using the record COLINFO or COLWIDTH.
- This record has no effect, if a STANDARDWIDTH record is present in the file.
-
- Record DEFCOLWIDTH, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 2 Column width in characters, using the width of the zero
- character from default font (first FONT record in the file)
- """
- _REC_ID = 0x0055
-
- def __init__(self, def_width):
- self._rec_data = pack('<H', options, def_width)
-
-class HorizontalPageBreaksRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It contains all
- horizontal manual page breaks.
-
- Record HORIZONTALPAGEBREAKS, BIFF8:
- Offset Size Contents
- 0 2 Number of following row index structures (nm)
- 2 6nm List of nm row index structures. Each row index
- structure contains:
- Offset Size Contents
- 0 2 Index to first row below the page break
- 2 2 Index to first column of this page break
- 4 2 Index to last column of this page break
-
- The row indexes in the lists must be ordered ascending.
- If in BIFF8 a row contains several page breaks, they must be ordered
- ascending by start column index.
- """
- _REC_ID = 0x001B
-
- def __init__(self, breaks_list):
- self._rec_data = pack('<H', len(breaks_list))
- for r, c1, c2 in breaks_list:
- self._rec_data += pack('<3H', r, c1, c2)
-
-class VerticalPageBreaksRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It contains all
- vertical manual page breaks.
-
- Record VERTICALPAGEBREAKS, BIFF8:
- Offset Size Contents
- 0 2 Number of following column index structures (nm)
- 2 6nm List of nm column index structures. Each column index
- structure contains:
- Offset Size Contents
- 0 2 Index to first column following the page
- break
- 2 2 Index to first row of this page break
- 4 2 Index to last row of this page break
-
- The column indexes in the lists must be ordered ascending.
- If in BIFF8 a column contains several page breaks, they must be ordered
- ascending by start row index.
- """
- _REC_ID = 0x001A
-
- def __init__(self, breaks_list):
- self._rec_data = pack('<H', len(breaks_list))
- for r, c1, c2 in breaks_list:
- self._rec_data += pack('<3H', r, c1, c2)
-
-class HeaderRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It specifies the
- page header string for the current worksheet. If this record is not
- present or completely empty (record size is 0), the sheet does not
- contain a page header.
-
- Record HEADER for non-empty page header, BIFF2-BIFF8:
- Offset Size Contents
- 0 var. Page header string
- BIFF2-BIFF7: Non-empty byte string, 8bit string
- length
- BIFF8: Non-empty Unicode string, 16bit string length
- The header string may contain special commands, i.e. placeholders for
- the page number, current date, or text formatting attributes. These
- fields are represented by single letters (exception: font name and
- size, see below) with a leading ampersand ("&"). If the ampersand
- is part of the regular header text, it will be duplicated ("&&"). The
- page header is divided into 3 sections: the left, the centred, and the
- right section. Each section is introduced by a special command. All
- text and all commands following are part of the selected section. Each
- section starts with the text formatting specified in the default font
- (first FONT record in the file). Active formatting attributes from
- a previous section do not go into the next section.
-
- The following table shows all available commands:
-
- Command Contents
- && The "&" character itself
- &L Start of the left section
- &C Start of the centred section
- &R Start of the right section
- &P Current page number
- &N Page count
- &D Current date
- &T Current time
- &A Sheet name (BIFF5-BIFF8)
- &F File name without path
- &Z File path without file name (BIFF8X)
- &G Picture (BIFF8X)
- &B Bold on/off (BIFF2-BIFF4)
- &I Italic on/off (BIFF2-BIFF4)
- &U Underlining on/off
- &E Double underlining on/off (BIFF5-BIFF8)
- &S Strikeout on/off
- &X Superscript on/off (BIFF5-BIFF8)
- &Y Subscript on/off (BIFF5-BIFF8)
- &"<fontname>" Set new font <fontname>
- &"<fontname>,<fontstyle>"
- Set new font with specified style <fontstyle>.
- The style <fontstyle> is in most cases one of
- "Regular", "Bold", "Italic", or "Bold Italic".
- But this setting is dependent on the used font,
- it may differ (localised style names, or "Standard",
- "Oblique", ...). (BIFF5-BIFF8)
- &<fontheight> Set font height in points (<fontheight> is a decimal value).
- If this command is followed by a plain number to be printed
- in the header, it will be separated from the font height
- with a space character.
-
- """
- _REC_ID = 0x0014
-
- def __init__(self, header_str):
- self._rec_data = upack2(header_str)
-
-class FooterRecord(BiffRecord):
- """
- Semantic is equal to HEADER record
- """
- _REC_ID = 0x0015
-
- def __init__(self, footer_str):
- self._rec_data = upack2(footer_str)
-
-
-class HCenterRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It specifies if the
- sheet is centred horizontally when printed.
-
- Record HCENTER, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Print sheet left aligned
- 1 = Print sheet centred horizontally
-
- """
- _REC_ID = 0x0083
-
- def __init__(self, is_horz_center):
- self._rec_data = pack('<H', is_horz_center)
-
-
-class VCenterRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It specifies if the
- sheet is centred vertically when printed.
-
- Record VCENTER, BIFF3-BIFF8:
-
- Offset Size Contents
- 0 2 0 = Print sheet aligned at top page border
- 1 = Print sheet vertically centred
-
- """
- _REC_ID = 0x0084
-
- def __init__(self, is_vert_center):
- self._rec_data = pack('<H', is_vert_center)
-
-
-class LeftMarginRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It contains the left
- page margin of the current worksheet.
-
- Record LEFTMARGIN, BIFF2-BIFF8:
-
- Offset Size Contents
- 0 8 Left page margin in inches
- (IEEE 754 floating-point value, 64bit double precision)
-
- """
- _REC_ID = 0x0026
-
- def __init__(self, margin):
- self._rec_data = pack('<d', margin)
-
-
-class RightMarginRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It contains the right
- page margin of the current worksheet.
-
- Offset Size Contents
- 0 8 Right page margin in inches
- (IEEE 754 floating-point value, 64?bit double precision)
-
- """
- _REC_ID = 0x0027
-
- def __init__(self, margin):
- self._rec_data = pack('<d', margin)
-
-class TopMarginRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It contains the top
- page margin of the current worksheet.
-
- Offset Size Contents
- 0 8 Top page margin in inches
- (IEEE 754 floating-point value, 64?bit double precision)
-
- """
- _REC_ID = 0x0028
-
- def __init__(self, margin):
- self._rec_data = pack('<d', margin)
-
-
-class BottomMarginRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It contains the bottom
- page margin of the current worksheet.
-
- Offset Size Contents
- 0 8 Bottom page margin in inches
- (IEEE 754 floating-point value, 64?bit double precision)
-
- """
- _REC_ID = 0x0029
-
- def __init__(self, margin):
- self._rec_data = pack('<d', margin)
-
-class SetupPageRecord(BiffRecord):
- """
- This record is part of the Page Settings Block. It stores the page
- format settings of the current sheet. The pages may be scaled in
- percent or by using an absolute number of pages. This setting is
- located in the WSBOOL record. If pages are scaled in percent,
- the scaling factor in this record is used, otherwise the "Fit to
- pages" values. One of the "Fit to pages" values may be 0. In this case
- the sheet is scaled to fit only to the other value.
-
- Record SETUP, BIFF5-BIFF8:
-
- Offset Size Contents
- 0 2 Paper size (see below)
- 2 2 Scaling factor in percent
- 4 2 Start page number
- 6 2 Fit worksheet width to this number of pages
- (0 = use as many as needed)
- 8 2 Fit worksheet height to this number of pages
- (0 = use as many as needed)
- 10 2 Option flags:
- Bit Mask Contents
- 0 0001H 0 = Print pages in columns
- 1 = Print pages in rows
- 1 0002H 0 = Landscape
- 1 = Portrait
- 2 0004H 1 = Paper size, scaling factor,
- paper orientation (portrait/landscape),
- print resolution and number of copies
- are not initialised
- 3 0008H 0 = Print coloured
- 1 = Print black and white
- 4 0010H 0 = Default print quality
- 1 = Draft quality
- 5 0020H 0 = Do not print cell notes
- 1 = Print cell notes
- 6 0040H 0 = Paper orientation setting is valid
- 1 = Paper orientation setting not
- initialised
- 7 0080H 0 = Automatic page numbers
- 1 = Use start page number
- The following flags are valid for BIFF8 only:
- 9 0200H 0 = Print notes as displayed
- 1 = Print notes at end of sheet
- 11-10 0C00H 00 = Print errors as displayed
- 01 = Do not print errors
- 10 = Print errors as "--"
- 11 = Print errors as "#N/A!"
- 12 2 Print resolution in dpi
- 14 2 Vertical print resolution in dpi
- 16 8 Header margin (IEEE 754 floating-point value,
- 64bit double precision)
- 24 8 Footer margin (IEEE 754 floating-point value,
- 64bit double precision)
- 32 2 Number of copies to print
-
-
- PAPER TYPES:
-
- Index Paper type Paper size
- 0 Undefined
- 1 Letter 8 1/2" x 11"
- 2 Letter small 8 1/2" x 11"
- 3 Tabloid 11" x 17"
- 4 Ledger 17" x 11"
- 5 Legal 8 1/2" x 14"
- 6 Statement 5 1/2" x 8 1/2"
- 7 Executive 7 1/4" x 10 1/2"
- 8 A3 297mm x 420mm
- 9 A4 210mm x 297mm
- 10 A4 small 210mm x 297mm
- 11 A5 148mm x 210mm
- 12 B4 (JIS) 257mm x 364mm
- 13 B5 (JIS) 182mm x 257mm
- 14 Folio 8 1/2" x 13"
- 15 Quarto 215mm x 275mm
- 16 10x14 10" x 14"
- 17 11x17 11" x 17"
- 18 Note 8 1/2" x 11"
- 19 Envelope #9 3 7/8" x 8 7/8"
- 20 Envelope #10 4 1/8" x 9 1/2"
- 21 Envelope #11 4 1/2" x 10 3/8"
- 22 Envelope #12 4 3/4" x 11"
- 23 Envelope #14 5" x 11 1/2"
- 24 C 17" x 22"
- 25 D 22" x 34"
- 26 E 34" x 44"
- 27 Envelope DL 110mm x 220mm
- 28 Envelope C5 162mm x 229mm
- 29 Envelope C3 324mm x 458mm
- 30 Envelope C4 229mm x 324mm
- 31 Envelope C6 114mm x 162mm
- 32 Envelope C6/C5 114mm x 229mm
- 33 B4 (ISO) 250mm x 353mm
- 34 B5 (ISO) 176mm x 250mm
- 35 B6 (ISO) 125mm x 176mm
- 36 Envelope Italy 110mm x 230mm
- 37 Envelope Monarch 3 7/8" x 7 1/2"
- 38 63/4 Envelope 3 5/8" x 6 1/2"
- 39 US Standard Fanfold 14 7/8" x 11"
- 40 German Std. Fanfold 8 1/2" x 12"
- 41 German Legal Fanfold 8 1/2" x 13"
- 42 B4 (ISO) 250mm x 353mm
- 43 Japanese Postcard 100mm x 148mm
- 44 9x11 9" x 11"
- 45 10x11 10" x 11"
- 46 15x11 15" x 11"
- 47 Envelope Invite 220mm x 220mm
- 48 Undefined
- 49 Undefined
- 50 Letter Extra 9 1/2" x 12"
- 51 Legal Extra 9 1/2" x 15"
- 52 Tabloid Extra 11 11/16" x 18"
- 53 A4 Extra 235mm x 322mm
- 54 Letter Transverse 8 1/2" x 11"
- 55 A4 Transverse 210mm x 297mm
- 56 Letter Extra Transv. 9 1/2" x 12"
- 57 Super A/A4 227mm x 356mm
- 58 Super B/A3 305mm x 487mm
- 59 Letter Plus 8 1/2" x 12 11/16"
- 60 A4 Plus 210mm x 330mm
- 61 A5 Transverse 148mm x 210mm
- 62 B5 (JIS) Transverse 182mm x 257mm
- 63 A3 Extra 322mm x 445mm
- 64 A5 Extra 174mm x 235mm
- 65 B5 (ISO) Extra 201mm x 276mm
- 66 A2 420mm x 594mm
- 67 A3 Transverse 297mm x 420mm
- 68 A3 Extra Transverse 322mm x 445mm
- 69 Dbl. Japanese Postcard 200mm x 148mm
- 70 A6 105mm x 148mm
- 71
- 72
- 73
- 74
- 75 Letter Rotated 11" x 8 1/2"
- 76 A3 Rotated 420mm x 297mm
- 77 A4 Rotated 297mm x 210mm
- 78 A5 Rotated 210mm x 148mm
- 79 B4 (JIS) Rotated 364mm x 257mm
- 80 B5 (JIS) Rotated 257mm x 182mm
- 81 Japanese Postcard Rot. 148mm x 100mm
- 82 Dbl. Jap. Postcard Rot. 148mm x 200mm
- 83 A6 Rotated 148mm x 105mm
- 84
- 85
- 86
- 87
- 88 B6 (JIS) 128mm x 182mm
- 89 B6 (JIS) Rotated 182mm x 128mm
- 90 12x11 12" x 11"
-
- """
- _REC_ID = 0x00A1
- def __init__(self, paper, scaling, start_num, fit_width_to, fit_height_to,
- options,
- hres, vres,
- header_margin, footer_margin,
- num_copies):
- self._rec_data = pack('<8H2dH', paper, scaling, start_num,
- fit_width_to, fit_height_to, \
- options,
- hres, vres,
- header_margin, footer_margin,
- num_copies)
-
-class NameRecord(BiffRecord):
- """
- This record is part of a Link Table. It contains the name and the token
- array of an internal defined name. Token arrays of defined names
- contain tokens with aberrant token classes.
-
- Record NAME, BIFF5/BIFF7:
- Offset Size Contents
- 0 2 Option flags, see below
- 2 1 Keyboard shortcut (only for command macro names, see below)
- 3 1 Length of the name (character count, ln)
- 4 2 Size of the formula data (sz)
- 6 2 0 = Global name, otherwise index to EXTERNSHEET record (one-based)
- 8 2 0 = Global name, otherwise index to sheet (one-based)
- 10 1 Length of menu text (character count, lm)
- 11 1 Length of description text (character count, ld)
- 12 1 Length of help topic text (character count, lh)
- 13 1 Length of status bar text (character count, ls)
- 14 ln Character array of the name
- 14+ln sz Formula data (RPN token array without size field, 4)
- 14+ln+sz lm Character array of menu text
- var. ld Character array of description text
- var. lh Character array of help topic text
- var. ls Character array of status bar text
-
- Record NAME, BIFF8:
- Offset Size Contents
- 0 2 Option flags, see below
- 2 1 Keyboard shortcut (only for command macro names, see below)
- 3 1 Length of the name (character count, ln)
- 4 2 Size of the formula data (sz)
- 6 2 Not used
- 8 2 0 = Global name, otherwise index to sheet (one-based)
- 10 1 Length of menu text (character count, lm)
- 11 1 Length of description text (character count, ld)
- 12 1 Length of help topic text (character count, lh)
- 13 1 Length of status bar text (character count, ls)
- 14 var. Name (Unicode string without length field, 3.4)
- var. sz Formula data (RPN token array without size field, 4)
- [var.] var. (optional, only if lm > 0) Menu text (Unicode string without length field, 3.4)
- [var.] var. (optional, only if ld > 0) Description text (Unicode string without length field, 3.4)
- [var.] var. (optional, only if lh > 0) Help topic text (Unicode string without length field, 3.4)
- [var.] var. (optional, only if ls > 0) Status bar text (Unicode string without length field, 3.4)
- """
- _REC_ID = 0x0018
-
- def __init__(self, options, keyboard_shortcut, name, sheet_index, rpn,
- menu_text=b'', desc_text=b'', help_text=b'', status_text=b''):
- if type(name) == int:
- uname = chr(name)
- else:
- uname = upack1(name)[1:]
- uname_len = len(uname)
-
- #~ self._rec_data = pack('<HBBHHHBBBB%ds%ds' % (uname_len, len(rpn)), options, keyboard_shortcut, uname_len, len(rpn), 0x0000, sheet_index, len(menu_text), len(desc_text), len(help_text), len(status_text), uname, rpn) + menu_text + desc_text + help_text + status_text
- self._rec_data = pack('<HBBHHHBBBBB%ds%ds' % (uname_len, len(rpn)), options, keyboard_shortcut, uname_len, len(rpn), 0x0000, sheet_index, 0x00, len(menu_text), len(desc_text), len(help_text), len(status_text), uname, rpn) + menu_text + desc_text + help_text + status_text
-
-# Excel (both 2003 and 2007) don't like refs
-# split over a record boundary, which is what the
-# standard BiffRecord.get method does.
-
-# 8224 max data bytes in a BIFF record
-# 6 bytes per ref
-# 1370 = floor((8224 - 2) / 6.0) max refs in a record
-
-_maxRefPerRecord = 1370
-
-class ExternSheetRecord(BiffRecord):
- """
- In BIFF8 the record stores a list with indexes to SUPBOOK
- records (list of REF structures, 6.100). See 5.10.3 for
- details about external references in BIFF8.
-
- Record EXTERNSHEET, BIFF8:
- Offset Size Contents
- 0 2 Number of following REF structures (nm)
- 2 6nm List of nm REF structures. Each REF contains the following data:
- Offset Size Contents
- 0 2 Index to SUPBOOK record
- 2 2 Index to first SUPBOOK sheet
- 4 2 Index to last SUPBOOK sheet
- """
- _REC_ID = 0x0017
-
- def __init__(self, refs):
-
- # do we always need this ref? or only if there are no refs?
- # (I believe that if there are no refs then we should not generate the link table - Ruben)
- #refs.insert(0, (0,0,0))
-
- self.refs = refs
-
- def get(self):
- res = []
- nrefs = len(self.refs)
- for idx in range(0, nrefs, _maxRefPerRecord):
- chunk = self.refs[idx:idx+_maxRefPerRecord]
- krefs = len(chunk)
- if idx: # CONTINUE record
- header = pack("<HH", 0x003C, 6 * krefs)
- else: # ExternSheetRecord
- header = pack("<HHH", self._REC_ID, 6 * krefs + 2, nrefs)
- res.append(header)
- res.extend([pack("<HHH", *r) for r in chunk])
- return b''.join(res)
-
-class SupBookRecord(BiffRecord):
- """
- This record mainly stores the URL of an external document
- and a list of sheet names inside this document. Furthermore
- it is used to store DDE and OLE object links, or to indicate
- an internal 3D reference or an add-in function. See 5.10.3
- for details about external references in BIFF8.
-
- """
- _REC_ID = 0x01AE
-
-class InternalReferenceSupBookRecord(SupBookRecord):
- """
- In each file occurs a SUPBOOK that is used for internal 3D
- references. It stores the number of sheets of the own document.
-
- Record SUPBOOK for 3D references, BIFF8:
- Offset Size Contents
- 0 2 Number of sheets in this document
- 2 2 01H 04H (relict of BIFF5/BIFF7, the byte string "<04H>", see 3.9.1)
-
- """
-
- def __init__(self, num_sheets):
- self._rec_data = pack('<HBB', num_sheets, 0x01, 0x04)
-
-class XcallSupBookRecord(SupBookRecord):
- """
- Add-in function names are stored in EXTERNNAME records following this record.
-
- Offset Size Contents
- 0 2 0001H
- 2 2 01H 3AH (relict of BIFF5, the byte string ':', see EXTERNSHEET record, 5.41)
-
- """
-
- def __init__(self):
- self._rec_data = pack('<HBB', 1, 0x01, 0x3A)
-
-
-class ExternnameRecord(BiffRecord):
- """
- Record EXTERNNAME for external names and Analysis add-in functions, BIFF5-BIFF8:
- Offset Size Contents
- 0 2 Option flags (see below)
- 2 2 0 for global names, or:
- BIFF5: One-based index to EXTERNSHEET record containing the sheet name,
- BIFF8: One-based index to sheet list in preceding EXTERNALBOOK record.
- 4 2 Not used
- 6 var. BIFF5: Name (byte string, 8-bit string length, ?2.5.2).
- BIFF8: Name (Unicode string, 8-bit string length, ?2.5.3).
- See DEFINEDNAME record (?5.33) for a list of built-in names, if the built-in flag is set
- in the option flags above.
- var. var. Formula data (RPN token array, ?3)
-
- Option flags for external names (BIFF5-BIFF8)
- Bit Mask Contents
- 0 0001H 0 = Standard name; 1 = Built-in name
- 1 0002H 0 = Manual link; 1 = Automatic link (DDE links and OLE links only)
- 2 0004H 1 = Picture link (DDE links and OLE links only)
- 3 0008H 1 = This is the “StdDocumentName” identifier (DDE links only)
- 4 0010H 1 = OLE link
- 14-5 7FE0H Clipboard format of last successful update (DDE links and OLE links only)
- 15 8000H 1 = Iconified picture link (BIFF8 OLE links only)
- """
- _REC_ID = 0x0023
-
- def __init__(self, options=0, index=0, name=None, fmla=None):
- self._rec_data = pack('<HHH', options, index, 0) + upack1(name) + fmla.encode()
-
diff --git a/tablib/packages/xlwt3/Bitmap.py b/tablib/packages/xlwt3/Bitmap.py
deleted file mode 100644
index 5da082b..0000000
--- a/tablib/packages/xlwt3/Bitmap.py
+++ /dev/null
@@ -1,258 +0,0 @@
-# Portions are Copyright (C) 2005 Roman V. Kiseliov
-# Portions are Copyright (c) 2004 Evgeny Filatov <fufff@users.sourceforge.net>
-# Portions are Copyright (c) 2002-2004 John McNamara (Perl Spreadsheet::WriteExcel)
-
-from .BIFFRecords import BiffRecord
-from struct import *
-
-
-def _size_col(sheet, col):
- return sheet.col_width(col)
-
-
-def _size_row(sheet, row):
- return sheet.row_height(row)
-
-
-def _position_image(sheet, row_start, col_start, x1, y1, width, height):
- """Calculate the vertices that define the position of the image as required by
- the OBJ record.
-
- +------------+------------+
- | A | B |
- +-----+------------+------------+
- | |(x1,y1) | |
- | 1 |(A1)._______|______ |
- | | | | |
- | | | | |
- +-----+----| BITMAP |-----+
- | | | | |
- | 2 | |______________. |
- | | | (B2)|
- | | | (x2,y2)|
- +---- +------------+------------+
-
- Example of a bitmap that covers some of the area from cell A1 to cell B2.
-
- Based on the width and height of the bitmap we need to calculate 8 vars:
- col_start, row_start, col_end, row_end, x1, y1, x2, y2.
- The width and height of the cells are also variable and have to be taken into
- account.
- The values of col_start and row_start are passed in from the calling
- function. The values of col_end and row_end are calculated by subtracting
- the width and height of the bitmap from the width and height of the
- underlying cells.
- The vertices are expressed as a percentage of the underlying cell width as
- follows (rhs values are in pixels):
-
- x1 = X / W *1024
- y1 = Y / H *256
- x2 = (X-1) / W *1024
- y2 = (Y-1) / H *256
-
- Where: X is distance from the left side of the underlying cell
- Y is distance from the top of the underlying cell
- W is the width of the cell
- H is the height of the cell
-
- Note: the SDK incorrectly states that the height should be expressed as a
- percentage of 1024.
-
- col_start - Col containing upper left corner of object
- row_start - Row containing top left corner of object
- x1 - Distance to left side of object
- y1 - Distance to top of object
- width - Width of image frame
- height - Height of image frame
-
- """
- # Adjust start column for offsets that are greater than the col width
- while x1 >= _size_col(sheet, col_start):
- x1 -= _size_col(sheet, col_start)
- col_start += 1
- # Adjust start row for offsets that are greater than the row height
- while y1 >= _size_row(sheet, row_start):
- y1 -= _size_row(sheet, row_start)
- row_start += 1
- # Initialise end cell to the same as the start cell
- row_end = row_start # Row containing bottom right corner of object
- col_end = col_start # Col containing lower right corner of object
- width = width + x1 - 1
- height = height + y1 - 1
- # Subtract the underlying cell widths to find the end cell of the image
- while (width >= _size_col(sheet, col_end)):
- width -= _size_col(sheet, col_end)
- col_end += 1
- # Subtract the underlying cell heights to find the end cell of the image
- while (height >= _size_row(sheet, row_end)):
- height -= _size_row(sheet, row_end)
- row_end += 1
- # Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell
- # with zero height or width.
- if ((_size_col(sheet, col_start) == 0) or (_size_col(sheet, col_end) == 0)
- or (_size_row(sheet, row_start) == 0) or (_size_row(sheet, row_end) == 0)):
- return
- # Convert the pixel values to the percentage value expected by Excel
- x1 = int(float(x1) / _size_col(sheet, col_start) * 1024)
- y1 = int(float(y1) / _size_row(sheet, row_start) * 256)
- # Distance to right side of object
- x2 = int(float(width) / _size_col(sheet, col_end) * 1024)
- # Distance to bottom of object
- y2 = int(float(height) / _size_row(sheet, row_end) * 256)
- return (col_start, x1, row_start, y1, col_end, x2, row_end, y2)
-
-
-class ObjBmpRecord(BiffRecord):
- _REC_ID = 0x005D # Record identifier
-
- def __init__(self, row, col, sheet, im_data_bmp, x, y, scale_x, scale_y):
- # Scale the frame of the image.
- width = im_data_bmp.width * scale_x
- height = im_data_bmp.height * scale_y
-
- # Calculate the vertices of the image and write the OBJ record
- coordinates = _position_image(sheet, row, col, x, y, width, height)
- # print coordinates
- col_start, x1, row_start, y1, col_end, x2, row_end, y2 = coordinates
-
- """Store the OBJ record that precedes an IMDATA record. This could be generalise
- to support other Excel objects.
-
- """
- cObj = 0x0001 # Count of objects in file (set to 1)
- OT = 0x0008 # Object type. 8 = Picture
- id = 0x0001 # Object ID
- grbit = 0x0614 # Option flags
- colL = col_start # Col containing upper left corner of object
- dxL = x1 # Distance from left side of cell
- rwT = row_start # Row containing top left corner of object
- dyT = y1 # Distance from top of cell
- colR = col_end # Col containing lower right corner of object
- dxR = x2 # Distance from right of cell
- rwB = row_end # Row containing bottom right corner of object
- dyB = y2 # Distance from bottom of cell
- cbMacro = 0x0000 # Length of FMLA structure
- Reserved1 = 0x0000 # Reserved
- Reserved2 = 0x0000 # Reserved
- icvBack = 0x09 # Background colour
- icvFore = 0x09 # Foreground colour
- fls = 0x00 # Fill pattern
- fAuto = 0x00 # Automatic fill
- icv = 0x08 # Line colour
- lns = 0xff # Line style
- lnw = 0x01 # Line weight
- fAutoB = 0x00 # Automatic border
- frs = 0x0000 # Frame style
- cf = 0x0009 # Image format, 9 = bitmap
- Reserved3 = 0x0000 # Reserved
- cbPictFmla = 0x0000 # Length of FMLA structure
- Reserved4 = 0x0000 # Reserved
- grbit2 = 0x0001 # Option flags
- Reserved5 = 0x0000 # Reserved
-
- data = pack("<L", cObj)
- data += pack("<H", OT)
- data += pack("<H", id)
- data += pack("<H", grbit)
- data += pack("<H", colL)
- data += pack("<H", dxL)
- data += pack("<H", rwT)
- data += pack("<H", dyT)
- data += pack("<H", colR)
- data += pack("<H", dxR)
- data += pack("<H", rwB)
- data += pack("<H", dyB)
- data += pack("<H", cbMacro)
- data += pack("<L", Reserved1)
- data += pack("<H", Reserved2)
- data += pack("<B", icvBack)
- data += pack("<B", icvFore)
- data += pack("<B", fls)
- data += pack("<B", fAuto)
- data += pack("<B", icv)
- data += pack("<B", lns)
- data += pack("<B", lnw)
- data += pack("<B", fAutoB)
- data += pack("<H", frs)
- data += pack("<L", cf)
- data += pack("<H", Reserved3)
- data += pack("<H", cbPictFmla)
- data += pack("<H", Reserved4)
- data += pack("<H", grbit2)
- data += pack("<L", Reserved5)
-
- self._rec_data = data
-
-def _process_bitmap(bitmap):
- """Convert a 24 bit bitmap into the modified internal format used by Windows.
- This is described in BITMAPCOREHEADER and BITMAPCOREINFO structures in the
- MSDN library.
-
- """
- # Open file and binmode the data in case the platform needs it.
- fh = open(bitmap, 'rb')
- try:
- # Slurp the file into a string.
- data = fh.read()
- finally:
- fh.close()
- # Check that the file is big enough to be a bitmap.
- if len(data) <= 0x36:
- raise Exception("bitmap doesn't contain enough data.")
- # The first 2 bytes are used to identify the bitmap.
- if (data[:2] != b"BM"):
- raise Exception("bitmap doesn't appear to to be a valid bitmap image.")
- # Remove bitmap data: ID.
- data = data[2:]
- # Read and remove the bitmap size. This is more reliable than reading
- # the data size at offset 0x22.
- #
- size = unpack("<L", data[:4])[0]
- size -= 0x36 # Subtract size of bitmap header.
- size += 0x0C # Add size of BIFF header.
- data = data[4:]
- # Remove bitmap data: reserved, offset, header length.
- data = data[12:]
- # Read and remove the bitmap width and height. Verify the sizes.
- width, height = unpack("<LL", data[:8])
- data = data[8:]
- if (width > 0xFFFF):
- raise Exception("bitmap: largest image width supported is 65k.")
- if (height > 0xFFFF):
- raise Exception("bitmap: largest image height supported is 65k.")
- # Read and remove the bitmap planes and bpp data. Verify them.
- planes, bitcount = unpack("<HH", data[:4])
- data = data[4:]
- if (bitcount != 24):
- raise Exception("bitmap isn't a 24bit true color bitmap.")
- if (planes != 1):
- raise Exception("bitmap: only 1 plane supported in bitmap image.")
- # Read and remove the bitmap compression. Verify compression.
- compression = unpack("<L", data[:4])[0]
- data = data[4:]
- if (compression != 0):
- raise Exception("bitmap: compression not supported in bitmap image.")
- # Remove bitmap data: data size, hres, vres, colours, imp. colours.
- data = data[20:]
- # Add the BITMAPCOREHEADER data
- header = pack("<LHHHH", 0x000c, width, height, 0x01, 0x18)
- data = header + data
- return (width, height, size, data)
-
-
-class ImDataBmpRecord(BiffRecord):
- _REC_ID = 0x007F
-
- def __init__(self, filename):
- """Insert a 24bit bitmap image in a worksheet. The main record required is
- IMDATA but it must be proceeded by a OBJ record to define its position.
-
- """
- BiffRecord.__init__(self)
-
- self.width, self.height, self.size, data = _process_bitmap(filename)
- # Write the IMDATA record to store the bitmap data
- cf = 0x09
- env = 0x01
- lcb = self.size
- self._rec_data = pack("<HHL", cf, env, lcb) + data
diff --git a/tablib/packages/xlwt3/Cell.py b/tablib/packages/xlwt3/Cell.py
deleted file mode 100644
index 08a9e42..0000000
--- a/tablib/packages/xlwt3/Cell.py
+++ /dev/null
@@ -1,233 +0,0 @@
-from struct import unpack, pack
-from . import BIFFRecords
-
-class StrCell(object):
- __slots__ = ["rowx", "colx", "xf_idx", "sst_idx"]
-
- def __init__(self, rowx, colx, xf_idx, sst_idx):
- self.rowx = rowx
- self.colx = colx
- self.xf_idx = xf_idx
- self.sst_idx = sst_idx
-
- def get_biff_data(self):
- return pack('<5HL', 0x00FD, 10, self.rowx, self.colx, self.xf_idx, self.sst_idx)
-
-class BlankCell(object):
- __slots__ = ["rowx", "colx", "xf_idx"]
-
- def __init__(self, rowx, colx, xf_idx):
- self.rowx = rowx
- self.colx = colx
- self.xf_idx = xf_idx
-
- def get_biff_data(self):
- return pack('<5H', 0x0201, 6, self.rowx, self.colx, self.xf_idx)
-
-class MulBlankCell(object):
- __slots__ = ["rowx", "colx1", "colx2", "xf_idx"]
-
- def __init__(self, rowx, colx1, colx2, xf_idx):
- self.rowx = rowx
- self.colx1 = colx1
- self.colx2 = colx2
- self.xf_idx = xf_idx
-
- def get_biff_data(self):
- return BIFFRecords.MulBlankRecord(self.rowx,
- self.colx1, self.colx2, self.xf_idx).get()
-
-class NumberCell(object):
- __slots__ = ["rowx", "colx", "xf_idx", "number"]
-
- def __init__(self, rowx, colx, xf_idx, number):
- self.rowx = rowx
- self.colx = colx
- self.xf_idx = xf_idx
- self.number = float(number)
-
- def get_encoded_data(self):
- rk_encoded = 0
- num = self.number
-
- # The four possible kinds of RK encoding are *not* mutually exclusive.
- # The 30-bit integer variety picks up the most.
- # In the code below, the four varieties are checked in descending order
- # of bangs per buck, or not at all.
- # SJM 2007-10-01
-
- if -0x20000000 <= num < 0x20000000: # fits in 30-bit *signed* int
- inum = int(num)
- if inum == num: # survives round-trip
- rk_encoded = 2 | (inum << 2)
- return 1, rk_encoded
-
- temp = num * 100
-
- if -0x20000000 <= temp < 0x20000000:
- # That was step 1: the coded value will fit in
- # a 30-bit signed integer.
- itemp = int(round(temp, 0))
- # That was step 2: "itemp" is the best candidate coded value.
- # Now for step 3: simulate the decoding,
- # to check for round-trip correctness.
- if itemp / 100.0 == num:
- rk_encoded = 3 | (itemp << 2)
- return 1, rk_encoded
-
- if 0: # Cost of extra pack+unpack not justified by tiny yield.
- packed = pack('<d', num)
- w01, w23 = unpack('<2i', packed)
- if not w01 and not(w23 & 3):
- return 1, w23
-
- packed100 = pack('<d', temp)
- w01, w23 = unpack('<2i', packed100)
- if not w01 and not(w23 & 3):
- return 1, w23 | 1
-
- return 0, pack('<5Hd', 0x0203, 14, self.rowx, self.colx, self.xf_idx, num)
-
- def get_biff_data(self):
- isRK, value = self.get_encoded_data()
- if isRK:
- return pack('<5Hi', 0x27E, 10, self.rowx, self.colx, self.xf_idx, value)
- return value # NUMBER record already packed
-
-class BooleanCell(object):
- __slots__ = ["rowx", "colx", "xf_idx", "number"]
-
- def __init__(self, rowx, colx, xf_idx, number):
- self.rowx = rowx
- self.colx = colx
- self.xf_idx = xf_idx
- self.number = number
-
- def get_biff_data(self):
- return BIFFRecords.BoolErrRecord(self.rowx,
- self.colx, self.xf_idx, self.number, 0).get()
-
-error_code_map = {
- 0x00: 0, # Intersection of two cell ranges is empty
- 0x07: 7, # Division by zero
- 0x0F: 15, # Wrong type of operand
- 0x17: 23, # Illegal or deleted cell reference
- 0x1D: 29, # Wrong function or range name
- 0x24: 36, # Value range overflow
- 0x2A: 42, # Argument or function not available
- '#NULL!' : 0, # Intersection of two cell ranges is empty
- '#DIV/0!': 7, # Division by zero
- '#VALUE!': 36, # Wrong type of operand
- '#REF!' : 23, # Illegal or deleted cell reference
- '#NAME?' : 29, # Wrong function or range name
- '#NUM!' : 36, # Value range overflow
- '#N/A!' : 42, # Argument or function not available
-}
-
-class ErrorCell(object):
- __slots__ = ["rowx", "colx", "xf_idx", "number"]
-
- def __init__(self, rowx, colx, xf_idx, error_string_or_code):
- self.rowx = rowx
- self.colx = colx
- self.xf_idx = xf_idx
- try:
- self.number = error_code_map[error_string_or_code]
- except KeyError:
- raise Exception('Illegal error value (%r)' % error_string_or_code)
-
- def get_biff_data(self):
- return BIFFRecords.BoolErrRecord(self.rowx,
- self.colx, self.xf_idx, self.number, 1).get()
-
-class FormulaCell(object):
- __slots__ = ["rowx", "colx", "xf_idx", "frmla", "calc_flags"]
-
- def __init__(self, rowx, colx, xf_idx, frmla, calc_flags=0):
- self.rowx = rowx
- self.colx = colx
- self.xf_idx = xf_idx
- self.frmla = frmla
- self.calc_flags = calc_flags
-
- def get_biff_data(self):
- return BIFFRecords.FormulaRecord(self.rowx,
- self.colx, self.xf_idx, self.frmla.rpn(), self.calc_flags).get()
-
-# module-level function for *internal* use by the Row module
-
-def _get_cells_biff_data_mul(rowx, cell_items):
- # Return the BIFF data for all cell records in the row.
- # Adjacent BLANK|RK records are combined into MUL(BLANK|RK) records.
- pieces = []
- nitems = len(cell_items)
- i = 0
- while i < nitems:
- icolx, icell = cell_items[i]
- if isinstance(icell, NumberCell):
- isRK, value = icell.get_encoded_data()
- if not isRK:
- pieces.append(value) # pre-packed NUMBER record
- i += 1
- continue
- muldata = [(value, icell.xf_idx)]
- target = NumberCell
- elif isinstance(icell, BlankCell):
- muldata = [icell.xf_idx]
- target = BlankCell
- else:
- pieces.append(icell.get_biff_data())
- i += 1
- continue
- lastcolx = icolx
- j = i
-
- packed_record = b'' # (to_py3): 'b' binary data
- for j in range(i+1, nitems):
- jcolx, jcell = cell_items[j]
- if jcolx != lastcolx + 1:
- nexti = j
- break
- if not isinstance(jcell, target):
- nexti = j
- break
- if target == NumberCell:
- isRK, value = jcell.get_encoded_data()
- if not isRK:
- packed_record = value
- nexti = j + 1
- break
- muldata.append((value, jcell.xf_idx))
- else:
- muldata.append(jcell.xf_idx)
- lastcolx = jcolx
- else:
- nexti = j + 1
- if target == NumberCell:
- if lastcolx == icolx:
- # RK record
- value, xf_idx = muldata[0]
- pieces.append(pack('<5Hi', 0x027E, 10, rowx, icolx, xf_idx, value))
- else:
- # MULRK record
- nc = lastcolx - icolx + 1
- pieces.append(pack('<4H', 0x00BD, 6 * nc + 6, rowx, icolx))
- # (to_py3): 'b' binary data
- pieces.append(b''.join([pack('<Hi', xf_idx, value) for value, xf_idx in muldata]))
- pieces.append(pack('<H', lastcolx))
- else:
- if lastcolx == icolx:
- # BLANK record
- xf_idx = muldata[0]
- pieces.append(pack('<5H', 0x0201, 6, rowx, icolx, xf_idx))
- else:
- # MULBLANK record
- nc = lastcolx - icolx + 1
- pieces.append(pack('<4H', 0x00BE, 2 * nc + 6, rowx, icolx))
- # (to_py3): 'b' binary data
- pieces.append(b''.join([pack('<H', xf_idx) for xf_idx in muldata]))
- pieces.append(pack('<H', lastcolx))
- if packed_record:
- pieces.append(packed_record)
- i = nexti
- return b''.join(pieces) # (to_py3): 'b' binary data
diff --git a/tablib/packages/xlwt3/Column.py b/tablib/packages/xlwt3/Column.py
deleted file mode 100644
index 4c75a2c..0000000
--- a/tablib/packages/xlwt3/Column.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- coding: windows-1252 -*-
-
-from .BIFFRecords import ColInfoRecord
-
-class Column(object):
- def __init__(self, colx, parent_sheet):
- if not(isinstance(colx, int) and 0 <= colx <= 255):
- raise ValueError("column index (%r) not an int in range(256)" % colx)
- self._index = colx
- self._parent = parent_sheet
- self._parent_wb = parent_sheet.get_parent()
- self._xf_index = 0x0F
-
- self.width = 0x0B92
- self.hidden = 0
- self.level = 0
- self.collapse = 0
-
- def set_style(self, style):
- self._xf_index = self._parent_wb.add_style(style)
-
- def width_in_pixels(self):
- # *** Approximation ****
- return int(round(self.width * 0.0272 + 0.446, 0))
-
- def get_biff_record(self):
- options = (self.hidden & 0x01) << 0
- options |= (self.level & 0x07) << 8
- options |= (self.collapse & 0x01) << 12
-
- return ColInfoRecord(self._index, self._index, self.width, self._xf_index, options).get()
-
-
-
diff --git a/tablib/packages/xlwt3/CompoundDoc.py b/tablib/packages/xlwt3/CompoundDoc.py
deleted file mode 100644
index d53726f..0000000
--- a/tablib/packages/xlwt3/CompoundDoc.py
+++ /dev/null
@@ -1,516 +0,0 @@
-import sys
-import struct
-
-ENCODING = 'utf-16-le'
-
-class Reader:
- def __init__(self, filename, dump = False):
- self.dump = dump
- self.STREAMS = {}
-
- doc = file(filename, 'rb').read()
- self.header, self.data = doc[0:512], doc[512:]
- del doc
-
- self.__build_header()
- self.__build_MSAT()
- self.__build_SAT()
- self.__build_directory()
- self.__build_short_sectors_data()
-
- if len(self.short_sectors_data) > 0:
- self.__build_SSAT()
- else:
- if self.dump and (self.total_ssat_sectors != 0 or self.ssat_start_sid != -2):
- print('NOTE: header says that must be', self.total_ssat_sectors, 'short sectors')
- print('NOTE: starting at', self.ssat_start_sid, 'sector')
- print('NOTE: but file does not contains data in short sectors')
- self.ssat_start_sid = -2
- self.total_ssat_sectors = 0
- self.SSAT = [-2]
-
- for dentry in self.dir_entry_list[1:]:
- (did,
- sz, name,
- t, c,
- did_left, did_right, did_root,
- dentry_start_sid,
- stream_size
- ) = dentry
- stream_data = b''
- if stream_size > 0:
- if stream_size >= self.min_stream_size:
- args = (self.data, self.SAT, dentry_start_sid, self.sect_size)
- else:
- args = (self.short_sectors_data, self.SSAT, dentry_start_sid, self.short_sect_size)
- stream_data = self.get_stream_data(*args)
-
- if name != b'':
- # BAD IDEA: names may be equal. NEED use full paths...
- self.STREAMS[name] = stream_data
-
-
- def __build_header(self):
- self.doc_magic = self.header[0:8]
-
- if self.doc_magic != b'\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1':
- raise Exception('Not an OLE file.')
-
- self.file_uid = self.header[8:24]
- self.rev_num = self.header[24:26]
- self.ver_num = self.header[26:28]
- self.byte_order = self.header[28:30]
- self.log2_sect_size, = struct.unpack('<H', self.header[30:32])
- self.log2_short_sect_size, = struct.unpack('<H', self.header[32:34])
- self.total_sat_sectors, = struct.unpack('<L', self.header[44:48])
- self.dir_start_sid, = struct.unpack('<l', self.header[48:52])
- self.min_stream_size, = struct.unpack('<L', self.header[56:60])
- self.ssat_start_sid, = struct.unpack('<l', self.header[60:64])
- self.total_ssat_sectors, = struct.unpack('<L', self.header[64:68])
- self.msat_start_sid, = struct.unpack('<l', self.header[68:72])
- self.total_msat_sectors, = struct.unpack('<L', self.header[72:76])
-
- self.sect_size = 1 << self.log2_sect_size
- self.short_sect_size = 1 << self.log2_short_sect_size
-
- if self.dump:
- print('file magic: ')
- print_bin_data(self.doc_magic)
-
- print('file uid: ')
- print_bin_data(self.file_uid)
-
- print('revision number: ')
- print_bin_data(self.rev_num)
-
- print('version number: ')
- print_bin_data(self.ver_num)
-
- print('byte order: ')
- print_bin_data(self.byte_order)
-
- print('sector size :', hex(self.sect_size), self.sect_size)
- #print 'total sectors in file :', hex(self.total_sectors), self.total_sectors
- print('short sector size :', hex(self.short_sect_size), self.short_sect_size)
- print('Total number of sectors used for the SAT :', hex(self.total_sat_sectors), self.total_sat_sectors)
- print('SID of first sector of the directory stream:', hex(self.dir_start_sid), self.dir_start_sid)
- print('Minimum size of a standard stream :', hex(self.min_stream_size), self.min_stream_size)
- print('SID of first sector of the SSAT :', hex(self.ssat_start_sid), self.ssat_start_sid)
- print('Total number of sectors used for the SSAT :', hex(self.total_ssat_sectors), self.total_ssat_sectors)
- print('SID of first additional sector of the MSAT :', hex(self.msat_start_sid), self.msat_start_sid)
- print('Total number of sectors used for the MSAT :', hex(self.total_msat_sectors), self.total_msat_sectors)
-
-
- def __build_MSAT(self):
- self.MSAT = list(struct.unpack('<109l', self.header[76:]))
-
- next = self.msat_start_sid
- while next > 0:
- msat_sector = struct.unpack('<128l', self.data[next*self.sect_size:(next+1)*self.sect_size])
- self.MSAT.extend(msat_sector[:127])
- next = msat_sector[-1]
-
- if self.dump:
- print('MSAT (header part): \n', self.MSAT[:109])
- print('additional MSAT sectors: \n', self.MSAT[109:])
-
-
- def __build_SAT(self):
- sat_stream = b''.join([self.data[i*self.sect_size:(i+1)*self.sect_size] for i in self.MSAT if i >= 0])
-
- sat_sids_count = len(sat_stream) >> 2
- self.SAT = struct.unpack('<%dl' % sat_sids_count, sat_stream) # SIDs tuple
-
- if self.dump:
- print('SAT sid count:\n', sat_sids_count)
- print('SAT content:\n', self.SAT)
-
-
- def __build_SSAT(self):
- ssat_stream = self.get_stream_data(self.data, self.SAT, self.ssat_start_sid, self.sect_size)
-
- ssids_count = len(ssat_stream) >> 2
- self.SSAT = struct.unpack('<%dl' % ssids_count, ssat_stream)
-
- if self.dump:
- print('SSID count:', ssids_count)
- print('SSAT content:\n', self.SSAT)
-
-
- def __build_directory(self):
- dir_stream = self.get_stream_data(self.data, self.SAT, self.dir_start_sid, self.sect_size)
-
- self.dir_entry_list = []
-
- i = 0
- while i < len(dir_stream):
- dentry = dir_stream[i:i+128] # 128 -- dir entry size
- i += 128
-
- did = len(self.dir_entry_list)
- sz, = struct.unpack('<H', dentry[64:66])
- if sz > 0 :
- name = dentry[0:sz-2].decode('utf_16_le', 'replace')
- else:
- name = b''
- t, = struct.unpack('B', dentry[66])
- c, = struct.unpack('B', dentry[67])
- did_left , = struct.unpack('<l', dentry[68:72])
- did_right , = struct.unpack('<l', dentry[72:76])
- did_root , = struct.unpack('<l', dentry[76:80])
- dentry_start_sid , = struct.unpack('<l', dentry[116:120])
- stream_size , = struct.unpack('<L', dentry[120:124])
-
- self.dir_entry_list.extend([(did, sz, name, t, c,
- did_left, did_right, did_root,
- dentry_start_sid, stream_size)])
-
- if self.dump:
- dentry_types = {
- 0x00: 'Empty',
- 0x01: 'User storage',
- 0x02: 'User stream',
- 0x03: 'LockBytes',
- 0x04: 'Property',
- 0x05: 'Root storage'
- }
- node_colours = {
- 0x00: 'Red',
- 0x01: 'Black'
- }
- print('total directory entries:', len(self.dir_entry_list))
-
- for dentry in self.dir_entry_list:
- (did, sz, name, t, c,
- did_left, did_right, did_root,
- dentry_start_sid, stream_size) = dentry
- print('DID', did)
- print('Size of the used area of the character buffer of the name:', sz)
- print('dir entry name:', repr(name))
- print('type of entry:', t, dentry_types[t])
- print('entry colour:', c, node_colours[c])
- print('left child DID :', did_left)
- print('right child DID:', did_right)
- print('root DID :', did_root)
- print('start SID :', dentry_start_sid)
- print('stream size :', stream_size)
- if stream_size == 0:
- print('stream is empty')
- elif stream_size >= self.min_stream_size:
- print('stream stored as normal stream')
- else:
- print('stream stored as short-stream')
-
-
- def __build_short_sectors_data(self):
- (did, sz, name, t, c,
- did_left, did_right, did_root,
- dentry_start_sid, stream_size) = self.dir_entry_list[0]
- assert t == 0x05 # Short-Stream Container Stream (SSCS) resides in Root Storage
- if stream_size == 0:
- self.short_sectors_data = b''
- else:
- self.short_sectors_data = self.get_stream_data(self.data, self.SAT, dentry_start_sid, self.sect_size)
-
-
- def get_stream_data(self, data, SAT, start_sid, sect_size):
- sid = start_sid
- chunks = [(sid, sid)]
- stream_data = b''
-
- while SAT[sid] >= 0:
- next_in_chain = SAT[sid]
- last_chunk_start, last_chunk_finish = chunks[-1]
- if next_in_chain == last_chunk_finish + 1:
- chunks[-1] = last_chunk_start, next_in_chain
- else:
- chunks.extend([(next_in_chain, next_in_chain)])
- sid = next_in_chain
- for s, f in chunks:
- stream_data += data[s*sect_size:(f+1)*sect_size]
- #print chunks
- return stream_data
-
-
-def print_bin_data(data):
- i = 0
- while i < len(data):
- j = 0
- while (i < len(data)) and (j < 16):
- c = b'0x%02X' % ord(data[i])
- sys.stdout.write(c)
- sys.stdout.write(' ')
- i += 1
- j += 1
- print()
- if i == 0:
- print('<NO DATA>')
-
-
-
-# This implementation writes only 'Root Entry', 'Workbook' streams
-# and 2 empty streams for aligning directory stream on sector boundary
-#
-# LAYOUT:
-# 0 header
-# 76 MSAT (1st part: 109 SID)
-# 512 workbook stream
-# ... additional MSAT sectors if streams' size > about 7 Mb == (109*512 * 128)
-# ... SAT
-# ... directory stream
-#
-# NOTE: this layout is "ad hoc". It can be more general. RTFM
-
-class XlsDoc:
- SECTOR_SIZE = 0x0200
- MIN_LIMIT = 0x1000
-
- SID_FREE_SECTOR = -1
- SID_END_OF_CHAIN = -2
- SID_USED_BY_SAT = -3
- SID_USED_BY_MSAT = -4
-
- def __init__(self):
- self.book_stream_sect = []
-
- self.dir_stream = b''
- self.dir_stream_sect = []
-
- self.packed_SAT = b''
- self.SAT_sect = []
-
- self.packed_MSAT_1st = b''
- self.packed_MSAT_2nd = b''
- self.MSAT_sect_2nd = []
-
- self.header = b''
-
- def __build_directory(self): # align on sector boundary
- self.dir_stream = b''
-
- #(to_py3): replaced = b'\x00'.join(b'Root Entry\x00') + b'\x00'
- dentry_name = 'Root Entry\x00'.encode(ENCODING)
- dentry_name_sz = len(dentry_name)
- dentry_name_pad = b'\x00'*(64 - dentry_name_sz)
- dentry_type = 0x05 # root storage
- dentry_colour = 0x01 # black
- dentry_did_left = -1
- dentry_did_right = -1
- dentry_did_root = 1
- dentry_start_sid = -2
- dentry_stream_sz = 0
-
- self.dir_stream += struct.pack('<64s H 2B 3l 9L l L L',
- dentry_name + dentry_name_pad,
- dentry_name_sz,
- dentry_type,
- dentry_colour,
- dentry_did_left,
- dentry_did_right,
- dentry_did_root,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,
- dentry_start_sid,
- dentry_stream_sz,
- 0
- )
- # (to_py3): replaced = b'\x00'.join(b'Workbook\x00') + b'\x00'
- dentry_name = 'Workbook\x00'.encode(ENCODING)
- dentry_name_sz = len(dentry_name)
- dentry_name_pad = b'\x00'*(64 - dentry_name_sz)
- dentry_type = 0x02 # user stream
- dentry_colour = 0x01 # black
- dentry_did_left = -1
- dentry_did_right = -1
- dentry_did_root = -1
- dentry_start_sid = 0
- dentry_stream_sz = self.book_stream_len
-
- self.dir_stream += struct.pack('<64s H 2B 3l 9L l L L',
- dentry_name + dentry_name_pad,
- dentry_name_sz,
- dentry_type,
- dentry_colour,
- dentry_did_left,
- dentry_did_right,
- dentry_did_root,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,
- dentry_start_sid,
- dentry_stream_sz,
- 0
- )
-
- # padding
- dentry_name = b''
- dentry_name_sz = len(dentry_name)
- dentry_name_pad = b'\x00'*(64 - dentry_name_sz)
- dentry_type = 0x00 # empty
- dentry_colour = 0x01 # black
- dentry_did_left = -1
- dentry_did_right = -1
- dentry_did_root = -1
- dentry_start_sid = -2
- dentry_stream_sz = 0
-
- self.dir_stream += struct.pack('<64s H 2B 3l 9L l L L',
- dentry_name + dentry_name_pad,
- dentry_name_sz,
- dentry_type,
- dentry_colour,
- dentry_did_left,
- dentry_did_right,
- dentry_did_root,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,
- dentry_start_sid,
- dentry_stream_sz,
- 0
- ) * 2
-
- def __build_sat(self):
- # Build SAT
- book_sect_count = self.book_stream_len >> 9
- dir_sect_count = len(self.dir_stream) >> 9
-
- total_sect_count = book_sect_count + dir_sect_count
- SAT_sect_count = 0
- MSAT_sect_count = 0
- SAT_sect_count_limit = 109
- while total_sect_count > 128*SAT_sect_count or SAT_sect_count > SAT_sect_count_limit:
- SAT_sect_count += 1
- total_sect_count += 1
- if SAT_sect_count > SAT_sect_count_limit:
- MSAT_sect_count += 1
- total_sect_count += 1
- SAT_sect_count_limit += 127
-
-
- SAT = [self.SID_FREE_SECTOR]*128*SAT_sect_count
-
- sect = 0
- while sect < book_sect_count - 1:
- self.book_stream_sect.append(sect)
- SAT[sect] = sect + 1
- sect += 1
- self.book_stream_sect.append(sect)
- SAT[sect] = self.SID_END_OF_CHAIN
- sect += 1
-
- while sect < book_sect_count + MSAT_sect_count:
- self.MSAT_sect_2nd.append(sect)
- SAT[sect] = self.SID_USED_BY_MSAT
- sect += 1
-
- while sect < book_sect_count + MSAT_sect_count + SAT_sect_count:
- self.SAT_sect.append(sect)
- SAT[sect] = self.SID_USED_BY_SAT
- sect += 1
-
- while sect < book_sect_count + MSAT_sect_count + SAT_sect_count + dir_sect_count - 1:
- self.dir_stream_sect.append(sect)
- SAT[sect] = sect + 1
- sect += 1
- self.dir_stream_sect.append(sect)
- SAT[sect] = self.SID_END_OF_CHAIN
- sect += 1
-
- self.packed_SAT = struct.pack('<%dl' % (SAT_sect_count*128), *SAT)
-
- MSAT_1st = [self.SID_FREE_SECTOR]*109
- for i, SAT_sect_num in zip(list(range(0, 109)), self.SAT_sect):
- MSAT_1st[i] = SAT_sect_num
- self.packed_MSAT_1st = struct.pack('<109l', *MSAT_1st)
-
- MSAT_2nd = [self.SID_FREE_SECTOR]*128*MSAT_sect_count
- if MSAT_sect_count > 0:
- MSAT_2nd[- 1] = self.SID_END_OF_CHAIN
-
- i = 109
- msat_sect = 0
- sid_num = 0
- while i < SAT_sect_count:
- if (sid_num + 1) % 128 == 0:
- #print 'link: ',
- msat_sect += 1
- if msat_sect < len(self.MSAT_sect_2nd):
- MSAT_2nd[sid_num] = self.MSAT_sect_2nd[msat_sect]
- else:
- #print 'sid: ',
- MSAT_2nd[sid_num] = self.SAT_sect[i]
- i += 1
- #print sid_num, MSAT_2nd[sid_num]
- sid_num += 1
-
- self.packed_MSAT_2nd = struct.pack('<%dl' % (MSAT_sect_count*128), *MSAT_2nd)
-
- #print vars()
- #print zip(range(0, sect), SAT)
- #print self.book_stream_sect
- #print self.MSAT_sect_2nd
- #print MSAT_2nd
- #print self.SAT_sect
- #print self.dir_stream_sect
-
-
- def __build_header(self):
- doc_magic = b'\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1'
- file_uid = b'\x00'*16
- rev_num = b'\x3E\x00'
- ver_num = b'\x03\x00'
- byte_order = b'\xFE\xFF'
- log_sect_size = struct.pack('<H', 9)
- log_short_sect_size = struct.pack('<H', 6)
- not_used0 = b'\x00'*10
- total_sat_sectors = struct.pack('<L', len(self.SAT_sect))
- dir_start_sid = struct.pack('<l', self.dir_stream_sect[0])
- not_used1 = b'\x00'*4
- min_stream_size = struct.pack('<L', 0x1000)
- ssat_start_sid = struct.pack('<l', -2)
- total_ssat_sectors = struct.pack('<L', 0)
-
- if len(self.MSAT_sect_2nd) == 0:
- msat_start_sid = struct.pack('<l', -2)
- else:
- msat_start_sid = struct.pack('<l', self.MSAT_sect_2nd[0])
-
- total_msat_sectors = struct.pack('<L', len(self.MSAT_sect_2nd))
-
- self.header = b''.join([ doc_magic,
- file_uid,
- rev_num,
- ver_num,
- byte_order,
- log_sect_size,
- log_short_sect_size,
- not_used0,
- total_sat_sectors,
- dir_start_sid,
- not_used1,
- min_stream_size,
- ssat_start_sid,
- total_ssat_sectors,
- msat_start_sid,
- total_msat_sectors
- ])
-
-
- def save(self, file_name_or_filelike_obj, stream):
- # 1. Align stream on 0x1000 boundary (and therefore on sector boundary)
- padding = b'\x00' * (0x1000 - (len(stream) % 0x1000))
- self.book_stream_len = len(stream) + len(padding)
-
- self.__build_directory()
- self.__build_sat()
- self.__build_header()
-
- f = file_name_or_filelike_obj
- we_own_it = not hasattr(f, 'write')
- if we_own_it:
- f = open(file_name_or_filelike_obj, 'wb')
- f.write(self.header)
- f.write(self.packed_MSAT_1st)
- f.write(stream)
- f.write(padding)
- f.write(self.packed_MSAT_2nd)
- f.write(self.packed_SAT)
- f.write(self.dir_stream)
- if we_own_it:
- f.close()
diff --git a/tablib/packages/xlwt3/ExcelFormula.py b/tablib/packages/xlwt3/ExcelFormula.py
deleted file mode 100644
index f7cc771..0000000
--- a/tablib/packages/xlwt3/ExcelFormula.py
+++ /dev/null
@@ -1,41 +0,0 @@
-from . import ExcelFormulaParser, ExcelFormulaLexer
-import struct
-from .antlr import ANTLRException
-
-
-class Formula(object):
- __slots__ = ["__s", "__parser", "__sheet_refs", "__xcall_refs"]
-
-
- def __init__(self, s):
- try:
- self.__s = s
- lexer = ExcelFormulaLexer.Lexer(s)
- self.__parser = ExcelFormulaParser.Parser(lexer)
- self.__parser.formula()
- self.__sheet_refs = self.__parser.sheet_references
- self.__xcall_refs = self.__parser.xcall_references
- except ANTLRException as e:
- # print e
- raise ExcelFormulaParser.FormulaParseException("can't parse formula " + s)
-
- def get_references(self):
- return self.__sheet_refs, self.__xcall_refs
-
- def patch_references(self, patches):
- for offset, idx in patches:
- self.__parser.rpn = self.__parser.rpn[:offset] + struct.pack('<H', idx) + self.__parser.rpn[offset+2:]
-
- def text(self):
- return self.__s
-
- def rpn(self):
- '''
- Offset Size Contents
- 0 2 Size of the following formula data (sz)
- 2 sz Formula data (RPN token array)
- [2+sz] var. (optional) Additional data for specific tokens
-
- '''
- return struct.pack("<H", len(self.__parser.rpn)) + self.__parser.rpn
-
diff --git a/tablib/packages/xlwt3/ExcelFormulaLexer.py b/tablib/packages/xlwt3/ExcelFormulaLexer.py
deleted file mode 100644
index 9b6103c..0000000
--- a/tablib/packages/xlwt3/ExcelFormulaLexer.py
+++ /dev/null
@@ -1,126 +0,0 @@
-import sys
-from .antlr import EOF, CommonToken as Tok, TokenStream, TokenStreamException
-import struct
-from . import ExcelFormulaParser
-from re import compile as recompile, match, UNICODE, IGNORECASE, VERBOSE
-
-
-int_const_pattern = r"\d+\b"
-flt_const_pattern = r"""
- (?:
- (?: \d* \. \d+ ) # .1 .12 .123 etc 9.1 etc 98.1 etc
- |
- (?: \d+ \. ) # 1. 12. 123. etc
- )
- # followed by optional exponent part
- (?: [Ee] [+-]? \d+ ) ?
- """
-str_const_pattern = r'"(?:[^"]|"")*"'
-#range2d_pattern = recompile(r"\$?[A-I]?[A-Z]\$?\d+:\$?[A-I]?[A-Z]\$?\d+"
-ref2d_r1c1_pattern = r"[Rr]0*[1-9][0-9]*[Cc]0*[1-9][0-9]*"
-ref2d_pattern = r"\$?[A-I]?[A-Z]\$?0*[1-9][0-9]*"
-true_pattern = r"TRUE\b"
-false_pattern = r"FALSE\b"
-if_pattern = r"IF\b"
-choose_pattern = r"CHOOSE\b"
-name_pattern = r"\w[\.\w]*"
-quotename_pattern = r"'(?:[^']|'')*'" #### It's essential that this bracket be non-grouping.
-ne_pattern = r"<>"
-ge_pattern = r">="
-le_pattern = r"<="
-
-pattern_type_tuples = (
- (flt_const_pattern, ExcelFormulaParser.NUM_CONST),
- (int_const_pattern, ExcelFormulaParser.INT_CONST),
- (str_const_pattern, ExcelFormulaParser.STR_CONST),
-# (range2d_pattern , ExcelFormulaParser.RANGE2D),
- (ref2d_r1c1_pattern, ExcelFormulaParser.REF2D_R1C1),
- (ref2d_pattern , ExcelFormulaParser.REF2D),
- (true_pattern , ExcelFormulaParser.TRUE_CONST),
- (false_pattern , ExcelFormulaParser.FALSE_CONST),
- (if_pattern , ExcelFormulaParser.FUNC_IF),
- (choose_pattern , ExcelFormulaParser.FUNC_CHOOSE),
- (name_pattern , ExcelFormulaParser.NAME),
- (quotename_pattern, ExcelFormulaParser.QUOTENAME),
- (ne_pattern, ExcelFormulaParser.NE),
- (ge_pattern, ExcelFormulaParser.GE),
- (le_pattern, ExcelFormulaParser.LE),
-)
-
-_re = recompile(
- '(' + ')|('.join([i[0] for i in pattern_type_tuples]) + ')',
- VERBOSE+IGNORECASE)
-
-_toktype = [None] + [i[1] for i in pattern_type_tuples]
-# need dummy at start because re.MatchObject.lastindex counts from 1
-
-single_char_lookup = {
- '=': ExcelFormulaParser.EQ,
- '<': ExcelFormulaParser.LT,
- '>': ExcelFormulaParser.GT,
- '+': ExcelFormulaParser.ADD,
- '-': ExcelFormulaParser.SUB,
- '*': ExcelFormulaParser.MUL,
- '/': ExcelFormulaParser.DIV,
- ':': ExcelFormulaParser.COLON,
- ';': ExcelFormulaParser.SEMICOLON,
- ',': ExcelFormulaParser.COMMA,
- '(': ExcelFormulaParser.LP,
- ')': ExcelFormulaParser.RP,
- '&': ExcelFormulaParser.CONCAT,
- '%': ExcelFormulaParser.PERCENT,
- '^': ExcelFormulaParser.POWER,
- '!': ExcelFormulaParser.BANG,
- }
-
-class Lexer(TokenStream):
- def __init__(self, text):
- self._text = text[:]
- self._pos = 0
- self._line = 0
-
- def isEOF(self):
- return len(self._text) <= self._pos
-
- def curr_ch(self):
- return self._text[self._pos]
-
- def next_ch(self, n = 1):
- self._pos += n
-
- def is_whitespace(self):
- return self.curr_ch() in " \t\n\r\f\v"
-
- def match_pattern(self):
- m = _re.match(self._text, self._pos)
- if not m:
- return None
- self._pos = m.end(0)
- return Tok(type = _toktype[m.lastindex], text = m.group(0), col = m.start(0) + 1)
-
- def nextToken(self):
- # skip whitespace
- while not self.isEOF() and self.is_whitespace():
- self.next_ch()
- if self.isEOF():
- return Tok(type = EOF)
- # first, try to match token with 2 or more chars
- t = self.match_pattern()
- if t:
- return t
- # second, we want 1-char tokens
- te = self.curr_ch()
- try:
- ty = single_char_lookup[te]
- except KeyError:
- raise TokenStreamException(
- "Unexpected char %r in column %u." % (self.curr_ch(), self._pos))
- self.next_ch()
- return Tok(type=ty, text=te, col=self._pos)
-
-if __name__ == '__main__':
- try:
- for t in Lexer(""" 1.23 456 "abcd" R2C2 a1 iv65536 true false if choose a_name 'qname' <> >= <= """):
- print(t)
- except TokenStreamException as e:
- print("error:", e)
diff --git a/tablib/packages/xlwt3/ExcelFormulaParser.py b/tablib/packages/xlwt3/ExcelFormulaParser.py
deleted file mode 100644
index 5e73934..0000000
--- a/tablib/packages/xlwt3/ExcelFormulaParser.py
+++ /dev/null
@@ -1,659 +0,0 @@
-### $ANTLR 2.7.7 (20060930): "xlwt/excel-formula.g" -> "ExcelFormulaParser.py"$
-### import antlr and other modules ..
-import sys
-from . import antlr
-
-### header action >>>
-import struct
-from . import Utils
-from .UnicodeUtils import upack1
-from .ExcelMagic import *
-
-_RVAdelta = {"R": 0, "V": 0x20, "A": 0x40}
-_RVAdeltaRef = {"R": 0, "V": 0x20, "A": 0x40, "D": 0x20}
-_RVAdeltaArea = {"R": 0, "V": 0x20, "A": 0x40, "D": 0}
-
-
-class FormulaParseException(Exception):
- """
- An exception indicating that a Formula could not be successfully parsed.
- """
-### header action <<<
-### preamble action>>>
-
-### preamble action <<<
-
-### import antlr.Token
-from .antlr import Token
-### >>>The Known Token Types <<<
-SKIP = antlr.SKIP
-INVALID_TYPE = antlr.INVALID_TYPE
-EOF_TYPE = antlr.EOF_TYPE
-EOF = antlr.EOF
-NULL_TREE_LOOKAHEAD = antlr.NULL_TREE_LOOKAHEAD
-MIN_USER_TYPE = antlr.MIN_USER_TYPE
-TRUE_CONST = 4
-FALSE_CONST = 5
-STR_CONST = 6
-NUM_CONST = 7
-INT_CONST = 8
-FUNC_IF = 9
-FUNC_CHOOSE = 10
-NAME = 11
-QUOTENAME = 12
-EQ = 13
-NE = 14
-GT = 15
-LT = 16
-GE = 17
-LE = 18
-ADD = 19
-SUB = 20
-MUL = 21
-DIV = 22
-POWER = 23
-PERCENT = 24
-LP = 25
-RP = 26
-LB = 27
-RB = 28
-COLON = 29
-COMMA = 30
-SEMICOLON = 31
-REF2D = 32
-REF2D_R1C1 = 33
-BANG = 34
-CONCAT = 35
-
-class Parser(antlr.LLkParser):
- ### user action >>>
- ### user action <<<
-
- def __init__(self, *args, **kwargs):
- antlr.LLkParser.__init__(self, *args, **kwargs)
- self.tokenNames = _tokenNames
- ### __init__ header action >>>
- self.rpn = b""
- self.sheet_references = []
- self.xcall_references = []
- ### __init__ header action <<<
-
- def formula(self):
- self.expr("V")
-
- def expr(self, arg_type):
- self.prec0_expr(arg_type)
- while True:
- if ((self.LA(1) >= EQ and self.LA(1) <= LE)):
- pass
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [EQ]:
- pass
- self.match(EQ)
- op = struct.pack('B', ptgEQ)
- elif la1 and la1 in [NE]:
- pass
- self.match(NE)
- op = struct.pack('B', ptgNE)
- elif la1 and la1 in [GT]:
- pass
- self.match(GT)
- op = struct.pack('B', ptgGT)
- elif la1 and la1 in [LT]:
- pass
- self.match(LT)
- op = struct.pack('B', ptgLT)
- elif la1 and la1 in [GE]:
- pass
- self.match(GE)
- op = struct.pack('B', ptgGE)
- elif la1 and la1 in [LE]:
- pass
- self.match(LE)
- op = struct.pack('B', ptgLE)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- self.prec0_expr(arg_type)
- self.rpn += op
- else:
- break
-
-
- def prec0_expr(self,
- arg_type
- ):
-
- pass
- self.prec1_expr(arg_type)
- while True:
- if (self.LA(1)==CONCAT):
- pass
- pass
- self.match(CONCAT)
- op = struct.pack('B', ptgConcat)
- self.prec1_expr(arg_type)
- self.rpn += op
- else:
- break
-
-
- def prec1_expr(self,
- arg_type
- ):
-
- pass
- self.prec2_expr(arg_type)
- while True:
- if (self.LA(1)==ADD or self.LA(1)==SUB):
- pass
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [ADD]:
- pass
- self.match(ADD)
- op = struct.pack('B', ptgAdd)
- elif la1 and la1 in [SUB]:
- pass
- self.match(SUB)
- op = struct.pack('B', ptgSub)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- self.prec2_expr(arg_type)
- self.rpn += op;
- # print "**prec1_expr4 %s" % arg_type
- else:
- break
-
-
- def prec2_expr(self,
- arg_type
- ):
-
- pass
- self.prec3_expr(arg_type)
- while True:
- if (self.LA(1)==MUL or self.LA(1)==DIV):
- pass
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [MUL]:
- pass
- self.match(MUL)
- op = struct.pack('B', ptgMul)
- elif la1 and la1 in [DIV]:
- pass
- self.match(DIV)
- op = struct.pack('B', ptgDiv)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- self.prec3_expr(arg_type)
- self.rpn += op
- else:
- break
-
-
- def prec3_expr(self,
- arg_type
- ):
-
- pass
- self.prec4_expr(arg_type)
- while True:
- if (self.LA(1)==POWER):
- pass
- pass
- self.match(POWER)
- op = struct.pack('B', ptgPower)
- self.prec4_expr(arg_type)
- self.rpn += op
- else:
- break
-
-
- def prec4_expr(self,
- arg_type
- ):
-
- pass
- self.prec5_expr(arg_type)
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [PERCENT]:
- pass
- self.match(PERCENT)
- self.rpn += struct.pack('B', ptgPercent)
- elif la1 and la1 in [EOF,EQ,NE,GT,LT,GE,LE,ADD,SUB,MUL,DIV,POWER,RP,COMMA,SEMICOLON,CONCAT]:
- pass
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
-
- def prec5_expr(self,
- arg_type
- ):
-
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,FUNC_IF,FUNC_CHOOSE,NAME,QUOTENAME,LP,REF2D]:
- pass
- self.primary(arg_type)
- elif la1 and la1 in [SUB]:
- pass
- self.match(SUB)
- self.primary(arg_type)
- self.rpn += struct.pack('B', ptgUminus)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
-
- def primary(self,
- arg_type
- ):
-
- str_tok = None
- int_tok = None
- num_tok = None
- ref2d_tok = None
- ref2d1_tok = None
- ref2d2_tok = None
- ref3d_ref2d = None
- ref3d_ref2d2 = None
- name_tok = None
- func_tok = None
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [TRUE_CONST]:
- pass
- self.match(TRUE_CONST)
- self.rpn += struct.pack("2B", ptgBool, 1)
- elif la1 and la1 in [FALSE_CONST]:
- pass
- self.match(FALSE_CONST)
- self.rpn += struct.pack("2B", ptgBool, 0)
- elif la1 and la1 in [STR_CONST]:
- pass
- str_tok = self.LT(1)
- self.match(STR_CONST)
- self.rpn += struct.pack("B", ptgStr) + upack1(str_tok.text[1:-1].replace("\"\"", "\""))
- elif la1 and la1 in [NUM_CONST]:
- pass
- num_tok = self.LT(1)
- self.match(NUM_CONST)
- self.rpn += struct.pack("<Bd", ptgNum, float(num_tok.text))
- elif la1 and la1 in [FUNC_IF]:
- pass
- self.match(FUNC_IF)
- self.match(LP)
- self.expr("V")
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [SEMICOLON]:
- pass
- self.match(SEMICOLON)
- elif la1 and la1 in [COMMA]:
- pass
- self.match(COMMA)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- self.rpn += struct.pack("<BBH", ptgAttr, 0x02, 0) # tAttrIf
- pos0 = len(self.rpn) - 2
- self.expr(arg_type)
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [SEMICOLON]:
- pass
- self.match(SEMICOLON)
- elif la1 and la1 in [COMMA]:
- pass
- self.match(COMMA)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- self.rpn += struct.pack("<BBH", ptgAttr, 0x08, 0) # tAttrSkip
- pos1 = len(self.rpn) - 2
- self.rpn = self.rpn[:pos0] + struct.pack("<H", pos1-pos0) + self.rpn[pos0+2:]
- self.expr(arg_type)
- self.match(RP)
- self.rpn += struct.pack("<BBH", ptgAttr, 0x08, 3) # tAttrSkip
- self.rpn += struct.pack("<BBH", ptgFuncVarR, 3, 1) # 3 = nargs, 1 = IF func
- pos2 = len(self.rpn)
- self.rpn = self.rpn[:pos1] + struct.pack("<H", pos2-(pos1+2)-1) + self.rpn[pos1+2:]
- elif la1 and la1 in [FUNC_CHOOSE]:
- pass
- self.match(FUNC_CHOOSE)
- arg_type = b"R"
- rpn_chunks = []
- self.match(LP)
- self.expr("V")
- rpn_start = len(self.rpn)
- ref_markers = [len(self.sheet_references)]
- while True:
- if (self.LA(1)==COMMA or self.LA(1)==SEMICOLON):
- pass
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [SEMICOLON]:
- pass
- self.match(SEMICOLON)
- elif la1 and la1 in [COMMA]:
- pass
- self.match(COMMA)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- mark = len(self.rpn)
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,FUNC_IF,FUNC_CHOOSE,NAME,QUOTENAME,SUB,LP,REF2D]:
- pass
- self.expr(arg_type)
- elif la1 and la1 in [RP,COMMA,SEMICOLON]:
- pass
- self.rpn += struct.pack("B", ptgMissArg)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- rpn_chunks.append(self.rpn[mark:])
- ref_markers.append(len(self.sheet_references))
- else:
- break
-
- self.match(RP)
- self.rpn = self.rpn[:rpn_start]
- nc = len(rpn_chunks)
- chunklens = [len(chunk) for chunk in rpn_chunks]
- skiplens = [0] * nc
- skiplens[-1] = 3
- for ic in range(nc-1, 0, -1):
- skiplens[ic-1] = skiplens[ic] + chunklens[ic] + 4
- jump_pos = [2 * nc + 2]
- for ic in range(nc):
- jump_pos.append(jump_pos[-1] + chunklens[ic] + 4)
- chunk_shift = 2 * nc + 6 # size of tAttrChoose
- for ic in range(nc):
- for refx in range(ref_markers[ic], ref_markers[ic+1]):
- ref = self.sheet_references[refx]
- self.sheet_references[refx] = (ref[0], ref[1], ref[2] + chunk_shift)
- chunk_shift += 4 # size of tAttrSkip
- choose_rpn = []
- choose_rpn.append(struct.pack("<BBH", ptgAttr, 0x04, nc)) # 0x04 is tAttrChoose
- choose_rpn.append(struct.pack("<%dH" % (nc+1), *jump_pos))
- for ic in range(nc):
- choose_rpn.append(rpn_chunks[ic])
- choose_rpn.append(struct.pack("<BBH", ptgAttr, 0x08, skiplens[ic])) # 0x08 is tAttrSkip
- choose_rpn.append(struct.pack("<BBH", ptgFuncVarV, nc+1, 100)) # 100 is CHOOSE fn
- self.rpn += b"".join(choose_rpn)
- elif la1 and la1 in [LP]:
- pass
- self.match(LP)
- self.expr(arg_type)
- self.match(RP)
- self.rpn += struct.pack("B", ptgParen)
- else:
- if (self.LA(1)==INT_CONST) and (_tokenSet_0.member(self.LA(2))):
- pass
- int_tok = self.LT(1)
- self.match(INT_CONST)
- # print "**int_const", int_tok.text
- int_value = int(int_tok.text)
- if int_value <= 65535:
- self.rpn += struct.pack("<BH", ptgInt, int_value)
- else:
- self.rpn += struct.pack("<Bd", ptgNum, float(int_value))
- elif (self.LA(1)==REF2D) and (_tokenSet_0.member(self.LA(2))):
- pass
- ref2d_tok = self.LT(1)
- self.match(REF2D)
- # print "**ref2d %s %s" % (ref2d_tok.text, arg_type)
- r, c = Utils.cell_to_packed_rowcol(ref2d_tok.text)
- ptg = ptgRefR + _RVAdeltaRef[arg_type]
- self.rpn += struct.pack("<B2H", ptg, r, c)
- elif (self.LA(1)==REF2D) and (self.LA(2)==COLON):
- pass
- ref2d1_tok = self.LT(1)
- self.match(REF2D)
- self.match(COLON)
- ref2d2_tok = self.LT(1)
- self.match(REF2D)
- r1, c1 = Utils.cell_to_packed_rowcol(ref2d1_tok.text)
- r2, c2 = Utils.cell_to_packed_rowcol(ref2d2_tok.text)
- ptg = ptgAreaR + _RVAdeltaArea[arg_type]
- self.rpn += struct.pack("<B4H", ptg, r1, r2, c1, c2)
- elif (self.LA(1)==INT_CONST or self.LA(1)==NAME or self.LA(1)==QUOTENAME) and (self.LA(2)==COLON or self.LA(2)==BANG):
- pass
- sheet1=self.sheet()
- sheet2 = sheet1
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [COLON]:
- pass
- self.match(COLON)
- sheet2=self.sheet()
- elif la1 and la1 in [BANG]:
- pass
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- self.match(BANG)
- ref3d_ref2d = self.LT(1)
- self.match(REF2D)
- ptg = ptgRef3dR + _RVAdeltaRef[arg_type]
- rpn_ref2d = b""
- r1, c1 = Utils.cell_to_packed_rowcol(ref3d_ref2d.text)
- rpn_ref2d = struct.pack("<3H", 0x0000, r1, c1)
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [COLON]:
- pass
- self.match(COLON)
- ref3d_ref2d2 = self.LT(1)
- self.match(REF2D)
- ptg = ptgArea3dR + _RVAdeltaArea[arg_type]
- r2, c2 = Utils.cell_to_packed_rowcol(ref3d_ref2d2.text)
- rpn_ref2d = struct.pack("<5H", 0x0000, r1, r2, c1, c2)
- elif la1 and la1 in [EOF,EQ,NE,GT,LT,GE,LE,ADD,SUB,MUL,DIV,POWER,PERCENT,RP,COMMA,SEMICOLON,CONCAT]:
- pass
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- self.rpn += struct.pack("<B", ptg)
- self.sheet_references.append((sheet1, sheet2, len(self.rpn)))
- self.rpn += rpn_ref2d
- elif (self.LA(1)==NAME) and (_tokenSet_0.member(self.LA(2))):
- name_tok = self.LT(1)
- self.match(NAME)
- raise Exception("[formula] found unexpected NAME token (%r)" % name_tok.txt)
- # #### TODO: handle references to defined names here
- elif (self.LA(1)==NAME) and (self.LA(2)==LP):
- func_tok = self.LT(1)
- self.match(NAME)
- func_toku = func_tok.text.upper()
- if func_toku in all_funcs_by_name:
- (opcode,
- min_argc,
- max_argc,
- func_type,
- arg_type_str) = all_funcs_by_name[func_toku]
- arg_type_list = list(arg_type_str)
- else:
- raise Exception("[formula] unknown function (%s)" % func_tok.text)
- # print "**func_tok1 %s %s" % (func_toku, func_type)
- xcall = opcode < 0
- if xcall:
- # The name of the add-in function is passed as the 1st arg
- # of the hidden XCALL function
- self.xcall_references.append((func_toku, len(self.rpn) + 1))
- self.rpn += struct.pack("<BHHH",
- ptgNameXR,
- 0xadde, # ##PATCHME## index to REF entry in EXTERNSHEET record
- 0xefbe, # ##PATCHME## one-based index to EXTERNNAME record
- 0x0000) # unused
- self.match(LP)
- arg_count=self.expr_list(arg_type_list, min_argc, max_argc)
- self.match(RP)
- if arg_count > max_argc or arg_count < min_argc:
- raise Exception("%d parameters for function: %s" % (arg_count, func_tok.text))
- if xcall:
- func_ptg = ptgFuncVarR + _RVAdelta[func_type]
- self.rpn += struct.pack("<2BH", func_ptg, arg_count + 1, 255) # 255 is magic XCALL function
- elif min_argc == max_argc:
- func_ptg = ptgFuncR + _RVAdelta[func_type]
- self.rpn += struct.pack("<BH", func_ptg, opcode)
- elif arg_count == 1 and func_tok.text.upper() == "SUM":
- self.rpn += struct.pack("<BBH", ptgAttr, 0x10, 0) # tAttrSum
- else:
- func_ptg = ptgFuncVarR + _RVAdelta[func_type]
- self.rpn += struct.pack("<2BH", func_ptg, arg_count, opcode)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- def sheet(self):
- ref = None
- sheet_ref_name = None
- sheet_ref_int = None
- sheet_ref_quote = None
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [NAME]:
- sheet_ref_name = self.LT(1)
- self.match(NAME)
- ref = sheet_ref_name.text
- elif la1 and la1 in [INT_CONST]:
- sheet_ref_int = self.LT(1)
- self.match(INT_CONST)
- ref = sheet_ref_int.text
- elif la1 and la1 in [QUOTENAME]:
- sheet_ref_quote = self.LT(1)
- self.match(QUOTENAME)
- ref = sheet_ref_quote.text[1:-1].replace("''", "'")
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- return ref
-
- def expr_list(self,
- arg_type_list, min_argc, max_argc
- ):
- arg_cnt = None
-
- arg_cnt = 0
- arg_type = arg_type_list[arg_cnt]
- # print "**expr_list1[%d] req=%s" % (arg_cnt, arg_type)
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,FUNC_IF,FUNC_CHOOSE,NAME,QUOTENAME,SUB,LP,REF2D]:
- pass
- self.expr(arg_type)
- arg_cnt += 1
- while True:
- if (self.LA(1)==COMMA or self.LA(1)==SEMICOLON):
- pass
- if arg_cnt < len(arg_type_list):
- arg_type = arg_type_list[arg_cnt]
- else:
- arg_type = arg_type_list[-1]
- if arg_type == "+":
- arg_type = arg_type_list[-2]
- # print "**expr_list2[%d] req=%s" % (arg_cnt, arg_type)
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [SEMICOLON]:
- pass
- self.match(SEMICOLON)
- elif la1 and la1 in [COMMA]:
- pass
- self.match(COMMA)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- la1 = self.LA(1)
- if False:
- pass
- elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,FUNC_IF,FUNC_CHOOSE,NAME,QUOTENAME,SUB,LP,REF2D]:
- pass
- self.expr(arg_type)
- elif la1 and la1 in [RP,COMMA,SEMICOLON]:
- pass
- self.rpn += struct.pack("B", ptgMissArg)
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- arg_cnt += 1
- else:
- break
-
- elif la1 and la1 in [RP]:
- pass
- else:
- raise antlr.NoViableAltException(self.LT(1), self.getFilename())
-
- return arg_cnt
-
-
-_tokenNames = [
- "<0>",
- "EOF",
- "<2>",
- "NULL_TREE_LOOKAHEAD",
- "TRUE_CONST",
- "FALSE_CONST",
- "STR_CONST",
- "NUM_CONST",
- "INT_CONST",
- "FUNC_IF",
- "FUNC_CHOOSE",
- "NAME",
- "QUOTENAME",
- "EQ",
- "NE",
- "GT",
- "LT",
- "GE",
- "LE",
- "ADD",
- "SUB",
- "MUL",
- "DIV",
- "POWER",
- "PERCENT",
- "LP",
- "RP",
- "LB",
- "RB",
- "COLON",
- "COMMA",
- "SEMICOLON",
- "REF2D",
- "REF2D_R1C1",
- "BANG",
- "CONCAT"
-]
-
-
-### generate bit set
-def mk_tokenSet_0():
- ### var1
- data = [ 37681618946, 0]
- return data
-_tokenSet_0 = antlr.BitSet(mk_tokenSet_0())
-
diff --git a/tablib/packages/xlwt3/ExcelMagic.py b/tablib/packages/xlwt3/ExcelMagic.py
deleted file mode 100644
index 90372b4..0000000
--- a/tablib/packages/xlwt3/ExcelMagic.py
+++ /dev/null
@@ -1,859 +0,0 @@
-""" lots of Excel Magic Numbers """
-
-# Boundaries BIFF8+
-
-MAX_ROW = 65536
-MAX_COL = 256
-
-
-biff_records = {
- 0x0000: "DIMENSIONS",
- 0x0001: "BLANK",
- 0x0002: "INTEGER",
- 0x0003: "NUMBER",
- 0x0004: "LABEL",
- 0x0005: "BOOLERR",
- 0x0006: "FORMULA",
- 0x0007: "STRING",
- 0x0008: "ROW",
- 0x0009: "BOF",
- 0x000A: "EOF",
- 0x000B: "INDEX",
- 0x000C: "CALCCOUNT",
- 0x000D: "CALCMODE",
- 0x000E: "PRECISION",
- 0x000F: "REFMODE",
- 0x0010: "DELTA",
- 0x0011: "ITERATION",
- 0x0012: "PROTECT",
- 0x0013: "PASSWORD",
- 0x0014: "HEADER",
- 0x0015: "FOOTER",
- 0x0016: "EXTERNCOUNT",
- 0x0017: "EXTERNSHEET",
- 0x0018: "NAME",
- 0x0019: "WINDOWPROTECT",
- 0x001A: "VERTICALPAGEBREAKS",
- 0x001B: "HORIZONTALPAGEBREAKS",
- 0x001C: "NOTE",
- 0x001D: "SELECTION",
- 0x001E: "FORMAT",
- 0x001F: "FORMATCOUNT",
- 0x0020: "COLUMNDEFAULT",
- 0x0021: "ARRAY",
- 0x0022: "1904",
- 0x0023: "EXTERNNAME",
- 0x0024: "COLWIDTH",
- 0x0025: "DEFAULTROWHEIGHT",
- 0x0026: "LEFTMARGIN",
- 0x0027: "RIGHTMARGIN",
- 0x0028: "TOPMARGIN",
- 0x0029: "BOTTOMMARGIN",
- 0x002A: "PRINTHEADERS",
- 0x002B: "PRINTGRIDLINES",
- 0x002F: "FILEPASS",
- 0x0031: "FONT",
- 0x0036: "TABLE",
- 0x003C: "CONTINUE",
- 0x003D: "WINDOW1",
- 0x003E: "WINDOW2",
- 0x0040: "BACKUP",
- 0x0041: "PANE",
- 0x0042: "CODEPAGE",
- 0x0043: "XF",
- 0x0044: "IXFE",
- 0x0045: "EFONT",
- 0x004D: "PLS",
- 0x0050: "DCON",
- 0x0051: "DCONREF",
- 0x0053: "DCONNAME",
- 0x0055: "DEFCOLWIDTH",
- 0x0056: "BUILTINFMTCNT",
- 0x0059: "XCT",
- 0x005A: "CRN",
- 0x005B: "FILESHARING",
- 0x005C: "WRITEACCESS",
- 0x005D: "OBJ",
- 0x005E: "UNCALCED",
- 0x005F: "SAFERECALC",
- 0x0060: "TEMPLATE",
- 0x0063: "OBJPROTECT",
- 0x007D: "COLINFO",
- 0x007E: "RK",
- 0x007F: "IMDATA",
- 0x0080: "GUTS",
- 0x0081: "WSBOOL",
- 0x0082: "GRIDSET",
- 0x0083: "HCENTER",
- 0x0084: "VCENTER",
- 0x0085: "BOUNDSHEET",
- 0x0086: "WRITEPROT",
- 0x0087: "ADDIN",
- 0x0088: "EDG",
- 0x0089: "PUB",
- 0x008C: "COUNTRY",
- 0x008D: "HIDEOBJ",
- 0x008E: "BUNDLESOFFSET",
- 0x008F: "BUNDLEHEADER",
- 0x0090: "SORT",
- 0x0091: "SUB",
- 0x0092: "PALETTE",
- 0x0093: "STYLE",
- 0x0094: "LHRECORD",
- 0x0095: "LHNGRAPH",
- 0x0096: "SOUND",
- 0x0098: "LPR",
- 0x0099: "STANDARDWIDTH",
- 0x009A: "FNGROUPNAME",
- 0x009B: "FILTERMODE",
- 0x009C: "FNGROUPCOUNT",
- 0x009D: "AUTOFILTERINFO",
- 0x009E: "AUTOFILTER",
- 0x00A0: "SCL",
- 0x00A1: "SETUP",
- 0x00A9: "COORDLIST",
- 0x00AB: "GCW",
- 0x00AE: "SCENMAN",
- 0x00AF: "SCENARIO",
- 0x00B0: "SXVIEW",
- 0x00B1: "SXVD",
- 0x00B2: "SXVI",
- 0x00B4: "SXIVD",
- 0x00B5: "SXLI",
- 0x00B6: "SXPI",
- 0x00B8: "DOCROUTE",
- 0x00B9: "RECIPNAME",
- 0x00BC: "SHRFMLA",
- 0x00BD: "MULRK",
- 0x00BE: "MULBLANK",
- 0x00C1: "MMS",
- 0x00C2: "ADDMENU",
- 0x00C3: "DELMENU",
- 0x00C5: "SXDI",
- 0x00C6: "SXDB",
- 0x00C7: "SXFIELD",
- 0x00C8: "SXINDEXLIST",
- 0x00C9: "SXDOUBLE",
- 0x00CD: "SXSTRING",
- 0x00CE: "SXDATETIME",
- 0x00D0: "SXTBL",
- 0x00D1: "SXTBRGITEM",
- 0x00D2: "SXTBPG",
- 0x00D3: "OBPROJ",
- 0x00D5: "SXIDSTM",
- 0x00D6: "RSTRING",
- 0x00D7: "DBCELL",
- 0x00DA: "BOOKBOOL",
- 0x00DC: "SXEXT|PARAMQRY",
- 0x00DD: "SCENPROTECT",
- 0x00DE: "OLESIZE",
- 0x00DF: "UDDESC",
- 0x00E0: "XF",
- 0x00E1: "INTERFACEHDR",
- 0x00E2: "INTERFACEEND",
- 0x00E3: "SXVS",
- 0x00E5: "MERGEDCELLS",
- 0x00E9: "BITMAP",
- 0x00EB: "MSODRAWINGGROUP",
- 0x00EC: "MSODRAWING",
- 0x00ED: "MSODRAWINGSELECTION",
- 0x00F0: "SXRULE",
- 0x00F1: "SXEX",
- 0x00F2: "SXFILT",
- 0x00F6: "SXNAME",
- 0x00F7: "SXSELECT",
- 0x00F8: "SXPAIR",
- 0x00F9: "SXFMLA",
- 0x00FB: "SXFORMAT",
- 0x00FC: "SST",
- 0x00FD: "LABELSST",
- 0x00FF: "EXTSST",
- 0x0100: "SXVDEX",
- 0x0103: "SXFORMULA",
- 0x0122: "SXDBEX",
- 0x0137: "CHTRINSERT",
- 0x0138: "CHTRINFO",
- 0x013B: "CHTRCELLCONTENT",
- 0x013D: "TABID",
- 0x0140: "CHTRMOVERANGE",
- 0x014D: "CHTRINSERTTAB",
- 0x015F: "LABELRANGES",
- 0x0160: "USESELFS",
- 0x0161: "DSF",
- 0x0162: "XL5MODIFY",
- 0x0196: "CHTRHEADER",
- 0x01A9: "USERBVIEW",
- 0x01AA: "USERSVIEWBEGIN",
- 0x01AB: "USERSVIEWEND",
- 0x01AD: "QSI",
- 0x01AE: "SUPBOOK",
- 0x01AF: "PROT4REV",
- 0x01B0: "CONDFMT",
- 0x01B1: "CF",
- 0x01B2: "DVAL",
- 0x01B5: "DCONBIN",
- 0x01B6: "TXO",
- 0x01B7: "REFRESHALL",
- 0x01B8: "HLINK",
- 0x01BA: "CODENAME",
- 0x01BB: "SXFDBTYPE",
- 0x01BC: "PROT4REVPASS",
- 0x01BE: "DV",
- 0x01C0: "XL9FILE",
- 0x01C1: "RECALCID",
- 0x0200: "DIMENSIONS",
- 0x0201: "BLANK",
- 0x0203: "NUMBER",
- 0x0204: "LABEL",
- 0x0205: "BOOLERR",
- 0x0206: "FORMULA",
- 0x0207: "STRING",
- 0x0208: "ROW",
- 0x0209: "BOF",
- 0x020B: "INDEX",
- 0x0218: "NAME",
- 0x0221: "ARRAY",
- 0x0223: "EXTERNNAME",
- 0x0225: "DEFAULTROWHEIGHT",
- 0x0231: "FONT",
- 0x0236: "TABLE",
- 0x023E: "WINDOW2",
- 0x0243: "XF",
- 0x027E: "RK",
- 0x0293: "STYLE",
- 0x0406: "FORMULA",
- 0x0409: "BOF",
- 0x041E: "FORMAT",
- 0x0443: "XF",
- 0x04BC: "SHRFMLA",
- 0x0800: "SCREENTIP",
- 0x0803: "WEBQRYSETTINGS",
- 0x0804: "WEBQRYTABLES",
- 0x0809: "BOF",
- 0x0862: "SHEETLAYOUT",
- 0x0867: "SHEETPROTECTION",
- 0x1001: "UNITS",
- 0x1002: "ChartChart",
- 0x1003: "ChartSeries",
- 0x1006: "ChartDataformat",
- 0x1007: "ChartLineformat",
- 0x1009: "ChartMarkerformat",
- 0x100A: "ChartAreaformat",
- 0x100B: "ChartPieformat",
- 0x100C: "ChartAttachedlabel",
- 0x100D: "ChartSeriestext",
- 0x1014: "ChartChartformat",
- 0x1015: "ChartLegend",
- 0x1016: "ChartSerieslist",
- 0x1017: "ChartBar",
- 0x1018: "ChartLine",
- 0x1019: "ChartPie",
- 0x101A: "ChartArea",
- 0x101B: "ChartScatter",
- 0x101C: "ChartChartline",
- 0x101D: "ChartAxis",
- 0x101E: "ChartTick",
- 0x101F: "ChartValuerange",
- 0x1020: "ChartCatserrange",
- 0x1021: "ChartAxislineformat",
- 0x1022: "ChartFormatlink",
- 0x1024: "ChartDefaulttext",
- 0x1025: "ChartText",
- 0x1026: "ChartFontx",
- 0x1027: "ChartObjectLink",
- 0x1032: "ChartFrame",
- 0x1033: "BEGIN",
- 0x1034: "END",
- 0x1035: "ChartPlotarea",
- 0x103A: "Chart3D",
- 0x103C: "ChartPicf",
- 0x103D: "ChartDropbar",
- 0x103E: "ChartRadar",
- 0x103F: "ChartSurface",
- 0x1040: "ChartRadararea",
- 0x1041: "ChartAxisparent",
- 0x1043: "ChartLegendxn",
- 0x1044: "ChartShtprops",
- 0x1045: "ChartSertocrt",
- 0x1046: "ChartAxesused",
- 0x1048: "ChartSbaseref",
- 0x104A: "ChartSerparent",
- 0x104B: "ChartSerauxtrend",
- 0x104E: "ChartIfmt",
- 0x104F: "ChartPos",
- 0x1050: "ChartAlruns",
- 0x1051: "ChartAI",
- 0x105B: "ChartSerauxerrbar",
- 0x105D: "ChartSerfmt",
- 0x105F: "Chart3DDataFormat",
- 0x1060: "ChartFbi",
- 0x1061: "ChartBoppop",
- 0x1062: "ChartAxcext",
- 0x1063: "ChartDat",
- 0x1064: "ChartPlotgrowth",
- 0x1065: "ChartSiindex",
- 0x1066: "ChartGelframe",
- 0x1067: "ChartBoppcustom",
- 0xFFFF: ""
-}
-
-
-all_funcs_by_name = {
- # Includes Analysis ToolPak aka ATP aka add-in aka xcall functions,
- # distinguished by -ve opcode.
- # name: (opcode, min # args, max # args, func return type, func arg types)
- # + in func arg types means more of the same.
- 'ABS' : ( 24, 1, 1, 'V', 'V'),
- 'ACCRINT' : ( -1, 6, 7, 'V', 'VVVVVVV'),
- 'ACCRINTM' : ( -1, 3, 5, 'V', 'VVVVV'),
- 'ACOS' : ( 99, 1, 1, 'V', 'V'),
- 'ACOSH' : (233, 1, 1, 'V', 'V'),
- 'ADDRESS' : (219, 2, 5, 'V', 'VVVVV'),
- 'AMORDEGRC' : ( -1, 7, 7, 'V', 'VVVVVVV'),
- 'AMORLINC' : ( -1, 7, 7, 'V', 'VVVVVVV'),
- 'AND' : ( 36, 1, 30, 'V', 'D+'),
- 'AREAS' : ( 75, 1, 1, 'V', 'R'),
- 'ASC' : (214, 1, 1, 'V', 'V'),
- 'ASIN' : ( 98, 1, 1, 'V', 'V'),
- 'ASINH' : (232, 1, 1, 'V', 'V'),
- 'ATAN' : ( 18, 1, 1, 'V', 'V'),
- 'ATAN2' : ( 97, 2, 2, 'V', 'VV'),
- 'ATANH' : (234, 1, 1, 'V', 'V'),
- 'AVEDEV' : (269, 1, 30, 'V', 'D+'),
- 'AVERAGE' : ( 5, 1, 30, 'V', 'D+'),
- 'AVERAGEA' : (361, 1, 30, 'V', 'D+'),
- 'BAHTTEXT' : (368, 1, 1, 'V', 'V'),
- 'BESSELI' : ( -1, 2, 2, 'V', 'VV'),
- 'BESSELJ' : ( -1, 2, 2, 'V', 'VV'),
- 'BESSELK' : ( -1, 2, 2, 'V', 'VV'),
- 'BESSELY' : ( -1, 2, 2, 'V', 'VV'),
- 'BETADIST' : (270, 3, 5, 'V', 'VVVVV'),
- 'BETAINV' : (272, 3, 5, 'V', 'VVVVV'),
- 'BIN2DEC' : ( -1, 1, 1, 'V', 'V'),
- 'BIN2HEX' : ( -1, 1, 2, 'V', 'VV'),
- 'BIN2OCT' : ( -1, 1, 2, 'V', 'VV'),
- 'BINOMDIST' : (273, 4, 4, 'V', 'VVVV'),
- 'CEILING' : (288, 2, 2, 'V', 'VV'),
- 'CELL' : (125, 1, 2, 'V', 'VR'),
- 'CHAR' : (111, 1, 1, 'V', 'V'),
- 'CHIDIST' : (274, 2, 2, 'V', 'VV'),
- 'CHIINV' : (275, 2, 2, 'V', 'VV'),
- 'CHITEST' : (306, 2, 2, 'V', 'AA'),
- 'CHOOSE' : (100, 2, 30, 'R', 'VR+'),
- 'CLEAN' : (162, 1, 1, 'V', 'V'),
- 'CODE' : (121, 1, 1, 'V', 'V'),
- 'COLUMN' : ( 9, 0, 1, 'V', 'R'),
- 'COLUMNS' : ( 77, 1, 1, 'V', 'R'),
- 'COMBIN' : (276, 2, 2, 'V', 'VV'),
- 'COMPLEX' : ( -1, 2, 3, 'V', 'VVV'),
- 'CONCATENATE' : (336, 1, 30, 'V', 'V+'),
- 'CONFIDENCE' : (277, 3, 3, 'V', 'VVV'),
- 'CONVERT' : ( -1, 3, 3, 'V', 'VVV'),
- 'CORREL' : (307, 2, 2, 'V', 'AA'),
- 'COS' : ( 16, 1, 1, 'V', 'V'),
- 'COSH' : (230, 1, 1, 'V', 'V'),
- 'COUNT' : ( 0, 1, 30, 'V', 'D+'),
- 'COUNTA' : (169, 1, 30, 'V', 'D+'),
- 'COUNTBLANK' : (347, 1, 1, 'V', 'R'),
- 'COUNTIF' : (346, 2, 2, 'V', 'RV'),
- 'COUPDAYBS' : ( -1, 3, 5, 'V', 'VVVVV'),
- 'COUPDAYS' : ( -1, 3, 5, 'V', 'VVVVV'),
- 'COUPDAYSNC' : ( -1, 3, 5, 'V', 'VVVVV'),
- 'COUPNCD' : ( -1, 3, 5, 'V', 'VVVVV'),
- 'COUPNUM' : ( -1, 3, 5, 'V', 'VVVVV'),
- 'COUPPCD' : ( -1, 3, 5, 'V', 'VVVVV'),
- 'COVAR' : (308, 2, 2, 'V', 'AA'),
- 'CRITBINOM' : (278, 3, 3, 'V', 'VVV'),
- 'CUMIPMT' : ( -1, 6, 6, 'V', 'VVVVVV'),
- 'CUMPRINC' : ( -1, 6, 6, 'V', 'VVVVVV'),
- 'DATE' : ( 65, 3, 3, 'V', 'VVV'),
- 'DATEDIF' : (351, 3, 3, 'V', 'VVV'),
- 'DATEVALUE' : (140, 1, 1, 'V', 'V'),
- 'DAVERAGE' : ( 42, 3, 3, 'V', 'RRR'),
- 'DAY' : ( 67, 1, 1, 'V', 'V'),
- 'DAYS360' : (220, 2, 3, 'V', 'VVV'),
- 'DB' : (247, 4, 5, 'V', 'VVVVV'),
- 'DBCS' : (215, 1, 1, 'V', 'V'),
- 'DCOUNT' : ( 40, 3, 3, 'V', 'RRR'),
- 'DCOUNTA' : (199, 3, 3, 'V', 'RRR'),
- 'DDB' : (144, 4, 5, 'V', 'VVVVV'),
- 'DEC2BIN' : ( -1, 1, 2, 'V', 'VV'),
- 'DEC2HEX' : ( -1, 1, 2, 'V', 'VV'),
- 'DEC2OCT' : ( -1, 1, 2, 'V', 'VV'),
- 'DEGREES' : (343, 1, 1, 'V', 'V'),
- 'DELTA' : ( -1, 1, 2, 'V', 'VV'),
- 'DEVSQ' : (318, 1, 30, 'V', 'D+'),
- 'DGET' : (235, 3, 3, 'V', 'RRR'),
- 'DISC' : ( -1, 4, 5, 'V', 'VVVVV'),
- 'DMAX' : ( 44, 3, 3, 'V', 'RRR'),
- 'DMIN' : ( 43, 3, 3, 'V', 'RRR'),
- 'DOLLAR' : ( 13, 1, 2, 'V', 'VV'),
- 'DOLLARDE' : ( -1, 2, 2, 'V', 'VV'),
- 'DOLLARFR' : ( -1, 2, 2, 'V', 'VV'),
- 'DPRODUCT' : (189, 3, 3, 'V', 'RRR'),
- 'DSTDEV' : ( 45, 3, 3, 'V', 'RRR'),
- 'DSTDEVP' : (195, 3, 3, 'V', 'RRR'),
- 'DSUM' : ( 41, 3, 3, 'V', 'RRR'),
- 'DURATION' : ( -1, 5, 6, 'V', 'VVVVVV'),
- 'DVAR' : ( 47, 3, 3, 'V', 'RRR'),
- 'DVARP' : (196, 3, 3, 'V', 'RRR'),
- 'EDATE' : ( -1, 2, 2, 'V', 'VV'),
- 'EFFECT' : ( -1, 2, 2, 'V', 'VV'),
- 'EOMONTH' : ( -1, 1, 2, 'V', 'VV'),
- 'ERF' : ( -1, 1, 2, 'V', 'VV'),
- 'ERFC' : ( -1, 1, 1, 'V', 'V'),
- 'ERROR.TYPE' : (261, 1, 1, 'V', 'V'),
- 'EVEN' : (279, 1, 1, 'V', 'V'),
- 'EXACT' : (117, 2, 2, 'V', 'VV'),
- 'EXP' : ( 21, 1, 1, 'V', 'V'),
- 'EXPONDIST' : (280, 3, 3, 'V', 'VVV'),
- 'FACT' : (184, 1, 1, 'V', 'V'),
- 'FACTDOUBLE' : ( -1, 1, 1, 'V', 'V'),
- 'FALSE' : ( 35, 0, 0, 'V', '-'),
- 'FDIST' : (281, 3, 3, 'V', 'VVV'),
- 'FIND' : (124, 2, 3, 'V', 'VVV'),
- 'FINDB' : (205, 2, 3, 'V', 'VVV'),
- 'FINV' : (282, 3, 3, 'V', 'VVV'),
- 'FISHER' : (283, 1, 1, 'V', 'V'),
- 'FISHERINV' : (284, 1, 1, 'V', 'V'),
- 'FIXED' : ( 14, 2, 3, 'V', 'VVV'),
- 'FLOOR' : (285, 2, 2, 'V', 'VV'),
- 'FORECAST' : (309, 3, 3, 'V', 'VAA'),
- 'FREQUENCY' : (252, 2, 2, 'A', 'RR'),
- 'FTEST' : (310, 2, 2, 'V', 'AA'),
- 'FV' : ( 57, 3, 5, 'V', 'VVVVV'),
- 'FVSCHEDULE' : ( -1, 2, 2, 'V', 'VA'),
- 'GAMMADIST' : (286, 4, 4, 'V', 'VVVV'),
- 'GAMMAINV' : (287, 3, 3, 'V', 'VVV'),
- 'GAMMALN' : (271, 1, 1, 'V', 'V'),
- 'GCD' : ( -1, 1, 29, 'V', 'V+'),
- 'GEOMEAN' : (319, 1, 30, 'V', 'D+'),
- 'GESTEP' : ( -1, 1, 2, 'V', 'VV'),
- 'GETPIVOTDATA': (358, 2, 30, 'A', 'VAV+'),
- 'GROWTH' : ( 52, 1, 4, 'A', 'RRRV'),
- 'HARMEAN' : (320, 1, 30, 'V', 'D+'),
- 'HEX2BIN' : ( -1, 1, 2, 'V', 'VV'),
- 'HEX2DEC' : ( -1, 1, 1, 'V', 'V'),
- 'HEX2OCT' : ( -1, 1, 2, 'V', 'VV'),
- 'HLOOKUP' : (101, 3, 4, 'V', 'VRRV'),
- 'HOUR' : ( 71, 1, 1, 'V', 'V'),
- 'HYPERLINK' : (359, 1, 2, 'V', 'VV'),
- 'HYPGEOMDIST' : (289, 4, 4, 'V', 'VVVV'),
- 'IF' : ( 1, 2, 3, 'R', 'VRR'),
- 'IMABS' : ( -1, 1, 1, 'V', 'V'),
- 'IMAGINARY' : ( -1, 1, 1, 'V', 'V'),
- 'IMARGUMENT' : ( -1, 1, 1, 'V', 'V'),
- 'IMCONJUGATE' : ( -1, 1, 1, 'V', 'V'),
- 'IMCOS' : ( -1, 1, 1, 'V', 'V'),
- 'IMDIV' : ( -1, 2, 2, 'V', 'VV'),
- 'IMEXP' : ( -1, 1, 1, 'V', 'V'),
- 'IMLN' : ( -1, 1, 1, 'V', 'V'),
- 'IMLOG10' : ( -1, 1, 1, 'V', 'V'),
- 'IMLOG2' : ( -1, 1, 1, 'V', 'V'),
- 'IMPOWER' : ( -1, 2, 2, 'V', 'VV'),
- 'IMPRODUCT' : ( -1, 2, 2, 'V', 'VV'),
- 'IMREAL' : ( -1, 1, 1, 'V', 'V'),
- 'IMSIN' : ( -1, 1, 1, 'V', 'V'),
- 'IMSQRT' : ( -1, 1, 1, 'V', 'V'),
- 'IMSUB' : ( -1, 2, 2, 'V', 'VV'),
- 'IMSUM' : ( -1, 1, 29, 'V', 'V+'),
- 'INDEX' : ( 29, 2, 4, 'R', 'RVVV'),
- 'INDIRECT' : (148, 1, 2, 'R', 'VV'),
- 'INFO' : (244, 1, 1, 'V', 'V'),
- 'INT' : ( 25, 1, 1, 'V', 'V'),
- 'INTERCEPT' : (311, 2, 2, 'V', 'AA'),
- 'INTRATE' : ( -1, 4, 5, 'V', 'VVVVV'),
- 'IPMT' : (167, 4, 6, 'V', 'VVVVVV'),
- 'IRR' : ( 62, 1, 2, 'V', 'RV'),
- 'ISBLANK' : (129, 1, 1, 'V', 'V'),
- 'ISERR' : (126, 1, 1, 'V', 'V'),
- 'ISERROR' : ( 3, 1, 1, 'V', 'V'),
- 'ISEVEN' : ( -1, 1, 1, 'V', 'V'),
- 'ISLOGICAL' : (198, 1, 1, 'V', 'V'),
- 'ISNA' : ( 2, 1, 1, 'V', 'V'),
- 'ISNONTEXT' : (190, 1, 1, 'V', 'V'),
- 'ISNUMBER' : (128, 1, 1, 'V', 'V'),
- 'ISODD' : ( -1, 1, 1, 'V', 'V'),
- 'ISPMT' : (350, 4, 4, 'V', 'VVVV'),
- 'ISREF' : (105, 1, 1, 'V', 'R'),
- 'ISTEXT' : (127, 1, 1, 'V', 'V'),
- 'KURT' : (322, 1, 30, 'V', 'D+'),
- 'LARGE' : (325, 2, 2, 'V', 'RV'),
- 'LCM' : ( -1, 1, 29, 'V', 'V+'),
- 'LEFT' : (115, 1, 2, 'V', 'VV'),
- 'LEFTB' : (208, 1, 2, 'V', 'VV'),
- 'LEN' : ( 32, 1, 1, 'V', 'V'),
- 'LENB' : (211, 1, 1, 'V', 'V'),
- 'LINEST' : ( 49, 1, 4, 'A', 'RRVV'),
- 'LN' : ( 22, 1, 1, 'V', 'V'),
- 'LOG' : (109, 1, 2, 'V', 'VV'),
- 'LOG10' : ( 23, 1, 1, 'V', 'V'),
- 'LOGEST' : ( 51, 1, 4, 'A', 'RRVV'),
- 'LOGINV' : (291, 3, 3, 'V', 'VVV'),
- 'LOGNORMDIST' : (290, 3, 3, 'V', 'VVV'),
- 'LOOKUP' : ( 28, 2, 3, 'V', 'VRR'),
- 'LOWER' : (112, 1, 1, 'V', 'V'),
- 'MATCH' : ( 64, 2, 3, 'V', 'VRR'),
- 'MAX' : ( 7, 1, 30, 'V', 'D+'),
- 'MAXA' : (362, 1, 30, 'V', 'D+'),
- 'MDETERM' : (163, 1, 1, 'V', 'A'),
- 'MDURATION' : ( -1, 5, 6, 'V', 'VVVVVV'),
- 'MEDIAN' : (227, 1, 30, 'V', 'D+'),
- 'MID' : ( 31, 3, 3, 'V', 'VVV'),
- 'MIDB' : (210, 3, 3, 'V', 'VVV'),
- 'MIN' : ( 6, 1, 30, 'V', 'D+'),
- 'MINA' : (363, 1, 30, 'V', 'D+'),
- 'MINUTE' : ( 72, 1, 1, 'V', 'V'),
- 'MINVERSE' : (164, 1, 1, 'A', 'A'),
- 'MIRR' : ( 61, 3, 3, 'V', 'RVV'),
- 'MMULT' : (165, 2, 2, 'A', 'AA'),
- 'MOD' : ( 39, 2, 2, 'V', 'VV'),
- 'MODE' : (330, 1, 30, 'V', 'A+'), ################ weird #################
- 'MONTH' : ( 68, 1, 1, 'V', 'V'),
- 'MROUND' : ( -1, 2, 2, 'V', 'VV'),
- 'MULTINOMIAL' : ( -1, 1, 29, 'V', 'V+'),
- 'N' : (131, 1, 1, 'V', 'R'),
- 'NA' : ( 10, 0, 0, 'V', '-'),
- 'NEGBINOMDIST': (292, 3, 3, 'V', 'VVV'),
- 'NETWORKDAYS' : ( -1, 2, 3, 'V', 'VVR'),
- 'NOMINAL' : ( -1, 2, 2, 'V', 'VV'),
- 'NORMDIST' : (293, 4, 4, 'V', 'VVVV'),
- 'NORMINV' : (295, 3, 3, 'V', 'VVV'),
- 'NORMSDIST' : (294, 1, 1, 'V', 'V'),
- 'NORMSINV' : (296, 1, 1, 'V', 'V'),
- 'NOT' : ( 38, 1, 1, 'V', 'V'),
- 'NOW' : ( 74, 0, 0, 'V', '-'),
- 'NPER' : ( 58, 3, 5, 'V', 'VVVVV'),
- 'NPV' : ( 11, 2, 30, 'V', 'VD+'),
- 'OCT2BIN' : ( -1, 1, 2, 'V', 'VV'),
- 'OCT2DEC' : ( -1, 1, 1, 'V', 'V'),
- 'OCT2HEX' : ( -1, 1, 2, 'V', 'VV'),
- 'ODD' : (298, 1, 1, 'V', 'V'),
- 'ODDFPRICE' : ( -1, 9, 9, 'V', 'VVVVVVVVV'),
- 'ODDFYIELD' : ( -1, 9, 9, 'V', 'VVVVVVVVV'),
- 'ODDLPRICE' : ( -1, 8, 8, 'V', 'VVVVVVVV'),
- 'ODDLYIELD' : ( -1, 8, 8, 'V', 'VVVVVVVV'),
- 'OFFSET' : ( 78, 3, 5, 'R', 'RVVVV'),
- 'OR' : ( 37, 1, 30, 'V', 'D+'),
- 'PEARSON' : (312, 2, 2, 'V', 'AA'),
- 'PERCENTILE' : (328, 2, 2, 'V', 'RV'),
- 'PERCENTRANK' : (329, 2, 3, 'V', 'RVV'),
- 'PERMUT' : (299, 2, 2, 'V', 'VV'),
- 'PHONETIC' : (360, 1, 1, 'V', 'R'),
- 'PI' : ( 19, 0, 0, 'V', '-'),
- 'PMT' : ( 59, 3, 5, 'V', 'VVVVV'),
- 'POISSON' : (300, 3, 3, 'V', 'VVV'),
- 'POWER' : (337, 2, 2, 'V', 'VV'),
- 'PPMT' : (168, 4, 6, 'V', 'VVVVVV'),
- 'PRICE' : ( -1, 6, 7, 'V', 'VVVVVVV'),
- 'PRICEDISC' : ( -1, 4, 5, 'V', 'VVVVV'),
- 'PRICEMAT' : ( -1, 5, 6, 'V', 'VVVVVV'),
- 'PROB' : (317, 3, 4, 'V', 'AAVV'),
- 'PRODUCT' : (183, 1, 30, 'V', 'D+'),
- 'PROPER' : (114, 1, 1, 'V', 'V'),
- 'PV' : ( 56, 3, 5, 'V', 'VVVVV'),
- 'QUARTILE' : (327, 2, 2, 'V', 'RV'),
- 'QUOTIENT' : ( -1, 2, 2, 'V', 'VV'),
- 'RADIANS' : (342, 1, 1, 'V', 'V'),
- 'RAND' : ( 63, 0, 0, 'V', '-'),
- 'RANDBETWEEN' : ( -1, 2, 2, 'V', 'VV'),
- 'RANK' : (216, 2, 3, 'V', 'VRV'),
- 'RATE' : ( 60, 3, 6, 'V', 'VVVVVV'),
- 'RECEIVED' : ( -1, 4, 5, 'V', 'VVVVV'),
- 'REPLACE' : (119, 4, 4, 'V', 'VVVV'),
- 'REPLACEB' : (207, 4, 4, 'V', 'VVVV'),
- 'REPT' : ( 30, 2, 2, 'V', 'VV'),
- 'RIGHT' : (116, 1, 2, 'V', 'VV'),
- 'RIGHTB' : (209, 1, 2, 'V', 'VV'),
- 'ROMAN' : (354, 1, 2, 'V', 'VV'),
- 'ROUND' : ( 27, 2, 2, 'V', 'VV'),
- 'ROUNDDOWN' : (213, 2, 2, 'V', 'VV'),
- 'ROUNDUP' : (212, 2, 2, 'V', 'VV'),
- 'ROW' : ( 8, 0, 1, 'V', 'R'),
- 'ROWS' : ( 76, 1, 1, 'V', 'R'),
- 'RSQ' : (313, 2, 2, 'V', 'AA'),
- 'RTD' : (379, 3, 30, 'A', 'VVV+'),
- 'SEARCH' : ( 82, 2, 3, 'V', 'VVV'),
- 'SEARCHB' : (206, 2, 3, 'V', 'VVV'),
- 'SECOND' : ( 73, 1, 1, 'V', 'V'),
- 'SERIESSUM' : ( -1, 4, 4, 'V', 'VVVA'),
- 'SIGN' : ( 26, 1, 1, 'V', 'V'),
- 'SIN' : ( 15, 1, 1, 'V', 'V'),
- 'SINH' : (229, 1, 1, 'V', 'V'),
- 'SKEW' : (323, 1, 30, 'V', 'D+'),
- 'SLN' : (142, 3, 3, 'V', 'VVV'),
- 'SLOPE' : (315, 2, 2, 'V', 'AA'),
- 'SMALL' : (326, 2, 2, 'V', 'RV'),
- 'SQRT' : ( 20, 1, 1, 'V', 'V'),
- 'SQRTPI' : ( -1, 1, 1, 'V', 'V'),
- 'STANDARDIZE' : (297, 3, 3, 'V', 'VVV'),
- 'STDEV' : ( 12, 1, 30, 'V', 'D+'),
- 'STDEVA' : (366, 1, 30, 'V', 'D+'),
- 'STDEVP' : (193, 1, 30, 'V', 'D+'),
- 'STDEVPA' : (364, 1, 30, 'V', 'D+'),
- 'STEYX' : (314, 2, 2, 'V', 'AA'),
- 'SUBSTITUTE' : (120, 3, 4, 'V', 'VVVV'),
- 'SUBTOTAL' : (344, 2, 30, 'V', 'VR+'),
- 'SUM' : ( 4, 1, 30, 'V', 'D+'),
- 'SUMIF' : (345, 2, 3, 'V', 'RVR'),
- 'SUMPRODUCT' : (228, 1, 30, 'V', 'A+'),
- 'SUMSQ' : (321, 1, 30, 'V', 'D+'),
- 'SUMX2MY2' : (304, 2, 2, 'V', 'AA'),
- 'SUMX2PY2' : (305, 2, 2, 'V', 'AA'),
- 'SUMXMY2' : (303, 2, 2, 'V', 'AA'),
- 'SYD' : (143, 4, 4, 'V', 'VVVV'),
- 'T' : (130, 1, 1, 'V', 'R'),
- 'TAN' : ( 17, 1, 1, 'V', 'V'),
- 'TANH' : (231, 1, 1, 'V', 'V'),
- 'TBILLEQ' : ( -1, 3, 3, 'V', 'VVV'),
- 'TBILLPRICE' : ( -1, 3, 3, 'V', 'VVV'),
- 'TBILLYIELD' : ( -1, 3, 3, 'V', 'VVV'),
- 'TDIST' : (301, 3, 3, 'V', 'VVV'),
- 'TEXT' : ( 48, 2, 2, 'V', 'VV'),
- 'TIME' : ( 66, 3, 3, 'V', 'VVV'),
- 'TIMEVALUE' : (141, 1, 1, 'V', 'V'),
- 'TINV' : (332, 2, 2, 'V', 'VV'),
- 'TODAY' : (221, 0, 0, 'V', '-'),
- 'TRANSPOSE' : ( 83, 1, 1, 'A', 'A'),
- 'TREND' : ( 50, 1, 4, 'A', 'RRRV'),
- 'TRIM' : (118, 1, 1, 'V', 'V'),
- 'TRIMMEAN' : (331, 2, 2, 'V', 'RV'),
- 'TRUE' : ( 34, 0, 0, 'V', '-'),
- 'TRUNC' : (197, 1, 2, 'V', 'VV'),
- 'TTEST' : (316, 4, 4, 'V', 'AAVV'),
- 'TYPE' : ( 86, 1, 1, 'V', 'V'),
- 'UPPER' : (113, 1, 1, 'V', 'V'),
- 'USDOLLAR' : (204, 1, 2, 'V', 'VV'),
- 'VALUE' : ( 33, 1, 1, 'V', 'V'),
- 'VAR' : ( 46, 1, 30, 'V', 'D+'),
- 'VARA' : (367, 1, 30, 'V', 'D+'),
- 'VARP' : (194, 1, 30, 'V', 'D+'),
- 'VARPA' : (365, 1, 30, 'V', 'D+'),
- 'VDB' : (222, 5, 7, 'V', 'VVVVVVV'),
- 'VLOOKUP' : (102, 3, 4, 'V', 'VRRV'),
- 'WEEKDAY' : ( 70, 1, 2, 'V', 'VV'),
- 'WEEKNUM' : ( -1, 1, 2, 'V', 'VV'),
- 'WEIBULL' : (302, 4, 4, 'V', 'VVVV'),
- 'WORKDAY' : ( -1, 2, 3, 'V', 'VVR'),
- 'XIRR' : ( -1, 2, 3, 'V', 'AAV'),
- 'XNPV' : ( -1, 3, 3, 'V', 'VAA'),
- 'YEAR' : ( 69, 1, 1, 'V', 'V'),
- 'YEARFRAC' : ( -1, 2, 3, 'V', 'VVV'),
- 'YIELD' : ( -1, 6, 7, 'V', 'VVVVVVV'),
- 'YIELDDISC' : ( -1, 4, 5, 'V', 'VVVVV'),
- 'YIELDMAT' : ( -1, 5, 6, 'V', 'VVVVVV'),
- 'ZTEST' : (324, 2, 3, 'V', 'RVV'),
- }
-
-# Formulas Parse things
-
-ptgExp = 0x01
-ptgTbl = 0x02
-ptgAdd = 0x03
-ptgSub = 0x04
-ptgMul = 0x05
-ptgDiv = 0x06
-ptgPower = 0x07
-ptgConcat = 0x08
-ptgLT = 0x09
-ptgLE = 0x0a
-ptgEQ = 0x0b
-ptgGE = 0x0c
-ptgGT = 0x0d
-ptgNE = 0x0e
-ptgIsect = 0x0f
-ptgUnion = 0x10
-ptgRange = 0x11
-ptgUplus = 0x12
-ptgUminus = 0x13
-ptgPercent = 0x14
-ptgParen = 0x15
-ptgMissArg = 0x16
-ptgStr = 0x17
-ptgExtend = 0x18
-ptgAttr = 0x19
-ptgSheet = 0x1a
-ptgEndSheet = 0x1b
-ptgErr = 0x1c
-ptgBool = 0x1d
-ptgInt = 0x1e
-ptgNum = 0x1f
-
-ptgArrayR = 0x20
-ptgFuncR = 0x21
-ptgFuncVarR = 0x22
-ptgNameR = 0x23
-ptgRefR = 0x24
-ptgAreaR = 0x25
-ptgMemAreaR = 0x26
-ptgMemErrR = 0x27
-ptgMemNoMemR = 0x28
-ptgMemFuncR = 0x29
-ptgRefErrR = 0x2a
-ptgAreaErrR = 0x2b
-ptgRefNR = 0x2c
-ptgAreaNR = 0x2d
-ptgMemAreaNR = 0x2e
-ptgMemNoMemNR = 0x2f
-ptgNameXR = 0x39
-ptgRef3dR = 0x3a
-ptgArea3dR = 0x3b
-ptgRefErr3dR = 0x3c
-ptgAreaErr3dR = 0x3d
-
-ptgArrayV = 0x40
-ptgFuncV = 0x41
-ptgFuncVarV = 0x42
-ptgNameV = 0x43
-ptgRefV = 0x44
-ptgAreaV = 0x45
-ptgMemAreaV = 0x46
-ptgMemErrV = 0x47
-ptgMemNoMemV = 0x48
-ptgMemFuncV = 0x49
-ptgRefErrV = 0x4a
-ptgAreaErrV = 0x4b
-ptgRefNV = 0x4c
-ptgAreaNV = 0x4d
-ptgMemAreaNV = 0x4e
-ptgMemNoMemNV = 0x4f
-ptgFuncCEV = 0x58
-ptgNameXV = 0x59
-ptgRef3dV = 0x5a
-ptgArea3dV = 0x5b
-ptgRefErr3dV = 0x5c
-ptgAreaErr3dV = 0x5d
-
-ptgArrayA = 0x60
-ptgFuncA = 0x61
-ptgFuncVarA = 0x62
-ptgNameA = 0x63
-ptgRefA = 0x64
-ptgAreaA = 0x65
-ptgMemAreaA = 0x66
-ptgMemErrA = 0x67
-ptgMemNoMemA = 0x68
-ptgMemFuncA = 0x69
-ptgRefErrA = 0x6a
-ptgAreaErrA = 0x6b
-ptgRefNA = 0x6c
-ptgAreaNA = 0x6d
-ptgMemAreaNA = 0x6e
-ptgMemNoMemNA = 0x6f
-ptgFuncCEA = 0x78
-ptgNameXA = 0x79
-ptgRef3dA = 0x7a
-ptgArea3dA = 0x7b
-ptgRefErr3dA = 0x7c
-ptgAreaErr3dA = 0x7d
-
-
-PtgNames = {
- ptgExp : "ptgExp",
- ptgTbl : "ptgTbl",
- ptgAdd : "ptgAdd",
- ptgSub : "ptgSub",
- ptgMul : "ptgMul",
- ptgDiv : "ptgDiv",
- ptgPower : "ptgPower",
- ptgConcat : "ptgConcat",
- ptgLT : "ptgLT",
- ptgLE : "ptgLE",
- ptgEQ : "ptgEQ",
- ptgGE : "ptgGE",
- ptgGT : "ptgGT",
- ptgNE : "ptgNE",
- ptgIsect : "ptgIsect",
- ptgUnion : "ptgUnion",
- ptgRange : "ptgRange",
- ptgUplus : "ptgUplus",
- ptgUminus : "ptgUminus",
- ptgPercent : "ptgPercent",
- ptgParen : "ptgParen",
- ptgMissArg : "ptgMissArg",
- ptgStr : "ptgStr",
- ptgExtend : "ptgExtend",
- ptgAttr : "ptgAttr",
- ptgSheet : "ptgSheet",
- ptgEndSheet : "ptgEndSheet",
- ptgErr : "ptgErr",
- ptgBool : "ptgBool",
- ptgInt : "ptgInt",
- ptgNum : "ptgNum",
- ptgArrayR : "ptgArrayR",
- ptgFuncR : "ptgFuncR",
- ptgFuncVarR : "ptgFuncVarR",
- ptgNameR : "ptgNameR",
- ptgRefR : "ptgRefR",
- ptgAreaR : "ptgAreaR",
- ptgMemAreaR : "ptgMemAreaR",
- ptgMemErrR : "ptgMemErrR",
- ptgMemNoMemR : "ptgMemNoMemR",
- ptgMemFuncR : "ptgMemFuncR",
- ptgRefErrR : "ptgRefErrR",
- ptgAreaErrR : "ptgAreaErrR",
- ptgRefNR : "ptgRefNR",
- ptgAreaNR : "ptgAreaNR",
- ptgMemAreaNR : "ptgMemAreaNR",
- ptgMemNoMemNR : "ptgMemNoMemNR",
- ptgNameXR : "ptgNameXR",
- ptgRef3dR : "ptgRef3dR",
- ptgArea3dR : "ptgArea3dR",
- ptgRefErr3dR : "ptgRefErr3dR",
- ptgAreaErr3dR : "ptgAreaErr3dR",
- ptgArrayV : "ptgArrayV",
- ptgFuncV : "ptgFuncV",
- ptgFuncVarV : "ptgFuncVarV",
- ptgNameV : "ptgNameV",
- ptgRefV : "ptgRefV",
- ptgAreaV : "ptgAreaV",
- ptgMemAreaV : "ptgMemAreaV",
- ptgMemErrV : "ptgMemErrV",
- ptgMemNoMemV : "ptgMemNoMemV",
- ptgMemFuncV : "ptgMemFuncV",
- ptgRefErrV : "ptgRefErrV",
- ptgAreaErrV : "ptgAreaErrV",
- ptgRefNV : "ptgRefNV",
- ptgAreaNV : "ptgAreaNV",
- ptgMemAreaNV : "ptgMemAreaNV",
- ptgMemNoMemNV : "ptgMemNoMemNV",
- ptgFuncCEV : "ptgFuncCEV",
- ptgNameXV : "ptgNameXV",
- ptgRef3dV : "ptgRef3dV",
- ptgArea3dV : "ptgArea3dV",
- ptgRefErr3dV : "ptgRefErr3dV",
- ptgAreaErr3dV : "ptgAreaErr3dV",
- ptgArrayA : "ptgArrayA",
- ptgFuncA : "ptgFuncA",
- ptgFuncVarA : "ptgFuncVarA",
- ptgNameA : "ptgNameA",
- ptgRefA : "ptgRefA",
- ptgAreaA : "ptgAreaA",
- ptgMemAreaA : "ptgMemAreaA",
- ptgMemErrA : "ptgMemErrA",
- ptgMemNoMemA : "ptgMemNoMemA",
- ptgMemFuncA : "ptgMemFuncA",
- ptgRefErrA : "ptgRefErrA",
- ptgAreaErrA : "ptgAreaErrA",
- ptgRefNA : "ptgRefNA",
- ptgAreaNA : "ptgAreaNA",
- ptgMemAreaNA : "ptgMemAreaNA",
- ptgMemNoMemNA : "ptgMemNoMemNA",
- ptgFuncCEA : "ptgFuncCEA",
- ptgNameXA : "ptgNameXA",
- ptgRef3dA : "ptgRef3dA",
- ptgArea3dA : "ptgArea3dA",
- ptgRefErr3dA : "ptgRefErr3dA",
- ptgAreaErr3dA : "ptgAreaErr3dA"
-}
-
-
-error_msg_by_code = {
- 0x00: "#NULL!", # intersection of two cell ranges is empty
- 0x07: "#DIV/0!", # division by zero
- 0x0F: "#VALUE!", # wrong type of operand
- 0x17: "#REF!", # illegal or deleted cell reference
- 0x1D: "#NAME?", # wrong function or range name
- 0x24: "#NUM!", # value range overflow
- 0x2A: "#N/A!" # argument or function not available
-}
diff --git a/tablib/packages/xlwt3/Formatting.py b/tablib/packages/xlwt3/Formatting.py
deleted file mode 100644
index c92498b..0000000
--- a/tablib/packages/xlwt3/Formatting.py
+++ /dev/null
@@ -1,261 +0,0 @@
-#!/usr/bin/env python
-'''
-The XF record is able to store explicit cell formatting attributes or the
-attributes of a cell style. Explicit formatting includes the reference to
-a cell style XF record. This allows to extend a defined cell style with
-some explicit attributes. The formatting attributes are divided into
-6 groups:
-
-Group Attributes
--------------------------------------
-Number format Number format index (index to FORMAT record)
-Font Font index (index to FONT record)
-Alignment Horizontal and vertical alignment, text wrap, indentation,
- orientation/rotation, text direction
-Border Border line styles and colours
-Background Background area style and colours
-Protection Cell locked, formula hidden
-
-For each group a flag in the cell XF record specifies whether to use the
-attributes contained in that XF record or in the referenced style
-XF record. In style XF records, these flags specify whether the attributes
-will overwrite explicit cell formatting when the style is applied to
-a cell. Changing a cell style (without applying this style to a cell) will
-change all cells which already use that style and do not contain explicit
-cell attributes for the changed style attributes. If a cell XF record does
-not contain explicit attributes in a group (if the attribute group flag
-is not set), it repeats the attributes of its style XF record.
-
-'''
-
-from . import BIFFRecords
-
-class Font(object):
-
- ESCAPEMENT_NONE = 0x00
- ESCAPEMENT_SUPERSCRIPT = 0x01
- ESCAPEMENT_SUBSCRIPT = 0x02
-
- UNDERLINE_NONE = 0x00
- UNDERLINE_SINGLE = 0x01
- UNDERLINE_SINGLE_ACC = 0x21
- UNDERLINE_DOUBLE = 0x02
- UNDERLINE_DOUBLE_ACC = 0x22
-
- FAMILY_NONE = 0x00
- FAMILY_ROMAN = 0x01
- FAMILY_SWISS = 0x02
- FAMILY_MODERN = 0x03
- FAMILY_SCRIPT = 0x04
- FAMILY_DECORATIVE = 0x05
-
- CHARSET_ANSI_LATIN = 0x00
- CHARSET_SYS_DEFAULT = 0x01
- CHARSET_SYMBOL = 0x02
- CHARSET_APPLE_ROMAN = 0x4D
- CHARSET_ANSI_JAP_SHIFT_JIS = 0x80
- CHARSET_ANSI_KOR_HANGUL = 0x81
- CHARSET_ANSI_KOR_JOHAB = 0x82
- CHARSET_ANSI_CHINESE_GBK = 0x86
- CHARSET_ANSI_CHINESE_BIG5 = 0x88
- CHARSET_ANSI_GREEK = 0xA1
- CHARSET_ANSI_TURKISH = 0xA2
- CHARSET_ANSI_VIETNAMESE = 0xA3
- CHARSET_ANSI_HEBREW = 0xB1
- CHARSET_ANSI_ARABIC = 0xB2
- CHARSET_ANSI_BALTIC = 0xBA
- CHARSET_ANSI_CYRILLIC = 0xCC
- CHARSET_ANSI_THAI = 0xDE
- CHARSET_ANSI_LATIN_II = 0xEE
- CHARSET_OEM_LATIN_I = 0xFF
-
- def __init__(self):
- # twip = 1/20 of a point = 1/1440 of a inch
- # usually resolution == 96 pixels per 1 inch
- # (rarely 120 pixels per 1 inch or another one)
-
- self.height = 0x00C8 # 200: this is font with height 10 points
- self.italic = False
- self.struck_out = False
- self.outline = False
- self.shadow = False
- self.colour_index = 0x7FFF
- self.bold = False
- self._weight = 0x0190 # 0x02BC gives bold font
- self.escapement = self.ESCAPEMENT_NONE
- self.underline = self.UNDERLINE_NONE
- self.family = self.FAMILY_NONE
- self.charset = self.CHARSET_SYS_DEFAULT
- self.name = b'Arial'
-
- def get_biff_record(self):
- height = self.height
-
- options = 0x00
- if self.bold:
- options |= 0x01
- self._weight = 0x02BC
- if self.italic:
- options |= 0x02
- if self.underline != self.UNDERLINE_NONE:
- options |= 0x04
- if self.struck_out:
- options |= 0x08
- if self.outline:
- options |= 0x010
- if self.shadow:
- options |= 0x020
-
- colour_index = self.colour_index
- weight = self._weight
- escapement = self.escapement
- underline = self.underline
- family = self.family
- charset = self.charset
- name = self.name
-
- return BIFFRecords.FontRecord(height, options, colour_index, weight, escapement,
- underline, family, charset,
- name)
-
- def _search_key(self):
- return (
- self.height,
- self.italic,
- self.struck_out,
- self.outline,
- self.shadow,
- self.colour_index,
- self.bold,
- self._weight,
- self.escapement,
- self.underline,
- self.family,
- self.charset,
- self.name,
- )
-
-class Alignment(object):
- HORZ_GENERAL = 0x00
- HORZ_LEFT = 0x01
- HORZ_CENTER = 0x02
- HORZ_RIGHT = 0x03
- HORZ_FILLED = 0x04
- HORZ_JUSTIFIED = 0x05 # BIFF4-BIFF8X
- HORZ_CENTER_ACROSS_SEL = 0x06 # Centred across selection (BIFF4-BIFF8X)
- HORZ_DISTRIBUTED = 0x07 # Distributed (BIFF8X)
-
- VERT_TOP = 0x00
- VERT_CENTER = 0x01
- VERT_BOTTOM = 0x02
- VERT_JUSTIFIED = 0x03 # Justified (BIFF5-BIFF8X)
- VERT_DISTRIBUTED = 0x04 # Distributed (BIFF8X)
-
- DIRECTION_GENERAL = 0x00 # BIFF8X
- DIRECTION_LR = 0x01
- DIRECTION_RL = 0x02
-
- ORIENTATION_NOT_ROTATED = 0x00
- ORIENTATION_STACKED = 0x01
- ORIENTATION_90_CC = 0x02
- ORIENTATION_90_CW = 0x03
-
- ROTATION_0_ANGLE = 0x00
- ROTATION_STACKED = 0xFF
-
- WRAP_AT_RIGHT = 0x01
- NOT_WRAP_AT_RIGHT = 0x00
-
- SHRINK_TO_FIT = 0x01
- NOT_SHRINK_TO_FIT = 0x00
-
- def __init__(self):
- self.horz = self.HORZ_GENERAL
- self.vert = self.VERT_BOTTOM
- self.dire = self.DIRECTION_GENERAL
- self.orie = self.ORIENTATION_NOT_ROTATED
- self.rota = self.ROTATION_0_ANGLE
- self.wrap = self.NOT_WRAP_AT_RIGHT
- self.shri = self.NOT_SHRINK_TO_FIT
- self.inde = 0
- self.merg = 0
-
- def _search_key(self):
- return (
- self.horz, self.vert, self.dire, self.orie, self.rota,
- self.wrap, self.shri, self.inde, self.merg,
- )
-
-class Borders(object):
- NO_LINE = 0x00
- THIN = 0x01
- MEDIUM = 0x02
- DASHED = 0x03
- DOTTED = 0x04
- THICK = 0x05
- DOUBLE = 0x06
- HAIR = 0x07
- #The following for BIFF8
- MEDIUM_DASHED = 0x08
- THIN_DASH_DOTTED = 0x09
- MEDIUM_DASH_DOTTED = 0x0A
- THIN_DASH_DOT_DOTTED = 0x0B
- MEDIUM_DASH_DOT_DOTTED = 0x0C
- SLANTED_MEDIUM_DASH_DOTTED = 0x0D
-
- NEED_DIAG1 = 0x01
- NEED_DIAG2 = 0x01
- NO_NEED_DIAG1 = 0x00
- NO_NEED_DIAG2 = 0x00
-
- def __init__(self):
- self.left = self.NO_LINE
- self.right = self.NO_LINE
- self.top = self.NO_LINE
- self.bottom = self.NO_LINE
- self.diag = self.NO_LINE
-
- self.left_colour = 0x40
- self.right_colour = 0x40
- self.top_colour = 0x40
- self.bottom_colour = 0x40
- self.diag_colour = 0x40
-
- self.need_diag1 = self.NO_NEED_DIAG1
- self.need_diag2 = self.NO_NEED_DIAG2
-
- def _search_key(self):
- return (
- self.left, self.right, self.top, self.bottom, self.diag,
- self.left_colour, self.right_colour, self.top_colour,
- self.bottom_colour, self.diag_colour,
- self.need_diag1, self.need_diag2,
- )
-
-class Pattern(object):
- # patterns 0x00 - 0x12
- NO_PATTERN = 0x00
- SOLID_PATTERN = 0x01
-
- def __init__(self):
- self.pattern = self.NO_PATTERN
- self.pattern_fore_colour = 0x40
- self.pattern_back_colour = 0x41
-
- def _search_key(self):
- return (
- self.pattern,
- self.pattern_fore_colour,
- self.pattern_back_colour,
- )
-
-class Protection(object):
- def __init__(self):
- self.cell_locked = 1
- self.formula_hidden = 0
-
- def _search_key(self):
- return (
- self.cell_locked,
- self.formula_hidden,
- )
diff --git a/tablib/packages/xlwt3/Row.py b/tablib/packages/xlwt3/Row.py
deleted file mode 100644
index 46447b8..0000000
--- a/tablib/packages/xlwt3/Row.py
+++ /dev/null
@@ -1,253 +0,0 @@
-# -*- coding: windows-1252 -*-
-
-from . import BIFFRecords
-from . import Style
-from .Cell import StrCell, BlankCell, NumberCell, FormulaCell, MulBlankCell, BooleanCell, ErrorCell, \
- _get_cells_biff_data_mul
-from . import ExcelFormula
-import datetime as dt
-try:
- from decimal import Decimal
-except ImportError:
- # Python 2.3: decimal not supported; create dummy Decimal class
- class Decimal(object):
- pass
-
-
-class Row(object):
- __slots__ = [# private variables
- "__idx",
- "__parent",
- "__parent_wb",
- "__cells",
- "__min_col_idx",
- "__max_col_idx",
- "__xf_index",
- "__has_default_xf_index",
- "__height_in_pixels",
- # public variables
- "height",
- "has_default_height",
- "height_mismatch",
- "level",
- "collapse",
- "hidden",
- "space_above",
- "space_below"]
-
- def __init__(self, rowx, parent_sheet):
- if not (isinstance(rowx, int) and 0 <= rowx <= 65535):
- raise ValueError("row index (%r) not an int in range(65536)" % rowx)
- self.__idx = rowx
- self.__parent = parent_sheet
- self.__parent_wb = parent_sheet.get_parent()
- self.__cells = {}
- self.__min_col_idx = 0
- self.__max_col_idx = 0
- self.__xf_index = 0x0F
- self.__has_default_xf_index = 0
- self.__height_in_pixels = 0x11
-
- self.height = 0x00FF
- self.has_default_height = 0x00
- self.height_mismatch = 0
- self.level = 0
- self.collapse = 0
- self.hidden = 0
- self.space_above = 0
- self.space_below = 0
-
-
- def __adjust_height(self, style):
- twips = style.font.height
- points = float(twips)/20.0
- # Cell height in pixels can be calcuted by following approx. formula:
- # cell height in pixels = font height in points * 83/50 + 2/5
- # It works when screen resolution is 96 dpi
- pix = int(round(points*83.0/50.0 + 2.0/5.0))
- if pix > self.__height_in_pixels:
- self.__height_in_pixels = pix
-
-
- def __adjust_bound_col_idx(self, *args):
- for arg in args:
- iarg = int(arg)
- if not ((0 <= iarg <= 255) and arg == iarg):
- raise ValueError("column index (%r) not an int in range(256)" % arg)
- sheet = self.__parent
- if iarg < self.__min_col_idx:
- self.__min_col_idx = iarg
- if iarg > self.__max_col_idx:
- self.__max_col_idx = iarg
- if iarg < sheet.first_used_col:
- sheet.first_used_col = iarg
- if iarg > sheet.last_used_col:
- sheet.last_used_col = iarg
-
- def __excel_date_dt(self, date):
- if isinstance(date, dt.date) and (not isinstance(date, dt.datetime)):
- epoch = dt.date(1899, 12, 31)
- elif isinstance(date, dt.time):
- date = dt.datetime.combine(dt.datetime(1900, 1, 1), date)
- epoch = dt.datetime(1900, 1, 1, 0, 0, 0)
- else:
- epoch = dt.datetime(1899, 12, 31, 0, 0, 0)
- delta = date - epoch
- xldate = delta.days + float(delta.seconds) / (24*60*60)
- # Add a day for Excel's missing leap day in 1900
- if xldate > 59:
- xldate += 1
- return xldate
-
- def get_height_in_pixels(self):
- return self.__height_in_pixels
-
-
- def set_style(self, style):
- self.__adjust_height(style)
- self.__xf_index = self.__parent_wb.add_style(style)
- self.__has_default_xf_index = 1
-
-
- def get_xf_index(self):
- return self.__xf_index
-
-
- def get_cells_count(self):
- return len(self.__cells)
-
-
- def get_min_col(self):
- return self.__min_col_idx
-
-
- def get_max_col(self):
- return self.__max_col_idx
-
-
- def get_row_biff_data(self):
- height_options = (self.height & 0x07FFF)
- height_options |= (self.has_default_height & 0x01) << 15
-
- options = (self.level & 0x07) << 0
- options |= (self.collapse & 0x01) << 4
- options |= (self.hidden & 0x01) << 5
- options |= (self.height_mismatch & 0x01) << 6
- options |= (self.__has_default_xf_index & 0x01) << 7
- options |= (0x01 & 0x01) << 8
- options |= (self.__xf_index & 0x0FFF) << 16
- options |= (self.space_above & 1) << 28
- options |= (self.space_below & 1) << 29
-
- return BIFFRecords.RowRecord(self.__idx, self.__min_col_idx,
- self.__max_col_idx, height_options, options).get()
-
- def insert_cell(self, col_index, cell_obj):
- if col_index in self.__cells:
- if not self.__parent._cell_overwrite_ok:
- msg = "Attempt to overwrite cell: sheetname=%r rowx=%d colx=%d" \
- % (self.__parent.name, self.__idx, col_index)
- raise Exception(msg)
- prev_cell_obj = self.__cells[col_index]
- sst_idx = getattr(prev_cell_obj, 'sst_idx', None)
- if sst_idx is not None:
- self.__parent_wb.del_str(sst_idx)
- self.__cells[col_index] = cell_obj
-
- def insert_mulcells(self, colx1, colx2, cell_obj):
- self.insert_cell(colx1, cell_obj)
- for col_index in range(colx1+1, colx2+1):
- self.insert_cell(col_index, None)
-
- def get_cells_biff_data(self):
- cell_items = [item for item in self.__cells.items() if item[1] is not None]
- cell_items.sort() # in column order
- return _get_cells_biff_data_mul(self.__idx, cell_items)
- # previously:
- # return ''.join([cell.get_biff_data() for colx, cell in cell_items])
-
- def get_index(self):
- return self.__idx
-
- def set_cell_text(self, colx, value, style=Style.default_style):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(colx)
- xf_index = self.__parent_wb.add_style(style)
- self.insert_cell(colx, StrCell(self.__idx, colx, xf_index, self.__parent_wb.add_str(value)))
-
- def set_cell_blank(self, colx, style=Style.default_style):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(colx)
- xf_index = self.__parent_wb.add_style(style)
- self.insert_cell(colx, BlankCell(self.__idx, colx, xf_index))
-
- def set_cell_mulblanks(self, first_colx, last_colx, style=Style.default_style):
- assert 0 <= first_colx <= last_colx <= 255
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(first_colx, last_colx)
- xf_index = self.__parent_wb.add_style(style)
- # ncols = last_colx - first_colx + 1
- self.insert_mulcells(first_colx, last_colx, MulBlankCell(self.__idx, first_colx, last_colx, xf_index))
-
- def set_cell_number(self, colx, number, style=Style.default_style):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(colx)
- xf_index = self.__parent_wb.add_style(style)
- self.insert_cell(colx, NumberCell(self.__idx, colx, xf_index, number))
-
- def set_cell_date(self, colx, datetime_obj, style=Style.default_style):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(colx)
- xf_index = self.__parent_wb.add_style(style)
- self.insert_cell(colx,
- NumberCell(self.__idx, colx, xf_index, self.__excel_date_dt(datetime_obj)))
-
- def set_cell_formula(self, colx, formula, style=Style.default_style, calc_flags=0):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(colx)
- xf_index = self.__parent_wb.add_style(style)
- self.__parent_wb.add_sheet_reference(formula)
- self.insert_cell(colx, FormulaCell(self.__idx, colx, xf_index, formula, calc_flags=0))
-
- def set_cell_boolean(self, colx, value, style=Style.default_style):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(colx)
- xf_index = self.__parent_wb.add_style(style)
- self.insert_cell(colx, BooleanCell(self.__idx, colx, xf_index, bool(value)))
-
- def set_cell_error(self, colx, error_string_or_code, style=Style.default_style):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(colx)
- xf_index = self.__parent_wb.add_style(style)
- self.insert_cell(colx, ErrorCell(self.__idx, colx, xf_index, error_string_or_code))
-
- def write(self, col, label, style=Style.default_style):
- self.__adjust_height(style)
- self.__adjust_bound_col_idx(col)
- style_index = self.__parent_wb.add_style(style)
- if isinstance(label, str):
- if len(label) > 0:
- self.insert_cell(col,
- StrCell(self.__idx, col, style_index, self.__parent_wb.add_str(label))
- )
- else:
- self.insert_cell(col, BlankCell(self.__idx, col, style_index))
- elif isinstance(label, bool): # bool is subclass of int; test bool first
- self.insert_cell(col, BooleanCell(self.__idx, col, style_index, label))
- elif isinstance(label, (float, int, Decimal)):
- self.insert_cell(col, NumberCell(self.__idx, col, style_index, label))
- elif isinstance(label, (dt.datetime, dt.date, dt.time)):
- date_number = self.__excel_date_dt(label)
- self.insert_cell(col, NumberCell(self.__idx, col, style_index, date_number))
- elif label is None:
- self.insert_cell(col, BlankCell(self.__idx, col, style_index))
- elif isinstance(label, ExcelFormula.Formula):
- self.__parent_wb.add_sheet_reference(label)
- self.insert_cell(col, FormulaCell(self.__idx, col, style_index, label))
- else:
- raise Exception("Unexpected data type %r" % type(label))
-
- write_blanks = set_cell_mulblanks
-
-
-
diff --git a/tablib/packages/xlwt3/Style.py b/tablib/packages/xlwt3/Style.py
deleted file mode 100644
index 182fc07..0000000
--- a/tablib/packages/xlwt3/Style.py
+++ /dev/null
@@ -1,593 +0,0 @@
-# -*- coding: windows-1252 -*-
-
-from . import Formatting
-from .BIFFRecords import *
-import collections
-
-FIRST_USER_DEFINED_NUM_FORMAT_IDX = 164
-
-class XFStyle(object):
-
- def __init__(self):
- self.num_format_str = 'General'
- self.font = Formatting.Font()
- self.alignment = Formatting.Alignment()
- self.borders = Formatting.Borders()
- self.pattern = Formatting.Pattern()
- self.protection = Formatting.Protection()
-
-default_style = XFStyle()
-
-class StyleCollection(object):
- _std_num_fmt_list = [
- 'general',
- '0',
- '0.00',
- '#,##0',
- '#,##0.00',
- '"$"#,##0_);("$"#,##',
- '"$"#,##0_);[Red]("$"#,##',
- '"$"#,##0.00_);("$"#,##',
- '"$"#,##0.00_);[Red]("$"#,##',
- '0%',
- '0.00%',
- '0.00E+00',
- '# ?/?',
- '# ??/??',
- 'M/D/YY',
- 'D-MMM-YY',
- 'D-MMM',
- 'MMM-YY',
- 'h:mm AM/PM',
- 'h:mm:ss AM/PM',
- 'h:mm',
- 'h:mm:ss',
- 'M/D/YY h:mm',
- '_(#,##0_);(#,##0)',
- '_(#,##0_);[Red](#,##0)',
- '_(#,##0.00_);(#,##0.00)',
- '_(#,##0.00_);[Red](#,##0.00)',
- '_("$"* #,##0_);_("$"* (#,##0);_("$"* "-"_);_(@_)',
- '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)',
- '_("$"* #,##0.00_);_("$"* (#,##0.00);_("$"* "-"??_);_(@_)',
- '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)',
- 'mm:ss',
- '[h]:mm:ss',
- 'mm:ss.0',
- '##0.0E+0',
- '@'
- ]
-
- def __init__(self, style_compression=0):
- self.style_compression = style_compression
- self.stats = [0, 0, 0, 0, 0, 0]
- self._font_id2x = {}
- self._font_x2id = {}
- self._font_val2x = {}
-
- for x in (0, 1, 2, 3, 5): # The font with index 4 is omitted in all BIFF versions
- font = Formatting.Font()
- search_key = font._search_key()
- self._font_id2x[font] = x
- self._font_x2id[x] = font
- self._font_val2x[search_key] = x
-
- self._xf_id2x = {}
- self._xf_x2id = {}
- self._xf_val2x = {}
-
- self._num_formats = {}
- for fmtidx, fmtstr in zip(list(range(0, 23)), StyleCollection._std_num_fmt_list[0:23]):
- self._num_formats[fmtstr] = fmtidx
- for fmtidx, fmtstr in zip(list(range(37, 50)), StyleCollection._std_num_fmt_list[23:]):
- self._num_formats[fmtstr] = fmtidx
-
- self.default_style = XFStyle()
- self._default_xf = self._add_style(self.default_style)[0]
-
- def add(self, style):
- if style == None:
- return 0x10
- return self._add_style(style)[1]
-
- def _add_style(self, style):
- num_format_str = style.num_format_str
- if num_format_str in self._num_formats:
- num_format_idx = self._num_formats[num_format_str]
- else:
- num_format_idx = (
- FIRST_USER_DEFINED_NUM_FORMAT_IDX
- + len(self._num_formats)
- - len(StyleCollection._std_num_fmt_list)
- )
- self._num_formats[num_format_str] = num_format_idx
-
- font = style.font
- if font in self._font_id2x:
- font_idx = self._font_id2x[font]
- self.stats[0] += 1
- elif self.style_compression:
- search_key = font._search_key()
- font_idx = self._font_val2x.get(search_key)
- if font_idx is not None:
- self._font_id2x[font] = font_idx
- self.stats[1] += 1
- else:
- font_idx = len(self._font_x2id) + 1 # Why plus 1? Font 4 is missing
- self._font_id2x[font] = font_idx
- self._font_val2x[search_key] = font_idx
- self._font_x2id[font_idx] = font
- self.stats[2] += 1
- else:
- font_idx = len(self._font_id2x) + 1
- self._font_id2x[font] = font_idx
- self.stats[2] += 1
-
- gof = (style.alignment, style.borders, style.pattern, style.protection)
- xf = (font_idx, num_format_idx) + gof
- if xf in self._xf_id2x:
- xf_index = self._xf_id2x[xf]
- self.stats[3] += 1
- elif self.style_compression == 2:
- xf_key = (font_idx, num_format_idx) + tuple([obj._search_key() for obj in gof])
- xf_index = self._xf_val2x.get(xf_key)
- if xf_index is not None:
- self._xf_id2x[xf] = xf_index
- self.stats[4] += 1
- else:
- xf_index = 0x10 + len(self._xf_x2id)
- self._xf_id2x[xf] = xf_index
- self._xf_val2x[xf_key] = xf_index
- self._xf_x2id[xf_index] = xf
- self.stats[5] += 1
- else:
- xf_index = 0x10 + len(self._xf_id2x)
- self._xf_id2x[xf] = xf_index
- self.stats[5] += 1
-
- if xf_index >= 0xFFF:
- # 12 bits allowed, 0xFFF is a sentinel value
- raise ValueError("More than 4094 XFs (styles)")
-
- return xf, xf_index
-
- def get_biff_data(self):
- result = b''
- result += self._all_fonts()
- result += self._all_num_formats()
- result += self._all_cell_styles()
- result += self._all_styles()
- return result
-
- def _all_fonts(self):
- result = b''
- if self.style_compression:
- alist = list(self._font_x2id.items())
- else:
- alist = [(x, o) for o, x in list(self._font_id2x.items())]
- alist.sort()
- for font_idx, font in alist:
- result += font.get_biff_record().get()
- return result
-
- def _all_num_formats(self):
- result = b''
- alist = [
- (v, k)
- for k, v in list(self._num_formats.items())
- if v >= FIRST_USER_DEFINED_NUM_FORMAT_IDX
- ]
- alist.sort()
- for fmtidx, fmtstr in alist:
- result += NumberFormatRecord(fmtidx, fmtstr).get()
- return result
-
- def _all_cell_styles(self):
- result = b''
- for i in range(0, 16):
- result += XFRecord(self._default_xf, 'style').get()
- if self.style_compression == 2:
- alist = list(self._xf_x2id.items())
- else:
- alist = [(x, o) for o, x in list(self._xf_id2x.items())]
- alist.sort()
- for xf_idx, xf in alist:
- result += XFRecord(xf).get()
- return result
-
- def _all_styles(self):
- return StyleRecord().get()
-
-# easyxf and its supporting objects ###################################
-
-class EasyXFException(Exception):
- pass
-
-class EasyXFCallerError(EasyXFException):
- pass
-
-class EasyXFAuthorError(EasyXFException):
- pass
-
-class IntULim(object):
- # If astring represents a valid unsigned integer ('123', '0xabcd', etc)
- # and it is <= limit, return the int value; otherwise return None.
-
- def __init__(self, limit):
- self.limit = limit
-
- def __call__(self, astring):
- try:
- value = int(astring, 0)
- except ValueError:
- return None
- if not 0 <= value <= self.limit:
- return None
- return value
-
-bool_map = {
- # Text values for all Boolean attributes
- '1': 1, 'yes': 1, 'true': 1, 'on': 1,
- '0': 0, 'no': 0, 'false': 0, 'off': 0,
- }
-
-border_line_map = {
- # Text values for these borders attributes:
- # left, right, top, bottom and diag
- 'no_line': 0x00,
- 'thin': 0x01,
- 'medium': 0x02,
- 'dashed': 0x03,
- 'dotted': 0x04,
- 'thick': 0x05,
- 'double': 0x06,
- 'hair': 0x07,
- 'medium_dashed': 0x08,
- 'thin_dash_dotted': 0x09,
- 'medium_dash_dotted': 0x0a,
- 'thin_dash_dot_dotted': 0x0b,
- 'medium_dash_dot_dotted': 0x0c,
- 'slanted_medium_dash_dotted': 0x0d,
- }
-
-charset_map = {
- # Text values for font.charset
- 'ansi_latin': 0x00,
- 'sys_default': 0x01,
- 'symbol': 0x02,
- 'apple_roman': 0x4d,
- 'ansi_jap_shift_jis': 0x80,
- 'ansi_kor_hangul': 0x81,
- 'ansi_kor_johab': 0x82,
- 'ansi_chinese_gbk': 0x86,
- 'ansi_chinese_big5': 0x88,
- 'ansi_greek': 0xa1,
- 'ansi_turkish': 0xa2,
- 'ansi_vietnamese': 0xa3,
- 'ansi_hebrew': 0xb1,
- 'ansi_arabic': 0xb2,
- 'ansi_baltic': 0xba,
- 'ansi_cyrillic': 0xcc,
- 'ansi_thai': 0xde,
- 'ansi_latin_ii': 0xee,
- 'oem_latin_i': 0xff,
- }
-
-
-# Text values for colour indices. "grey" is a synonym of "gray".
-# The names are those given by Microsoft Excel 2003 to the colours
-# in the default palette. There is no great correspondence with
-# any W3C name-to-RGB mapping.
-_colour_map_text = """\
-aqua 0x31
-black 0x08
-blue 0x0C
-blue_gray 0x36
-bright_green 0x0B
-brown 0x3C
-coral 0x1D
-cyan_ega 0x0F
-dark_blue 0x12
-dark_blue_ega 0x12
-dark_green 0x3A
-dark_green_ega 0x11
-dark_purple 0x1C
-dark_red 0x10
-dark_red_ega 0x10
-dark_teal 0x38
-dark_yellow 0x13
-gold 0x33
-gray_ega 0x17
-gray25 0x16
-gray40 0x37
-gray50 0x17
-gray80 0x3F
-green 0x11
-ice_blue 0x1F
-indigo 0x3E
-ivory 0x1A
-lavender 0x2E
-light_blue 0x30
-light_green 0x2A
-light_orange 0x34
-light_turquoise 0x29
-light_yellow 0x2B
-lime 0x32
-magenta_ega 0x0E
-ocean_blue 0x1E
-olive_ega 0x13
-olive_green 0x3B
-orange 0x35
-pale_blue 0x2C
-periwinkle 0x18
-pink 0x0E
-plum 0x3D
-purple_ega 0x14
-red 0x0A
-rose 0x2D
-sea_green 0x39
-silver_ega 0x16
-sky_blue 0x28
-tan 0x2F
-teal 0x15
-teal_ega 0x15
-turquoise 0x0F
-violet 0x14
-white 0x09
-yellow 0x0D"""
-
-colour_map = {}
-for _line in _colour_map_text.splitlines():
- _name, _num = _line.split()
- _num = int(_num, 0)
- colour_map[_name] = _num
- if 'gray' in _name:
- colour_map[_name.replace('gray', 'grey')] = _num
-del _colour_map_text, _line, _name, _num
-
-
-pattern_map = {
- # Text values for pattern.pattern
- # xlwt/doc/pattern_examples.xls showcases all of these patterns.
- 'no_fill': 0,
- 'none': 0,
- 'solid': 1,
- 'solid_fill': 1,
- 'solid_pattern': 1,
- 'fine_dots': 2,
- 'alt_bars': 3,
- 'sparse_dots': 4,
- 'thick_horz_bands': 5,
- 'thick_vert_bands': 6,
- 'thick_backward_diag': 7,
- 'thick_forward_diag': 8,
- 'big_spots': 9,
- 'bricks': 10,
- 'thin_horz_bands': 11,
- 'thin_vert_bands': 12,
- 'thin_backward_diag': 13,
- 'thin_forward_diag': 14,
- 'squares': 15,
- 'diamonds': 16,
- }
-
-def any_str_func(s):
- return s.strip()
-
-def colour_index_func(s, maxval=0x7F):
- try:
- value = int(s, 0)
- except ValueError:
- return None
- if not (0 <= value <= maxval):
- return None
- return value
-
-colour_index_func_7 = colour_index_func
-
-def colour_index_func_15(s):
- return colour_index_func(s, maxval=0x7FFF)
-
-def rotation_func(s):
- try:
- value = int(s, 0)
- except ValueError:
- return None
- if not (-90 <= value <= 90):
- raise EasyXFCallerError("rotation %d: should be -90 to +90 degrees" % value)
- if value < 0:
- value = 90 - value # encode as 91 to 180 (clockwise)
- return value
-
-xf_dict = {
- 'align': 'alignment', # synonym
- 'alignment': {
- 'dire': {
- 'general': 0,
- 'lr': 1,
- 'rl': 2,
- },
- 'direction': 'dire',
- 'horiz': 'horz',
- 'horizontal': 'horz',
- 'horz': {
- 'general': 0,
- 'left': 1,
- 'center': 2,
- 'centre': 2, # "align: horiz centre" means xf.alignment.horz is set to 2
- 'right': 3,
- 'filled': 4,
- 'justified': 5,
- 'center_across_selection': 6,
- 'centre_across_selection': 6,
- 'distributed': 7,
- },
- 'inde': IntULim(15), # restriction: 0 <= value <= 15
- 'indent': 'inde',
- 'rota': [{'stacked': 255, 'none': 0, }, rotation_func],
- 'rotation': 'rota',
- 'shri': bool_map,
- 'shrink': 'shri',
- 'shrink_to_fit': 'shri',
- 'vert': {
- 'top': 0,
- 'center': 1,
- 'centre': 1,
- 'bottom': 2,
- 'justified': 3,
- 'distributed': 4,
- },
- 'vertical': 'vert',
- 'wrap': bool_map,
- },
- 'border': 'borders',
- 'borders': {
- 'left': [border_line_map, IntULim(0x0d)],
- 'right': [border_line_map, IntULim(0x0d)],
- 'top': [border_line_map, IntULim(0x0d)],
- 'bottom': [border_line_map, IntULim(0x0d)],
- 'diag': [border_line_map, IntULim(0x0d)],
- 'top_colour': [colour_map, colour_index_func_7],
- 'bottom_colour': [colour_map, colour_index_func_7],
- 'left_colour': [colour_map, colour_index_func_7],
- 'right_colour': [colour_map, colour_index_func_7],
- 'diag_colour': [colour_map, colour_index_func_7],
- 'top_color': 'top_colour',
- 'bottom_color': 'bottom_colour',
- 'left_color': 'left_colour',
- 'right_color': 'right_colour',
- 'diag_color': 'diag-colour',
- 'need_diag_1': bool_map,
- 'need_diag_2': bool_map,
- },
- 'font': {
- 'bold': bool_map,
- 'charset': charset_map,
- 'color': 'colour_index',
- 'color_index': 'colour_index',
- 'colour': 'colour_index',
- 'colour_index': [colour_map, colour_index_func_15],
- 'escapement': {'none': 0, 'superscript': 1, 'subscript': 2},
- 'family': {'none': 0, 'roman': 1, 'swiss': 2, 'modern': 3, 'script': 4, 'decorative': 5, },
- 'height': IntULim(0xFFFF), # practical limits are much narrower e.g. 160 to 1440 (8pt to 72pt)
- 'italic': bool_map,
- 'name': any_str_func,
- 'outline': bool_map,
- 'shadow': bool_map,
- 'struck_out': bool_map,
- 'underline': [bool_map, {'none': 0, 'single': 1, 'single_acc': 0x21, 'double': 2, 'double_acc': 0x22, }],
- },
- 'pattern': {
- 'back_color': 'pattern_back_colour',
- 'back_colour': 'pattern_back_colour',
- 'fore_color': 'pattern_fore_colour',
- 'fore_colour': 'pattern_fore_colour',
- 'pattern': [pattern_map, IntULim(16)],
- 'pattern_back_color': 'pattern_back_colour',
- 'pattern_back_colour': [colour_map, colour_index_func_7],
- 'pattern_fore_color': 'pattern_fore_colour',
- 'pattern_fore_colour': [colour_map, colour_index_func_7],
- },
- 'protection': {
- 'cell_locked' : bool_map,
- 'formula_hidden': bool_map,
- },
- }
-
-def _esplit(s, split_char, esc_char="\\"):
- escaped = False
- olist = ['']
- for c in s:
- if escaped:
- olist[-1] += c
- escaped = False
- elif c == esc_char:
- escaped = True
- elif c == split_char:
- olist.append('')
- else:
- olist[-1] += c
- return olist
-
-def _parse_strg_to_obj(strg, obj, parse_dict,
- field_sep=",", line_sep=";", intro_sep=":", esc_char="\\", debug=False):
- for line in _esplit(strg, line_sep, esc_char):
- line = line.strip()
- if not line:
- break
- split_line = _esplit(line, intro_sep, esc_char)
- if len(split_line) != 2:
- raise EasyXFCallerError('line %r should have exactly 1 "%c"' % (line, intro_sep))
- section, item_str = split_line
- section = section.strip().lower()
- for counter in range(2):
- result = parse_dict.get(section)
- if result is None:
- raise EasyXFCallerError('section %r is unknown' % section)
- if isinstance(result, dict):
- break
- if not isinstance(result, str):
- raise EasyXFAuthorError(
- 'section %r should map to dict or str object; found %r' % (section, type(result)))
- # synonym
- old_section = section
- section = result
- else:
- raise EasyXFAuthorError('Attempt to define synonym of synonym (%r: %r)' % (old_section, result))
- section_dict = result
- section_obj = getattr(obj, section, None)
- if section_obj is None:
- raise EasyXFAuthorError('instance of %s class has no attribute named %s' % (obj.__class__.__name__, section))
- for kv_str in _esplit(item_str, field_sep, esc_char):
- guff = kv_str.split()
- if not guff:
- continue
- k = guff[0].lower().replace('-', '_')
- v = ' '.join(guff[1:])
- if not v:
- raise EasyXFCallerError("no value supplied for %s.%s" % (section, k))
- for counter in range(2):
- result = section_dict.get(k)
- if result is None:
- raise EasyXFCallerError('%s.%s is not a known attribute' % (section, k))
- if not isinstance(result, str):
- break
- # synonym
- old_k = k
- k = result
- else:
- raise EasyXFAuthorError('Attempt to define synonym of synonym (%r: %r)' % (old_k, result))
- value_info = result
- if not isinstance(value_info, list):
- value_info = [value_info]
- for value_rule in value_info:
- if isinstance(value_rule, dict):
- # dict maps strings to integer field values
- vl = v.lower().replace('-', '_')
- if vl in value_rule:
- value = value_rule[vl]
- break
- elif isinstance(value_rule, collections.Callable):
- value = value_rule(v)
- if value is not None:
- break
- else:
- raise EasyXFAuthorError("unknown value rule for attribute %r: %r" % (k, value_rule))
- else:
- raise EasyXFCallerError("unexpected value %r for %s.%s" % (v, section, k))
- try:
- orig = getattr(section_obj, k)
- except AttributeError:
- raise EasyXFAuthorError('%s.%s in dictionary but not in supplied object' % (section, k))
- if debug: print("+++ %s.%s = %r # %s; was %r" % (section, k, value, v, orig))
- setattr(section_obj, k, value)
-
-def easyxf(strg_to_parse="", num_format_str=None,
- field_sep=",", line_sep=";", intro_sep=":", esc_char="\\", debug=False):
- xfobj = XFStyle()
- if num_format_str is not None:
- xfobj.num_format_str = num_format_str
- if strg_to_parse:
- _parse_strg_to_obj(strg_to_parse, xfobj, xf_dict,
- field_sep=field_sep, line_sep=line_sep, intro_sep=intro_sep, esc_char=esc_char, debug=debug)
- return xfobj
diff --git a/tablib/packages/xlwt3/UnicodeUtils.py b/tablib/packages/xlwt3/UnicodeUtils.py
deleted file mode 100644
index 204d13c..0000000
--- a/tablib/packages/xlwt3/UnicodeUtils.py
+++ /dev/null
@@ -1,79 +0,0 @@
-'''
-From BIFF8 on, strings are always stored using UTF-16LE text encoding. The
-character array is a sequence of 16-bit values4. Additionally it is
-possible to use a compressed format, which omits the high bytes of all
-characters, if they are all zero.
-
-The following tables describe the standard format of the entire string, but
-in many records the strings differ from this format. This will be mentioned
-separately. It is possible (but not required) to store Rich-Text formatting
-information and Asian phonetic information inside a Unicode string. This
-results in four different ways to store a string. The character array
-is not zero-terminated.
-
-The string consists of the character count (as usual an 8-bit value or
-a 16-bit value), option flags, the character array and optional formatting
-information. If the string is empty, sometimes the option flags field will
-not occur. This is mentioned at the respective place.
-
-Offset Size Contents
-0 1 or 2 Length of the string (character count, ln)
-1 or 2 1 Option flags:
- Bit Mask Contents
- 0 01H Character compression (ccompr):
- 0 = Compressed (8-bit characters)
- 1 = Uncompressed (16-bit characters)
- 2 04H Asian phonetic settings (phonetic):
- 0 = Does not contain Asian phonetic settings
- 1 = Contains Asian phonetic settings
- 3 08H Rich-Text settings (richtext):
- 0 = Does not contain Rich-Text settings
- 1 = Contains Rich-Text settings
-[2 or 3] 2 (optional, only if richtext=1) Number of Rich-Text formatting runs (rt)
-[var.] 4 (optional, only if phonetic=1) Size of Asian phonetic settings block (in bytes, sz)
-var. ln or
- 2·ln Character array (8-bit characters or 16-bit characters, dependent on ccompr)
-[var.] 4·rt (optional, only if richtext=1) List of rt formatting runs
-[var.] sz (optional, only if phonetic=1) Asian Phonetic Settings Block
-'''
-
-
-from struct import pack
-
-def upack2(s, encoding='ascii'):
- # If not unicode, make it so.
- if isinstance(s, str):
- us = s
- else:
- us = str(s, encoding)
- # Limit is based on number of content characters
- # (not on number of bytes in packed result)
- len_us = len(us)
- if len_us > 65535:
- raise Exception('String longer than 65535 characters')
- try:
- encs = us.encode('latin1')
- # Success here means all chars are in U+0000 to U+00FF
- # inclusive, meaning that we can use "compressed format".
- flag = 0
- except UnicodeEncodeError:
- encs = us.encode('utf_16_le')
- flag = 1
- return pack('<HB', len_us, flag) + encs
-
-def upack1(s, encoding='ascii'):
- # Same as upack2(), but with a one-byte length field.
- if isinstance(s, str):
- us = s
- else:
- us = str(s, encoding)
- len_us = len(us)
- if len_us > 255:
- raise Exception('String longer than 255 characters')
- try:
- encs = us.encode('latin1')
- flag = 0
- except UnicodeEncodeError:
- encs = us.encode('utf_16_le')
- flag = 1
- return pack('<BB', len_us, flag) + encs
diff --git a/tablib/packages/xlwt3/Utils.py b/tablib/packages/xlwt3/Utils.py
deleted file mode 100644
index 3509f03..0000000
--- a/tablib/packages/xlwt3/Utils.py
+++ /dev/null
@@ -1,196 +0,0 @@
-# pyXLWriter: A library for generating Excel Spreadsheets
-# Copyright (c) 2004 Evgeny Filatov <fufff@users.sourceforge.net>
-# Copyright (c) 2002-2004 John McNamara (Perl Spreadsheet::WriteExcel)
-#
-# This library is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
-# General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this library; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#----------------------------------------------------------------------------
-# This module was written/ported from PERL Spreadsheet::WriteExcel module
-# The author of the PERL Spreadsheet::WriteExcel module is John McNamara
-# <jmcnamara@cpan.org>
-#----------------------------------------------------------------------------
-# See the README.txt distributed with pyXLWriter for more details.
-
-# Portions are (C) Roman V. Kiseliov, 2005
-
-
-# Utilities for work with reference to cells and with sheetnames
-
-
-__rev_id__ = """$Id: Utils.py 3844 2009-05-20 01:02:54Z sjmachin $"""
-
-import re
-from struct import pack
-from .ExcelMagic import MAX_ROW, MAX_COL
-
-
-_re_cell_ex = re.compile(r"(\$?)([A-I]?[A-Z])(\$?)(\d+)", re.IGNORECASE)
-_re_row_range = re.compile(r"\$?(\d+):\$?(\d+)")
-_re_col_range = re.compile(r"\$?([A-I]?[A-Z]):\$?([A-I]?[A-Z])", re.IGNORECASE)
-_re_cell_range = re.compile(r"\$?([A-I]?[A-Z]\$?\d+):\$?([A-I]?[A-Z]\$?\d+)", re.IGNORECASE)
-_re_cell_ref = re.compile(r"\$?([A-I]?[A-Z]\$?\d+)", re.IGNORECASE)
-
-
-def col_by_name(colname):
- """
- """
- col = 0
- pow = 1
- for i in range(len(colname)-1, -1, -1):
- ch = colname[i]
- col += (ord(ch) - ord('A') + 1) * pow
- pow *= 26
- return col - 1
-
-
-def cell_to_rowcol(cell):
- """Convert an Excel cell reference string in A1 notation
- to numeric row/col notation.
-
- Returns: row, col, row_abs, col_abs
-
- """
- m = _re_cell_ex.match(cell)
- if not m:
- raise Exception("Ill-formed single_cell reference: %s" % cell)
- col_abs, col, row_abs, row = m.groups()
- row_abs = bool(row_abs)
- col_abs = bool(col_abs)
- row = int(row) - 1
- col = col_by_name(col.upper())
- return row, col, row_abs, col_abs
-
-
-def cell_to_rowcol2(cell):
- """Convert an Excel cell reference string in A1 notation
- to numeric row/col notation.
-
- Returns: row, col
-
- """
- m = _re_cell_ex.match(cell)
- if not m:
- raise Exception("Error in cell format")
- col_abs, col, row_abs, row = m.groups()
- # Convert base26 column string to number
- # All your Base are belong to us.
- row = int(row) - 1
- col = col_by_name(col.upper())
- return row, col
-
-
-def rowcol_to_cell(row, col, row_abs=False, col_abs=False):
- """Convert numeric row/col notation to an Excel cell reference string in
- A1 notation.
-
- """
- assert 0 <= row < MAX_ROW # MAX_ROW counts from 1
- assert 0 <= col < MAX_COL # MAX_COL counts from 1
- d = col // 26
- m = col % 26
- chr1 = "" # Most significant character in AA1
- if row_abs:
- row_abs = '$'
- else:
- row_abs = ''
- if col_abs:
- col_abs = '$'
- else:
- col_abs = ''
- if d > 0:
- chr1 = chr(ord('A') + d - 1)
- chr2 = chr(ord('A') + m)
- # Zero index to 1-index
- return col_abs + chr1 + chr2 + row_abs + str(row + 1)
-
-def rowcol_pair_to_cellrange(row1, col1, row2, col2,
- row1_abs=False, col1_abs=False, row2_abs=False, col2_abs=False):
- """Convert two (row,column) pairs
- into a cell range string in A1:B2 notation.
-
- Returns: cell range string
- """
- assert row1 <= row2
- assert col1 <= col2
- return (
- rowcol_to_cell(row1, col1, row1_abs, col1_abs)
- + ":"
- + rowcol_to_cell(row2, col2, row2_abs, col2_abs)
- )
-
-def cellrange_to_rowcol_pair(cellrange):
- """Convert cell range string in A1 notation to numeric row/col
- pair.
-
- Returns: row1, col1, row2, col2
-
- """
- cellrange = cellrange.upper()
- # Convert a row range: '1:3'
- res = _re_row_range.match(cellrange)
- if res:
- row1 = int(res.group(1)) - 1
- col1 = 0
- row2 = int(res.group(2)) - 1
- col2 = -1
- return row1, col1, row2, col2
- # Convert a column range: 'A:A' or 'B:G'.
- # A range such as A:A is equivalent to A1:A16384, so add rows as required
- res = _re_col_range.match(cellrange)
- if res:
- col1 = col_by_name(res.group(1).upper())
- row1 = 0
- col2 = col_by_name(res.group(2).upper())
- row2 = -1
- return row1, col1, row2, col2
- # Convert a cell range: 'A1:B7'
- res = _re_cell_range.match(cellrange)
- if res:
- row1, col1 = cell_to_rowcol2(res.group(1))
- row2, col2 = cell_to_rowcol2(res.group(2))
- return row1, col1, row2, col2
- # Convert a cell reference: 'A1' or 'AD2000'
- res = _re_cell_ref.match(cellrange)
- if res:
- row1, col1 = cell_to_rowcol2(res.group(1))
- return row1, col1, row1, col1
- raise Exception("Unknown cell reference %s" % (cell))
-
-
-def cell_to_packed_rowcol(cell):
- """ pack row and column into the required 4 byte format """
- row, col, row_abs, col_abs = cell_to_rowcol(cell)
- if col >= MAX_COL:
- raise Exception("Column %s greater than IV in formula" % cell)
- if row >= MAX_ROW: # this for BIFF8. for BIFF7 available 2^14
- raise Exception("Row %s greater than %d in formula" % (cell, MAX_ROW))
- col |= int(not row_abs) << 15
- col |= int(not col_abs) << 14
- return row, col
-
-# === sheetname functions ===
-
-def valid_sheet_name(sheet_name):
- if sheet_name == "" or sheet_name[0] == "'" or len(sheet_name) > 31:
- return False
- for c in sheet_name:
- if c in "[]:\\?/*\x00":
- return False
- return True
-
-def quote_sheet_name(unquoted_sheet_name):
- if not valid_sheet_name(unquoted_sheet_name):
- raise Exception(
- 'attempt to quote an invalid worksheet name %r' % unquoted_sheet_name)
- return "'" + unquoted_sheet_name.replace("'", "''") + "'"
diff --git a/tablib/packages/xlwt3/Workbook.py b/tablib/packages/xlwt3/Workbook.py
deleted file mode 100644
index ba42e6b..0000000
--- a/tablib/packages/xlwt3/Workbook.py
+++ /dev/null
@@ -1,635 +0,0 @@
-'''
-Record Order in BIFF8
- Workbook Globals Substream
- BOF Type = workbook globals
- Interface Header
- MMS
- Interface End
- WRITEACCESS
- CODEPAGE
- DSF
- TABID
- FNGROUPCOUNT
- Workbook Protection Block
- WINDOWPROTECT
- PROTECT
- PASSWORD
- PROT4REV
- PROT4REVPASS
- BACKUP
- HIDEOBJ
- WINDOW1
- DATEMODE
- PRECISION
- REFRESHALL
- BOOKBOOL
- FONT +
- FORMAT *
- XF +
- STYLE +
- ? PALETTE
- USESELFS
-
- BOUNDSHEET +
-
- COUNTRY
- ? Link Table
- SST
- ExtSST
- EOF
-'''
-
-from . import BIFFRecords
-from . import Style
-
-class Workbook(object):
-
- #################################################################
- ## Constructor
- #################################################################
- def __init__(self, encoding='ascii', style_compression=0):
- self.encoding = encoding
- self.__owner = 'None'
- self.__country_code = None # 0x07 is Russia :-)
- self.__wnd_protect = 0
- self.__obj_protect = 0
- self.__protect = 0
- self.__backup_on_save = 0
- # for WINDOW1 record
- self.__hpos_twips = 0x01E0
- self.__vpos_twips = 0x005A
- self.__width_twips = 0x3FCF
- self.__height_twips = 0x2A4E
-
- self.__active_sheet = 0
- self.__first_tab_index = 0
- self.__selected_tabs = 0x01
- self.__tab_width_twips = 0x0258
-
- self.__wnd_hidden = 0
- self.__wnd_mini = 0
- self.__hscroll_visible = 1
- self.__vscroll_visible = 1
- self.__tabs_visible = 1
-
- self.__styles = Style.StyleCollection(style_compression)
-
- self.__dates_1904 = 0
- self.__use_cell_values = 1
-
- self.__sst = BIFFRecords.SharedStringTable(self.encoding)
-
- self.__worksheets = []
- self.__worksheet_idx_from_name = {}
- self.__sheet_refs = {}
- self._supbook_xref = {}
- self._xcall_xref = {}
- self._ownbook_supbookx = None
- self._ownbook_supbook_ref = None
- self._xcall_supbookx = None
- self._xcall_supbook_ref = None
-
-
-
- #################################################################
- ## Properties, "getters", "setters"
- #################################################################
-
- def get_style_stats(self):
- return self.__styles.stats[:]
-
- def set_owner(self, value):
- self.__owner = value
-
- def get_owner(self):
- return self.__owner
-
- owner = property(get_owner, set_owner)
-
- #################################################################
-
- def set_country_code(self, value):
- self.__country_code = value
-
- def get_country_code(self):
- return self.__country_code
-
- country_code = property(get_country_code, set_country_code)
-
- #################################################################
-
- def set_wnd_protect(self, value):
- self.__wnd_protect = int(value)
-
- def get_wnd_protect(self):
- return bool(self.__wnd_protect)
-
- wnd_protect = property(get_wnd_protect, set_wnd_protect)
-
- #################################################################
-
- def set_obj_protect(self, value):
- self.__obj_protect = int(value)
-
- def get_obj_protect(self):
- return bool(self.__obj_protect)
-
- obj_protect = property(get_obj_protect, set_obj_protect)
-
- #################################################################
-
- def set_protect(self, value):
- self.__protect = int(value)
-
- def get_protect(self):
- return bool(self.__protect)
-
- protect = property(get_protect, set_protect)
-
- #################################################################
-
- def set_backup_on_save(self, value):
- self.__backup_on_save = int(value)
-
- def get_backup_on_save(self):
- return bool(self.__backup_on_save)
-
- backup_on_save = property(get_backup_on_save, set_backup_on_save)
-
- #################################################################
-
- def set_hpos(self, value):
- self.__hpos_twips = value & 0xFFFF
-
- def get_hpos(self):
- return self.__hpos_twips
-
- hpos = property(get_hpos, set_hpos)
-
- #################################################################
-
- def set_vpos(self, value):
- self.__vpos_twips = value & 0xFFFF
-
- def get_vpos(self):
- return self.__vpos_twips
-
- vpos = property(get_vpos, set_vpos)
-
- #################################################################
-
- def set_width(self, value):
- self.__width_twips = value & 0xFFFF
-
- def get_width(self):
- return self.__width_twips
-
- width = property(get_width, set_width)
-
- #################################################################
-
- def set_height(self, value):
- self.__height_twips = value & 0xFFFF
-
- def get_height(self):
- return self.__height_twips
-
- height = property(get_height, set_height)
-
- #################################################################
-
- def set_active_sheet(self, value):
- self.__active_sheet = value & 0xFFFF
- self.__first_tab_index = self.__active_sheet
-
- def get_active_sheet(self):
- return self.__active_sheet
-
- active_sheet = property(get_active_sheet, set_active_sheet)
-
- #################################################################
-
- def set_tab_width(self, value):
- self.__tab_width_twips = value & 0xFFFF
-
- def get_tab_width(self):
- return self.__tab_width_twips
-
- tab_width = property(get_tab_width, set_tab_width)
-
- #################################################################
-
- def set_wnd_visible(self, value):
- self.__wnd_hidden = int(not value)
-
- def get_wnd_visible(self):
- return not bool(self.__wnd_hidden)
-
- wnd_visible = property(get_wnd_visible, set_wnd_visible)
-
- #################################################################
-
- def set_wnd_mini(self, value):
- self.__wnd_mini = int(value)
-
- def get_wnd_mini(self):
- return bool(self.__wnd_mini)
-
- wnd_mini = property(get_wnd_mini, set_wnd_mini)
-
- #################################################################
-
- def set_hscroll_visible(self, value):
- self.__hscroll_visible = int(value)
-
- def get_hscroll_visible(self):
- return bool(self.__hscroll_visible)
-
- hscroll_visible = property(get_hscroll_visible, set_hscroll_visible)
-
- #################################################################
-
- def set_vscroll_visible(self, value):
- self.__vscroll_visible = int(value)
-
- def get_vscroll_visible(self):
- return bool(self.__vscroll_visible)
-
- vscroll_visible = property(get_vscroll_visible, set_vscroll_visible)
-
- #################################################################
-
- def set_tabs_visible(self, value):
- self.__tabs_visible = int(value)
-
- def get_tabs_visible(self):
- return bool(self.__tabs_visible)
-
- tabs_visible = property(get_tabs_visible, set_tabs_visible)
-
- #################################################################
-
- def set_dates_1904(self, value):
- self.__dates_1904 = int(value)
-
- def get_dates_1904(self):
- return bool(self.__dates_1904)
-
- dates_1904 = property(get_dates_1904, set_dates_1904)
-
- #################################################################
-
- def set_use_cell_values(self, value):
- self.__use_cell_values = int(value)
-
- def get_use_cell_values(self):
- return bool(self.__use_cell_values)
-
- use_cell_values = property(get_use_cell_values, set_use_cell_values)
-
- #################################################################
-
- def get_default_style(self):
- return self.__styles.default_style
-
- default_style = property(get_default_style)
-
- ##################################################################
- ## Methods
- ##################################################################
-
- def add_style(self, style):
- return self.__styles.add(style)
-
- def add_str(self, s):
- return self.__sst.add_str(s)
-
- def del_str(self, sst_idx):
- self.__sst.del_str(sst_idx)
-
- def str_index(self, s):
- return self.__sst.str_index(s)
-
- def add_sheet(self, sheetname, cell_overwrite_ok=False):
- from . import Worksheet, Utils
- if not isinstance(sheetname, str):
- sheetname = sheetname.decode(self.encoding)
- if not Utils.valid_sheet_name(sheetname):
- raise Exception("invalid worksheet name %r" % sheetname)
- lower_name = sheetname.lower()
- if lower_name in self.__worksheet_idx_from_name:
- raise Exception("duplicate worksheet name %r" % sheetname)
- self.__worksheet_idx_from_name[lower_name] = len(self.__worksheets)
- self.__worksheets.append(Worksheet(sheetname, self, cell_overwrite_ok))
- return self.__worksheets[-1]
-
- def get_sheet(self, sheetnum):
- return self.__worksheets[sheetnum]
-
- def raise_bad_sheetname(self, sheetname):
- raise Exception("Formula: unknown sheet name %s" % sheetname)
-
- def convert_sheetindex(self, strg_ref, n_sheets):
- idx = int(strg_ref)
- if 0 <= idx < n_sheets:
- return idx
- msg = "Formula: sheet index (%s) >= number of sheets (%d)" % (strg_ref, n_sheets)
- raise Exception(msg)
-
- def _get_supbook_index(self, tag):
- if tag in self._supbook_xref:
- return self._supbook_xref[tag]
- self._supbook_xref[tag] = idx = len(self._supbook_xref)
- return idx
-
- def setup_ownbook(self):
- self._ownbook_supbookx = self._get_supbook_index(('ownbook', 0))
- self._ownbook_supbook_ref = None
- reference = (self._ownbook_supbookx, 0xFFFE, 0xFFFE)
- if reference in self.__sheet_refs:
- raise Exception("can't happen")
- self.__sheet_refs[reference] = self._ownbook_supbook_ref = len(self.__sheet_refs)
-
- def setup_xcall(self):
- self._xcall_supbookx = self._get_supbook_index(('xcall', 0))
- self._xcall_supbook_ref = None
- reference = (self._xcall_supbookx, 0xFFFE, 0xFFFE)
- if reference in self.__sheet_refs:
- raise Exception("can't happen")
- self.__sheet_refs[reference] = self._xcall_supbook_ref = len(self.__sheet_refs)
-
- def add_sheet_reference(self, formula):
- patches = []
- n_sheets = len(self.__worksheets)
- sheet_refs, xcall_refs = formula.get_references()
-
- for ref0, ref1, offset in sheet_refs:
- if not ref0.isdigit():
- try:
- ref0n = self.__worksheet_idx_from_name[ref0.lower()]
- except KeyError:
- self.raise_bad_sheetname(ref0)
- else:
- ref0n = self.convert_sheetindex(ref0, n_sheets)
- if ref1 == ref0:
- ref1n = ref0n
- elif not ref1.isdigit():
- try:
- ref1n = self.__worksheet_idx_from_name[ref1.lower()]
- except KeyError:
- self.raise_bad_sheetname(ref1)
- else:
- ref1n = self.convert_sheetindex(ref1, n_sheets)
- if ref1n < ref0n:
- msg = "Formula: sheets out of order; %r:%r -> (%d, %d)" \
- % (ref0, ref1, ref0n, ref1n)
- raise Exception(msg)
- if self._ownbook_supbookx is None:
- self.setup_ownbook()
- reference = (self._ownbook_supbookx, ref0n, ref1n)
- if reference in self.__sheet_refs:
- patches.append((offset, self.__sheet_refs[reference]))
- else:
- nrefs = len(self.__sheet_refs)
- if nrefs > 65535:
- raise Exception('More than 65536 inter-sheet references')
- self.__sheet_refs[reference] = nrefs
- patches.append((offset, nrefs))
-
- for funcname, offset in xcall_refs:
- if self._ownbook_supbookx is None:
- self.setup_ownbook()
- if self._xcall_supbookx is None:
- self.setup_xcall()
- # print funcname, self._supbook_xref
- patches.append((offset, self._xcall_supbook_ref))
- if not isinstance(funcname, str):
- funcname = funcname.decode(self.encoding)
- if funcname in self._xcall_xref:
- idx = self._xcall_xref[funcname]
- else:
- self._xcall_xref[funcname] = idx = len(self._xcall_xref)
- patches.append((offset + 2, idx + 1))
-
- formula.patch_references(patches)
-
- ##################################################################
- ## BIFF records generation
- ##################################################################
-
- def __bof_rec(self):
- return BIFFRecords.Biff8BOFRecord(BIFFRecords.Biff8BOFRecord.BOOK_GLOBAL).get()
-
- def __eof_rec(self):
- return BIFFRecords.EOFRecord().get()
-
- def __intf_hdr_rec(self):
- return BIFFRecords.InteraceHdrRecord().get()
-
- def __intf_end_rec(self):
- return BIFFRecords.InteraceEndRecord().get()
-
- def __intf_mms_rec(self):
- return BIFFRecords.MMSRecord().get()
-
- def __write_access_rec(self):
- return BIFFRecords.WriteAccessRecord(self.__owner).get()
-
- def __wnd_protect_rec(self):
- return BIFFRecords.WindowProtectRecord(self.__wnd_protect).get()
-
- def __obj_protect_rec(self):
- return BIFFRecords.ObjectProtectRecord(self.__obj_protect).get()
-
- def __protect_rec(self):
- return BIFFRecords.ProtectRecord(self.__protect).get()
-
- def __password_rec(self):
- return BIFFRecords.PasswordRecord().get()
-
- def __prot4rev_rec(self):
- return BIFFRecords.Prot4RevRecord().get()
-
- def __prot4rev_pass_rec(self):
- return BIFFRecords.Prot4RevPassRecord().get()
-
- def __backup_rec(self):
- return BIFFRecords.BackupRecord(self.__backup_on_save).get()
-
- def __hide_obj_rec(self):
- return BIFFRecords.HideObjRecord().get()
-
- def __window1_rec(self):
- flags = 0
- flags |= (self.__wnd_hidden) << 0
- flags |= (self.__wnd_mini) << 1
- flags |= (self.__hscroll_visible) << 3
- flags |= (self.__vscroll_visible) << 4
- flags |= (self.__tabs_visible) << 5
-
- return BIFFRecords.Window1Record(self.__hpos_twips, self.__vpos_twips,
- self.__width_twips, self.__height_twips,
- flags,
- self.__active_sheet, self.__first_tab_index,
- self.__selected_tabs, self.__tab_width_twips).get()
-
- def __codepage_rec(self):
- return BIFFRecords.CodepageBiff8Record().get()
-
- def __country_rec(self):
- if not self.__country_code:
- return b''
- return BIFFRecords.CountryRecord(self.__country_code, self.__country_code).get()
-
- def __dsf_rec(self):
- return BIFFRecords.DSFRecord().get()
-
- def __tabid_rec(self):
- return BIFFRecords.TabIDRecord(len(self.__worksheets)).get()
-
- def __fngroupcount_rec(self):
- return BIFFRecords.FnGroupCountRecord().get()
-
- def __datemode_rec(self):
- return BIFFRecords.DateModeRecord(self.__dates_1904).get()
-
- def __precision_rec(self):
- return BIFFRecords.PrecisionRecord(self.__use_cell_values).get()
-
- def __refresh_all_rec(self):
- return BIFFRecords.RefreshAllRecord().get()
-
- def __bookbool_rec(self):
- return BIFFRecords.BookBoolRecord().get()
-
- def __all_fonts_num_formats_xf_styles_rec(self):
- return self.__styles.get_biff_data()
-
- def __palette_rec(self):
- result = b''
- return result
-
- def __useselfs_rec(self):
- return BIFFRecords.UseSelfsRecord().get()
-
- def __boundsheets_rec(self, data_len_before, data_len_after, sheet_biff_lens):
- # .................................
- # BOUNDSEHEET0
- # BOUNDSEHEET1
- # BOUNDSEHEET2
- # ..................................
- # WORKSHEET0
- # WORKSHEET1
- # WORKSHEET2
- boundsheets_len = 0
- for sheet in self.__worksheets:
- boundsheets_len += len(BIFFRecords.BoundSheetRecord(
- 0x00, sheet.visibility, sheet.name, self.encoding
- ).get())
-
- start = data_len_before + boundsheets_len + data_len_after
-
- result = b''
- for sheet_biff_len, sheet in zip(sheet_biff_lens, self.__worksheets):
- result += BIFFRecords.BoundSheetRecord(
- start, sheet.visibility, sheet.name, self.encoding
- ).get()
- start += sheet_biff_len
- return result
-
- def __all_links_rec(self):
- pieces = []
- temp = [(idx, tag) for tag, idx in list(self._supbook_xref.items())]
- temp.sort()
- for idx, tag in temp:
- stype, snum = tag
- if stype == 'ownbook':
- rec = BIFFRecords.InternalReferenceSupBookRecord(len(self.__worksheets)).get()
- pieces.append(rec)
- elif stype == 'xcall':
- rec = BIFFRecords.XcallSupBookRecord().get()
- pieces.append(rec)
- temp = [(idx, name) for name, idx in list(self._xcall_xref.items())]
- temp.sort()
- for idx, name in temp:
- rec = BIFFRecords.ExternnameRecord(
- options=0, index=0, name=name, fmla='\x02\x00\x1c\x17').get()
- pieces.append(rec)
- else:
- raise Exception('unknown supbook stype %r' % stype)
- if len(self.__sheet_refs) > 0:
- # get references in index order
- temp = [(idx, ref) for ref, idx in list(self.__sheet_refs.items())]
- temp.sort()
- temp = [ref for idx, ref in temp]
- externsheet_record = BIFFRecords.ExternSheetRecord(temp).get()
- pieces.append(externsheet_record)
- return b''.join(pieces)
-
- def __sst_rec(self):
- return self.__sst.get_biff_record()
-
- def __ext_sst_rec(self, abs_stream_pos):
- return b''
- #return BIFFRecords.ExtSSTRecord(abs_stream_pos, self.sst_record.str_placement,
- #self.sst_record.portions_len).get()
-
- def get_biff_data(self):
- before = b''
- before += self.__bof_rec()
- before += self.__intf_hdr_rec()
- before += self.__intf_mms_rec()
- before += self.__intf_end_rec()
- before += self.__write_access_rec()
- before += self.__codepage_rec()
- before += self.__dsf_rec()
- before += self.__tabid_rec()
- before += self.__fngroupcount_rec()
- before += self.__wnd_protect_rec()
- before += self.__protect_rec()
- before += self.__obj_protect_rec()
- before += self.__password_rec()
- before += self.__prot4rev_rec()
- before += self.__prot4rev_pass_rec()
- before += self.__backup_rec()
- before += self.__hide_obj_rec()
- before += self.__window1_rec()
- before += self.__datemode_rec()
- before += self.__precision_rec()
- before += self.__refresh_all_rec()
- before += self.__bookbool_rec()
- before += self.__all_fonts_num_formats_xf_styles_rec()
- before += self.__palette_rec()
- before += self.__useselfs_rec()
-
- country = self.__country_rec()
- all_links = self.__all_links_rec()
-
- shared_str_table = self.__sst_rec()
- after = country + all_links + shared_str_table
-
- ext_sst = self.__ext_sst_rec(0) # need fake cause we need calc stream pos
- eof = self.__eof_rec()
-
- self.__worksheets[self.__active_sheet].selected = True
- sheets = b''
- sheet_biff_lens = []
- for sheet in self.__worksheets:
- data = sheet.get_biff_data()
- sheets += data
- sheet_biff_lens.append(len(data))
-
- bundlesheets = self.__boundsheets_rec(len(before), len(after)+len(ext_sst)+len(eof), sheet_biff_lens)
-
- sst_stream_pos = len(before) + len(bundlesheets) + len(country) + len(all_links)
- ext_sst = self.__ext_sst_rec(sst_stream_pos)
-
- return before + bundlesheets + after + ext_sst + eof + sheets
-
- def save(self, filename):
- from . import CompoundDoc
-
- doc = CompoundDoc.XlsDoc()
- doc.save(filename, self.get_biff_data())
-
-
diff --git a/tablib/packages/xlwt3/Worksheet.py b/tablib/packages/xlwt3/Worksheet.py
deleted file mode 100644
index f358dd6..0000000
--- a/tablib/packages/xlwt3/Worksheet.py
+++ /dev/null
@@ -1,1296 +0,0 @@
-'''
- BOF
- UNCALCED
- INDEX
- Calculation Settings Block
- PRINTHEADERS
- PRINTGRIDLINES
- GRIDSET
- GUTS
- DEFAULTROWHEIGHT
- WSBOOL
- Page Settings Block
- Worksheet Protection Block
- DEFCOLWIDTH
- COLINFO
- SORT
- DIMENSIONS
- Row Blocks
- WINDOW2
- SCL
- PANE
- SELECTION
- STANDARDWIDTH
- MERGEDCELLS
- LABELRANGES
- PHONETIC
- Conditional Formatting Table
- Hyperlink Table
- Data Validity Table
- SHEETLAYOUT (BIFF8X only)
- SHEETPROTECTION (BIFF8X only)
- RANGEPROTECTION (BIFF8X only)
- EOF
-'''
-
-from . import BIFFRecords
-from . import Bitmap
-from . import Formatting
-from . import Style
-import tempfile
-
-
-class Worksheet(object):
- from .Workbook import Workbook
-
- #################################################################
- ## Constructor
- #################################################################
- def __init__(self, sheetname, parent_book, cell_overwrite_ok=False):
- from . import Row
- self.Row = Row #(to_py3): Row.Row -> Row
-
- from . import Column
- self.Column = Column #(to_py3): Column.Column -> Column
-
- self.__name = sheetname
- self.__parent = parent_book
- self._cell_overwrite_ok = cell_overwrite_ok
-
- self.__rows = {}
- self.__cols = {}
- self.__merged_ranges = []
- self.__bmp_rec = b''
-
- self.__show_formulas = 0
- self.__show_grid = 1
- self.__show_headers = 1
- self.__panes_frozen = 0
- ### self.__show_empty_as_zero = 1 ### deprecated with extreme prejudice 2009-05-19
- self.show_zero_values = 1
- self.__auto_colour_grid = 1
- self.__cols_right_to_left = 0
- self.__show_outline = 1
- self.__remove_splits = 0
- self.__selected = 0
- # RED HERRING ALERT: "sheet_visible" is a clone of the "selected" attribute.
- # Typically a workbook created by the Excel UI will have one sheet
- # (the sheet that was selected when the user saved it)
- # with both bits set to 1, and all other sheets will have both
- # bits set to 0. The true visibility of the sheet is found in the "visibility"
- # attribute obtained from the BOUNDSHEET record.
- self.__sheet_visible = 0
- self.__page_preview = 0
-
- self.__first_visible_row = 0
- self.__first_visible_col = 0
- self.__grid_colour = 0x40
- self.__preview_magn = 60 # percent
- self.__normal_magn = 100 # percent
-
- self.visibility = 0 # from/to BOUNDSHEET record.
-
- self.__vert_split_pos = None
- self.__horz_split_pos = None
- self.__vert_split_first_visible = None
- self.__horz_split_first_visible = None
- self.__split_active_pane = None
-
- self.__row_gut_width = 0
- self.__col_gut_height = 0
-
- self.__show_auto_page_breaks = 1
- self.__dialogue_sheet = 0
- self.__auto_style_outline = 0
- self.__outline_below = 0
- self.__outline_right = 0
- self.__fit_num_pages = 0
- self.__show_row_outline = 1
- self.__show_col_outline = 1
- self.__alt_expr_eval = 0
- self.__alt_formula_entries = 0
-
- self.__row_default_height = 0x00FF
- self.row_default_height_mismatch = 0
- self.row_default_hidden = 0
- self.row_default_space_above = 0
- self.row_default_space_below = 0
-
- self.__col_default_width = 0x0008
-
- self.__calc_mode = 1
- self.__calc_count = 0x0064
- self.__RC_ref_mode = 1
- self.__iterations_on = 0
- self.__delta = 0.001
- self.__save_recalc = 0
-
- self.__print_headers = 0
- self.__print_grid = 0
- self.__grid_set = 1
- self.__vert_page_breaks = []
- self.__horz_page_breaks = []
- self.__header_str = '&P'
- self.__footer_str = '&F'
- self.__print_centered_vert = 0
- self.__print_centered_horz = 1
- self.__left_margin = 0.3 #0.5
- self.__right_margin = 0.3 #0.5
- self.__top_margin = 0.61 #1.0
- self.__bottom_margin = 0.37 #1.0
- self.__paper_size_code = 9 # A4
- self.__print_scaling = 100
- self.__start_page_number = 1
- self.__fit_width_to_pages = 1
- self.__fit_height_to_pages = 1
- self.__print_in_rows = 1
- self.__portrait = 1
- self.__print_not_colour = 0
- self.__print_draft = 0
- self.__print_notes = 0
- self.__print_notes_at_end = 0
- self.__print_omit_errors = 0
- self.__print_hres = 0x012C # 300 dpi
- self.__print_vres = 0x012C # 300 dpi
- self.__header_margin = 0.1
- self.__footer_margin = 0.1
- self.__copies_num = 1
-
- self.__wnd_protect = 0
- self.__obj_protect = 0
- self.__protect = 0
- self.__scen_protect = 0
- self.__password = b''
-
- self.last_used_row = 0
- self.first_used_row = 65535
- self.last_used_col = 0
- self.first_used_col = 255
- self.row_tempfile = None
- self.__flushed_rows = {}
- self.__row_visible_levels = 0
-
- #################################################################
- ## Properties, "getters", "setters"
- #################################################################
-
- def set_name(self, value):
- self.__name = value
-
- def get_name(self):
- return self.__name
-
- name = property(get_name, set_name)
-
- #################################################################
-
- def get_parent(self):
- return self.__parent
-
- parent = property(get_parent)
-
- #################################################################
-
- def get_rows(self):
- return self.__rows
-
- rows = property(get_rows)
-
- #################################################################
-
- def get_cols(self):
- return self.__cols
-
- cols = property(get_cols)
-
- #################################################################
-
- def get_merged_ranges(self):
- return self.__merged_ranges
-
- merged_ranges = property(get_merged_ranges)
-
- #################################################################
-
- def get_bmp_rec(self):
- return self.__bmp_rec
-
- bmp_rec = property(get_bmp_rec)
-
- #################################################################
-
- def set_show_formulas(self, value):
- self.__show_formulas = int(value)
-
- def get_show_formulas(self):
- return bool(self.__show_formulas)
-
- show_formulas = property(get_show_formulas, set_show_formulas)
-
- #################################################################
-
- def set_show_grid(self, value):
- self.__show_grid = int(value)
-
- def get_show_grid(self):
- return bool(self.__show_grid)
-
- show_grid = property(get_show_grid, set_show_grid)
-
- #################################################################
-
- def set_show_headers(self, value):
- self.__show_headers = int(value)
-
- def get_show_headers(self):
- return bool(self.__show_headers)
-
- show_headers = property(get_show_headers, set_show_headers)
-
- #################################################################
-
- def set_panes_frozen(self, value):
- self.__panes_frozen = int(value)
-
- def get_panes_frozen(self):
- return bool(self.__panes_frozen)
-
- panes_frozen = property(get_panes_frozen, set_panes_frozen)
-
- #################################################################
-
- ### def set_show_empty_as_zero(self, value):
- ### self.__show_empty_as_zero = int(value)
-
- ### def get_show_empty_as_zero(self):
- ### return bool(self.__show_empty_as_zero)
-
- ### show_empty_as_zero = property(get_show_empty_as_zero, set_show_empty_as_zero)
-
- #################################################################
-
- def set_auto_colour_grid(self, value):
- self.__auto_colour_grid = int(value)
-
- def get_auto_colour_grid(self):
- return bool(self.__auto_colour_grid)
-
- auto_colour_grid = property(get_auto_colour_grid, set_auto_colour_grid)
-
- #################################################################
-
- def set_cols_right_to_left(self, value):
- self.__cols_right_to_left = int(value)
-
- def get_cols_right_to_left(self):
- return bool(self.__cols_right_to_left)
-
- cols_right_to_left = property(get_cols_right_to_left, set_cols_right_to_left)
-
- #################################################################
-
- def set_show_outline(self, value):
- self.__show_outline = int(value)
-
- def get_show_outline(self):
- return bool(self.__show_outline)
-
- show_outline = property(get_show_outline, set_show_outline)
-
- #################################################################
-
- def set_remove_splits(self, value):
- self.__remove_splits = int(value)
-
- def get_remove_splits(self):
- return bool(self.__remove_splits)
-
- remove_splits = property(get_remove_splits, set_remove_splits)
-
- #################################################################
-
- def set_selected(self, value):
- self.__selected = int(value)
-
- def get_selected(self):
- return bool(self.__selected)
-
- selected = property(get_selected, set_selected)
-
- #################################################################
-
- def set_sheet_visible(self, value):
- self.__sheet_visible = int(value)
-
- def get_sheet_visible(self):
- return bool(self.__sheet_visible)
-
- sheet_visible = property(get_sheet_visible, set_sheet_visible)
-
- #################################################################
-
- def set_page_preview(self, value):
- self.__page_preview = int(value)
-
- def get_page_preview(self):
- return bool(self.__page_preview)
-
- page_preview = property(get_page_preview, set_page_preview)
-
- #################################################################
-
- def set_first_visible_row(self, value):
- self.__first_visible_row = value
-
- def get_first_visible_row(self):
- return self.__first_visible_row
-
- first_visible_row = property(get_first_visible_row, set_first_visible_row)
-
- #################################################################
-
- def set_first_visible_col(self, value):
- self.__first_visible_col = value
-
- def get_first_visible_col(self):
- return self.__first_visible_col
-
- first_visible_col = property(get_first_visible_col, set_first_visible_col)
-
- #################################################################
-
- def set_grid_colour(self, value):
- self.__grid_colour = value
-
- def get_grid_colour(self):
- return self.__grid_colour
-
- grid_colour = property(get_grid_colour, set_grid_colour)
-
- #################################################################
-
- def set_preview_magn(self, value):
- self.__preview_magn = value
-
- def get_preview_magn(self):
- return self.__preview_magn
-
- preview_magn = property(get_preview_magn, set_preview_magn)
-
- #################################################################
-
- def set_normal_magn(self, value):
- self.__normal_magn = value
-
- def get_normal_magn(self):
- return self.__normal_magn
-
- normal_magn = property(get_normal_magn, set_normal_magn)
-
- #################################################################
-
- def set_vert_split_pos(self, value):
- self.__vert_split_pos = abs(value)
-
- def get_vert_split_pos(self):
- return self.__vert_split_pos
-
- vert_split_pos = property(get_vert_split_pos, set_vert_split_pos)
-
- #################################################################
-
- def set_horz_split_pos(self, value):
- self.__horz_split_pos = abs(value)
-
- def get_horz_split_pos(self):
- return self.__horz_split_pos
-
- horz_split_pos = property(get_horz_split_pos, set_horz_split_pos)
-
- #################################################################
-
- def set_vert_split_first_visible(self, value):
- self.__vert_split_first_visible = abs(value)
-
- def get_vert_split_first_visible(self):
- return self.__vert_split_first_visible
-
- vert_split_first_visible = property(get_vert_split_first_visible, set_vert_split_first_visible)
-
- #################################################################
-
- def set_horz_split_first_visible(self, value):
- self.__horz_split_first_visible = abs(value)
-
- def get_horz_split_first_visible(self):
- return self.__horz_split_first_visible
-
- horz_split_first_visible = property(get_horz_split_first_visible, set_horz_split_first_visible)
-
- #################################################################
-
- #def set_split_active_pane(self, value):
- # self.__split_active_pane = abs(value) & 0x03
- #
- #def get_split_active_pane(self):
- # return self.__split_active_pane
- #
- #split_active_pane = property(get_split_active_pane, set_split_active_pane)
-
- #################################################################
-
- #def set_row_gut_width(self, value):
- # self.__row_gut_width = value
- #
- #def get_row_gut_width(self):
- # return self.__row_gut_width
- #
- #row_gut_width = property(get_row_gut_width, set_row_gut_width)
- #
- #################################################################
- #
- #def set_col_gut_height(self, value):
- # self.__col_gut_height = value
- #
- #def get_col_gut_height(self):
- # return self.__col_gut_height
- #
- #col_gut_height = property(get_col_gut_height, set_col_gut_height)
- #
- #################################################################
-
- def set_show_auto_page_breaks(self, value):
- self.__show_auto_page_breaks = int(value)
-
- def get_show_auto_page_breaks(self):
- return bool(self.__show_auto_page_breaks)
-
- show_auto_page_breaks = property(get_show_auto_page_breaks, set_show_auto_page_breaks)
-
- #################################################################
-
- def set_dialogue_sheet(self, value):
- self.__dialogue_sheet = int(value)
-
- def get_dialogue_sheet(self):
- return bool(self.__dialogue_sheet)
-
- dialogue_sheet = property(get_dialogue_sheet, set_dialogue_sheet)
-
- #################################################################
-
- def set_auto_style_outline(self, value):
- self.__auto_style_outline = int(value)
-
- def get_auto_style_outline(self):
- return bool(self.__auto_style_outline)
-
- auto_style_outline = property(get_auto_style_outline, set_auto_style_outline)
-
- #################################################################
-
- def set_outline_below(self, value):
- self.__outline_below = int(value)
-
- def get_outline_below(self):
- return bool(self.__outline_below)
-
- outline_below = property(get_outline_below, set_outline_below)
-
- #################################################################
-
- def set_outline_right(self, value):
- self.__outline_right = int(value)
-
- def get_outline_right(self):
- return bool(self.__outline_right)
-
- outline_right = property(get_outline_right, set_outline_right)
-
- #################################################################
-
- def set_fit_num_pages(self, value):
- self.__fit_num_pages = value
-
- def get_fit_num_pages(self):
- return self.__fit_num_pages
-
- fit_num_pages = property(get_fit_num_pages, set_fit_num_pages)
-
- #################################################################
-
- def set_show_row_outline(self, value):
- self.__show_row_outline = int(value)
-
- def get_show_row_outline(self):
- return bool(self.__show_row_outline)
-
- show_row_outline = property(get_show_row_outline, set_show_row_outline)
-
- #################################################################
-
- def set_show_col_outline(self, value):
- self.__show_col_outline = int(value)
-
- def get_show_col_outline(self):
- return bool(self.__show_col_outline)
-
- show_col_outline = property(get_show_col_outline, set_show_col_outline)
-
- #################################################################
-
- def set_alt_expr_eval(self, value):
- self.__alt_expr_eval = int(value)
-
- def get_alt_expr_eval(self):
- return bool(self.__alt_expr_eval)
-
- alt_expr_eval = property(get_alt_expr_eval, set_alt_expr_eval)
-
- #################################################################
-
- def set_alt_formula_entries(self, value):
- self.__alt_formula_entries = int(value)
-
- def get_alt_formula_entries(self):
- return bool(self.__alt_formula_entries)
-
- alt_formula_entries = property(get_alt_formula_entries, set_alt_formula_entries)
-
- #################################################################
-
- def set_row_default_height(self, value):
- self.__row_default_height = value
-
- def get_row_default_height(self):
- return self.__row_default_height
-
- row_default_height = property(get_row_default_height, set_row_default_height)
-
- #################################################################
-
- def set_col_default_width(self, value):
- self.__col_default_width = value
-
- def get_col_default_width(self):
- return self.__col_default_width
-
- col_default_width = property(get_col_default_width, set_col_default_width)
-
- #################################################################
-
- def set_calc_mode(self, value):
- self.__calc_mode = value & 0x03
-
- def get_calc_mode(self):
- return self.__calc_mode
-
- calc_mode = property(get_calc_mode, set_calc_mode)
-
- #################################################################
-
- def set_calc_count(self, value):
- self.__calc_count = value
-
- def get_calc_count(self):
- return self.__calc_count
-
- calc_count = property(get_calc_count, set_calc_count)
-
- #################################################################
-
- def set_RC_ref_mode(self, value):
- self.__RC_ref_mode = int(value)
-
- def get_RC_ref_mode(self):
- return bool(self.__RC_ref_mode)
-
- RC_ref_mode = property(get_RC_ref_mode, set_RC_ref_mode)
-
- #################################################################
-
- def set_iterations_on(self, value):
- self.__iterations_on = int(value)
-
- def get_iterations_on(self):
- return bool(self.__iterations_on)
-
- iterations_on = property(get_iterations_on, set_iterations_on)
-
- #################################################################
-
- def set_delta(self, value):
- self.__delta = value
-
- def get_delta(self):
- return self.__delta
-
- delta = property(get_delta, set_delta)
-
- #################################################################
-
- def set_save_recalc(self, value):
- self.__save_recalc = int(value)
-
- def get_save_recalc(self):
- return bool(self.__save_recalc)
-
- save_recalc = property(get_save_recalc, set_save_recalc)
-
- #################################################################
-
- def set_print_headers(self, value):
- self.__print_headers = int(value)
-
- def get_print_headers(self):
- return bool(self.__print_headers)
-
- print_headers = property(get_print_headers, set_print_headers)
-
- #################################################################
-
- def set_print_grid(self, value):
- self.__print_grid = int(value)
-
- def get_print_grid(self):
- return bool(self.__print_grid)
-
- print_grid = property(get_print_grid, set_print_grid)
-
- #################################################################
- #
- #def set_grid_set(self, value):
- # self.__grid_set = int(value)
- #
- #def get_grid_set(self):
- # return bool(self.__grid_set)
- #
- #grid_set = property(get_grid_set, set_grid_set)
- #
- #################################################################
-
- def set_vert_page_breaks(self, value):
- self.__vert_page_breaks = value
-
- def get_vert_page_breaks(self):
- return self.__vert_page_breaks
-
- vert_page_breaks = property(get_vert_page_breaks, set_vert_page_breaks)
-
- #################################################################
-
- def set_horz_page_breaks(self, value):
- self.__horz_page_breaks = value
-
- def get_horz_page_breaks(self):
- return self.__horz_page_breaks
-
- horz_page_breaks = property(get_horz_page_breaks, set_horz_page_breaks)
-
- #################################################################
-
- def set_header_str(self, value):
- if isinstance(value, str):
- value = str(value, self.__parent.encoding)
- self.__header_str = value
-
- def get_header_str(self):
- return self.__header_str
-
- header_str = property(get_header_str, set_header_str)
-
- #################################################################
-
- def set_footer_str(self, value):
- if isinstance(value, str):
- value = str(value, self.__parent.encoding)
- self.__footer_str = value
-
- def get_footer_str(self):
- return self.__footer_str
-
- footer_str = property(get_footer_str, set_footer_str)
-
- #################################################################
-
- def set_print_centered_vert(self, value):
- self.__print_centered_vert = int(value)
-
- def get_print_centered_vert(self):
- return bool(self.__print_centered_vert)
-
- print_centered_vert = property(get_print_centered_vert, set_print_centered_vert)
-
- #################################################################
-
- def set_print_centered_horz(self, value):
- self.__print_centered_horz = int(value)
-
- def get_print_centered_horz(self):
- return bool(self.__print_centered_horz)
-
- print_centered_horz = property(get_print_centered_horz, set_print_centered_horz)
-
- #################################################################
-
- def set_left_margin(self, value):
- self.__left_margin = value
-
- def get_left_margin(self):
- return self.__left_margin
-
- left_margin = property(get_left_margin, set_left_margin)
-
- #################################################################
-
- def set_right_margin(self, value):
- self.__right_margin = value
-
- def get_right_margin(self):
- return self.__right_margin
-
- right_margin = property(get_right_margin, set_right_margin)
-
- #################################################################
-
- def set_top_margin(self, value):
- self.__top_margin = value
-
- def get_top_margin(self):
- return self.__top_margin
-
- top_margin = property(get_top_margin, set_top_margin)
-
- #################################################################
-
- def set_bottom_margin(self, value):
- self.__bottom_margin = value
-
- def get_bottom_margin(self):
- return self.__bottom_margin
-
- bottom_margin = property(get_bottom_margin, set_bottom_margin)
-
- #################################################################
-
- def set_paper_size_code(self, value):
- self.__paper_size_code = value
-
- def get_paper_size_code(self):
- return self.__paper_size_code
-
- paper_size_code = property(get_paper_size_code, set_paper_size_code)
-
- #################################################################
-
- def set_print_scaling(self, value):
- self.__print_scaling = value
-
- def get_print_scaling(self):
- return self.__print_scaling
-
- print_scaling = property(get_print_scaling, set_print_scaling)
-
- #################################################################
-
- def set_start_page_number(self, value):
- self.__start_page_number = value
-
- def get_start_page_number(self):
- return self.__start_page_number
-
- start_page_number = property(get_start_page_number, set_start_page_number)
-
- #################################################################
-
- def set_fit_width_to_pages(self, value):
- self.__fit_width_to_pages = value
-
- def get_fit_width_to_pages(self):
- return self.__fit_width_to_pages
-
- fit_width_to_pages = property(get_fit_width_to_pages, set_fit_width_to_pages)
-
- #################################################################
-
- def set_fit_height_to_pages(self, value):
- self.__fit_height_to_pages = value
-
- def get_fit_height_to_pages(self):
- return self.__fit_height_to_pages
-
- fit_height_to_pages = property(get_fit_height_to_pages, set_fit_height_to_pages)
-
- #################################################################
-
- def set_print_in_rows(self, value):
- self.__print_in_rows = int(value)
-
- def get_print_in_rows(self):
- return bool(self.__print_in_rows)
-
- print_in_rows = property(get_print_in_rows, set_print_in_rows)
-
- #################################################################
-
- def set_portrait(self, value):
- self.__portrait = int(value)
-
- def get_portrait(self):
- return bool(self.__portrait)
-
- portrait = property(get_portrait, set_portrait)
-
- #################################################################
-
- def set_print_colour(self, value):
- self.__print_not_colour = int(not value)
-
- def get_print_colour(self):
- return not bool(self.__print_not_colour)
-
- print_colour = property(get_print_colour, set_print_colour)
-
- #################################################################
-
- def set_print_draft(self, value):
- self.__print_draft = int(value)
-
- def get_print_draft(self):
- return bool(self.__print_draft)
-
- print_draft = property(get_print_draft, set_print_draft)
-
- #################################################################
-
- def set_print_notes(self, value):
- self.__print_notes = int(value)
-
- def get_print_notes(self):
- return bool(self.__print_notes)
-
- print_notes = property(get_print_notes, set_print_notes)
-
- #################################################################
-
- def set_print_notes_at_end(self, value):
- self.__print_notes_at_end = int(value)
-
- def get_print_notes_at_end(self):
- return bool(self.__print_notes_at_end)
-
- print_notes_at_end = property(get_print_notes_at_end, set_print_notes_at_end)
-
- #################################################################
-
- def set_print_omit_errors(self, value):
- self.__print_omit_errors = int(value)
-
- def get_print_omit_errors(self):
- return bool(self.__print_omit_errors)
-
- print_omit_errors = property(get_print_omit_errors, set_print_omit_errors)
-
- #################################################################
-
- def set_print_hres(self, value):
- self.__print_hres = value
-
- def get_print_hres(self):
- return self.__print_hres
-
- print_hres = property(get_print_hres, set_print_hres)
-
- #################################################################
-
- def set_print_vres(self, value):
- self.__print_vres = value
-
- def get_print_vres(self):
- return self.__print_vres
-
- print_vres = property(get_print_vres, set_print_vres)
-
- #################################################################
-
- def set_header_margin(self, value):
- self.__header_margin = value
-
- def get_header_margin(self):
- return self.__header_margin
-
- header_margin = property(get_header_margin, set_header_margin)
-
- #################################################################
-
- def set_footer_margin(self, value):
- self.__footer_margin = value
-
- def get_footer_margin(self):
- return self.__footer_margin
-
- footer_margin = property(get_footer_margin, set_footer_margin)
-
- #################################################################
-
- def set_copies_num(self, value):
- self.__copies_num = value
-
- def get_copies_num(self):
- return self.__copies_num
-
- copies_num = property(get_copies_num, set_copies_num)
-
- ##################################################################
-
- def set_wnd_protect(self, value):
- self.__wnd_protect = int(value)
-
- def get_wnd_protect(self):
- return bool(self.__wnd_protect)
-
- wnd_protect = property(get_wnd_protect, set_wnd_protect)
-
- #################################################################
-
- def set_obj_protect(self, value):
- self.__obj_protect = int(value)
-
- def get_obj_protect(self):
- return bool(self.__obj_protect)
-
- obj_protect = property(get_obj_protect, set_obj_protect)
-
- #################################################################
-
- def set_protect(self, value):
- self.__protect = int(value)
-
- def get_protect(self):
- return bool(self.__protect)
-
- protect = property(get_protect, set_protect)
-
- #################################################################
-
- def set_scen_protect(self, value):
- self.__scen_protect = int(value)
-
- def get_scen_protect(self):
- return bool(self.__scen_protect)
-
- scen_protect = property(get_scen_protect, set_scen_protect)
-
- #################################################################
-
- def set_password(self, value):
- self.__password = value
-
- def get_password(self):
- return self.__password
-
- password = property(get_password, set_password)
-
- ##################################################################
- ## Methods
- ##################################################################
-
- def get_parent(self):
- return self.__parent
-
- def write(self, r, c, label=b"", style=Style.default_style):
- self.row(r).write(c, label, style)
-
- def merge(self, r1, r2, c1, c2, style=Style.default_style):
- # Stand-alone merge of previously written cells.
- # Problems: (1) style to be used should be existing style of
- # the top-left cell, not an arg.
- # (2) should ensure that any previous data value in
- # non-top-left cells is nobbled.
- # Note: if a cell is set by a data record then later
- # is referenced by a [MUL]BLANK record, Excel will blank
- # out the cell on the screen, but OOo & Gnu will not
- # blank it out. Need to do something better than writing
- # multiple records. In the meantime, avoid this method and use
- # write_merge() instead.
- if c2 > c1:
- self.row(r1).write_blanks(c1 + 1, c2, style)
- for r in range(r1+1, r2+1):
- self.row(r).write_blanks(c1, c2, style)
- self.__merged_ranges.append((r1, r2, c1, c2))
-
- def write_merge(self, r1, r2, c1, c2, label=b"", style=Style.default_style):
- assert 0 <= c1 <= c2 <= 255
- assert 0 <= r1 <= r2 <= 65535
- self.write(r1, c1, label, style)
- if c2 > c1:
- self.row(r1).write_blanks(c1 + 1, c2, style) # skip (r1, c1)
- for r in range(r1+1, r2+1):
- self.row(r).write_blanks(c1, c2, style)
- self.__merged_ranges.append((r1, r2, c1, c2))
-
- def insert_bitmap(self, filename, row, col, x = 0, y = 0, scale_x = 1, scale_y = 1):
- bmp = Bitmap.ImDataBmpRecord(filename)
- obj = Bitmap.ObjBmpRecord(row, col, self, bmp, x, y, scale_x, scale_y)
-
- self.__bmp_rec += obj.get() + bmp.get()
-
- def col(self, indx):
- if indx not in self.__cols:
- self.__cols[indx] = self.Column(indx, self)
- return self.__cols[indx]
-
- def row(self, indx):
- if indx not in self.__rows:
- if indx in self.__flushed_rows:
- raise Exception("Attempt to reuse row index %d of sheet %r after flushing" % (indx, self.__name))
- self.__rows[indx] = self.Row(indx, self)
- if indx > self.last_used_row:
- self.last_used_row = indx
- if indx < self.first_used_row:
- self.first_used_row = indx
- return self.__rows[indx]
-
- def row_height(self, row): # in pixels
- if row in self.__rows:
- return self.__rows[row].get_height_in_pixels()
- else:
- return 17
-
- def col_width(self, col): # in pixels
- if col in self.__cols:
- return self.__cols[col].width_in_pixels()
- else:
- return 64
-
-
- ##################################################################
- ## BIFF records generation
- ##################################################################
-
- def __bof_rec(self):
- return BIFFRecords.Biff8BOFRecord(BIFFRecords.Biff8BOFRecord.WORKSHEET).get()
-
- def __update_row_visible_levels(self):
- if self.__rows:
- temp = max([self.__rows[r].level for r in self.__rows]) + 1
- self.__row_visible_levels = max(temp, self.__row_visible_levels)
-
- def __guts_rec(self):
- self.__update_row_visible_levels()
- col_visible_levels = 0
- if len(self.__cols) != 0:
- col_visible_levels = max([self.__cols[c].level for c in self.__cols]) + 1
- return BIFFRecords.GutsRecord(
- self.__row_gut_width, self.__col_gut_height, self.__row_visible_levels, col_visible_levels).get()
-
- def __defaultrowheight_rec(self):
- options = 0x0000
- options |= (self.row_default_height_mismatch & 1) << 0
- options |= (self.row_default_hidden & 1) << 1
- options |= (self.row_default_space_above & 1) << 2
- options |= (self.row_default_space_below & 1) << 3
- defht = self.__row_default_height
- return BIFFRecords.DefaultRowHeightRecord(options, defht).get()
-
- def __wsbool_rec(self):
- options = 0x00
- options |= (self.__show_auto_page_breaks & 0x01) << 0
- options |= (self.__dialogue_sheet & 0x01) << 4
- options |= (self.__auto_style_outline & 0x01) << 5
- options |= (self.__outline_below & 0x01) << 6
- options |= (self.__outline_right & 0x01) << 7
- options |= (self.__fit_num_pages & 0x01) << 8
- options |= (self.__show_row_outline & 0x01) << 10
- options |= (self.__show_col_outline & 0x01) << 11
- options |= (self.__alt_expr_eval & 0x01) << 14
- options |= (self.__alt_formula_entries & 0x01) << 15
-
- return BIFFRecords.WSBoolRecord(options).get()
-
- def __eof_rec(self):
- return BIFFRecords.EOFRecord().get()
-
- def __colinfo_rec(self):
- result = b''
- for col in self.__cols:
- result += self.__cols[col].get_biff_record()
- return result
-
- def __dimensions_rec(self):
- return BIFFRecords.DimensionsRecord(
- self.first_used_row, self.last_used_row,
- self.first_used_col, self.last_used_col
- ).get()
-
- def __window2_rec(self):
- # Appends SCL record.
- options = 0
- options |= (self.__show_formulas & 0x01) << 0
- options |= (self.__show_grid & 0x01) << 1
- options |= (self.__show_headers & 0x01) << 2
- options |= (self.__panes_frozen & 0x01) << 3
- options |= (self.show_zero_values & 0x01) << 4
- options |= (self.__auto_colour_grid & 0x01) << 5
- options |= (self.__cols_right_to_left & 0x01) << 6
- options |= (self.__show_outline & 0x01) << 7
- options |= (self.__remove_splits & 0x01) << 8
- options |= (self.__selected & 0x01) << 9
- options |= (self.__sheet_visible & 0x01) << 10
- options |= (self.__page_preview & 0x01) << 11
- if self.__page_preview:
- scl_magn = self.__preview_magn
- else:
- scl_magn = self.__normal_magn
- return BIFFRecords.Window2Record(
- options, self.__first_visible_row, self.__first_visible_col,
- self.__grid_colour,
- self.__preview_magn, self.__normal_magn, scl_magn).get()
-
- def __panes_rec(self):
- if self.__vert_split_pos is None and self.__horz_split_pos is None:
- return b""
-
- if self.__vert_split_pos is None:
- self.__vert_split_pos = 0
- if self.__horz_split_pos is None:
- self.__horz_split_pos = 0
-
- if self.__panes_frozen:
- if self.__vert_split_first_visible is None:
- self.__vert_split_first_visible = self.__vert_split_pos
- if self.__horz_split_first_visible is None:
- self.__horz_split_first_visible = self.__horz_split_pos
- else:
- if self.__vert_split_first_visible is None:
- self.__vert_split_first_visible = 0
- if self.__horz_split_first_visible is None:
- self.__horz_split_first_visible = 0
- # inspired by pyXLWriter
- self.__horz_split_pos = 20*self.__horz_split_pos + 255
- self.__vert_split_pos = int(113.879*self.__vert_split_pos + 390)
-
- if self.__vert_split_pos > 0 and self.__horz_split_pos > 0:
- self.__split_active_pane = 0
- elif self.__vert_split_pos > 0 and self.__horz_split_pos == 0:
- self.__split_active_pane = 1
- elif self.__vert_split_pos == 0 and self.__horz_split_pos > 0:
- self.__split_active_pane = 2
- else:
- self.__split_active_pane = 3
-
- result = BIFFRecords.PanesRecord(self.__vert_split_pos,
- self.__horz_split_pos,
- self.__horz_split_first_visible,
- self.__vert_split_first_visible,
- self.__split_active_pane).get()
- return result
-
- def __row_blocks_rec(self):
- result = []
- for row in self.__rows.values():
- result.append(row.get_row_biff_data())
- result.append(row.get_cells_biff_data())
- return b''.join(result)
-
- def __merged_rec(self):
- return BIFFRecords.MergedCellsRecord(self.__merged_ranges).get()
-
- def __bitmaps_rec(self):
- return self.__bmp_rec
-
- def __calc_settings_rec(self):
- result = b''
- result += BIFFRecords.CalcModeRecord(self.__calc_mode & 0x01).get()
- result += BIFFRecords.CalcCountRecord(self.__calc_count & 0xFFFF).get()
- result += BIFFRecords.RefModeRecord(self.__RC_ref_mode & 0x01).get()
- result += BIFFRecords.IterationRecord(self.__iterations_on & 0x01).get()
- result += BIFFRecords.DeltaRecord(self.__delta).get()
- result += BIFFRecords.SaveRecalcRecord(self.__save_recalc & 0x01).get()
- return result
-
- def __print_settings_rec(self):
- result = b''
- result += BIFFRecords.PrintHeadersRecord(self.__print_headers).get()
- result += BIFFRecords.PrintGridLinesRecord(self.__print_grid).get()
- result += BIFFRecords.GridSetRecord(self.__grid_set).get()
- result += BIFFRecords.HorizontalPageBreaksRecord(self.__horz_page_breaks).get()
- result += BIFFRecords.VerticalPageBreaksRecord(self.__vert_page_breaks).get()
- result += BIFFRecords.HeaderRecord(self.__header_str).get()
- result += BIFFRecords.FooterRecord(self.__footer_str).get()
- result += BIFFRecords.HCenterRecord(self.__print_centered_horz).get()
- result += BIFFRecords.VCenterRecord(self.__print_centered_vert).get()
- result += BIFFRecords.LeftMarginRecord(self.__left_margin).get()
- result += BIFFRecords.RightMarginRecord(self.__right_margin).get()
- result += BIFFRecords.TopMarginRecord(self.__top_margin).get()
- result += BIFFRecords.BottomMarginRecord(self.__bottom_margin).get()
-
- setup_page_options = (self.__print_in_rows & 0x01) << 0
- setup_page_options |= (self.__portrait & 0x01) << 1
- setup_page_options |= (0x00 & 0x01) << 2
- setup_page_options |= (self.__print_not_colour & 0x01) << 3
- setup_page_options |= (self.__print_draft & 0x01) << 4
- setup_page_options |= (self.__print_notes & 0x01) << 5
- setup_page_options |= (0x00 & 0x01) << 6
- setup_page_options |= (0x01 & 0x01) << 7
- setup_page_options |= (self.__print_notes_at_end & 0x01) << 9
- setup_page_options |= (self.__print_omit_errors & 0x03) << 10
-
- result += BIFFRecords.SetupPageRecord(self.__paper_size_code,
- self.__print_scaling,
- self.__start_page_number,
- self.__fit_width_to_pages,
- self.__fit_height_to_pages,
- setup_page_options,
- self.__print_hres,
- self.__print_vres,
- self.__header_margin,
- self.__footer_margin,
- self.__copies_num).get()
- return result
-
- def __protection_rec(self):
- result = b''
- result += BIFFRecords.ProtectRecord(self.__protect).get()
- result += BIFFRecords.ScenProtectRecord(self.__scen_protect).get()
- result += BIFFRecords.WindowProtectRecord(self.__wnd_protect).get()
- result += BIFFRecords.ObjectProtectRecord(self.__obj_protect).get()
- result += BIFFRecords.PasswordRecord(self.__password).get()
- return result
-
- def get_biff_data(self):
- result = [
- self.__bof_rec(),
- self.__calc_settings_rec(),
- self.__guts_rec(),
- self.__defaultrowheight_rec(),
- self.__wsbool_rec(),
- self.__colinfo_rec(),
- self.__dimensions_rec(),
- self.__print_settings_rec(),
- self.__protection_rec(),
- ]
- if self.row_tempfile:
- self.row_tempfile.flush()
- self.row_tempfile.seek(0)
- result.append(self.row_tempfile.read())
- result.extend([
- self.__row_blocks_rec(),
- self.__merged_rec(),
- self.__bitmaps_rec(),
- self.__window2_rec(),
- self.__panes_rec(),
- self.__eof_rec(),
- ])
- return b''.join(result)
-
- def flush_row_data(self):
- if self.row_tempfile is None:
- self.row_tempfile = tempfile.TemporaryFile()
- self.row_tempfile.write(self.__row_blocks_rec())
- for rowx in self.__rows:
- self.__flushed_rows[rowx] = 1
- self.__update_row_visible_levels()
- self.__rows = {}
-
-
diff --git a/tablib/packages/xlwt3/__init__.py b/tablib/packages/xlwt3/__init__.py
deleted file mode 100644
index ee8373e..0000000
--- a/tablib/packages/xlwt3/__init__.py
+++ /dev/null
@@ -1,9 +0,0 @@
-import sys
-
-from .Workbook import Workbook
-from .Worksheet import Worksheet
-from .Row import Row
-from .Column import Column
-from .Formatting import Font, Alignment, Borders, Pattern, Protection
-from .Style import XFStyle, easyxf
-from .ExcelFormula import *
diff --git a/tablib/packages/xlwt3/antlr.py b/tablib/packages/xlwt3/antlr.py
deleted file mode 100644
index b7b5029..0000000
--- a/tablib/packages/xlwt3/antlr.py
+++ /dev/null
@@ -1,2868 +0,0 @@
-## This file is part of PyANTLR. See LICENSE.txt for license
-## details..........Copyright (C) Wolfgang Haefelinger, 2004.
-
-## This file was copied for use with xlwt from the 2.7.7 ANTLR distribution. Yes, it
-## says 2.7.5 below. The 2.7.5 distribution version didn't have a
-## version in it.
-
-## Here is the contents of the ANTLR 2.7.7 LICENSE.txt referred to above.
-
-# SOFTWARE RIGHTS
-#
-# ANTLR 1989-2006 Developed by Terence Parr
-# Partially supported by University of San Francisco & jGuru.com
-#
-# We reserve no legal rights to the ANTLR--it is fully in the
-# public domain. An individual or company may do whatever
-# they wish with source code distributed with ANTLR or the
-# code generated by ANTLR, including the incorporation of
-# ANTLR, or its output, into commerical software.
-#
-# We encourage users to develop software with ANTLR. However,
-# we do ask that credit is given to us for developing
-# ANTLR. By "credit", we mean that if you use ANTLR or
-# incorporate any source code into one of your programs
-# (commercial product, research project, or otherwise) that
-# you acknowledge this fact somewhere in the documentation,
-# research report, etc... If you like ANTLR and have
-# developed a nice tool with the output, please mention that
-# you developed it using ANTLR. In addition, we ask that the
-# headers remain intact in our source code. As long as these
-# guidelines are kept, we expect to continue enhancing this
-# system and expect to make other tools available as they are
-# completed.
-#
-# The primary ANTLR guy:
-#
-# Terence Parr
-# parrt@cs.usfca.edu
-# parrt@antlr.org
-
-## End of contents of the ANTLR 2.7.7 LICENSE.txt ########################
-
-## get sys module
-import sys
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### global symbols ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-### ANTLR Standard Tokens
-SKIP = -1
-INVALID_TYPE = 0
-EOF_TYPE = 1
-EOF = 1
-NULL_TREE_LOOKAHEAD = 3
-MIN_USER_TYPE = 4
-
-### ANTLR's EOF Symbol
-EOF_CHAR = ''
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### general functions ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-## Version should be automatically derived from configure.in. For now,
-## we need to bump it ourselfs. Don't remove the <version> tags.
-## <version>
-def version():
- r = {
- 'major' : '2',
- 'minor' : '7',
- 'micro' : '5',
- 'patch' : '' ,
- 'version': '2.7.5'
- }
- return r
-## </version>
-
-def error(fmt,*args):
- if fmt:
- print("error: ", fmt % tuple(args))
-
-def ifelse(cond,_then,_else):
- if cond :
- r = _then
- else:
- r = _else
- return r
-
-def is_string_type(x):
- # return (isinstance(x,str) or isinstance(x,unicode))
- # Simplify; xlwt doesn't support Python < 2.3
- return isinstance(str)
-
-def assert_string_type(x):
- assert is_string_type(x)
- pass
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### ANTLR Exceptions ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class ANTLRException(Exception):
-
- def __init__(self, *args):
- Exception.__init__(self, *args)
-
-
-class RecognitionException(ANTLRException):
-
- def __init__(self, *args):
- ANTLRException.__init__(self, *args)
- self.fileName = None
- self.line = -1
- self.column = -1
- if len(args) >= 2:
- self.fileName = args[1]
- if len(args) >= 3:
- self.line = args[2]
- if len(args) >= 4:
- self.column = args[3]
-
- def __str__(self):
- buf = ['']
- if self.fileName:
- buf.append(self.fileName + ":")
- if self.line != -1:
- if not self.fileName:
- buf.append("line ")
- buf.append(str(self.line))
- if self.column != -1:
- buf.append(":" + str(self.column))
- buf.append(":")
- buf.append(" ")
- return str('').join(buf)
-
- __repr__ = __str__
-
-
-class NoViableAltException(RecognitionException):
-
- def __init__(self, *args):
- RecognitionException.__init__(self, *args)
- self.token = None
- self.node = None
- if isinstance(args[0],AST):
- self.node = args[0]
- elif isinstance(args[0],Token):
- self.token = args[0]
- else:
- raise TypeError("NoViableAltException requires Token or AST argument")
-
- def __str__(self):
- if self.token:
- line = self.token.getLine()
- col = self.token.getColumn()
- text = self.token.getText()
- return "unexpected symbol at line %s (column %s): \"%s\"" % (line,col,text)
- if self.node == ASTNULL:
- return "unexpected end of subtree"
- assert self.node
- ### hackish, we assume that an AST contains method getText
- return "unexpected node: %s" % (self.node.getText())
-
- __repr__ = __str__
-
-
-class NoViableAltForCharException(RecognitionException):
-
- def __init__(self, *args):
- self.foundChar = None
- if len(args) == 2:
- self.foundChar = args[0]
- scanner = args[1]
- RecognitionException.__init__(self, "NoViableAlt",
- scanner.getFilename(),
- scanner.getLine(),
- scanner.getColumn())
- elif len(args) == 4:
- self.foundChar = args[0]
- fileName = args[1]
- line = args[2]
- column = args[3]
- RecognitionException.__init__(self, "NoViableAlt",
- fileName, line, column)
- else:
- RecognitionException.__init__(self, "NoViableAlt",
- '', -1, -1)
-
- def __str__(self):
- mesg = "unexpected char: "
- if self.foundChar >= ' ' and self.foundChar <= '~':
- mesg += "'" + self.foundChar + "'"
- elif self.foundChar:
- mesg += "0x" + hex(ord(self.foundChar)).upper()[2:]
- else:
- mesg += "<None>"
- return mesg
-
- __repr__ = __str__
-
-
-class SemanticException(RecognitionException):
-
- def __init__(self, *args):
- RecognitionException.__init__(self, *args)
-
-
-class MismatchedCharException(RecognitionException):
-
- NONE = 0
- CHAR = 1
- NOT_CHAR = 2
- RANGE = 3
- NOT_RANGE = 4
- SET = 5
- NOT_SET = 6
-
- def __init__(self, *args):
- self.args = args
- if len(args) == 5:
- # Expected range / not range
- if args[3]:
- self.mismatchType = MismatchedCharException.NOT_RANGE
- else:
- self.mismatchType = MismatchedCharException.RANGE
- self.foundChar = args[0]
- self.expecting = args[1]
- self.upper = args[2]
- self.scanner = args[4]
- RecognitionException.__init__(self, "Mismatched char range",
- self.scanner.getFilename(),
- self.scanner.getLine(),
- self.scanner.getColumn())
- elif len(args) == 4 and is_string_type(args[1]):
- # Expected char / not char
- if args[2]:
- self.mismatchType = MismatchedCharException.NOT_CHAR
- else:
- self.mismatchType = MismatchedCharException.CHAR
- self.foundChar = args[0]
- self.expecting = args[1]
- self.scanner = args[3]
- RecognitionException.__init__(self, "Mismatched char",
- self.scanner.getFilename(),
- self.scanner.getLine(),
- self.scanner.getColumn())
- elif len(args) == 4 and isinstance(args[1], BitSet):
- # Expected BitSet / not BitSet
- if args[2]:
- self.mismatchType = MismatchedCharException.NOT_SET
- else:
- self.mismatchType = MismatchedCharException.SET
- self.foundChar = args[0]
- self.set = args[1]
- self.scanner = args[3]
- RecognitionException.__init__(self, "Mismatched char set",
- self.scanner.getFilename(),
- self.scanner.getLine(),
- self.scanner.getColumn())
- else:
- self.mismatchType = MismatchedCharException.NONE
- RecognitionException.__init__(self, "Mismatched char")
-
- ## Append a char to the msg buffer. If special,
- # then show escaped version
- #
- def appendCharName(self, sb, c):
- if not c or c == 65535:
- # 65535 = (char) -1 = EOF
- sb.append("'<EOF>'")
- elif c == '\n':
- sb.append("'\\n'")
- elif c == '\r':
- sb.append("'\\r'");
- elif c == '\t':
- sb.append("'\\t'")
- else:
- sb.append('\'' + c + '\'')
-
- ##
- # Returns an error message with line number/column information
- #
- def __str__(self):
- sb = ['']
- sb.append(RecognitionException.__str__(self))
-
- if self.mismatchType == MismatchedCharException.CHAR:
- sb.append("expecting ")
- self.appendCharName(sb, self.expecting)
- sb.append(", found ")
- self.appendCharName(sb, self.foundChar)
- elif self.mismatchType == MismatchedCharException.NOT_CHAR:
- sb.append("expecting anything but '")
- self.appendCharName(sb, self.expecting)
- sb.append("'; got it anyway")
- elif self.mismatchType in [MismatchedCharException.RANGE, MismatchedCharException.NOT_RANGE]:
- sb.append("expecting char ")
- if self.mismatchType == MismatchedCharException.NOT_RANGE:
- sb.append("NOT ")
- sb.append("in range: ")
- appendCharName(sb, self.expecting)
- sb.append("..")
- appendCharName(sb, self.upper)
- sb.append(", found ")
- appendCharName(sb, self.foundChar)
- elif self.mismatchType in [MismatchedCharException.SET, MismatchedCharException.NOT_SET]:
- sb.append("expecting ")
- if self.mismatchType == MismatchedCharException.NOT_SET:
- sb.append("NOT ")
- sb.append("one of (")
- for i in range(len(self.set)):
- self.appendCharName(sb, self.set[i])
- sb.append("), found ")
- self.appendCharName(sb, self.foundChar)
-
- return str().join(sb).strip()
-
- __repr__ = __str__
-
-
-class MismatchedTokenException(RecognitionException):
-
- NONE = 0
- TOKEN = 1
- NOT_TOKEN = 2
- RANGE = 3
- NOT_RANGE = 4
- SET = 5
- NOT_SET = 6
-
- def __init__(self, *args):
- self.args = args
- self.tokenNames = []
- self.token = None
- self.tokenText = ''
- self.node = None
- if len(args) == 6:
- # Expected range / not range
- if args[3]:
- self.mismatchType = MismatchedTokenException.NOT_RANGE
- else:
- self.mismatchType = MismatchedTokenException.RANGE
- self.tokenNames = args[0]
- self.expecting = args[2]
- self.upper = args[3]
- self.fileName = args[5]
-
- elif len(args) == 4 and isinstance(args[2], int):
- # Expected token / not token
- if args[3]:
- self.mismatchType = MismatchedTokenException.NOT_TOKEN
- else:
- self.mismatchType = MismatchedTokenException.TOKEN
- self.tokenNames = args[0]
- self.expecting = args[2]
-
- elif len(args) == 4 and isinstance(args[2], BitSet):
- # Expected BitSet / not BitSet
- if args[3]:
- self.mismatchType = MismatchedTokenException.NOT_SET
- else:
- self.mismatchType = MismatchedTokenException.SET
- self.tokenNames = args[0]
- self.set = args[2]
-
- else:
- self.mismatchType = MismatchedTokenException.NONE
- RecognitionException.__init__(self, "Mismatched Token: expecting any AST node", "<AST>", -1, -1)
-
- if len(args) >= 2:
- if isinstance(args[1],Token):
- self.token = args[1]
- self.tokenText = self.token.getText()
- RecognitionException.__init__(self, "Mismatched Token",
- self.fileName,
- self.token.getLine(),
- self.token.getColumn())
- elif isinstance(args[1],AST):
- self.node = args[1]
- self.tokenText = str(self.node)
- RecognitionException.__init__(self, "Mismatched Token",
- "<AST>",
- self.node.getLine(),
- self.node.getColumn())
- else:
- self.tokenText = "<empty tree>"
- RecognitionException.__init__(self, "Mismatched Token",
- "<AST>", -1, -1)
-
- def appendTokenName(self, sb, tokenType):
- if tokenType == INVALID_TYPE:
- sb.append("<Set of tokens>")
- elif tokenType < 0 or tokenType >= len(self.tokenNames):
- sb.append("<" + str(tokenType) + ">")
- else:
- sb.append(self.tokenNames[tokenType])
-
- ##
- # Returns an error message with line number/column information
- #
- def __str__(self):
- sb = ['']
- sb.append(RecognitionException.__str__(self))
-
- if self.mismatchType == MismatchedTokenException.TOKEN:
- sb.append("expecting ")
- self.appendTokenName(sb, self.expecting)
- sb.append(", found " + self.tokenText)
- elif self.mismatchType == MismatchedTokenException.NOT_TOKEN:
- sb.append("expecting anything but '")
- self.appendTokenName(sb, self.expecting)
- sb.append("'; got it anyway")
- elif self.mismatchType in [MismatchedTokenException.RANGE, MismatchedTokenException.NOT_RANGE]:
- sb.append("expecting token ")
- if self.mismatchType == MismatchedTokenException.NOT_RANGE:
- sb.append("NOT ")
- sb.append("in range: ")
- appendTokenName(sb, self.expecting)
- sb.append("..")
- appendTokenName(sb, self.upper)
- sb.append(", found " + self.tokenText)
- elif self.mismatchType in [MismatchedTokenException.SET, MismatchedTokenException.NOT_SET]:
- sb.append("expecting ")
- if self.mismatchType == MismatchedTokenException.NOT_SET:
- sb.append("NOT ")
- sb.append("one of (")
- for i in range(len(self.set)):
- self.appendTokenName(sb, self.set[i])
- sb.append("), found " + self.tokenText)
-
- return str().join(sb).strip()
-
- __repr__ = __str__
-
-
-class TokenStreamException(ANTLRException):
-
- def __init__(self, *args):
- ANTLRException.__init__(self, *args)
-
-
-# Wraps an Exception in a TokenStreamException
-class TokenStreamIOException(TokenStreamException):
-
- def __init__(self, *args):
- if args and isinstance(args[0], Exception):
- io = args[0]
- TokenStreamException.__init__(self, str(io))
- self.io = io
- else:
- TokenStreamException.__init__(self, *args)
- self.io = self
-
-
-# Wraps a RecognitionException in a TokenStreamException
-class TokenStreamRecognitionException(TokenStreamException):
-
- def __init__(self, *args):
- if args and isinstance(args[0], RecognitionException):
- recog = args[0]
- TokenStreamException.__init__(self, str(recog))
- self.recog = recog
- else:
- raise TypeError("TokenStreamRecognitionException requires RecognitionException argument")
-
- def __str__(self):
- return str(self.recog)
-
- __repr__ = __str__
-
-
-class TokenStreamRetryException(TokenStreamException):
-
- def __init__(self, *args):
- TokenStreamException.__init__(self, *args)
-
-
-class CharStreamException(ANTLRException):
-
- def __init__(self, *args):
- ANTLRException.__init__(self, *args)
-
-
-# Wraps an Exception in a CharStreamException
-class CharStreamIOException(CharStreamException):
-
- def __init__(self, *args):
- if args and isinstance(args[0], Exception):
- io = args[0]
- CharStreamException.__init__(self, str(io))
- self.io = io
- else:
- CharStreamException.__init__(self, *args)
- self.io = self
-
-
-class TryAgain(Exception):
- pass
-
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### Token ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class Token(object):
- SKIP = -1
- INVALID_TYPE = 0
- EOF_TYPE = 1
- EOF = 1
- NULL_TREE_LOOKAHEAD = 3
- MIN_USER_TYPE = 4
-
- def __init__(self,**argv):
- try:
- self.type = argv['type']
- except:
- self.type = INVALID_TYPE
- try:
- self.text = argv['text']
- except:
- self.text = "<no text>"
-
- def isEOF(self):
- return (self.type == EOF_TYPE)
-
- def getColumn(self):
- return 0
-
- def getLine(self):
- return 0
-
- def getFilename(self):
- return None
-
- def setFilename(self,name):
- return self
-
- def getText(self):
- return "<no text>"
-
- def setText(self,text):
- if is_string_type(text):
- pass
- else:
- raise TypeError("Token.setText requires string argument")
- return self
-
- def setColumn(self,column):
- return self
-
- def setLine(self,line):
- return self
-
- def getType(self):
- return self.type
-
- def setType(self,type):
- if isinstance(type,int):
- self.type = type
- else:
- raise TypeError("Token.setType requires integer argument")
- return self
-
- def toString(self):
- ## not optimal
- type_ = self.type
- if type_ == 3:
- tval = 'NULL_TREE_LOOKAHEAD'
- elif type_ == 1:
- tval = 'EOF_TYPE'
- elif type_ == 0:
- tval = 'INVALID_TYPE'
- elif type_ == -1:
- tval = 'SKIP'
- else:
- tval = type_
- return '["%s",<%s>]' % (self.getText(),tval)
-
- __str__ = toString
- __repr__ = toString
-
-### static attribute ..
-Token.badToken = Token( type=INVALID_TYPE, text="<no text>")
-
-if __name__ == "__main__":
- print("testing ..")
- T = Token.badToken
- print(T)
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### CommonToken ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class CommonToken(Token):
-
- def __init__(self,**argv):
- Token.__init__(self,**argv)
- self.line = 0
- self.col = 0
- try:
- self.line = argv['line']
- except:
- pass
- try:
- self.col = argv['col']
- except:
- pass
-
- def getLine(self):
- return self.line
-
- def getText(self):
- return self.text
-
- def getColumn(self):
- return self.col
-
- def setLine(self,line):
- self.line = line
- return self
-
- def setText(self,text):
- self.text = text
- return self
-
- def setColumn(self,col):
- self.col = col
- return self
-
- def toString(self):
- ## not optimal
- type_ = self.type
- if type_ == 3:
- tval = 'NULL_TREE_LOOKAHEAD'
- elif type_ == 1:
- tval = 'EOF_TYPE'
- elif type_ == 0:
- tval = 'INVALID_TYPE'
- elif type_ == -1:
- tval = 'SKIP'
- else:
- tval = type_
- d = {
- 'text' : self.text,
- 'type' : tval,
- 'line' : self.line,
- 'colm' : self.col
- }
-
- fmt = '["%(text)s",<%(type)s>,line=%(line)s,col=%(colm)s]'
- return fmt % d
-
- __str__ = toString
- __repr__ = toString
-
-
-if __name__ == '__main__' :
- T = CommonToken()
- print(T)
- T = CommonToken(col=15,line=1,text="some text", type=5)
- print(T)
- T = CommonToken()
- T.setLine(1).setColumn(15).setText("some text").setType(5)
- print(T)
- print(T.getLine())
- print(T.getColumn())
- print(T.getText())
- print(T.getType())
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### CommonHiddenStreamToken ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class CommonHiddenStreamToken(CommonToken):
- def __init__(self,*args):
- CommonToken.__init__(self,*args)
- self.hiddenBefore = None
- self.hiddenAfter = None
-
- def getHiddenAfter(self):
- return self.hiddenAfter
-
- def getHiddenBefore(self):
- return self.hiddenBefore
-
- def setHiddenAfter(self,t):
- self.hiddenAfter = t
-
- def setHiddenBefore(self, t):
- self.hiddenBefore = t
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### Queue ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-## Shall be a circular buffer on tokens ..
-class Queue(object):
-
- def __init__(self):
- self.buffer = [] # empty list
-
- def append(self,item):
- self.buffer.append(item)
-
- def elementAt(self,index):
- return self.buffer[index]
-
- def reset(self):
- self.buffer = []
-
- def removeFirst(self):
- self.buffer.pop(0)
-
- def length(self):
- return len(self.buffer)
-
- def __str__(self):
- return str(self.buffer)
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### InputBuffer ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class InputBuffer(object):
- def __init__(self):
- self.nMarkers = 0
- self.markerOffset = 0
- self.numToConsume = 0
- self.queue = Queue()
-
- def __str__(self):
- return "(%s,%s,%s,%s)" % (
- self.nMarkers,
- self.markerOffset,
- self.numToConsume,
- self.queue)
-
- def __repr__(self):
- return str(self)
-
- def commit(self):
- self.nMarkers -= 1
-
- def consume(self) :
- self.numToConsume += 1
-
- ## probably better to return a list of items
- ## because of unicode. Or return a unicode
- ## string ..
- def getLAChars(self) :
- i = self.markerOffset
- n = self.queue.length()
- s = ''
- while i<n:
- s += self.queue.elementAt(i)
- return s
-
- ## probably better to return a list of items
- ## because of unicode chars
- def getMarkedChars(self) :
- s = ''
- i = 0
- n = self.markerOffset
- while i<n:
- s += self.queue.elementAt(i)
- return s
-
- def isMarked(self) :
- return self.nMarkers != 0
-
- def fill(self,k):
- ### abstract method
- raise NotImplementedError()
-
- def LA(self,k) :
- self.fill(k)
- return self.queue.elementAt(self.markerOffset + k - 1)
-
- def mark(self) :
- self.syncConsume()
- self.nMarkers += 1
- return self.markerOffset
-
- def rewind(self,mark) :
- self.syncConsume()
- self.markerOffset = mark
- self.nMarkers -= 1
-
- def reset(self) :
- self.nMarkers = 0
- self.markerOffset = 0
- self.numToConsume = 0
- self.queue.reset()
-
- def syncConsume(self) :
- while self.numToConsume > 0:
- if self.nMarkers > 0:
- # guess mode -- leave leading characters and bump offset.
- self.markerOffset += 1
- else:
- # normal mode -- remove first character
- self.queue.removeFirst()
- self.numToConsume -= 1
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### CharBuffer ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class CharBuffer(InputBuffer):
- def __init__(self,reader):
- ##assert isinstance(reader,file)
- super(CharBuffer,self).__init__()
- ## a reader is supposed to be anything that has
- ## a method 'read(int)'.
- self.input = reader
-
- def __str__(self):
- base = super(CharBuffer,self).__str__()
- return "CharBuffer{%s,%s" % (base,str(input))
-
- def fill(self,amount):
- try:
- self.syncConsume()
- while self.queue.length() < (amount + self.markerOffset) :
- ## retrieve just one char - what happend at end
- ## of input?
- c = self.input.read(1)
- ### python's behaviour is to return the empty string on
- ### EOF, ie. no exception whatsoever is thrown. An empty
- ### python string has the nice feature that it is of
- ### type 'str' and "not ''" would return true. Contrary,
- ### one can't do this: '' in 'abc'. This should return
- ### false, but all we get is then a TypeError as an
- ### empty string is not a character.
-
- ### Let's assure then that we have either seen a
- ### character or an empty string (EOF).
- assert len(c) == 0 or len(c) == 1
-
- ### And it shall be of type string (ASCII or UNICODE).
- assert is_string_type(c)
-
- ### Just append EOF char to buffer. Note that buffer may
- ### contain then just more than one EOF char ..
-
- ### use unicode chars instead of ASCII ..
- self.queue.append(c)
- except Exception as e:
- raise CharStreamIOException(e)
- ##except: # (mk) Cannot happen ...
- ##error ("unexpected exception caught ..")
- ##assert 0
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### LexerSharedInputState ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class LexerSharedInputState(object):
- def __init__(self,ibuf):
- assert isinstance(ibuf,InputBuffer)
- self.input = ibuf
- self.column = 1
- self.line = 1
- self.tokenStartColumn = 1
- self.tokenStartLine = 1
- self.guessing = 0
- self.filename = None
-
- def reset(self):
- self.column = 1
- self.line = 1
- self.tokenStartColumn = 1
- self.tokenStartLine = 1
- self.guessing = 0
- self.filename = None
- self.input.reset()
-
- def LA(self,k):
- return self.input.LA(k)
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TokenStream ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TokenStream(object):
- def nextToken(self):
- pass
-
- def __iter__(self):
- return TokenStreamIterator(self)
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TokenStreamIterator ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TokenStreamIterator(object):
- def __init__(self,inst):
- if isinstance(inst,TokenStream):
- self.inst = inst
- return
- raise TypeError("TokenStreamIterator requires TokenStream object")
-
- def __next__(self):
- assert self.inst
- item = self.inst.nextToken()
- if not item or item.isEOF():
- raise StopIteration()
- return item
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TokenStreamSelector ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TokenStreamSelector(TokenStream):
-
- def __init__(self):
- self._input = None
- self._stmap = {}
- self._stack = []
-
- def addInputStream(self,stream,key):
- self._stmap[key] = stream
-
- def getCurrentStream(self):
- return self._input
-
- def getStream(self,sname):
- try:
- stream = self._stmap[sname]
- except:
- raise ValueError("TokenStream " + sname + " not found");
- return stream;
-
- def nextToken(self):
- while 1:
- try:
- return self._input.nextToken()
- except TokenStreamRetryException as r:
- ### just retry "forever"
- pass
-
- def pop(self):
- stream = self._stack.pop();
- self.select(stream);
- return stream;
-
- def push(self,arg):
- self._stack.append(self._input);
- self.select(arg)
-
- def retry(self):
- raise TokenStreamRetryException()
-
- def select(self,arg):
- if isinstance(arg,TokenStream):
- self._input = arg
- return
- if is_string_type(arg):
- self._input = self.getStream(arg)
- return
- raise TypeError("TokenStreamSelector.select requires " +
- "TokenStream or string argument")
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TokenStreamBasicFilter ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TokenStreamBasicFilter(TokenStream):
-
- def __init__(self,input):
-
- self.input = input;
- self.discardMask = BitSet()
-
- def discard(self,arg):
- if isinstance(arg,int):
- self.discardMask.add(arg)
- return
- if isinstance(arg,BitSet):
- self.discardMark = arg
- return
- raise TypeError("TokenStreamBasicFilter.discard requires" +
- "integer or BitSet argument")
-
- def nextToken(self):
- tok = self.input.nextToken()
- while tok and self.discardMask.member(tok.getType()):
- tok = self.input.nextToken()
- return tok
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TokenStreamHiddenTokenFilter ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TokenStreamHiddenTokenFilter(TokenStreamBasicFilter):
-
- def __init__(self,input):
- TokenStreamBasicFilter.__init__(self,input)
- self.hideMask = BitSet()
- self.nextMonitoredToken = None
- self.lastHiddenToken = None
- self.firstHidden = None
-
- def consume(self):
- self.nextMonitoredToken = self.input.nextToken()
-
- def consumeFirst(self):
- self.consume()
-
- p = None;
- while self.hideMask.member(self.LA(1).getType()) or \
- self.discardMask.member(self.LA(1).getType()):
- if self.hideMask.member(self.LA(1).getType()):
- if not p:
- p = self.LA(1)
- else:
- p.setHiddenAfter(self.LA(1))
- self.LA(1).setHiddenBefore(p)
- p = self.LA(1)
- self.lastHiddenToken = p
- if not self.firstHidden:
- self.firstHidden = p
- self.consume()
-
- def getDiscardMask(self):
- return self.discardMask
-
- def getHiddenAfter(self,t):
- return t.getHiddenAfter()
-
- def getHiddenBefore(self,t):
- return t.getHiddenBefore()
-
- def getHideMask(self):
- return self.hideMask
-
- def getInitialHiddenToken(self):
- return self.firstHidden
-
- def hide(self,m):
- if isinstance(m,int):
- self.hideMask.add(m)
- return
- if isinstance(m.BitMask):
- self.hideMask = m
- return
-
- def LA(self,i):
- return self.nextMonitoredToken
-
- def nextToken(self):
- if not self.LA(1):
- self.consumeFirst()
-
- monitored = self.LA(1)
-
- monitored.setHiddenBefore(self.lastHiddenToken)
- self.lastHiddenToken = None
-
- self.consume()
- p = monitored
-
- while self.hideMask.member(self.LA(1).getType()) or \
- self.discardMask.member(self.LA(1).getType()):
- if self.hideMask.member(self.LA(1).getType()):
- p.setHiddenAfter(self.LA(1))
- if p != monitored:
- self.LA(1).setHiddenBefore(p)
- p = self.lastHiddenToken = self.LA(1)
- self.consume()
- return monitored
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### StringBuffer ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class StringBuffer:
- def __init__(self,string=None):
- if string:
- self.text = list(string)
- else:
- self.text = []
-
- def setLength(self,sz):
- if not sz :
- self.text = []
- return
- assert sz>0
- if sz >= self.length():
- return
- ### just reset to empty buffer
- self.text = self.text[0:sz]
-
- def length(self):
- return len(self.text)
-
- def append(self,c):
- self.text.append(c)
-
- ### return buffer as string. Arg 'a' is used as index
- ## into the buffer and 2nd argument shall be the length.
- ## If 2nd args is absent, we return chars till end of
- ## buffer starting with 'a'.
- def getString(self,a=None,length=None):
- if not a :
- a = 0
- assert a>=0
- if a>= len(self.text) :
- return ""
-
- if not length:
- ## no second argument
- L = self.text[a:]
- else:
- assert (a+length) <= len(self.text)
- b = a + length
- L = self.text[a:b]
- s = ""
- for x in L : s += x
- return s
-
- toString = getString ## alias
-
- def __str__(self):
- return str(self.text)
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### Reader ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-## When reading Japanese chars, it happens that a stream returns a
-## 'char' of length 2. This looks like a bug in the appropriate
-## codecs - but I'm rather unsure about this. Anyway, if this is
-## the case, I'm going to split this string into a list of chars
-## and put them on hold, ie. on a buffer. Next time when called
-## we read from buffer until buffer is empty.
-## wh: nov, 25th -> problem does not appear in Python 2.4.0.c1.
-
-class Reader(object):
- def __init__(self,stream):
- self.cin = stream
- self.buf = []
-
- def read(self,num):
- assert num==1
-
- if len(self.buf):
- return self.buf.pop()
-
- ## Read a char - this may return a string.
- ## Is this a bug in codecs/Python?
- c = self.cin.read(1)
-
- if not c or len(c)==1:
- return c
-
- L = list(c)
- L.reverse()
- for x in L:
- self.buf.append(x)
-
- ## read one char ..
- return self.read(1)
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### CharScanner ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class CharScanner(TokenStream):
- ## class members
- NO_CHAR = 0
- EOF_CHAR = '' ### EOF shall be the empty string.
-
- def __init__(self, *argv, **kwargs):
- super(CharScanner, self).__init__()
- self.saveConsumedInput = True
- self.tokenClass = None
- self.caseSensitive = True
- self.caseSensitiveLiterals = True
- self.literals = None
- self.tabsize = 8
- self._returnToken = None
- self.commitToPath = False
- self.traceDepth = 0
- self.text = StringBuffer()
- self.hashString = hash(self)
- self.setTokenObjectClass(CommonToken)
- self.setInput(*argv)
-
- def __iter__(self):
- return CharScannerIterator(self)
-
- def setInput(self,*argv):
- ## case 1:
- ## if there's no arg we default to read from
- ## standard input
- if not argv:
- import sys
- self.setInput(sys.stdin)
- return
-
- ## get 1st argument
- arg1 = argv[0]
-
- ## case 2:
- ## if arg1 is a string, we assume it's a file name
- ## and open a stream using 2nd argument as open
- ## mode. If there's no 2nd argument we fall back to
- ## mode '+rb'.
- if is_string_type(arg1):
- f = open(arg1,"rb")
- self.setInput(f)
- self.setFilename(arg1)
- return
-
- ## case 3:
- ## if arg1 is a file we wrap it by a char buffer (
- ## some additional checks?? No, can't do this in
- ## general).
- if isinstance(arg1,file):
- self.setInput(CharBuffer(arg1))
- return
-
- ## case 4:
- ## if arg1 is of type SharedLexerInputState we use
- ## argument as is.
- if isinstance(arg1,LexerSharedInputState):
- self.inputState = arg1
- return
-
- ## case 5:
- ## check whether argument type is of type input
- ## buffer. If so create a SharedLexerInputState and
- ## go ahead.
- if isinstance(arg1,InputBuffer):
- self.setInput(LexerSharedInputState(arg1))
- return
-
- ## case 6:
- ## check whether argument type has a method read(int)
- ## If so create CharBuffer ...
- try:
- if arg1.read:
- rd = Reader(arg1)
- cb = CharBuffer(rd)
- ss = LexerSharedInputState(cb)
- self.inputState = ss
- return
- except:
- pass
-
- ## case 7:
- ## raise wrong argument exception
- raise TypeError(argv)
-
- def setTabSize(self,size) :
- self.tabsize = size
-
- def getTabSize(self) :
- return self.tabsize
-
- def setCaseSensitive(self,t) :
- self.caseSensitive = t
-
- def setCommitToPath(self,commit) :
- self.commitToPath = commit
-
- def setFilename(self,f) :
- self.inputState.filename = f
-
- def setLine(self,line) :
- self.inputState.line = line
-
- def setText(self,s) :
- self.resetText()
- self.text.append(s)
-
- def getCaseSensitive(self) :
- return self.caseSensitive
-
- def getCaseSensitiveLiterals(self) :
- return self.caseSensitiveLiterals
-
- def getColumn(self) :
- return self.inputState.column
-
- def setColumn(self,c) :
- self.inputState.column = c
-
- def getCommitToPath(self) :
- return self.commitToPath
-
- def getFilename(self) :
- return self.inputState.filename
-
- def getInputBuffer(self) :
- return self.inputState.input
-
- def getInputState(self) :
- return self.inputState
-
- def setInputState(self,state) :
- assert isinstance(state,LexerSharedInputState)
- self.inputState = state
-
- def getLine(self) :
- return self.inputState.line
-
- def getText(self) :
- return str(self.text)
-
- def getTokenObject(self) :
- return self._returnToken
-
- def LA(self,i) :
- c = self.inputState.input.LA(i)
- if not self.caseSensitive:
- ### E0006
- c = c.__class__.lower(c)
- return c
-
- def makeToken(self,type) :
- try:
- ## dynamically load a class
- assert self.tokenClass
- tok = self.tokenClass()
- tok.setType(type)
- tok.setColumn(self.inputState.tokenStartColumn)
- tok.setLine(self.inputState.tokenStartLine)
- return tok
- except:
- self.panic("unable to create new token")
- return Token.badToken
-
- def mark(self) :
- return self.inputState.input.mark()
-
- def _match_bitset(self,b) :
- if b.member(self.LA(1)):
- self.consume()
- else:
- raise MismatchedCharException(self.LA(1), b, False, self)
-
- def _match_string(self,s) :
- for c in s:
- if self.LA(1) == c:
- self.consume()
- else:
- raise MismatchedCharException(self.LA(1), c, False, self)
-
- def match(self,item):
- if is_string_type(item):
- return self._match_string(item)
- else:
- return self._match_bitset(item)
-
- def matchNot(self,c) :
- if self.LA(1) != c:
- self.consume()
- else:
- raise MismatchedCharException(self.LA(1), c, True, self)
-
- def matchRange(self,c1,c2) :
- if self.LA(1) < c1 or self.LA(1) > c2 :
- raise MismatchedCharException(self.LA(1), c1, c2, False, self)
- else:
- self.consume()
-
- def newline(self) :
- self.inputState.line += 1
- self.inputState.column = 1
-
- def tab(self) :
- c = self.getColumn()
- nc = ( ((c-1)/self.tabsize) + 1) * self.tabsize + 1
- self.setColumn(nc)
-
- def panic(self,s='') :
- print("CharScanner: panic: " + s)
- sys.exit(1)
-
- def reportError(self,ex) :
- print(ex)
-
- def reportError(self,s) :
- if not self.getFilename():
- print("error: " + str(s))
- else:
- print(self.getFilename() + ": error: " + str(s))
-
- def reportWarning(self,s) :
- if not self.getFilename():
- print("warning: " + str(s))
- else:
- print(self.getFilename() + ": warning: " + str(s))
-
- def resetText(self) :
- self.text.setLength(0)
- self.inputState.tokenStartColumn = self.inputState.column
- self.inputState.tokenStartLine = self.inputState.line
-
- def rewind(self,pos) :
- self.inputState.input.rewind(pos)
-
- def setTokenObjectClass(self,cl):
- self.tokenClass = cl
-
- def testForLiteral(self,token):
- if not token:
- return
- assert isinstance(token,Token)
-
- _type = token.getType()
-
- ## special tokens can't be literals
- if _type in [SKIP,INVALID_TYPE,EOF_TYPE,NULL_TREE_LOOKAHEAD] :
- return
-
- _text = token.getText()
- if not _text:
- return
-
- assert is_string_type(_text)
- _type = self.testLiteralsTable(_text,_type)
- token.setType(_type)
- return _type
-
- def testLiteralsTable(self,*args):
- if is_string_type(args[0]):
- s = args[0]
- i = args[1]
- else:
- s = self.text.getString()
- i = args[0]
-
- ## check whether integer has been given
- if not isinstance(i,int):
- assert isinstance(i,int)
-
- ## check whether we have a dict
- assert isinstance(self.literals,dict)
- try:
- ## E0010
- if not self.caseSensitiveLiterals:
- s = s.__class__.lower(s)
- i = self.literals[s]
- except:
- pass
- return i
-
- def toLower(self,c):
- return c.__class__.lower()
-
- def traceIndent(self):
- print(' ' * self.traceDepth)
-
- def traceIn(self,rname):
- self.traceDepth += 1
- self.traceIndent()
- print("> lexer %s c== %s" % (rname,self.LA(1)))
-
- def traceOut(self,rname):
- self.traceIndent()
- print("< lexer %s c== %s" % (rname,self.LA(1)))
- self.traceDepth -= 1
-
- def uponEOF(self):
- pass
-
- def append(self,c):
- if self.saveConsumedInput :
- self.text.append(c)
-
- def commit(self):
- self.inputState.input.commit()
-
- def consume(self):
- if not self.inputState.guessing:
- c = self.LA(1)
- if self.caseSensitive:
- self.append(c)
- else:
- # use input.LA(), not LA(), to get original case
- # CharScanner.LA() would toLower it.
- c = self.inputState.input.LA(1)
- self.append(c)
-
- if c and c in "\t":
- self.tab()
- else:
- self.inputState.column += 1
- self.inputState.input.consume()
-
- ## Consume chars until one matches the given char
- def consumeUntil_char(self,c):
- while self.LA(1) != EOF_CHAR and self.LA(1) != c:
- self.consume()
-
- ## Consume chars until one matches the given set
- def consumeUntil_bitset(self,bitset):
- while self.LA(1) != EOF_CHAR and not self.set.member(self.LA(1)):
- self.consume()
-
- ### If symbol seen is EOF then generate and set token, otherwise
- ### throw exception.
- def default(self,la1):
- if not la1 :
- self.uponEOF()
- self._returnToken = self.makeToken(EOF_TYPE)
- else:
- self.raise_NoViableAlt(la1)
-
- def filterdefault(self,la1,*args):
- if not la1:
- self.uponEOF()
- self._returnToken = self.makeToken(EOF_TYPE)
- return
-
- if not args:
- self.consume()
- raise TryAgain()
- else:
- ### apply filter object
- self.commit();
- try:
- func=args[0]
- args=args[1:]
- func(*args)
- except RecognitionException as e:
- ## catastrophic failure
- self.reportError(e);
- self.consume();
- raise TryAgain()
-
- def raise_NoViableAlt(self,la1=None):
- if not la1: la1 = self.LA(1)
- fname = self.getFilename()
- line = self.getLine()
- col = self.getColumn()
- raise NoViableAltForCharException(la1,fname,line,col)
-
- def set_return_token(self,_create,_token,_ttype,_offset):
- if _create and not _token and (not _ttype == SKIP):
- string = self.text.getString(_offset)
- _token = self.makeToken(_ttype)
- _token.setText(string)
- self._returnToken = _token
- return _token
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### CharScannerIterator ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class CharScannerIterator:
-
- def __init__(self,inst):
- if isinstance(inst,CharScanner):
- self.inst = inst
- return
- raise TypeError("CharScannerIterator requires CharScanner object")
-
- def __next__(self):
- assert self.inst
- item = self.inst.nextToken()
- if not item or item.isEOF():
- raise StopIteration()
- return item
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### BitSet ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-### I'm assuming here that a long is 64bits. It appears however, that
-### a long is of any size. That means we can use a single long as the
-### bitset (!), ie. Python would do almost all the work (TBD).
-
-class BitSet(object):
- BITS = 64
- NIBBLE = 4
- LOG_BITS = 6
- MOD_MASK = BITS -1
-
- def __init__(self,data=None):
- if not data:
- BitSet.__init__(self,[int(0)])
- return
- if isinstance(data,int):
- BitSet.__init__(self,[int(data)])
- return
- if isinstance(data,int):
- BitSet.__init__(self,[data])
- return
- if not isinstance(data,list):
- raise TypeError("BitSet requires integer, long, or " +
- "list argument")
- for x in data:
- if not isinstance(x,int):
- raise TypeError(self,"List argument item is " +
- "not a long: %s" % (x))
- self.data = data
-
- def __str__(self):
- bits = len(self.data) * BitSet.BITS
- s = ""
- for i in range(0,bits):
- if self.at(i):
- s += "1"
- else:
- s += "o"
- if not ((i+1) % 10):
- s += '|%s|' % (i+1)
- return s
-
- def __repr__(self):
- return str(self)
-
- def member(self,item):
- if not item:
- return False
-
- if isinstance(item,int):
- return self.at(item)
-
- if not is_string_type(item):
- raise TypeError(self,"char or unichar expected: %s" % (item))
-
- ## char is a (unicode) string with at most lenght 1, ie.
- ## a char.
-
- if len(item) != 1:
- raise TypeError(self,"char expected: %s" % (item))
-
- ### handle ASCII/UNICODE char
- num = ord(item)
-
- ### check whether position num is in bitset
- return self.at(num)
-
- def wordNumber(self,bit):
- return bit >> BitSet.LOG_BITS
-
- def bitMask(self,bit):
- pos = bit & BitSet.MOD_MASK ## bit mod BITS
- return (1 << pos)
-
- def set(self,bit,on=True):
- # grow bitset as required (use with care!)
- i = self.wordNumber(bit)
- mask = self.bitMask(bit)
- if i>=len(self.data):
- d = i - len(self.data) + 1
- for x in range(0,d):
- self.data.append(0)
- assert len(self.data) == i+1
- if on:
- self.data[i] |= mask
- else:
- self.data[i] &= (~mask)
-
- ### make add an alias for set
- add = set
-
- def off(self,bit,off=True):
- self.set(bit,not off)
-
- def at(self,bit):
- i = self.wordNumber(bit)
- v = self.data[i]
- m = self.bitMask(bit)
- return v & m
-
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### some further funcs ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-def illegalarg_ex(func):
- raise ValueError(
- "%s is only valid if parser is built for debugging" %
- (func.__name__))
-
-def runtime_ex(func):
- raise RuntimeException(
- "%s is only valid if parser is built for debugging" %
- (func.__name__))
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TokenBuffer ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TokenBuffer(object):
- def __init__(self,stream):
- self.input = stream
- self.nMarkers = 0
- self.markerOffset = 0
- self.numToConsume = 0
- self.queue = Queue()
-
- def reset(self) :
- self.nMarkers = 0
- self.markerOffset = 0
- self.numToConsume = 0
- self.queue.reset()
-
- def consume(self) :
- self.numToConsume += 1
-
- def fill(self, amount):
- self.syncConsume()
- while self.queue.length() < (amount + self.markerOffset):
- self.queue.append(self.input.nextToken())
-
- def getInput(self):
- return self.input
-
- def LA(self,k) :
- self.fill(k)
- return self.queue.elementAt(self.markerOffset + k - 1).type
-
- def LT(self,k) :
- self.fill(k)
- return self.queue.elementAt(self.markerOffset + k - 1)
-
- def mark(self) :
- self.syncConsume()
- self.nMarkers += 1
- return self.markerOffset
-
- def rewind(self,mark) :
- self.syncConsume()
- self.markerOffset = mark
- self.nMarkers -= 1
-
- def syncConsume(self) :
- while self.numToConsume > 0:
- if self.nMarkers > 0:
- # guess mode -- leave leading characters and bump offset.
- self.markerOffset += 1
- else:
- # normal mode -- remove first character
- self.queue.removeFirst()
- self.numToConsume -= 1
-
- def __str__(self):
- return "(%s,%s,%s,%s,%s)" % (
- self.input,
- self.nMarkers,
- self.markerOffset,
- self.numToConsume,
- self.queue)
-
- def __repr__(self):
- return str(self)
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### ParserSharedInputState ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class ParserSharedInputState(object):
-
- def __init__(self):
- self.input = None
- self.reset()
-
- def reset(self):
- self.guessing = 0
- self.filename = None
- if self.input:
- self.input.reset()
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### Parser ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class Parser(object):
-
- def __init__(self, *args, **kwargs):
- self.tokenNames = None
- self.returnAST = None
- self.astFactory = None
- self.tokenTypeToASTClassMap = {}
- self.ignoreInvalidDebugCalls = False
- self.traceDepth = 0
- if not args:
- self.inputState = ParserSharedInputState()
- return
- arg0 = args[0]
- assert isinstance(arg0,ParserSharedInputState)
- self.inputState = arg0
- return
-
- def getTokenTypeToASTClassMap(self):
- return self.tokenTypeToASTClassMap
-
-
- def addMessageListener(self, l):
- if not self.ignoreInvalidDebugCalls:
- illegalarg_ex(addMessageListener)
-
- def addParserListener(self,l) :
- if (not self.ignoreInvalidDebugCalls) :
- illegalarg_ex(addParserListener)
-
- def addParserMatchListener(self, l) :
- if (not self.ignoreInvalidDebugCalls) :
- illegalarg_ex(addParserMatchListener)
-
- def addParserTokenListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- illegalarg_ex(addParserTokenListener)
-
- def addSemanticPredicateListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- illegalarg_ex(addSemanticPredicateListener)
-
- def addSyntacticPredicateListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- illegalarg_ex(addSyntacticPredicateListener)
-
- def addTraceListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- illegalarg_ex(addTraceListener)
-
- def consume(self):
- raise NotImplementedError()
-
- def _consumeUntil_type(self,tokenType):
- while self.LA(1) != EOF_TYPE and self.LA(1) != tokenType:
- self.consume()
-
- def _consumeUntil_bitset(self, set):
- while self.LA(1) != EOF_TYPE and not set.member(self.LA(1)):
- self.consume()
-
- def consumeUntil(self,arg):
- if isinstance(arg,int):
- self._consumeUntil_type(arg)
- else:
- self._consumeUntil_bitset(arg)
-
- def defaultDebuggingSetup(self):
- pass
-
- def getAST(self) :
- return self.returnAST
-
- def getASTFactory(self) :
- return self.astFactory
-
- def getFilename(self) :
- return self.inputState.filename
-
- def getInputState(self) :
- return self.inputState
-
- def setInputState(self, state) :
- self.inputState = state
-
- def getTokenName(self,num) :
- return self.tokenNames[num]
-
- def getTokenNames(self) :
- return self.tokenNames
-
- def isDebugMode(self) :
- return self.false
-
- def LA(self, i):
- raise NotImplementedError()
-
- def LT(self, i):
- raise NotImplementedError()
-
- def mark(self):
- return self.inputState.input.mark()
-
- def _match_int(self,t):
- if (self.LA(1) != t):
- raise MismatchedTokenException(
- self.tokenNames, self.LT(1), t, False, self.getFilename())
- else:
- self.consume()
-
- def _match_set(self, b):
- if (not b.member(self.LA(1))):
- raise MismatchedTokenException(
- self.tokenNames,self.LT(1), b, False, self.getFilename())
- else:
- self.consume()
-
- def match(self,set) :
- if isinstance(set,int):
- self._match_int(set)
- return
- if isinstance(set,BitSet):
- self._match_set(set)
- return
- raise TypeError("Parser.match requires integer ot BitSet argument")
-
- def matchNot(self,t):
- if self.LA(1) == t:
- raise MismatchedTokenException(
- tokenNames, self.LT(1), t, True, self.getFilename())
- else:
- self.consume()
-
- def removeMessageListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(removeMessageListener)
-
- def removeParserListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(removeParserListener)
-
- def removeParserMatchListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(removeParserMatchListener)
-
- def removeParserTokenListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(removeParserTokenListener)
-
- def removeSemanticPredicateListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(removeSemanticPredicateListener)
-
- def removeSyntacticPredicateListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(removeSyntacticPredicateListener)
-
- def removeTraceListener(self, l) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(removeTraceListener)
-
- def reportError(self,x) :
- fmt = "syntax error:"
- f = self.getFilename()
- if f:
- fmt = ("%s:" % f) + fmt
- if isinstance(x,Token):
- line = x.getColumn()
- col = x.getLine()
- text = x.getText()
- fmt = fmt + 'unexpected symbol at line %s (column %s) : "%s"'
- print(fmt % (line,col,text), file=sys.stderr)
- else:
- print(fmt,str(x), file=sys.stderr)
-
- def reportWarning(self,s):
- f = self.getFilename()
- if f:
- print("%s:warning: %s" % (f,str(x)))
- else:
- print("warning: %s" % (str(x)))
-
- def rewind(self, pos) :
- self.inputState.input.rewind(pos)
-
- def setASTFactory(self, f) :
- self.astFactory = f
-
- def setASTNodeClass(self, cl) :
- self.astFactory.setASTNodeType(cl)
-
- def setASTNodeType(self, nodeType) :
- self.setASTNodeClass(nodeType)
-
- def setDebugMode(self, debugMode) :
- if (not self.ignoreInvalidDebugCalls):
- runtime_ex(setDebugMode)
-
- def setFilename(self, f) :
- self.inputState.filename = f
-
- def setIgnoreInvalidDebugCalls(self, value) :
- self.ignoreInvalidDebugCalls = value
-
- def setTokenBuffer(self, t) :
- self.inputState.input = t
-
- def traceIndent(self):
- print(" " * self.traceDepth)
-
- def traceIn(self,rname):
- self.traceDepth += 1
- self.trace("> ", rname)
-
- def traceOut(self,rname):
- self.trace("< ", rname)
- self.traceDepth -= 1
-
- ### wh: moved from ASTFactory to Parser
- def addASTChild(self,currentAST, child):
- if not child:
- return
- if not currentAST.root:
- currentAST.root = child
- elif not currentAST.child:
- currentAST.root.setFirstChild(child)
- else:
- currentAST.child.setNextSibling(child)
- currentAST.child = child
- currentAST.advanceChildToEnd()
-
- ### wh: moved from ASTFactory to Parser
- def makeASTRoot(self,currentAST,root) :
- if root:
- ### Add the current root as a child of new root
- root.addChild(currentAST.root)
- ### The new current child is the last sibling of the old root
- currentAST.child = currentAST.root
- currentAST.advanceChildToEnd()
- ### Set the new root
- currentAST.root = root
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### LLkParser ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class LLkParser(Parser):
-
- def __init__(self, *args, **kwargs):
- try:
- arg1 = args[0]
- except:
- arg1 = 1
-
- if isinstance(arg1,int):
- super(LLkParser,self).__init__()
- self.k = arg1
- return
-
- if isinstance(arg1,ParserSharedInputState):
- super(LLkParser,self).__init__(arg1)
- self.set_k(1,*args)
- return
-
- if isinstance(arg1,TokenBuffer):
- super(LLkParser,self).__init__()
- self.setTokenBuffer(arg1)
- self.set_k(1,*args)
- return
-
- if isinstance(arg1,TokenStream):
- super(LLkParser,self).__init__()
- tokenBuf = TokenBuffer(arg1)
- self.setTokenBuffer(tokenBuf)
- self.set_k(1,*args)
- return
-
- ### unknown argument
- raise TypeError("LLkParser requires integer, " +
- "ParserSharedInputStream or TokenStream argument")
-
- def consume(self):
- self.inputState.input.consume()
-
- def LA(self,i):
- return self.inputState.input.LA(i)
-
- def LT(self,i):
- return self.inputState.input.LT(i)
-
- def set_k(self,index,*args):
- try:
- self.k = args[index]
- except:
- self.k = 1
-
- def trace(self,ee,rname):
- print(type(self))
- self.traceIndent()
- guess = ""
- if self.inputState.guessing > 0:
- guess = " [guessing]"
- print((ee + rname + guess))
- for i in range(1,self.k+1):
- if i != 1:
- print(", ")
- if self.LT(i) :
- v = self.LT(i).getText()
- else:
- v = "null"
- print("LA(%s) == %s" % (i,v))
- print("\n")
-
- def traceIn(self,rname):
- self.traceDepth += 1;
- self.trace("> ", rname);
-
- def traceOut(self,rname):
- self.trace("< ", rname);
- self.traceDepth -= 1;
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TreeParserSharedInputState ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TreeParserSharedInputState(object):
- def __init__(self):
- self.guessing = 0
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### TreeParser ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class TreeParser(object):
-
- def __init__(self, *args, **kwargs):
- self.inputState = TreeParserSharedInputState()
- self._retTree = None
- self.tokenNames = []
- self.returnAST = None
- self.astFactory = ASTFactory()
- self.traceDepth = 0
-
- def getAST(self):
- return self.returnAST
-
- def getASTFactory(self):
- return self.astFactory
-
- def getTokenName(self,num) :
- return self.tokenNames[num]
-
- def getTokenNames(self):
- return self.tokenNames
-
- def match(self,t,set) :
- assert isinstance(set,int) or isinstance(set,BitSet)
- if not t or t == ASTNULL:
- raise MismatchedTokenException(self.getTokenNames(), t,set, False)
-
- if isinstance(set,int) and t.getType() != set:
- raise MismatchedTokenException(self.getTokenNames(), t,set, False)
-
- if isinstance(set,BitSet) and not set.member(t.getType):
- raise MismatchedTokenException(self.getTokenNames(), t,set, False)
-
- def matchNot(self,t, ttype) :
- if not t or (t == ASTNULL) or (t.getType() == ttype):
- raise MismatchedTokenException(getTokenNames(), t, ttype, True)
-
- def reportError(self,ex):
- print("error:",ex, file=sys.stderr)
-
- def reportWarning(self, s):
- print("warning:",s)
-
- def setASTFactory(self,f):
- self.astFactory = f
-
- def setASTNodeType(self,nodeType):
- self.setASTNodeClass(nodeType)
-
- def setASTNodeClass(self,nodeType):
- self.astFactory.setASTNodeType(nodeType)
-
- def traceIndent(self):
- print(" " * self.traceDepth)
-
- def traceIn(self,rname,t):
- self.traceDepth += 1
- self.traceIndent()
- print(("> " + rname + "(" +
- ifelse(t,str(t),"null") + ")" +
- ifelse(self.inputState.guessing>0,"[guessing]","")))
-
- def traceOut(self,rname,t):
- self.traceIndent()
- print(("< " + rname + "(" +
- ifelse(t,str(t),"null") + ")" +
- ifelse(self.inputState.guessing>0,"[guessing]","")))
- self.traceDepth -= 1
-
- ### wh: moved from ASTFactory to TreeParser
- def addASTChild(self,currentAST, child):
- if not child:
- return
- if not currentAST.root:
- currentAST.root = child
- elif not currentAST.child:
- currentAST.root.setFirstChild(child)
- else:
- currentAST.child.setNextSibling(child)
- currentAST.child = child
- currentAST.advanceChildToEnd()
-
- ### wh: moved from ASTFactory to TreeParser
- def makeASTRoot(self,currentAST,root):
- if root:
- ### Add the current root as a child of new root
- root.addChild(currentAST.root)
- ### The new current child is the last sibling of the old root
- currentAST.child = currentAST.root
- currentAST.advanceChildToEnd()
- ### Set the new root
- currentAST.root = root
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### funcs to work on trees ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-def rightmost(ast):
- if ast:
- while(ast.right):
- ast = ast.right
- return ast
-
-def cmptree(s,t,partial):
- while(s and t):
- ### as a quick optimization, check roots first.
- if not s.equals(t):
- return False
-
- ### if roots match, do full list match test on children.
- if not cmptree(s.getFirstChild(),t.getFirstChild(),partial):
- return False
-
- s = s.getNextSibling()
- t = t.getNextSibling()
-
- r = ifelse(partial,not t,not s and not t)
- return r
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### AST ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class AST(object):
- def __init__(self):
- pass
-
- def addChild(self, c):
- pass
-
- def equals(self, t):
- return False
-
- def equalsList(self, t):
- return False
-
- def equalsListPartial(self, t):
- return False
-
- def equalsTree(self, t):
- return False
-
- def equalsTreePartial(self, t):
- return False
-
- def findAll(self, tree):
- return None
-
- def findAllPartial(self, subtree):
- return None
-
- def getFirstChild(self):
- return self
-
- def getNextSibling(self):
- return self
-
- def getText(self):
- return ""
-
- def getType(self):
- return INVALID_TYPE
-
- def getLine(self):
- return 0
-
- def getColumn(self):
- return 0
-
- def getNumberOfChildren(self):
- return 0
-
- def initialize(self, t, txt):
- pass
-
- def initialize(self, t):
- pass
-
- def setFirstChild(self, c):
- pass
-
- def setNextSibling(self, n):
- pass
-
- def setText(self, text):
- pass
-
- def setType(self, ttype):
- pass
-
- def toString(self):
- self.getText()
-
- __str__ = toString
-
- def toStringList(self):
- return self.getText()
-
- def toStringTree(self):
- return self.getText()
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### ASTNULLType ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-### There is only one instance of this class **/
-class ASTNULLType(AST):
- def __init__(self):
- AST.__init__(self)
- pass
-
- def getText(self):
- return "<ASTNULL>"
-
- def getType(self):
- return NULL_TREE_LOOKAHEAD
-
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### BaseAST ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class BaseAST(AST):
-
- verboseStringConversion = False
- tokenNames = None
-
- def __init__(self):
- self.down = None ## kid
- self.right = None ## sibling
-
- def addChild(self,node):
- if node:
- t = rightmost(self.down)
- if t:
- t.right = node
- else:
- assert not self.down
- self.down = node
-
- def getNumberOfChildren(self):
- t = self.down
- n = 0
- while t:
- n += 1
- t = t.right
- return n
-
- def doWorkForFindAll(self,v,target,partialMatch):
- sibling = self
-
- while sibling:
- c1 = partialMatch and sibling.equalsTreePartial(target)
- if c1:
- v.append(sibling)
- else:
- c2 = not partialMatch and sibling.equalsTree(target)
- if c2:
- v.append(sibling)
-
- ### regardless of match or not, check any children for matches
- if sibling.getFirstChild():
- sibling.getFirstChild().doWorkForFindAll(v,target,partialMatch)
-
- sibling = sibling.getNextSibling()
-
- ### Is node t equal to 'self' in terms of token type and text?
- def equals(self,t):
- if not t:
- return False
- return self.getText() == t.getText() and self.getType() == t.getType()
-
- ### Is t an exact structural and equals() match of this tree. The
- ### 'self' reference is considered the start of a sibling list.
- ###
- def equalsList(self, t):
- return cmptree(self, t, partial=False)
-
- ### Is 't' a subtree of this list?
- ### The siblings of the root are NOT ignored.
- ###
- def equalsListPartial(self,t):
- return cmptree(self,t,partial=True)
-
- ### Is tree rooted at 'self' equal to 't'? The siblings
- ### of 'self' are ignored.
- ###
- def equalsTree(self, t):
- return self.equals(t) and \
- cmptree(self.getFirstChild(), t.getFirstChild(), partial=False)
-
- ### Is 't' a subtree of the tree rooted at 'self'? The siblings
- ### of 'self' are ignored.
- ###
- def equalsTreePartial(self, t):
- if not t:
- return True
- return self.equals(t) and cmptree(
- self.getFirstChild(), t.getFirstChild(), partial=True)
-
- ### Walk the tree looking for all exact subtree matches. Return
- ### an ASTEnumerator that lets the caller walk the list
- ### of subtree roots found herein.
- def findAll(self,target):
- roots = []
-
- ### the empty tree cannot result in an enumeration
- if not target:
- return None
- # find all matches recursively
- self.doWorkForFindAll(roots, target, False)
- return roots
-
- ### Walk the tree looking for all subtrees. Return
- ### an ASTEnumerator that lets the caller walk the list
- ### of subtree roots found herein.
- def findAllPartial(self,sub):
- roots = []
-
- ### the empty tree cannot result in an enumeration
- if not sub:
- return None
-
- self.doWorkForFindAll(roots, sub, True) ### find all matches recursively
- return roots
-
- ### Get the first child of this node None if not children
- def getFirstChild(self):
- return self.down
-
- ### Get the next sibling in line after this one
- def getNextSibling(self):
- return self.right
-
- ### Get the token text for this node
- def getText(self):
- return ""
-
- ### Get the token type for this node
- def getType(self):
- return 0
-
- def getLine(self):
- return 0
-
- def getColumn(self):
- return 0
-
- ### Remove all children */
- def removeChildren(self):
- self.down = None
-
- def setFirstChild(self,c):
- self.down = c
-
- def setNextSibling(self, n):
- self.right = n
-
- ### Set the token text for this node
- def setText(self, text):
- pass
-
- ### Set the token type for this node
- def setType(self, ttype):
- pass
-
- ### static
- def setVerboseStringConversion(verbose,names):
- verboseStringConversion = verbose
- tokenNames = names
- setVerboseStringConversion = staticmethod(setVerboseStringConversion)
-
- ### Return an array of strings that maps token ID to it's text.
- ## @since 2.7.3
- def getTokenNames():
- return tokenNames
-
- def toString(self):
- return self.getText()
-
- ### return tree as lisp string - sibling included
- def toStringList(self):
- ts = self.toStringTree()
- sib = self.getNextSibling()
- if sib:
- ts += sib.toStringList()
- return ts
-
- __str__ = toStringList
-
- ### return tree as string - siblings ignored
- def toStringTree(self):
- ts = ""
- kid = self.getFirstChild()
- if kid:
- ts += " ("
- ts += " " + self.toString()
- if kid:
- ts += kid.toStringList()
- ts += " )"
- return ts
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### CommonAST ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-### Common AST node implementation
-class CommonAST(BaseAST):
- def __init__(self,token=None):
- super(CommonAST,self).__init__()
- self.ttype = INVALID_TYPE
- self.text = "<no text>"
- self.line = 0
- self.column= 0
- self.initialize(token)
- #assert self.text
-
- ### Get the token text for this node
- def getText(self):
- return self.text
-
- ### Get the token type for this node
- def getType(self):
- return self.ttype
-
- ### Get the line for this node
- def getLine(self):
- return self.line
-
- ### Get the column for this node
- def getColumn(self):
- return self.column
-
- def initialize(self,*args):
- if not args:
- return
-
- arg0 = args[0]
-
- if isinstance(arg0,int):
- arg1 = args[1]
- self.setType(arg0)
- self.setText(arg1)
- return
-
- if isinstance(arg0,AST) or isinstance(arg0,Token):
- self.setText(arg0.getText())
- self.setType(arg0.getType())
- self.line = arg0.getLine()
- self.column = arg0.getColumn()
- return
-
- ### Set the token text for this node
- def setText(self,text_):
- assert is_string_type(text_)
- self.text = text_
-
- ### Set the token type for this node
- def setType(self,ttype_):
- assert isinstance(ttype_,int)
- self.ttype = ttype_
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### CommonASTWithHiddenTokens ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class CommonASTWithHiddenTokens(CommonAST):
-
- def __init__(self,*args):
- CommonAST.__init__(self,*args)
- self.hiddenBefore = None
- self.hiddenAfter = None
-
- def getHiddenAfter(self):
- return self.hiddenAfter
-
- def getHiddenBefore(self):
- return self.hiddenBefore
-
- def initialize(self,*args):
- CommonAST.initialize(self,*args)
- if args and isinstance(args[0],Token):
- assert isinstance(args[0],CommonHiddenStreamToken)
- self.hiddenBefore = args[0].getHiddenBefore()
- self.hiddenAfter = args[0].getHiddenAfter()
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### ASTPair ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class ASTPair(object):
- def __init__(self):
- self.root = None ### current root of tree
- self.child = None ### current child to which siblings are added
-
- ### Make sure that child is the last sibling */
- def advanceChildToEnd(self):
- if self.child:
- while self.child.getNextSibling():
- self.child = self.child.getNextSibling()
-
- ### Copy an ASTPair. Don't call it clone() because we want type-safety */
- def copy(self):
- tmp = ASTPair()
- tmp.root = self.root
- tmp.child = self.child
- return tmp
-
- def toString(self):
- r = ifelse(not root,"null",self.root.getText())
- c = ifelse(not child,"null",self.child.getText())
- return "[%s,%s]" % (r,c)
-
- __str__ = toString
- __repr__ = toString
-
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### ASTFactory ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class ASTFactory(object):
- def __init__(self,table=None):
- self._class = None
- self._classmap = ifelse(table,table,None)
-
- def create(self,*args):
- if not args:
- return self.create(INVALID_TYPE)
-
- arg0 = args[0]
- arg1 = None
- arg2 = None
-
- try:
- arg1 = args[1]
- arg2 = args[2]
- except:
- pass
-
- # ctor(int)
- if isinstance(arg0,int) and not arg2:
- ### get class for 'self' type
- c = self.getASTNodeType(arg0)
- t = self.create(c)
- if t:
- t.initialize(arg0, ifelse(arg1,arg1,""))
- return t
-
- # ctor(int,something)
- if isinstance(arg0,int) and arg2:
- t = self.create(arg2)
- if t:
- t.initialize(arg0,arg1)
- return t
-
- # ctor(AST)
- if isinstance(arg0,AST):
- t = self.create(arg0.getType())
- if t:
- t.initialize(arg0)
- return t
-
- # ctor(token)
- if isinstance(arg0,Token) and not arg1:
- ttype = arg0.getType()
- assert isinstance(ttype,int)
- t = self.create(ttype)
- if t:
- t.initialize(arg0)
- return t
-
- # ctor(token,class)
- if isinstance(arg0,Token) and arg1:
- assert isinstance(arg1,type)
- assert issubclass(arg1,AST)
- # this creates instance of 'arg1' using 'arg0' as
- # argument. Wow, that's magic!
- t = arg1(arg0)
- assert t and isinstance(t,AST)
- return t
-
- # ctor(class)
- if isinstance(arg0,type):
- ### next statement creates instance of type (!)
- t = arg0()
- assert isinstance(t,AST)
- return t
-
-
- def setASTNodeClass(self,className=None):
- if not className:
- return
- assert isinstance(className,type)
- assert issubclass(className,AST)
- self._class = className
-
- ### kind of misnomer - use setASTNodeClass instead.
- setASTNodeType = setASTNodeClass
-
- def getASTNodeClass(self):
- return self._class
-
-
-
- def getTokenTypeToASTClassMap(self):
- return self._classmap
-
- def setTokenTypeToASTClassMap(self,amap):
- self._classmap = amap
-
- def error(self, e):
- import sys
- print(e, file=sys.stderr)
-
- def setTokenTypeASTNodeType(self, tokenType, className):
- """
- Specify a mapping between a token type and a (AST) class.
- """
- if not self._classmap:
- self._classmap = {}
-
- if not className:
- try:
- del self._classmap[tokenType]
- except:
- pass
- else:
- ### here we should also perform actions to ensure that
- ### a. class can be loaded
- ### b. class is a subclass of AST
- ###
- assert isinstance(className,type)
- assert issubclass(className,AST) ## a & b
- ### enter the class
- self._classmap[tokenType] = className
-
- def getASTNodeType(self,tokenType):
- """
- For a given token type return the AST node type. First we
- lookup a mapping table, second we try _class
- and finally we resolve to "antlr.CommonAST".
- """
-
- # first
- if self._classmap:
- try:
- c = self._classmap[tokenType]
- if c:
- return c
- except:
- pass
- # second
- if self._class:
- return self._class
-
- # default
- return CommonAST
-
- ### methods that have been moved to file scope - just listed
- ### here to be somewhat consistent with original API
- def dup(self,t):
- return antlr.dup(t,self)
-
- def dupList(self,t):
- return antlr.dupList(t,self)
-
- def dupTree(self,t):
- return antlr.dupTree(t,self)
-
- ### methods moved to other classes
- ### 1. makeASTRoot -> Parser
- ### 2. addASTChild -> Parser
-
- ### non-standard: create alias for longish method name
- maptype = setTokenTypeASTNodeType
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### ASTVisitor ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-class ASTVisitor(object):
- def __init__(self,*args):
- pass
-
- def visit(self,ast):
- pass
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-### static methods and variables ###
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
-
-ASTNULL = ASTNULLType()
-
-### wh: moved from ASTFactory as there's nothing ASTFactory-specific
-### in this method.
-def make(*nodes):
- if not nodes:
- return None
-
- for i in range(0,len(nodes)):
- node = nodes[i]
- if node:
- assert isinstance(node,AST)
-
- root = nodes[0]
- tail = None
- if root:
- root.setFirstChild(None)
-
- for i in range(1,len(nodes)):
- if not nodes[i]:
- continue
- if not root:
- root = tail = nodes[i]
- elif not tail:
- root.setFirstChild(nodes[i])
- tail = root.getFirstChild()
- else:
- tail.setNextSibling(nodes[i])
- tail = tail.getNextSibling()
-
- ### Chase tail to last sibling
- while tail.getNextSibling():
- tail = tail.getNextSibling()
- return root
-
-def dup(t,factory):
- if not t:
- return None
-
- if factory:
- dup_t = factory.create(t.__class__)
- else:
- raise TypeError("dup function requires ASTFactory argument")
- dup_t.initialize(t)
- return dup_t
-
-def dupList(t,factory):
- result = dupTree(t,factory)
- nt = result
- while t:
- ## for each sibling of the root
- t = t.getNextSibling()
- nt.setNextSibling(dupTree(t,factory))
- nt = nt.getNextSibling()
- return result
-
-def dupTree(t,factory):
- result = dup(t,factory)
- if t:
- result.setFirstChild(dupList(t.getFirstChild(),factory))
- return result
-
-###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-### $Id: antlr.py 3750 2009-02-13 00:13:04Z sjmachin $
-
-# Local Variables: ***
-# mode: python ***
-# py-indent-offset: 4 ***
-# End: ***