mirror of
https://github.com/kennethreitz/tablib.git
synced 2026-06-05 15:00:19 +00:00
Compare commits
335 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 26b6faa88d | |||
| 140736ff33 | |||
| 5379c5683d | |||
| e8b44b5777 | |||
| a0822bc9b0 | |||
| 89b431213b | |||
| 695e8c5af7 | |||
| 0797ec67d4 | |||
| 1852624a7e | |||
| f81dc41a57 | |||
| 34415b89b8 | |||
| d25655588b | |||
| 22c4d185e1 | |||
| e3b3659ea4 | |||
| 22d337790a | |||
| 0784d4b32c | |||
| 332c5bccd9 | |||
| 7055d18a2e | |||
| 6a7c685111 | |||
| 0e5b8f7058 | |||
| e3e6b656e3 | |||
| 99896a5f28 | |||
| 25da44f569 | |||
| 7727171379 | |||
| 91bd4eb9c7 | |||
| 9b74b139fd | |||
| 823a543f41 | |||
| 1aa275bf99 | |||
| 17bb0d3b2c | |||
| 1a9aee9289 | |||
| 196edb82cc | |||
| a2990d5852 | |||
| d992ece86a | |||
| 46f302255d | |||
| 9e3ab4c13f | |||
| eaed0e48c2 | |||
| 501187b357 | |||
| ea4aef88b6 | |||
| 24d800fac3 | |||
| d8136ab613 | |||
| 36bbe2726b | |||
| 1427be2901 | |||
| 10ce000d31 | |||
| a91254117c | |||
| b67762604f | |||
| 83a8346e8f | |||
| 657ab98d04 | |||
| 9ddb4de942 | |||
| 5fad80a540 | |||
| cabab73045 | |||
| 2bb0525990 | |||
| f364bb576e | |||
| 09d057094e | |||
| 8082c4ad43 | |||
| 00e9ae0120 | |||
| f01c22213e | |||
| a58bf269d9 | |||
| 437a135dd3 | |||
| 0409ff50af | |||
| dd24edcc24 | |||
| cf28f4baa8 | |||
| 52dcf79c41 | |||
| 49f098ee22 | |||
| 642b1d8def | |||
| f6964bba8f | |||
| 8d6e75ad20 | |||
| 30487999ba | |||
| b74308e81e | |||
| 577289cbc3 | |||
| cf10703e31 | |||
| 778ad0265e | |||
| e3dedb8887 | |||
| c6e240fa52 | |||
| 5c747c9c2e | |||
| 0bbd990ed8 | |||
| fcada243a2 | |||
| fca8ad6182 | |||
| 35d9e390fd | |||
| 8ca180c461 | |||
| ff63558a67 | |||
| f621b56178 | |||
| 2b529bcb1c | |||
| 90c3435600 | |||
| 1fa28ee2ca | |||
| a5cae7c249 | |||
| 666991ca1e | |||
| 5f4162918f | |||
| b554ce36bb | |||
| e5e22d3ca2 | |||
| 8626351618 | |||
| cdfacb6d6e | |||
| 108c9de130 | |||
| 271aeebf56 | |||
| e75a00541d | |||
| 3b0e0c7991 | |||
| 23440fb7a3 | |||
| 459f310857 | |||
| f9021f53c2 | |||
| 7fda829d27 | |||
| ca08ac8a7b | |||
| 08b51113d3 | |||
| 3e391fc8e3 | |||
| a230844914 | |||
| bc82be09c5 | |||
| ed9fe01604 | |||
| e69546a0ff | |||
| d4b659ece9 | |||
| 55eb3f93e3 | |||
| be7182aea9 | |||
| 48def2cba6 | |||
| df8c0335d1 | |||
| d0b09f0fce | |||
| 9efd982bfa | |||
| a3c82804cd | |||
| 2e75e93f57 | |||
| 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 | |||
| 310400af5b | |||
| d52537b75b | |||
| 40490d1ba5 |
+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,6 @@ Development Lead
|
||||
Patches and Suggestions
|
||||
```````````````````````
|
||||
|
||||
- A Lucky Someone
|
||||
- Luke Lee
|
||||
- Josh Ourisman
|
||||
- Luca Beltrame
|
||||
+123
-4
@@ -1,7 +1,126 @@
|
||||
History
|
||||
=======
|
||||
-------
|
||||
|
||||
0.1.0 (2010-09-??)
|
||||
------------------
|
||||
0.9.3 (2011-01-31)
|
||||
++++++++++++++++++
|
||||
|
||||
* Databook duplication leak fix.
|
||||
* HTML Table output.
|
||||
* Added column sorting.
|
||||
|
||||
|
||||
0.9.2 (2010-11-17)
|
||||
++++++++++++++++++
|
||||
|
||||
* Tanspose method added to Datasets.
|
||||
* New frozen top row in Excel output.
|
||||
* Pickling support for Datasets and Rows.
|
||||
* Support for row/column stacking.
|
||||
|
||||
|
||||
0.9.1 (2010-11-04)
|
||||
++++++++++++++++++
|
||||
|
||||
* Minor reference shadowing bugfix.
|
||||
|
||||
|
||||
0.9.0 (2010-11-04)
|
||||
++++++++++++++++++
|
||||
|
||||
* Massive documentation update!
|
||||
* Tablib.org!
|
||||
* Row taggins and Dataset filtering!
|
||||
* Column insert/delete support
|
||||
* Column append API change (header required)
|
||||
* Internal Changes (Row object and use thereof)
|
||||
|
||||
|
||||
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.
|
||||
|
||||
* Initial Release
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2010 Kenneth Reitz.
|
||||
Copyright (c) 2011 Kenneth Reitz.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
include HISTORY.rst README.rst tabbed
|
||||
include HISTORY.rst README.rst LICENSE AUTHORS
|
||||
@@ -0,0 +1,169 @@
|
||||
Tablib includes some vendorized python libraries: ordereddict, pyyaml,
|
||||
simplejson, and xlwt.
|
||||
|
||||
Markup License
|
||||
==============
|
||||
|
||||
Markup is in the public domain.
|
||||
|
||||
|
||||
|
||||
OrderedDict License
|
||||
===================
|
||||
|
||||
Copyright (c) 2009 Raymond Hettinger
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
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
-64
@@ -1,104 +1,190 @@
|
||||
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:
|
||||
|
||||
At this time, Tabbed supports the **export** of it's powerful Dataset object instances into any of the above formats. Import is underway.
|
||||
- Excel (Sets + Books)
|
||||
- JSON (Sets + Books)
|
||||
- YAML (Sets + Books)
|
||||
- HTML (Sets)
|
||||
- TSV (Sets)
|
||||
- CSV (Sets)
|
||||
|
||||
Please note that tabbed *purposefully* excludes XML support. It always will.
|
||||
Import formats supported:
|
||||
|
||||
- JSON (Sets + Books)
|
||||
- YAML (Sets + Books)
|
||||
- TSV (Sets)
|
||||
- CSV (Sets)
|
||||
|
||||
Features
|
||||
Note that tablib *purposefully* excludes XML support. It always will.
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
.. Convert datafile formats via API: ::
|
||||
..
|
||||
.. tablib.source(filename='data.csv').export('data.json')
|
||||
`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.
|
||||
|
||||
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.Dataset(*data, headers=headers)
|
||||
|
||||
# Establish file location and save
|
||||
data.save('test.xls')
|
||||
|
||||
|
||||
Intelligently add new rows: ::
|
||||
|
||||
data.append('Bob', 'Dylan', 3.2)
|
||||
|
||||
print data.headers
|
||||
# >>> ('first_name', 'last_name', 'gpa')
|
||||
|
||||
>>> data.append(('Henry', 'Ford'))
|
||||
|
||||
Intelligently add new columns: ::
|
||||
|
||||
>>> data.append(col=(90, 67, 83), header='age')
|
||||
|
||||
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']
|
||||
..
|
||||
Slice columns by header: ::
|
||||
|
||||
Manipulate rows by index: ::
|
||||
>>> print data['first_name']
|
||||
['John', 'George', 'Henry']
|
||||
|
||||
del data[0]
|
||||
print data[0:1]
|
||||
# >>> [('George', 'Washington', 2.6), ('Henry', 'Ford', 2.3)]
|
||||
|
||||
.. # Update saved file
|
||||
.. data.save()
|
||||
|
||||
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
|
||||
|
||||
Contribute
|
||||
----------
|
||||
|
||||
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
|
||||
-------
|
||||
- Import datasets from CSV, JSON, YAML
|
||||
- Release CLI Interface
|
||||
- Auto-detect import format
|
||||
- Plugin support
|
||||
- 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
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
* Add seperator support to HTML out
|
||||
* Hooks System
|
||||
- pre/post-append
|
||||
- pre/post-import
|
||||
- pre/post-export
|
||||
* Big Data
|
||||
* Backwards-compatible OrderedDict support
|
||||
* Write more exhausive unit-tests.
|
||||
* Write stress tests.
|
||||
* Make CSV write customizable.
|
||||
* Integrate django-tablib
|
||||
* Mention django-tablib in Documention
|
||||
* Dataset title usage in documentation (#17)
|
||||
+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) 2011 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 = ''
|
||||
@@ -0,0 +1,64 @@
|
||||
.. _api:
|
||||
|
||||
===
|
||||
API
|
||||
===
|
||||
|
||||
|
||||
.. module:: tablib
|
||||
|
||||
This part of the documentation covers all the interfaces of Tablib. For
|
||||
parts where Tablib depends on external libraries, we document the most
|
||||
important right here and provide links to the canonical documentation.
|
||||
|
||||
|
||||
--------------
|
||||
Dataset Object
|
||||
--------------
|
||||
|
||||
|
||||
.. autoclass:: Dataset
|
||||
:inherited-members:
|
||||
|
||||
|
||||
---------------
|
||||
Databook Object
|
||||
---------------
|
||||
|
||||
|
||||
.. autoclass:: Databook
|
||||
:inherited-members:
|
||||
|
||||
|
||||
|
||||
---------
|
||||
Functions
|
||||
---------
|
||||
|
||||
|
||||
.. autofunction:: detect
|
||||
|
||||
.. autofunction:: import_set
|
||||
|
||||
|
||||
----------
|
||||
Exceptions
|
||||
----------
|
||||
|
||||
|
||||
.. class:: InvalidDatasetType
|
||||
|
||||
You're trying to add something that doesn't quite look right.
|
||||
|
||||
|
||||
.. class:: InvalidDimensions
|
||||
|
||||
You're trying to add something that doesn't quite fit right.
|
||||
|
||||
|
||||
.. class:: UnsupportedFormat
|
||||
|
||||
You're trying to add something that doesn't quite taste right.
|
||||
|
||||
|
||||
Now, go start some :ref:`Tablib Development <development>`.
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
# -*- 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
|
||||
import tablib
|
||||
|
||||
# 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'2011, Kenneth Reitz. Styles (modified) © Armin Ronacher'
|
||||
|
||||
# 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 = tablib.core.__version__
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = version
|
||||
|
||||
# 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 = 'flask_theme_support.FlaskyStyle'
|
||||
|
||||
# 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 = False
|
||||
|
||||
# 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,246 @@
|
||||
.. _development:
|
||||
|
||||
Development
|
||||
===========
|
||||
|
||||
Tablib is under active development, and contributors are welcome.
|
||||
|
||||
If you have a feature request, suggestion, or bug report, please open a new issue on GitHub_. To submit patches, please send a pull request on GitHub_.
|
||||
|
||||
If you'd like to contribute, there's plenty to do. Here's a short todo list.
|
||||
|
||||
.. include:: ../TODO.rst
|
||||
|
||||
|
||||
.. _GitHub: http://github.com/kennethreitz/tablib/
|
||||
|
||||
|
||||
|
||||
.. _design:
|
||||
|
||||
---------------------
|
||||
Design Considerations
|
||||
---------------------
|
||||
|
||||
Tablib was developed with a few :pep:`20` idioms in mind.
|
||||
|
||||
#. Beautiful is better than ugly.
|
||||
#. Explicit is better than implicit.
|
||||
#. Simple is better than complex.
|
||||
#. Complex is better than complicated.
|
||||
#. Readability counts.
|
||||
|
||||
A few other things to keep in mind:
|
||||
|
||||
#. Keep your code DRY.
|
||||
#. Strive to be as simple (to use) as possible.
|
||||
|
||||
.. _scm:
|
||||
|
||||
--------------
|
||||
Source Control
|
||||
--------------
|
||||
|
||||
|
||||
Tablib source is controlled with Git_, the lean, mean, distributed source control machine.
|
||||
|
||||
The repository is publicly accessable.
|
||||
|
||||
``git clone git://github.com/kennethreitz/tablib.git``
|
||||
|
||||
The project is hosted both on **GitHub** and **git.kennethreitz.com**.
|
||||
|
||||
|
||||
GitHub:
|
||||
http://github.com/kennethreitz/tablib
|
||||
"Mirror":
|
||||
http://git.kennethreitz.com/projects/tablib
|
||||
|
||||
|
||||
Git Branch Structure
|
||||
++++++++++++++++++++
|
||||
|
||||
Feature / Hotfix / Release branches follow a `Successful Git Branching Model`_ . Git-flow_ is a great tool for managing the repository. I highly recommend it.
|
||||
|
||||
``develop``
|
||||
The "next release" branch. Likely unstable.
|
||||
``master``
|
||||
Current production release (|version|) on PyPi.
|
||||
``gh-pages``
|
||||
Current release of http://tablib.org.
|
||||
|
||||
Each release is tagged.
|
||||
|
||||
When submitting patches, please place your feature/change in its own branch prior to opening a pull reqeust on GitHub_.
|
||||
|
||||
|
||||
.. _Git: http://git-scm.org
|
||||
.. _`Successful Git Branching Model`: http://nvie.com/posts/a-successful-git-branching-model/
|
||||
.. _git-flow: http://github.com/nvie/gitflow
|
||||
|
||||
|
||||
.. _newformats:
|
||||
|
||||
------------------
|
||||
Adding New Formats
|
||||
------------------
|
||||
|
||||
Tablib welcomes new format additions! Format suggestions include:
|
||||
|
||||
* Tab Seperated Values
|
||||
* MySQL Dump
|
||||
* HTML Table
|
||||
|
||||
|
||||
Coding by Convention
|
||||
++++++++++++++++++++
|
||||
|
||||
Tablib features a micro-framework for adding format support. The easiest way to understand it is to use it. So, let's define our own format, named *xxx*.
|
||||
|
||||
1. Write a new format interface.
|
||||
|
||||
:class:`tablib.core` follows a simple pattern for automatically utilizing your format throughout Tablib. Function names are crucial.
|
||||
|
||||
Example **tablib/formats/_xxx.py**: ::
|
||||
|
||||
title = 'xxx'
|
||||
|
||||
def export_set(dset):
|
||||
....
|
||||
# returns string representation of given dataset
|
||||
|
||||
def export_book(dbook):
|
||||
....
|
||||
# returns string representation of given databook
|
||||
|
||||
def import_set(dset, in_stream):
|
||||
...
|
||||
# populates given Dataset with given datastream
|
||||
|
||||
def import_book(dbook, in_stream):
|
||||
...
|
||||
# returns Databook instance
|
||||
|
||||
def detect(stream):
|
||||
...
|
||||
# returns True if given stream is parsable as xxx
|
||||
|
||||
.. admonition:: Excluding Support
|
||||
|
||||
|
||||
If the format excludes support for an import/export mechanism (*eg.* :class:`csv <tablib.Dataset.csv>` excludes :class:`Databook <tablib.Databook>` support), simply don't define the respecive functions. Appropriate errors will be raised.
|
||||
|
||||
2.
|
||||
|
||||
Add your new format module to the :class:`tablib.formats.avalable` tuple.
|
||||
|
||||
3.
|
||||
Add a mock property to the :class:`Dataset <tablib.Dataset>` class with verbose `reStructured Text`_ docstring. This alleviates IDE confusion, and allows for pretty auto-generated Sphinx_ documentation.
|
||||
|
||||
4. Write respective :ref:`tests <testing>`.
|
||||
|
||||
.. _testing:
|
||||
|
||||
--------------
|
||||
Testing Tablib
|
||||
--------------
|
||||
|
||||
Testing is crucial to Tablib's stability. This stable project is used in production by many companies and developers, so it is important to be certian that every version released is fully operational. When developing a new feature for Tablib, be sure to write proper tests for it as well.
|
||||
|
||||
When developing a feature for Tablib, the easiest way to test your changes for potential issues is to simply run the test suite directly. ::
|
||||
|
||||
$ ./test_tablib.py
|
||||
|
||||
|
||||
`Hudson CI`_, amongst other tools, supports Java's xUnit testing report format. Nose_ allows us to generate our own xUnit reports.
|
||||
|
||||
Installing nose is simple. ::
|
||||
|
||||
$ pip install nose
|
||||
|
||||
Once installed, we can generate our xUnit report with a single command. ::
|
||||
|
||||
$ nosetests test_tablib.py --with-xunit
|
||||
|
||||
This will generate a **nosetests.xml** file, which can then be analyzed.
|
||||
|
||||
.. _Nose: http://somethingaboutorange.com/mrl/projects/nose/
|
||||
|
||||
|
||||
|
||||
.. _hudson:
|
||||
|
||||
----------------------
|
||||
Continuous Integration
|
||||
----------------------
|
||||
|
||||
Every commit made to the **develop** branch is automatically tested and inspected upon receipt with `Hudson CI`_. If you have access to the main respository and broke the build, you will receive an email accordingly.
|
||||
|
||||
Anyone may view the build status and history at any time.
|
||||
|
||||
http://git.kennethreitz.com/ci/
|
||||
|
||||
|
||||
If you are trustworthy and plan to contribute to tablib on a regular basis, please contact `Kenneth Reitz`_ to get an account on the Hudson Server.
|
||||
|
||||
|
||||
Additional reports will also be included here in the future, including :pep:`8` checks and stress reports for extremely large datasets.
|
||||
|
||||
.. _`Hudson CI`: http://hudson.dev.java.net
|
||||
.. _`Kenneth Reitz`: http://kennethreitz.com/contact-me/
|
||||
|
||||
|
||||
.. _docs:
|
||||
|
||||
-----------------
|
||||
Building the Docs
|
||||
-----------------
|
||||
|
||||
Documentation is written in the powerful, flexible, and standard Python documentation format, `reStructured Text`_.
|
||||
Documentation builds are powered by the powerful Pocoo project, Sphinx_. The :ref:`API Documentation <api>` is mostly documented inline throught the module.
|
||||
|
||||
The Docs live in ``tablib/docs``. In order to build them, you will first need to install Sphinx. ::
|
||||
|
||||
$ pip install sphinx
|
||||
|
||||
|
||||
Then, to build an HTML version of the docs, simply run the following from the **docs** directory: ::
|
||||
|
||||
$ make html
|
||||
|
||||
Your ``docs/_build/html`` directory will then contain an HTML representation of the documentation, ready for publication on most web servers.
|
||||
|
||||
You can also generate the documentation in **ebpub**, **latex**, **json**, *&c* similarly.
|
||||
|
||||
.. admonition:: GitHub Pages
|
||||
|
||||
To push the documentation up to `GitHub Pages`_, you will first need to run `sphinx-to-github`_ against your ``docs/_build/html`` directory.
|
||||
|
||||
GitHub Pages are powered by an HTML generation system called Jeckyl_, which is configured to ignore files and folders that begin with "``_``" (*ie.* **_static**).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
and `sphinx-to-github`_. ::
|
||||
|
||||
Installing sphinx-to-github is simple. ::
|
||||
|
||||
$ pip install sphinx-to-github
|
||||
|
||||
Running it against the docs is even simpler. ::
|
||||
|
||||
$ sphinx-to-github _build/html
|
||||
|
||||
Move the resulting files to the **gh-pages** branch of your repository, and push it up to GitHub.
|
||||
|
||||
.. _`reStructured Text`: http://docutils.sourceforge.net/rst.html
|
||||
.. _Sphinx: http://sphinx.pocoo.org
|
||||
.. _`GitHub Pages`: http://pages.github.com
|
||||
.. _Jeckyl: http://github.com/mojombo/jekyll
|
||||
.. _`sphinx-to-github`: http://github.com/michaeljones/sphinx-to-github
|
||||
|
||||
----------
|
||||
|
||||
Make sure to check out the :ref:`API Documentation <api>`.
|
||||
@@ -0,0 +1,62 @@
|
||||
.. 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.
|
||||
|
||||
Tablib: Pythonic Tabular Data
|
||||
=============================
|
||||
|
||||
.. Contents:
|
||||
..
|
||||
.. .. toctree::
|
||||
.. :maxdepth: 2
|
||||
..
|
||||
|
||||
.. Indices and tables
|
||||
.. ==================
|
||||
..
|
||||
.. * :ref:`genindex`
|
||||
.. * :ref:`modindex`
|
||||
.. * :ref:`search`
|
||||
|
||||
|
||||
Tablib is an :ref:`MIT Lisenced <mit>` format-agnostic tabular dataset library, written in Python. It allows you to import, export, and manipulate tabular data sets. Advanced features include, segregation, dynamic columns, tags & filtering, and seamless format import & exmport.
|
||||
|
||||
I recommend you start with :ref:`Installation <install>`.
|
||||
|
||||
User's Guide
|
||||
------------
|
||||
|
||||
This part of the documentation, which is mostly prose, begins with some background information about Tablib, then focuses on step-by-step instructions for getting the most out of your datasets.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
intro
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
install
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
tutorial
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
development
|
||||
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
If you are looking for information on a specific function, class or
|
||||
method, this part of the documentation is for you.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
api
|
||||
@@ -0,0 +1,78 @@
|
||||
.. _install:
|
||||
Installation
|
||||
============
|
||||
|
||||
This part of the documentation covers the installation of Tablib. The first step to using any software package is getting it properly installed. Please read this section carefully, or you may miss out on some nice :ref:`speed enhancments <peed-extentions>`.
|
||||
|
||||
|
||||
.. _installing:
|
||||
|
||||
-----------------
|
||||
Installing Tablib
|
||||
-----------------
|
||||
|
||||
To install Tablib, it only takes one simple command. ::
|
||||
|
||||
$ pip install tablib
|
||||
|
||||
Or, if you must: ::
|
||||
|
||||
$ easy_install tablib
|
||||
|
||||
But, you really shouldn't do that.
|
||||
|
||||
|
||||
-------------------
|
||||
Download the Source
|
||||
-------------------
|
||||
|
||||
You can also install tablib from source. The latest release (|version|) is available from GitHub.
|
||||
|
||||
* tarball_
|
||||
* zipball_
|
||||
|
||||
.. _
|
||||
Once you have a copy of the source, you can embed it in your Python package, or install it into your site-packages easily. ::
|
||||
|
||||
$ python setup.py install
|
||||
|
||||
|
||||
To download the full source history from Git, see :ref:`Source Control <scm>`.
|
||||
|
||||
.. _tarball: http://github.com/kennethreitz/tablib/tarball/master
|
||||
.. _zipball: http://github.com/kennethreitz/tablib/zipball/master
|
||||
|
||||
|
||||
.. _speed-extentions:
|
||||
Speed Extentions
|
||||
----------------
|
||||
|
||||
.. versionadded:: 0.8.5
|
||||
|
||||
Tablib is partially dependent on the **pyyaml**, **simplejson**, and **xlwt** modules. To reduce installation issues, fully integrated versions of all required libraries are included in Tablib.
|
||||
|
||||
However, if performance is important to you (and it should be), you can install **pyyaml** with C extentions from PyPi. ::
|
||||
|
||||
$ pip install PyYAML
|
||||
|
||||
If you're using Python 2.5 (currently unsupported), you should also install the **simplejson** module. If you're using Python 2.6+, the built-in **json** module is already optimized and in use. ::
|
||||
|
||||
$ pip install simplejson
|
||||
|
||||
|
||||
|
||||
.. _updates:
|
||||
Staying Updated
|
||||
---------------
|
||||
|
||||
The latest version of Tablib will always be available here:
|
||||
|
||||
* PyPi: http://pypi.python.org/pypi/tablib/
|
||||
* GitHub: http://github.com/kennethreitz/tablib/
|
||||
|
||||
When a new version is available, upgrading is simple. ::
|
||||
|
||||
$ pip install tablib --upgrade
|
||||
|
||||
|
||||
Now, go get a :ref:`Quick Start <quickstart>`.
|
||||
@@ -0,0 +1,55 @@
|
||||
.. _intro:
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This part of the documentation covers all the interfaces of Tablib.
|
||||
Tablib is a format-agnostic tabular dataset library, written in Python. It allows you to Pythonically import, export, and manipulate tabular data sets. Advanced features include, segregation, dynamic columns, tags / filtering, and seamless format import/exmport.
|
||||
|
||||
|
||||
Philosphy
|
||||
---------
|
||||
|
||||
Tablib was developed with a few :pep:`20` idioms in mind.
|
||||
|
||||
|
||||
#. Beautiful is better than ugly.
|
||||
#. Explicit is better than implicit.
|
||||
#. Simple is better than complex.
|
||||
#. Complex is better than complicated.
|
||||
#. Readability counts.
|
||||
|
||||
All contributions to Tablib should keep these important rules in mind.
|
||||
|
||||
.. _mit:
|
||||
|
||||
MIT License
|
||||
-----------
|
||||
|
||||
A large number of open source projects you find today are `GPL Licensed`_. While the GPL certianly has essential applications, it should most certianly not be your go-to license for your next open source project.
|
||||
|
||||
A project that is released as GPL cannot be usd in any commercial product without the product itself also being offered as open source. The MIT and BSD licenses are great alternatives to the GPL that allow your open-source software to be used in proprietary, closed-source software.
|
||||
|
||||
Tablib is released under terms of `The MIT License`_.
|
||||
|
||||
.. _`GPL Licensed`: http://www.opensource.org/licenses/gpl-license.php
|
||||
.. _`The MIT License`: http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
|
||||
|
||||
.. _pythonsupport:
|
||||
|
||||
Pythons Supported
|
||||
-----------------
|
||||
|
||||
At this time, the following Python platforms are officially supported:
|
||||
|
||||
* Python 2.6
|
||||
* Python 2.7
|
||||
|
||||
Support for other Pythons will be rolled out soon.
|
||||
|
||||
|
||||
|
||||
|
||||
Now, go :ref:`Install Tablib <install>`.
|
||||
@@ -0,0 +1,353 @@
|
||||
.. _quickstart:
|
||||
|
||||
==========
|
||||
Quickstart
|
||||
==========
|
||||
|
||||
|
||||
.. module:: tablib
|
||||
|
||||
|
||||
Eager to get started? This page gives a good introduction in how to get started with Tablib. This assumes you already have Tablib installed. If you do not, head over to the :ref:`Installation <install>` section.
|
||||
|
||||
First, make sure that:
|
||||
|
||||
* Tablib is :ref:`installed <install>`
|
||||
* Tablib is :ref:`up-to-date <updates>`
|
||||
|
||||
|
||||
Lets gets started with some simple use cases and examples.
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
Creating a Dataset
|
||||
------------------
|
||||
|
||||
|
||||
A :class:`Dataset <tablib.Dataset>` is nothing more than what its name implies—a set of data.
|
||||
|
||||
Creating your own instance of the :class:`tablib.Dataset` object is simple. ::
|
||||
|
||||
data = tablib.Dataset()
|
||||
|
||||
You can now start filling this :class:`Dataset <tablib.Dataset>` object with data.
|
||||
|
||||
.. admonition:: Example Context
|
||||
|
||||
From here on out, if you see ``data``, assume that it's a fresh :class:`Dataset <tablib.Dataset>` object.
|
||||
|
||||
|
||||
|
||||
-----------
|
||||
Adding Rows
|
||||
-----------
|
||||
|
||||
|
||||
Let's say you want to collect a simple list of names. ::
|
||||
|
||||
# collection of names
|
||||
names = ['Kenneth Reitz', 'Bessie Monke']
|
||||
|
||||
for name in names:
|
||||
# split name appropriately
|
||||
fname, lname = name.split()
|
||||
|
||||
# add names to Dataset
|
||||
data.append([fname, lname])
|
||||
|
||||
You can get a nice, Pythonic view of the dataset at any time with :class:`Dataset.dict`.
|
||||
|
||||
>>> data.dict
|
||||
[('Kenneth', 'Reitz'), ('Bessie', 'Monke')]
|
||||
|
||||
|
||||
|
||||
--------------
|
||||
Adding Headers
|
||||
--------------
|
||||
|
||||
|
||||
It's time enhance our :class:`Dataset` by giving our columns some titles. To do so, set :class:`Dataset.headers`. ::
|
||||
|
||||
data.headers = ['First Name', 'Last Name']
|
||||
|
||||
Now our data looks a little different. ::
|
||||
|
||||
>>> data.dict
|
||||
[{'Last Name': 'Reitz', 'First Name': 'Kenneth'}, {'Last Name': 'Monke', 'First Name': 'Bessie'}]
|
||||
|
||||
|
||||
|
||||
|
||||
--------------
|
||||
Adding Columns
|
||||
--------------
|
||||
|
||||
|
||||
Now that we have a basic :class:`Dataset` in place, let's add a column of **ages** to it. ::
|
||||
|
||||
data.append(col=[22, 20], header='Age')
|
||||
|
||||
Let's view the data now. ::
|
||||
|
||||
>>> data.dict
|
||||
[{'Last Name': 'Reitz', 'First Name': 'Kenneth', 'Age': 22}, {'Last Name': 'Monke', 'First Name': 'Bessie', 'Age': 20}]
|
||||
|
||||
It's that easy.
|
||||
|
||||
|
||||
--------------
|
||||
Exporting Data
|
||||
--------------
|
||||
|
||||
Tablib's killer feature is the ability to export your :class:`Dataset` objects into a number of formats.
|
||||
|
||||
**Comma-Seperated Values** ::
|
||||
|
||||
>>> data.csv
|
||||
Last Name,First Name,Age
|
||||
Reitz,Kenneth,22
|
||||
Monke,Bessie,20
|
||||
|
||||
**JavaScript Object Notation** ::
|
||||
|
||||
>>> data.json
|
||||
[{"Last Name": "Reitz", "First Name": "Kenneth", "Age": 22}, {"Last Name": "Monke", "First Name": "Bessie", "Age": 20}]
|
||||
|
||||
|
||||
**YAML Ain't Markup Language** ::
|
||||
|
||||
>>> data.yaml
|
||||
- {Age: 22, First Name: Kenneth, Last Name: Reitz}
|
||||
- {Age: 20, First Name: Bessie, Last Name: Monke}
|
||||
|
||||
|
||||
**Microsoft Excel** ::
|
||||
|
||||
>>> data.xls
|
||||
<censored binary data>
|
||||
|
||||
|
||||
------------------------
|
||||
Selecting Rows & Columns
|
||||
------------------------
|
||||
|
||||
|
||||
You can slice and dice your data, just like a standard Python list. ::
|
||||
|
||||
>>> data[0]
|
||||
('Kenneth', 'Reitz', 22)
|
||||
|
||||
|
||||
If we had a set of data consisting of thousands of rows, it could be useful to get a list of values in a column.
|
||||
To do so, we access the :class:`Dataset` as if it were a standard Python dictionary. ::
|
||||
|
||||
>>> data['First Name']
|
||||
['Kenneth', 'Bessie']
|
||||
|
||||
Let's find the average age. ::
|
||||
|
||||
>>> ages = data['Age']
|
||||
>>> float(sum(ages)) / len(ages)
|
||||
21.0
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
Removing Rows & Columns
|
||||
-----------------------
|
||||
|
||||
It's easier than you could imagine. ::
|
||||
|
||||
>>> del data['Col Name']
|
||||
|
||||
::
|
||||
|
||||
>>> del data[0:12]
|
||||
|
||||
|
||||
==============
|
||||
Advanced Usage
|
||||
==============
|
||||
|
||||
|
||||
This part of the documentation services to give you an idea that are otherwise hard to extract from the :ref:`API Documentation <api>`
|
||||
|
||||
And now for something completely different.
|
||||
|
||||
|
||||
.. _dyncols:
|
||||
|
||||
---------------
|
||||
Dynamic Columns
|
||||
---------------
|
||||
|
||||
.. versionadded:: 0.8.3
|
||||
|
||||
Thanks to Josh Ourisman, Tablib now supports adding dynamic columns. A dynamic column is a single callable object (*ie.* a function).
|
||||
|
||||
Let's add a dynamic column to our :class:`Dataset` object. In this example, we have a function that generates a random grade for our students. ::
|
||||
|
||||
import random
|
||||
|
||||
def random_grade(row):
|
||||
"""Returns a random integer for entry."""
|
||||
return (random.randint(60,100)/100.0)
|
||||
|
||||
data.append(col=[random_grade], header='Grade')
|
||||
|
||||
Let's have a look at our data. ::
|
||||
|
||||
>>> data.yaml
|
||||
- {Age: 22, First Name: Kenneth, Grade: 0.6, Last Name: Reitz}
|
||||
- {Age: 20, First Name: Bessie, Grade: 0.75, Last Name: Monke}
|
||||
|
||||
|
||||
Let's remove that column. ::
|
||||
|
||||
>>> del data['Grade']
|
||||
|
||||
|
||||
When you add a dynamic column, the first argument that is passed in to the given callable is the current data row. You can use this to perform calculations against your data row.
|
||||
|
||||
For example, we can use the data available in the row to guess the gender of a student. ::
|
||||
|
||||
def guess_gender(row):
|
||||
"""Calculates gender of given student data row."""
|
||||
m_names = ('Kenneth', 'Mike', 'Yuri')
|
||||
f_names = ('Bessie', 'Samantha', 'Heather')
|
||||
|
||||
name = row[0]
|
||||
|
||||
if name in m_names:
|
||||
return 'Male'
|
||||
elif name in f_names:
|
||||
return 'Female'
|
||||
else:
|
||||
return 'Unknown'
|
||||
|
||||
Adding this function to our dataset as a dynamic column would result in: ::
|
||||
|
||||
>>> data.yaml
|
||||
- {Age: 22, First Name: Kenneth, Gender: Male, Last Name: Reitz}
|
||||
- {Age: 20, First Name: Bessie, Gender: Female, Last Name: Monke}
|
||||
|
||||
|
||||
.. _tags:
|
||||
|
||||
----------------------------
|
||||
Filtering Datasets with Tags
|
||||
----------------------------
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
|
||||
|
||||
When constructing a :class:`Dataset` object, you can add tags to rows by specifying the ``tags`` parameter.
|
||||
This allows you to filter your :class:`Dataset` later. This can be useful so seperate rows of data based on
|
||||
arbitrary criteria (*e.g.* origin) that you don't want to include in your :class:`Dataset`.
|
||||
|
||||
Let's tag some students. ::
|
||||
|
||||
students = tablib.Dataset()
|
||||
|
||||
students.headers = ['first', 'last']
|
||||
|
||||
students.append(['Kenneth', 'Reitz'], tags=['male', 'technical'])
|
||||
students.append(['Bessie', 'Monke'], tags=['female', 'creative'])
|
||||
|
||||
Now that we have extra meta-data on our rows, we can use easily filter our :class:`Dataset`. Let's just see Male students. ::
|
||||
|
||||
|
||||
>>> data.filter(['male']).yaml
|
||||
- {first: Kenneth, Last: Reitz}
|
||||
|
||||
It's that simple. The original :class:`Dataset` is untouched.
|
||||
|
||||
|
||||
Excel Workbook With Multiple Sheets
|
||||
------------------------------------
|
||||
|
||||
When dealine with a large number of :class:`Datasets <Dataset>` in spreadsheet format, it's quite common to group mulitple spreadsheets into a single Excel file, known as a Workbook. Tablib makes it extremely easy to build webooks with the handy, :class:`Databook` class.
|
||||
|
||||
|
||||
Let's say we have 3 different :class:`Datasets <Dataset>`. All we have to do is add then to a :class:`Databook` object... ::
|
||||
|
||||
book = tablib.Databook([data1, data2, data3])
|
||||
|
||||
... and export to Excel just like :class:`Datasets <Dataset>`. ::
|
||||
|
||||
with open('students.xls', 'wb') as f:
|
||||
f.write(book.xls)
|
||||
|
||||
The resulting **students.xls** file will contain a seperate spreadsheet for each :class:`Dataset` object in the :class:`Databook`.
|
||||
|
||||
.. admonition:: Binary Warning
|
||||
|
||||
Make sure to open the output file in binary mode.
|
||||
|
||||
|
||||
.. _seperators:
|
||||
|
||||
----------
|
||||
Seperators
|
||||
----------
|
||||
|
||||
.. versionadded:: 0.8.2
|
||||
|
||||
When, it's often useful to create a blank row containing information on the upcomming data. So,
|
||||
|
||||
|
||||
|
||||
::
|
||||
|
||||
daniel_tests = [
|
||||
('11/24/09', 'Math 101 Mid-term Exam', 56.),
|
||||
('05/24/10', 'Math 101 Final Exam', 62.)
|
||||
]
|
||||
|
||||
suzie_tests = [
|
||||
('11/24/09', 'Math 101 Mid-term Exam', 56.),
|
||||
('05/24/10', 'Math 101 Final Exam', 62.)
|
||||
]
|
||||
|
||||
# Create new dataset
|
||||
tests = tablib.Dataset()
|
||||
tests.headers = ['Date', 'Test Name', 'Grade']
|
||||
|
||||
# Daniel's Tests
|
||||
tests.append_seperator('Daniel\'s Scores')
|
||||
|
||||
for test_row in daniel_tests:
|
||||
tests.append(test_row)
|
||||
|
||||
# Susie's Tests
|
||||
tests.append_seperator('Susie\'s Scores')
|
||||
|
||||
for test_row in suzie_tests:
|
||||
tests.append(test_row)
|
||||
|
||||
# Write spreadsheet to disk
|
||||
with open('grades.xls', 'wb') as f:
|
||||
f.write(tests.xls)
|
||||
|
||||
The resulting **tests.xls** will have the following layout:
|
||||
|
||||
|
||||
Daniel's Scores:
|
||||
* '11/24/09', 'Math 101 Mid-term Exam', 56.
|
||||
* '05/24/10', 'Math 101 Final Exam', 62.
|
||||
|
||||
Suzie's Scores:
|
||||
* '11/24/09', 'Math 101 Mid-term Exam', 56.
|
||||
* '05/24/10', 'Math 101 Final Exam', 62.
|
||||
|
||||
|
||||
|
||||
.. admonition:: Format Support
|
||||
|
||||
At this time, only :class:`Excel <Dataset.xls>` output supports seperators.
|
||||
|
||||
----
|
||||
|
||||
Now, go check out the :ref:`API Documentation <api>` or begin :ref:`Tablib Development <development>`.
|
||||
Vendored
+11
-21
@@ -1,27 +1,17 @@
|
||||
import os
|
||||
from fabric.api import *
|
||||
|
||||
|
||||
def scrub():
|
||||
""" Death to the bytecode! """
|
||||
local("rm -fr dist build")
|
||||
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()
|
||||
|
||||
|
||||
def docs():
|
||||
"""Build docs."""
|
||||
os.system('make html')
|
||||
os.chdir('_build/html')
|
||||
os.system('sphinxtogithub .')
|
||||
os.system('git add -A')
|
||||
os.system('git commit -m \'documentation update\'')
|
||||
os.system('git push origin gh-pages')
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
import tablib
|
||||
|
||||
from distutils.core import setup
|
||||
|
||||
@@ -11,33 +11,40 @@ def publish():
|
||||
"""Publish to PyPi"""
|
||||
os.system("python setup.py sdist upload")
|
||||
|
||||
|
||||
if sys.argv[-1] == "publish":
|
||||
publish()
|
||||
sys.exit()
|
||||
|
||||
required = []
|
||||
|
||||
setup(
|
||||
name='tablib',
|
||||
version='0.0.4',
|
||||
description='Python wrapper for Gist API',
|
||||
version='0.9.3',
|
||||
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'],
|
||||
url='http://tablib.org',
|
||||
packages= [
|
||||
'tablib', 'tablib.formats',
|
||||
'tablib.packages',
|
||||
'tablib.packages.simplejson',
|
||||
'tablib.packages.xlwt',
|
||||
'tablib.packages.yaml',
|
||||
],
|
||||
install_requires=required,
|
||||
license='MIT',
|
||||
classifiers=(
|
||||
'Development Status :: 4 - Beta',
|
||||
'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.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',
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Tabbed
|
||||
Copyright (c) 2010 Kenneth Reitz. MIT License.
|
||||
"""
|
||||
|
||||
import tablib.cli
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
tablib.cli.start()
|
||||
+8
-1
@@ -1 +1,8 @@
|
||||
from core import *
|
||||
""" Tablib.
|
||||
"""
|
||||
|
||||
from tablib.core import (
|
||||
Databook, Dataset, detect, import_set,
|
||||
InvalidDatasetType, InvalidDimensions, UnsupportedFormat
|
||||
)
|
||||
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
""" Tabbed CLI Inteface Application
|
||||
"""
|
||||
|
||||
import io
|
||||
import sys
|
||||
|
||||
from helpers import *
|
||||
import tablib.core
|
||||
|
||||
from packages import opster
|
||||
|
||||
|
||||
FORMATS = ('json', 'yaml', 'xls', 'csv', 'html')
|
||||
|
||||
opts = []
|
||||
|
||||
opts.append(('v', 'version', False, 'Report tabbed version'))
|
||||
|
||||
for format in FORMATS:
|
||||
opts.append(('', format, False, 'Output to %s' % (format.upper())))
|
||||
|
||||
|
||||
|
||||
@opster.command(options=opts, usage='[FILE] [--FORMAT | FILE]')
|
||||
def start(in_file=None, out_file=None, **opts):
|
||||
"""Covertly convert dataset formats"""
|
||||
|
||||
opts = Object(**opts)
|
||||
|
||||
if opts.version:
|
||||
print('Tabbed, Ver. %s' % tabbed.core.__version__)
|
||||
sys.sys.exit(0)
|
||||
|
||||
stdin = piped()
|
||||
|
||||
if stdin:
|
||||
print stdin
|
||||
|
||||
elif in_file:
|
||||
|
||||
try:
|
||||
in_file = io.open(in_file, 'r')
|
||||
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:
|
||||
print('Import format not supported.')
|
||||
sys.exit(65)
|
||||
else:
|
||||
print('Please provide input.')
|
||||
sys.exit(65)
|
||||
|
||||
|
||||
|
||||
_formats_sum = sum(opts[f] for f in FORMATS)
|
||||
|
||||
# Multiple output formats given
|
||||
if _formats_sum > 1:
|
||||
print('Please specify a single output format.')
|
||||
sys.exit(64)
|
||||
|
||||
# No output formats given
|
||||
elif _formats_sum < 1:
|
||||
print('Please specify an output format.')
|
||||
sys.exit(64)
|
||||
|
||||
|
||||
# fetch options.formats list
|
||||
# if sum(()) > 1
|
||||
# log only one data format please
|
||||
# if sum of formats == 0, specity format
|
||||
|
||||
# look for filename
|
||||
|
||||
print opts.__dict__
|
||||
print in_file
|
||||
print out_file
|
||||
+657
-117
@@ -1,100 +1,227 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
tablib.core
|
||||
~~~~~~~~~~~
|
||||
|
||||
# _____ ______ ______ _________
|
||||
# __ /_______ ____ /_ ___ /_ _____ ______ /
|
||||
# _ __/_ __ `/__ __ \__ __ \_ _ \_ __ /
|
||||
# / /_ / /_/ / _ /_/ /_ /_/ // __// /_/ /
|
||||
# \__/ \__,_/ /_.___/ /_.___/ \___/ \__,_/
|
||||
This module implements the central tablib objects.
|
||||
|
||||
:copyright: (c) 2011 by Kenneth Reitz.
|
||||
:license: MIT, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from copy import copy
|
||||
from operator import itemgetter
|
||||
|
||||
from tablib import formats
|
||||
|
||||
|
||||
import csv
|
||||
import cStringIO
|
||||
import os
|
||||
|
||||
from helpers import *
|
||||
from packages import simplejson as json
|
||||
from packages import xlwt
|
||||
|
||||
try:
|
||||
import yaml
|
||||
except ImportError, why:
|
||||
from packages import yaml
|
||||
|
||||
|
||||
|
||||
__all__ = ['Dataset', 'source']
|
||||
|
||||
__name__ = 'tablib'
|
||||
__version__ = '0.0.4'
|
||||
__build__ = '0x000004'
|
||||
__title__ = 'tablib'
|
||||
__version__ = '0.9.3'
|
||||
__build__ = 0x000903
|
||||
__author__ = 'Kenneth Reitz'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright 2010 Kenneth Reitz'
|
||||
__copyright__ = 'Copyright 2011 Kenneth Reitz'
|
||||
|
||||
|
||||
FILE_EXTENSIONS = ('csv', 'json', 'xls', 'yaml')
|
||||
class Row(object):
|
||||
"""Internal Row object. Mainly used for filtering."""
|
||||
|
||||
__slots__ = ['tuple', '_row', 'tags']
|
||||
|
||||
def __init__(self, row=list(), tags=list()):
|
||||
self._row = list(row)
|
||||
self.tags = list(tags)
|
||||
|
||||
def __iter__(self):
|
||||
return (col for col in self._row)
|
||||
|
||||
def __len__(self):
|
||||
return len(self._row)
|
||||
|
||||
def __repr__(self):
|
||||
return repr(self._row)
|
||||
|
||||
def __getslice__(self, i, j):
|
||||
return self._row[i,j]
|
||||
|
||||
def __getitem__(self, i):
|
||||
return self._row[i]
|
||||
|
||||
def __setitem__(self, i, value):
|
||||
self._row[i] = value
|
||||
|
||||
def __delitem__(self, i):
|
||||
del self._row[i]
|
||||
|
||||
def __getstate__(self):
|
||||
result = dict()
|
||||
result['_row'] = self._row
|
||||
result['tags'] = self.tags
|
||||
|
||||
return result
|
||||
|
||||
def __setstate__(self, state):
|
||||
self._row = state['_row']
|
||||
self.tags = state['tags']
|
||||
|
||||
def append(self, value):
|
||||
self._row.append(value)
|
||||
|
||||
def insert(self, index, value):
|
||||
self._row.insert(index, value)
|
||||
|
||||
def __contains__(self, item):
|
||||
return (item in self._row)
|
||||
|
||||
@property
|
||||
def tuple(self):
|
||||
'''Tuple representation of :class:`Row`.'''
|
||||
return tuple(self._row)
|
||||
|
||||
@property
|
||||
def list(self):
|
||||
'''List representation of :class:`Row`.'''
|
||||
return list(self._row)
|
||||
|
||||
def has_tag(self, tag):
|
||||
"""Returns true if current row contains tag."""
|
||||
|
||||
if tag == None:
|
||||
return False
|
||||
elif isinstance(tag, basestring):
|
||||
return (tag in self.tags)
|
||||
else:
|
||||
return True if len(set(tag) & set(self.tags)) else False
|
||||
|
||||
|
||||
class Dataset(object):
|
||||
"""Epic Tabular-Dataset object. """
|
||||
"""The :class:`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:: Format Attributes Definition
|
||||
|
||||
If you look at the code, the various output/import formats are not
|
||||
defined within the :class:`Dataset` object. To add support for a new format, see
|
||||
:ref:`Adding New Formats <newformats>`.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._data = None
|
||||
self._saved_file = None
|
||||
self._saved_format = None
|
||||
self._data = list(Row(arg) for arg in args)
|
||||
self.__headers = None
|
||||
|
||||
|
||||
self._data = list(args)
|
||||
# ('title', index) tuples
|
||||
self._separators = []
|
||||
|
||||
try:
|
||||
self.headers = kwargs['headers']
|
||||
except KeyError, why:
|
||||
self.headers = kwargs['headers']
|
||||
except KeyError:
|
||||
self.headers = None
|
||||
|
||||
try:
|
||||
self.title = kwargs['title']
|
||||
except KeyError, why:
|
||||
self.title = kwargs['title']
|
||||
except KeyError:
|
||||
self.title = None
|
||||
|
||||
|
||||
self._register_formats()
|
||||
|
||||
|
||||
def __len__(self):
|
||||
return self.height
|
||||
|
||||
|
||||
|
||||
def __getitem__(self, key):
|
||||
if is_string(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]
|
||||
_results = self._data[key]
|
||||
if isinstance(_results, Row):
|
||||
return _results.tuple
|
||||
else:
|
||||
return [result.tuple for result in _results]
|
||||
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self._validate(value)
|
||||
self._data[key] = tuple(value)
|
||||
self._data[key] = Row(value)
|
||||
|
||||
|
||||
def __delitem__(self, key):
|
||||
del self._data[key]
|
||||
if isinstance(key, basestring):
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
if self.title:
|
||||
return '<%s dataset>' % (self.title.lower())
|
||||
if key in self.headers:
|
||||
|
||||
pos = self.headers.index(key)
|
||||
del self.headers[pos]
|
||||
|
||||
for i, row in enumerate(self._data):
|
||||
|
||||
del row[pos]
|
||||
self._data[i] = row
|
||||
else:
|
||||
raise KeyError
|
||||
else:
|
||||
del self._data[key]
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
try:
|
||||
return '<%s dataset>' % (self.title.lower())
|
||||
except AttributeError:
|
||||
return '<dataset object>'
|
||||
|
||||
|
||||
def _validate(self, row=None, safety=False):
|
||||
@classmethod
|
||||
def _register_formats(cls):
|
||||
"""Adds format properties."""
|
||||
for fmt in formats.available:
|
||||
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 len(col) < 1:
|
||||
is_valid = True
|
||||
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))
|
||||
is_valid = all((len(x) == self.width for x in self._data))
|
||||
|
||||
if is_valid:
|
||||
return True
|
||||
@@ -117,104 +244,517 @@ class Dataset(object):
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def _clean_col(self, col):
|
||||
"""Prepares the given column for insert/append."""
|
||||
|
||||
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)
|
||||
|
||||
return col
|
||||
|
||||
|
||||
@property
|
||||
def height(self):
|
||||
"""Returns the height of the Dataset."""
|
||||
"""The number of rows currently in the :class:`Dataset`.
|
||||
Cannot be directly modified.
|
||||
"""
|
||||
return len(self._data)
|
||||
|
||||
|
||||
@property
|
||||
def width(self):
|
||||
"""Returns the width of the Dataset."""
|
||||
"""The number of columns currently in the :class:`Dataset`.
|
||||
Cannot be directly modified.
|
||||
"""
|
||||
|
||||
try:
|
||||
return len(self._data[0])
|
||||
except KeyError, why:
|
||||
return 0
|
||||
|
||||
|
||||
@property
|
||||
def json(self):
|
||||
"""Returns JSON representation of Dataset."""
|
||||
return json.dumps(self._package())
|
||||
|
||||
|
||||
@property
|
||||
def yaml(self):
|
||||
"""Returns YAML representation of Dataset."""
|
||||
return yaml.dump(self._package())
|
||||
return len(self._data[0])
|
||||
except IndexError:
|
||||
try:
|
||||
return len(self.headers)
|
||||
except TypeError:
|
||||
return 0
|
||||
|
||||
|
||||
@property
|
||||
def csv(self):
|
||||
"""Returns CSV representation of Dataset."""
|
||||
stream = cStringIO.StringIO()
|
||||
_csv = csv.writer(stream)
|
||||
def headers(self):
|
||||
"""An *optional* list of strings to be used for header rows and attribute names.
|
||||
|
||||
for row in self._package(dicts=False):
|
||||
_csv.writerow(row)
|
||||
|
||||
return stream.getvalue()
|
||||
This must be set manually. The given list length must equal :class:`Dataset.width`.
|
||||
|
||||
"""
|
||||
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 xls(self):
|
||||
"""Returns XLS representation of Dataset."""
|
||||
stream = cStringIO.StringIO()
|
||||
|
||||
wb = xlwt.Workbook()
|
||||
ws = wb.add_sheet(self.title if self.title else 'Tabbed Dataset')
|
||||
# for row in self._package(dicts=False):
|
||||
for i, row in enumerate(self._package(dicts=False)):
|
||||
for j, col in enumerate(row):
|
||||
ws.write(i, j, col)
|
||||
def dict(self):
|
||||
"""A JSON representation of the :class:`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.
|
||||
|
||||
wb.save(stream)
|
||||
return stream.getvalue()
|
||||
A dataset object can also be imported by setting the `Dataset.json` attribute: ::
|
||||
|
||||
|
||||
def append(self, row):
|
||||
"""Adds a row to the end of Dataset"""
|
||||
self._validate(row)
|
||||
self._data.append(tuple(row))
|
||||
data = tablib.Dataset()
|
||||
data.json = '[{"last_name": "Adams","age": 90,"first_name": "John"}]'
|
||||
|
||||
def index(self, i, row):
|
||||
"""Inserts a row at given position in Dataset"""
|
||||
self._validate(row)
|
||||
self._data.insert(i, tuple(row))
|
||||
"""
|
||||
return self._package()
|
||||
|
||||
def sort_by(self, key):
|
||||
"""Sorts datastet by given key"""
|
||||
# todo: accpept string if headers, or index nubmer
|
||||
|
||||
@dict.setter
|
||||
def dict(self, pickle):
|
||||
"""A 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 :class:`Dataset.dict` attribute. ::
|
||||
|
||||
data = tablib.Dataset()
|
||||
data.dict = [{'age': 90, 'first_name': 'Kenneth', 'last_name': 'Reitz'}]
|
||||
|
||||
"""
|
||||
if not len(pickle):
|
||||
return
|
||||
|
||||
# if list of rows
|
||||
if isinstance(pickle[0], list):
|
||||
self.wipe()
|
||||
for row in pickle:
|
||||
self.append(Row(row))
|
||||
|
||||
# if list of objects
|
||||
elif isinstance(pickle[0], dict):
|
||||
self.wipe()
|
||||
self.headers = pickle[0].keys()
|
||||
for row in pickle:
|
||||
self.append(Row(row.values()))
|
||||
else:
|
||||
raise UnsupportedFormat
|
||||
|
||||
@property
|
||||
def xls():
|
||||
"""An Excel Spreadsheet representation of the :class:`Dataset` object, with :ref:`seperators`. Cannot be set.
|
||||
|
||||
.. admonition:: Binary Warning
|
||||
|
||||
:class:`Dataset.xls` contains binary data, so make sure to write in binary mode::
|
||||
|
||||
with open('output.xls', 'wb') as f:
|
||||
f.write(data.xls)'
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def save(self, filename=None, format=None):
|
||||
"""Saves dataset"""
|
||||
if not format:
|
||||
format = filename.split('.')[-1].lower() # set format from filename
|
||||
|
||||
if format not in FILE_EXTENSIONS:
|
||||
raise UnsupportedFormat
|
||||
|
||||
@property
|
||||
def csv():
|
||||
"""A CSV representation of the :class:`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.
|
||||
|
||||
# note export format
|
||||
# open file, save the bitch
|
||||
A dataset object can also be imported by setting the :class:`Dataset.csv` attribute. ::
|
||||
|
||||
data = tablib.Dataset()
|
||||
data.csv = 'age, first_name, last_name\\n90, John, Adams'
|
||||
|
||||
Import assumes (for now) that headers exist.
|
||||
"""
|
||||
pass
|
||||
|
||||
@property
|
||||
def tsv():
|
||||
"""A TSV representation of the :class:`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 :class:`Dataset.tsv` attribute. ::
|
||||
|
||||
data = tablib.Dataset()
|
||||
data.tsv = 'age\tfirst_name\tlast_name\\n90\tJohn\tAdams'
|
||||
|
||||
Import assumes (for now) that headers exist.
|
||||
"""
|
||||
|
||||
@property
|
||||
def yaml():
|
||||
"""A YAML representation of the :class:`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 :class:`Dataset.json` attribute: ::
|
||||
|
||||
data = tablib.Dataset()
|
||||
data.yaml = '- {age: 90, first_name: John, last_name: Adams}'
|
||||
|
||||
Import assumes (for now) that headers exist.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@property
|
||||
def json():
|
||||
"""A JSON representation of the :class:`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 :class:`Dataset.json` attribute: ::
|
||||
|
||||
data = tablib.Dataset()
|
||||
data.json = '[{age: 90, first_name: "John", liast_name: "Adams"}]'
|
||||
|
||||
Import assumes (for now) that headers exist.
|
||||
"""
|
||||
|
||||
@property
|
||||
def html():
|
||||
"""A HTML table representation of the :class:`Dataset` object. If
|
||||
headers have been set, they will be used as table headers.
|
||||
|
||||
..notice:: This method can be used for export only.
|
||||
"""
|
||||
pass
|
||||
|
||||
def append(self, row=None, col=None, header=None, tags=list()):
|
||||
"""Adds a row or column to the :class:`Dataset`.
|
||||
Usage is :class:`Dataset.insert` for documentation.
|
||||
"""
|
||||
|
||||
if row is not None:
|
||||
self.insert(self.height, row=row, tags=tags)
|
||||
elif col is not None:
|
||||
self.insert(self.width, col=col, header=header)
|
||||
|
||||
def insert_separator(self, index, text='-'):
|
||||
"""Adds a separator to :class:`Dataset` at given index."""
|
||||
|
||||
sep = (index, text)
|
||||
self._separators.append(sep)
|
||||
|
||||
|
||||
def append_separator(self, text='-'):
|
||||
"""Adds a :ref:`seperator <seperators>` to the :class:`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, index, row=None, col=None, header=None, tags=list()):
|
||||
"""Inserts a row or column to the :class:`Dataset` at the given index.
|
||||
|
||||
Rows and columns inserted must be the correct size (height or width).
|
||||
|
||||
The default behaviour is to insert the given row to the :class:`Dataset`
|
||||
object at the given index. If the ``col`` parameter is given, however,
|
||||
a new column will be insert to the :class:`Dataset` object instead.
|
||||
|
||||
You can also insert a column of a single callable object, which will
|
||||
add a new column with the return values of the callable each as an
|
||||
item in the column. ::
|
||||
|
||||
data.append(col=random.randint)
|
||||
|
||||
See :ref:`dyncols` for an in-depth example.
|
||||
|
||||
.. versionchanged:: 0.9.0
|
||||
If inserting a column, and :class:`Dataset.headers` is set, the
|
||||
header attribute must be set, and will be considered the header for
|
||||
that row.
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
If inserting a row, you can add :ref:`tags <tags>` to the row you are inserting.
|
||||
This gives you the ability to :class:`filter <Dataset.filter>` your
|
||||
:class:`Dataset` later.
|
||||
|
||||
"""
|
||||
if row:
|
||||
self._validate(row)
|
||||
self._data.insert(index, Row(row, tags=tags))
|
||||
elif col:
|
||||
col = list(col)
|
||||
|
||||
# Callable Columns...
|
||||
if len(col) == 1 and callable(col[0]):
|
||||
col = map(col[0], self._data)
|
||||
|
||||
col = self._clean_col(col)
|
||||
self._validate(col=col)
|
||||
|
||||
if self.headers:
|
||||
# pop the first item off, add to headers
|
||||
if not header:
|
||||
raise HeadersNeeded()
|
||||
self.headers.insert(index, header)
|
||||
|
||||
if self.height and self.width:
|
||||
|
||||
for i, row in enumerate(self._data):
|
||||
|
||||
row.insert(index, col[i])
|
||||
self._data[i] = row
|
||||
else:
|
||||
self._data = [Row([row]) for row in col]
|
||||
|
||||
|
||||
def filter(self, tag):
|
||||
"""Returns a new instance of the :class:`Dataset`, excluding any rows
|
||||
that do not contain the given :ref:`tags <tags>`.
|
||||
"""
|
||||
_dset = copy(self)
|
||||
_dset._data = [row for row in _dset._data if row.has_tag(tag)]
|
||||
|
||||
return _dset
|
||||
|
||||
|
||||
def sort(self, col, reverse=False):
|
||||
"""Sort a :class:`Dataset` by a specific column, given string (for
|
||||
header) or integer (for column index). The order can be reversed by
|
||||
setting ``reverse`` to ``True``.
|
||||
Returns a new :class:`Dataset` instance where columns have been
|
||||
sorted."""
|
||||
|
||||
def export(self):
|
||||
"""Exports Dataset to given filename or file-object."""
|
||||
if isinstance(col, basestring):
|
||||
|
||||
if not self.headers:
|
||||
raise HeadersNeeded
|
||||
|
||||
_sorted = sorted(self.dict, key=itemgetter(col), reverse=reverse)
|
||||
_dset = Dataset(headers=self.headers)
|
||||
|
||||
for item in _sorted:
|
||||
row = [item[key] for key in self.headers]
|
||||
_dset.append(row=row)
|
||||
|
||||
else:
|
||||
if self.headers:
|
||||
col = self.headers[col]
|
||||
|
||||
_sorted = sorted(self.dict, key=itemgetter(col), reverse=reverse)
|
||||
_dset = Dataset(headers=self.headers)
|
||||
|
||||
for item in _sorted:
|
||||
if self.headers:
|
||||
row = [item[key] for key in self.headers]
|
||||
else:
|
||||
row = item
|
||||
_dset.append(row=row)
|
||||
|
||||
|
||||
return _dset
|
||||
|
||||
def transpose(self):
|
||||
"""Transpose a :class:`Dataset`, turning rows into columns and vice
|
||||
versa, returning a new ``Dataset`` instance. The first row of the
|
||||
original instance becomes the new header row."""
|
||||
|
||||
# Don't transpose if there is no data
|
||||
if not self:
|
||||
return
|
||||
|
||||
_dset = Dataset()
|
||||
# The first element of the headers stays in the headers,
|
||||
# it is our "hinge" on which we rotate the data
|
||||
new_headers = [self.headers[0]] + self[self.headers[0]]
|
||||
|
||||
_dset.headers = new_headers
|
||||
for column in self.headers:
|
||||
|
||||
if column == self.headers[0]:
|
||||
# It's in the headers, so skip it
|
||||
continue
|
||||
|
||||
# Adding the column name as now they're a regular column
|
||||
row_data = [column] + self[column]
|
||||
row_data = Row(row_data)
|
||||
_dset.append(row=row_data)
|
||||
|
||||
return _dset
|
||||
|
||||
|
||||
def stack_rows(self, other):
|
||||
"""Stack two :class:`Dataset` instances together by
|
||||
joining at the row level, and return new combined
|
||||
``Dataset`` instance."""
|
||||
|
||||
if not isinstance(other, Dataset):
|
||||
return
|
||||
|
||||
if self.width != other.width:
|
||||
raise InvalidDimensions
|
||||
|
||||
# Copy the source data
|
||||
_dset = copy(self)
|
||||
|
||||
rows_to_stack = [row for row in _dset._data]
|
||||
other_rows = [row for row in other._data]
|
||||
|
||||
rows_to_stack.extend(other_rows)
|
||||
_dset._data = rows_to_stack
|
||||
|
||||
return _dset
|
||||
|
||||
|
||||
def stack_columns(self, other):
|
||||
"""Stack two :class:`Dataset` instances together by
|
||||
joining at the column level, and return a new
|
||||
combined ``Dataset`` instance. If either ``Dataset``
|
||||
has headers set, than the other must as well."""
|
||||
|
||||
if not isinstance(other, Dataset):
|
||||
return
|
||||
|
||||
if self.headers or other.headers:
|
||||
if not self.headers or not other.headers:
|
||||
raise HeadersNeeded
|
||||
|
||||
if self.height != other.height:
|
||||
raise InvalidDimensions
|
||||
|
||||
try:
|
||||
new_headers = self.headers + other.headers
|
||||
except TypeError:
|
||||
new_headers = None
|
||||
|
||||
_dset = Dataset()
|
||||
|
||||
for column in self.headers:
|
||||
_dset.append(col=self[column])
|
||||
|
||||
for column in other.headers:
|
||||
_dset.append(col=other[column])
|
||||
|
||||
_dset.headers = new_headers
|
||||
|
||||
return _dset
|
||||
|
||||
def wipe(self):
|
||||
"""Removes all content and headers from the :class:`Dataset` object."""
|
||||
self._data = list()
|
||||
self.__headers = None
|
||||
|
||||
|
||||
class Databook(object):
|
||||
"""A book of :class:`Dataset` objects.
|
||||
"""
|
||||
|
||||
def __init__(self, sets=None):
|
||||
|
||||
if sets is None:
|
||||
self._datasets = list()
|
||||
else:
|
||||
self._datasets = sets
|
||||
|
||||
self._register_formats()
|
||||
|
||||
def __repr__(self):
|
||||
try:
|
||||
return '<%s databook>' % (self.title.lower())
|
||||
except AttributeError:
|
||||
return '<databook object>'
|
||||
|
||||
|
||||
def wipe(self):
|
||||
"""Removes all :class:`Dataset` objects from the :class:`Databook`."""
|
||||
self._datasets = []
|
||||
|
||||
|
||||
@classmethod
|
||||
def _register_formats(cls):
|
||||
"""Adds format properties."""
|
||||
for fmt in formats.available:
|
||||
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 :class:`Dataset` to the :class:`Databook`."""
|
||||
if type(dataset) is Dataset:
|
||||
self._datasets.append(dataset)
|
||||
else:
|
||||
raise InvalidDatasetType
|
||||
|
||||
|
||||
def _package(self):
|
||||
"""Packages :class:`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 :class:`Dataset` objects within :class:`Databook`."""
|
||||
return len(self._datasets)
|
||||
|
||||
|
||||
def detect(stream):
|
||||
"""Return (format, stream) of given stream."""
|
||||
for fmt in formats.available:
|
||||
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 HeadersNeeded(Exception):
|
||||
"Header parameter must be given when appending a column in this Dataset."
|
||||
|
||||
class UnsupportedFormat(NotImplementedError):
|
||||
"Format is not supported"
|
||||
|
||||
|
||||
|
||||
def source(src=None, file=None, filename=None):
|
||||
"""docstring for import"""
|
||||
#open by filename
|
||||
pass
|
||||
@@ -0,0 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
""" Tablib - formats
|
||||
"""
|
||||
|
||||
import _csv as csv
|
||||
import _json as json
|
||||
import _xls as xls
|
||||
import _yaml as yaml
|
||||
import _tsv as tsv
|
||||
import _html as html
|
||||
|
||||
available = (json, xls, yaml, csv, tsv, html)
|
||||
@@ -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,53 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
""" Tablib - HTML export support.
|
||||
"""
|
||||
|
||||
from StringIO import StringIO
|
||||
|
||||
from tablib.packages import markup
|
||||
import tablib
|
||||
|
||||
BOOK_ENDINGS = 'h3'
|
||||
|
||||
title = 'html'
|
||||
extentions = ('html', )
|
||||
|
||||
|
||||
def export_set(dataset):
|
||||
"""HTML representation of a Dataset."""
|
||||
|
||||
stream = StringIO()
|
||||
|
||||
page = markup.page()
|
||||
page.table.open()
|
||||
|
||||
if dataset.headers is not None:
|
||||
page.thead.open()
|
||||
headers = markup.oneliner.th(dataset.headers)
|
||||
page.tr(headers)
|
||||
page.thead.close()
|
||||
|
||||
for row in dataset:
|
||||
html_row = markup.oneliner.td(row)
|
||||
page.tr(html_row)
|
||||
|
||||
page.table.close()
|
||||
|
||||
stream.writelines(str(page))
|
||||
|
||||
return stream.getvalue()
|
||||
|
||||
|
||||
def export_book(databook):
|
||||
"""HTML representation of a Databook."""
|
||||
|
||||
stream = StringIO()
|
||||
|
||||
for i, dset in enumerate(databook._datasets):
|
||||
title = (dset.title if dset.title else 'Set %s' % (i))
|
||||
stream.write('<%s>%s</%s>\n' % (BOOK_ENDINGS, title, BOOK_ENDINGS))
|
||||
stream.write(dset.html)
|
||||
stream.write('\n')
|
||||
|
||||
return stream.getvalue()
|
||||
@@ -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,51 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
""" Tablib - TSV (Tab Separated Values) Support.
|
||||
"""
|
||||
|
||||
import cStringIO
|
||||
import csv
|
||||
import os
|
||||
|
||||
import tablib
|
||||
|
||||
|
||||
title = 'tsv'
|
||||
extentions = ('tsv',)
|
||||
|
||||
|
||||
|
||||
def export_set(dataset):
|
||||
"""Returns a TSV representation of Dataset."""
|
||||
stream = cStringIO.StringIO()
|
||||
_tsv = csv.writer(stream, delimiter='\t')
|
||||
|
||||
for row in dataset._package(dicts=False):
|
||||
_tsv.writerow(row)
|
||||
|
||||
return stream.getvalue()
|
||||
|
||||
|
||||
def import_set(dset, in_stream, headers=True):
|
||||
"""Returns dataset from TSV stream."""
|
||||
dset.wipe()
|
||||
|
||||
rows = csv.reader(in_stream.split('\r\n'), delimiter='\t')
|
||||
for i, row in enumerate(rows):
|
||||
# Skip empty rows
|
||||
if not row:
|
||||
continue
|
||||
|
||||
if (i == 0) and (headers):
|
||||
dset.headers = row
|
||||
else:
|
||||
dset.append(row)
|
||||
|
||||
|
||||
def detect(stream):
|
||||
"""Returns True if given stream is valid TSV."""
|
||||
try:
|
||||
rows = dialect = csv.Sniffer().sniff(stream, delimiters='\t')
|
||||
return True
|
||||
except csv.Error:
|
||||
return False
|
||||
@@ -0,0 +1,85 @@
|
||||
# -*- 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)
|
||||
|
||||
# frozen header row
|
||||
ws.panes_frozen = True
|
||||
ws.horz_split_pos = 1
|
||||
|
||||
|
||||
# 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
|
||||
+20
-8
@@ -1,25 +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
|
||||
|
||||
|
||||
def is_string(obj):
|
||||
"""Tests if an object is a string"""
|
||||
|
||||
return True if type(obj).__name__ == 'str' else False
|
||||
@@ -1 +0,0 @@
|
||||
all = ['simplejson', 'typecheck', 'xlwt', 'opster']
|
||||
@@ -0,0 +1,484 @@
|
||||
# This code is in the public domain, it comes
|
||||
# with absolutely no warranty and you can do
|
||||
# absolutely whatever you want with it.
|
||||
|
||||
__date__ = '17 May 2007'
|
||||
__version__ = '1.7'
|
||||
__doc__= """
|
||||
This is markup.py - a Python module that attempts to
|
||||
make it easier to generate HTML/XML from a Python program
|
||||
in an intuitive, lightweight, customizable and pythonic way.
|
||||
|
||||
The code is in the public domain.
|
||||
|
||||
Version: %s as of %s.
|
||||
|
||||
Documentation and further info is at http://markup.sourceforge.net/
|
||||
|
||||
Please send bug reports, feature requests, enhancement
|
||||
ideas or questions to nogradi at gmail dot com.
|
||||
|
||||
Installation: drop markup.py somewhere into your Python path.
|
||||
""" % ( __version__, __date__ )
|
||||
|
||||
import string
|
||||
|
||||
class element:
|
||||
"""This class handles the addition of a new element."""
|
||||
|
||||
def __init__( self, tag, case='lower', parent=None ):
|
||||
self.parent = parent
|
||||
|
||||
if case == 'lower':
|
||||
self.tag = tag.lower( )
|
||||
else:
|
||||
self.tag = tag.upper( )
|
||||
|
||||
def __call__( self, *args, **kwargs ):
|
||||
if len( args ) > 1:
|
||||
raise ArgumentError( self.tag )
|
||||
|
||||
# if class_ was defined in parent it should be added to every element
|
||||
if self.parent is not None and self.parent.class_ is not None:
|
||||
if 'class_' not in kwargs:
|
||||
kwargs['class_'] = self.parent.class_
|
||||
|
||||
if self.parent is None and len( args ) == 1:
|
||||
x = [ self.render( self.tag, False, myarg, mydict ) for myarg, mydict in _argsdicts( args, kwargs ) ]
|
||||
return '\n'.join( x )
|
||||
elif self.parent is None and len( args ) == 0:
|
||||
x = [ self.render( self.tag, True, myarg, mydict ) for myarg, mydict in _argsdicts( args, kwargs ) ]
|
||||
return '\n'.join( x )
|
||||
|
||||
if self.tag in self.parent.twotags:
|
||||
for myarg, mydict in _argsdicts( args, kwargs ):
|
||||
self.render( self.tag, False, myarg, mydict )
|
||||
elif self.tag in self.parent.onetags:
|
||||
if len( args ) == 0:
|
||||
for myarg, mydict in _argsdicts( args, kwargs ):
|
||||
self.render( self.tag, True, myarg, mydict ) # here myarg is always None, because len( args ) = 0
|
||||
else:
|
||||
raise ClosingError( self.tag )
|
||||
elif self.parent.mode == 'strict_html' and self.tag in self.parent.deptags:
|
||||
raise DeprecationError( self.tag )
|
||||
else:
|
||||
raise InvalidElementError( self.tag, self.parent.mode )
|
||||
|
||||
def render( self, tag, single, between, kwargs ):
|
||||
"""Append the actual tags to content."""
|
||||
|
||||
out = "<%s" % tag
|
||||
for key, value in kwargs.iteritems( ):
|
||||
if value is not None: # when value is None that means stuff like <... checked>
|
||||
key = key.strip('_') # strip this so class_ will mean class, etc.
|
||||
if key == 'http_equiv': # special cases, maybe change _ to - overall?
|
||||
key = 'http-equiv'
|
||||
elif key == 'accept_charset':
|
||||
key = 'accept-charset'
|
||||
out = "%s %s=\"%s\"" % ( out, key, escape( value ) )
|
||||
else:
|
||||
out = "%s %s" % ( out, key )
|
||||
if between is not None:
|
||||
out = "%s>%s</%s>" % ( out, between, tag )
|
||||
else:
|
||||
if single:
|
||||
out = "%s />" % out
|
||||
else:
|
||||
out = "%s>" % out
|
||||
if self.parent is not None:
|
||||
self.parent.content.append( out )
|
||||
else:
|
||||
return out
|
||||
|
||||
def close( self ):
|
||||
"""Append a closing tag unless element has only opening tag."""
|
||||
|
||||
if self.tag in self.parent.twotags:
|
||||
self.parent.content.append( "</%s>" % self.tag )
|
||||
elif self.tag in self.parent.onetags:
|
||||
raise ClosingError( self.tag )
|
||||
elif self.parent.mode == 'strict_html' and self.tag in self.parent.deptags:
|
||||
raise DeprecationError( self.tag )
|
||||
|
||||
def open( self, **kwargs ):
|
||||
"""Append an opening tag."""
|
||||
|
||||
if self.tag in self.parent.twotags or self.tag in self.parent.onetags:
|
||||
self.render( self.tag, False, None, kwargs )
|
||||
elif self.mode == 'strict_html' and self.tag in self.parent.deptags:
|
||||
raise DeprecationError( self.tag )
|
||||
|
||||
class page:
|
||||
"""This is our main class representing a document. Elements are added
|
||||
as attributes of an instance of this class."""
|
||||
|
||||
def __init__( self, mode='strict_html', case='lower', onetags=None, twotags=None, separator='\n', class_=None ):
|
||||
"""Stuff that effects the whole document.
|
||||
|
||||
mode -- 'strict_html' for HTML 4.01 (default)
|
||||
'html' alias for 'strict_html'
|
||||
'loose_html' to allow some deprecated elements
|
||||
'xml' to allow arbitrary elements
|
||||
|
||||
case -- 'lower' element names will be printed in lower case (default)
|
||||
'upper' they will be printed in upper case
|
||||
|
||||
onetags -- list or tuple of valid elements with opening tags only
|
||||
twotags -- list or tuple of valid elements with both opening and closing tags
|
||||
these two keyword arguments may be used to select
|
||||
the set of valid elements in 'xml' mode
|
||||
invalid elements will raise appropriate exceptions
|
||||
|
||||
separator -- string to place between added elements, defaults to newline
|
||||
|
||||
class_ -- a class that will be added to every element if defined"""
|
||||
|
||||
valid_onetags = [ "AREA", "BASE", "BR", "COL", "FRAME", "HR", "IMG", "INPUT", "LINK", "META", "PARAM" ]
|
||||
valid_twotags = [ "A", "ABBR", "ACRONYM", "ADDRESS", "B", "BDO", "BIG", "BLOCKQUOTE", "BODY", "BUTTON",
|
||||
"CAPTION", "CITE", "CODE", "COLGROUP", "DD", "DEL", "DFN", "DIV", "DL", "DT", "EM", "FIELDSET",
|
||||
"FORM", "FRAMESET", "H1", "H2", "H3", "H4", "H5", "H6", "HEAD", "HTML", "I", "IFRAME", "INS",
|
||||
"KBD", "LABEL", "LEGEND", "LI", "MAP", "NOFRAMES", "NOSCRIPT", "OBJECT", "OL", "OPTGROUP",
|
||||
"OPTION", "P", "PRE", "Q", "SAMP", "SCRIPT", "SELECT", "SMALL", "SPAN", "STRONG", "STYLE",
|
||||
"SUB", "SUP", "TABLE", "TBODY", "TD", "TEXTAREA", "TFOOT", "TH", "THEAD", "TITLE", "TR",
|
||||
"TT", "UL", "VAR" ]
|
||||
deprecated_onetags = [ "BASEFONT", "ISINDEX" ]
|
||||
deprecated_twotags = [ "APPLET", "CENTER", "DIR", "FONT", "MENU", "S", "STRIKE", "U" ]
|
||||
|
||||
self.header = [ ]
|
||||
self.content = [ ]
|
||||
self.footer = [ ]
|
||||
self.case = case
|
||||
self.separator = separator
|
||||
|
||||
# init( ) sets it to True so we know that </body></html> has to be printed at the end
|
||||
self._full = False
|
||||
self.class_= class_
|
||||
|
||||
if mode == 'strict_html' or mode == 'html':
|
||||
self.onetags = valid_onetags
|
||||
self.onetags += map( string.lower, self.onetags )
|
||||
self.twotags = valid_twotags
|
||||
self.twotags += map( string.lower, self.twotags )
|
||||
self.deptags = deprecated_onetags + deprecated_twotags
|
||||
self.deptags += map( string.lower, self.deptags )
|
||||
self.mode = 'strict_html'
|
||||
elif mode == 'loose_html':
|
||||
self.onetags = valid_onetags + deprecated_onetags
|
||||
self.onetags += map( string.lower, self.onetags )
|
||||
self.twotags = valid_twotags + deprecated_twotags
|
||||
self.twotags += map( string.lower, self.twotags )
|
||||
self.mode = mode
|
||||
elif mode == 'xml':
|
||||
if onetags and twotags:
|
||||
self.onetags = onetags
|
||||
self.twotags = twotags
|
||||
elif ( onetags and not twotags ) or ( twotags and not onetags ):
|
||||
raise CustomizationError( )
|
||||
else:
|
||||
self.onetags = russell( )
|
||||
self.twotags = russell( )
|
||||
self.mode = mode
|
||||
else:
|
||||
raise ModeError( mode )
|
||||
|
||||
def __getattr__( self, attr ):
|
||||
if attr.startswith("__") and attr.endswith("__"):
|
||||
raise AttributeError, attr
|
||||
return element( attr, case=self.case, parent=self )
|
||||
|
||||
def __str__( self ):
|
||||
|
||||
if self._full and ( self.mode == 'strict_html' or self.mode == 'loose_html' ):
|
||||
end = [ '</body>', '</html>' ]
|
||||
else:
|
||||
end = [ ]
|
||||
|
||||
return self.separator.join( self.header + self.content + self.footer + end )
|
||||
|
||||
def __call__( self, escape=False ):
|
||||
"""Return the document as a string.
|
||||
|
||||
escape -- False print normally
|
||||
True replace < and > by < and >
|
||||
the default escape sequences in most browsers"""
|
||||
|
||||
if escape:
|
||||
return _escape( self.__str__( ) )
|
||||
else:
|
||||
return self.__str__( )
|
||||
|
||||
def add( self, text ):
|
||||
"""This is an alias to addcontent."""
|
||||
self.addcontent( text )
|
||||
|
||||
def addfooter( self, text ):
|
||||
"""Add some text to the bottom of the document"""
|
||||
self.footer.append( text )
|
||||
|
||||
def addheader( self, text ):
|
||||
"""Add some text to the top of the document"""
|
||||
self.header.append( text )
|
||||
|
||||
def addcontent( self, text ):
|
||||
"""Add some text to the main part of the document"""
|
||||
self.content.append( text )
|
||||
|
||||
|
||||
def init( self, lang='en', css=None, metainfo=None, title=None, header=None,
|
||||
footer=None, charset=None, encoding=None, doctype=None, bodyattrs=None, script=None ):
|
||||
"""This method is used for complete documents with appropriate
|
||||
doctype, encoding, title, etc information. For an HTML/XML snippet
|
||||
omit this method.
|
||||
|
||||
lang -- language, usually a two character string, will appear
|
||||
as <html lang='en'> in html mode (ignored in xml mode)
|
||||
|
||||
css -- Cascading Style Sheet filename as a string or a list of
|
||||
strings for multiple css files (ignored in xml mode)
|
||||
|
||||
metainfo -- a dictionary in the form { 'name':'content' } to be inserted
|
||||
into meta element(s) as <meta name='name' content='content'>
|
||||
(ignored in xml mode)
|
||||
|
||||
bodyattrs --a dictionary in the form { 'key':'value', ... } which will be added
|
||||
as attributes of the <body> element as <body key='value' ... >
|
||||
(ignored in xml mode)
|
||||
|
||||
script -- dictionary containing src:type pairs, <script type='text/type' src=src></script>
|
||||
|
||||
title -- the title of the document as a string to be inserted into
|
||||
a title element as <title>my title</title> (ignored in xml mode)
|
||||
|
||||
header -- some text to be inserted right after the <body> element
|
||||
(ignored in xml mode)
|
||||
|
||||
footer -- some text to be inserted right before the </body> element
|
||||
(ignored in xml mode)
|
||||
|
||||
charset -- a string defining the character set, will be inserted into a
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=myset'>
|
||||
element (ignored in xml mode)
|
||||
|
||||
encoding -- a string defining the encoding, will be put into to first line of
|
||||
the document as <?xml version='1.0' encoding='myencoding' ?> in
|
||||
xml mode (ignored in html mode)
|
||||
|
||||
doctype -- the document type string, defaults to
|
||||
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>
|
||||
in html mode (ignored in xml mode)"""
|
||||
|
||||
self._full = True
|
||||
|
||||
if self.mode == 'strict_html' or self.mode == 'loose_html':
|
||||
if doctype is None:
|
||||
doctype = "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>"
|
||||
self.header.append( doctype )
|
||||
self.html( lang=lang )
|
||||
self.head( )
|
||||
if charset is not None:
|
||||
self.meta( http_equiv='Content-Type', content="text/html; charset=%s" % charset )
|
||||
if metainfo is not None:
|
||||
self.metainfo( metainfo )
|
||||
if css is not None:
|
||||
self.css( css )
|
||||
if title is not None:
|
||||
self.title( title )
|
||||
if script is not None:
|
||||
self.scripts( script )
|
||||
self.head.close()
|
||||
if bodyattrs is not None:
|
||||
self.body( **bodyattrs )
|
||||
else:
|
||||
self.body( )
|
||||
if header is not None:
|
||||
self.content.append( header )
|
||||
if footer is not None:
|
||||
self.footer.append( footer )
|
||||
|
||||
elif self.mode == 'xml':
|
||||
if doctype is None:
|
||||
if encoding is not None:
|
||||
doctype = "<?xml version='1.0' encoding='%s' ?>" % encoding
|
||||
else:
|
||||
doctype = "<?xml version='1.0' ?>"
|
||||
self.header.append( doctype )
|
||||
|
||||
def css( self, filelist ):
|
||||
"""This convenience function is only useful for html.
|
||||
It adds css stylesheet(s) to the document via the <link> element."""
|
||||
|
||||
if isinstance( filelist, basestring ):
|
||||
self.link( href=filelist, rel='stylesheet', type='text/css', media='all' )
|
||||
else:
|
||||
for file in filelist:
|
||||
self.link( href=file, rel='stylesheet', type='text/css', media='all' )
|
||||
|
||||
def metainfo( self, mydict ):
|
||||
"""This convenience function is only useful for html.
|
||||
It adds meta information via the <meta> element, the argument is
|
||||
a dictionary of the form { 'name':'content' }."""
|
||||
|
||||
if isinstance( mydict, dict ):
|
||||
for name, content in mydict.iteritems( ):
|
||||
self.meta( name=name, content=content )
|
||||
else:
|
||||
raise TypeError, "Metainfo should be called with a dictionary argument of name:content pairs."
|
||||
|
||||
def scripts( self, mydict ):
|
||||
"""Only useful in html, mydict is dictionary of src:type pairs will
|
||||
be rendered as <script type='text/type' src=src></script>"""
|
||||
|
||||
if isinstance( mydict, dict ):
|
||||
for src, type in mydict.iteritems( ):
|
||||
self.script( '', src=src, type='text/%s' % type )
|
||||
else:
|
||||
raise TypeError, "Script should be given a dictionary of src:type pairs."
|
||||
|
||||
|
||||
class _oneliner:
|
||||
"""An instance of oneliner returns a string corresponding to one element.
|
||||
This class can be used to write 'oneliners' that return a string
|
||||
immediately so there is no need to instantiate the page class."""
|
||||
|
||||
def __init__( self, case='lower' ):
|
||||
self.case = case
|
||||
|
||||
def __getattr__( self, attr ):
|
||||
if attr.startswith("__") and attr.endswith("__"):
|
||||
raise AttributeError, attr
|
||||
return element( attr, case=self.case, parent=None )
|
||||
|
||||
oneliner = _oneliner( case='lower' )
|
||||
upper_oneliner = _oneliner( case='upper' )
|
||||
|
||||
def _argsdicts( args, mydict ):
|
||||
"""A utility generator that pads argument list and dictionary values, will only be called with len( args ) = 0, 1."""
|
||||
|
||||
if len( args ) == 0:
|
||||
args = None,
|
||||
elif len( args ) == 1:
|
||||
args = _totuple( args[0] )
|
||||
else:
|
||||
raise Exception, "We should have never gotten here."
|
||||
|
||||
mykeys = mydict.keys( )
|
||||
myvalues = map( _totuple, mydict.values( ) )
|
||||
|
||||
maxlength = max( map( len, [ args ] + myvalues ) )
|
||||
|
||||
for i in xrange( maxlength ):
|
||||
thisdict = { }
|
||||
for key, value in zip( mykeys, myvalues ):
|
||||
try:
|
||||
thisdict[ key ] = value[i]
|
||||
except IndexError:
|
||||
thisdict[ key ] = value[-1]
|
||||
try:
|
||||
thisarg = args[i]
|
||||
except IndexError:
|
||||
thisarg = args[-1]
|
||||
|
||||
yield thisarg, thisdict
|
||||
|
||||
def _totuple( x ):
|
||||
"""Utility stuff to convert string, int, float, None or anything to a usable tuple."""
|
||||
|
||||
if isinstance( x, basestring ):
|
||||
out = x,
|
||||
elif isinstance( x, ( int, float ) ):
|
||||
out = str( x ),
|
||||
elif x is None:
|
||||
out = None,
|
||||
else:
|
||||
out = tuple( x )
|
||||
|
||||
return out
|
||||
|
||||
def escape( text, newline=False ):
|
||||
"""Escape special html characters."""
|
||||
|
||||
if isinstance( text, basestring ):
|
||||
if '&' in text:
|
||||
text = text.replace( '&', '&' )
|
||||
if '>' in text:
|
||||
text = text.replace( '>', '>' )
|
||||
if '<' in text:
|
||||
text = text.replace( '<', '<' )
|
||||
if '\"' in text:
|
||||
text = text.replace( '\"', '"' )
|
||||
if '\'' in text:
|
||||
text = text.replace( '\'', '"' )
|
||||
if newline:
|
||||
if '\n' in text:
|
||||
text = text.replace( '\n', '<br>' )
|
||||
|
||||
return text
|
||||
|
||||
_escape = escape
|
||||
|
||||
def unescape( text ):
|
||||
"""Inverse of escape."""
|
||||
|
||||
if isinstance( text, basestring ):
|
||||
if '&' in text:
|
||||
text = text.replace( '&', '&' )
|
||||
if '>' in text:
|
||||
text = text.replace( '>', '>' )
|
||||
if '<' in text:
|
||||
text = text.replace( '<', '<' )
|
||||
if '"' in text:
|
||||
text = text.replace( '"', '\"' )
|
||||
|
||||
return text
|
||||
|
||||
class dummy:
|
||||
"""A dummy class for attaching attributes."""
|
||||
pass
|
||||
|
||||
doctype = dummy( )
|
||||
doctype.frameset = "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Frameset//EN' 'http://www.w3.org/TR/html4/frameset.dtd'>"
|
||||
doctype.strict = "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>"
|
||||
doctype.loose = "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'>"
|
||||
|
||||
class russell:
|
||||
"""A dummy class that contains anything."""
|
||||
|
||||
def __contains__( self, item ):
|
||||
return True
|
||||
|
||||
|
||||
class MarkupError( Exception ):
|
||||
"""All our exceptions subclass this."""
|
||||
def __str__( self ):
|
||||
return self.message
|
||||
|
||||
class ClosingError( MarkupError ):
|
||||
def __init__( self, tag ):
|
||||
self.message = "The element '%s' does not accept non-keyword arguments (has no closing tag)." % tag
|
||||
|
||||
class OpeningError( MarkupError ):
|
||||
def __init__( self, tag ):
|
||||
self.message = "The element '%s' can not be opened." % tag
|
||||
|
||||
class ArgumentError( MarkupError ):
|
||||
def __init__( self, tag ):
|
||||
self.message = "The element '%s' was called with more than one non-keyword argument." % tag
|
||||
|
||||
class InvalidElementError( MarkupError ):
|
||||
def __init__( self, tag, mode ):
|
||||
self.message = "The element '%s' is not valid for your mode '%s'." % ( tag, mode )
|
||||
|
||||
class DeprecationError( MarkupError ):
|
||||
def __init__( self, tag ):
|
||||
self.message = "The element '%s' is deprecated, instantiate markup.page with mode='loose_html' to allow it." % tag
|
||||
|
||||
class ModeError( MarkupError ):
|
||||
def __init__( self, mode ):
|
||||
self.message = "Mode '%s' is invalid, possible values: strict_html, loose_html, xml." % mode
|
||||
|
||||
class CustomizationError( MarkupError ):
|
||||
def __init__( self ):
|
||||
self.message = "If you customize the allowed elements, you must define both types 'onetags' and 'twotags'."
|
||||
|
||||
if __name__ == '__main__':
|
||||
print __doc__
|
||||
@@ -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'
|
||||
@@ -0,0 +1,127 @@
|
||||
# Copyright (c) 2009 Raymond Hettinger
|
||||
#
|
||||
# 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.
|
||||
|
||||
from UserDict import DictMixin
|
||||
|
||||
class OrderedDict(dict, DictMixin):
|
||||
|
||||
def __init__(self, *args, **kwds):
|
||||
if len(args) > 1:
|
||||
raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
||||
try:
|
||||
self.__end
|
||||
except AttributeError:
|
||||
self.clear()
|
||||
self.update(*args, **kwds)
|
||||
|
||||
def clear(self):
|
||||
self.__end = end = []
|
||||
end += [None, end, end] # sentinel node for doubly linked list
|
||||
self.__map = {} # key --> [key, prev, next]
|
||||
dict.clear(self)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if key not in self:
|
||||
end = self.__end
|
||||
curr = end[1]
|
||||
curr[2] = end[1] = self.__map[key] = [key, curr, end]
|
||||
dict.__setitem__(self, key, value)
|
||||
|
||||
def __delitem__(self, key):
|
||||
dict.__delitem__(self, key)
|
||||
key, prev, next = self.__map.pop(key)
|
||||
prev[2] = next
|
||||
next[1] = prev
|
||||
|
||||
def __iter__(self):
|
||||
end = self.__end
|
||||
curr = end[2]
|
||||
while curr is not end:
|
||||
yield curr[0]
|
||||
curr = curr[2]
|
||||
|
||||
def __reversed__(self):
|
||||
end = self.__end
|
||||
curr = end[1]
|
||||
while curr is not end:
|
||||
yield curr[0]
|
||||
curr = curr[1]
|
||||
|
||||
def popitem(self, last=True):
|
||||
if not self:
|
||||
raise KeyError('dictionary is empty')
|
||||
if last:
|
||||
key = reversed(self).next()
|
||||
else:
|
||||
key = iter(self).next()
|
||||
value = self.pop(key)
|
||||
return key, value
|
||||
|
||||
def __reduce__(self):
|
||||
items = [[k, self[k]] for k in self]
|
||||
tmp = self.__map, self.__end
|
||||
del self.__map, self.__end
|
||||
inst_dict = vars(self).copy()
|
||||
self.__map, self.__end = tmp
|
||||
if inst_dict:
|
||||
return (self.__class__, (items,), inst_dict)
|
||||
return self.__class__, (items,)
|
||||
|
||||
def keys(self):
|
||||
return list(self)
|
||||
|
||||
setdefault = DictMixin.setdefault
|
||||
update = DictMixin.update
|
||||
pop = DictMixin.pop
|
||||
values = DictMixin.values
|
||||
items = DictMixin.items
|
||||
iterkeys = DictMixin.iterkeys
|
||||
itervalues = DictMixin.itervalues
|
||||
iteritems = DictMixin.iteritems
|
||||
|
||||
def __repr__(self):
|
||||
if not self:
|
||||
return '%s()' % (self.__class__.__name__,)
|
||||
return '%s(%r)' % (self.__class__.__name__, self.items())
|
||||
|
||||
def copy(self):
|
||||
return self.__class__(self)
|
||||
|
||||
@classmethod
|
||||
def fromkeys(cls, iterable, value=None):
|
||||
d = cls()
|
||||
for key in iterable:
|
||||
d[key] = value
|
||||
return d
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, OrderedDict):
|
||||
if len(self) != len(other):
|
||||
return False
|
||||
for p, q in zip(self.items(), other.items()):
|
||||
if p != q:
|
||||
return False
|
||||
return True
|
||||
return dict.__eq__(self, other)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
+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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user