mirror of
https://github.com/kennethreitz/tablib.git
synced 2026-06-05 15:00:19 +00:00
Compare commits
257 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a26d782e88 | |||
| f5c0c5c34d | |||
| d9aee8e605 | |||
| 315a082b70 | |||
| 120ce9fcd6 | |||
| 914a82eac9 | |||
| 3931bcb4e6 | |||
| 471e56c387 | |||
| 8553dbc040 | |||
| 96c93871cf | |||
| a54949bc08 | |||
| ed686c2391 | |||
| 143677be77 | |||
| b2c35c2543 | |||
| 9dfd9d0c8e | |||
| 140e23c980 | |||
| ac797f1eda | |||
| 7c90595364 | |||
| 38ac98fdb2 | |||
| 07c7d172d9 | |||
| 9c7707be60 | |||
| 14bee65208 | |||
| 4fc5e0655d | |||
| da2e670d0d | |||
| 5912bf4870 | |||
| 28e9d7e23e | |||
| 930d38cf5a | |||
| 5e433c263d | |||
| 19ac9b9716 | |||
| 6feb59504a | |||
| 817eedd6f5 | |||
| 4d1c5a9996 | |||
| 520a1986d7 | |||
| 1ea793112c | |||
| 41a7a5d329 | |||
| c4edaa2ca8 | |||
| c612bb3dae | |||
| c223dfbdf1 | |||
| 49bd48b016 | |||
| c6d90bc825 | |||
| bcd0e37a65 | |||
| 8c92e878a3 | |||
| da2b011358 | |||
| a8b0bf4b5f | |||
| 6574d3e58b | |||
| 1020799828 | |||
| 333e73f892 | |||
| bfe70066b8 | |||
| fbfbe01b70 | |||
| 06a394ea5c | |||
| 9427decdb0 | |||
| fb59035f8d | |||
| 187d12cffc | |||
| eaa4de7793 | |||
| d479c5735a | |||
| 96668bb393 | |||
| b369baba40 | |||
| 25f846a78a | |||
| 22fe18239f | |||
| 149bafa97b | |||
| 9f7fec2379 | |||
| 762ac39e27 | |||
| 2a7aa959b3 | |||
| d85523b6a6 | |||
| 6407afba3e | |||
| 25a5bcea0c | |||
| 7aada68952 | |||
| 5ba92b0f6b | |||
| f58d4b67dc | |||
| a310ab7a09 | |||
| 7f2f925ddb | |||
| 3fc898e222 | |||
| de46f45e2e | |||
| 392eaac299 | |||
| 3a9c3944cf | |||
| 8c402da729 | |||
| 8feb6e8ddf | |||
| 9072b6ddae | |||
| 9f26c23eb5 | |||
| 8136f4b09e | |||
| 7e7ad73ddd | |||
| f889910629 | |||
| 969d9d957d | |||
| 86d84b555d | |||
| 66867527d2 | |||
| 7505d8d985 | |||
| d5515c17b8 | |||
| 07ac723971 | |||
| 5d7843ea59 | |||
| b5f0cf9d37 | |||
| a73bbe1645 | |||
| f1bdf43aab | |||
| 7623bfe7b0 | |||
| 59ccc0b422 | |||
| 99154aa6d6 | |||
| 65836d5ace | |||
| 4117503ed5 | |||
| dfa26a7d53 | |||
| 4f035caf1b | |||
| a9c7a5067d | |||
| 80cb42e8dd | |||
| 8d7e5732cd | |||
| 942dd3dadf | |||
| b1d282744c | |||
| 4c0c879d65 | |||
| cab63e02c8 | |||
| 63d025888a | |||
| 5a993ac281 | |||
| 666dd1d2c7 | |||
| ac1666e3ae | |||
| 5b7e817db2 | |||
| f9c168e4bc | |||
| 82f3d84c7d | |||
| 121cf46aec | |||
| 4bb4a05bcb | |||
| e52b8dd329 | |||
| 93fb89b8b6 | |||
| c01b66a16a | |||
| c3fa29a166 | |||
| 8d6a52aaf5 | |||
| 703b1da04c | |||
| 0e6bd079cc | |||
| 579dbf0cc0 | |||
| fbabb430ca | |||
| b8f923f8c5 | |||
| fbe6fe1612 | |||
| 17e90e71e5 | |||
| dc21825f34 | |||
| 7364995eaa | |||
| 3407170b99 | |||
| dd13744c92 | |||
| 31e4c39762 | |||
| 4fc70957ac | |||
| 7f17ccf445 | |||
| fbcc3b60af | |||
| 9b3268f0ad | |||
| f386ef8ac8 | |||
| e8f5e023c4 | |||
| 81445aeec8 | |||
| f94a236122 | |||
| bfbb7c626f | |||
| be0f77f9ee | |||
| 3b44349090 | |||
| 04a16afa58 | |||
| a8632125dc | |||
| ccf2ebcde2 | |||
| 2c60ce9233 | |||
| 649c7e8bb7 | |||
| 2d3dc5ef71 | |||
| efc516f366 | |||
| b2a51fd941 | |||
| d54d70bc22 | |||
| 391ad61bef | |||
| 99a45814d1 | |||
| fad3546614 | |||
| 7ba2849829 | |||
| 7ec0f2ef07 | |||
| bd470684a4 | |||
| dbcea81c17 | |||
| 49dc4a249e | |||
| 7cd82f956f | |||
| 13c3e537fd | |||
| f913853cae | |||
| ea1de420a3 | |||
| d0c8df95a3 | |||
| bb4e97f8aa | |||
| ffaeb64639 | |||
| f31ec562b4 | |||
| 68d7204b2d | |||
| 52db1ddc3e | |||
| 4755020dd7 | |||
| 5468dd7e67 | |||
| 8673710ddb | |||
| f01cf184d4 | |||
| 1482ca4a19 | |||
| 93c6c39581 | |||
| a0cb44cc43 | |||
| b2cd061773 | |||
| 876b849950 | |||
| 40c9e09578 | |||
| 9f5379fcc7 | |||
| 9ecc57dbf7 | |||
| a7471f7302 | |||
| 70211b71e0 | |||
| ddf4b441b0 | |||
| a0509126e0 | |||
| ec5b1cf3e0 | |||
| 3fb729aac6 | |||
| 647f69044f | |||
| 3da34af76f | |||
| 5b42824871 | |||
| 89209b6bd3 | |||
| 9362d3283b | |||
| 123851a737 | |||
| 54973c276c | |||
| 275ac9d194 | |||
| 4ecd5888af | |||
| 359f12c83c | |||
| de8d76fdae | |||
| f188e3dd87 | |||
| 3dff8f5b79 | |||
| c24d2dd45d | |||
| 4e98563483 | |||
| ca17c9f965 | |||
| 41c4fcc59f | |||
| e9166b14fd | |||
| a5528d731e | |||
| 1a122f2a4d | |||
| e9d9350e43 | |||
| ac4b568cba | |||
| 8be372b8cc | |||
| f8d8d3058a | |||
| d03ba7e532 | |||
| 35102ab951 | |||
| b8587e5cb0 | |||
| da4f2013f1 | |||
| ff069b1604 | |||
| 2994a9fc0d | |||
| 310400af5b | |||
| d52537b75b | |||
| 40490d1ba5 | |||
| 9f025dc111 | |||
| 335e3b1134 | |||
| 6b4afc38d1 | |||
| bd3099897c | |||
| 4b6fbe9225 | |||
| f22357f1bc | |||
| 37ffbc71c0 | |||
| 6f7c64eb03 | |||
| 89be8f402f | |||
| 607ea4a8aa | |||
| 7044896d56 | |||
| 8fca234388 | |||
| 0862b35905 | |||
| e8bf07da1a | |||
| 5c70fe0a07 | |||
| 6c37412c76 | |||
| 54a83602e4 | |||
| f486b77a7a | |||
| fecfecfd16 | |||
| 9a65b8deed | |||
| 61231b38ac | |||
| b7a8b65c00 | |||
| 6dd71c8830 | |||
| 8d44ad8a12 | |||
| 1850a934aa | |||
| ee953512b7 | |||
| 6405ec3baf | |||
| ea64e4cfac | |||
| 0bea48ccc3 | |||
| 687670762f | |||
| 254ce62b2a | |||
| 2b3f277138 | |||
| a2f59584e4 | |||
| 4d3a31e19f | |||
| 95c98861da | |||
| 59d1f9fded |
+7
-2
@@ -1,10 +1,11 @@
|
||||
# application builds
|
||||
build/*
|
||||
dist/*
|
||||
MANIFEST
|
||||
|
||||
# python skin
|
||||
.pyc
|
||||
.pyo
|
||||
*.pyc
|
||||
*.pyo
|
||||
|
||||
# osx noise
|
||||
.DS_Store
|
||||
@@ -13,3 +14,7 @@ profile
|
||||
# pycharm noise
|
||||
.idea
|
||||
.idea/*
|
||||
|
||||
# vi noise
|
||||
*.swp
|
||||
docs/_build/*
|
||||
@@ -1,4 +1,4 @@
|
||||
GistAPI.py is written and maintained by Kenneth Reitz and
|
||||
Tablib is written and maintained by Kenneth Reitz and
|
||||
various contributors:
|
||||
|
||||
Development Lead
|
||||
@@ -10,4 +10,5 @@ Development Lead
|
||||
Patches and Suggestions
|
||||
```````````````````````
|
||||
|
||||
- A Lucky Someone
|
||||
- Luke Lee
|
||||
- Josh Ourisman
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
History
|
||||
=======
|
||||
|
||||
0.8.5 (2010-10-06)
|
||||
------------------
|
||||
|
||||
* New import system. All dependencies attempt to load from site-packages,
|
||||
then fallback on vendorized modules.
|
||||
|
||||
|
||||
0.8.4 (2010-10-04)
|
||||
------------------
|
||||
|
||||
* Upated XLS output: Only wrap if '\n' in cell.
|
||||
|
||||
|
||||
0.8.3 (2010-10-04)
|
||||
------------------
|
||||
|
||||
* Ability to append new column passing a callable
|
||||
as the value that will be applied to every row.
|
||||
|
||||
|
||||
0.8.2 (2010-10-04)
|
||||
------------------
|
||||
|
||||
* Added alignment wrapping to written cells.
|
||||
* Added separator support to XLS.
|
||||
|
||||
|
||||
0.8.1 (2010-09-28)
|
||||
------------------
|
||||
* Packaging Fix
|
||||
|
||||
|
||||
0.8.0 (2010-09-25)
|
||||
------------------
|
||||
* New format plugin system!
|
||||
* Imports! ELEGANT Imports!
|
||||
* Tests. Lots of tests.
|
||||
|
||||
|
||||
0.7.1 (2010-09-20)
|
||||
------------------
|
||||
|
||||
* Reverting methods back to properties.
|
||||
* Windows bug compenated in documentation.
|
||||
|
||||
|
||||
0.7.0 (2010-09-20)
|
||||
------------------
|
||||
|
||||
* Renamed DataBook Databook for consistiency.
|
||||
* Export properties changed to methods (XLS filename / StringIO bug).
|
||||
* Optional Dataset.xls(path='filename') support (for writing on windows).
|
||||
* Added utf-8 on the worksheet level.
|
||||
|
||||
|
||||
0.6.4 (2010-09-19)
|
||||
------------------
|
||||
|
||||
* Updated unicode export for XLS.
|
||||
* More exhaustive unit tests.
|
||||
|
||||
|
||||
0.6.3 (2010-09-14)
|
||||
------------------
|
||||
* Added Dataset.append() support for columns.
|
||||
|
||||
|
||||
0.6.2 (2010-09-13)
|
||||
------------------
|
||||
* Fixed Dataset.append() error on empty dataset.
|
||||
* Updated Dataset.headers property w/ validation.
|
||||
* Added Testing Fixtures.
|
||||
|
||||
0.6.1 (2010-09-12)
|
||||
------------------
|
||||
|
||||
* Packaging hotfixes.
|
||||
|
||||
|
||||
0.6.0 (2010-09-11)
|
||||
------------------
|
||||
|
||||
* Public Release.
|
||||
* Export Support for XLS, JSON, YAML, and CSV.
|
||||
* DataBook Export for XLS, JSON, and YAML.
|
||||
* Python Dict Property Support.
|
||||
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
include HISTORY.rst README.rst tabbed
|
||||
include HISTORY.rst README.rst LICENSE AUTHORS
|
||||
@@ -0,0 +1,136 @@
|
||||
Tablib includes some vendorized python libraries: pyyaml, simplejson, and xlwt.
|
||||
|
||||
|
||||
|
||||
PyYAML License
|
||||
==============
|
||||
|
||||
Copyright (c) 2006 Kirill Simonov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
|
||||
SimpleJSON License
|
||||
==================
|
||||
|
||||
Copyright (c) 2006 Bob Ippolito
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
|
||||
|
||||
XLWT 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
|
||||
+150
-59
@@ -1,97 +1,188 @@
|
||||
Tabbed: format-agnostic tabular dataset library
|
||||
Tablib: format-agnostic tabular dataset library
|
||||
===============================================
|
||||
|
||||
::
|
||||
|
||||
_____ ______ ______ _________
|
||||
__ /_______ ____ /_ ___ /_ _____ ______ /
|
||||
_ __/_ __ `/__ __ \__ __ \_ _ \_ __ /
|
||||
/ /_ / /_/ / _ /_/ /_ /_/ // __// /_/ /
|
||||
\__/ \__,_/ /_.___/ /_.___/ \___/ \__,_/
|
||||
|
||||
*Tabbed is under active documentation-driven development.*
|
||||
_____ ______ ___________ ______
|
||||
__ /_______ ____ /_ ___ /___(_)___ /_
|
||||
_ __/_ __ `/__ __ \__ / __ / __ __ \
|
||||
/ /_ / /_/ / _ /_/ /_ / _ / _ /_/ /
|
||||
\__/ \__,_/ /_.___/ /_/ /_/ /_.___/
|
||||
|
||||
|
||||
Tabbed is a format-agnostic tabular dataset library, written in Python.
|
||||
It is a full python module which doubles as a CLI application for quick
|
||||
dataset conversions.
|
||||
|
||||
Formats supported:
|
||||
Tablib is a format-agnostic tabular dataset library, written in Python.
|
||||
|
||||
- JSON
|
||||
- YAML
|
||||
- Excel
|
||||
- CSV
|
||||
- HTML
|
||||
Output formats supported:
|
||||
|
||||
Please note that tabbed *purposefully* excludes XML support. It always will.
|
||||
- Excel (Sets + Books)
|
||||
- JSON (Sets + Books)
|
||||
- YAML (Sets + Books)
|
||||
- CSV (Sets)
|
||||
|
||||
Import formats supported:
|
||||
|
||||
Features
|
||||
- JSON (Sets + Books)
|
||||
- YAML (Sets + Books)
|
||||
- CSV (Sets)
|
||||
|
||||
Note that tablib *purposefully* excludes XML support. It always will.
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
Convert datafile formats via API: ::
|
||||
`tablib.Dataset()`
|
||||
A Dataset is a table of tabular data. It may or may not have a header row. They can be build and maniuplated as raw Python datatypes (Lists of tuples|dictonaries). Datasets can be imported from JSON, YAML, and CSV; they can be exported to Excel (XLS), JSON, YAML, and CSV.
|
||||
|
||||
`tablib.Databook()`
|
||||
A Databook is a set of Datasets. The most common form of a Databook is an Excel file with multiple spreadsheets. Databooks can be imported from JSON and YAML; they can be exported to Excel (XLS), JSON, and YAML.
|
||||
|
||||
tablib.import(filename='data.csv').export('data.json')
|
||||
Usage
|
||||
-----
|
||||
|
||||
|
||||
Convert datafile formats via CLI: ::
|
||||
|
||||
$ tabbed data.csv data.json
|
||||
|
||||
Convert data formats via CLI pipe interface: ::
|
||||
|
||||
$ curl http://domain.dev/dataset.json | tabbed --to excel | gist -p
|
||||
|
||||
|
||||
Populate fresh data files: ::
|
||||
|
||||
headers = ('first_name', 'last_name', 'gpa')
|
||||
headers = ('first_name', 'last_name')
|
||||
|
||||
data = [
|
||||
('John', 'Adams', 4.0),
|
||||
('George', 'Washington', 2.6),
|
||||
('Henry', 'Ford', 2.3)
|
||||
('John', 'Adams'),
|
||||
('George', 'Washington')
|
||||
]
|
||||
|
||||
data = tablib.Data(*data, headers=headers)
|
||||
data = tablib.Dataset(*data, headers=headers)
|
||||
|
||||
# Establish file location and save
|
||||
data.save('test.xls')
|
||||
|
||||
|
||||
Intelligently add new rows: ::
|
||||
|
||||
data.add_row('Bob', 'Dylan')
|
||||
# >>> Warning: Existing column count is 3
|
||||
|
||||
print data.headers
|
||||
# >>> ('first_name', 'last_name', 'gpa')
|
||||
|
||||
>>> data.append(('Henry', 'Ford'))
|
||||
|
||||
Intelligently add new columns: ::
|
||||
|
||||
>>> data.append(col=('age', 90, 67, 83))
|
||||
|
||||
Slice rows: ::
|
||||
|
||||
print data[0:1]
|
||||
# >>> [('John', 'Adams', 4.0), ('George', 'Washington', 2.6)]
|
||||
>>> print data[:2]
|
||||
[('John', 'Adams', 90), ('George', 'Washington', 67)]
|
||||
|
||||
|
||||
Slice columns by header: ::
|
||||
|
||||
print data['first_name']
|
||||
# >>> ['John', 'George', 'Henry']
|
||||
>>> print data['first_name']
|
||||
['John', 'George', 'Henry']
|
||||
|
||||
Easily delete rows: ::
|
||||
|
||||
>>> del data[1]
|
||||
|
||||
Exports
|
||||
-------
|
||||
|
||||
Drumroll please...........
|
||||
|
||||
JSON!
|
||||
+++++
|
||||
::
|
||||
|
||||
>>> print data.json
|
||||
[
|
||||
{
|
||||
"last_name": "Adams",
|
||||
"age": 90,
|
||||
"first_name": "John"
|
||||
},
|
||||
{
|
||||
"last_name": "Ford",
|
||||
"age": 83,
|
||||
"first_name": "Henry"
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
YAML!
|
||||
+++++
|
||||
::
|
||||
|
||||
>>> print data.yaml
|
||||
- {age: 90, first_name: John, last_name: Adams}
|
||||
- {age: 83, first_name: Henry, last_name: Ford}
|
||||
|
||||
CSV...
|
||||
++++++
|
||||
::
|
||||
|
||||
>>> print data.csv
|
||||
first_name,last_name,age
|
||||
John,Adams,90
|
||||
Henry,Ford,83
|
||||
|
||||
EXCEL!
|
||||
++++++
|
||||
::
|
||||
|
||||
>>> open('people.xls', 'wb').write(data.xls)
|
||||
|
||||
It's that easy.
|
||||
|
||||
Imports!
|
||||
--------
|
||||
|
||||
JSON
|
||||
++++
|
||||
|
||||
::
|
||||
|
||||
>>> data.json = '[{"last_name": "Adams","age": 90,"first_name": "John"}]'
|
||||
>>> print data[0]
|
||||
('John', 'Adams', 90)
|
||||
|
||||
|
||||
YAML
|
||||
++++
|
||||
::
|
||||
|
||||
>>> data.yaml = '- {age: 90, first_name: John, last_name: Adams}'
|
||||
>>> print data[0]
|
||||
('John', 'Adams', 90)
|
||||
|
||||
CSV
|
||||
+++
|
||||
::
|
||||
|
||||
>>> data.csv = 'age, first_name, last_name\n90, John, Adams'
|
||||
>>> print data[0]
|
||||
('John', 'Adams', 90)
|
||||
|
||||
>>> print data.yaml
|
||||
- {age: 90, first_name: John, last_name: Adams}
|
||||
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
To install tablib, simply: ::
|
||||
|
||||
$ pip install tablib
|
||||
|
||||
Or, if you absolutely must: ::
|
||||
|
||||
$ easy_install tablib
|
||||
|
||||
|
||||
Manipulate rows by index: ::
|
||||
Contribute
|
||||
----------
|
||||
|
||||
data.delRow(0)
|
||||
print data[0:1]
|
||||
# >>> [('George', 'Washington', 2.6), ('Henry', 'Ford', 2.3)]
|
||||
|
||||
# Update saved file
|
||||
data.save()
|
||||
|
||||
If you'd like to contribute, simply fork `the repository`_, commit your changes to the **develop** branch (or branch off of it), and send a pull request. Make sure you add yourself to AUTHORS_.
|
||||
|
||||
Export to various formats: ::
|
||||
|
||||
# Save copy as CSV
|
||||
data.export('backup.csv')
|
||||
Roadmap
|
||||
-------
|
||||
- Release CLI Interface
|
||||
- Auto-detect import format
|
||||
- Add possible other exports (SQL?)
|
||||
- Ability to assign types to rows (set, regex=, &c.)
|
||||
|
||||
.. _`the repository`: http://github.com/kennethreitz/tablib
|
||||
.. _AUTHORS: http://github.com/kennethreitz/tablib/blob/master/AUTHORS
|
||||
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = _build
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Tablib.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Tablib.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/Tablib"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Tablib"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
make -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
@@ -0,0 +1,3 @@
|
||||
*.pyc
|
||||
*.pyo
|
||||
.DS_Store
|
||||
Vendored
+45
@@ -0,0 +1,45 @@
|
||||
Modifications:
|
||||
|
||||
Copyright (c) 2010 Kenneth Reitz.
|
||||
|
||||
|
||||
Original Project:
|
||||
|
||||
Copyright (c) 2010 by Armin Ronacher.
|
||||
|
||||
|
||||
Some rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms of the theme, with or
|
||||
without modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* 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.
|
||||
|
||||
* The names of the contributors may not be used to endorse or
|
||||
promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
We kindly ask you to only use these themes in an unmodified manner just
|
||||
for Flask and Flask-related products, not for unrelated projects. If you
|
||||
like the visual style and want to use it for your own projects, please
|
||||
consider making some larger changes to the themes (such as changing
|
||||
font faces, sizes, colors or margins).
|
||||
|
||||
THIS THEME 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 THEME, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
krTheme Sphinx Style
|
||||
====================
|
||||
|
||||
This repository contains sphinx styles Kenneth Reitz uses in most of
|
||||
his projects. It is a drivative of Mitsuhiko's themes for Flask and Flask related
|
||||
projects. To use this style in your Sphinx documentation, follow
|
||||
this guide:
|
||||
|
||||
1. put this folder as _themes into your docs folder. Alternatively
|
||||
you can also use git submodules to check out the contents there.
|
||||
|
||||
2. add this to your conf.py: ::
|
||||
|
||||
sys.path.append(os.path.abspath('_themes'))
|
||||
html_theme_path = ['_themes']
|
||||
html_theme = 'flask'
|
||||
|
||||
The following themes exist:
|
||||
|
||||
**kr**
|
||||
the standard flask documentation theme for large projects
|
||||
|
||||
**kr_small**
|
||||
small one-page theme. Intended to be used by very small addon libraries.
|
||||
|
||||
Vendored
+86
@@ -0,0 +1,86 @@
|
||||
# flasky extensions. flasky pygments style based on tango style
|
||||
from pygments.style import Style
|
||||
from pygments.token import Keyword, Name, Comment, String, Error, \
|
||||
Number, Operator, Generic, Whitespace, Punctuation, Other, Literal
|
||||
|
||||
|
||||
class FlaskyStyle(Style):
|
||||
background_color = "#f8f8f8"
|
||||
default_style = ""
|
||||
|
||||
styles = {
|
||||
# No corresponding class for the following:
|
||||
#Text: "", # class: ''
|
||||
Whitespace: "underline #f8f8f8", # class: 'w'
|
||||
Error: "#a40000 border:#ef2929", # class: 'err'
|
||||
Other: "#000000", # class 'x'
|
||||
|
||||
Comment: "italic #8f5902", # class: 'c'
|
||||
Comment.Preproc: "noitalic", # class: 'cp'
|
||||
|
||||
Keyword: "bold #004461", # class: 'k'
|
||||
Keyword.Constant: "bold #004461", # class: 'kc'
|
||||
Keyword.Declaration: "bold #004461", # class: 'kd'
|
||||
Keyword.Namespace: "bold #004461", # class: 'kn'
|
||||
Keyword.Pseudo: "bold #004461", # class: 'kp'
|
||||
Keyword.Reserved: "bold #004461", # class: 'kr'
|
||||
Keyword.Type: "bold #004461", # class: 'kt'
|
||||
|
||||
Operator: "#582800", # class: 'o'
|
||||
Operator.Word: "bold #004461", # class: 'ow' - like keywords
|
||||
|
||||
Punctuation: "bold #000000", # class: 'p'
|
||||
|
||||
# because special names such as Name.Class, Name.Function, etc.
|
||||
# are not recognized as such later in the parsing, we choose them
|
||||
# to look the same as ordinary variables.
|
||||
Name: "#000000", # class: 'n'
|
||||
Name.Attribute: "#c4a000", # class: 'na' - to be revised
|
||||
Name.Builtin: "#004461", # class: 'nb'
|
||||
Name.Builtin.Pseudo: "#3465a4", # class: 'bp'
|
||||
Name.Class: "#000000", # class: 'nc' - to be revised
|
||||
Name.Constant: "#000000", # class: 'no' - to be revised
|
||||
Name.Decorator: "#888", # class: 'nd' - to be revised
|
||||
Name.Entity: "#ce5c00", # class: 'ni'
|
||||
Name.Exception: "bold #cc0000", # class: 'ne'
|
||||
Name.Function: "#000000", # class: 'nf'
|
||||
Name.Property: "#000000", # class: 'py'
|
||||
Name.Label: "#f57900", # class: 'nl'
|
||||
Name.Namespace: "#000000", # class: 'nn' - to be revised
|
||||
Name.Other: "#000000", # class: 'nx'
|
||||
Name.Tag: "bold #004461", # class: 'nt' - like a keyword
|
||||
Name.Variable: "#000000", # class: 'nv' - to be revised
|
||||
Name.Variable.Class: "#000000", # class: 'vc' - to be revised
|
||||
Name.Variable.Global: "#000000", # class: 'vg' - to be revised
|
||||
Name.Variable.Instance: "#000000", # class: 'vi' - to be revised
|
||||
|
||||
Number: "#990000", # class: 'm'
|
||||
|
||||
Literal: "#000000", # class: 'l'
|
||||
Literal.Date: "#000000", # class: 'ld'
|
||||
|
||||
String: "#4e9a06", # class: 's'
|
||||
String.Backtick: "#4e9a06", # class: 'sb'
|
||||
String.Char: "#4e9a06", # class: 'sc'
|
||||
String.Doc: "italic #8f5902", # class: 'sd' - like a comment
|
||||
String.Double: "#4e9a06", # class: 's2'
|
||||
String.Escape: "#4e9a06", # class: 'se'
|
||||
String.Heredoc: "#4e9a06", # class: 'sh'
|
||||
String.Interpol: "#4e9a06", # class: 'si'
|
||||
String.Other: "#4e9a06", # class: 'sx'
|
||||
String.Regex: "#4e9a06", # class: 'sr'
|
||||
String.Single: "#4e9a06", # class: 's1'
|
||||
String.Symbol: "#4e9a06", # class: 'ss'
|
||||
|
||||
Generic: "#000000", # class: 'g'
|
||||
Generic.Deleted: "#a40000", # class: 'gd'
|
||||
Generic.Emph: "italic #000000", # class: 'ge'
|
||||
Generic.Error: "#ef2929", # class: 'gr'
|
||||
Generic.Heading: "bold #000080", # class: 'gh'
|
||||
Generic.Inserted: "#00A000", # class: 'gi'
|
||||
Generic.Output: "#888", # class: 'go'
|
||||
Generic.Prompt: "#745334", # class: 'gp'
|
||||
Generic.Strong: "bold #000000", # class: 'gs'
|
||||
Generic.Subheading: "bold #800080", # class: 'gu'
|
||||
Generic.Traceback: "bold #a40000", # class: 'gt'
|
||||
}
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
{%- extends "basic/layout.html" %}
|
||||
{%- block extrahead %}
|
||||
{{ super() }}
|
||||
{% if theme_touch_icon %}
|
||||
<link rel="apple-touch-icon" href="{{ pathto('_static/' ~ theme_touch_icon, 1) }}" />
|
||||
{% endif %}
|
||||
<link media="only screen and (max-device-width: 480px)" href="{{
|
||||
pathto('_static/small_flask.css', 1) }}" type= "text/css" rel="stylesheet" />
|
||||
{% endblock %}
|
||||
{%- block relbar2 %}{% endblock %}
|
||||
{%- block footer %}
|
||||
<div class="footer">
|
||||
© Copyright {{ copyright }}.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
|
||||
</div>
|
||||
{%- endblock %}
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="{{ pathto(master_doc) }}">Documentation overview</a><ul>
|
||||
{%- for parent in parents %}
|
||||
<li><a href="{{ parent.link|e }}">{{ parent.title }}</a><ul>
|
||||
{%- endfor %}
|
||||
{%- if prev %}
|
||||
<li>Previous: <a href="{{ prev.link|e }}" title="{{ _('previous chapter')
|
||||
}}">{{ prev.title }}</a></li>
|
||||
{%- endif %}
|
||||
{%- if next %}
|
||||
<li>Next: <a href="{{ next.link|e }}" title="{{ _('next chapter')
|
||||
}}">{{ next.title }}</a></li>
|
||||
{%- endif %}
|
||||
{%- for parent in parents %}
|
||||
</ul></li>
|
||||
{%- endfor %}
|
||||
</ul></li>
|
||||
</ul>
|
||||
Vendored
+387
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* flasky.css_t
|
||||
* ~~~~~~~~~~~~
|
||||
*
|
||||
* :copyright: Copyright 2010 by Armin Ronacher. Modifications by Kenneth Reitz.
|
||||
* :license: Flask Design License, see LICENSE for details.
|
||||
*/
|
||||
|
||||
{% set page_width = '940px' %}
|
||||
{% set sidebar_width = '220px' %}
|
||||
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
body {
|
||||
font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro';
|
||||
font-size: 17px;
|
||||
background-color: white;
|
||||
color: #000;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.document {
|
||||
width: {{ page_width }};
|
||||
margin: 30px auto 0 auto;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 0 0 {{ sidebar_width }};
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
width: {{ sidebar_width }};
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid #B1B4B6;
|
||||
}
|
||||
|
||||
div.body {
|
||||
background-color: #ffffff;
|
||||
color: #3E4349;
|
||||
padding: 0 30px 0 30px;
|
||||
}
|
||||
|
||||
img.floatingflask {
|
||||
padding: 0 0 10px 10px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
width: {{ page_width }};
|
||||
margin: 20px auto 30px auto;
|
||||
font-size: 14px;
|
||||
color: #888;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
div.related {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: #444;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dotted #999;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a:hover {
|
||||
border-bottom: 1px solid #999;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
padding: 18px 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper p.logo {
|
||||
padding: 0 0 20px 0;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3,
|
||||
div.sphinxsidebar h4 {
|
||||
font-family: 'Garamond', 'Georgia', serif;
|
||||
color: #444;
|
||||
font-size: 24px;
|
||||
font-weight: normal;
|
||||
margin: 0 0 5px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h4 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 a {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.logo a,
|
||||
div.sphinxsidebar h3 a,
|
||||
div.sphinxsidebar p.logo a:hover,
|
||||
div.sphinxsidebar h3 a:hover {
|
||||
border: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p {
|
||||
color: #555;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
margin: 10px 0;
|
||||
padding: 0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #ccc;
|
||||
font-family: 'Georgia', serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
a {
|
||||
color: #004B6B;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #6D4100;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6 {
|
||||
font-family: 'Garamond', 'Georgia', serif;
|
||||
font-weight: normal;
|
||||
margin: 30px 0px 10px 0px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
|
||||
div.body h2 { font-size: 180%; }
|
||||
div.body h3 { font-size: 150%; }
|
||||
div.body h4 { font-size: 130%; }
|
||||
div.body h5 { font-size: 100%; }
|
||||
div.body h6 { font-size: 100%; }
|
||||
|
||||
a.headerlink {
|
||||
color: #ddd;
|
||||
padding: 0 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
color: #444;
|
||||
background: #eaeaea;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li {
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
div.admonition {
|
||||
background: #fafafa;
|
||||
margin: 20px -30px;
|
||||
padding: 10px 30px;
|
||||
border-top: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.admonition tt.xref, div.admonition a tt {
|
||||
border-bottom: 1px solid #fafafa;
|
||||
}
|
||||
|
||||
dd div.admonition {
|
||||
margin-left: -60px;
|
||||
padding-left: 60px;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title {
|
||||
font-family: 'Garamond', 'Georgia', serif;
|
||||
font-weight: normal;
|
||||
font-size: 24px;
|
||||
margin: 0 0 10px 0;
|
||||
padding: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
div.admonition p.last {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.highlight {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
dt:target, .highlight {
|
||||
background: #FAF3E8;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #eee;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #ffc;
|
||||
border: 1px solid #ff6;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
pre, tt {
|
||||
font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
img.screenshot {
|
||||
}
|
||||
|
||||
tt.descname, tt.descclassname {
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
tt.descname {
|
||||
padding-right: 0.08em;
|
||||
}
|
||||
|
||||
img.screenshot {
|
||||
-moz-box-shadow: 2px 2px 4px #eee;
|
||||
-webkit-box-shadow: 2px 2px 4px #eee;
|
||||
box-shadow: 2px 2px 4px #eee;
|
||||
}
|
||||
|
||||
table.docutils {
|
||||
border: 1px solid #888;
|
||||
-moz-box-shadow: 2px 2px 4px #eee;
|
||||
-webkit-box-shadow: 2px 2px 4px #eee;
|
||||
box-shadow: 2px 2px 4px #eee;
|
||||
}
|
||||
|
||||
table.docutils td, table.docutils th {
|
||||
border: 1px solid #888;
|
||||
padding: 0.25em 0.7em;
|
||||
}
|
||||
|
||||
table.field-list, table.footnote {
|
||||
border: none;
|
||||
-moz-box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
table.footnote {
|
||||
margin: 15px 0;
|
||||
width: 100%;
|
||||
border: 1px solid #eee;
|
||||
background: #fdfdfd;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
table.footnote + table.footnote {
|
||||
margin-top: -15px;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
table.field-list th {
|
||||
padding: 0 0.8em 0 0;
|
||||
}
|
||||
|
||||
table.field-list td {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.footnote td.label {
|
||||
width: 0px;
|
||||
padding: 0.3em 0 0.3em 0.5em;
|
||||
}
|
||||
|
||||
table.footnote td {
|
||||
padding: 0.3em 0.5em;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
dl dd {
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 0 30px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
margin: 10px 0 10px 30px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #eee;
|
||||
padding: 7px 30px;
|
||||
margin: 15px -30px;
|
||||
line-height: 1.3em;
|
||||
}
|
||||
|
||||
dl pre, blockquote pre, li pre {
|
||||
margin-left: -60px;
|
||||
padding-left: 60px;
|
||||
}
|
||||
|
||||
dl dl pre {
|
||||
margin-left: -90px;
|
||||
padding-left: 90px;
|
||||
}
|
||||
|
||||
tt {
|
||||
background-color: #ecf0f3;
|
||||
color: #222;
|
||||
/* padding: 1px 2px; */
|
||||
}
|
||||
|
||||
tt.xref, a tt {
|
||||
background-color: #FBFBFB;
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
|
||||
a.reference {
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dotted #004B6B;
|
||||
}
|
||||
|
||||
a.reference:hover {
|
||||
border-bottom: 1px solid #6D4100;
|
||||
}
|
||||
|
||||
a.footnote-reference {
|
||||
text-decoration: none;
|
||||
font-size: 0.7em;
|
||||
vertical-align: top;
|
||||
border-bottom: 1px dotted #004B6B;
|
||||
}
|
||||
|
||||
a.footnote-reference:hover {
|
||||
border-bottom: 1px solid #6D4100;
|
||||
}
|
||||
|
||||
a:hover tt {
|
||||
background: #EEE;
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* small_flask.css_t
|
||||
* ~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* :copyright: Copyright 2010 by Armin Ronacher.
|
||||
* :license: Flask Design License, see LICENSE for details.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 20px 30px;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: none;
|
||||
background: white;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
display: block;
|
||||
float: none;
|
||||
width: 102.5%;
|
||||
margin: 50px -30px -20px -30px;
|
||||
padding: 10px 20px;
|
||||
background: #333;
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p,
|
||||
div.sphinxsidebar h3 a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.logo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.document {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.related {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 10px 0 20px 0;
|
||||
}
|
||||
|
||||
div.related ul,
|
||||
div.related ul li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.body {
|
||||
min-height: 0;
|
||||
padding: 0;
|
||||
}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
[theme]
|
||||
inherit = basic
|
||||
stylesheet = flasky.css
|
||||
pygments_style = flask_theme_support.FlaskyStyle
|
||||
|
||||
[options]
|
||||
touch_icon =
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
{% extends "basic/layout.html" %}
|
||||
{% block header %}
|
||||
{{ super() }}
|
||||
{% if pagename == 'index' %}
|
||||
<div class=indexwrapper>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block footer %}
|
||||
{% if pagename == 'index' %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{# do not display relbars #}
|
||||
{% block relbar1 %}{% endblock %}
|
||||
{% block relbar2 %}
|
||||
{% if theme_github_fork %}
|
||||
<a href="http://github.com/{{ theme_github_fork }}"><img style="position: fixed; top: 0; right: 0; border: 0;"
|
||||
src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block sidebar1 %}{% endblock %}
|
||||
{% block sidebar2 %}{% endblock %}
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* flasky.css_t
|
||||
* ~~~~~~~~~~~~
|
||||
*
|
||||
* Sphinx stylesheet -- flasky theme based on nature theme.
|
||||
*
|
||||
* :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
body {
|
||||
font-family: 'Georgia', serif;
|
||||
font-size: 17px;
|
||||
color: #000;
|
||||
background: white;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 40px auto 0 auto;
|
||||
width: 700px;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid #B1B4B6;
|
||||
}
|
||||
|
||||
div.body {
|
||||
background-color: #ffffff;
|
||||
color: #3E4349;
|
||||
padding: 0 30px 30px 30px;
|
||||
}
|
||||
|
||||
img.floatingflask {
|
||||
padding: 0 0 10px 10px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
text-align: right;
|
||||
color: #888;
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
width: 650px;
|
||||
margin: 0 auto 40px auto;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: #888;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.related {
|
||||
line-height: 32px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
div.related ul {
|
||||
padding: 0 0 0 10px;
|
||||
}
|
||||
|
||||
div.related a {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
a {
|
||||
color: #004B6B;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #6D4100;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.body {
|
||||
padding-bottom: 40px; /* saved for footer */
|
||||
}
|
||||
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6 {
|
||||
font-family: 'Garamond', 'Georgia', serif;
|
||||
font-weight: normal;
|
||||
margin: 30px 0px 10px 0px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
{% if theme_index_logo %}
|
||||
div.indexwrapper h1 {
|
||||
text-indent: -999999px;
|
||||
background: url({{ theme_index_logo }}) no-repeat center center;
|
||||
height: {{ theme_index_logo_height }};
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
div.body h2 { font-size: 180%; }
|
||||
div.body h3 { font-size: 150%; }
|
||||
div.body h4 { font-size: 130%; }
|
||||
div.body h5 { font-size: 100%; }
|
||||
div.body h6 { font-size: 100%; }
|
||||
|
||||
a.headerlink {
|
||||
color: white;
|
||||
padding: 0 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
color: #444;
|
||||
background: #eaeaea;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li {
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
div.admonition {
|
||||
background: #fafafa;
|
||||
margin: 20px -30px;
|
||||
padding: 10px 30px;
|
||||
border-top: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title {
|
||||
font-family: 'Garamond', 'Georgia', serif;
|
||||
font-weight: normal;
|
||||
font-size: 24px;
|
||||
margin: 0 0 10px 0;
|
||||
padding: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
div.admonition p.last {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.highlight{
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
dt:target, .highlight {
|
||||
background: #FAF3E8;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #eee;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #ffc;
|
||||
border: 1px solid #ff6;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
background-color: #ffe4e4;
|
||||
border: 1px solid #f66;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
pre, tt {
|
||||
font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
img.screenshot {
|
||||
}
|
||||
|
||||
tt.descname, tt.descclassname {
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
tt.descname {
|
||||
padding-right: 0.08em;
|
||||
}
|
||||
|
||||
img.screenshot {
|
||||
-moz-box-shadow: 2px 2px 4px #eee;
|
||||
-webkit-box-shadow: 2px 2px 4px #eee;
|
||||
box-shadow: 2px 2px 4px #eee;
|
||||
}
|
||||
|
||||
table.docutils {
|
||||
border: 1px solid #888;
|
||||
-moz-box-shadow: 2px 2px 4px #eee;
|
||||
-webkit-box-shadow: 2px 2px 4px #eee;
|
||||
box-shadow: 2px 2px 4px #eee;
|
||||
}
|
||||
|
||||
table.docutils td, table.docutils th {
|
||||
border: 1px solid #888;
|
||||
padding: 0.25em 0.7em;
|
||||
}
|
||||
|
||||
table.field-list, table.footnote {
|
||||
border: none;
|
||||
-moz-box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
table.footnote {
|
||||
margin: 15px 0;
|
||||
width: 100%;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
|
||||
table.field-list th {
|
||||
padding: 0 0.8em 0 0;
|
||||
}
|
||||
|
||||
table.field-list td {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.footnote td {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
dl dd {
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 0;
|
||||
margin: 15px -30px;
|
||||
padding: 8px;
|
||||
line-height: 1.3em;
|
||||
padding: 7px 30px;
|
||||
background: #eee;
|
||||
border-radius: 2px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
}
|
||||
|
||||
dl pre {
|
||||
margin-left: -60px;
|
||||
padding-left: 60px;
|
||||
}
|
||||
|
||||
tt {
|
||||
background-color: #ecf0f3;
|
||||
color: #222;
|
||||
/* padding: 1px 2px; */
|
||||
}
|
||||
|
||||
tt.xref, a tt {
|
||||
background-color: #FBFBFB;
|
||||
}
|
||||
|
||||
a:hover tt {
|
||||
background: #EEE;
|
||||
}
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
[theme]
|
||||
inherit = basic
|
||||
stylesheet = flasky.css
|
||||
nosidebar = true
|
||||
pygments_style = flask_theme_support.FlaskyStyle
|
||||
|
||||
[options]
|
||||
index_logo = ''
|
||||
index_logo_height = 120px
|
||||
github_fork = ''
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Tablib documentation build configuration file, created by
|
||||
# sphinx-quickstart on Tue Oct 5 15:25:21 2010.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys, os
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'Tablib'
|
||||
copyright = u'2010, Kenneth Reitz'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.8.3'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.8.3'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Tablibdoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
||||
# The paper size ('letter' or 'a4').
|
||||
#latex_paper_size = 'letter'
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#latex_font_size = '10pt'
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'Tablib.tex', u'Tablib Documentation',
|
||||
u'Kenneth Reitz', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#latex_preamble = ''
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output --------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'tablib', u'Tablib Documentation',
|
||||
[u'Kenneth Reitz'], 1)
|
||||
]
|
||||
|
||||
sys.path.append(os.path.abspath('_themes'))
|
||||
html_theme_path = ['_themes']
|
||||
html_theme = 'kr'
|
||||
@@ -0,0 +1,34 @@
|
||||
.. Tablib documentation master file, created by
|
||||
sphinx-quickstart on Tue Oct 5 15:25:21 2010.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to Tablib's documentation!
|
||||
==================================
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
||||
Dataset Object
|
||||
--------------
|
||||
.. module:: tablib
|
||||
|
||||
.. autoclass:: Databook
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
Databook Object
|
||||
---------------
|
||||
|
||||
.. autoclass:: Dataset
|
||||
:members:
|
||||
:inherited-members:
|
||||
Vendored
-20
@@ -5,23 +5,3 @@ def scrub():
|
||||
""" Death to the bytecode! """
|
||||
local("rm -fr dist build")
|
||||
local("find . -name \"*.pyc\" -exec rm '{}' ';'")
|
||||
|
||||
def test():
|
||||
""" Test parsing! """
|
||||
local("rm output/*")
|
||||
local("./strata.py --nsanity_files 'strata/tests/samples/nsanity' -d")
|
||||
|
||||
def build():
|
||||
""" Build application"""
|
||||
pass
|
||||
|
||||
def init():
|
||||
""" Initialize Environment """
|
||||
# TODO: Possibly add Virtual Environment?
|
||||
local("sudo pip install -r REQUIREMENTS")
|
||||
|
||||
if __name__ == '__main__':
|
||||
# TODO: Remove (for testing purposes)
|
||||
# TODO: [Possibly] add doctests
|
||||
test()
|
||||
|
||||
@@ -1,36 +1,57 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
import tablib
|
||||
|
||||
from distutils.core import setup
|
||||
|
||||
|
||||
def publish():
|
||||
"""Publish to PyPi"""
|
||||
os.system("python setup.py sdist upload")
|
||||
"""Publish to PyPi"""
|
||||
os.system("python setup.py sdist upload")
|
||||
|
||||
if sys.argv[-1] == "publish":
|
||||
publish()
|
||||
sys.exit()
|
||||
publish()
|
||||
sys.exit()
|
||||
|
||||
setup(name='tablib',
|
||||
version=tablib.__version__,
|
||||
description='Python wrapper for Gist API',
|
||||
long_description=open('README.rst').read() + '\n\n' +
|
||||
open('HISTORY.rst').read(),
|
||||
author='Kenneth Reitz',
|
||||
author_email='me@kennethreitz.com',
|
||||
url='http://github.com/kennethreitz/tabbed',
|
||||
packages=['tablib'],
|
||||
license='MIT',
|
||||
classifiers=(
|
||||
"Development Status :: 4 - Beta",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 2.5",
|
||||
"Programming Language :: Python :: 2.6",
|
||||
"Programming Language :: Python :: 2.7",
|
||||
)
|
||||
)
|
||||
required = []
|
||||
|
||||
# if sys.version_info < (2, 6):
|
||||
# required.append('simplejson')
|
||||
|
||||
setup(
|
||||
name='tablib',
|
||||
version='0.8.5',
|
||||
description='Format agnostic tabular data library (XLS, JSON, YAML, CSV)',
|
||||
long_description=open('README.rst').read() + '\n\n' +
|
||||
open('HISTORY.rst').read(),
|
||||
author='Kenneth Reitz',
|
||||
author_email='me@kennethreitz.com',
|
||||
url='http://github.com/kennethreitz/tablib',
|
||||
packages= [
|
||||
'tablib', 'tablib.formats',
|
||||
'tablib.packages.simplejson'
|
||||
'tablib.packages.xlwt',
|
||||
'tablib.packages.yaml',
|
||||
],
|
||||
install_requires=required,
|
||||
license='MIT',
|
||||
classifiers=(
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Intended Audience :: Developers',
|
||||
'Natural Language :: English',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Programming Language :: Python',
|
||||
# 'Programming Language :: Python :: 2.5',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
# 'Programming Language :: Python :: 3.0',
|
||||
# 'Programming Language :: Python :: 3.1',
|
||||
),
|
||||
# entry_points={
|
||||
# 'console_scripts': [
|
||||
# 'tabbed = tablib.cli:start',
|
||||
# ],
|
||||
# }
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Tabbed
|
||||
Tabbed -- CLI for Tablib
|
||||
Copyright (c) 2010 Kenneth Reitz. MIT License.
|
||||
"""
|
||||
|
||||
|
||||
+8
-1
@@ -1 +1,8 @@
|
||||
from core import *
|
||||
""" Tablib.
|
||||
"""
|
||||
|
||||
from tablib.core import (
|
||||
Databook, Dataset, detect, import_set,
|
||||
InvalidDatasetType, InvalidDimensions, UnsupportedFormat
|
||||
)
|
||||
|
||||
|
||||
+18
-19
@@ -7,13 +7,14 @@
|
||||
import io
|
||||
import sys
|
||||
|
||||
from helpers import *
|
||||
import tablib.core
|
||||
import argue
|
||||
|
||||
from packages import opster
|
||||
import tablib
|
||||
from helpers import Struct, piped
|
||||
|
||||
|
||||
FORMATS = ('json', 'yaml', 'xls', 'csv', 'html')
|
||||
|
||||
FORMATS = [fmt.title for fmt in tablib.formats.FORMATS]
|
||||
|
||||
opts = []
|
||||
|
||||
@@ -24,34 +25,33 @@ for format in FORMATS:
|
||||
|
||||
|
||||
|
||||
@opster.command(options=opts, usage='[FILE] [--FORMAT | FILE]')
|
||||
@argue.command(options=opts, usage='[FILE] [--FORMAT | FILE]')
|
||||
def start(in_file=None, out_file=None, **opts):
|
||||
"""Covertly convert dataset formats"""
|
||||
|
||||
opts = Object(**opts)
|
||||
opts = Struct(**opts)
|
||||
|
||||
if opts.version:
|
||||
print('Tabbed, Ver. %s' % tabbed.core.__version__)
|
||||
sys.sys.exit(0)
|
||||
print('Tabbed, Ver. %s' % tablib.core.__version__)
|
||||
sys.exit(0)
|
||||
|
||||
stdin = piped()
|
||||
|
||||
if stdin:
|
||||
print stdin
|
||||
data = tablib.import_set(stdin)
|
||||
|
||||
elif in_file:
|
||||
|
||||
try:
|
||||
in_file = io.open(in_file, 'r')
|
||||
in_stream =- io.open(in_file, 'r').read()
|
||||
except Exception, e:
|
||||
print(' %s cannot be read.' % in_file)
|
||||
sys.exit(65)
|
||||
|
||||
file_ext = in_file.name.split('.')[-1]
|
||||
|
||||
if file_ext.lower() in FORMATS:
|
||||
setattr(opts, file_ext, True)
|
||||
else:
|
||||
try:
|
||||
tablib.import_set(in_stream)
|
||||
except Exception, e:
|
||||
raise e
|
||||
print('Import format not supported.')
|
||||
sys.exit(65)
|
||||
else:
|
||||
@@ -59,7 +59,6 @@ def start(in_file=None, out_file=None, **opts):
|
||||
sys.exit(65)
|
||||
|
||||
|
||||
|
||||
_formats_sum = sum(opts[f] for f in FORMATS)
|
||||
|
||||
# Multiple output formats given
|
||||
@@ -80,6 +79,6 @@ def start(in_file=None, out_file=None, **opts):
|
||||
|
||||
# look for filename
|
||||
|
||||
print opts.__dict__
|
||||
print in_file
|
||||
print out_file
|
||||
# print opts.__dict__
|
||||
# print in_file
|
||||
# print out_file
|
||||
+422
-20
@@ -1,38 +1,440 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
tablib.core
|
||||
~~~~~~~~~~~
|
||||
|
||||
# _____ ______ ______ _________
|
||||
# __ /_______ ____ /_ ___ /_ _____ ______ /
|
||||
# _ __/_ __ `/__ __ \__ __ \_ _ \_ __ /
|
||||
# / /_ / /_/ / _ /_/ /_ /_/ // __// /_/ /
|
||||
# \__/ \__,_/ /_.___/ /_.___/ \___/ \__,_/
|
||||
This module implements the central tablib objects.
|
||||
|
||||
__version__ = '0.0.3'
|
||||
__build__ = '0x000003'
|
||||
:copyright: (c) 2010 by Kenneth Reitz.
|
||||
:license: MIT, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from tablib.formats import FORMATS as formats
|
||||
|
||||
|
||||
__title__ = 'tablib'
|
||||
__version__ = '0.8.5'
|
||||
__build__ = 0x000805
|
||||
__author__ = 'Kenneth Reitz'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright 2010 Kenneth Reitz'
|
||||
|
||||
|
||||
def importer():
|
||||
"""docstring for import"""
|
||||
class Dataset(object):
|
||||
"""The tablib Dataset object is the heart of tablib. It provides all core
|
||||
functionality.
|
||||
|
||||
Usually you create a :class:`Dataset` instance in your main module, and append
|
||||
rows and columns as you collect data. ::
|
||||
|
||||
data = tablib.Dataset()
|
||||
data.headers = ('name', 'age')
|
||||
|
||||
for (name, age) in some_collector():
|
||||
data.append((name, age))
|
||||
|
||||
You can also set rows and headers upon instantiation. This is useful if dealing
|
||||
with dozens or hundres of :class:`Dataset` objects. ::
|
||||
|
||||
headers = ('first_name', 'last_name')
|
||||
data = [('John', 'Adams'), ('George', 'Washington')]
|
||||
|
||||
data = tablib.Dataset(*data, headers=headers)
|
||||
|
||||
|
||||
:param \*args: (optional) list of rows to populate Dataset
|
||||
:param headers: (optional) list strings for Dataset header row
|
||||
|
||||
|
||||
.. admonition:: About the Format Attributes
|
||||
|
||||
If you look at the code, the various output/import formats are not
|
||||
defined within the itself. To add support for a new format, see
|
||||
:ref:`Adding New Formats`.
|
||||
|
||||
.. attribute:: csv
|
||||
|
||||
A CSV representation of the Dataset object. The top row will contain
|
||||
headers, if they have been set. Otherwise, the top row will contain
|
||||
the first row of the dataset.
|
||||
|
||||
A dataset object can also be imported by setting the `Dataset.csv` attribute: ::
|
||||
|
||||
data = tablib.Dataset()
|
||||
data.csv = 'age, first_name, last_name\\n90, John, Adams'
|
||||
|
||||
Import assumes (for now) that headers exist.
|
||||
|
||||
|
||||
.. attribute:: dict
|
||||
|
||||
class Data(object):
|
||||
"""test"""
|
||||
def __init__(self):
|
||||
pass
|
||||
self.headers = None
|
||||
An native Python representation of the Dataset object. If headers have been
|
||||
set, a list of Python dictionaries will be returned. If no headers have been
|
||||
set, a list of tuples (rows) will be returned instead.
|
||||
|
||||
A dataset object can also be imported by setting the `Dataset.dict` attribute: ::
|
||||
|
||||
data = tablib.Dataset()
|
||||
data.dict = [{'age': 90, 'first_name': 'Kenneth', 'last_name': 'Reitz'}]
|
||||
|
||||
|
||||
.. attribute:: xls
|
||||
|
||||
An Excel Spreadsheet representation of the Dataset object, including
|
||||
:ref:`seperators`.
|
||||
|
||||
*Note:* `Dataset.xls` contains binary data, so make sure to write in binary
|
||||
mode::
|
||||
|
||||
with open('output.xls', 'wb') as f:
|
||||
f.write(data.xls)
|
||||
|
||||
|
||||
.. attribute:: yaml
|
||||
|
||||
A YAML representation of the Dataset object. If headers have been
|
||||
set, a YAML list of objects will be returned. If no headers have
|
||||
been set, a YAML list of lists (rows) will be returned instead.
|
||||
|
||||
A dataset object can also be imported by setting the `Dataset.json` attribute: ::
|
||||
|
||||
data = tablib.Dataset()
|
||||
data.yaml = '- {age: 90, first_name: John, last_name: Adams}'
|
||||
|
||||
Import assumes (for now) that headers exist.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._data = list(args)
|
||||
self.__headers = None
|
||||
|
||||
# ('title', index) tuples
|
||||
self._separators = []
|
||||
|
||||
try:
|
||||
self.headers = kwargs['headers']
|
||||
except KeyError:
|
||||
self.headers = None
|
||||
|
||||
try:
|
||||
self.title = kwargs['title']
|
||||
except KeyError:
|
||||
self.title = None
|
||||
|
||||
self._register_formats()
|
||||
|
||||
|
||||
def __len__(self):
|
||||
return self.height
|
||||
|
||||
def add_row(self, index=None):
|
||||
pass
|
||||
|
||||
def del_row(self):
|
||||
pass
|
||||
def __getitem__(self, key):
|
||||
if isinstance(key, basestring):
|
||||
if key in self.headers:
|
||||
pos = self.headers.index(key) # get 'key' index from each data
|
||||
return [row[pos] for row in self._data]
|
||||
else:
|
||||
raise KeyError
|
||||
else:
|
||||
return self._data[key]
|
||||
|
||||
def save(self):
|
||||
pass
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self._validate(value)
|
||||
self._data[key] = tuple(value)
|
||||
|
||||
|
||||
def __delitem__(self, key):
|
||||
del self._data[key]
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
try:
|
||||
return '<%s dataset>' % (self.title.lower())
|
||||
except AttributeError:
|
||||
return '<dataset object>'
|
||||
|
||||
|
||||
@classmethod
|
||||
def _register_formats(cls):
|
||||
"""Adds format properties."""
|
||||
for fmt in formats:
|
||||
try:
|
||||
try:
|
||||
setattr(cls, fmt.title, property(fmt.export_set, fmt.import_set))
|
||||
except AttributeError:
|
||||
setattr(cls, fmt.title, property(fmt.export_set))
|
||||
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
|
||||
def _validate(self, row=None, col=None, safety=False):
|
||||
"""Assures size of every row in dataset is of proper proportions."""
|
||||
if row:
|
||||
is_valid = (len(row) == self.width) if self.width else True
|
||||
elif col:
|
||||
if self.headers:
|
||||
is_valid = (len(col) - 1) == self.height
|
||||
else:
|
||||
is_valid = (len(col) == self.height) if self.height else True
|
||||
else:
|
||||
is_valid = all((len(x)== self.width for x in self._data))
|
||||
|
||||
if is_valid:
|
||||
return True
|
||||
else:
|
||||
if not safety:
|
||||
raise InvalidDimensions
|
||||
return False
|
||||
|
||||
|
||||
def _package(self, dicts=True):
|
||||
"""Packages Dataset into lists of dictionaries for transmission."""
|
||||
|
||||
if self.headers:
|
||||
if dicts:
|
||||
data = [dict(zip(self.headers, data_row)) for data_row in self ._data]
|
||||
else:
|
||||
data = [list(self.headers)] + list(self._data)
|
||||
else:
|
||||
data = [list(row) for row in self._data]
|
||||
|
||||
return data
|
||||
|
||||
|
||||
@property
|
||||
def height(self):
|
||||
"""Returns the height of the Dataset."""
|
||||
return len(self._data)
|
||||
|
||||
|
||||
@property
|
||||
def width(self):
|
||||
"""Returns the width of the Dataset."""
|
||||
try:
|
||||
return len(self._data[0])
|
||||
except IndexError:
|
||||
try:
|
||||
return len(self.headers)
|
||||
except TypeError:
|
||||
return 0
|
||||
|
||||
|
||||
@property
|
||||
def headers(self):
|
||||
"""Headers property."""
|
||||
return self.__headers
|
||||
|
||||
|
||||
@headers.setter
|
||||
def headers(self, collection):
|
||||
"""Validating headers setter."""
|
||||
self._validate(collection)
|
||||
if collection:
|
||||
try:
|
||||
self.__headers = list(collection)
|
||||
except TypeError:
|
||||
raise TypeError
|
||||
else:
|
||||
self.__headers = None
|
||||
|
||||
|
||||
@property
|
||||
def dict(self):
|
||||
"""A JSON representation of the Dataset object. If headers have been
|
||||
set, a JSON list of objects will be returned. If no headers have
|
||||
been set, a JSON list of lists (rows) will be returned instead.
|
||||
|
||||
A dataset object can also be imported by setting the `Dataset.json` attribute: ::
|
||||
|
||||
data = tablib.Dataset()
|
||||
data.json = '[{"last_name": "Adams","age": 90,"first_name": "John"}]'
|
||||
|
||||
"""
|
||||
return self._package()
|
||||
|
||||
|
||||
@dict.setter
|
||||
def dict(self, pickle):
|
||||
|
||||
if not len(pickle):
|
||||
return
|
||||
|
||||
# if list of rows
|
||||
if isinstance(pickle[0], list):
|
||||
self.wipe()
|
||||
for row in pickle:
|
||||
self.append(row)
|
||||
|
||||
# if list of objects
|
||||
elif isinstance(pickle[0], dict):
|
||||
self.wipe()
|
||||
self.headers = pickle[0].keys()
|
||||
for row in pickle:
|
||||
self.append(row.values())
|
||||
else:
|
||||
raise UnsupportedFormat
|
||||
|
||||
|
||||
def append(self, row=None, col=None):
|
||||
"""Adds a row to the end of Dataset"""
|
||||
if row is not None:
|
||||
self._validate(row)
|
||||
self._data.append(tuple(row))
|
||||
elif col is not None:
|
||||
col = list(col)
|
||||
if self.headers:
|
||||
header = [col.pop(0)]
|
||||
else:
|
||||
header = []
|
||||
if len(col) == 1 and callable(col[0]):
|
||||
col = map(col[0], self._data)
|
||||
col = tuple(header + col)
|
||||
|
||||
self._validate(col=col)
|
||||
|
||||
if self.headers:
|
||||
# pop the first item off, add to headers
|
||||
self.headers.append(col[0])
|
||||
col = col[1:]
|
||||
|
||||
if self.height and self.width:
|
||||
|
||||
for i, row in enumerate(self._data):
|
||||
_row = list(row)
|
||||
_row.append(col[i])
|
||||
self._data[i] = tuple(_row)
|
||||
else:
|
||||
self._data = [tuple([row]) for row in col]
|
||||
|
||||
|
||||
def insert_separator(self, index, text='-'):
|
||||
"""Adds a separator to Dataset at given index."""
|
||||
|
||||
sep = (index, text)
|
||||
self._separators.append(sep)
|
||||
|
||||
|
||||
def append_separator(self, text='-'):
|
||||
"""Adds a separator to Dataset."""
|
||||
|
||||
# change offsets if headers are or aren't defined
|
||||
if not self.headers:
|
||||
index = self.height if self.height else 0
|
||||
else:
|
||||
index = (self.height + 1) if self.height else 1
|
||||
|
||||
self.insert_separator(index, text)
|
||||
|
||||
|
||||
def insert(self, i, row=None):
|
||||
"""Inserts a row at given position in Dataset"""
|
||||
if row:
|
||||
self._validate(row)
|
||||
self._data.insert(i, tuple(row))
|
||||
elif col:
|
||||
pass
|
||||
|
||||
|
||||
def wipe(self):
|
||||
"""Erases all data from Dataset."""
|
||||
self._data = list()
|
||||
self.__headers = None
|
||||
|
||||
|
||||
class Databook(object):
|
||||
"""A book of Dataset objects.
|
||||
Currently, this exists only for XLS workbook support.
|
||||
"""
|
||||
|
||||
def __init__(self, sets=[]):
|
||||
self._datasets = sets
|
||||
self._register_formats()
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
try:
|
||||
return '<%s databook>' % (self.title.lower())
|
||||
except AttributeError:
|
||||
return '<databook object>'
|
||||
|
||||
|
||||
def wipe(self):
|
||||
"""Wipe book clean."""
|
||||
self._datasets = []
|
||||
|
||||
|
||||
@classmethod
|
||||
def _register_formats(cls):
|
||||
"""Adds format properties."""
|
||||
for fmt in formats:
|
||||
try:
|
||||
try:
|
||||
setattr(cls, fmt.title, property(fmt.export_book, fmt.import_book))
|
||||
except AttributeError:
|
||||
setattr(cls, fmt.title, property(fmt.export_book))
|
||||
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
|
||||
def add_sheet(self, dataset):
|
||||
"""Adds given dataset."""
|
||||
if type(dataset) is Dataset:
|
||||
self._datasets.append(dataset)
|
||||
else:
|
||||
raise InvalidDatasetType
|
||||
|
||||
|
||||
def _package(self):
|
||||
"""Packages Databook for delivery."""
|
||||
collector = []
|
||||
for dset in self._datasets:
|
||||
collector.append(dict(
|
||||
title = dset.title,
|
||||
data = dset.dict
|
||||
))
|
||||
return collector
|
||||
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
"""The number of the Datasets within DataBook."""
|
||||
return len(self._datasets)
|
||||
|
||||
|
||||
def detect(stream):
|
||||
"""Return (format, stream) of given stream."""
|
||||
for fmt in formats:
|
||||
try:
|
||||
if fmt.detect(stream):
|
||||
return (fmt, stream)
|
||||
except AttributeError:
|
||||
pass
|
||||
return (None, stream)
|
||||
|
||||
|
||||
def import_set(stream):
|
||||
"""Return dataset of given stream."""
|
||||
(format, stream) = detect(stream)
|
||||
|
||||
try:
|
||||
data = Dataset()
|
||||
format.import_set(data, stream)
|
||||
return data
|
||||
|
||||
except AttributeError, e:
|
||||
return None
|
||||
|
||||
|
||||
class InvalidDatasetType(Exception):
|
||||
"Only Datasets can be added to a DataBook"
|
||||
|
||||
|
||||
class InvalidDimensions(Exception):
|
||||
"Invalid size"
|
||||
|
||||
|
||||
class UnsupportedFormat(NotImplementedError):
|
||||
"Format is not supported"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
""" Tablib - formats
|
||||
"""
|
||||
|
||||
import _csv as csv
|
||||
import _json as json
|
||||
import _xls as xls
|
||||
import _yaml as yaml
|
||||
|
||||
FORMATS = (json, xls, yaml, csv)
|
||||
@@ -0,0 +1,49 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
""" Tablib - CSV Support.
|
||||
"""
|
||||
|
||||
import cStringIO
|
||||
import csv
|
||||
import os
|
||||
|
||||
import tablib
|
||||
|
||||
|
||||
title = 'csv'
|
||||
extentions = ('csv',)
|
||||
|
||||
|
||||
|
||||
def export_set(dataset):
|
||||
"""Returns CSV representation of Dataset."""
|
||||
stream = cStringIO.StringIO()
|
||||
_csv = csv.writer(stream)
|
||||
|
||||
for row in dataset._package(dicts=False):
|
||||
_csv.writerow(row)
|
||||
|
||||
return stream.getvalue()
|
||||
|
||||
|
||||
def import_set(dset, in_stream, headers=True):
|
||||
"""Returns dataset from CSV stream."""
|
||||
|
||||
dset.wipe()
|
||||
|
||||
rows = csv.reader(in_stream.split())
|
||||
for i, row in enumerate(rows):
|
||||
|
||||
if (i == 0) and (headers):
|
||||
dset.headers = row
|
||||
else:
|
||||
dset.append(row)
|
||||
|
||||
|
||||
def detect(stream):
|
||||
"""Returns True if given stream is valid CSV."""
|
||||
try:
|
||||
rows = dialect = csv.Sniffer().sniff(stream)
|
||||
return True
|
||||
except csv.Error:
|
||||
return False
|
||||
@@ -0,0 +1,55 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
""" Tablib - JSON Support
|
||||
"""
|
||||
|
||||
try:
|
||||
import json # load system JSON (Python >= 2.6)
|
||||
except ImportError:
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import tablib.packages.simplejson as json # use the vendorized copy
|
||||
|
||||
import tablib.core
|
||||
|
||||
|
||||
title = 'json'
|
||||
extentions = ('json', 'jsn')
|
||||
|
||||
|
||||
def export_set(dataset):
|
||||
"""Returns JSON representation of Dataset."""
|
||||
return json.dumps(dataset.dict)
|
||||
|
||||
|
||||
def export_book(databook):
|
||||
"""Returns JSON representation of Databook."""
|
||||
return json.dumps(databook._package())
|
||||
|
||||
|
||||
def import_set(dset, in_stream):
|
||||
"""Returns dataset from JSON stream."""
|
||||
|
||||
dset.wipe()
|
||||
dset.dict = json.loads(in_stream)
|
||||
|
||||
|
||||
def import_book(dbook, in_stream):
|
||||
"""Returns databook from JSON stream."""
|
||||
|
||||
dbook.wipe()
|
||||
for sheet in json.loads(in_stream):
|
||||
data = tablib.core.Dataset()
|
||||
data.title = sheet['title']
|
||||
data.dict = sheet['data']
|
||||
dbook.add_sheet(data)
|
||||
|
||||
|
||||
def detect(stream):
|
||||
"""Returns True if given stream is valid JSON."""
|
||||
try:
|
||||
json.loads(stream)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
@@ -0,0 +1,80 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
""" Tablib - XLS Support.
|
||||
"""
|
||||
|
||||
import cStringIO
|
||||
|
||||
try:
|
||||
import xlwt
|
||||
except ImportError:
|
||||
import tablib.packages.xlwt as xlwt
|
||||
|
||||
|
||||
title = 'xls'
|
||||
extentions = ('xls',)
|
||||
|
||||
# special styles
|
||||
wrap = xlwt.easyxf("alignment: wrap on")
|
||||
bold = xlwt.easyxf("font: bold on")
|
||||
|
||||
|
||||
def export_set(dataset):
|
||||
"""Returns XLS representation of Dataset."""
|
||||
|
||||
wb = xlwt.Workbook(encoding='utf8')
|
||||
ws = wb.add_sheet(dataset.title if dataset.title else 'Tabbed Dataset')
|
||||
|
||||
dset_sheet(dataset, ws)
|
||||
|
||||
stream = cStringIO.StringIO()
|
||||
wb.save(stream)
|
||||
return stream.getvalue()
|
||||
|
||||
|
||||
def export_book(databook):
|
||||
"""Returns XLS representation of DataBook."""
|
||||
|
||||
wb = xlwt.Workbook(encoding='utf8')
|
||||
|
||||
for i, dset in enumerate(databook._datasets):
|
||||
ws = wb.add_sheet(dset.title if dset.title else 'Sheet%s' % (i))
|
||||
|
||||
dset_sheet(dset, ws)
|
||||
|
||||
|
||||
stream = cStringIO.StringIO()
|
||||
wb.save(stream)
|
||||
return stream.getvalue()
|
||||
|
||||
|
||||
def dset_sheet(dataset, ws):
|
||||
"""Completes given worksheet from given Dataset."""
|
||||
_package = dataset._package(dicts=False)
|
||||
|
||||
for i, sep in enumerate(dataset._separators):
|
||||
_offset = i
|
||||
_package.insert((sep[0] + _offset), (sep[1],))
|
||||
|
||||
for i, row in enumerate(_package):
|
||||
for j, col in enumerate(row):
|
||||
|
||||
# bold headers
|
||||
if (i == 0) and dataset.headers:
|
||||
ws.write(i, j, col, bold)
|
||||
|
||||
# bold separators
|
||||
elif len(row) < dataset.width:
|
||||
ws.write(i, j, col, bold)
|
||||
|
||||
# wrap the rest
|
||||
else:
|
||||
try:
|
||||
if '\n' in col:
|
||||
ws.write(i, j, col, wrap)
|
||||
else:
|
||||
ws.write(i, j, col)
|
||||
except TypeError:
|
||||
ws.write(i, j, col)
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
""" Tablib - YAML Support.
|
||||
"""
|
||||
|
||||
try:
|
||||
import yaml
|
||||
except ImportError:
|
||||
import tablib.packages.yaml as yaml
|
||||
|
||||
import tablib
|
||||
|
||||
|
||||
|
||||
title = 'yaml'
|
||||
extentions = ('yaml', 'yml')
|
||||
|
||||
|
||||
|
||||
def export_set(dataset):
|
||||
"""Returns YAML representation of Dataset."""
|
||||
return yaml.dump(dataset.dict)
|
||||
|
||||
|
||||
def export_book(databook):
|
||||
"""Returns YAML representation of Databook."""
|
||||
return yaml.dump(databook._package())
|
||||
|
||||
|
||||
def import_set(dset, in_stream):
|
||||
"""Returns dataset from YAML stream."""
|
||||
|
||||
dset.wipe()
|
||||
dset.dict = yaml.load(in_stream)
|
||||
|
||||
|
||||
def import_book(dbook, in_stream):
|
||||
"""Returns databook from YAML stream."""
|
||||
|
||||
dbook.wipe()
|
||||
|
||||
for sheet in yaml.load(in_stream):
|
||||
data = tablib.core.Dataset()
|
||||
data.title = sheet['title']
|
||||
data.dict = sheet['data']
|
||||
dbook.add_sheet(data)
|
||||
|
||||
def detect(stream):
|
||||
"""Returns True if given stream is valid YAML."""
|
||||
try:
|
||||
_yaml = yaml.load(stream)
|
||||
if isinstance(_yaml, (list, tuple, dict)):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
except yaml.parser.ParserError:
|
||||
return False
|
||||
+21
-4
@@ -1,20 +1,37 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
""" Tablib - General Helpers.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
class Object(object):
|
||||
class Struct(object):
|
||||
"""Your attributes are belong to us."""
|
||||
|
||||
def __init__(self, **entries):
|
||||
self.__dict__.update(entries)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return getattr(self, key)
|
||||
return getattr(self, key, None)
|
||||
|
||||
def dictionary(self):
|
||||
"""Returns dictionary representation of object."""
|
||||
return self.__dict__
|
||||
|
||||
def items(self):
|
||||
"""Returns items within object."""
|
||||
return self.__dict__.items()
|
||||
|
||||
def keys(self):
|
||||
"""Returns keys within object."""
|
||||
return self.__dict__.keys()
|
||||
|
||||
|
||||
|
||||
def piped():
|
||||
"""Returns piped input via stdin, else False"""
|
||||
|
||||
"""Returns piped input via stdin, else False."""
|
||||
with sys.stdin as stdin:
|
||||
# TTY is only way to detect if stdin contains data
|
||||
return stdin.read() if not stdin.isatty() else None
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
all = ['simplejson', 'typecheck', 'xlwt', 'opster']
|
||||
@@ -1,612 +0,0 @@
|
||||
# (c) Alexander Solovyov, 2009, under terms of the new BSD License
|
||||
'''Command line arguments parser
|
||||
'''
|
||||
|
||||
import sys, traceback, getopt, types, textwrap, inspect, os
|
||||
from itertools import imap
|
||||
|
||||
__all__ = ['command', 'dispatch']
|
||||
__version__ = '0.9.10'
|
||||
__author__ = 'Alexander Solovyov'
|
||||
__email__ = 'piranha@piranha.org.ua'
|
||||
|
||||
write = sys.stdout.write
|
||||
err = sys.stderr.write
|
||||
|
||||
CMDTABLE = {}
|
||||
|
||||
# --------
|
||||
# Public interface
|
||||
# --------
|
||||
|
||||
def command(options=None, usage=None, name=None, shortlist=False, hide=False):
|
||||
'''Decorator to mark function to be used for command line processing.
|
||||
|
||||
All arguments are optional:
|
||||
|
||||
- ``options``: options in format described in docs. If not supplied,
|
||||
will be determined from function.
|
||||
- ``usage``: usage string for function, replaces ``%name`` with name
|
||||
of program or subcommand. In case if it's subcommand and ``%name``
|
||||
is not present, usage is prepended by ``name``
|
||||
- ``name``: used for multiple subcommands. Defaults to wrapped
|
||||
function name
|
||||
- ``shortlist``: if command should be included in shortlist. Used
|
||||
only with multiple subcommands
|
||||
- ``hide``: if command should be hidden from help listing. Used only
|
||||
with multiple subcommands, overrides ``shortlist``
|
||||
'''
|
||||
def wrapper(func):
|
||||
try:
|
||||
options_ = list(guess_options(func))
|
||||
except TypeError:
|
||||
options_ = []
|
||||
try:
|
||||
options_ = options_ + list(options)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
name_ = name or func.__name__.replace('_', '-')
|
||||
if usage is None:
|
||||
usage_ = guess_usage(func, options_)
|
||||
else:
|
||||
usage_ = usage
|
||||
prefix = hide and '~' or (shortlist and '^' or '')
|
||||
CMDTABLE[prefix + name_] = (func, options_, usage_)
|
||||
|
||||
def help_func(name=None):
|
||||
return help_cmd(func, replace_name(usage_, sysname()), options_)
|
||||
|
||||
@wraps(func)
|
||||
def inner(*args, **opts):
|
||||
# look if we need to add 'help' option
|
||||
try:
|
||||
(True for option in reversed(options_)
|
||||
if option[1] == 'help').next()
|
||||
except StopIteration:
|
||||
options_.append(('h', 'help', False, 'show help'))
|
||||
|
||||
argv = opts.pop('argv', sys.argv[1:])
|
||||
if opts.pop('help', False):
|
||||
return help_func()
|
||||
|
||||
if args or opts:
|
||||
# no catcher here because this is call from Python
|
||||
return call_cmd_regular(func, options_)(*args, **opts)
|
||||
|
||||
try:
|
||||
opts, args = catcher(lambda: parse(argv, options_), help_func)
|
||||
except Abort:
|
||||
return -1
|
||||
|
||||
try:
|
||||
if opts.pop('help', False):
|
||||
return help_func()
|
||||
return catcher(lambda: call_cmd(name_, func)(*args, **opts),
|
||||
help_func)
|
||||
except Abort:
|
||||
return -1
|
||||
|
||||
return inner
|
||||
return wrapper
|
||||
|
||||
|
||||
def dispatch(args=None, cmdtable=None, globaloptions=None,
|
||||
middleware=lambda x: x):
|
||||
'''Dispatch command arguments based on subcommands.
|
||||
|
||||
- ``args``: list of arguments, default: ``sys.argv[1:]``
|
||||
- ``cmdtable``: dict of commands in format described below.
|
||||
If not supplied, will use functions decorated with ``@command``.
|
||||
- ``globaloptions``: list of options which are applied to all
|
||||
commands, will contain ``--help`` option at least.
|
||||
- ``middleware``: global decorator for all commands.
|
||||
|
||||
cmdtable format description::
|
||||
|
||||
{'name': (function, options, usage)}
|
||||
|
||||
- ``name`` is the name used on command-line. Can contain aliases
|
||||
(separate them with ``|``), pointer to a fact that this command
|
||||
should be displayed in short help (start name with ``^``), or to
|
||||
a fact that this command should be hidden (start name with ``~``)
|
||||
- ``function`` is the actual callable
|
||||
- ``options`` is options list in format described in docs
|
||||
- ``usage`` is the short string of usage
|
||||
'''
|
||||
args = args or sys.argv[1:]
|
||||
cmdtable = cmdtable or CMDTABLE
|
||||
|
||||
globaloptions = globaloptions or []
|
||||
globaloptions.append(('h', 'help', False, 'display help'))
|
||||
|
||||
cmdtable['help'] = (help_(cmdtable, globaloptions), [], '[TOPIC]')
|
||||
help_func = cmdtable['help'][0]
|
||||
|
||||
autocomplete(cmdtable, args)
|
||||
|
||||
try:
|
||||
name, func, args, kwargs = catcher(
|
||||
lambda: _dispatch(args, cmdtable, globaloptions),
|
||||
help_func)
|
||||
return catcher(
|
||||
lambda: call_cmd(name, middleware(func))(*args, **kwargs),
|
||||
help_func)
|
||||
except Abort:
|
||||
return -1
|
||||
|
||||
# --------
|
||||
# Help
|
||||
# --------
|
||||
|
||||
def help_(cmdtable, globalopts):
|
||||
def help_inner(name=None):
|
||||
'''Show help for a given help topic or a help overview
|
||||
|
||||
With no arguments, print a list of commands with short help messages.
|
||||
|
||||
Given a command name, print help for that command.
|
||||
'''
|
||||
def helplist():
|
||||
hlp = {}
|
||||
# determine if any command is marked for shortlist
|
||||
shortlist = (name == 'shortlist' and
|
||||
any(imap(lambda x: x.startswith('^'), cmdtable)))
|
||||
|
||||
for cmd, info in cmdtable.items():
|
||||
if cmd.startswith('~'):
|
||||
continue # do not display hidden commands
|
||||
if shortlist and not cmd.startswith('^'):
|
||||
continue # short help contains only marked commands
|
||||
cmd = cmd.lstrip('^~')
|
||||
doc = info[0].__doc__ or '(no help text available)'
|
||||
hlp[cmd] = doc.splitlines()[0].rstrip()
|
||||
|
||||
hlplist = sorted(hlp)
|
||||
maxlen = max(map(len, hlplist))
|
||||
|
||||
write('usage: %s <command> [options]\n' % sysname())
|
||||
write('\ncommands:\n\n')
|
||||
for cmd in hlplist:
|
||||
doc = hlp[cmd]
|
||||
if False: # verbose?
|
||||
write(' %s:\n %s\n' % (cmd.replace('|', ', '), doc))
|
||||
else:
|
||||
write(' %-*s %s\n' % (maxlen, cmd.split('|', 1)[0],
|
||||
doc))
|
||||
|
||||
if not cmdtable:
|
||||
return err('No commands specified!\n')
|
||||
|
||||
if not name or name == 'shortlist':
|
||||
return helplist()
|
||||
|
||||
aliases, (cmd, options, usage) = findcmd(name, cmdtable)
|
||||
return help_cmd(cmd,
|
||||
replace_name(usage, sysname() + ' ' + aliases[0]),
|
||||
options + globalopts)
|
||||
return help_inner
|
||||
|
||||
def help_cmd(func, usage, options):
|
||||
'''show help for given command
|
||||
|
||||
- ``func``: function to generate help for (``func.__doc__`` is taken)
|
||||
- ``usage``: usage string
|
||||
- ``options``: options in usual format
|
||||
|
||||
>>> def test(*args, **opts):
|
||||
... """that's a test command
|
||||
...
|
||||
... you can do nothing with this command"""
|
||||
... pass
|
||||
>>> opts = [('l', 'listen', 'localhost',
|
||||
... 'ip to listen on'),
|
||||
... ('p', 'port', 8000,
|
||||
... 'port to listen on'),
|
||||
... ('d', 'daemonize', False,
|
||||
... 'daemonize process'),
|
||||
... ('', 'pid-file', '',
|
||||
... 'name of file to write process ID to')]
|
||||
>>> help_cmd(test, 'test [-l HOST] [NAME]', opts)
|
||||
test [-l HOST] [NAME]
|
||||
<BLANKLINE>
|
||||
that's a test command
|
||||
<BLANKLINE>
|
||||
you can do nothing with this command
|
||||
<BLANKLINE>
|
||||
options:
|
||||
<BLANKLINE>
|
||||
-l --listen ip to listen on (default: localhost)
|
||||
-p --port port to listen on (default: 8000)
|
||||
-d --daemonize daemonize process
|
||||
--pid-file name of file to write process ID to
|
||||
<BLANKLINE>
|
||||
'''
|
||||
write(usage + '\n')
|
||||
doc = func.__doc__
|
||||
if not doc:
|
||||
doc = '(no help text available)'
|
||||
write('\n' + doc.strip() + '\n\n')
|
||||
if options:
|
||||
write(''.join(help_options(options)))
|
||||
|
||||
def help_options(options):
|
||||
yield 'options:\n\n'
|
||||
output = []
|
||||
for short, name, default, desc in options:
|
||||
if hasattr(default, '__call__'):
|
||||
default = default(None)
|
||||
default = default and ' (default: %s)' % default or ''
|
||||
output.append(('%2s%s' % (short and '-%s' % short,
|
||||
name and ' --%s' % name),
|
||||
'%s%s' % (desc, default)))
|
||||
|
||||
opts_len = max([len(first) for first, second in output if second] or [0])
|
||||
for first, second in output:
|
||||
if second:
|
||||
# wrap description at 78 chars
|
||||
second = textwrap.wrap(second, width=(78 - opts_len - 3))
|
||||
pad = '\n' + ' ' * (opts_len + 3)
|
||||
yield ' %-*s %s\n' % (opts_len, first, pad.join(second))
|
||||
else:
|
||||
yield '%s\n' % first
|
||||
|
||||
|
||||
# --------
|
||||
# Options parsing
|
||||
# --------
|
||||
|
||||
def parse(args, options):
|
||||
'''
|
||||
>>> opts = [('l', 'listen', 'localhost',
|
||||
... 'ip to listen on'),
|
||||
... ('p', 'port', 8000,
|
||||
... 'port to listen on'),
|
||||
... ('d', 'daemonize', False,
|
||||
... 'daemonize process'),
|
||||
... ('', 'pid-file', '',
|
||||
... 'name of file to write process ID to')]
|
||||
>>> print parse(['-l', '0.0.0.0', '--pi', 'test', 'all'], opts)
|
||||
({'pid_file': 'test', 'daemonize': False, 'port': 8000, 'listen': '0.0.0.0'}, ['all'])
|
||||
|
||||
'''
|
||||
argmap, defmap, state = {}, {}, {}
|
||||
shortlist, namelist, funlist = '', [], []
|
||||
|
||||
for short, name, default, comment in options:
|
||||
if short and len(short) != 1:
|
||||
raise FOError('Short option should be only a single'
|
||||
' character: %s' % short)
|
||||
if not name:
|
||||
raise FOError(
|
||||
'Long name should be defined for every option')
|
||||
# change name to match Python styling
|
||||
pyname = name.replace('-', '_')
|
||||
argmap['-' + short] = argmap['--' + name] = pyname
|
||||
defmap[pyname] = default
|
||||
|
||||
# copy defaults to state
|
||||
if isinstance(default, list):
|
||||
state[pyname] = default[:]
|
||||
elif hasattr(default, '__call__'):
|
||||
funlist.append(pyname)
|
||||
state[pyname] = None
|
||||
else:
|
||||
state[pyname] = default
|
||||
|
||||
# getopt wants indication that it takes a parameter
|
||||
if not (default is None or default is True or default is False):
|
||||
if short: short += ':'
|
||||
if name: name += '='
|
||||
if short:
|
||||
shortlist += short
|
||||
if name:
|
||||
namelist.append(name)
|
||||
|
||||
opts, args = getopt.gnu_getopt(args, shortlist, namelist)
|
||||
|
||||
# transfer result to state
|
||||
for opt, val in opts:
|
||||
name = argmap[opt]
|
||||
t = type(defmap[name])
|
||||
if t is types.FunctionType:
|
||||
del funlist[funlist.index(name)]
|
||||
state[name] = defmap[name](val)
|
||||
elif t is types.ListType:
|
||||
state[name].append(val)
|
||||
elif t in (types.NoneType, types.BooleanType):
|
||||
state[name] = not defmap[name]
|
||||
else:
|
||||
state[name] = t(val)
|
||||
|
||||
for name in funlist:
|
||||
state[name] = defmap[name](None)
|
||||
|
||||
return state, args
|
||||
# --------
|
||||
# Subcommand system
|
||||
# --------
|
||||
|
||||
def _dispatch(args, cmdtable, globalopts):
|
||||
cmd, func, args, options = cmdparse(args, cmdtable, globalopts)
|
||||
|
||||
if options.pop('help', False):
|
||||
return 'help', cmdtable['help'][0], [cmd], {}
|
||||
elif not cmd:
|
||||
return 'help', cmdtable['help'][0], ['shortlist'], {}
|
||||
|
||||
return cmd, func, args, options
|
||||
|
||||
def cmdparse(args, cmdtable, globalopts):
|
||||
# command is the first non-option
|
||||
cmd = None
|
||||
for arg in args:
|
||||
if not arg.startswith('-'):
|
||||
cmd = arg
|
||||
break
|
||||
|
||||
if cmd:
|
||||
args.pop(args.index(cmd))
|
||||
|
||||
aliases, info = findcmd(cmd, cmdtable)
|
||||
cmd = aliases[0]
|
||||
possibleopts = list(info[1])
|
||||
else:
|
||||
possibleopts = []
|
||||
|
||||
possibleopts.extend(globalopts)
|
||||
|
||||
try:
|
||||
options, args = parse(args, possibleopts)
|
||||
except getopt.GetoptError, e:
|
||||
raise ParseError(cmd, e)
|
||||
|
||||
return (cmd, cmd and info[0] or None, args, options)
|
||||
|
||||
def aliases_(cmdtable_key):
|
||||
return cmdtable_key.lstrip("^~").split("|")
|
||||
|
||||
def findpossible(cmd, table):
|
||||
"""
|
||||
Return cmd -> (aliases, command table entry)
|
||||
for each matching command.
|
||||
"""
|
||||
choice = {}
|
||||
for e in table.keys():
|
||||
aliases = aliases_(e)
|
||||
found = None
|
||||
if cmd in aliases:
|
||||
found = cmd
|
||||
else:
|
||||
for a in aliases:
|
||||
if a.startswith(cmd):
|
||||
found = a
|
||||
break
|
||||
if found is not None:
|
||||
choice[found] = (aliases, table[e])
|
||||
|
||||
return choice
|
||||
|
||||
def findcmd(cmd, table):
|
||||
"""Return (aliases, command table entry) for command string."""
|
||||
choice = findpossible(cmd, table)
|
||||
|
||||
if cmd in choice:
|
||||
return choice[cmd]
|
||||
|
||||
if len(choice) > 1:
|
||||
clist = choice.keys()
|
||||
clist.sort()
|
||||
raise AmbiguousCommand(cmd, clist)
|
||||
|
||||
if choice:
|
||||
return choice.values()[0]
|
||||
|
||||
raise UnknownCommand(cmd)
|
||||
|
||||
# --------
|
||||
# Helpers
|
||||
# --------
|
||||
|
||||
def guess_options(func):
|
||||
args, varargs, varkw, defaults = inspect.getargspec(func)
|
||||
for name, option in zip(args[-len(defaults):], defaults):
|
||||
try:
|
||||
sname, default, hlp = option
|
||||
yield (sname, name.replace('_', '-'), default, hlp)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
def guess_usage(func, options):
|
||||
usage = '%name '
|
||||
if options:
|
||||
usage += '[OPTIONS] '
|
||||
args, varargs = inspect.getargspec(func)[:2]
|
||||
argnum = len(args) - len(options)
|
||||
if argnum > 0:
|
||||
usage += args[0].upper()
|
||||
if argnum > 1:
|
||||
usage += 'S'
|
||||
elif varargs:
|
||||
usage += '[%s]' % varargs.upper()
|
||||
return usage
|
||||
|
||||
def catcher(target, help_func):
|
||||
'''Catches all exceptions and prints human-readable information on them
|
||||
'''
|
||||
try:
|
||||
return target()
|
||||
except UnknownCommand, e:
|
||||
err("unknown command: '%s'\n" % e)
|
||||
except AmbiguousCommand, e:
|
||||
err("command '%s' is ambiguous:\n %s\n" %
|
||||
(e.args[0], ' '.join(e.args[1])))
|
||||
except ParseError, e:
|
||||
err('%s: %s\n' % (e.args[0], e.args[1]))
|
||||
help_func(e.args[0])
|
||||
except getopt.GetoptError, e:
|
||||
err('error: %s\n' % e)
|
||||
help_func()
|
||||
except FOError, e:
|
||||
err('%s\n' % e)
|
||||
except KeyboardInterrupt:
|
||||
err('interrupted!\n')
|
||||
except SystemExit:
|
||||
raise
|
||||
except:
|
||||
err('unknown exception encountered')
|
||||
raise
|
||||
|
||||
raise Abort
|
||||
|
||||
def call_cmd(name, func):
|
||||
def inner(*args, **kwargs):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except TypeError:
|
||||
if len(traceback.extract_tb(sys.exc_info()[2])) == 1:
|
||||
raise ParseError(name, "invalid arguments")
|
||||
raise
|
||||
return inner
|
||||
|
||||
def call_cmd_regular(func, opts):
|
||||
def inner(*args, **kwargs):
|
||||
funcargs, _, varkw, defaults = inspect.getargspec(func)
|
||||
if len(args) > len(funcargs):
|
||||
raise TypeError('You have supplied more positional arguments'
|
||||
' than applicable')
|
||||
|
||||
funckwargs = dict((lname.replace('-', '_'), default)
|
||||
for _, lname, default, _ in opts)
|
||||
if 'help' not in (defaults or ()) and not varkw:
|
||||
funckwargs.pop('help', None)
|
||||
funckwargs.update(kwargs)
|
||||
return func(*args, **funckwargs)
|
||||
return inner
|
||||
|
||||
def replace_name(usage, name):
|
||||
if '%name' in usage:
|
||||
return usage.replace('%name', name, 1)
|
||||
return name + ' ' + usage
|
||||
|
||||
def sysname():
|
||||
name = sys.argv[0]
|
||||
if name.startswith('./'):
|
||||
return name[2:]
|
||||
return name
|
||||
|
||||
try:
|
||||
from functools import wraps
|
||||
except ImportError:
|
||||
def wraps(wrapped, assigned=('__module__', '__name__', '__doc__'),
|
||||
updated=('__dict__',)):
|
||||
def inner(wrapper):
|
||||
for attr in assigned:
|
||||
setattr(wrapper, attr, getattr(wrapped, attr))
|
||||
for attr in updated:
|
||||
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
|
||||
return wrapper
|
||||
return inner
|
||||
|
||||
# --------
|
||||
# Autocomplete system
|
||||
# --------
|
||||
|
||||
# Borrowed from PIP
|
||||
def autocomplete(cmdtable, args):
|
||||
"""Command and option completion.
|
||||
|
||||
Enable by sourcing one of the completion shell scripts (bash or zsh).
|
||||
"""
|
||||
|
||||
# Don't complete if user hasn't sourced bash_completion file.
|
||||
if not os.environ.has_key('OPSTER_AUTO_COMPLETE'):
|
||||
return
|
||||
cwords = os.environ['COMP_WORDS'].split()[1:]
|
||||
cword = int(os.environ['COMP_CWORD'])
|
||||
|
||||
try:
|
||||
current = cwords[cword-1]
|
||||
except IndexError:
|
||||
current = ''
|
||||
|
||||
commands = []
|
||||
for k in cmdtable.keys():
|
||||
commands += aliases_(k)
|
||||
|
||||
# command
|
||||
if cword == 1:
|
||||
print ' '.join(filter(lambda x: x.startswith(current), commands))
|
||||
|
||||
# command options
|
||||
elif cwords[0] in commands:
|
||||
options = []
|
||||
aliases, (cmd, opts, usage) = findcmd(cwords[0], cmdtable)
|
||||
for (short, long, default, help) in opts:
|
||||
options.append('-%s' % short)
|
||||
options.append('--%s' % long)
|
||||
|
||||
options = [o for o in options if o.startswith(current)]
|
||||
print ' '.join(filter(lambda x: x.startswith(current), options))
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
COMPLETIONS = {
|
||||
'bash':
|
||||
"""
|
||||
# opster bash completion start
|
||||
_opster_completion()
|
||||
{
|
||||
COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]}" \\
|
||||
COMP_CWORD=$COMP_CWORD \\
|
||||
OPSTER_AUTO_COMPLETE=1 $1 ) )
|
||||
}
|
||||
complete -o default -F _opster_completion %s
|
||||
# opster bash completion end
|
||||
""",
|
||||
'zsh':
|
||||
"""
|
||||
# opster zsh completion start
|
||||
function _opster_completion {
|
||||
local words cword
|
||||
read -Ac words
|
||||
read -cn cword
|
||||
reply=( $( COMP_WORDS="$words[*]" \\
|
||||
COMP_CWORD=$(( cword-1 )) \\
|
||||
OPSTER_AUTO_COMPLETE=1 $words[1] ) )
|
||||
}
|
||||
compctl -K _opster_completion %s
|
||||
# opster zsh completion end
|
||||
"""
|
||||
}
|
||||
|
||||
@command(name='_completion', hide=True)
|
||||
def completion(type=('t', 'bash', 'Completion type (bash or zsh)')):
|
||||
"""Outputs completion script for bash or zsh."""
|
||||
|
||||
prog_name = os.path.split(sys.argv[0])[1]
|
||||
print COMPLETIONS[type] % prog_name
|
||||
|
||||
# --------
|
||||
# Exceptions
|
||||
# --------
|
||||
|
||||
# Command exceptions
|
||||
class CommandException(Exception):
|
||||
'Base class for command exceptions'
|
||||
|
||||
class AmbiguousCommand(CommandException):
|
||||
'Raised if command is ambiguous'
|
||||
|
||||
class UnknownCommand(CommandException):
|
||||
'Raised if command is unknown'
|
||||
|
||||
class ParseError(CommandException):
|
||||
'Raised on error in command line parsing'
|
||||
|
||||
class Abort(CommandException):
|
||||
'Abort execution'
|
||||
|
||||
class FOError(CommandException):
|
||||
'Raised on trouble with opster configuration'
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +0,0 @@
|
||||
"""
|
||||
This module allows doctest to find typechecked functions.
|
||||
|
||||
Currently, doctest verifies functions to make sure that their
|
||||
globals() dict is the __dict__ of their module. In the case of
|
||||
decorated functions, the globals() dict *is* not the right one.
|
||||
|
||||
To enable support for doctest do:
|
||||
|
||||
import typecheck.doctest_support
|
||||
|
||||
This import must occur before any calls to doctest methods.
|
||||
"""
|
||||
|
||||
def __DocTestFinder_from_module(self, module, object):
|
||||
"""
|
||||
Return true if the given object is defined in the given
|
||||
module.
|
||||
"""
|
||||
import inspect
|
||||
|
||||
if module is None:
|
||||
return True
|
||||
elif inspect.isfunction(object) or inspect.isclass(object):
|
||||
return module.__name__ == object.__module__
|
||||
elif inspect.getmodule(object) is not None:
|
||||
return module is inspect.getmodule(object)
|
||||
elif hasattr(object, '__module__'):
|
||||
return module.__name__ == object.__module__
|
||||
elif isinstance(object, property):
|
||||
return True # [XX] no way not be sure.
|
||||
else:
|
||||
raise ValueError("object must be a class or function")
|
||||
|
||||
import doctest as __doctest
|
||||
__doctest.DocTestFinder._from_module = __DocTestFinder_from_module
|
||||
@@ -1,84 +0,0 @@
|
||||
from typecheck import _TC_NestedError, _TC_TypeError, check_type, Or
|
||||
from typecheck import register_type, _TC_Exception
|
||||
|
||||
class _TC_IterationError(_TC_NestedError):
|
||||
def __init__(self, iteration, value, inner_exception):
|
||||
_TC_NestedError.__init__(self, inner_exception)
|
||||
|
||||
self.iteration = iteration
|
||||
self.value = value
|
||||
|
||||
def error_message(self):
|
||||
return ("at iteration %d (value: %s)" % (self.iteration, repr(self.value))) + _TC_NestedError.error_message(self)
|
||||
|
||||
### This is the shadow class behind UnorderedIteratorMixin.
|
||||
### Again, it tries to pretend it doesn't exist by mimicing
|
||||
### the class of <obj> as much as possible.
|
||||
###
|
||||
### This mixin provides typechecking for iterator classes
|
||||
### where you don't care about the order of the types (ie,
|
||||
### you simply Or() the types together, as opposed to patterned
|
||||
### lists, which would be ordered mixins)
|
||||
class _UnorderedIteratorMixin(object):
|
||||
def __init__(self, class_name, obj):
|
||||
vals = [o for o in obj]
|
||||
|
||||
self.type = self
|
||||
self._type = Or(*vals)
|
||||
self.__cls = obj.__class__
|
||||
self.__vals = vals
|
||||
# This is necessary because it's a huge pain in the ass
|
||||
# to get the "raw" name of the class once it's created
|
||||
self.__cls_name = class_name
|
||||
|
||||
def __typecheck__(self, func, to_check):
|
||||
if not isinstance(to_check, self.__cls):
|
||||
raise _TC_TypeError(to_check, self)
|
||||
|
||||
for i, item in enumerate(to_check):
|
||||
try:
|
||||
check_type(self._type, func, item)
|
||||
except _TC_Exception, e:
|
||||
raise _TC_IterationError(i, item, e)
|
||||
|
||||
@classmethod
|
||||
def __typesig__(cls, obj):
|
||||
if isinstance(obj, cls):
|
||||
return obj
|
||||
|
||||
def __str__(self):
|
||||
return "%s(%s)" % (self.__cls_name, str(self._type))
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
### This is included in a class's parent-class section like so:
|
||||
### class MyClass(UnorderedIteratorMixin("MyClass")):
|
||||
### blah blah blah
|
||||
###
|
||||
### This serves as a class factory, whose produced classes
|
||||
### attempt to mask the fact they exist. Their purpose
|
||||
### is to redirect __typesig__ calls to appropriate
|
||||
### instances of _UnorderedIteratorMixin
|
||||
def UnorderedIteratorMixin(class_name):
|
||||
class UIM(object):
|
||||
@classmethod
|
||||
def __typesig__(cls, obj):
|
||||
if isinstance(obj, cls):
|
||||
return _UnorderedIteratorMixin(class_name, obj)
|
||||
|
||||
def __repr__(self):
|
||||
return "%s%s" % (class_name, str(tuple(e for e in self)))
|
||||
|
||||
# We register each produced class anew
|
||||
# If someone needs to unregister these classes, they should
|
||||
# save a copy of it before including it in the class-definition:
|
||||
#
|
||||
# my_UIM = UnorderedIteratorMixin("FooClass")
|
||||
# class FooClass(my_UIM):
|
||||
# ...
|
||||
#
|
||||
# Alternatively, you could just look in FooClass.__bases__ later; whatever
|
||||
register_type(UIM)
|
||||
return UIM
|
||||
|
||||
register_type(_UnorderedIteratorMixin)
|
||||
@@ -1,62 +0,0 @@
|
||||
from typecheck import CheckType, _TC_TypeError, check_type, Type
|
||||
from typecheck import register_type, Or, _TC_Exception, _TC_KeyError
|
||||
from typecheck import _TC_LengthError
|
||||
|
||||
### Provide typechecking for the built-in set() class
|
||||
###
|
||||
### XXX: Investigate rewriting this in terms of
|
||||
### UnorderedIteratorMixin or Or()
|
||||
class Set(CheckType):
|
||||
def __init__(self, set_list):
|
||||
self.type = set(set_list)
|
||||
self._types = [Type(t) for t in self.type]
|
||||
|
||||
# self._type is used to build _TC_TypeError
|
||||
if len(self._types) > 1:
|
||||
self._type = Or(*self.type)
|
||||
elif len(self._types) == 1:
|
||||
# XXX Is there an easier way to get this?
|
||||
t = self.type.pop()
|
||||
self._type = t
|
||||
self.type.add(t)
|
||||
|
||||
def __str__(self):
|
||||
return "Set(" + str([e for e in self.type]) + ")"
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
def __typecheck__(self, func, to_check):
|
||||
if not isinstance(to_check, set):
|
||||
raise _TC_TypeError(to_check, self.type)
|
||||
|
||||
if len(self._types) == 0 and len(to_check) > 0:
|
||||
raise _TC_LengthError(len(to_check), 0)
|
||||
|
||||
for obj in to_check:
|
||||
error = False
|
||||
for type in self._types:
|
||||
try:
|
||||
check_type(type, func, obj)
|
||||
except _TC_Exception:
|
||||
error = True
|
||||
continue
|
||||
else:
|
||||
error = False
|
||||
break
|
||||
if error:
|
||||
raise _TC_KeyError(obj, _TC_TypeError(obj, self._type))
|
||||
|
||||
def __eq__(self, other):
|
||||
if self.__class__ is not other.__class__:
|
||||
return False
|
||||
return self.type == other.type
|
||||
|
||||
def __hash__(self):
|
||||
return hash(str(hash(self.__class__)) + str(hash(frozenset(self.type))))
|
||||
|
||||
@classmethod
|
||||
def __typesig__(self, obj):
|
||||
if isinstance(obj, set):
|
||||
return Set(obj)
|
||||
|
||||
register_type(Set)
|
||||
@@ -1,35 +0,0 @@
|
||||
from typecheck import Typeclass
|
||||
|
||||
### Number
|
||||
####################################################
|
||||
|
||||
_numbers = [int, float, complex, long, bool]
|
||||
try:
|
||||
from decimal import Decimal
|
||||
_numbers.append(Decimal)
|
||||
del Decimal
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
Number = Typeclass(*_numbers)
|
||||
del _numbers
|
||||
|
||||
### String -- subinstance of ImSequence
|
||||
####################################################
|
||||
|
||||
String = Typeclass(str, unicode)
|
||||
|
||||
### ImSequence -- immutable sequences
|
||||
####################################################
|
||||
|
||||
ImSequence = Typeclass(tuple, xrange, String)
|
||||
|
||||
### MSequence -- mutable sequences
|
||||
####################################################
|
||||
|
||||
MSequence = Typeclass(list)
|
||||
|
||||
### Mapping
|
||||
####################################################
|
||||
|
||||
Mapping = Typeclass(dict)
|
||||
+2393
-2393
File diff suppressed because it is too large
Load Diff
+262
-262
@@ -1,262 +1,262 @@
|
||||
# -*- 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
|
||||
|
||||
|
||||
# -*- 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
|
||||
|
||||
|
||||
|
||||
+243
-243
@@ -1,243 +1,243 @@
|
||||
# -*- 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)
|
||||
|
||||
# -*- 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)
|
||||
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
# -*- 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()
|
||||
|
||||
|
||||
|
||||
# -*- 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()
|
||||
|
||||
|
||||
|
||||
|
||||
+516
-516
File diff suppressed because it is too large
Load Diff
@@ -1,43 +1,43 @@
|
||||
# -*- 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
|
||||
|
||||
# -*- 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
|
||||
|
||||
|
||||
@@ -1,128 +1,128 @@
|
||||
# -*- 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, LOCALE, 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+LOCALE+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
|
||||
# -*- 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, LOCALE, 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+LOCALE+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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+862
-862
File diff suppressed because it is too large
Load Diff
+261
-261
@@ -1,261 +1,261 @@
|
||||
#!/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,
|
||||
)
|
||||
#!/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,
|
||||
)
|
||||
|
||||
+253
-253
@@ -1,253 +1,253 @@
|
||||
# -*- 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
|
||||
|
||||
|
||||
|
||||
# -*- 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
|
||||
|
||||
|
||||
|
||||
|
||||
+592
-592
File diff suppressed because it is too large
Load Diff
@@ -1,81 +1,81 @@
|
||||
# -*- 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
|
||||
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, 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
|
||||
# -*- 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
|
||||
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, 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
|
||||
|
||||
+196
-196
@@ -1,196 +1,196 @@
|
||||
# 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"'"
|
||||
# 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"'"
|
||||
|
||||
+636
-636
File diff suppressed because it is too large
Load Diff
+1297
-1297
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,16 @@
|
||||
# -*- coding: windows-1252 -*-
|
||||
|
||||
__VERSION__ = '0.7.2'
|
||||
|
||||
import sys
|
||||
if sys.version_info[:2] < (2, 3):
|
||||
print >> sys.stderr, "Sorry, xlwt requires Python 2.3 or later"
|
||||
sys.exit(1)
|
||||
|
||||
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 *
|
||||
# -*- coding: windows-1252 -*-
|
||||
|
||||
__VERSION__ = '0.7.2'
|
||||
|
||||
import sys
|
||||
if sys.version_info[:2] < (2, 3):
|
||||
print >> sys.stderr, "Sorry, xlwt requires Python 2.3 or later"
|
||||
sys.exit(1)
|
||||
|
||||
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 *
|
||||
|
||||
+2874
-2874
File diff suppressed because it is too large
Load Diff
+199
-199
@@ -1,199 +1,199 @@
|
||||
<!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 ™ 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>
|
||||
<!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 ™ 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>
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
#!/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)
|
||||
|
||||
|
||||
#!/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)
|
||||
|
||||
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
#!/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)
|
||||
|
||||
|
||||
#!/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)
|
||||
|
||||
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
#!/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)
|
||||
#!/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)
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
#!/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")
|
||||
#!/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")
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
@@ -1,102 +1,102 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
Binary file not shown.
@@ -1,60 +1,60 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
@@ -1,60 +1,113 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: ascii -*-
|
||||
# Portions Copyright (C) 2005 Kiseliov Roman
|
||||
|
||||
import xlwt
|
||||
|
||||
style = xlwt.easyxf(
|
||||
"font: name Arial, colour_index blue, bold on;"
|
||||
"borders: top double, bottom double, left double, right double;"
|
||||
)
|
||||
|
||||
def write_data_cells(ws):
|
||||
ws.write_merge(1, 1, 1, 5, 'test 1', style)
|
||||
ws.write_merge(2, 2, 1, 4, 'test 1', style)
|
||||
ws.write_merge(3, 3, 1, 3, 'test 2', style)
|
||||
ws.write_merge(4, 4, 1, 4, 'test 1', style)
|
||||
ws.write_merge(5, 5, 1, 4, 'test 3', style)
|
||||
ws.write_merge(6, 6, 1, 5, 'test 1', style)
|
||||
ws.write_merge(7, 7, 1, 5, 'test 4', style)
|
||||
ws.write_merge(8, 8, 1, 4, 'test 1', style)
|
||||
ws.write_merge(9, 9, 1, 3, 'test 5', style)
|
||||
|
||||
def write_row_outline_levels(ws):
|
||||
ws.row(1).level = 1
|
||||
ws.row(2).level = 1
|
||||
ws.row(3).level = 2
|
||||
ws.row(4).level = 2
|
||||
ws.row(5).level = 2
|
||||
ws.row(6).level = 2
|
||||
ws.row(7).level = 2
|
||||
ws.row(8).level = 1
|
||||
ws.row(9).level = 1
|
||||
|
||||
def write_column_outline_levels(ws):
|
||||
ws.col(1).level = 1
|
||||
ws.col(2).level = 1
|
||||
ws.col(3).level = 2
|
||||
ws.col(4).level = 2
|
||||
ws.col(5).level = 2
|
||||
ws.col(6).level = 2
|
||||
ws.col(7).level = 2
|
||||
ws.col(8).level = 1
|
||||
ws.col(9).level = 1
|
||||
|
||||
wb = xlwt.Workbook()
|
||||
|
||||
ws0 = wb.add_sheet('Rows Outline')
|
||||
write_data_cells(ws0)
|
||||
write_row_outline_levels(ws0)
|
||||
|
||||
ws1 = wb.add_sheet('Columns Outline')
|
||||
write_data_cells(ws1)
|
||||
write_column_outline_levels(ws1)
|
||||
|
||||
ws2 = wb.add_sheet('Rows and Columns Outline')
|
||||
write_data_cells(ws2)
|
||||
write_row_outline_levels(ws2)
|
||||
write_column_outline_levels(ws2)
|
||||
|
||||
wb.save('outline.xls')
|
||||
#!/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')
|
||||
|
||||
@@ -1,58 +1,58 @@
|
||||
#!/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')
|
||||
|
||||
#!/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')
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
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])
|
||||
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])
|
||||
|
||||
@@ -1,134 +1,122 @@
|
||||
# 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(3, 3, 1, 3, 'test 2', style)
|
||||
if 0:
|
||||
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
|
||||
|
||||
if 0:
|
||||
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')
|
||||
# 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')
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
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')
|
||||
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')
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#!/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')
|
||||
#!/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')
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
#!/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')
|
||||
|
||||
#!/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')
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#!/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')
|
||||
|
||||
#!/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')
|
||||
|
||||
|
||||
@@ -1,155 +1,155 @@
|
||||
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
|
||||
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
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
|
||||
# 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)
|
||||
|
||||
# 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)
|
||||
|
||||
@@ -1,374 +1,374 @@
|
||||
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("''", "'") }
|
||||
;
|
||||
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("''", "'") }
|
||||
;
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
|
||||
from error import *
|
||||
|
||||
from tokens import *
|
||||
from events import *
|
||||
from nodes import *
|
||||
|
||||
from loader import *
|
||||
from dumper import *
|
||||
|
||||
__version__ = '3.09'
|
||||
|
||||
try:
|
||||
from cyaml import *
|
||||
__with_libyaml__ = True
|
||||
except ImportError:
|
||||
__with_libyaml__ = False
|
||||
|
||||
def scan(stream, Loader=Loader):
|
||||
"""
|
||||
Scan a YAML stream and produce scanning tokens.
|
||||
"""
|
||||
loader = Loader(stream)
|
||||
while loader.check_token():
|
||||
yield loader.get_token()
|
||||
|
||||
def parse(stream, Loader=Loader):
|
||||
"""
|
||||
Parse a YAML stream and produce parsing events.
|
||||
"""
|
||||
loader = Loader(stream)
|
||||
while loader.check_event():
|
||||
yield loader.get_event()
|
||||
|
||||
def compose(stream, Loader=Loader):
|
||||
"""
|
||||
Parse the first YAML document in a stream
|
||||
and produce the corresponding representation tree.
|
||||
"""
|
||||
loader = Loader(stream)
|
||||
return loader.get_single_node()
|
||||
|
||||
def compose_all(stream, Loader=Loader):
|
||||
"""
|
||||
Parse all YAML documents in a stream
|
||||
and produce corresponding representation trees.
|
||||
"""
|
||||
loader = Loader(stream)
|
||||
while loader.check_node():
|
||||
yield loader.get_node()
|
||||
|
||||
def load(stream, Loader=Loader):
|
||||
"""
|
||||
Parse the first YAML document in a stream
|
||||
and produce the corresponding Python object.
|
||||
"""
|
||||
loader = Loader(stream)
|
||||
return loader.get_single_data()
|
||||
|
||||
def load_all(stream, Loader=Loader):
|
||||
"""
|
||||
Parse all YAML documents in a stream
|
||||
and produce corresponding Python objects.
|
||||
"""
|
||||
loader = Loader(stream)
|
||||
while loader.check_data():
|
||||
yield loader.get_data()
|
||||
|
||||
def safe_load(stream):
|
||||
"""
|
||||
Parse the first YAML document in a stream
|
||||
and produce the corresponding Python object.
|
||||
Resolve only basic YAML tags.
|
||||
"""
|
||||
return load(stream, SafeLoader)
|
||||
|
||||
def safe_load_all(stream):
|
||||
"""
|
||||
Parse all YAML documents in a stream
|
||||
and produce corresponding Python objects.
|
||||
Resolve only basic YAML tags.
|
||||
"""
|
||||
return load_all(stream, SafeLoader)
|
||||
|
||||
def emit(events, stream=None, Dumper=Dumper,
|
||||
canonical=None, indent=None, width=None,
|
||||
allow_unicode=None, line_break=None):
|
||||
"""
|
||||
Emit YAML parsing events into a stream.
|
||||
If stream is None, return the produced string instead.
|
||||
"""
|
||||
getvalue = None
|
||||
if stream is None:
|
||||
from StringIO import StringIO
|
||||
stream = StringIO()
|
||||
getvalue = stream.getvalue
|
||||
dumper = Dumper(stream, canonical=canonical, indent=indent, width=width,
|
||||
allow_unicode=allow_unicode, line_break=line_break)
|
||||
for event in events:
|
||||
dumper.emit(event)
|
||||
if getvalue:
|
||||
return getvalue()
|
||||
|
||||
def serialize_all(nodes, stream=None, Dumper=Dumper,
|
||||
canonical=None, indent=None, width=None,
|
||||
allow_unicode=None, line_break=None,
|
||||
encoding='utf-8', explicit_start=None, explicit_end=None,
|
||||
version=None, tags=None):
|
||||
"""
|
||||
Serialize a sequence of representation trees into a YAML stream.
|
||||
If stream is None, return the produced string instead.
|
||||
"""
|
||||
getvalue = None
|
||||
if stream is None:
|
||||
if encoding is None:
|
||||
from StringIO import StringIO
|
||||
else:
|
||||
from cStringIO import StringIO
|
||||
stream = StringIO()
|
||||
getvalue = stream.getvalue
|
||||
dumper = Dumper(stream, canonical=canonical, indent=indent, width=width,
|
||||
allow_unicode=allow_unicode, line_break=line_break,
|
||||
encoding=encoding, version=version, tags=tags,
|
||||
explicit_start=explicit_start, explicit_end=explicit_end)
|
||||
dumper.open()
|
||||
for node in nodes:
|
||||
dumper.serialize(node)
|
||||
dumper.close()
|
||||
if getvalue:
|
||||
return getvalue()
|
||||
|
||||
def serialize(node, stream=None, Dumper=Dumper, **kwds):
|
||||
"""
|
||||
Serialize a representation tree into a YAML stream.
|
||||
If stream is None, return the produced string instead.
|
||||
"""
|
||||
return serialize_all([node], stream, Dumper=Dumper, **kwds)
|
||||
|
||||
def dump_all(documents, stream=None, Dumper=Dumper,
|
||||
default_style=None, default_flow_style=None,
|
||||
canonical=None, indent=None, width=None,
|
||||
allow_unicode=None, line_break=None,
|
||||
encoding='utf-8', explicit_start=None, explicit_end=None,
|
||||
version=None, tags=None):
|
||||
"""
|
||||
Serialize a sequence of Python objects into a YAML stream.
|
||||
If stream is None, return the produced string instead.
|
||||
"""
|
||||
getvalue = None
|
||||
if stream is None:
|
||||
if encoding is None:
|
||||
from StringIO import StringIO
|
||||
else:
|
||||
from cStringIO import StringIO
|
||||
stream = StringIO()
|
||||
getvalue = stream.getvalue
|
||||
dumper = Dumper(stream, default_style=default_style,
|
||||
default_flow_style=default_flow_style,
|
||||
canonical=canonical, indent=indent, width=width,
|
||||
allow_unicode=allow_unicode, line_break=line_break,
|
||||
encoding=encoding, version=version, tags=tags,
|
||||
explicit_start=explicit_start, explicit_end=explicit_end)
|
||||
dumper.open()
|
||||
for data in documents:
|
||||
dumper.represent(data)
|
||||
dumper.close()
|
||||
if getvalue:
|
||||
return getvalue()
|
||||
|
||||
def dump(data, stream=None, Dumper=Dumper, **kwds):
|
||||
"""
|
||||
Serialize a Python object into a YAML stream.
|
||||
If stream is None, return the produced string instead.
|
||||
"""
|
||||
return dump_all([data], stream, Dumper=Dumper, **kwds)
|
||||
|
||||
def safe_dump_all(documents, stream=None, **kwds):
|
||||
"""
|
||||
Serialize a sequence of Python objects into a YAML stream.
|
||||
Produce only basic YAML tags.
|
||||
If stream is None, return the produced string instead.
|
||||
"""
|
||||
return dump_all(documents, stream, Dumper=SafeDumper, **kwds)
|
||||
|
||||
def safe_dump(data, stream=None, **kwds):
|
||||
"""
|
||||
Serialize a Python object into a YAML stream.
|
||||
Produce only basic YAML tags.
|
||||
If stream is None, return the produced string instead.
|
||||
"""
|
||||
return dump_all([data], stream, Dumper=SafeDumper, **kwds)
|
||||
|
||||
def add_implicit_resolver(tag, regexp, first=None,
|
||||
Loader=Loader, Dumper=Dumper):
|
||||
"""
|
||||
Add an implicit scalar detector.
|
||||
If an implicit scalar value matches the given regexp,
|
||||
the corresponding tag is assigned to the scalar.
|
||||
first is a sequence of possible initial characters or None.
|
||||
"""
|
||||
Loader.add_implicit_resolver(tag, regexp, first)
|
||||
Dumper.add_implicit_resolver(tag, regexp, first)
|
||||
|
||||
def add_path_resolver(tag, path, kind=None, Loader=Loader, Dumper=Dumper):
|
||||
"""
|
||||
Add a path based resolver for the given tag.
|
||||
A path is a list of keys that forms a path
|
||||
to a node in the representation tree.
|
||||
Keys can be string values, integers, or None.
|
||||
"""
|
||||
Loader.add_path_resolver(tag, path, kind)
|
||||
Dumper.add_path_resolver(tag, path, kind)
|
||||
|
||||
def add_constructor(tag, constructor, Loader=Loader):
|
||||
"""
|
||||
Add a constructor for the given tag.
|
||||
Constructor is a function that accepts a Loader instance
|
||||
and a node object and produces the corresponding Python object.
|
||||
"""
|
||||
Loader.add_constructor(tag, constructor)
|
||||
|
||||
def add_multi_constructor(tag_prefix, multi_constructor, Loader=Loader):
|
||||
"""
|
||||
Add a multi-constructor for the given tag prefix.
|
||||
Multi-constructor is called for a node if its tag starts with tag_prefix.
|
||||
Multi-constructor accepts a Loader instance, a tag suffix,
|
||||
and a node object and produces the corresponding Python object.
|
||||
"""
|
||||
Loader.add_multi_constructor(tag_prefix, multi_constructor)
|
||||
|
||||
def add_representer(data_type, representer, Dumper=Dumper):
|
||||
"""
|
||||
Add a representer for the given type.
|
||||
Representer is a function accepting a Dumper instance
|
||||
and an instance of the given data type
|
||||
and producing the corresponding representation node.
|
||||
"""
|
||||
Dumper.add_representer(data_type, representer)
|
||||
|
||||
def add_multi_representer(data_type, multi_representer, Dumper=Dumper):
|
||||
"""
|
||||
Add a representer for the given type.
|
||||
Multi-representer is a function accepting a Dumper instance
|
||||
and an instance of the given data type or subtype
|
||||
and producing the corresponding representation node.
|
||||
"""
|
||||
Dumper.add_multi_representer(data_type, multi_representer)
|
||||
|
||||
class YAMLObjectMetaclass(type):
|
||||
"""
|
||||
The metaclass for YAMLObject.
|
||||
"""
|
||||
def __init__(cls, name, bases, kwds):
|
||||
super(YAMLObjectMetaclass, cls).__init__(name, bases, kwds)
|
||||
if 'yaml_tag' in kwds and kwds['yaml_tag'] is not None:
|
||||
cls.yaml_loader.add_constructor(cls.yaml_tag, cls.from_yaml)
|
||||
cls.yaml_dumper.add_representer(cls, cls.to_yaml)
|
||||
|
||||
class YAMLObject(object):
|
||||
"""
|
||||
An object that can dump itself to a YAML stream
|
||||
and load itself from a YAML stream.
|
||||
"""
|
||||
|
||||
__metaclass__ = YAMLObjectMetaclass
|
||||
__slots__ = () # no direct instantiation, so allow immutable subclasses
|
||||
|
||||
yaml_loader = Loader
|
||||
yaml_dumper = Dumper
|
||||
|
||||
yaml_tag = None
|
||||
yaml_flow_style = None
|
||||
|
||||
def from_yaml(cls, loader, node):
|
||||
"""
|
||||
Convert a representation node to a Python object.
|
||||
"""
|
||||
return loader.construct_yaml_object(node, cls)
|
||||
from_yaml = classmethod(from_yaml)
|
||||
|
||||
def to_yaml(cls, dumper, data):
|
||||
"""
|
||||
Convert a Python object to a representation node.
|
||||
"""
|
||||
return dumper.represent_yaml_object(cls.yaml_tag, data, cls,
|
||||
flow_style=cls.yaml_flow_style)
|
||||
to_yaml = classmethod(to_yaml)
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
|
||||
__all__ = ['Composer', 'ComposerError']
|
||||
|
||||
from error import MarkedYAMLError
|
||||
from events import *
|
||||
from nodes import *
|
||||
|
||||
class ComposerError(MarkedYAMLError):
|
||||
pass
|
||||
|
||||
class Composer(object):
|
||||
|
||||
def __init__(self):
|
||||
self.anchors = {}
|
||||
|
||||
def check_node(self):
|
||||
# Drop the STREAM-START event.
|
||||
if self.check_event(StreamStartEvent):
|
||||
self.get_event()
|
||||
|
||||
# If there are more documents available?
|
||||
return not self.check_event(StreamEndEvent)
|
||||
|
||||
def get_node(self):
|
||||
# Get the root node of the next document.
|
||||
if not self.check_event(StreamEndEvent):
|
||||
return self.compose_document()
|
||||
|
||||
def get_single_node(self):
|
||||
# Drop the STREAM-START event.
|
||||
self.get_event()
|
||||
|
||||
# Compose a document if the stream is not empty.
|
||||
document = None
|
||||
if not self.check_event(StreamEndEvent):
|
||||
document = self.compose_document()
|
||||
|
||||
# Ensure that the stream contains no more documents.
|
||||
if not self.check_event(StreamEndEvent):
|
||||
event = self.get_event()
|
||||
raise ComposerError("expected a single document in the stream",
|
||||
document.start_mark, "but found another document",
|
||||
event.start_mark)
|
||||
|
||||
# Drop the STREAM-END event.
|
||||
self.get_event()
|
||||
|
||||
return document
|
||||
|
||||
def compose_document(self):
|
||||
# Drop the DOCUMENT-START event.
|
||||
self.get_event()
|
||||
|
||||
# Compose the root node.
|
||||
node = self.compose_node(None, None)
|
||||
|
||||
# Drop the DOCUMENT-END event.
|
||||
self.get_event()
|
||||
|
||||
self.anchors = {}
|
||||
return node
|
||||
|
||||
def compose_node(self, parent, index):
|
||||
if self.check_event(AliasEvent):
|
||||
event = self.get_event()
|
||||
anchor = event.anchor
|
||||
if anchor not in self.anchors:
|
||||
raise ComposerError(None, None, "found undefined alias %r"
|
||||
% anchor.encode('utf-8'), event.start_mark)
|
||||
return self.anchors[anchor]
|
||||
event = self.peek_event()
|
||||
anchor = event.anchor
|
||||
if anchor is not None:
|
||||
if anchor in self.anchors:
|
||||
raise ComposerError("found duplicate anchor %r; first occurence"
|
||||
% anchor.encode('utf-8'), self.anchors[anchor].start_mark,
|
||||
"second occurence", event.start_mark)
|
||||
self.descend_resolver(parent, index)
|
||||
if self.check_event(ScalarEvent):
|
||||
node = self.compose_scalar_node(anchor)
|
||||
elif self.check_event(SequenceStartEvent):
|
||||
node = self.compose_sequence_node(anchor)
|
||||
elif self.check_event(MappingStartEvent):
|
||||
node = self.compose_mapping_node(anchor)
|
||||
self.ascend_resolver()
|
||||
return node
|
||||
|
||||
def compose_scalar_node(self, anchor):
|
||||
event = self.get_event()
|
||||
tag = event.tag
|
||||
if tag is None or tag == u'!':
|
||||
tag = self.resolve(ScalarNode, event.value, event.implicit)
|
||||
node = ScalarNode(tag, event.value,
|
||||
event.start_mark, event.end_mark, style=event.style)
|
||||
if anchor is not None:
|
||||
self.anchors[anchor] = node
|
||||
return node
|
||||
|
||||
def compose_sequence_node(self, anchor):
|
||||
start_event = self.get_event()
|
||||
tag = start_event.tag
|
||||
if tag is None or tag == u'!':
|
||||
tag = self.resolve(SequenceNode, None, start_event.implicit)
|
||||
node = SequenceNode(tag, [],
|
||||
start_event.start_mark, None,
|
||||
flow_style=start_event.flow_style)
|
||||
if anchor is not None:
|
||||
self.anchors[anchor] = node
|
||||
index = 0
|
||||
while not self.check_event(SequenceEndEvent):
|
||||
node.value.append(self.compose_node(node, index))
|
||||
index += 1
|
||||
end_event = self.get_event()
|
||||
node.end_mark = end_event.end_mark
|
||||
return node
|
||||
|
||||
def compose_mapping_node(self, anchor):
|
||||
start_event = self.get_event()
|
||||
tag = start_event.tag
|
||||
if tag is None or tag == u'!':
|
||||
tag = self.resolve(MappingNode, None, start_event.implicit)
|
||||
node = MappingNode(tag, [],
|
||||
start_event.start_mark, None,
|
||||
flow_style=start_event.flow_style)
|
||||
if anchor is not None:
|
||||
self.anchors[anchor] = node
|
||||
while not self.check_event(MappingEndEvent):
|
||||
#key_event = self.peek_event()
|
||||
item_key = self.compose_node(node, None)
|
||||
#if item_key in node.value:
|
||||
# raise ComposerError("while composing a mapping", start_event.start_mark,
|
||||
# "found duplicate key", key_event.start_mark)
|
||||
item_value = self.compose_node(node, item_key)
|
||||
#node.value[item_key] = item_value
|
||||
node.value.append((item_key, item_value))
|
||||
end_event = self.get_event()
|
||||
node.end_mark = end_event.end_mark
|
||||
return node
|
||||
|
||||
@@ -0,0 +1,684 @@
|
||||
|
||||
__all__ = ['BaseConstructor', 'SafeConstructor', 'Constructor',
|
||||
'ConstructorError']
|
||||
|
||||
from error import *
|
||||
from nodes import *
|
||||
|
||||
import datetime
|
||||
|
||||
try:
|
||||
set
|
||||
except NameError:
|
||||
from sets import Set as set
|
||||
|
||||
import binascii, re, sys, types
|
||||
|
||||
class ConstructorError(MarkedYAMLError):
|
||||
pass
|
||||
|
||||
class BaseConstructor(object):
|
||||
|
||||
yaml_constructors = {}
|
||||
yaml_multi_constructors = {}
|
||||
|
||||
def __init__(self):
|
||||
self.constructed_objects = {}
|
||||
self.recursive_objects = {}
|
||||
self.state_generators = []
|
||||
self.deep_construct = False
|
||||
|
||||
def check_data(self):
|
||||
# If there are more documents available?
|
||||
return self.check_node()
|
||||
|
||||
def get_data(self):
|
||||
# Construct and return the next document.
|
||||
if self.check_node():
|
||||
return self.construct_document(self.get_node())
|
||||
|
||||
def get_single_data(self):
|
||||
# Ensure that the stream contains a single document and construct it.
|
||||
node = self.get_single_node()
|
||||
if node is not None:
|
||||
return self.construct_document(node)
|
||||
return None
|
||||
|
||||
def construct_document(self, node):
|
||||
data = self.construct_object(node)
|
||||
while self.state_generators:
|
||||
state_generators = self.state_generators
|
||||
self.state_generators = []
|
||||
for generator in state_generators:
|
||||
for dummy in generator:
|
||||
pass
|
||||
self.constructed_objects = {}
|
||||
self.recursive_objects = {}
|
||||
self.deep_construct = False
|
||||
return data
|
||||
|
||||
def construct_object(self, node, deep=False):
|
||||
if deep:
|
||||
old_deep = self.deep_construct
|
||||
self.deep_construct = True
|
||||
if node in self.constructed_objects:
|
||||
return self.constructed_objects[node]
|
||||
if node in self.recursive_objects:
|
||||
raise ConstructorError(None, None,
|
||||
"found unconstructable recursive node", node.start_mark)
|
||||
self.recursive_objects[node] = None
|
||||
constructor = None
|
||||
tag_suffix = None
|
||||
if node.tag in self.yaml_constructors:
|
||||
constructor = self.yaml_constructors[node.tag]
|
||||
else:
|
||||
for tag_prefix in self.yaml_multi_constructors:
|
||||
if node.tag.startswith(tag_prefix):
|
||||
tag_suffix = node.tag[len(tag_prefix):]
|
||||
constructor = self.yaml_multi_constructors[tag_prefix]
|
||||
break
|
||||
else:
|
||||
if None in self.yaml_multi_constructors:
|
||||
tag_suffix = node.tag
|
||||
constructor = self.yaml_multi_constructors[None]
|
||||
elif None in self.yaml_constructors:
|
||||
constructor = self.yaml_constructors[None]
|
||||
elif isinstance(node, ScalarNode):
|
||||
constructor = self.__class__.construct_scalar
|
||||
elif isinstance(node, SequenceNode):
|
||||
constructor = self.__class__.construct_sequence
|
||||
elif isinstance(node, MappingNode):
|
||||
constructor = self.__class__.construct_mapping
|
||||
if tag_suffix is None:
|
||||
data = constructor(self, node)
|
||||
else:
|
||||
data = constructor(self, tag_suffix, node)
|
||||
if isinstance(data, types.GeneratorType):
|
||||
generator = data
|
||||
data = generator.next()
|
||||
if self.deep_construct:
|
||||
for dummy in generator:
|
||||
pass
|
||||
else:
|
||||
self.state_generators.append(generator)
|
||||
self.constructed_objects[node] = data
|
||||
del self.recursive_objects[node]
|
||||
if deep:
|
||||
self.deep_construct = old_deep
|
||||
return data
|
||||
|
||||
def construct_scalar(self, node):
|
||||
if not isinstance(node, ScalarNode):
|
||||
raise ConstructorError(None, None,
|
||||
"expected a scalar node, but found %s" % node.id,
|
||||
node.start_mark)
|
||||
return node.value
|
||||
|
||||
def construct_sequence(self, node, deep=False):
|
||||
if not isinstance(node, SequenceNode):
|
||||
raise ConstructorError(None, None,
|
||||
"expected a sequence node, but found %s" % node.id,
|
||||
node.start_mark)
|
||||
return [self.construct_object(child, deep=deep)
|
||||
for child in node.value]
|
||||
|
||||
def construct_mapping(self, node, deep=False):
|
||||
if not isinstance(node, MappingNode):
|
||||
raise ConstructorError(None, None,
|
||||
"expected a mapping node, but found %s" % node.id,
|
||||
node.start_mark)
|
||||
mapping = {}
|
||||
for key_node, value_node in node.value:
|
||||
key = self.construct_object(key_node, deep=deep)
|
||||
try:
|
||||
hash(key)
|
||||
except TypeError, exc:
|
||||
raise ConstructorError("while constructing a mapping", node.start_mark,
|
||||
"found unacceptable key (%s)" % exc, key_node.start_mark)
|
||||
value = self.construct_object(value_node, deep=deep)
|
||||
mapping[key] = value
|
||||
return mapping
|
||||
|
||||
def construct_pairs(self, node, deep=False):
|
||||
if not isinstance(node, MappingNode):
|
||||
raise ConstructorError(None, None,
|
||||
"expected a mapping node, but found %s" % node.id,
|
||||
node.start_mark)
|
||||
pairs = []
|
||||
for key_node, value_node in node.value:
|
||||
key = self.construct_object(key_node, deep=deep)
|
||||
value = self.construct_object(value_node, deep=deep)
|
||||
pairs.append((key, value))
|
||||
return pairs
|
||||
|
||||
def add_constructor(cls, tag, constructor):
|
||||
if not 'yaml_constructors' in cls.__dict__:
|
||||
cls.yaml_constructors = cls.yaml_constructors.copy()
|
||||
cls.yaml_constructors[tag] = constructor
|
||||
add_constructor = classmethod(add_constructor)
|
||||
|
||||
def add_multi_constructor(cls, tag_prefix, multi_constructor):
|
||||
if not 'yaml_multi_constructors' in cls.__dict__:
|
||||
cls.yaml_multi_constructors = cls.yaml_multi_constructors.copy()
|
||||
cls.yaml_multi_constructors[tag_prefix] = multi_constructor
|
||||
add_multi_constructor = classmethod(add_multi_constructor)
|
||||
|
||||
class SafeConstructor(BaseConstructor):
|
||||
|
||||
def construct_scalar(self, node):
|
||||
if isinstance(node, MappingNode):
|
||||
for key_node, value_node in node.value:
|
||||
if key_node.tag == u'tag:yaml.org,2002:value':
|
||||
return self.construct_scalar(value_node)
|
||||
return BaseConstructor.construct_scalar(self, node)
|
||||
|
||||
def flatten_mapping(self, node):
|
||||
merge = []
|
||||
index = 0
|
||||
while index < len(node.value):
|
||||
key_node, value_node = node.value[index]
|
||||
if key_node.tag == u'tag:yaml.org,2002:merge':
|
||||
del node.value[index]
|
||||
if isinstance(value_node, MappingNode):
|
||||
self.flatten_mapping(value_node)
|
||||
merge.extend(value_node.value)
|
||||
elif isinstance(value_node, SequenceNode):
|
||||
submerge = []
|
||||
for subnode in value_node.value:
|
||||
if not isinstance(subnode, MappingNode):
|
||||
raise ConstructorError("while constructing a mapping",
|
||||
node.start_mark,
|
||||
"expected a mapping for merging, but found %s"
|
||||
% subnode.id, subnode.start_mark)
|
||||
self.flatten_mapping(subnode)
|
||||
submerge.append(subnode.value)
|
||||
submerge.reverse()
|
||||
for value in submerge:
|
||||
merge.extend(value)
|
||||
else:
|
||||
raise ConstructorError("while constructing a mapping", node.start_mark,
|
||||
"expected a mapping or list of mappings for merging, but found %s"
|
||||
% value_node.id, value_node.start_mark)
|
||||
elif key_node.tag == u'tag:yaml.org,2002:value':
|
||||
key_node.tag = u'tag:yaml.org,2002:str'
|
||||
index += 1
|
||||
else:
|
||||
index += 1
|
||||
if merge:
|
||||
node.value = merge + node.value
|
||||
|
||||
def construct_mapping(self, node, deep=False):
|
||||
if isinstance(node, MappingNode):
|
||||
self.flatten_mapping(node)
|
||||
return BaseConstructor.construct_mapping(self, node, deep=deep)
|
||||
|
||||
def construct_yaml_null(self, node):
|
||||
self.construct_scalar(node)
|
||||
return None
|
||||
|
||||
bool_values = {
|
||||
u'yes': True,
|
||||
u'no': False,
|
||||
u'true': True,
|
||||
u'false': False,
|
||||
u'on': True,
|
||||
u'off': False,
|
||||
}
|
||||
|
||||
def construct_yaml_bool(self, node):
|
||||
value = self.construct_scalar(node)
|
||||
return self.bool_values[value.lower()]
|
||||
|
||||
def construct_yaml_int(self, node):
|
||||
value = str(self.construct_scalar(node))
|
||||
value = value.replace('_', '')
|
||||
sign = +1
|
||||
if value[0] == '-':
|
||||
sign = -1
|
||||
if value[0] in '+-':
|
||||
value = value[1:]
|
||||
if value == '0':
|
||||
return 0
|
||||
elif value.startswith('0b'):
|
||||
return sign*int(value[2:], 2)
|
||||
elif value.startswith('0x'):
|
||||
return sign*int(value[2:], 16)
|
||||
elif value[0] == '0':
|
||||
return sign*int(value, 8)
|
||||
elif ':' in value:
|
||||
digits = [int(part) for part in value.split(':')]
|
||||
digits.reverse()
|
||||
base = 1
|
||||
value = 0
|
||||
for digit in digits:
|
||||
value += digit*base
|
||||
base *= 60
|
||||
return sign*value
|
||||
else:
|
||||
return sign*int(value)
|
||||
|
||||
inf_value = 1e300
|
||||
while inf_value != inf_value*inf_value:
|
||||
inf_value *= inf_value
|
||||
nan_value = -inf_value/inf_value # Trying to make a quiet NaN (like C99).
|
||||
|
||||
def construct_yaml_float(self, node):
|
||||
value = str(self.construct_scalar(node))
|
||||
value = value.replace('_', '').lower()
|
||||
sign = +1
|
||||
if value[0] == '-':
|
||||
sign = -1
|
||||
if value[0] in '+-':
|
||||
value = value[1:]
|
||||
if value == '.inf':
|
||||
return sign*self.inf_value
|
||||
elif value == '.nan':
|
||||
return self.nan_value
|
||||
elif ':' in value:
|
||||
digits = [float(part) for part in value.split(':')]
|
||||
digits.reverse()
|
||||
base = 1
|
||||
value = 0.0
|
||||
for digit in digits:
|
||||
value += digit*base
|
||||
base *= 60
|
||||
return sign*value
|
||||
else:
|
||||
return sign*float(value)
|
||||
|
||||
def construct_yaml_binary(self, node):
|
||||
value = self.construct_scalar(node)
|
||||
try:
|
||||
return str(value).decode('base64')
|
||||
except (binascii.Error, UnicodeEncodeError), exc:
|
||||
raise ConstructorError(None, None,
|
||||
"failed to decode base64 data: %s" % exc, node.start_mark)
|
||||
|
||||
timestamp_regexp = re.compile(
|
||||
ur'''^(?P<year>[0-9][0-9][0-9][0-9])
|
||||
-(?P<month>[0-9][0-9]?)
|
||||
-(?P<day>[0-9][0-9]?)
|
||||
(?:(?:[Tt]|[ \t]+)
|
||||
(?P<hour>[0-9][0-9]?)
|
||||
:(?P<minute>[0-9][0-9])
|
||||
:(?P<second>[0-9][0-9])
|
||||
(?:\.(?P<fraction>[0-9]*))?
|
||||
(?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
|
||||
(?::(?P<tz_minute>[0-9][0-9]))?))?)?$''', re.X)
|
||||
|
||||
def construct_yaml_timestamp(self, node):
|
||||
value = self.construct_scalar(node)
|
||||
match = self.timestamp_regexp.match(node.value)
|
||||
values = match.groupdict()
|
||||
year = int(values['year'])
|
||||
month = int(values['month'])
|
||||
day = int(values['day'])
|
||||
if not values['hour']:
|
||||
return datetime.date(year, month, day)
|
||||
hour = int(values['hour'])
|
||||
minute = int(values['minute'])
|
||||
second = int(values['second'])
|
||||
fraction = 0
|
||||
if values['fraction']:
|
||||
fraction = values['fraction'][:6]
|
||||
while len(fraction) < 6:
|
||||
fraction += '0'
|
||||
fraction = int(fraction)
|
||||
delta = None
|
||||
if values['tz_sign']:
|
||||
tz_hour = int(values['tz_hour'])
|
||||
tz_minute = int(values['tz_minute'] or 0)
|
||||
delta = datetime.timedelta(hours=tz_hour, minutes=tz_minute)
|
||||
if values['tz_sign'] == '-':
|
||||
delta = -delta
|
||||
data = datetime.datetime(year, month, day, hour, minute, second, fraction)
|
||||
if delta:
|
||||
data -= delta
|
||||
return data
|
||||
|
||||
def construct_yaml_omap(self, node):
|
||||
# Note: we do not check for duplicate keys, because it's too
|
||||
# CPU-expensive.
|
||||
omap = []
|
||||
yield omap
|
||||
if not isinstance(node, SequenceNode):
|
||||
raise ConstructorError("while constructing an ordered map", node.start_mark,
|
||||
"expected a sequence, but found %s" % node.id, node.start_mark)
|
||||
for subnode in node.value:
|
||||
if not isinstance(subnode, MappingNode):
|
||||
raise ConstructorError("while constructing an ordered map", node.start_mark,
|
||||
"expected a mapping of length 1, but found %s" % subnode.id,
|
||||
subnode.start_mark)
|
||||
if len(subnode.value) != 1:
|
||||
raise ConstructorError("while constructing an ordered map", node.start_mark,
|
||||
"expected a single mapping item, but found %d items" % len(subnode.value),
|
||||
subnode.start_mark)
|
||||
key_node, value_node = subnode.value[0]
|
||||
key = self.construct_object(key_node)
|
||||
value = self.construct_object(value_node)
|
||||
omap.append((key, value))
|
||||
|
||||
def construct_yaml_pairs(self, node):
|
||||
# Note: the same code as `construct_yaml_omap`.
|
||||
pairs = []
|
||||
yield pairs
|
||||
if not isinstance(node, SequenceNode):
|
||||
raise ConstructorError("while constructing pairs", node.start_mark,
|
||||
"expected a sequence, but found %s" % node.id, node.start_mark)
|
||||
for subnode in node.value:
|
||||
if not isinstance(subnode, MappingNode):
|
||||
raise ConstructorError("while constructing pairs", node.start_mark,
|
||||
"expected a mapping of length 1, but found %s" % subnode.id,
|
||||
subnode.start_mark)
|
||||
if len(subnode.value) != 1:
|
||||
raise ConstructorError("while constructing pairs", node.start_mark,
|
||||
"expected a single mapping item, but found %d items" % len(subnode.value),
|
||||
subnode.start_mark)
|
||||
key_node, value_node = subnode.value[0]
|
||||
key = self.construct_object(key_node)
|
||||
value = self.construct_object(value_node)
|
||||
pairs.append((key, value))
|
||||
|
||||
def construct_yaml_set(self, node):
|
||||
data = set()
|
||||
yield data
|
||||
value = self.construct_mapping(node)
|
||||
data.update(value)
|
||||
|
||||
def construct_yaml_str(self, node):
|
||||
value = self.construct_scalar(node)
|
||||
try:
|
||||
return value.encode('ascii')
|
||||
except UnicodeEncodeError:
|
||||
return value
|
||||
|
||||
def construct_yaml_seq(self, node):
|
||||
data = []
|
||||
yield data
|
||||
data.extend(self.construct_sequence(node))
|
||||
|
||||
def construct_yaml_map(self, node):
|
||||
data = {}
|
||||
yield data
|
||||
value = self.construct_mapping(node)
|
||||
data.update(value)
|
||||
|
||||
def construct_yaml_object(self, node, cls):
|
||||
data = cls.__new__(cls)
|
||||
yield data
|
||||
if hasattr(data, '__setstate__'):
|
||||
state = self.construct_mapping(node, deep=True)
|
||||
data.__setstate__(state)
|
||||
else:
|
||||
state = self.construct_mapping(node)
|
||||
data.__dict__.update(state)
|
||||
|
||||
def construct_undefined(self, node):
|
||||
raise ConstructorError(None, None,
|
||||
"could not determine a constructor for the tag %r" % node.tag.encode('utf-8'),
|
||||
node.start_mark)
|
||||
|
||||
SafeConstructor.add_constructor(
|
||||
u'tag:yaml.org,2002:null',
|
||||
SafeConstructor.construct_yaml_null)
|
||||
|
||||
SafeConstructor.add_constructor(
|
||||
u'tag:yaml.org,2002:bool',
|
||||
SafeConstructor.construct_yaml_bool)
|
||||
|
||||
SafeConstructor.add_constructor(
|
||||
u'tag:yaml.org,2002:int',
|
||||
SafeConstructor.construct_yaml_int)
|
||||
|
||||
SafeConstructor.add_constructor(
|
||||
u'tag:yaml.org,2002:float',
|
||||
SafeConstructor.construct_yaml_float)
|
||||
|
||||
SafeConstructor.add_constructor(
|
||||
u'tag:yaml.org,2002:binary',
|
||||
SafeConstructor.construct_yaml_binary)
|
||||
|
||||
SafeConstructor.add_constructor(
|
||||
u'tag:yaml.org,2002:timestamp',
|
||||
SafeConstructor.construct_yaml_timestamp)
|
||||
|
||||
SafeConstructor.add_constructor(
|
||||
u'tag:yaml.org,2002:omap',
|
||||
SafeConstructor.construct_yaml_omap)
|
||||
|
||||
SafeConstructor.add_constructor(
|
||||
u'tag:yaml.org,2002:pairs',
|
||||
SafeConstructor.construct_yaml_pairs)
|
||||
|
||||
SafeConstructor.add_constructor(
|
||||
u'tag:yaml.org,2002:set',
|
||||
SafeConstructor.construct_yaml_set)
|
||||
|
||||
SafeConstructor.add_constructor(
|
||||
u'tag:yaml.org,2002:str',
|
||||
SafeConstructor.construct_yaml_str)
|
||||
|
||||
SafeConstructor.add_constructor(
|
||||
u'tag:yaml.org,2002:seq',
|
||||
SafeConstructor.construct_yaml_seq)
|
||||
|
||||
SafeConstructor.add_constructor(
|
||||
u'tag:yaml.org,2002:map',
|
||||
SafeConstructor.construct_yaml_map)
|
||||
|
||||
SafeConstructor.add_constructor(None,
|
||||
SafeConstructor.construct_undefined)
|
||||
|
||||
class Constructor(SafeConstructor):
|
||||
|
||||
def construct_python_str(self, node):
|
||||
return self.construct_scalar(node).encode('utf-8')
|
||||
|
||||
def construct_python_unicode(self, node):
|
||||
return self.construct_scalar(node)
|
||||
|
||||
def construct_python_long(self, node):
|
||||
return long(self.construct_yaml_int(node))
|
||||
|
||||
def construct_python_complex(self, node):
|
||||
return complex(self.construct_scalar(node))
|
||||
|
||||
def construct_python_tuple(self, node):
|
||||
return tuple(self.construct_sequence(node))
|
||||
|
||||
def find_python_module(self, name, mark):
|
||||
if not name:
|
||||
raise ConstructorError("while constructing a Python module", mark,
|
||||
"expected non-empty name appended to the tag", mark)
|
||||
try:
|
||||
__import__(name)
|
||||
except ImportError, exc:
|
||||
raise ConstructorError("while constructing a Python module", mark,
|
||||
"cannot find module %r (%s)" % (name.encode('utf-8'), exc), mark)
|
||||
return sys.modules[name]
|
||||
|
||||
def find_python_name(self, name, mark):
|
||||
if not name:
|
||||
raise ConstructorError("while constructing a Python object", mark,
|
||||
"expected non-empty name appended to the tag", mark)
|
||||
if u'.' in name:
|
||||
# Python 2.4 only
|
||||
#module_name, object_name = name.rsplit('.', 1)
|
||||
items = name.split('.')
|
||||
object_name = items.pop()
|
||||
module_name = '.'.join(items)
|
||||
else:
|
||||
module_name = '__builtin__'
|
||||
object_name = name
|
||||
try:
|
||||
__import__(module_name)
|
||||
except ImportError, exc:
|
||||
raise ConstructorError("while constructing a Python object", mark,
|
||||
"cannot find module %r (%s)" % (module_name.encode('utf-8'), exc), mark)
|
||||
module = sys.modules[module_name]
|
||||
if not hasattr(module, object_name):
|
||||
raise ConstructorError("while constructing a Python object", mark,
|
||||
"cannot find %r in the module %r" % (object_name.encode('utf-8'),
|
||||
module.__name__), mark)
|
||||
return getattr(module, object_name)
|
||||
|
||||
def construct_python_name(self, suffix, node):
|
||||
value = self.construct_scalar(node)
|
||||
if value:
|
||||
raise ConstructorError("while constructing a Python name", node.start_mark,
|
||||
"expected the empty value, but found %r" % value.encode('utf-8'),
|
||||
node.start_mark)
|
||||
return self.find_python_name(suffix, node.start_mark)
|
||||
|
||||
def construct_python_module(self, suffix, node):
|
||||
value = self.construct_scalar(node)
|
||||
if value:
|
||||
raise ConstructorError("while constructing a Python module", node.start_mark,
|
||||
"expected the empty value, but found %r" % value.encode('utf-8'),
|
||||
node.start_mark)
|
||||
return self.find_python_module(suffix, node.start_mark)
|
||||
|
||||
class classobj: pass
|
||||
|
||||
def make_python_instance(self, suffix, node,
|
||||
args=None, kwds=None, newobj=False):
|
||||
if not args:
|
||||
args = []
|
||||
if not kwds:
|
||||
kwds = {}
|
||||
cls = self.find_python_name(suffix, node.start_mark)
|
||||
if newobj and isinstance(cls, type(self.classobj)) \
|
||||
and not args and not kwds:
|
||||
instance = self.classobj()
|
||||
instance.__class__ = cls
|
||||
return instance
|
||||
elif newobj and isinstance(cls, type):
|
||||
return cls.__new__(cls, *args, **kwds)
|
||||
else:
|
||||
return cls(*args, **kwds)
|
||||
|
||||
def set_python_instance_state(self, instance, state):
|
||||
if hasattr(instance, '__setstate__'):
|
||||
instance.__setstate__(state)
|
||||
else:
|
||||
slotstate = {}
|
||||
if isinstance(state, tuple) and len(state) == 2:
|
||||
state, slotstate = state
|
||||
if hasattr(instance, '__dict__'):
|
||||
instance.__dict__.update(state)
|
||||
elif state:
|
||||
slotstate.update(state)
|
||||
for key, value in slotstate.items():
|
||||
setattr(object, key, value)
|
||||
|
||||
def construct_python_object(self, suffix, node):
|
||||
# Format:
|
||||
# !!python/object:module.name { ... state ... }
|
||||
instance = self.make_python_instance(suffix, node, newobj=True)
|
||||
yield instance
|
||||
deep = hasattr(instance, '__setstate__')
|
||||
state = self.construct_mapping(node, deep=deep)
|
||||
self.set_python_instance_state(instance, state)
|
||||
|
||||
def construct_python_object_apply(self, suffix, node, newobj=False):
|
||||
# Format:
|
||||
# !!python/object/apply # (or !!python/object/new)
|
||||
# args: [ ... arguments ... ]
|
||||
# kwds: { ... keywords ... }
|
||||
# state: ... state ...
|
||||
# listitems: [ ... listitems ... ]
|
||||
# dictitems: { ... dictitems ... }
|
||||
# or short format:
|
||||
# !!python/object/apply [ ... arguments ... ]
|
||||
# The difference between !!python/object/apply and !!python/object/new
|
||||
# is how an object is created, check make_python_instance for details.
|
||||
if isinstance(node, SequenceNode):
|
||||
args = self.construct_sequence(node, deep=True)
|
||||
kwds = {}
|
||||
state = {}
|
||||
listitems = []
|
||||
dictitems = {}
|
||||
else:
|
||||
value = self.construct_mapping(node, deep=True)
|
||||
args = value.get('args', [])
|
||||
kwds = value.get('kwds', {})
|
||||
state = value.get('state', {})
|
||||
listitems = value.get('listitems', [])
|
||||
dictitems = value.get('dictitems', {})
|
||||
instance = self.make_python_instance(suffix, node, args, kwds, newobj)
|
||||
if state:
|
||||
self.set_python_instance_state(instance, state)
|
||||
if listitems:
|
||||
instance.extend(listitems)
|
||||
if dictitems:
|
||||
for key in dictitems:
|
||||
instance[key] = dictitems[key]
|
||||
return instance
|
||||
|
||||
def construct_python_object_new(self, suffix, node):
|
||||
return self.construct_python_object_apply(suffix, node, newobj=True)
|
||||
|
||||
Constructor.add_constructor(
|
||||
u'tag:yaml.org,2002:python/none',
|
||||
Constructor.construct_yaml_null)
|
||||
|
||||
Constructor.add_constructor(
|
||||
u'tag:yaml.org,2002:python/bool',
|
||||
Constructor.construct_yaml_bool)
|
||||
|
||||
Constructor.add_constructor(
|
||||
u'tag:yaml.org,2002:python/str',
|
||||
Constructor.construct_python_str)
|
||||
|
||||
Constructor.add_constructor(
|
||||
u'tag:yaml.org,2002:python/unicode',
|
||||
Constructor.construct_python_unicode)
|
||||
|
||||
Constructor.add_constructor(
|
||||
u'tag:yaml.org,2002:python/int',
|
||||
Constructor.construct_yaml_int)
|
||||
|
||||
Constructor.add_constructor(
|
||||
u'tag:yaml.org,2002:python/long',
|
||||
Constructor.construct_python_long)
|
||||
|
||||
Constructor.add_constructor(
|
||||
u'tag:yaml.org,2002:python/float',
|
||||
Constructor.construct_yaml_float)
|
||||
|
||||
Constructor.add_constructor(
|
||||
u'tag:yaml.org,2002:python/complex',
|
||||
Constructor.construct_python_complex)
|
||||
|
||||
Constructor.add_constructor(
|
||||
u'tag:yaml.org,2002:python/list',
|
||||
Constructor.construct_yaml_seq)
|
||||
|
||||
Constructor.add_constructor(
|
||||
u'tag:yaml.org,2002:python/tuple',
|
||||
Constructor.construct_python_tuple)
|
||||
|
||||
Constructor.add_constructor(
|
||||
u'tag:yaml.org,2002:python/dict',
|
||||
Constructor.construct_yaml_map)
|
||||
|
||||
Constructor.add_multi_constructor(
|
||||
u'tag:yaml.org,2002:python/name:',
|
||||
Constructor.construct_python_name)
|
||||
|
||||
Constructor.add_multi_constructor(
|
||||
u'tag:yaml.org,2002:python/module:',
|
||||
Constructor.construct_python_module)
|
||||
|
||||
Constructor.add_multi_constructor(
|
||||
u'tag:yaml.org,2002:python/object:',
|
||||
Constructor.construct_python_object)
|
||||
|
||||
Constructor.add_multi_constructor(
|
||||
u'tag:yaml.org,2002:python/object/apply:',
|
||||
Constructor.construct_python_object_apply)
|
||||
|
||||
Constructor.add_multi_constructor(
|
||||
u'tag:yaml.org,2002:python/object/new:',
|
||||
Constructor.construct_python_object_new)
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
|
||||
__all__ = ['CBaseLoader', 'CSafeLoader', 'CLoader',
|
||||
'CBaseDumper', 'CSafeDumper', 'CDumper']
|
||||
|
||||
from _yaml import CParser, CEmitter
|
||||
|
||||
from constructor import *
|
||||
|
||||
from serializer import *
|
||||
from representer import *
|
||||
|
||||
from resolver import *
|
||||
|
||||
class CBaseLoader(CParser, BaseConstructor, BaseResolver):
|
||||
|
||||
def __init__(self, stream):
|
||||
CParser.__init__(self, stream)
|
||||
BaseConstructor.__init__(self)
|
||||
BaseResolver.__init__(self)
|
||||
|
||||
class CSafeLoader(CParser, SafeConstructor, Resolver):
|
||||
|
||||
def __init__(self, stream):
|
||||
CParser.__init__(self, stream)
|
||||
SafeConstructor.__init__(self)
|
||||
Resolver.__init__(self)
|
||||
|
||||
class CLoader(CParser, Constructor, Resolver):
|
||||
|
||||
def __init__(self, stream):
|
||||
CParser.__init__(self, stream)
|
||||
Constructor.__init__(self)
|
||||
Resolver.__init__(self)
|
||||
|
||||
class CBaseDumper(CEmitter, BaseRepresenter, BaseResolver):
|
||||
|
||||
def __init__(self, stream,
|
||||
default_style=None, default_flow_style=None,
|
||||
canonical=None, indent=None, width=None,
|
||||
allow_unicode=None, line_break=None,
|
||||
encoding=None, explicit_start=None, explicit_end=None,
|
||||
version=None, tags=None):
|
||||
CEmitter.__init__(self, stream, canonical=canonical,
|
||||
indent=indent, width=width, encoding=encoding,
|
||||
allow_unicode=allow_unicode, line_break=line_break,
|
||||
explicit_start=explicit_start, explicit_end=explicit_end,
|
||||
version=version, tags=tags)
|
||||
Representer.__init__(self, default_style=default_style,
|
||||
default_flow_style=default_flow_style)
|
||||
Resolver.__init__(self)
|
||||
|
||||
class CSafeDumper(CEmitter, SafeRepresenter, Resolver):
|
||||
|
||||
def __init__(self, stream,
|
||||
default_style=None, default_flow_style=None,
|
||||
canonical=None, indent=None, width=None,
|
||||
allow_unicode=None, line_break=None,
|
||||
encoding=None, explicit_start=None, explicit_end=None,
|
||||
version=None, tags=None):
|
||||
CEmitter.__init__(self, stream, canonical=canonical,
|
||||
indent=indent, width=width, encoding=encoding,
|
||||
allow_unicode=allow_unicode, line_break=line_break,
|
||||
explicit_start=explicit_start, explicit_end=explicit_end,
|
||||
version=version, tags=tags)
|
||||
SafeRepresenter.__init__(self, default_style=default_style,
|
||||
default_flow_style=default_flow_style)
|
||||
Resolver.__init__(self)
|
||||
|
||||
class CDumper(CEmitter, Serializer, Representer, Resolver):
|
||||
|
||||
def __init__(self, stream,
|
||||
default_style=None, default_flow_style=None,
|
||||
canonical=None, indent=None, width=None,
|
||||
allow_unicode=None, line_break=None,
|
||||
encoding=None, explicit_start=None, explicit_end=None,
|
||||
version=None, tags=None):
|
||||
CEmitter.__init__(self, stream, canonical=canonical,
|
||||
indent=indent, width=width, encoding=encoding,
|
||||
allow_unicode=allow_unicode, line_break=line_break,
|
||||
explicit_start=explicit_start, explicit_end=explicit_end,
|
||||
version=version, tags=tags)
|
||||
Representer.__init__(self, default_style=default_style,
|
||||
default_flow_style=default_flow_style)
|
||||
Resolver.__init__(self)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user