fastpyxl 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastpyxl-1.0.0/LICENCE.rst +23 -0
- fastpyxl-1.0.0/PKG-INFO +73 -0
- fastpyxl-1.0.0/README.rst +50 -0
- fastpyxl-1.0.0/fastpyxl/__init__.py +19 -0
- fastpyxl-1.0.0/fastpyxl/_constants.py +13 -0
- fastpyxl-1.0.0/fastpyxl/cell/__init__.py +4 -0
- fastpyxl-1.0.0/fastpyxl/cell/_writer.py +136 -0
- fastpyxl-1.0.0/fastpyxl/cell/cell.py +341 -0
- fastpyxl-1.0.0/fastpyxl/cell/read_only.py +134 -0
- fastpyxl-1.0.0/fastpyxl/cell/rich_text.py +204 -0
- fastpyxl-1.0.0/fastpyxl/cell/text.py +319 -0
- fastpyxl-1.0.0/fastpyxl/chart/_3d.py +163 -0
- fastpyxl-1.0.0/fastpyxl/chart/__init__.py +19 -0
- fastpyxl-1.0.0/fastpyxl/chart/_chart.py +222 -0
- fastpyxl-1.0.0/fastpyxl/chart/area_chart.py +94 -0
- fastpyxl-1.0.0/fastpyxl/chart/axis.py +500 -0
- fastpyxl-1.0.0/fastpyxl/chart/bar_chart.py +160 -0
- fastpyxl-1.0.0/fastpyxl/chart/bubble_chart.py +95 -0
- fastpyxl-1.0.0/fastpyxl/chart/chartspace.py +277 -0
- fastpyxl-1.0.0/fastpyxl/chart/data_source.py +258 -0
- fastpyxl-1.0.0/fastpyxl/chart/descriptors.py +49 -0
- fastpyxl-1.0.0/fastpyxl/chart/error_bar.py +104 -0
- fastpyxl-1.0.0/fastpyxl/chart/label.py +140 -0
- fastpyxl-1.0.0/fastpyxl/chart/layout.py +132 -0
- fastpyxl-1.0.0/fastpyxl/chart/legend.py +87 -0
- fastpyxl-1.0.0/fastpyxl/chart/line_chart.py +156 -0
- fastpyxl-1.0.0/fastpyxl/chart/marker.py +138 -0
- fastpyxl-1.0.0/fastpyxl/chart/picture.py +61 -0
- fastpyxl-1.0.0/fastpyxl/chart/pie_chart.py +208 -0
- fastpyxl-1.0.0/fastpyxl/chart/pivot.py +67 -0
- fastpyxl-1.0.0/fastpyxl/chart/plotarea.py +202 -0
- fastpyxl-1.0.0/fastpyxl/chart/print_settings.py +57 -0
- fastpyxl-1.0.0/fastpyxl/chart/radar_chart.py +63 -0
- fastpyxl-1.0.0/fastpyxl/chart/reader.py +32 -0
- fastpyxl-1.0.0/fastpyxl/chart/reference.py +124 -0
- fastpyxl-1.0.0/fastpyxl/chart/scatter_chart.py +63 -0
- fastpyxl-1.0.0/fastpyxl/chart/series.py +269 -0
- fastpyxl-1.0.0/fastpyxl/chart/series_factory.py +40 -0
- fastpyxl-1.0.0/fastpyxl/chart/shapes.py +162 -0
- fastpyxl-1.0.0/fastpyxl/chart/stock_chart.py +53 -0
- fastpyxl-1.0.0/fastpyxl/chart/surface_chart.py +102 -0
- fastpyxl-1.0.0/fastpyxl/chart/text.py +69 -0
- fastpyxl-1.0.0/fastpyxl/chart/title.py +79 -0
- fastpyxl-1.0.0/fastpyxl/chart/trendline.py +132 -0
- fastpyxl-1.0.0/fastpyxl/chart/updown_bars.py +36 -0
- fastpyxl-1.0.0/fastpyxl/chartsheet/__init__.py +3 -0
- fastpyxl-1.0.0/fastpyxl/chartsheet/chartsheet.py +108 -0
- fastpyxl-1.0.0/fastpyxl/chartsheet/custom.py +69 -0
- fastpyxl-1.0.0/fastpyxl/chartsheet/properties.py +23 -0
- fastpyxl-1.0.0/fastpyxl/chartsheet/protection.py +46 -0
- fastpyxl-1.0.0/fastpyxl/chartsheet/publish.py +76 -0
- fastpyxl-1.0.0/fastpyxl/chartsheet/relation.py +94 -0
- fastpyxl-1.0.0/fastpyxl/chartsheet/views.py +46 -0
- fastpyxl-1.0.0/fastpyxl/comments/__init__.py +4 -0
- fastpyxl-1.0.0/fastpyxl/comments/author.py +18 -0
- fastpyxl-1.0.0/fastpyxl/comments/comment_sheet.py +254 -0
- fastpyxl-1.0.0/fastpyxl/comments/comments.py +62 -0
- fastpyxl-1.0.0/fastpyxl/comments/shape_writer.py +112 -0
- fastpyxl-1.0.0/fastpyxl/compat/__init__.py +54 -0
- fastpyxl-1.0.0/fastpyxl/compat/abc.py +12 -0
- fastpyxl-1.0.0/fastpyxl/compat/numbers.py +43 -0
- fastpyxl-1.0.0/fastpyxl/compat/product.py +21 -0
- fastpyxl-1.0.0/fastpyxl/compat/singleton.py +40 -0
- fastpyxl-1.0.0/fastpyxl/compat/strings.py +25 -0
- fastpyxl-1.0.0/fastpyxl/descriptors/__init__.py +75 -0
- fastpyxl-1.0.0/fastpyxl/descriptors/base.py +260 -0
- fastpyxl-1.0.0/fastpyxl/descriptors/container.py +44 -0
- fastpyxl-1.0.0/fastpyxl/descriptors/excel.py +116 -0
- fastpyxl-1.0.0/fastpyxl/descriptors/namespace.py +12 -0
- fastpyxl-1.0.0/fastpyxl/descriptors/nested.py +107 -0
- fastpyxl-1.0.0/fastpyxl/descriptors/sequence.py +131 -0
- fastpyxl-1.0.0/fastpyxl/descriptors/serialisable.py +213 -0
- fastpyxl-1.0.0/fastpyxl/descriptors/slots.py +22 -0
- fastpyxl-1.0.0/fastpyxl/drawing/__init__.py +4 -0
- fastpyxl-1.0.0/fastpyxl/drawing/colors.py +608 -0
- fastpyxl-1.0.0/fastpyxl/drawing/connector.py +147 -0
- fastpyxl-1.0.0/fastpyxl/drawing/drawing.py +99 -0
- fastpyxl-1.0.0/fastpyxl/drawing/effect.py +399 -0
- fastpyxl-1.0.0/fastpyxl/drawing/fill.py +404 -0
- fastpyxl-1.0.0/fastpyxl/drawing/geometry.py +685 -0
- fastpyxl-1.0.0/fastpyxl/drawing/graphic.py +169 -0
- fastpyxl-1.0.0/fastpyxl/drawing/image.py +68 -0
- fastpyxl-1.0.0/fastpyxl/drawing/line.py +237 -0
- fastpyxl-1.0.0/fastpyxl/drawing/picture.py +139 -0
- fastpyxl-1.0.0/fastpyxl/drawing/properties.py +185 -0
- fastpyxl-1.0.0/fastpyxl/drawing/relation.py +17 -0
- fastpyxl-1.0.0/fastpyxl/drawing/spreadsheet_drawing.py +391 -0
- fastpyxl-1.0.0/fastpyxl/drawing/text.py +977 -0
- fastpyxl-1.0.0/fastpyxl/drawing/xdr.py +22 -0
- fastpyxl-1.0.0/fastpyxl/formatting/__init__.py +3 -0
- fastpyxl-1.0.0/fastpyxl/formatting/formatting.py +99 -0
- fastpyxl-1.0.0/fastpyxl/formatting/rule.py +297 -0
- fastpyxl-1.0.0/fastpyxl/formula/__init__.py +3 -0
- fastpyxl-1.0.0/fastpyxl/formula/tokenizer.py +448 -0
- fastpyxl-1.0.0/fastpyxl/formula/translate.py +166 -0
- fastpyxl-1.0.0/fastpyxl/packaging/__init__.py +3 -0
- fastpyxl-1.0.0/fastpyxl/packaging/core.py +162 -0
- fastpyxl-1.0.0/fastpyxl/packaging/custom.py +307 -0
- fastpyxl-1.0.0/fastpyxl/packaging/extended.py +178 -0
- fastpyxl-1.0.0/fastpyxl/packaging/interface.py +62 -0
- fastpyxl-1.0.0/fastpyxl/packaging/manifest.py +222 -0
- fastpyxl-1.0.0/fastpyxl/packaging/relationship.py +158 -0
- fastpyxl-1.0.0/fastpyxl/packaging/workbook.py +222 -0
- fastpyxl-1.0.0/fastpyxl/pivot/__init__.py +1 -0
- fastpyxl-1.0.0/fastpyxl/pivot/cache.py +976 -0
- fastpyxl-1.0.0/fastpyxl/pivot/fields.py +342 -0
- fastpyxl-1.0.0/fastpyxl/pivot/record.py +106 -0
- fastpyxl-1.0.0/fastpyxl/pivot/table.py +1380 -0
- fastpyxl-1.0.0/fastpyxl/reader/__init__.py +1 -0
- fastpyxl-1.0.0/fastpyxl/reader/drawings.py +74 -0
- fastpyxl-1.0.0/fastpyxl/reader/excel.py +355 -0
- fastpyxl-1.0.0/fastpyxl/reader/strings.py +44 -0
- fastpyxl-1.0.0/fastpyxl/reader/workbook.py +133 -0
- fastpyxl-1.0.0/fastpyxl/styles/__init__.py +11 -0
- fastpyxl-1.0.0/fastpyxl/styles/alignment.py +125 -0
- fastpyxl-1.0.0/fastpyxl/styles/borders.py +147 -0
- fastpyxl-1.0.0/fastpyxl/styles/builtins.py +1397 -0
- fastpyxl-1.0.0/fastpyxl/styles/cell_style.py +222 -0
- fastpyxl-1.0.0/fastpyxl/styles/colors.py +228 -0
- fastpyxl-1.0.0/fastpyxl/styles/differential.py +95 -0
- fastpyxl-1.0.0/fastpyxl/styles/fills.py +283 -0
- fastpyxl-1.0.0/fastpyxl/styles/fonts.py +205 -0
- fastpyxl-1.0.0/fastpyxl/styles/named_styles.py +272 -0
- fastpyxl-1.0.0/fastpyxl/styles/numbers.py +200 -0
- fastpyxl-1.0.0/fastpyxl/styles/protection.py +17 -0
- fastpyxl-1.0.0/fastpyxl/styles/proxy.py +62 -0
- fastpyxl-1.0.0/fastpyxl/styles/styleable.py +294 -0
- fastpyxl-1.0.0/fastpyxl/styles/stylesheet.py +276 -0
- fastpyxl-1.0.0/fastpyxl/styles/table.py +129 -0
- fastpyxl-1.0.0/fastpyxl/typed_serialisable/__init__.py +11 -0
- fastpyxl-1.0.0/fastpyxl/typed_serialisable/base.py +420 -0
- fastpyxl-1.0.0/fastpyxl/typed_serialisable/compat.py +9 -0
- fastpyxl-1.0.0/fastpyxl/typed_serialisable/errors.py +14 -0
- fastpyxl-1.0.0/fastpyxl/typed_serialisable/field_info.py +45 -0
- fastpyxl-1.0.0/fastpyxl/typed_serialisable/fields.py +253 -0
- fastpyxl-1.0.0/fastpyxl/typed_serialisable/parse.py +30 -0
- fastpyxl-1.0.0/fastpyxl/typed_serialisable/render.py +25 -0
- fastpyxl-1.0.0/fastpyxl/utils/__init__.py +17 -0
- fastpyxl-1.0.0/fastpyxl/utils/bound_dictionary.py +26 -0
- fastpyxl-1.0.0/fastpyxl/utils/cell.py +251 -0
- fastpyxl-1.0.0/fastpyxl/utils/dataframe.py +84 -0
- fastpyxl-1.0.0/fastpyxl/utils/datetime.py +141 -0
- fastpyxl-1.0.0/fastpyxl/utils/escape.py +43 -0
- fastpyxl-1.0.0/fastpyxl/utils/exceptions.py +34 -0
- fastpyxl-1.0.0/fastpyxl/utils/formulas.py +24 -0
- fastpyxl-1.0.0/fastpyxl/utils/indexed_list.py +54 -0
- fastpyxl-1.0.0/fastpyxl/utils/inference.py +59 -0
- fastpyxl-1.0.0/fastpyxl/utils/protection.py +22 -0
- fastpyxl-1.0.0/fastpyxl/utils/units.py +108 -0
- fastpyxl-1.0.0/fastpyxl/workbook/__init__.py +4 -0
- fastpyxl-1.0.0/fastpyxl/workbook/_writer.py +196 -0
- fastpyxl-1.0.0/fastpyxl/workbook/child.py +186 -0
- fastpyxl-1.0.0/fastpyxl/workbook/defined_name.py +200 -0
- fastpyxl-1.0.0/fastpyxl/workbook/external_link/__init__.py +3 -0
- fastpyxl-1.0.0/fastpyxl/workbook/external_link/external.py +193 -0
- fastpyxl-1.0.0/fastpyxl/workbook/external_reference.py +14 -0
- fastpyxl-1.0.0/fastpyxl/workbook/function_group.py +31 -0
- fastpyxl-1.0.0/fastpyxl/workbook/properties.py +167 -0
- fastpyxl-1.0.0/fastpyxl/workbook/protection.py +160 -0
- fastpyxl-1.0.0/fastpyxl/workbook/smart_tags.py +62 -0
- fastpyxl-1.0.0/fastpyxl/workbook/views.py +167 -0
- fastpyxl-1.0.0/fastpyxl/workbook/web.py +113 -0
- fastpyxl-1.0.0/fastpyxl/workbook/workbook.py +498 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/__init__.py +1 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/_read_only.py +196 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/_reader.py +488 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/_write_only.py +165 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/_writer.py +390 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/cell_range.py +544 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/cell_watch.py +31 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/controls.py +100 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/copier.py +84 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/custom.py +31 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/datavalidation.py +212 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/dimensions.py +310 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/drawing.py +15 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/errors.py +87 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/filters.py +422 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/formula.py +53 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/header_footer.py +270 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/hyperlink.py +43 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/merge.py +148 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/ole.py +157 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/page.py +170 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/pagebreak.py +81 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/picture.py +9 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/print_settings.py +184 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/properties.py +104 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/protection.py +117 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/related.py +16 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/scenario.py +101 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/smart_tag.py +82 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/table.py +364 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/views.py +142 -0
- fastpyxl-1.0.0/fastpyxl/worksheet/worksheet.py +957 -0
- fastpyxl-1.0.0/fastpyxl/writer/__init__.py +1 -0
- fastpyxl-1.0.0/fastpyxl/writer/excel.py +297 -0
- fastpyxl-1.0.0/fastpyxl/writer/theme.py +291 -0
- fastpyxl-1.0.0/fastpyxl/xml/__init__.py +42 -0
- fastpyxl-1.0.0/fastpyxl/xml/constants.py +129 -0
- fastpyxl-1.0.0/fastpyxl/xml/functions.py +111 -0
- fastpyxl-1.0.0/fastpyxl.egg-info/PKG-INFO +73 -0
- fastpyxl-1.0.0/fastpyxl.egg-info/SOURCES.txt +206 -0
- fastpyxl-1.0.0/fastpyxl.egg-info/dependency_links.txt +1 -0
- fastpyxl-1.0.0/fastpyxl.egg-info/requires.txt +1 -0
- fastpyxl-1.0.0/fastpyxl.egg-info/top_level.txt +1 -0
- fastpyxl-1.0.0/pyproject.toml +174 -0
- fastpyxl-1.0.0/setup.cfg +4 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
This software is under the MIT Licence
|
|
2
|
+
======================================
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2010 fastpyxl
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
|
7
|
+
copy of this software and associated documentation files (the
|
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
12
|
+
the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included
|
|
15
|
+
in all copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
18
|
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
20
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
21
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
22
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
23
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
fastpyxl-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastpyxl
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A high-performance Python library to read/write Excel 2010 xlsx/xlsm files
|
|
5
|
+
Author-email: See AUTHORS <charlie.clark@clark-consulting.eu>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Documentation, https://fastpyxl.readthedocs.io/en/stable/
|
|
8
|
+
Project-URL: Source, https://github.com/fastpyxl/fastpyxl
|
|
9
|
+
Project-URL: Tracker, https://github.com/fastpyxl/fastpyxl/issues
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
12
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
13
|
+
Classifier: Operating System :: POSIX
|
|
14
|
+
Classifier: Programming Language :: Python
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Description-Content-Type: text/x-rst
|
|
20
|
+
License-File: LICENCE.rst
|
|
21
|
+
Requires-Dist: et_xmlfile
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
Introduction
|
|
25
|
+
------------
|
|
26
|
+
|
|
27
|
+
fastpyxl is a high-performance Python library to read/write Excel 2010
|
|
28
|
+
xlsx/xlsm/xltx/xltm files. It is a fork of `openpyxl <https://pypi.org/project/openpyxl/>`_,
|
|
29
|
+
focused on optimized performance for large-scale Excel processing.
|
|
30
|
+
|
|
31
|
+
All kudos to the PHPExcel team and the openpyxl developers whose work this
|
|
32
|
+
project builds upon.
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
Security
|
|
36
|
+
--------
|
|
37
|
+
|
|
38
|
+
By default fastpyxl does not guard against quadratic blowup or billion laughs
|
|
39
|
+
xml attacks. To guard against these attacks install defusedxml.
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
Sample code::
|
|
43
|
+
|
|
44
|
+
from fastpyxl import Workbook
|
|
45
|
+
wb = Workbook()
|
|
46
|
+
|
|
47
|
+
# grab the active worksheet
|
|
48
|
+
ws = wb.active
|
|
49
|
+
|
|
50
|
+
# Data can be assigned directly to cells
|
|
51
|
+
ws['A1'] = 42
|
|
52
|
+
|
|
53
|
+
# Rows can also be appended
|
|
54
|
+
ws.append([1, 2, 3])
|
|
55
|
+
|
|
56
|
+
# Python types will automatically be converted
|
|
57
|
+
import datetime
|
|
58
|
+
ws['A2'] = datetime.datetime.now()
|
|
59
|
+
|
|
60
|
+
# Save the file
|
|
61
|
+
wb.save("sample.xlsx")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
Documentation
|
|
65
|
+
-------------
|
|
66
|
+
|
|
67
|
+
The documentation is at: https://fastpyxl.readthedocs.io
|
|
68
|
+
|
|
69
|
+
* installation methods
|
|
70
|
+
* code examples
|
|
71
|
+
* instructions for contributing
|
|
72
|
+
|
|
73
|
+
Release notes: https://fastpyxl.readthedocs.io/en/stable/changes.html
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
Introduction
|
|
2
|
+
------------
|
|
3
|
+
|
|
4
|
+
fastpyxl is a high-performance Python library to read/write Excel 2010
|
|
5
|
+
xlsx/xlsm/xltx/xltm files. It is a fork of `openpyxl <https://pypi.org/project/openpyxl/>`_,
|
|
6
|
+
focused on optimized performance for large-scale Excel processing.
|
|
7
|
+
|
|
8
|
+
All kudos to the PHPExcel team and the openpyxl developers whose work this
|
|
9
|
+
project builds upon.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
Security
|
|
13
|
+
--------
|
|
14
|
+
|
|
15
|
+
By default fastpyxl does not guard against quadratic blowup or billion laughs
|
|
16
|
+
xml attacks. To guard against these attacks install defusedxml.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
Sample code::
|
|
20
|
+
|
|
21
|
+
from fastpyxl import Workbook
|
|
22
|
+
wb = Workbook()
|
|
23
|
+
|
|
24
|
+
# grab the active worksheet
|
|
25
|
+
ws = wb.active
|
|
26
|
+
|
|
27
|
+
# Data can be assigned directly to cells
|
|
28
|
+
ws['A1'] = 42
|
|
29
|
+
|
|
30
|
+
# Rows can also be appended
|
|
31
|
+
ws.append([1, 2, 3])
|
|
32
|
+
|
|
33
|
+
# Python types will automatically be converted
|
|
34
|
+
import datetime
|
|
35
|
+
ws['A2'] = datetime.datetime.now()
|
|
36
|
+
|
|
37
|
+
# Save the file
|
|
38
|
+
wb.save("sample.xlsx")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
Documentation
|
|
42
|
+
-------------
|
|
43
|
+
|
|
44
|
+
The documentation is at: https://fastpyxl.readthedocs.io
|
|
45
|
+
|
|
46
|
+
* installation methods
|
|
47
|
+
* code examples
|
|
48
|
+
* instructions for contributing
|
|
49
|
+
|
|
50
|
+
Release notes: https://fastpyxl.readthedocs.io/en/stable/changes.html
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Copyright (c) 2010-2024 fastpyxl
|
|
2
|
+
|
|
3
|
+
DEBUG = False
|
|
4
|
+
|
|
5
|
+
from fastpyxl.compat.numbers import NUMPY
|
|
6
|
+
from fastpyxl.xml import DEFUSEDXML, LXML
|
|
7
|
+
from fastpyxl.workbook import Workbook
|
|
8
|
+
from fastpyxl.reader.excel import load_workbook as open
|
|
9
|
+
from fastpyxl.reader.excel import load_workbook
|
|
10
|
+
import fastpyxl._constants as constants
|
|
11
|
+
|
|
12
|
+
# Expose constants especially the version number
|
|
13
|
+
|
|
14
|
+
__author__ = constants.__author__
|
|
15
|
+
__author_email__ = constants.__author_email__
|
|
16
|
+
__license__ = constants.__license__
|
|
17
|
+
__maintainer_email__ = constants.__maintainer_email__
|
|
18
|
+
__url__ = constants.__url__
|
|
19
|
+
__version__ = constants.__version__
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Copyright (c) 2010-2024 fastpyxl
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Package metadata
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__author__ = "See AUTHORS"
|
|
8
|
+
__author_email__ = "charlie.clark@clark-consulting.eu"
|
|
9
|
+
__license__ = "MIT"
|
|
10
|
+
__maintainer_email__ = "fastpyxl-users@googlegroups.com"
|
|
11
|
+
__url__ = "https://fastpyxl.readthedocs.io"
|
|
12
|
+
__version__ = "1.0.0"
|
|
13
|
+
__python__ = "3.8"
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Copyright (c) 2010-2024 fastpyxl
|
|
2
|
+
|
|
3
|
+
from fastpyxl.compat import safe_string
|
|
4
|
+
from fastpyxl.xml.functions import Element, SubElement, whitespace, XML_NS
|
|
5
|
+
from fastpyxl import LXML
|
|
6
|
+
from fastpyxl.utils.datetime import to_excel, to_ISO8601
|
|
7
|
+
from datetime import timedelta
|
|
8
|
+
|
|
9
|
+
from fastpyxl.worksheet.formula import DataTableFormula, ArrayFormula
|
|
10
|
+
from fastpyxl.cell.rich_text import CellRichText
|
|
11
|
+
|
|
12
|
+
def _set_attributes(cell, styled=None):
|
|
13
|
+
"""
|
|
14
|
+
Set coordinate and datatype
|
|
15
|
+
"""
|
|
16
|
+
coordinate = cell.coordinate
|
|
17
|
+
attrs = {'r': coordinate}
|
|
18
|
+
if styled:
|
|
19
|
+
attrs['s'] = f"{cell.style_id}"
|
|
20
|
+
|
|
21
|
+
if cell.data_type == "s":
|
|
22
|
+
attrs['t'] = "inlineStr"
|
|
23
|
+
elif cell.data_type != 'f':
|
|
24
|
+
attrs['t'] = cell.data_type
|
|
25
|
+
|
|
26
|
+
value = cell._value
|
|
27
|
+
|
|
28
|
+
if cell.data_type == "d":
|
|
29
|
+
if hasattr(value, "tzinfo") and value.tzinfo is not None:
|
|
30
|
+
raise TypeError("Excel does not support timezones in datetimes. "
|
|
31
|
+
"The tzinfo in the datetime/time object must be set to None.")
|
|
32
|
+
|
|
33
|
+
if cell.parent.parent.iso_dates and not isinstance(value, timedelta):
|
|
34
|
+
value = to_ISO8601(value)
|
|
35
|
+
else:
|
|
36
|
+
attrs['t'] = "n"
|
|
37
|
+
value = to_excel(value, cell.parent.parent.epoch)
|
|
38
|
+
|
|
39
|
+
if cell.hyperlink:
|
|
40
|
+
cell.parent._hyperlinks.append(cell.hyperlink)
|
|
41
|
+
|
|
42
|
+
return value, attrs
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def etree_write_cell(xf, worksheet, cell, styled=None):
|
|
46
|
+
|
|
47
|
+
value, attributes = _set_attributes(cell, styled)
|
|
48
|
+
|
|
49
|
+
el = Element("c", attributes)
|
|
50
|
+
if value is None or value == "":
|
|
51
|
+
xf.write(el)
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
if cell.data_type == 'f':
|
|
55
|
+
attrib = {}
|
|
56
|
+
|
|
57
|
+
if isinstance(value, ArrayFormula):
|
|
58
|
+
attrib = dict(value)
|
|
59
|
+
value = value.text
|
|
60
|
+
|
|
61
|
+
elif isinstance(value, DataTableFormula):
|
|
62
|
+
attrib = dict(value)
|
|
63
|
+
value = None
|
|
64
|
+
|
|
65
|
+
formula = SubElement(el, 'f', attrib)
|
|
66
|
+
if value is not None and not attrib.get('t') == "dataTable":
|
|
67
|
+
formula.text = value[1:]
|
|
68
|
+
value = None
|
|
69
|
+
|
|
70
|
+
if cell.data_type == 's':
|
|
71
|
+
if isinstance(value, CellRichText):
|
|
72
|
+
el.append(value.to_tree())
|
|
73
|
+
else:
|
|
74
|
+
inline_string = Element("is")
|
|
75
|
+
text = Element('t')
|
|
76
|
+
text.text = value
|
|
77
|
+
whitespace(text)
|
|
78
|
+
inline_string.append(text)
|
|
79
|
+
el.append(inline_string)
|
|
80
|
+
|
|
81
|
+
else:
|
|
82
|
+
cell_content = SubElement(el, 'v')
|
|
83
|
+
if value is not None:
|
|
84
|
+
cell_content.text = safe_string(value)
|
|
85
|
+
|
|
86
|
+
xf.write(el)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def lxml_write_cell(xf, worksheet, cell, styled=False):
|
|
90
|
+
value, attributes = _set_attributes(cell, styled)
|
|
91
|
+
|
|
92
|
+
if value == '' or value is None:
|
|
93
|
+
with xf.element("c", attributes):
|
|
94
|
+
return
|
|
95
|
+
|
|
96
|
+
with xf.element('c', attributes):
|
|
97
|
+
if cell.data_type == 'f':
|
|
98
|
+
attrib = {}
|
|
99
|
+
|
|
100
|
+
if isinstance(value, ArrayFormula):
|
|
101
|
+
attrib = dict(value)
|
|
102
|
+
value = value.text
|
|
103
|
+
|
|
104
|
+
elif isinstance(value, DataTableFormula):
|
|
105
|
+
attrib = dict(value)
|
|
106
|
+
value = None
|
|
107
|
+
|
|
108
|
+
with xf.element('f', attrib):
|
|
109
|
+
if value is not None and not attrib.get('t') == "dataTable":
|
|
110
|
+
xf.write(value[1:])
|
|
111
|
+
value = None
|
|
112
|
+
|
|
113
|
+
if cell.data_type == 's':
|
|
114
|
+
if isinstance(value, CellRichText):
|
|
115
|
+
el = value.to_tree()
|
|
116
|
+
xf.write(el)
|
|
117
|
+
else:
|
|
118
|
+
with xf.element("is"):
|
|
119
|
+
if isinstance(value, str):
|
|
120
|
+
attrs = {}
|
|
121
|
+
if value != value.strip():
|
|
122
|
+
attrs["{%s}space" % XML_NS] = "preserve"
|
|
123
|
+
el = Element("t", attrs) # lxml can't handle xml-ns
|
|
124
|
+
el.text = value
|
|
125
|
+
xf.write(el)
|
|
126
|
+
|
|
127
|
+
else:
|
|
128
|
+
with xf.element("v"):
|
|
129
|
+
if value is not None:
|
|
130
|
+
xf.write(safe_string(value))
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
if LXML:
|
|
134
|
+
write_cell = lxml_write_cell
|
|
135
|
+
else:
|
|
136
|
+
write_cell = etree_write_cell
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
# Copyright (c) 2010-2024 fastpyxl
|
|
2
|
+
|
|
3
|
+
"""Manage individual cells in a spreadsheet.
|
|
4
|
+
|
|
5
|
+
The Cell class is required to know its value and type, display options,
|
|
6
|
+
and any other features of an Excel cell. Utilities for referencing
|
|
7
|
+
cells using Excel's 'A1' column/row nomenclature are also provided.
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
__docformat__ = "restructuredtext en"
|
|
12
|
+
|
|
13
|
+
# Python stdlib imports
|
|
14
|
+
from copy import copy
|
|
15
|
+
import datetime
|
|
16
|
+
import re
|
|
17
|
+
from typing import cast
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
from fastpyxl.compat import (
|
|
21
|
+
NUMERIC_TYPES,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
from fastpyxl.utils.exceptions import IllegalCharacterError
|
|
25
|
+
|
|
26
|
+
from fastpyxl.utils import get_column_letter
|
|
27
|
+
from fastpyxl.styles import numbers, is_date_format, is_timedelta_format
|
|
28
|
+
from fastpyxl.styles.styleable import StyleableObject
|
|
29
|
+
from fastpyxl.worksheet.hyperlink import Hyperlink
|
|
30
|
+
from fastpyxl.worksheet.formula import DataTableFormula, ArrayFormula
|
|
31
|
+
from fastpyxl.cell.rich_text import CellRichText
|
|
32
|
+
|
|
33
|
+
# constants
|
|
34
|
+
|
|
35
|
+
TIME_TYPES = (datetime.datetime, datetime.date, datetime.time, datetime.timedelta)
|
|
36
|
+
TIME_FORMATS = {
|
|
37
|
+
datetime.datetime:numbers.FORMAT_DATE_DATETIME,
|
|
38
|
+
datetime.date:numbers.FORMAT_DATE_YYYYMMDD2,
|
|
39
|
+
datetime.time:numbers.FORMAT_DATE_TIME6,
|
|
40
|
+
datetime.timedelta:numbers.FORMAT_DATE_TIMEDELTA,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
STRING_TYPES = (str, bytes, CellRichText)
|
|
44
|
+
KNOWN_TYPES = NUMERIC_TYPES + TIME_TYPES + STRING_TYPES + (bool, type(None))
|
|
45
|
+
|
|
46
|
+
ILLEGAL_CHARACTERS_RE = re.compile(r'[\000-\010]|[\013-\014]|[\016-\037]')
|
|
47
|
+
ERROR_CODES = ('#NULL!', '#DIV/0!', '#VALUE!', '#REF!', '#NAME?', '#NUM!',
|
|
48
|
+
'#N/A')
|
|
49
|
+
|
|
50
|
+
TYPE_STRING = 's'
|
|
51
|
+
TYPE_FORMULA = 'f'
|
|
52
|
+
TYPE_NUMERIC = 'n'
|
|
53
|
+
TYPE_BOOL = 'b'
|
|
54
|
+
TYPE_NULL = 'n'
|
|
55
|
+
TYPE_INLINE = 'inlineStr'
|
|
56
|
+
TYPE_ERROR = 'e'
|
|
57
|
+
TYPE_FORMULA_CACHE_STRING = 'str'
|
|
58
|
+
|
|
59
|
+
VALID_TYPES = (TYPE_STRING, TYPE_FORMULA, TYPE_NUMERIC, TYPE_BOOL,
|
|
60
|
+
TYPE_NULL, TYPE_INLINE, TYPE_ERROR, TYPE_FORMULA_CACHE_STRING)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
_TYPES = {int:'n', float:'n', str:'s', bool:'b'}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def get_type(t, value):
|
|
67
|
+
if isinstance(value, NUMERIC_TYPES):
|
|
68
|
+
dt = 'n'
|
|
69
|
+
elif isinstance(value, STRING_TYPES):
|
|
70
|
+
dt = 's'
|
|
71
|
+
elif isinstance(value, TIME_TYPES):
|
|
72
|
+
dt = 'd'
|
|
73
|
+
elif isinstance(value, (DataTableFormula, ArrayFormula)):
|
|
74
|
+
dt = 'f'
|
|
75
|
+
else:
|
|
76
|
+
return
|
|
77
|
+
_TYPES[t] = dt
|
|
78
|
+
return dt
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def get_time_format(t):
|
|
82
|
+
value = TIME_FORMATS.get(t)
|
|
83
|
+
if value:
|
|
84
|
+
return value
|
|
85
|
+
for base in t.mro()[1:]:
|
|
86
|
+
value = TIME_FORMATS.get(base)
|
|
87
|
+
if value:
|
|
88
|
+
TIME_FORMATS[t] = value
|
|
89
|
+
return value
|
|
90
|
+
raise ValueError("Could not get time format for {0!r}".format(value))
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class Cell(StyleableObject):
|
|
94
|
+
"""Describes cell associated properties.
|
|
95
|
+
|
|
96
|
+
Properties of interest include style, type, value, and address.
|
|
97
|
+
|
|
98
|
+
"""
|
|
99
|
+
__slots__ = (
|
|
100
|
+
'row',
|
|
101
|
+
'column',
|
|
102
|
+
'_value',
|
|
103
|
+
'data_type',
|
|
104
|
+
'parent',
|
|
105
|
+
'_hyperlink',
|
|
106
|
+
'_comment',
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
def __init__(self, worksheet, row=None, column=None, value=None, style_array=None):
|
|
110
|
+
super().__init__(worksheet, style_array)
|
|
111
|
+
self.row = row
|
|
112
|
+
"""Row number of this cell (1-based)"""
|
|
113
|
+
self.column = column
|
|
114
|
+
"""Column number of this cell (1-based)"""
|
|
115
|
+
# _value is the stored value, while value is the displayed value
|
|
116
|
+
self._value = None
|
|
117
|
+
self._hyperlink = None
|
|
118
|
+
self.data_type = 'n'
|
|
119
|
+
if value is not None:
|
|
120
|
+
self.value = value
|
|
121
|
+
self._comment = None
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def coordinate(self):
|
|
126
|
+
"""This cell's coordinate (ex. 'A5')"""
|
|
127
|
+
col = get_column_letter(self.column)
|
|
128
|
+
return f"{col}{self.row}"
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def col_idx(self):
|
|
133
|
+
"""The numerical index of the column"""
|
|
134
|
+
return self.column
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
def column_letter(self):
|
|
139
|
+
return get_column_letter(self.column)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
def encoding(self):
|
|
144
|
+
return self.parent.encoding
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def base_date(self):
|
|
148
|
+
return self.parent.parent.epoch
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def __repr__(self):
|
|
152
|
+
return "<Cell {0!r}.{1}>".format(self.parent.title, self.coordinate)
|
|
153
|
+
|
|
154
|
+
def check_string(self, value):
|
|
155
|
+
"""Check string coding, length, and line break character"""
|
|
156
|
+
if value is None:
|
|
157
|
+
return
|
|
158
|
+
# convert to str string
|
|
159
|
+
if not isinstance(value, str):
|
|
160
|
+
value = str(value, self.encoding)
|
|
161
|
+
value = str(value)
|
|
162
|
+
# string must never be longer than 32,767 characters
|
|
163
|
+
# truncate if necessary
|
|
164
|
+
value = value[:32767]
|
|
165
|
+
if next(ILLEGAL_CHARACTERS_RE.finditer(value), None):
|
|
166
|
+
raise IllegalCharacterError(f"{value} cannot be used in worksheets.")
|
|
167
|
+
return value
|
|
168
|
+
|
|
169
|
+
def check_error(self, value):
|
|
170
|
+
"""Tries to convert Error" else N/A"""
|
|
171
|
+
try:
|
|
172
|
+
return str(value)
|
|
173
|
+
except UnicodeDecodeError:
|
|
174
|
+
return u'#N/A'
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def _bind_value(self, value):
|
|
178
|
+
"""Given a value, infer the correct data type"""
|
|
179
|
+
|
|
180
|
+
self.data_type = "n"
|
|
181
|
+
if isinstance(value, datetime.timedelta):
|
|
182
|
+
self._value = value.total_seconds() / 86400.0
|
|
183
|
+
self.data_type = "n"
|
|
184
|
+
self.number_format = numbers.FORMAT_DATE_TIMEDELTA
|
|
185
|
+
return
|
|
186
|
+
|
|
187
|
+
t = type(value)
|
|
188
|
+
try:
|
|
189
|
+
dt = _TYPES[t]
|
|
190
|
+
except KeyError:
|
|
191
|
+
dt = get_type(t, value)
|
|
192
|
+
|
|
193
|
+
if dt is None and value is not None:
|
|
194
|
+
raise ValueError("Cannot convert {0!r} to Excel".format(value))
|
|
195
|
+
|
|
196
|
+
if dt:
|
|
197
|
+
self.data_type = dt
|
|
198
|
+
|
|
199
|
+
if dt == 'd':
|
|
200
|
+
if not is_date_format(self.number_format):
|
|
201
|
+
self.number_format = get_time_format(t)
|
|
202
|
+
|
|
203
|
+
elif dt == "s" and not isinstance(value, CellRichText):
|
|
204
|
+
value = self.check_string(value)
|
|
205
|
+
if len(value) > 1 and value.startswith("="):
|
|
206
|
+
self.data_type = 'f'
|
|
207
|
+
elif value in ERROR_CODES:
|
|
208
|
+
self.data_type = 'e'
|
|
209
|
+
|
|
210
|
+
self._value = value
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@property
|
|
214
|
+
def value(self):
|
|
215
|
+
"""Get or set the value held in the cell.
|
|
216
|
+
|
|
217
|
+
:type: depends on the value (string, float, int or
|
|
218
|
+
:class:`datetime.datetime`)
|
|
219
|
+
"""
|
|
220
|
+
return self._value
|
|
221
|
+
|
|
222
|
+
@value.setter
|
|
223
|
+
def value(self, value):
|
|
224
|
+
"""Set the value and infer type and display options."""
|
|
225
|
+
self._bind_value(value)
|
|
226
|
+
|
|
227
|
+
@property
|
|
228
|
+
def internal_value(self):
|
|
229
|
+
"""Always returns the value for excel."""
|
|
230
|
+
return self._value
|
|
231
|
+
|
|
232
|
+
@property
|
|
233
|
+
def hyperlink(self):
|
|
234
|
+
"""Return the hyperlink target or an empty string"""
|
|
235
|
+
return self._hyperlink
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
@hyperlink.setter
|
|
239
|
+
def hyperlink(self, val):
|
|
240
|
+
"""Set value and display for hyperlinks in a cell.
|
|
241
|
+
Automatically sets the `value` of the cell with link text,
|
|
242
|
+
but you can modify it afterwards by setting the `value`
|
|
243
|
+
property, and the hyperlink will remain.
|
|
244
|
+
Hyperlink is removed if set to ``None``."""
|
|
245
|
+
if val is None:
|
|
246
|
+
self._hyperlink = None
|
|
247
|
+
else:
|
|
248
|
+
if not isinstance(val, Hyperlink):
|
|
249
|
+
val = Hyperlink(ref="", target=val)
|
|
250
|
+
val.ref = self.coordinate
|
|
251
|
+
self._hyperlink = val
|
|
252
|
+
if self._value is None:
|
|
253
|
+
self.value = val.target or val.location
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
@property
|
|
257
|
+
def is_date(self):
|
|
258
|
+
"""True if the value is formatted as a date
|
|
259
|
+
|
|
260
|
+
:type: bool
|
|
261
|
+
"""
|
|
262
|
+
return self.data_type == 'd' or (
|
|
263
|
+
self.data_type == 'n'
|
|
264
|
+
and is_date_format(self.number_format)
|
|
265
|
+
and not is_timedelta_format(self.number_format)
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def offset(self, row=0, column=0):
|
|
270
|
+
"""Returns a cell location relative to this cell.
|
|
271
|
+
|
|
272
|
+
:param row: number of rows to offset
|
|
273
|
+
:type row: int
|
|
274
|
+
|
|
275
|
+
:param column: number of columns to offset
|
|
276
|
+
:type column: int
|
|
277
|
+
|
|
278
|
+
:rtype: :class:`fastpyxl.cell.Cell`
|
|
279
|
+
"""
|
|
280
|
+
offset_column = cast(int, self.column) + column
|
|
281
|
+
offset_row = cast(int, self.row) + row
|
|
282
|
+
return self.parent.cell(column=offset_column, row=offset_row)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
@property
|
|
286
|
+
def comment(self):
|
|
287
|
+
""" Returns the comment associated with this cell
|
|
288
|
+
|
|
289
|
+
:type: :class:`fastpyxl.comments.Comment`
|
|
290
|
+
"""
|
|
291
|
+
return self._comment
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
@comment.setter
|
|
295
|
+
def comment(self, value):
|
|
296
|
+
"""
|
|
297
|
+
Assign a comment to a cell
|
|
298
|
+
"""
|
|
299
|
+
|
|
300
|
+
if value is not None:
|
|
301
|
+
if value.parent:
|
|
302
|
+
value = copy(value)
|
|
303
|
+
value.bind(self)
|
|
304
|
+
elif value is None and self._comment:
|
|
305
|
+
self._comment.unbind()
|
|
306
|
+
self._comment = value
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
class MergedCell(StyleableObject):
|
|
310
|
+
|
|
311
|
+
"""
|
|
312
|
+
Describes the properties of a cell in a merged cell and helps to
|
|
313
|
+
display the borders of the merged cell.
|
|
314
|
+
|
|
315
|
+
The value of a MergedCell is always None.
|
|
316
|
+
"""
|
|
317
|
+
|
|
318
|
+
__slots__ = ('row', 'column')
|
|
319
|
+
|
|
320
|
+
_value = None
|
|
321
|
+
data_type = "n"
|
|
322
|
+
comment = None
|
|
323
|
+
hyperlink = None
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def __init__(self, worksheet, row=None, column=None):
|
|
327
|
+
super().__init__(worksheet)
|
|
328
|
+
self.row = row
|
|
329
|
+
self.column = column
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def __repr__(self):
|
|
333
|
+
return "<MergedCell {0!r}.{1}>".format(self.parent.title, self.coordinate)
|
|
334
|
+
|
|
335
|
+
coordinate = Cell.coordinate
|
|
336
|
+
_comment = comment
|
|
337
|
+
value = _value
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
def WriteOnlyCell(ws=None, value=None):
|
|
341
|
+
return Cell(worksheet=ws, column=1, row=1, value=value)
|