Version 0.1

Added sidebar, Dashboard, Line Graph
This commit is contained in:
Ayxan 2022-05-23 04:12:37 +04:00
parent d660f2a4ca
commit 9e90b4a150
204 changed files with 29218 additions and 109 deletions

View File

@ -0,0 +1,4 @@
The authors in alphabetical order
* Charlie Clark
* Elias Rabel

View File

@ -0,0 +1 @@
pip

View File

@ -0,0 +1,34 @@
This software is under the MIT Licence
======================================
Copyright (c) 2010 openpyxl
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.
Odict implementation in openpyxl/writer/odict.py uses the following licence:
Copyright (c) 2001-2011 Python Software Foundation
2011 Raymond Hettinger
License: PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
See http://www.opensource.org/licenses/Python-2.0 for full terms
Note: backport changes by Raymond were originally distributed under MIT
license, but since the original license for Python is more
restrictive than MIT, code cannot be released under its terms and
still adheres to the limitations of Python license.

View File

@ -0,0 +1,37 @@
Metadata-Version: 2.1
Name: et-xmlfile
Version: 1.1.0
Summary: An implementation of lxml.xmlfile for the standard library
Home-page: https://foss.heptapod.net/openpyxl/et_xmlfile
Author: See ATUHORS.txt
Author-email: charlie.clark@clark-consulting.eu
License: MIT
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Requires-Python: >=3.6
et_xmfile
=========
et_xmlfile is a low memory library for creating large XML files.
It is based upon the `xmlfile module from lxml <http://lxml.de/api.html#incremental-xml-generation>`_ with the aim of allowing code to be developed that will work with both libraries. It was developed initially for the openpyxl project but is now a standalone module.
The code was written by Elias Rabel as part of the `Python Düsseldorf <http://pyddf.de>`_ openpyxl sprint in September 2014.
Note on performance
-------------------
The code was not developed with performance in mind but turned out to be faster than the existing SAX-based implementation but is significantly slower than lxml's xmlfile. There is one area where an optimisation for lxml will negatively affect the performance of et_xmfile and that is when using the `.element()` method on an xmlfile context manager. It is, therefore, recommended not to use this, though the method is provided for code compatibility.

View File

@ -0,0 +1,11 @@
et_xmlfile-1.1.0.dist-info/AUTHORS.txt,sha256=Y6mQLe0ywXMVP7WVFrZgEW3CqhIv-plM1CaOtdtBuXs,64
et_xmlfile-1.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
et_xmlfile-1.1.0.dist-info/LICENCE.rst,sha256=r-YrNgzcqB-43m7kt2ENodhsORd3qAx6y20RRVxTxCk,1694
et_xmlfile-1.1.0.dist-info/METADATA,sha256=B5hV5UW4GqmWGgwAW44C2ofZZEmV0MRnTEU98kzcUGw,1775
et_xmlfile-1.1.0.dist-info/RECORD,,
et_xmlfile-1.1.0.dist-info/WHEEL,sha256=OqRkF0eY5GHssMorFjlbTIq072vpHpF60fIQA6lS9xA,92
et_xmlfile-1.1.0.dist-info/top_level.txt,sha256=34-74d5NNARgTsPxCMta5o28XpBNmSN0iCZhtmx2Fk8,11
et_xmlfile/__init__.py,sha256=-oTKwE6upIG2gOmnOc4KLgV-pKbBwy-zhQfizbmCruQ,269
et_xmlfile/__pycache__/__init__.cpython-310.pyc,,
et_xmlfile/__pycache__/xmlfile.cpython-310.pyc,,
et_xmlfile/xmlfile.py,sha256=_h20RRb3ptDZ6xXoxMU_Wrx8rG6UZsg0TS7HEOrotzg,3204

View File

@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.36.2)
Root-Is-Purelib: true
Tag: py3-none-any

View File

@ -0,0 +1 @@
et_xmlfile

View File

@ -0,0 +1,11 @@
from __future__ import absolute_import
from .xmlfile import xmlfile
# constants
__version__ = '1.1.0'
__author__ = 'See ATUHORS.txt'
__license__ = 'MIT'
__author_email__ = 'charlie.clark@clark-consulting.eu'
__url__ = 'https://foss.heptapod.net/openpyxl/et_xmlfile'

View File

@ -0,0 +1,104 @@
from __future__ import absolute_import
# Copyright (c) 2010-2015 openpyxl
"""Implements the lxml.etree.xmlfile API using the standard library xml.etree"""
from contextlib import contextmanager
from xml.etree.ElementTree import Element, tostring
class LxmlSyntaxError(Exception):
pass
class _FakeIncrementalFileWriter(object):
"""Replacement for _IncrementalFileWriter of lxml.
Uses ElementTree to build xml in memory."""
def __init__(self, output_file):
self._element_stack = []
self._top_element = None
self._file = output_file
self._have_root = False
@contextmanager
def element(self, tag, attrib=None, nsmap=None, **_extra):
"""Create a new xml element using a context manager.
The elements are written when the top level context is left.
This is for code compatibility only as it is quite slow.
"""
# __enter__ part
self._have_root = True
if attrib is None:
attrib = {}
self._top_element = Element(tag, attrib=attrib, **_extra)
self._top_element.text = ''
self._top_element.tail = ''
self._element_stack.append(self._top_element)
yield
# __exit__ part
el = self._element_stack.pop()
if self._element_stack:
parent = self._element_stack[-1]
parent.append(self._top_element)
self._top_element = parent
else:
self._write_element(el)
self._top_element = None
def write(self, arg):
"""Write a string or subelement."""
if isinstance(arg, str):
# it is not allowed to write a string outside of an element
if self._top_element is None:
raise LxmlSyntaxError()
if len(self._top_element) == 0:
# element has no children: add string to text
self._top_element.text += arg
else:
# element has children: add string to tail of last child
self._top_element[-1].tail += arg
else:
if self._top_element is not None:
self._top_element.append(arg)
elif not self._have_root:
self._write_element(arg)
else:
raise LxmlSyntaxError()
def _write_element(self, element):
xml = tostring(element)
self._file.write(xml)
def __enter__(self):
pass
def __exit__(self, type, value, traceback):
# without root the xml document is incomplete
if not self._have_root:
raise LxmlSyntaxError()
class xmlfile(object):
"""Context manager that can replace lxml.etree.xmlfile."""
def __init__(self, output_file, buffered=False, encoding=None, close=False):
if isinstance(output_file, str):
self._file = open(output_file, 'wb')
self._close = True
else:
self._file = output_file
self._close = close
def __enter__(self):
return _FakeIncrementalFileWriter(self._file)
def __exit__(self, type, value, traceback):
if self._close == True:
self._file.close()

View File

@ -0,0 +1 @@
pip

View File

@ -0,0 +1,23 @@
This software is under the MIT Licence
======================================
Copyright (c) 2010 openpyxl
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.

View File

@ -0,0 +1,87 @@
Metadata-Version: 2.1
Name: openpyxl
Version: 3.0.10
Summary: A Python library to read/write Excel 2010 xlsx/xlsm files
Home-page: https://openpyxl.readthedocs.io
Author: See AUTHORS
Author-email: charlie.clark@clark-consulting.eu
License: MIT
Project-URL: Documentation, https://openpyxl.readthedocs.io/en/stable/
Project-URL: Source, https://foss.heptapod.net/openpyxl/openpyxl
Project-URL: Tracker, https://foss.heptapod.net/openpyxl/openpyxl/-/issues
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Requires-Python: >=3.6
License-File: LICENCE.rst
Requires-Dist: et-xmlfile
.. image:: https://coveralls.io/repos/bitbucket/openpyxl/openpyxl/badge.svg?branch=default
:target: https://coveralls.io/bitbucket/openpyxl/openpyxl?branch=default
:alt: coverage status
Introduction
------------
openpyxl is a Python library to read/write Excel 2010 xlsx/xlsm/xltx/xltm files.
It was born from lack of existing library to read/write natively from Python
the Office Open XML format.
All kudos to the PHPExcel team as openpyxl was initially based on PHPExcel.
Security
--------
By default openpyxl does not guard against quadratic blowup or billion laughs
xml attacks. To guard against these attacks install defusedxml.
Mailing List
------------
The user list can be found on http://groups.google.com/group/openpyxl-users
Sample code::
from openpyxl import Workbook
wb = Workbook()
# grab the active worksheet
ws = wb.active
# Data can be assigned directly to cells
ws['A1'] = 42
# Rows can also be appended
ws.append([1, 2, 3])
# Python types will automatically be converted
import datetime
ws['A2'] = datetime.datetime.now()
# Save the file
wb.save("sample.xlsx")
Documentation
-------------
The documentation is at: https://openpyxl.readthedocs.io
* installation methods
* code examples
* instructions for contributing
Release notes: https://openpyxl.readthedocs.io/en/stable/changes.html

View File

@ -0,0 +1,377 @@
openpyxl-3.0.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
openpyxl-3.0.10.dist-info/LICENCE.rst,sha256=DIS7QvXTZ-Xr-fwt3jWxYUHfXuD9wYklCFi8bFVg9p4,1131
openpyxl-3.0.10.dist-info/METADATA,sha256=r6YDI7oMq_RBCWv1t7hoLUfCndfSKMvZ3YgSNOKfk4U,2429
openpyxl-3.0.10.dist-info/RECORD,,
openpyxl-3.0.10.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
openpyxl-3.0.10.dist-info/WHEEL,sha256=WzZ8cwjh8l0jtULNjYq1Hpr-WCqCRgPr--TX4P5I1Wo,110
openpyxl-3.0.10.dist-info/top_level.txt,sha256=mKJO5QFAsUEDtJ_c97F-IbmVtHYEDymqD7d5X0ULkVs,9
openpyxl/__init__.py,sha256=VtMPdsxka8GIDNczecdDTUIHQOIVHeDp3DYSbgFOZfA,589
openpyxl/__pycache__/__init__.cpython-310.pyc,,
openpyxl/__pycache__/_constants.cpython-310.pyc,,
openpyxl/_constants.py,sha256=R63KSSz5_YgnXh6ecWuwUGaoKR9deHy1QkMcKheNfIQ,307
openpyxl/cell/__init__.py,sha256=eEjbyTZfWrVERGpzukPo03WgevOvDJqpacyA4Whx5n8,122
openpyxl/cell/__pycache__/__init__.cpython-310.pyc,,
openpyxl/cell/__pycache__/_writer.cpython-310.pyc,,
openpyxl/cell/__pycache__/cell.cpython-310.pyc,,
openpyxl/cell/__pycache__/read_only.cpython-310.pyc,,
openpyxl/cell/__pycache__/text.cpython-310.pyc,,
openpyxl/cell/_writer.py,sha256=SF2utlBS0iyswJpuboFX6Y_wXgsxs5ARgQCox_sFCxg,3186
openpyxl/cell/cell.py,sha256=xQHDiR8yjBpPyN1JbJdLXEe-HxtTbDLMuXr7hzi6j5o,8670
openpyxl/cell/read_only.py,sha256=rNEragjLK2TYU8lHRivO8_4lp-a4mJtZJO0-Pdxl4gk,3113
openpyxl/cell/text.py,sha256=pHtvucnpW8pe2qU8ekDdActJu5UnUmwos0WCR_pxG8M,4367
openpyxl/chart/_3d.py,sha256=mBWQGZ1qgwprx7sTzIVxkHsGoqX4kLtscbgKXPll5f4,3104
openpyxl/chart/__init__.py,sha256=sitthdKhd--R4C3S7hBWghxhgCC-KVnORglOVs5doIQ,564
openpyxl/chart/__pycache__/_3d.cpython-310.pyc,,
openpyxl/chart/__pycache__/__init__.cpython-310.pyc,,
openpyxl/chart/__pycache__/_chart.cpython-310.pyc,,
openpyxl/chart/__pycache__/area_chart.cpython-310.pyc,,
openpyxl/chart/__pycache__/axis.cpython-310.pyc,,
openpyxl/chart/__pycache__/bar_chart.cpython-310.pyc,,
openpyxl/chart/__pycache__/bubble_chart.cpython-310.pyc,,
openpyxl/chart/__pycache__/chartspace.cpython-310.pyc,,
openpyxl/chart/__pycache__/data_source.cpython-310.pyc,,
openpyxl/chart/__pycache__/descriptors.cpython-310.pyc,,
openpyxl/chart/__pycache__/error_bar.cpython-310.pyc,,
openpyxl/chart/__pycache__/label.cpython-310.pyc,,
openpyxl/chart/__pycache__/layout.cpython-310.pyc,,
openpyxl/chart/__pycache__/legend.cpython-310.pyc,,
openpyxl/chart/__pycache__/line_chart.cpython-310.pyc,,
openpyxl/chart/__pycache__/marker.cpython-310.pyc,,
openpyxl/chart/__pycache__/picture.cpython-310.pyc,,
openpyxl/chart/__pycache__/pie_chart.cpython-310.pyc,,
openpyxl/chart/__pycache__/pivot.cpython-310.pyc,,
openpyxl/chart/__pycache__/plotarea.cpython-310.pyc,,
openpyxl/chart/__pycache__/print_settings.cpython-310.pyc,,
openpyxl/chart/__pycache__/radar_chart.cpython-310.pyc,,
openpyxl/chart/__pycache__/reader.cpython-310.pyc,,
openpyxl/chart/__pycache__/reference.cpython-310.pyc,,
openpyxl/chart/__pycache__/scatter_chart.cpython-310.pyc,,
openpyxl/chart/__pycache__/series.cpython-310.pyc,,
openpyxl/chart/__pycache__/series_factory.cpython-310.pyc,,
openpyxl/chart/__pycache__/shapes.cpython-310.pyc,,
openpyxl/chart/__pycache__/stock_chart.cpython-310.pyc,,
openpyxl/chart/__pycache__/surface_chart.cpython-310.pyc,,
openpyxl/chart/__pycache__/text.cpython-310.pyc,,
openpyxl/chart/__pycache__/title.cpython-310.pyc,,
openpyxl/chart/__pycache__/trendline.cpython-310.pyc,,
openpyxl/chart/__pycache__/updown_bars.cpython-310.pyc,,
openpyxl/chart/_chart.py,sha256=5p29QQtdXmwrMWveTVbQmxAqcxNMaLo5_TYHmWpIXhM,5583
openpyxl/chart/area_chart.py,sha256=_yWbDwamxVaXeNLjDFjfmYQj2pNKmWwJ7t8-zmj2RFs,2925
openpyxl/chart/axis.py,sha256=ZhS5lHCRpAFLjO-LSBvPqmo3JFoStJURNpjerOvLry0,12657
openpyxl/chart/bar_chart.py,sha256=gVUIwK7QMHejTqxkrRUMHK4g_euyGo9snvR9UiU3OeM,4175
openpyxl/chart/bubble_chart.py,sha256=oQFIoXmFbck665Xrha8tTJkgaWYzXpnSaIWRaN20_FU,2021
openpyxl/chart/chartspace.py,sha256=21asc8NG4Lzvu72-4fJafe1MV_PCXdEOiHRZkkBkaGI,6084
openpyxl/chart/data_source.py,sha256=ZGFU04_tol5aj99Cy_z90A0TOySo-zsdgLXXLm98ZnU,5809
openpyxl/chart/descriptors.py,sha256=n2z3gt3wajcZlxETyNx6i2q94Xhdt0xkMj8ezGg4fCo,764
openpyxl/chart/error_bar.py,sha256=P6cMiz7SoxrsAZPYr3uNtBgKKFt_42pRsOjwgGGmeYQ,1832
openpyxl/chart/label.py,sha256=hX6jerhmoqUgv60nW8LGkFjrxbmlYsh-9I2UdcZsxEY,4167
openpyxl/chart/layout.py,sha256=nOob9eaim8AbQKEWt9dR5UaJ0i8HLb4TuHYz8yrTMlY,2040
openpyxl/chart/legend.py,sha256=7Rx9q9w1DlXCZKQFQLcwtwIbDdqTjaRepIHmaeSnKp4,2040
openpyxl/chart/line_chart.py,sha256=CiVznoifZD8fBclgJXqXl5GgoC3B-GXF8FyQA48GMQI,3986
openpyxl/chart/marker.py,sha256=nfzOuh2L6xng8d2L1o4GbRdZUC0iNzxVzyor6pasJZQ,2600
openpyxl/chart/picture.py,sha256=-uC50EG_Edye3FzQqSXgjMdc9JQ2IiZ04o9UqD5_cmc,1156
openpyxl/chart/pie_chart.py,sha256=gyX0Wx4qJs4J7UFfyG1aPd1Dmp-lGyssK--TwsZNuZ8,4868
openpyxl/chart/pivot.py,sha256=eqGfjudiANL1se3pbQVJVMs0asFH53vkuSU5_aYrq0w,1741
openpyxl/chart/plotarea.py,sha256=ZaPQ9zrw7ZsvUXxI4z0jtueLaxEvPaclM1JiG6BXMg4,5832
openpyxl/chart/print_settings.py,sha256=9h7hqB_bOOWQcwv-nXxUJx9LF8ldZ7uXgy8kpaSEAps,1454
openpyxl/chart/radar_chart.py,sha256=5BY3nHnrbrMzCg3lhmFseKF7aTkRTQBqQf9jCQMVryQ,1537
openpyxl/chart/reader.py,sha256=Lw_sTWhbK4OyG6TDyCvc1YxwsA-O8MtKWaxTVP5bgcg,719
openpyxl/chart/reference.py,sha256=4VmUSvnq2PK1RhXppAoMnsgbM7xkfV3y6VNQXm1wI88,3098
openpyxl/chart/scatter_chart.py,sha256=6ZGA8us3mn9ML1SNznMbnDoZGa3eEKhlQfJy0eBxEP4,1559
openpyxl/chart/series.py,sha256=lacE1JDETHpw6wt-gQQJpXA8TohBw6j33-Pq5ln24NI,5908
openpyxl/chart/series_factory.py,sha256=KI1cyin3vRjolNKZnJU3fVJL2lAA1EDFVJOIGpb7Ovs,1368
openpyxl/chart/shapes.py,sha256=LuuMGPi8TpFKSiEACdRaqSM1UfrRs4OHl6bO97MFM-U,2815
openpyxl/chart/stock_chart.py,sha256=PaySnFES8SkmEurl8l1ozqNNs9jbcdDKM1yGrUaIFMY,1620
openpyxl/chart/surface_chart.py,sha256=tVr-y9U3yqVtiwAMdI1FVnoPvdowpe7Q0jOLsx6LLN8,2955
openpyxl/chart/text.py,sha256=XWCcUSIkEeNDPL2i6Vd5DIQrXYdj0gMZBA04eYwlms0,1857
openpyxl/chart/title.py,sha256=jCj0KKTV8jfZEJJW9jRZIC4658oSqP5T7R_7X6a4FCo,1973
openpyxl/chart/trendline.py,sha256=dfykzMNDQADooCk3eGDtJsb-HtS5IjLPXUSpJj_F3Es,3053
openpyxl/chart/updown_bars.py,sha256=EEHh1masZYcwuBVCBEVuYaHp1sYGM9NuRXBu8ZeqGvI,897
openpyxl/chartsheet/__init__.py,sha256=LWRt_ng8kVyFPaPlkQcz09a4lmhMKuW1zNg2wViWi_k,71
openpyxl/chartsheet/__pycache__/__init__.cpython-310.pyc,,
openpyxl/chartsheet/__pycache__/chartsheet.cpython-310.pyc,,
openpyxl/chartsheet/__pycache__/custom.cpython-310.pyc,,
openpyxl/chartsheet/__pycache__/properties.cpython-310.pyc,,
openpyxl/chartsheet/__pycache__/protection.cpython-310.pyc,,
openpyxl/chartsheet/__pycache__/publish.cpython-310.pyc,,
openpyxl/chartsheet/__pycache__/relation.cpython-310.pyc,,
openpyxl/chartsheet/__pycache__/views.cpython-310.pyc,,
openpyxl/chartsheet/chartsheet.py,sha256=m10kVu5nVE2-pdEMXrPlmMj5EdJHYPaSZ3BfEToYpo4,4042
openpyxl/chartsheet/custom.py,sha256=adJoF6ZTWT6lNAK-VAqVXDZ4Js_Hpa4mqm1goaMO9oc,1691
openpyxl/chartsheet/properties.py,sha256=Sj6qcgdkmMDUEYwS4ugXAzXMhj5_9w3SoN6b2pxTijU,679
openpyxl/chartsheet/protection.py,sha256=eJixEBmdoTDO2_0h6g51sdSdfSdCaP8UUNsbEqHds6U,1265
openpyxl/chartsheet/publish.py,sha256=0zOyFw5eIp2J9-WaNiuFcbLyHwr5f7rbkI7Ux6CbB1s,1587
openpyxl/chartsheet/relation.py,sha256=UX6_M0VziJSXnrWGtKo_Ztp7ax5XGFHCL08emEmq2zs,2731
openpyxl/chartsheet/views.py,sha256=WDbrdA7FYybD9f-iohh9J09qOcPpWdlkU3aJrROn2K8,1341
openpyxl/comments/__init__.py,sha256=vS5MXYD5sbLGpWXb7q-GwN9SvdvlXoMM6voVZJMrfEI,67
openpyxl/comments/__pycache__/__init__.cpython-310.pyc,,
openpyxl/comments/__pycache__/author.cpython-310.pyc,,
openpyxl/comments/__pycache__/comment_sheet.cpython-310.pyc,,
openpyxl/comments/__pycache__/comments.cpython-310.pyc,,
openpyxl/comments/__pycache__/shape_writer.cpython-310.pyc,,
openpyxl/comments/author.py,sha256=EKZq4Bvg0Uq_Vi3_OUhU-z8TrmQb9cWyTaOUl2CBeUI,388
openpyxl/comments/comment_sheet.py,sha256=vpvJO1QaRJ2QvgFy-a59TWizvRke2eIyQJytWhgPcrA,5874
openpyxl/comments/comments.py,sha256=LiOlDmCknMa_Ab_pUvulaj804CvsjGpBqi0ypXH4fxM,1474
openpyxl/comments/shape_writer.py,sha256=0gYUfez5cAU5rLHTpuPX0hOah-8EwpY5SCzzM3ER_vc,3868
openpyxl/compat/__init__.py,sha256=Nl-SeWQbkNn10RtizWEAgnk4glYoLRmUV4mwXQDi7OQ,1592
openpyxl/compat/__pycache__/__init__.cpython-310.pyc,,
openpyxl/compat/__pycache__/abc.cpython-310.pyc,,
openpyxl/compat/__pycache__/numbers.cpython-310.pyc,,
openpyxl/compat/__pycache__/product.cpython-310.pyc,,
openpyxl/compat/__pycache__/singleton.cpython-310.pyc,,
openpyxl/compat/__pycache__/strings.cpython-310.pyc,,
openpyxl/compat/abc.py,sha256=9en931ecvRZKxR7qmcllR2p33HF4ZlcljII1H2QGNEk,155
openpyxl/compat/numbers.py,sha256=6dSz7rLWsS9Wrs_VC5Qx2e4fbOZexwV5eEXeXv8SWPY,1617
openpyxl/compat/product.py,sha256=PckDpAMWi2xcIuQpz9un6YtBK1aMDb17sDIEZeEHKBg,264
openpyxl/compat/singleton.py,sha256=_odbcfJhL_P25QjrNYfCpUbRveis7uDiTtfUWvnFha4,1083
openpyxl/compat/strings.py,sha256=zJb2-t-ezKuAqv9b68ZOguRUDdwEQepca1Zxg5srKj8,604
openpyxl/descriptors/__init__.py,sha256=p_J_95x3LzJ-WAlkmClVOfibMi3PIwzgFu_9Ce3F-r8,1816
openpyxl/descriptors/__pycache__/__init__.cpython-310.pyc,,
openpyxl/descriptors/__pycache__/base.cpython-310.pyc,,
openpyxl/descriptors/__pycache__/excel.cpython-310.pyc,,
openpyxl/descriptors/__pycache__/namespace.cpython-310.pyc,,
openpyxl/descriptors/__pycache__/nested.cpython-310.pyc,,
openpyxl/descriptors/__pycache__/sequence.cpython-310.pyc,,
openpyxl/descriptors/__pycache__/serialisable.cpython-310.pyc,,
openpyxl/descriptors/__pycache__/slots.cpython-310.pyc,,
openpyxl/descriptors/base.py,sha256=AEnaMxOZ0EA-vjaqVdoN9SSmyAfBz3hiOJ8JcwR3Geo,7110
openpyxl/descriptors/excel.py,sha256=TPYzzf0x5uyCyXC3USjO8AZhzD83J0T08OaUOfqCyhs,2438
openpyxl/descriptors/namespace.py,sha256=ZvQcYT_aLJIsdc5LjlmRPZQ7UZp-1OdWkPrD7hG2Jmc,309
openpyxl/descriptors/nested.py,sha256=lkmVD1zG_VPAbukFpk8jnj5MjPkDaVRzVKKJfBRCWqc,2651
openpyxl/descriptors/sequence.py,sha256=DJjJ8RyFaiuPSfNvEVevMii5uzUoZe2hjOESaS4kHig,3324
openpyxl/descriptors/serialisable.py,sha256=cfRFFSAMbTM0GCPY5Lqy_UrmJABbKf-Klesw8pitTRo,7343
openpyxl/descriptors/slots.py,sha256=xNj5vLWWoounpYqbP2JDnnhlTiTLRn-uTfQxncpFfn0,824
openpyxl/drawing/__init__.py,sha256=4PhbbB73RtQ15UUWzzA12nN7gLRaG7D8rXNPY9OCWXU,66
openpyxl/drawing/__pycache__/__init__.cpython-310.pyc,,
openpyxl/drawing/__pycache__/colors.cpython-310.pyc,,
openpyxl/drawing/__pycache__/connector.cpython-310.pyc,,
openpyxl/drawing/__pycache__/drawing.cpython-310.pyc,,
openpyxl/drawing/__pycache__/effect.cpython-310.pyc,,
openpyxl/drawing/__pycache__/fill.cpython-310.pyc,,
openpyxl/drawing/__pycache__/geometry.cpython-310.pyc,,
openpyxl/drawing/__pycache__/graphic.cpython-310.pyc,,
openpyxl/drawing/__pycache__/image.cpython-310.pyc,,
openpyxl/drawing/__pycache__/line.cpython-310.pyc,,
openpyxl/drawing/__pycache__/picture.cpython-310.pyc,,
openpyxl/drawing/__pycache__/properties.cpython-310.pyc,,
openpyxl/drawing/__pycache__/relation.cpython-310.pyc,,
openpyxl/drawing/__pycache__/spreadsheet_drawing.cpython-310.pyc,,
openpyxl/drawing/__pycache__/text.cpython-310.pyc,,
openpyxl/drawing/__pycache__/xdr.cpython-310.pyc,,
openpyxl/drawing/colors.py,sha256=DmY3f50XNemqt4gqK-HhEhMpY9mXa-H_gDGAJycjwpM,15278
openpyxl/drawing/connector.py,sha256=BLeLHvxh--N5J0cscc45kSu4gwwclrtAhkCAjroyHg0,3863
openpyxl/drawing/drawing.py,sha256=TVgnUo510WG9mgqbBEMZ-T-S4SXga_n2AQIYvHWfYrs,2785
openpyxl/drawing/effect.py,sha256=iws9anMvqN_0zEdo8wCwsKmvjdn5u3_OVNIdh2aJL7A,9529
openpyxl/drawing/fill.py,sha256=_k7ONkSM4pzDlcEcQs9tgIgKmg-SJ48NvSN0ro-1ov0,12701
openpyxl/drawing/geometry.py,sha256=jCJit07H5zNv4HyTI18mZzFO2eJNgP8KQaCJ4btrdoI,17733
openpyxl/drawing/graphic.py,sha256=GNE7VhmHE2FxlBzAAHNJAG9EYOeP04yL4n-LHXuE7nY,5127
openpyxl/drawing/image.py,sha256=PbIRz5136GqdLf9738twuOThoF1LPoIVpIwuj8-F9Ks,1463
openpyxl/drawing/line.py,sha256=pYrMRa7O0OzNu56-CmcWNV5x_bmKcJp4T3vRO9pE4uM,4105
openpyxl/drawing/picture.py,sha256=lqf4WezgKKIRjT6ZU1hsfZNyQF8OP7ngAfIlcSC9zmY,4287
openpyxl/drawing/properties.py,sha256=UH9e7NlPuSs13oM2IC4kMJURg6oWcBbXpxeLJ-gR6Gk,4948
openpyxl/drawing/relation.py,sha256=igkBJ_OKZ16-IcdO-asvIw2hGub-mKzvH3k4K_ShmRQ,344
openpyxl/drawing/spreadsheet_drawing.py,sha256=e2dJHU2Sp6OgKFH-egxrd8CqbRbPjjjuoWeePNHRn9o,10762
openpyxl/drawing/text.py,sha256=vjOY-mIIwQII4GoiKQdQE_zqof8CLFNfyttIT3R90eo,22345
openpyxl/drawing/xdr.py,sha256=xjSzolAxpxb4CWa4rbDTEX3iBw-uBsIOQeFRkzStgEA,626
openpyxl/formatting/__init__.py,sha256=JQyMJU_rnfUyXM_Tk4Hz_dUM1uUqbz0UlIK0i5_rEZQ,59
openpyxl/formatting/__pycache__/__init__.cpython-310.pyc,,
openpyxl/formatting/__pycache__/formatting.cpython-310.pyc,,
openpyxl/formatting/__pycache__/rule.cpython-310.pyc,,
openpyxl/formatting/formatting.py,sha256=ZLflOZbG5sfSGe_oTv_ghOZkz-XGAstUK_0hSCuvLGs,2805
openpyxl/formatting/rule.py,sha256=0CcEqFpu9PSyGn5lbSFg-CeM49l7oHBBvRmJwuoCHMY,9308
openpyxl/formula/__init__.py,sha256=KFbd8A3fcY4abjI58_pHkZ_4ba3OJx8RpzTUuixD3uQ,69
openpyxl/formula/__pycache__/__init__.cpython-310.pyc,,
openpyxl/formula/__pycache__/tokenizer.cpython-310.pyc,,
openpyxl/formula/__pycache__/translate.cpython-310.pyc,,
openpyxl/formula/tokenizer.py,sha256=LYD7rjTds1kbKo_EeL22H4QtPgvzD04uAAh_XX_XQV0,15104
openpyxl/formula/translate.py,sha256=3yduwyIg71VUHquJFbFKYorfpfwSdC4QNXdM3HyqGug,6661
openpyxl/packaging/__init__.py,sha256=KcNtO2zoYizOgG-iZzayZffSL1WeZR98i1Q8QYTRhfI,90
openpyxl/packaging/__pycache__/__init__.cpython-310.pyc,,
openpyxl/packaging/__pycache__/core.cpython-310.pyc,,
openpyxl/packaging/__pycache__/extended.cpython-310.pyc,,
openpyxl/packaging/__pycache__/interface.cpython-310.pyc,,
openpyxl/packaging/__pycache__/manifest.cpython-310.pyc,,
openpyxl/packaging/__pycache__/relationship.cpython-310.pyc,,
openpyxl/packaging/__pycache__/workbook.cpython-310.pyc,,
openpyxl/packaging/core.py,sha256=RZxejREIjo3zmsh2TYYT1D1w2wmIhNCJApZHvSnVhWA,4011
openpyxl/packaging/extended.py,sha256=xvC-SBAqkE5GMV_oInfpxIcUzLpTcSNrCcMvk_nM7CM,4755
openpyxl/packaging/interface.py,sha256=TAzyUJG3uFLY3uf_-bxTadTw7Thlq9TXC6JNbsSMlBg,920
openpyxl/packaging/manifest.py,sha256=DMpq2jbB0LFzCRYUgprPfS7ncorSx0hATpL7AOJcMaY,5643
openpyxl/packaging/relationship.py,sha256=k_7v8v0VTyJiYGkO9Izp8HskfCFrKcllx17tvUb1Jyc,4356
openpyxl/packaging/workbook.py,sha256=kfqU5svwVYz_TDf23UM5c2CBvOUaBd08Khgst2xrlC4,7024
openpyxl/pivot/__init__.py,sha256=vy0Tqjyg0JU0hFQkaKwsNNXId2uWxw94S4fNgk1JwmY,35
openpyxl/pivot/__pycache__/__init__.cpython-310.pyc,,
openpyxl/pivot/__pycache__/cache.cpython-310.pyc,,
openpyxl/pivot/__pycache__/fields.cpython-310.pyc,,
openpyxl/pivot/__pycache__/record.cpython-310.pyc,,
openpyxl/pivot/__pycache__/table.cpython-310.pyc,,
openpyxl/pivot/cache.py,sha256=_1-6g7SOPTOBHq7wJHMBkvKMuVg9YyNbZ5nIapjdOGs,30587
openpyxl/pivot/fields.py,sha256=yd2Iz2EIti0nJkMgSAhft0l7XHuNxnazvavpTStZrZY,6984
openpyxl/pivot/record.py,sha256=y0s27ZvcvetQFsG3BpLFdUniC2cuQc09NzOY4zoagTY,2687
openpyxl/pivot/table.py,sha256=cmMEh5s7zIcBWICWwuUd5E9FNAslX6V8Q2G2H-by5eg,37786
openpyxl/reader/__init__.py,sha256=vy0Tqjyg0JU0hFQkaKwsNNXId2uWxw94S4fNgk1JwmY,35
openpyxl/reader/__pycache__/__init__.cpython-310.pyc,,
openpyxl/reader/__pycache__/drawings.cpython-310.pyc,,
openpyxl/reader/__pycache__/excel.cpython-310.pyc,,
openpyxl/reader/__pycache__/strings.cpython-310.pyc,,
openpyxl/reader/__pycache__/workbook.cpython-310.pyc,,
openpyxl/reader/drawings.py,sha256=x0P-Hdauvp5pOfWg-PxTqNKnoVwE1m-ssolF99rA_fo,2052
openpyxl/reader/excel.py,sha256=w1LMHWMmpbNhC73fc_LNFjfih8T700kKYLB85Y-FkNI,10978
openpyxl/reader/strings.py,sha256=Vr23VuVcmGASy1m2Zv_q9WXafVQmkGUvh8vGTtbN30I,565
openpyxl/reader/workbook.py,sha256=GZZLNq3ttKU-zHOcEApgEscMRIdFY928ndXyhBw5PRw,3921
openpyxl/styles/__init__.py,sha256=6vl70dr1Z0LPjhf5GxPXXGC5625kSLrzwlHILYqs3Lo,363
openpyxl/styles/__pycache__/__init__.cpython-310.pyc,,
openpyxl/styles/__pycache__/alignment.cpython-310.pyc,,
openpyxl/styles/__pycache__/borders.cpython-310.pyc,,
openpyxl/styles/__pycache__/builtins.cpython-310.pyc,,
openpyxl/styles/__pycache__/cell_style.cpython-310.pyc,,
openpyxl/styles/__pycache__/colors.cpython-310.pyc,,
openpyxl/styles/__pycache__/differential.cpython-310.pyc,,
openpyxl/styles/__pycache__/fills.cpython-310.pyc,,
openpyxl/styles/__pycache__/fonts.cpython-310.pyc,,
openpyxl/styles/__pycache__/named_styles.cpython-310.pyc,,
openpyxl/styles/__pycache__/numbers.cpython-310.pyc,,
openpyxl/styles/__pycache__/protection.cpython-310.pyc,,
openpyxl/styles/__pycache__/proxy.cpython-310.pyc,,
openpyxl/styles/__pycache__/styleable.cpython-310.pyc,,
openpyxl/styles/__pycache__/stylesheet.cpython-310.pyc,,
openpyxl/styles/__pycache__/table.cpython-310.pyc,,
openpyxl/styles/alignment.py,sha256=UcDakgcFWDwOlLtcZNC_3HLdBWzRsG7SmkSQA4u9KeY,2512
openpyxl/styles/borders.py,sha256=dqzcD9b-l_HidrhiP0B6JmkXANOBv0Y_wegqKrRQkSo,3594
openpyxl/styles/builtins.py,sha256=tvDp4fl300bR3cwZNEykgEUI8b4n-LcjdvXXwrUtqNU,31182
openpyxl/styles/cell_style.py,sha256=ErOjpxrayeOPNl9NWCyF9h2eH4Qj2cstaUIKOs6Bg24,5304
openpyxl/styles/colors.py,sha256=nHtEQyXtdvIyw1ktoGy3Du0qNdqqkPdvBdNJjOaYzSM,4653
openpyxl/styles/differential.py,sha256=bB7H_6HraiFkK-Y1jNYkjZkTAlyA74OvLPa4f8PFyM4,2267
openpyxl/styles/fills.py,sha256=1xVb5ES4IoHowYnoWMIwvRJTWFvOW3PvHkZlwm73RDY,6443
openpyxl/styles/fonts.py,sha256=ke5GmJ3S-AKiUZFJzXXFBEugRmBYTZhLbdyoyOk96Rw,3525
openpyxl/styles/named_styles.py,sha256=y62QW2bkzKU4SOOkS2wmpV6_QNwjpVow5mtJf9Olz5w,7424
openpyxl/styles/numbers.py,sha256=iJjorVr1VFPH95d4UQpjyrwa8EkLIKqDMyw6oA8SwLY,5120
openpyxl/styles/protection.py,sha256=VCR5HcpppNmTAqoUbIa7rQwdb0dp8517wWRVQXASBa0,394
openpyxl/styles/proxy.py,sha256=1b351V-qVfG89G6KRhJpxByOZCq-MXLNShqKUi3LCco,1456
openpyxl/styles/styleable.py,sha256=tJPWC8g8i0CEH5HHU00ArDetakYw6IrzsM3SOlNYXxI,4565
openpyxl/styles/stylesheet.py,sha256=cvSuL72cnf2GRiIS5Fiky9fvoylx_x5PI6aXFl_7tLo,8535
openpyxl/styles/table.py,sha256=Z9N_EpJ7ooDbIlWS0j9oYmSoL0R6NqhZc9irS58Z0LY,2801
openpyxl/utils/__init__.py,sha256=JihKdC-kPyYYDj57UNbEXXn_hj707nWkWMX0SliR1H4,324
openpyxl/utils/__pycache__/__init__.cpython-310.pyc,,
openpyxl/utils/__pycache__/bound_dictionary.cpython-310.pyc,,
openpyxl/utils/__pycache__/cell.cpython-310.pyc,,
openpyxl/utils/__pycache__/dataframe.cpython-310.pyc,,
openpyxl/utils/__pycache__/datetime.cpython-310.pyc,,
openpyxl/utils/__pycache__/escape.cpython-310.pyc,,
openpyxl/utils/__pycache__/exceptions.cpython-310.pyc,,
openpyxl/utils/__pycache__/formulas.cpython-310.pyc,,
openpyxl/utils/__pycache__/indexed_list.cpython-310.pyc,,
openpyxl/utils/__pycache__/inference.cpython-310.pyc,,
openpyxl/utils/__pycache__/protection.cpython-310.pyc,,
openpyxl/utils/__pycache__/units.cpython-310.pyc,,
openpyxl/utils/bound_dictionary.py,sha256=S8A5avfYgj8C9qY02VqPVPlao65n5qA4LZyww62LxNI,759
openpyxl/utils/cell.py,sha256=0sDS5epgU4k9Hr-Vj2RUha9A6dpodiJ4Wd39KsZNPhI,6535
openpyxl/utils/dataframe.py,sha256=4DnrL0HZYK9rWdwj1tQO00upaU108vfFjIjH26XGjhU,2596
openpyxl/utils/datetime.py,sha256=Bf0YnwbYG_uZaTacGOY5LGRayX9MWPS3wGtz7Fuy9is,4529
openpyxl/utils/escape.py,sha256=Bdfcwl5IzIqMD3r7BHxYLZ9azAwtN43pDRNjLzpWVzI,790
openpyxl/utils/exceptions.py,sha256=-iVaVgQk_Xq65ItCh4aIJCQ6oLHIlTMR7KjcrVv8kZw,889
openpyxl/utils/formulas.py,sha256=06fJ7kMfYD_bUemPc8MTyauJdh3UsYZVmnk2MDBN1Ag,3733
openpyxl/utils/indexed_list.py,sha256=8XDEm8hAbp_XqpuPCeSBMBZPVaMw1q3irC4-A-sVLzc,1257
openpyxl/utils/inference.py,sha256=iBefUcthoRSIO-htrh7fGr_P1_Lx0GU9pWlkIydFs08,1582
openpyxl/utils/protection.py,sha256=sGpCIoMOW-V2f91x7R5uCg1P4lscvSJgS-E_Y_s06FM,830
openpyxl/utils/units.py,sha256=tXAag0lQFkhWtAOARrrNBAJ69WTBNl48QrPR5VuMBrc,2674
openpyxl/workbook/__init__.py,sha256=3YwXULCwZZlhWImVB_07V-IjyrHgziAgiitErnmP6nI,68
openpyxl/workbook/__pycache__/__init__.cpython-310.pyc,,
openpyxl/workbook/__pycache__/_writer.cpython-310.pyc,,
openpyxl/workbook/__pycache__/child.cpython-310.pyc,,
openpyxl/workbook/__pycache__/defined_name.cpython-310.pyc,,
openpyxl/workbook/__pycache__/external_reference.cpython-310.pyc,,
openpyxl/workbook/__pycache__/function_group.cpython-310.pyc,,
openpyxl/workbook/__pycache__/properties.cpython-310.pyc,,
openpyxl/workbook/__pycache__/protection.cpython-310.pyc,,
openpyxl/workbook/__pycache__/smart_tags.cpython-310.pyc,,
openpyxl/workbook/__pycache__/views.cpython-310.pyc,,
openpyxl/workbook/__pycache__/web.cpython-310.pyc,,
openpyxl/workbook/__pycache__/workbook.cpython-310.pyc,,
openpyxl/workbook/_writer.py,sha256=jz0Ljx8Vl73sb0FYwub2pF7k9Zwk95k1Um15Jk4hQAg,6537
openpyxl/workbook/child.py,sha256=hLBNKhlBF19O3ZnYuCwdmDI0nb_1P5udbDqkgkIQt_s,4060
openpyxl/workbook/defined_name.py,sha256=84mftP70VemW4t0q1gMAd8jqpc_DX8rt0jcusLk1Z8I,7444
openpyxl/workbook/external_link/__init__.py,sha256=p42iTw7McXeftIWoyIBsG1_FkZQjUcJ_iL-dYkKyglw,71
openpyxl/workbook/external_link/__pycache__/__init__.cpython-310.pyc,,
openpyxl/workbook/external_link/__pycache__/external.cpython-310.pyc,,
openpyxl/workbook/external_link/external.py,sha256=Hb98DAk1BgyyLdYXqInjz9uYhX6VywKpHC9qotYHJPg,4555
openpyxl/workbook/external_reference.py,sha256=swiOV5kB_rUAWVZwrZA7yFGS5FtaqqjBknJNntJCICM,348
openpyxl/workbook/function_group.py,sha256=6dxHCm08V3A_XbhufMrSMtfN2wxetnK9H5gztR7mDu0,803
openpyxl/workbook/properties.py,sha256=QXjwXTdN0c3lOs1Cjf-B8U9jvlmam6ds1yva6O2t5hk,5261
openpyxl/workbook/protection.py,sha256=N_-4oJ9ST1DY5y1QUSPJj3rD9wrcBJxsJ-X8Gmwojb0,6031
openpyxl/workbook/smart_tags.py,sha256=svv9SAsEpJucdtSLDr8vIm8ykGAfCZfuH64WaqZFfu0,1181
openpyxl/workbook/views.py,sha256=LpjPsFmOA7Xz97bXe7L9DA63gsfQDzgwNBQZOyXlKyc,5214
openpyxl/workbook/web.py,sha256=PhcttYhzh35m8jkwEkw5Q0wHnbJGjD2yvd_H2YldN2s,2642
openpyxl/workbook/workbook.py,sha256=u0CU87LakDscmiazQQPfFpvBQn412Tc-8KMW_tjJi4c,13948
openpyxl/worksheet/__init__.py,sha256=vy0Tqjyg0JU0hFQkaKwsNNXId2uWxw94S4fNgk1JwmY,35
openpyxl/worksheet/__pycache__/__init__.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/_read_only.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/_reader.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/_write_only.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/_writer.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/cell_range.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/cell_watch.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/controls.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/copier.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/custom.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/datavalidation.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/dimensions.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/drawing.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/errors.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/filters.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/header_footer.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/hyperlink.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/merge.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/ole.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/page.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/pagebreak.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/picture.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/properties.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/protection.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/related.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/scenario.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/smart_tag.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/table.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/views.cpython-310.pyc,,
openpyxl/worksheet/__pycache__/worksheet.cpython-310.pyc,,
openpyxl/worksheet/_read_only.py,sha256=N0OBX8AWDtUXGn04B7KvdBKVAq1WeU5WtXSi9cwm-MU,5439
openpyxl/worksheet/_reader.py,sha256=3fwxRovWHrz5YvQTu6MyDMOFqKJV9Qdu6q0l-yhNZBw,15856
openpyxl/worksheet/_write_only.py,sha256=tSJQmFedR2J8n8M4cCL74a2DwaTLhFw7-cAfQM7_jMw,4256
openpyxl/worksheet/_writer.py,sha256=ucDCufJ6SpFX58FebvGXarkVWS2RRX9_JUSIwjEYGik,10318
openpyxl/worksheet/cell_range.py,sha256=JAmAMh9SDh-7j-0WP3uc-lgtyg3AKiamadOyqBD34HM,14642
openpyxl/worksheet/cell_watch.py,sha256=LdxGcTmXbZ4sxm6inasFgZPld1ijdL5_ODSUvvz13DU,608
openpyxl/worksheet/controls.py,sha256=N3cx3jYJ5HQHxYTT95HC9Bk77CG4zAvp1jZlKWRT8gE,2735
openpyxl/worksheet/copier.py,sha256=yy3tV3Fvafb6KhwbIE7qKM-8jwRLADv_yfgf6ubJCZU,2327
openpyxl/worksheet/custom.py,sha256=CRlQ98GwqqKmEDkv8gPUCa0ApNM2Vz-BLs_-RMu3jLA,639
openpyxl/worksheet/datavalidation.py,sha256=PZo_Ojre6BAndAltZSyhHahDikaptLgLWCQHYzgJEn8,6136
openpyxl/worksheet/dimensions.py,sha256=J9PiC1Uj1VNJoJqgph4BTHB_HMwfuKyJbN38YC_olwc,8877
openpyxl/worksheet/drawing.py,sha256=OxtZKz-iGEdBe8cAIiNE0_dJmtxy740-ilvK4eshcW8,275
openpyxl/worksheet/errors.py,sha256=KkFC4bnckvCp74XsVXA7JUCi4MIimEFu3uAddcQpjo0,2435
openpyxl/worksheet/filters.py,sha256=DOcn_Eiyvf38X4FBEups5aunWmyZzttduAVI3mnL-Zg,10854
openpyxl/worksheet/header_footer.py,sha256=AQ7BLJ_xNQ1FZ5E7ObZ4vAxHiGEacajqNss6jVhO6y4,7886
openpyxl/worksheet/hyperlink.py,sha256=j4D98tw6TDEB-KsYRxlnCevaQg-zcNYDsCL8eRX11KY,1391
openpyxl/worksheet/merge.py,sha256=LEV-etpiaD8ROQY-ppfi9DmSyIbkqIt4f5ssley-O_k,4140
openpyxl/worksheet/ole.py,sha256=VDINt__P9yPRcwQnFhGSuuSdaFZXc5OrNXS2aXCX_Wc,3530
openpyxl/worksheet/page.py,sha256=1uZMPI_218SXoR_41SfS2_mra7YMq2-VACupPUl8E4M,4920
openpyxl/worksheet/pagebreak.py,sha256=SmJWoXhYn5ajLSVKT3dcwP4dFET9cbXNgEBGOeQohGE,1811
openpyxl/worksheet/picture.py,sha256=72TctCxzk2JU8uFfjiEbTBufEe5eQxIieSPBRhU6m1Q,185
openpyxl/worksheet/properties.py,sha256=xGM6ULgtLMCGxzPOGM4V0kOsvWEFYG9lLsfZYgF6IYk,3087
openpyxl/worksheet/protection.py,sha256=kKanq7Tkmjw37nwm1q0VY9B579zLKWF2sFRLu849vX4,3787
openpyxl/worksheet/related.py,sha256=dZcMFcmW8jXi6dTAomvZPLODjj9mPDVZZKz22TMfQts,348
openpyxl/worksheet/scenario.py,sha256=ny0BiVQhzUKxi-ubTkbTF6v4AWGy7ZnV2jE3Rt8_um8,2401
openpyxl/worksheet/smart_tag.py,sha256=nLbt04IqeJllk7TmNS1eTNdb7On5jMf3llfyy3otDSk,1608
openpyxl/worksheet/table.py,sha256=HJgFVvv57qamZmlZf53qgZ3QfKrxuwSR-7EbUcr-ZNE,11716
openpyxl/worksheet/views.py,sha256=jeuym07ghdbNft8P3eXZ3q1b0YWl72bMQD58v1cFWxc,4632
openpyxl/worksheet/worksheet.py,sha256=qugIcPJtyLu_fqIhdIbzVi_JpRN3TaHn4Yxi1RisQZw,27473
openpyxl/writer/__init__.py,sha256=vy0Tqjyg0JU0hFQkaKwsNNXId2uWxw94S4fNgk1JwmY,35
openpyxl/writer/__pycache__/__init__.cpython-310.pyc,,
openpyxl/writer/__pycache__/excel.cpython-310.pyc,,
openpyxl/writer/__pycache__/theme.cpython-310.pyc,,
openpyxl/writer/excel.py,sha256=vsSn-sCmOxUCzPrH0PX6MBTnT6vMC5v7htGBbv71E3U,9854
openpyxl/writer/theme.py,sha256=eRW0tETAWL8HyE6zyt6lLPnzWX9ul5JPXX3VHkZnw84,10320
openpyxl/xml/__init__.py,sha256=f28-m53hDspYqdZxg2h-cMBOCjBCH7tzcsMLDZ7ax3c,1016
openpyxl/xml/__pycache__/__init__.cpython-310.pyc,,
openpyxl/xml/__pycache__/constants.cpython-310.pyc,,
openpyxl/xml/__pycache__/functions.cpython-310.pyc,,
openpyxl/xml/constants.py,sha256=EmxmaCPuoGbzKAQovJXcjq6QHDUhAxaU1bt-Lf7mCko,4546
openpyxl/xml/functions.py,sha256=EcldyNqNvSjLgJA7qpZ7Xp2fChlMr4H-zq0pIu4XA4Q,1929

View File

@ -0,0 +1,6 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.37.0)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any

View File

@ -0,0 +1 @@
openpyxl

View File

@ -0,0 +1,18 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.compat.numbers import NUMPY
from openpyxl.xml import DEFUSEDXML, LXML
from openpyxl.workbook import Workbook
from openpyxl.reader.excel import load_workbook as open
from openpyxl.reader.excel import load_workbook
import openpyxl._constants as constants
# Expose constants especially the version number
__author__ = constants.__author__
__author_email__ = constants.__author_email__
__license__ = constants.__license__
__maintainer_email__ = constants.__maintainer_email__
__url__ = constants.__url__
__version__ = constants.__version__

View File

@ -0,0 +1,13 @@
# Copyright (c) 2010-2022 openpyxl
"""
Package metadata
"""
__author__ = "See AUTHORS"
__author_email__ = "charlie.clark@clark-consulting.eu"
__license__ = "MIT"
__maintainer_email__ = "openpyxl-users@googlegroups.com"
__url__ = "https://openpyxl.readthedocs.io"
__version__ = "3.0.10"
__python__ = "3.6"

View File

@ -0,0 +1,4 @@
# Copyright (c) 2010-2022 openpyxl
from .cell import Cell, WriteOnlyCell, MergedCell
from .read_only import ReadOnlyCell

View File

@ -0,0 +1,108 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.compat import safe_string
from openpyxl.xml.functions import Element, SubElement, whitespace, XML_NS, REL_NS
from openpyxl import LXML
from openpyxl.utils.datetime import to_excel, to_ISO8601
from datetime import timedelta
def _set_attributes(cell, styled=None):
"""
Set coordinate and datatype
"""
coordinate = cell.coordinate
attrs = {'r': coordinate}
if styled:
attrs['s'] = f"{cell.style_id}"
if cell.data_type == "s":
attrs['t'] = "inlineStr"
elif cell.data_type != 'f':
attrs['t'] = cell.data_type
value = cell._value
if cell.data_type == "d":
if hasattr(value, "tzinfo") and value.tzinfo is not None:
raise TypeError("Excel does not support timezones in datetimes. "
"The tzinfo in the datetime/time object must be set to None.")
if cell.parent.parent.iso_dates and not isinstance(value, timedelta):
value = to_ISO8601(value)
else:
attrs['t'] = "n"
value = to_excel(value, cell.parent.parent.epoch)
if cell.hyperlink:
cell.parent._hyperlinks.append(cell.hyperlink)
return value, attrs
def etree_write_cell(xf, worksheet, cell, styled=None):
value, attributes = _set_attributes(cell, styled)
el = Element("c", attributes)
if value is None or value == "":
xf.write(el)
return
if cell.data_type == 'f':
shared_formula = worksheet.formula_attributes.get(cell.coordinate, {})
formula = SubElement(el, 'f', shared_formula)
if value is not None:
formula.text = value[1:]
value = None
if cell.data_type == 's':
inline_string = SubElement(el, 'is')
text = SubElement(inline_string, 't')
text.text = value
whitespace(text)
else:
cell_content = SubElement(el, 'v')
if value is not None:
cell_content.text = safe_string(value)
xf.write(el)
def lxml_write_cell(xf, worksheet, cell, styled=False):
value, attributes = _set_attributes(cell, styled)
if value == '' or value is None:
with xf.element("c", attributes):
return
with xf.element('c', attributes):
if cell.data_type == 'f':
shared_formula = worksheet.formula_attributes.get(cell.coordinate, {})
with xf.element('f', shared_formula):
if value is not None:
xf.write(value[1:])
value = None
if cell.data_type == 's':
with xf.element("is"):
attrs = {}
if value != value.strip():
attrs["{%s}space" % XML_NS] = "preserve"
el = Element("t", attrs) # lxml can't handle xml-ns
el.text = value
xf.write(el)
#with xf.element("t", attrs):
#xf.write(value)
else:
with xf.element("v"):
if value is not None:
xf.write(safe_string(value))
if LXML:
write_cell = lxml_write_cell
else:
write_cell = etree_write_cell

View File

@ -0,0 +1,329 @@
# Copyright (c) 2010-2022 openpyxl
"""Manage individual cells in a spreadsheet.
The Cell class is required to know its value and type, display options,
and any other features of an Excel cell. Utilities for referencing
cells using Excel's 'A1' column/row nomenclature are also provided.
"""
__docformat__ = "restructuredtext en"
# Python stdlib imports
from copy import copy
import datetime
import re
from openpyxl.compat import (
NUMERIC_TYPES,
deprecated,
)
from openpyxl.utils.exceptions import IllegalCharacterError
from openpyxl.utils import get_column_letter
from openpyxl.styles import numbers, is_date_format
from openpyxl.styles.styleable import StyleableObject
from openpyxl.worksheet.hyperlink import Hyperlink
# constants
TIME_TYPES = (datetime.datetime, datetime.date, datetime.time, datetime.timedelta)
TIME_FORMATS = {
datetime.datetime:numbers.FORMAT_DATE_DATETIME,
datetime.date:numbers.FORMAT_DATE_YYYYMMDD2,
datetime.time:numbers.FORMAT_DATE_TIME6,
datetime.timedelta:numbers.FORMAT_DATE_TIMEDELTA,
}
STRING_TYPES = (str, bytes)
KNOWN_TYPES = NUMERIC_TYPES + TIME_TYPES + STRING_TYPES + (bool, type(None))
ILLEGAL_CHARACTERS_RE = re.compile(r'[\000-\010]|[\013-\014]|[\016-\037]')
ERROR_CODES = ('#NULL!', '#DIV/0!', '#VALUE!', '#REF!', '#NAME?', '#NUM!',
'#N/A')
TYPE_STRING = 's'
TYPE_FORMULA = 'f'
TYPE_NUMERIC = 'n'
TYPE_BOOL = 'b'
TYPE_NULL = 'n'
TYPE_INLINE = 'inlineStr'
TYPE_ERROR = 'e'
TYPE_FORMULA_CACHE_STRING = 'str'
VALID_TYPES = (TYPE_STRING, TYPE_FORMULA, TYPE_NUMERIC, TYPE_BOOL,
TYPE_NULL, TYPE_INLINE, TYPE_ERROR, TYPE_FORMULA_CACHE_STRING)
_TYPES = {int:'n', float:'n', str:'s', bool:'b'}
def get_type(t, value):
if isinstance(value, NUMERIC_TYPES):
dt = 'n'
elif isinstance(value, STRING_TYPES):
dt = 's'
elif isinstance(value, TIME_TYPES):
dt = 'd'
else:
return
_TYPES[t] = dt
return dt
def get_time_format(t):
value = TIME_FORMATS.get(t)
if value:
return value
for base in t.mro()[1:]:
value = TIME_FORMATS.get(base)
if value:
TIME_FORMATS[t] = value
return value
raise ValueError("Could not get time format for {0!r}".format(value))
class Cell(StyleableObject):
"""Describes cell associated properties.
Properties of interest include style, type, value, and address.
"""
__slots__ = (
'row',
'column',
'_value',
'data_type',
'parent',
'_hyperlink',
'_comment',
)
def __init__(self, worksheet, row=None, column=None, value=None, style_array=None):
super(Cell, self).__init__(worksheet, style_array)
self.row = row
"""Row number of this cell (1-based)"""
self.column = column
"""Column number of this cell (1-based)"""
# _value is the stored value, while value is the displayed value
self._value = None
self._hyperlink = None
self.data_type = 'n'
if value is not None:
self.value = value
self._comment = None
@property
def coordinate(self):
"""This cell's coordinate (ex. 'A5')"""
col = get_column_letter(self.column)
return f"{col}{self.row}"
@property
def col_idx(self):
"""The numerical index of the column"""
return self.column
@property
def column_letter(self):
return get_column_letter(self.column)
@property
def encoding(self):
return self.parent.encoding
@property
def base_date(self):
return self.parent.parent.epoch
def __repr__(self):
return "<Cell {0!r}.{1}>".format(self.parent.title, self.coordinate)
def check_string(self, value):
"""Check string coding, length, and line break character"""
if value is None:
return
# convert to str string
if not isinstance(value, str):
value = str(value, self.encoding)
value = str(value)
# string must never be longer than 32,767 characters
# truncate if necessary
value = value[:32767]
if next(ILLEGAL_CHARACTERS_RE.finditer(value), None):
raise IllegalCharacterError
return value
def check_error(self, value):
"""Tries to convert Error" else N/A"""
try:
return str(value)
except UnicodeDecodeError:
return u'#N/A'
def _bind_value(self, value):
"""Given a value, infer the correct data type"""
self.data_type = "n"
t = type(value)
try:
dt = _TYPES[t]
except KeyError:
dt = get_type(t, value)
if dt is None and value is not None:
raise ValueError("Cannot convert {0!r} to Excel".format(value))
if dt:
self.data_type = dt
if dt == 'd':
if not is_date_format(self.number_format):
self.number_format = get_time_format(t)
elif dt == "s":
value = self.check_string(value)
if len(value) > 1 and value.startswith("="):
self.data_type = 'f'
elif value in ERROR_CODES:
self.data_type = 'e'
self._value = value
@property
def value(self):
"""Get or set the value held in the cell.
:type: depends on the value (string, float, int or
:class:`datetime.datetime`)
"""
return self._value
@value.setter
def value(self, value):
"""Set the value and infer type and display options."""
self._bind_value(value)
@property
def internal_value(self):
"""Always returns the value for excel."""
return self._value
@property
def hyperlink(self):
"""Return the hyperlink target or an empty string"""
return self._hyperlink
@hyperlink.setter
def hyperlink(self, val):
"""Set value and display for hyperlinks in a cell.
Automatically sets the `value` of the cell with link text,
but you can modify it afterwards by setting the `value`
property, and the hyperlink will remain.
Hyperlink is removed if set to ``None``."""
if val is None:
self._hyperlink = None
else:
if not isinstance(val, Hyperlink):
val = Hyperlink(ref="", target=val)
val.ref = self.coordinate
self._hyperlink = val
if self._value is None:
self.value = val.target or val.location
@property
def is_date(self):
"""True if the value is formatted as a date
:type: bool
"""
return self.data_type == 'd' or (
self.data_type == 'n' and is_date_format(self.number_format)
)
def offset(self, row=0, column=0):
"""Returns a cell location relative to this cell.
:param row: number of rows to offset
:type row: int
:param column: number of columns to offset
:type column: int
:rtype: :class:`openpyxl.cell.Cell`
"""
offset_column = self.col_idx + column
offset_row = self.row + row
return self.parent.cell(column=offset_column, row=offset_row)
@property
def comment(self):
""" Returns the comment associated with this cell
:type: :class:`openpyxl.comments.Comment`
"""
return self._comment
@comment.setter
def comment(self, value):
"""
Assign a comment to a cell
"""
if value is not None:
if value.parent:
value = copy(value)
value.bind(self)
elif value is None and self._comment:
self._comment.unbind()
self._comment = value
class MergedCell(StyleableObject):
"""
Describes the properties of a cell in a merged cell and helps to
display the borders of the merged cell.
The value of a MergedCell is always None.
"""
__slots__ = ('row', 'column')
_value = None
data_type = "n"
comment = None
hyperlink = None
def __init__(self, worksheet, row=None, column=None):
super(MergedCell, self).__init__(worksheet)
self.row = row
self.column = column
def __repr__(self):
return "<MergedCell {0!r}.{1}>".format(self.parent.title, self.coordinate)
coordinate = Cell.coordinate
_comment = comment
value = _value
def WriteOnlyCell(ws=None, value=None):
return Cell(worksheet=ws, column=1, row=1, value=value)

View File

@ -0,0 +1,136 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.cell import Cell
from openpyxl.utils import get_column_letter
from openpyxl.utils.datetime import from_excel
from openpyxl.styles import is_date_format
from openpyxl.styles.numbers import BUILTIN_FORMATS, BUILTIN_FORMATS_MAX_SIZE
class ReadOnlyCell(object):
__slots__ = ('parent', 'row', 'column', '_value', 'data_type', '_style_id')
def __init__(self, sheet, row, column, value, data_type='n', style_id=0):
self.parent = sheet
self._value = None
self.row = row
self.column = column
self.data_type = data_type
self.value = value
self._style_id = style_id
def __eq__(self, other):
for a in self.__slots__:
if getattr(self, a) != getattr(other, a):
return
return True
def __ne__(self, other):
return not self.__eq__(other)
def __repr__(self):
return "<ReadOnlyCell {0!r}.{1}>".format(self.parent.title, self.coordinate)
@property
def coordinate(self):
column = get_column_letter(self.column)
return "{1}{0}".format(self.row, column)
@property
def coordinate(self):
return Cell.coordinate.__get__(self)
@property
def column_letter(self):
return Cell.column_letter.__get__(self)
@property
def style_array(self):
return self.parent.parent._cell_styles[self._style_id]
@property
def has_style(self):
return self._style_id != 0
@property
def number_format(self):
_id = self.style_array.numFmtId
if _id < BUILTIN_FORMATS_MAX_SIZE:
return BUILTIN_FORMATS.get(_id, "General")
else:
return self.parent.parent._number_formats[
_id - BUILTIN_FORMATS_MAX_SIZE]
@property
def font(self):
_id = self.style_array.fontId
return self.parent.parent._fonts[_id]
@property
def fill(self):
_id = self.style_array.fillId
return self.parent.parent._fills[_id]
@property
def border(self):
_id = self.style_array.borderId
return self.parent.parent._borders[_id]
@property
def alignment(self):
_id = self.style_array.alignmentId
return self.parent.parent._alignments[_id]
@property
def protection(self):
_id = self.style_array.protectionId
return self.parent.parent._protections[_id]
@property
def is_date(self):
return Cell.is_date.__get__(self)
@property
def internal_value(self):
return self._value
@property
def value(self):
return self._value
@value.setter
def value(self, value):
if self._value is not None:
raise AttributeError("Cell is read only")
self._value = value
class EmptyCell(object):
__slots__ = ()
value = None
is_date = False
font = None
border = None
fill = None
number_format = None
alignment = None
data_type = 'n'
def __repr__(self):
return "<EmptyCell>"
EMPTY_CELL = EmptyCell()

View File

@ -0,0 +1,184 @@
# Copyright (c) 2010-2022 openpyxl
"""
Richtext definition
"""
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Alias,
Typed,
Integer,
Set,
NoneSet,
Bool,
String,
Sequence,
)
from openpyxl.descriptors.nested import (
NestedBool,
NestedInteger,
NestedString,
NestedText,
)
from openpyxl.styles.fonts import Font
class PhoneticProperties(Serialisable):
tagname = "phoneticPr"
fontId = Integer()
type = NoneSet(values=(['halfwidthKatakana', 'fullwidthKatakana',
'Hiragana', 'noConversion']))
alignment = NoneSet(values=(['noControl', 'left', 'center', 'distributed']))
def __init__(self,
fontId=None,
type=None,
alignment=None,
):
self.fontId = fontId
self.type = type
self.alignment = alignment
class PhoneticText(Serialisable):
tagname = "rPh"
sb = Integer()
eb = Integer()
t = NestedText(expected_type=str)
text = Alias('t')
def __init__(self,
sb=None,
eb=None,
t=None,
):
self.sb = sb
self.eb = eb
self.t = t
class InlineFont(Font):
"""
Font for inline text because, yes what you need are different objects with the same elements but different constraints.
"""
tagname = "RPrElt"
rFont = NestedString(allow_none=True)
charset = Font.charset
family = Font.family
b =Font.b
i = Font.i
strike = Font.strike
outline = Font.outline
shadow = Font.shadow
condense = Font.condense
extend = Font.extend
color = Font.color
sz = Font.sz
u = Font.u
vertAlign = Font.vertAlign
scheme = Font.scheme
__elements__ = ('rFont', 'charset', 'family', 'b', 'i', 'strike',
'outline', 'shadow', 'condense', 'extend', 'color', 'sz', 'u',
'vertAlign', 'scheme')
def __init__(self,
rFont=None,
charset=None,
family=None,
b=None,
i=None,
strike=None,
outline=None,
shadow=None,
condense=None,
extend=None,
color=None,
sz=None,
u=None,
vertAlign=None,
scheme=None,
):
self.rFont = rFont
self.charset = charset
self.family = family
self.b = b
self.i = i
self.strike = strike
self.outline = outline
self.shadow = shadow
self.condense = condense
self.extend = extend
self.color = color
self.sz = sz
self.u = u
self.vertAlign = vertAlign
self.scheme = scheme
class RichText(Serialisable):
tagname = "RElt"
rPr = Typed(expected_type=InlineFont, allow_none=True)
font = Alias("rPr")
t = NestedText(expected_type=str, allow_none=True)
text = Alias("t")
__elements__ = ('rPr', 't')
def __init__(self,
rPr=None,
t=None,
):
self.rPr = rPr
self.t = t
class Text(Serialisable):
tagname = "text"
t = NestedText(allow_none=True, expected_type=str)
plain = Alias("t")
r = Sequence(expected_type=RichText, allow_none=True)
formatted = Alias("r")
rPh = Sequence(expected_type=PhoneticText, allow_none=True)
phonetic = Alias("rPh")
phoneticPr = Typed(expected_type=PhoneticProperties, allow_none=True)
PhoneticProperties = Alias("phoneticPr")
__elements__ = ('t', 'r', 'rPh', 'phoneticPr')
def __init__(self,
t=None,
r=(),
rPh=(),
phoneticPr=None,
):
self.t = t
self.r = r
self.rPh = rPh
self.phoneticPr = phoneticPr
@property
def content(self):
"""
Text stripped of all formatting
"""
snippets = []
if self.plain is not None:
snippets.append(self.plain)
for block in self.formatted:
if block.t is not None:
snippets.append(block.t)
return u"".join(snippets)

View File

@ -0,0 +1,105 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors import Typed, Alias
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors.nested import (
NestedBool,
NestedInteger,
NestedMinMax,
)
from openpyxl.descriptors.excel import ExtensionList
from .marker import PictureOptions
from .shapes import GraphicalProperties
class View3D(Serialisable):
tagname = "view3D"
rotX = NestedMinMax(min=-90, max=90, allow_none=True)
x_rotation = Alias('rotX')
hPercent = NestedMinMax(min=5, max=500, allow_none=True)
height_percent = Alias('hPercent')
rotY = NestedInteger(min=-90, max=90, allow_none=True)
y_rotation = Alias('rotY')
depthPercent = NestedInteger(allow_none=True)
rAngAx = NestedBool(allow_none=True)
right_angle_axes = Alias('rAngAx')
perspective = NestedInteger(allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('rotX', 'hPercent', 'rotY', 'depthPercent', 'rAngAx',
'perspective',)
def __init__(self,
rotX=15,
hPercent=None,
rotY=20,
depthPercent=None,
rAngAx=True,
perspective=None,
extLst=None,
):
self.rotX = rotX
self.hPercent = hPercent
self.rotY = rotY
self.depthPercent = depthPercent
self.rAngAx = rAngAx
self.perspective = perspective
class Surface(Serialisable):
tagname = "surface"
thickness = NestedInteger(allow_none=True)
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias('spPr')
pictureOptions = Typed(expected_type=PictureOptions, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('thickness', 'spPr', 'pictureOptions',)
def __init__(self,
thickness=None,
spPr=None,
pictureOptions=None,
extLst=None,
):
self.thickness = thickness
self.spPr = spPr
self.pictureOptions = pictureOptions
class _3DBase(Serialisable):
"""
Base class for 3D charts
"""
tagname = "ChartBase"
view3D = Typed(expected_type=View3D, allow_none=True)
floor = Typed(expected_type=Surface, allow_none=True)
sideWall = Typed(expected_type=Surface, allow_none=True)
backWall = Typed(expected_type=Surface, allow_none=True)
def __init__(self,
view3D=None,
floor=None,
sideWall=None,
backWall=None,
):
if view3D is None:
view3D = View3D()
self.view3D = view3D
if floor is None:
floor = Surface()
self.floor = floor
if sideWall is None:
sideWall = Surface()
self.sideWall = sideWall
if backWall is None:
backWall = Surface()
self.backWall = backWall
super(_3DBase, self).__init__()

View File

@ -0,0 +1,19 @@
# Copyright (c) 2010-2022 openpyxl
from .area_chart import AreaChart, AreaChart3D
from .bar_chart import BarChart, BarChart3D
from .bubble_chart import BubbleChart
from .line_chart import LineChart, LineChart3D
from .pie_chart import (
PieChart,
PieChart3D,
DoughnutChart,
ProjectedPieChart
)
from .radar_chart import RadarChart
from .scatter_chart import ScatterChart
from .stock_chart import StockChart
from .surface_chart import SurfaceChart, SurfaceChart3D
from .series_factory import SeriesFactory as Series
from .reference import Reference

View File

@ -0,0 +1,196 @@
# Copyright (c) 2010-2022 openpyxl
from collections import OrderedDict
from operator import attrgetter
from openpyxl.descriptors import (
Typed,
Integer,
Alias,
MinMax,
Bool,
Set,
)
from openpyxl.descriptors.sequence import ValueSequence
from openpyxl.descriptors.serialisable import Serialisable
from ._3d import _3DBase
from .data_source import AxDataSource, NumRef
from .layout import Layout
from .legend import Legend
from .reference import Reference
from .series_factory import SeriesFactory
from .series import attribute_mapping
from .shapes import GraphicalProperties
from .title import TitleDescriptor
class AxId(Serialisable):
val = Integer()
def __init__(self, val):
self.val = val
def PlotArea():
from .chartspace import PlotArea
return PlotArea()
class ChartBase(Serialisable):
"""
Base class for all charts
"""
legend = Typed(expected_type=Legend, allow_none=True)
layout = Typed(expected_type=Layout, allow_none=True)
roundedCorners = Bool(allow_none=True)
axId = ValueSequence(expected_type=int)
visible_cells_only = Bool(allow_none=True)
display_blanks = Set(values=['span', 'gap', 'zero'])
_series_type = ""
ser = ()
series = Alias('ser')
title = TitleDescriptor()
anchor = "E15" # default anchor position
width = 15 # in cm, approx 5 rows
height = 7.5 # in cm, approx 14 rows
_id = 1
_path = "/xl/charts/chart{0}.xml"
style = MinMax(allow_none=True, min=1, max=48)
mime_type = "application/vnd.openxmlformats-officedocument.drawingml.chart+xml"
graphical_properties = Typed(expected_type=GraphicalProperties, allow_none=True)
__elements__ = ()
def __init__(self, axId=(), **kw):
self._charts = [self]
self.title = None
self.layout = None
self.roundedCorners = None
self.legend = Legend()
self.graphical_properties = None
self.style = None
self.plot_area = PlotArea()
self.axId = axId
self.display_blanks = 'gap'
self.pivotSource = None
self.pivotFormats = ()
self.visible_cells_only = True
self.idx_base = 0
super(ChartBase, self).__init__()
def __hash__(self):
"""
Just need to check for identity
"""
return id(self)
def __iadd__(self, other):
"""
Combine the chart with another one
"""
if not isinstance(other, ChartBase):
raise TypeError("Only other charts can be added")
self._charts.append(other)
return self
def to_tree(self, namespace=None, tagname=None, idx=None):
self.axId = [id for id in self._axes]
if self.ser is not None:
for s in self.ser:
s.__elements__ = attribute_mapping[self._series_type]
return super(ChartBase, self).to_tree(tagname, idx)
def _reindex(self):
"""
Normalise and rebase series: sort by order and then rebase order
"""
# sort data series in order and rebase
ds = sorted(self.series, key=attrgetter("order"))
for idx, s in enumerate(ds):
s.order = idx
self.series = ds
def _write(self):
from .chartspace import ChartSpace, ChartContainer
self.plot_area.layout = self.layout
idx_base = self.idx_base
for chart in self._charts:
if chart not in self.plot_area._charts:
chart.idx_base = idx_base
idx_base += len(chart.series)
self.plot_area._charts = self._charts
container = ChartContainer(plotArea=self.plot_area, legend=self.legend, title=self.title)
if isinstance(chart, _3DBase):
container.view3D = chart.view3D
container.floor = chart.floor
container.sideWall = chart.sideWall
container.backWall = chart.backWall
container.plotVisOnly = self.visible_cells_only
container.dispBlanksAs = self.display_blanks
container.pivotFmts = self.pivotFormats
cs = ChartSpace(chart=container)
cs.style = self.style
cs.roundedCorners = self.roundedCorners
cs.pivotSource = self.pivotSource
return cs.to_tree()
@property
def _axes(self):
x = getattr(self, "x_axis", None)
y = getattr(self, "y_axis", None)
z = getattr(self, "z_axis", None)
return OrderedDict([(axis.axId, axis) for axis in (x, y, z) if axis])
def set_categories(self, labels):
"""
Set the categories / x-axis values
"""
if not isinstance(labels, Reference):
labels = Reference(range_string=labels)
for s in self.ser:
s.cat = AxDataSource(numRef=NumRef(f=labels))
def add_data(self, data, from_rows=False, titles_from_data=False):
"""
Add a range of data in a single pass.
The default is to treat each column as a data series.
"""
if not isinstance(data, Reference):
data = Reference(range_string=data)
if from_rows:
values = data.rows
else:
values = data.cols
for ref in values:
series = SeriesFactory(ref, title_from_data=titles_from_data)
self.series.append(series)
def append(self, value):
"""Append a data series to the chart"""
l = self.series[:]
l.append(value)
self.series = l
@property
def path(self):
return self._path.format(self._id)

View File

@ -0,0 +1,106 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Set,
Bool,
Integer,
Sequence,
Alias,
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.nested import (
NestedMinMax,
NestedSet,
NestedBool,
)
from ._chart import ChartBase
from .descriptors import NestedGapAmount
from .axis import TextAxis, NumericAxis, SeriesAxis, ChartLines
from .label import DataLabelList
from .series import Series
class _AreaChartBase(ChartBase):
grouping = NestedSet(values=(['percentStacked', 'standard', 'stacked']))
varyColors = NestedBool(nested=True, allow_none=True)
ser = Sequence(expected_type=Series, allow_none=True)
dLbls = Typed(expected_type=DataLabelList, allow_none=True)
dataLabels = Alias("dLbls")
dropLines = Typed(expected_type=ChartLines, allow_none=True)
_series_type = "area"
__elements__ = ('grouping', 'varyColors', 'ser', 'dLbls', 'dropLines')
def __init__(self,
grouping="standard",
varyColors=None,
ser=(),
dLbls=None,
dropLines=None,
):
self.grouping = grouping
self.varyColors = varyColors
self.ser = ser
self.dLbls = dLbls
self.dropLines = dropLines
super(_AreaChartBase, self).__init__()
class AreaChart(_AreaChartBase):
tagname = "areaChart"
grouping = _AreaChartBase.grouping
varyColors = _AreaChartBase.varyColors
ser = _AreaChartBase.ser
dLbls = _AreaChartBase.dLbls
dropLines = _AreaChartBase.dropLines
# chart properties actually used by containing classes
x_axis = Typed(expected_type=TextAxis)
y_axis = Typed(expected_type=NumericAxis)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = _AreaChartBase.__elements__ + ('axId',)
def __init__(self,
axId=None,
extLst=None,
**kw
):
self.x_axis = TextAxis()
self.y_axis = NumericAxis()
super(AreaChart, self).__init__(**kw)
class AreaChart3D(AreaChart):
tagname = "area3DChart"
grouping = _AreaChartBase.grouping
varyColors = _AreaChartBase.varyColors
ser = _AreaChartBase.ser
dLbls = _AreaChartBase.dLbls
dropLines = _AreaChartBase.dropLines
gapDepth = NestedGapAmount()
x_axis = Typed(expected_type=TextAxis)
y_axis = Typed(expected_type=NumericAxis)
z_axis = Typed(expected_type=SeriesAxis, allow_none=True)
__elements__ = AreaChart.__elements__ + ('gapDepth', )
def __init__(self, gapDepth=None, **kw):
self.gapDepth = gapDepth
super(AreaChart3D, self).__init__(**kw)
self.x_axis = TextAxis()
self.y_axis = NumericAxis()
self.z_axis = SeriesAxis()

View File

@ -0,0 +1,401 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Float,
NoneSet,
Bool,
Integer,
MinMax,
NoneSet,
Set,
String,
Alias,
)
from openpyxl.descriptors.excel import (
ExtensionList,
Percentage,
_explicit_none,
)
from openpyxl.descriptors.nested import (
NestedValue,
NestedSet,
NestedBool,
NestedNoneSet,
NestedFloat,
NestedInteger,
NestedMinMax,
)
from openpyxl.xml.constants import CHART_NS
from .descriptors import NumberFormatDescriptor
from .layout import Layout
from .text import Text, RichText
from .shapes import GraphicalProperties
from .title import Title, TitleDescriptor
class ChartLines(Serialisable):
tagname = "chartLines"
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias('spPr')
def __init__(self, spPr=None):
self.spPr = spPr
class Scaling(Serialisable):
tagname = "scaling"
logBase = NestedFloat(allow_none=True)
orientation = NestedSet(values=(['maxMin', 'minMax']))
max = NestedFloat(allow_none=True)
min = NestedFloat(allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('logBase', 'orientation', 'max', 'min',)
def __init__(self,
logBase=None,
orientation="minMax",
max=None,
min=None,
extLst=None,
):
self.logBase = logBase
self.orientation = orientation
self.max = max
self.min = min
class _BaseAxis(Serialisable):
axId = NestedInteger(expected_type=int)
scaling = Typed(expected_type=Scaling)
delete = NestedBool(allow_none=True)
axPos = NestedSet(values=(['b', 'l', 'r', 't']))
majorGridlines = Typed(expected_type=ChartLines, allow_none=True)
minorGridlines = Typed(expected_type=ChartLines, allow_none=True)
title = TitleDescriptor()
numFmt = NumberFormatDescriptor()
number_format = Alias("numFmt")
majorTickMark = NestedNoneSet(values=(['cross', 'in', 'out']), to_tree=_explicit_none)
minorTickMark = NestedNoneSet(values=(['cross', 'in', 'out']), to_tree=_explicit_none)
tickLblPos = NestedNoneSet(values=(['high', 'low', 'nextTo']))
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias('spPr')
txPr = Typed(expected_type=RichText, allow_none=True)
textProperties = Alias('txPr')
crossAx = NestedInteger(expected_type=int) # references other axis
crosses = NestedNoneSet(values=(['autoZero', 'max', 'min']))
crossesAt = NestedFloat(allow_none=True)
# crosses & crossesAt are mutually exclusive
__elements__ = ('axId', 'scaling', 'delete', 'axPos', 'majorGridlines',
'minorGridlines', 'title', 'numFmt', 'majorTickMark', 'minorTickMark',
'tickLblPos', 'spPr', 'txPr', 'crossAx', 'crosses', 'crossesAt')
def __init__(self,
axId=None,
scaling=None,
delete=None,
axPos='l',
majorGridlines=None,
minorGridlines=None,
title=None,
numFmt=None,
majorTickMark=None,
minorTickMark=None,
tickLblPos=None,
spPr=None,
txPr= None,
crossAx=None,
crosses=None,
crossesAt=None,
):
self.axId = axId
if scaling is None:
scaling = Scaling()
self.scaling = scaling
self.delete = delete
self.axPos = axPos
self.majorGridlines = majorGridlines
self.minorGridlines = minorGridlines
self.title = title
self.numFmt = numFmt
self.majorTickMark = majorTickMark
self.minorTickMark = minorTickMark
self.tickLblPos = tickLblPos
self.spPr = spPr
self.txPr = txPr
self.crossAx = crossAx
self.crosses = crosses
self.crossesAt = crossesAt
class DisplayUnitsLabel(Serialisable):
tagname = "dispUnitsLbl"
layout = Typed(expected_type=Layout, allow_none=True)
tx = Typed(expected_type=Text, allow_none=True)
text = Alias("tx")
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias("spPr")
txPr = Typed(expected_type=RichText, allow_none=True)
textPropertes = Alias("txPr")
__elements__ = ('layout', 'tx', 'spPr', 'txPr')
def __init__(self,
layout=None,
tx=None,
spPr=None,
txPr=None,
):
self.layout = layout
self.tx = tx
self.spPr = spPr
self.txPr = txPr
class DisplayUnitsLabelList(Serialisable):
tagname = "dispUnits"
custUnit = NestedFloat(allow_none=True)
builtInUnit = NestedNoneSet(values=(['hundreds', 'thousands',
'tenThousands', 'hundredThousands', 'millions', 'tenMillions',
'hundredMillions', 'billions', 'trillions']))
dispUnitsLbl = Typed(expected_type=DisplayUnitsLabel, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('custUnit', 'builtInUnit', 'dispUnitsLbl',)
def __init__(self,
custUnit=None,
builtInUnit=None,
dispUnitsLbl=None,
extLst=None,
):
self.custUnit = custUnit
self.builtInUnit = builtInUnit
self.dispUnitsLbl = dispUnitsLbl
class NumericAxis(_BaseAxis):
tagname = "valAx"
axId = _BaseAxis.axId
scaling = _BaseAxis.scaling
delete = _BaseAxis.delete
axPos = _BaseAxis.axPos
majorGridlines = _BaseAxis.majorGridlines
minorGridlines = _BaseAxis.minorGridlines
title = _BaseAxis.title
numFmt = _BaseAxis.numFmt
majorTickMark = _BaseAxis.majorTickMark
minorTickMark = _BaseAxis.minorTickMark
tickLblPos = _BaseAxis.tickLblPos
spPr = _BaseAxis.spPr
txPr = _BaseAxis.txPr
crossAx = _BaseAxis.crossAx
crosses = _BaseAxis.crosses
crossesAt = _BaseAxis.crossesAt
crossBetween = NestedNoneSet(values=(['between', 'midCat']))
majorUnit = NestedFloat(allow_none=True)
minorUnit = NestedFloat(allow_none=True)
dispUnits = Typed(expected_type=DisplayUnitsLabelList, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = _BaseAxis.__elements__ + ('crossBetween', 'majorUnit',
'minorUnit', 'dispUnits',)
def __init__(self,
crossBetween=None,
majorUnit=None,
minorUnit=None,
dispUnits=None,
extLst=None,
**kw
):
self.crossBetween = crossBetween
self.majorUnit = majorUnit
self.minorUnit = minorUnit
self.dispUnits = dispUnits
kw.setdefault('majorGridlines', ChartLines())
kw.setdefault('axId', 100)
kw.setdefault('crossAx', 10)
super(NumericAxis, self).__init__(**kw)
@classmethod
def from_tree(cls, node):
"""
Special case value axes with no gridlines
"""
self = super(NumericAxis, cls).from_tree(node)
gridlines = node.find("{%s}majorGridlines" % CHART_NS)
if gridlines is None:
self.majorGridlines = None
return self
class TextAxis(_BaseAxis):
tagname = "catAx"
axId = _BaseAxis.axId
scaling = _BaseAxis.scaling
delete = _BaseAxis.delete
axPos = _BaseAxis.axPos
majorGridlines = _BaseAxis.majorGridlines
minorGridlines = _BaseAxis.minorGridlines
title = _BaseAxis.title
numFmt = _BaseAxis.numFmt
majorTickMark = _BaseAxis.majorTickMark
minorTickMark = _BaseAxis.minorTickMark
tickLblPos = _BaseAxis.tickLblPos
spPr = _BaseAxis.spPr
txPr = _BaseAxis.txPr
crossAx = _BaseAxis.crossAx
crosses = _BaseAxis.crosses
crossesAt = _BaseAxis.crossesAt
auto = NestedBool(allow_none=True)
lblAlgn = NestedNoneSet(values=(['ctr', 'l', 'r']))
lblOffset = NestedMinMax(min=0, max=1000)
tickLblSkip = NestedInteger(allow_none=True)
tickMarkSkip = NestedInteger(allow_none=True)
noMultiLvlLbl = NestedBool(allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = _BaseAxis.__elements__ + ('auto', 'lblAlgn', 'lblOffset',
'tickLblSkip', 'tickMarkSkip', 'noMultiLvlLbl')
def __init__(self,
auto=None,
lblAlgn=None,
lblOffset=100,
tickLblSkip=None,
tickMarkSkip=None,
noMultiLvlLbl=None,
extLst=None,
**kw
):
self.auto = auto
self.lblAlgn = lblAlgn
self.lblOffset = lblOffset
self.tickLblSkip = tickLblSkip
self.tickMarkSkip = tickMarkSkip
self.noMultiLvlLbl = noMultiLvlLbl
kw.setdefault('axId', 10)
kw.setdefault('crossAx', 100)
super(TextAxis, self).__init__(**kw)
class DateAxis(TextAxis):
tagname = "dateAx"
axId = _BaseAxis.axId
scaling = _BaseAxis.scaling
delete = _BaseAxis.delete
axPos = _BaseAxis.axPos
majorGridlines = _BaseAxis.majorGridlines
minorGridlines = _BaseAxis.minorGridlines
title = _BaseAxis.title
numFmt = _BaseAxis.numFmt
majorTickMark = _BaseAxis.majorTickMark
minorTickMark = _BaseAxis.minorTickMark
tickLblPos = _BaseAxis.tickLblPos
spPr = _BaseAxis.spPr
txPr = _BaseAxis.txPr
crossAx = _BaseAxis.crossAx
crosses = _BaseAxis.crosses
crossesAt = _BaseAxis.crossesAt
auto = NestedBool(allow_none=True)
lblOffset = NestedInteger(allow_none=True)
baseTimeUnit = NestedNoneSet(values=(['days', 'months', 'years']))
majorUnit = NestedFloat(allow_none=True)
majorTimeUnit = NestedNoneSet(values=(['days', 'months', 'years']))
minorUnit = NestedFloat(allow_none=True)
minorTimeUnit = NestedNoneSet(values=(['days', 'months', 'years']))
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = _BaseAxis.__elements__ + ('auto', 'lblOffset',
'baseTimeUnit', 'majorUnit', 'majorTimeUnit', 'minorUnit',
'minorTimeUnit')
def __init__(self,
auto=None,
lblOffset=None,
baseTimeUnit=None,
majorUnit=None,
majorTimeUnit=None,
minorUnit=None,
minorTimeUnit=None,
extLst=None,
**kw
):
self.auto = auto
self.lblOffset = lblOffset
self.baseTimeUnit = baseTimeUnit
self.majorUnit = majorUnit
self.majorTimeUnit = majorTimeUnit
self.minorUnit = minorUnit
self.minorTimeUnit = minorTimeUnit
kw.setdefault('axId', 500)
kw.setdefault('lblOffset', lblOffset)
super(DateAxis, self).__init__(**kw)
class SeriesAxis(_BaseAxis):
tagname = "serAx"
axId = _BaseAxis.axId
scaling = _BaseAxis.scaling
delete = _BaseAxis.delete
axPos = _BaseAxis.axPos
majorGridlines = _BaseAxis.majorGridlines
minorGridlines = _BaseAxis.minorGridlines
title = _BaseAxis.title
numFmt = _BaseAxis.numFmt
majorTickMark = _BaseAxis.majorTickMark
minorTickMark = _BaseAxis.minorTickMark
tickLblPos = _BaseAxis.tickLblPos
spPr = _BaseAxis.spPr
txPr = _BaseAxis.txPr
crossAx = _BaseAxis.crossAx
crosses = _BaseAxis.crosses
crossesAt = _BaseAxis.crossesAt
tickLblSkip = NestedInteger(allow_none=True)
tickMarkSkip = NestedInteger(allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = _BaseAxis.__elements__ + ('tickLblSkip', 'tickMarkSkip')
def __init__(self,
tickLblSkip=None,
tickMarkSkip=None,
extLst=None,
**kw
):
self.tickLblSkip = tickLblSkip
self.tickMarkSkip = tickMarkSkip
kw.setdefault('axId', 1000)
kw.setdefault('crossAx', 10)
super(SeriesAxis, self).__init__(**kw)

View File

@ -0,0 +1,144 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Bool,
Integer,
Sequence,
Alias,
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.nested import (
NestedNoneSet,
NestedSet,
NestedBool,
NestedInteger,
NestedMinMax,
)
from .descriptors import (
NestedGapAmount,
NestedOverlap,
)
from ._chart import ChartBase
from ._3d import _3DBase
from .axis import TextAxis, NumericAxis, SeriesAxis, ChartLines
from .shapes import GraphicalProperties
from .series import Series
from .legend import Legend
from .label import DataLabelList
class _BarChartBase(ChartBase):
barDir = NestedSet(values=(['bar', 'col']))
type = Alias("barDir")
grouping = NestedSet(values=(['percentStacked', 'clustered', 'standard',
'stacked']))
varyColors = NestedBool(nested=True, allow_none=True)
ser = Sequence(expected_type=Series, allow_none=True)
dLbls = Typed(expected_type=DataLabelList, allow_none=True)
dataLabels = Alias("dLbls")
__elements__ = ('barDir', 'grouping', 'varyColors', 'ser', 'dLbls')
_series_type = "bar"
def __init__(self,
barDir="col",
grouping="clustered",
varyColors=None,
ser=(),
dLbls=None,
**kw
):
self.barDir = barDir
self.grouping = grouping
self.varyColors = varyColors
self.ser = ser
self.dLbls = dLbls
super(_BarChartBase, self).__init__(**kw)
class BarChart(_BarChartBase):
tagname = "barChart"
barDir = _BarChartBase.barDir
grouping = _BarChartBase.grouping
varyColors = _BarChartBase.varyColors
ser = _BarChartBase.ser
dLbls = _BarChartBase.dLbls
gapWidth = NestedGapAmount()
overlap = NestedOverlap()
serLines = Typed(expected_type=ChartLines, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
# chart properties actually used by containing classes
x_axis = Typed(expected_type=TextAxis)
y_axis = Typed(expected_type=NumericAxis)
__elements__ = _BarChartBase.__elements__ + ('gapWidth', 'overlap', 'serLines', 'axId')
def __init__(self,
gapWidth=150,
overlap=None,
serLines=None,
extLst=None,
**kw
):
self.gapWidth = gapWidth
self.overlap = overlap
self.serLines = serLines
self.x_axis = TextAxis()
self.y_axis = NumericAxis()
self.legend = Legend()
super(BarChart, self).__init__(**kw)
class BarChart3D(_BarChartBase, _3DBase):
tagname = "bar3DChart"
barDir = _BarChartBase.barDir
grouping = _BarChartBase.grouping
varyColors = _BarChartBase.varyColors
ser = _BarChartBase.ser
dLbls = _BarChartBase.dLbls
view3D = _3DBase.view3D
floor = _3DBase.floor
sideWall = _3DBase.sideWall
backWall = _3DBase.backWall
gapWidth = NestedGapAmount()
gapDepth = NestedGapAmount()
shape = NestedNoneSet(values=(['cone', 'coneToMax', 'box', 'cylinder', 'pyramid', 'pyramidToMax']))
serLines = Typed(expected_type=ChartLines, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
x_axis = Typed(expected_type=TextAxis)
y_axis = Typed(expected_type=NumericAxis)
z_axis = Typed(expected_type=SeriesAxis, allow_none=True)
__elements__ = _BarChartBase.__elements__ + ('gapWidth', 'gapDepth', 'shape', 'serLines', 'axId')
def __init__(self,
gapWidth=150,
gapDepth=150,
shape=None,
serLines=None,
extLst=None,
**kw
):
self.gapWidth = gapWidth
self.gapDepth = gapDepth
self.shape = shape
self.serLines = serLines
self.x_axis = TextAxis()
self.y_axis = NumericAxis()
self.z_axis = SeriesAxis()
super(BarChart3D, self).__init__(**kw)

View File

@ -0,0 +1,67 @@
#Autogenerated schema
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Set,
MinMax,
Bool,
Integer,
Alias,
Sequence,
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.nested import (
NestedNoneSet,
NestedMinMax,
NestedBool,
)
from ._chart import ChartBase
from .axis import TextAxis, NumericAxis
from .series import XYSeries
from .label import DataLabelList
class BubbleChart(ChartBase):
tagname = "bubbleChart"
varyColors = NestedBool(allow_none=True)
ser = Sequence(expected_type=XYSeries, allow_none=True)
dLbls = Typed(expected_type=DataLabelList, allow_none=True)
dataLabels = Alias("dLbls")
bubble3D = NestedBool(allow_none=True)
bubbleScale = NestedMinMax(min=0, max=300, allow_none=True)
showNegBubbles = NestedBool(allow_none=True)
sizeRepresents = NestedNoneSet(values=(['area', 'w']))
extLst = Typed(expected_type=ExtensionList, allow_none=True)
x_axis = Typed(expected_type=NumericAxis)
y_axis = Typed(expected_type=NumericAxis)
_series_type = "bubble"
__elements__ = ('varyColors', 'ser', 'dLbls', 'bubble3D', 'bubbleScale',
'showNegBubbles', 'sizeRepresents', 'axId')
def __init__(self,
varyColors=None,
ser=(),
dLbls=None,
bubble3D=None,
bubbleScale=None,
showNegBubbles=None,
sizeRepresents=None,
extLst=None,
**kw
):
self.varyColors = varyColors
self.ser = ser
self.dLbls = dLbls
self.bubble3D = bubble3D
self.bubbleScale = bubbleScale
self.showNegBubbles = showNegBubbles
self.sizeRepresents = sizeRepresents
self.x_axis = NumericAxis(axId=10, crossAx=20)
self.y_axis = NumericAxis(axId=20, crossAx=10)
super(BubbleChart, self).__init__(**kw)

View File

@ -0,0 +1,195 @@
# Copyright (c) 2010-2022 openpyxl
"""
Enclosing chart object. The various chart types are actually child objects.
Will probably need to call this indirectly
"""
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
String,
Alias,
)
from openpyxl.descriptors.excel import (
ExtensionList,
Relation
)
from openpyxl.descriptors.nested import (
NestedBool,
NestedNoneSet,
NestedString,
NestedMinMax,
)
from openpyxl.descriptors.sequence import NestedSequence
from openpyxl.xml.constants import CHART_NS
from openpyxl.drawing.colors import ColorMapping
from .text import RichText
from .shapes import GraphicalProperties
from .legend import Legend
from ._3d import _3DBase
from .plotarea import PlotArea
from .title import Title
from .pivot import (
PivotFormat,
PivotSource,
)
from .print_settings import PrintSettings
class ChartContainer(Serialisable):
tagname = "chart"
title = Typed(expected_type=Title, allow_none=True)
autoTitleDeleted = NestedBool(allow_none=True)
pivotFmts = NestedSequence(expected_type=PivotFormat)
view3D = _3DBase.view3D
floor = _3DBase.floor
sideWall = _3DBase.sideWall
backWall = _3DBase.backWall
plotArea = Typed(expected_type=PlotArea, )
legend = Typed(expected_type=Legend, allow_none=True)
plotVisOnly = NestedBool()
dispBlanksAs = NestedNoneSet(values=(['span', 'gap', 'zero']))
showDLblsOverMax = NestedBool(allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('title', 'autoTitleDeleted', 'pivotFmts', 'view3D',
'floor', 'sideWall', 'backWall', 'plotArea', 'legend', 'plotVisOnly',
'dispBlanksAs', 'showDLblsOverMax')
def __init__(self,
title=None,
autoTitleDeleted=None,
pivotFmts=(),
view3D=None,
floor=None,
sideWall=None,
backWall=None,
plotArea=None,
legend=None,
plotVisOnly=True,
dispBlanksAs="gap",
showDLblsOverMax=None,
extLst=None,
):
self.title = title
self.autoTitleDeleted = autoTitleDeleted
self.pivotFmts = pivotFmts
self.view3D = view3D
self.floor = floor
self.sideWall = sideWall
self.backWall = backWall
if plotArea is None:
plotArea = PlotArea()
self.plotArea = plotArea
self.legend = legend
self.plotVisOnly = plotVisOnly
self.dispBlanksAs = dispBlanksAs
self.showDLblsOverMax = showDLblsOverMax
class Protection(Serialisable):
tagname = "protection"
chartObject = NestedBool(allow_none=True)
data = NestedBool(allow_none=True)
formatting = NestedBool(allow_none=True)
selection = NestedBool(allow_none=True)
userInterface = NestedBool(allow_none=True)
__elements__ = ("chartObject", "data", "formatting", "selection", "userInterface")
def __init__(self,
chartObject=None,
data=None,
formatting=None,
selection=None,
userInterface=None,
):
self.chartObject = chartObject
self.data = data
self.formatting = formatting
self.selection = selection
self.userInterface = userInterface
class ExternalData(Serialisable):
tagname = "externalData"
autoUpdate = NestedBool(allow_none=True)
id = String() # Needs namespace
def __init__(self,
autoUpdate=None,
id=None
):
self.autoUpdate = autoUpdate
self.id = id
class ChartSpace(Serialisable):
tagname = "chartSpace"
date1904 = NestedBool(allow_none=True)
lang = NestedString(allow_none=True)
roundedCorners = NestedBool(allow_none=True)
style = NestedMinMax(allow_none=True, min=1, max=48)
clrMapOvr = Typed(expected_type=ColorMapping, allow_none=True)
pivotSource = Typed(expected_type=PivotSource, allow_none=True)
protection = Typed(expected_type=Protection, allow_none=True)
chart = Typed(expected_type=ChartContainer)
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias("spPr")
txPr = Typed(expected_type=RichText, allow_none=True)
textProperties = Alias("txPr")
externalData = Typed(expected_type=ExternalData, allow_none=True)
printSettings = Typed(expected_type=PrintSettings, allow_none=True)
userShapes = Relation()
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('date1904', 'lang', 'roundedCorners', 'style',
'clrMapOvr', 'pivotSource', 'protection', 'chart', 'spPr', 'txPr',
'externalData', 'printSettings', 'userShapes')
def __init__(self,
date1904=None,
lang=None,
roundedCorners=None,
style=None,
clrMapOvr=None,
pivotSource=None,
protection=None,
chart=None,
spPr=None,
txPr=None,
externalData=None,
printSettings=None,
userShapes=None,
extLst=None,
):
self.date1904 = date1904
self.lang = lang
self.roundedCorners = roundedCorners
self.style = style
self.clrMapOvr = clrMapOvr
self.pivotSource = pivotSource
self.protection = protection
self.chart = chart
self.spPr = spPr
self.txPr = txPr
self.externalData = externalData
self.printSettings = printSettings
self.userShapes = userShapes
def to_tree(self, tagname=None, idx=None, namespace=None):
tree = super(ChartSpace, self).to_tree()
tree.set("xmlns", CHART_NS)
return tree

View File

@ -0,0 +1,246 @@
"""
Collection of utility primitives for charts.
"""
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Bool,
Typed,
Alias,
String,
Integer,
Sequence,
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.nested import (
NestedString,
NestedText,
NestedInteger,
)
class NumFmt(Serialisable):
formatCode = String()
sourceLinked = Bool()
def __init__(self,
formatCode=None,
sourceLinked=False
):
self.formatCode = formatCode
self.sourceLinked = sourceLinked
class NumberValueDescriptor(NestedText):
"""
Data should be numerical but isn't always :-/
"""
allow_none = True
def __set__(self, instance, value):
if value == "#N/A":
self.expected_type = str
else:
self.expected_type = float
super(NumberValueDescriptor, self).__set__(instance, value)
class NumVal(Serialisable):
idx = Integer()
formatCode = NestedText(allow_none=True, expected_type=str)
v = NumberValueDescriptor()
def __init__(self,
idx=None,
formatCode=None,
v=None,
):
self.idx = idx
self.formatCode = formatCode
self.v = v
class NumData(Serialisable):
formatCode = NestedText(expected_type=str, allow_none=True)
ptCount = NestedInteger(allow_none=True)
pt = Sequence(expected_type=NumVal)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('formatCode', 'ptCount', 'pt')
def __init__(self,
formatCode=None,
ptCount=None,
pt=(),
extLst=None,
):
self.formatCode = formatCode
self.ptCount = ptCount
self.pt = pt
class NumRef(Serialisable):
f = NestedText(expected_type=str)
ref = Alias('f')
numCache = Typed(expected_type=NumData, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('f', 'numCache')
def __init__(self,
f=None,
numCache=None,
extLst=None,
):
self.f = f
self.numCache = numCache
class StrVal(Serialisable):
tagname = "strVal"
idx = Integer()
v = NestedText(expected_type=str)
def __init__(self,
idx=0,
v=None,
):
self.idx = idx
self.v = v
class StrData(Serialisable):
tagname = "strData"
ptCount = NestedInteger(allow_none=True)
pt = Sequence(expected_type=StrVal)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('ptCount', 'pt')
def __init__(self,
ptCount=None,
pt=(),
extLst=None,
):
self.ptCount = ptCount
self.pt = pt
class StrRef(Serialisable):
tagname = "strRef"
f = NestedText(expected_type=str, allow_none=True)
strCache = Typed(expected_type=StrData, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('f', 'strCache')
def __init__(self,
f=None,
strCache=None,
extLst=None,
):
self.f = f
self.strCache = strCache
class NumDataSource(Serialisable):
numRef = Typed(expected_type=NumRef, allow_none=True)
numLit = Typed(expected_type=NumData, allow_none=True)
def __init__(self,
numRef=None,
numLit=None,
):
self.numRef = numRef
self.numLit = numLit
class Level(Serialisable):
tagname = "lvl"
pt = Sequence(expected_type=StrVal)
__elements__ = ('pt',)
def __init__(self,
pt=(),
):
self.pt = pt
class MultiLevelStrData(Serialisable):
tagname = "multiLvlStrData"
ptCount = Integer(allow_none=True)
lvl = Sequence(expected_type=Level)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('ptCount', 'lvl',)
def __init__(self,
ptCount=None,
lvl=(),
extLst=None,
):
self.ptCount = ptCount
self.lvl = lvl
class MultiLevelStrRef(Serialisable):
tagname = "multiLvlStrRef"
f = NestedText(expected_type=str)
multiLvlStrCache = Typed(expected_type=MultiLevelStrData, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('multiLvlStrCache', 'f')
def __init__(self,
f=None,
multiLvlStrCache=None,
extLst=None,
):
self.f = f
self.multiLvlStrCache = multiLvlStrCache
class AxDataSource(Serialisable):
tagname = "cat"
numRef = Typed(expected_type=NumRef, allow_none=True)
numLit = Typed(expected_type=NumData, allow_none=True)
strRef = Typed(expected_type=StrRef, allow_none=True)
strLit = Typed(expected_type=StrData, allow_none=True)
multiLvlStrRef = Typed(expected_type=MultiLevelStrRef, allow_none=True)
def __init__(self,
numRef=None,
numLit=None,
strRef=None,
strLit=None,
multiLvlStrRef=None,
):
if not any([numLit, numRef, strRef, strLit, multiLvlStrRef]):
raise TypeError("A data source must be provided")
self.numRef = numRef
self.numLit = numLit
self.strRef = strRef
self.strLit = strLit
self.multiLvlStrRef = multiLvlStrRef

View File

@ -0,0 +1,43 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.nested import (
NestedMinMax
)
from openpyxl.descriptors import Typed
from .data_source import NumFmt
"""
Utility descriptors for the chart module.
For convenience but also clarity.
"""
class NestedGapAmount(NestedMinMax):
allow_none = True
min = 0
max = 500
class NestedOverlap(NestedMinMax):
allow_none = True
min = -100
max = 100
class NumberFormatDescriptor(Typed):
"""
Allow direct assignment of format code
"""
expected_type = NumFmt
allow_none = True
def __set__(self, instance, value):
if isinstance(value, str):
value = NumFmt(value)
super(NumberFormatDescriptor, self).__set__(instance, value)

View File

@ -0,0 +1,62 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Float,
Set,
Alias
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.nested import (
NestedNoneSet,
NestedSet,
NestedBool,
NestedFloat,
)
from .data_source import NumDataSource
from .shapes import GraphicalProperties
class ErrorBars(Serialisable):
tagname = "errBars"
errDir = NestedNoneSet(values=(['x', 'y']))
direction = Alias("errDir")
errBarType = NestedSet(values=(['both', 'minus', 'plus']))
style = Alias("errBarType")
errValType = NestedSet(values=(['cust', 'fixedVal', 'percentage', 'stdDev', 'stdErr']))
size = Alias("errValType")
noEndCap = NestedBool(nested=True, allow_none=True)
plus = Typed(expected_type=NumDataSource, allow_none=True)
minus = Typed(expected_type=NumDataSource, allow_none=True)
val = NestedFloat(allow_none=True)
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias("spPr")
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('errDir','errBarType', 'errValType', 'noEndCap','minus', 'plus', 'val', 'spPr')
def __init__(self,
errDir=None,
errBarType="both",
errValType="fixedVal",
noEndCap=None,
plus=None,
minus=None,
val=None,
spPr=None,
extLst=None,
):
self.errDir = errDir
self.errBarType = errBarType
self.errValType = errValType
self.noEndCap = noEndCap
self.plus = plus
self.minus = minus
self.val = val
self.spPr = spPr

View File

@ -0,0 +1,127 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Sequence,
Alias,
Typed
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.nested import (
NestedNoneSet,
NestedBool,
NestedString,
NestedInteger,
)
from .shapes import GraphicalProperties
from .text import RichText
class _DataLabelBase(Serialisable):
numFmt = NestedString(allow_none=True, attribute="formatCode")
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias('spPr')
txPr = Typed(expected_type=RichText, allow_none=True)
textProperties = Alias('txPr')
dLblPos = NestedNoneSet(values=['bestFit', 'b', 'ctr', 'inBase', 'inEnd',
'l', 'outEnd', 'r', 't'])
position = Alias('dLblPos')
showLegendKey = NestedBool(allow_none=True)
showVal = NestedBool(allow_none=True)
showCatName = NestedBool(allow_none=True)
showSerName = NestedBool(allow_none=True)
showPercent = NestedBool(allow_none=True)
showBubbleSize = NestedBool(allow_none=True)
showLeaderLines = NestedBool(allow_none=True)
separator = NestedString(allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ("numFmt", "spPr", "txPr", "dLblPos", "showLegendKey",
"showVal", "showCatName", "showSerName", "showPercent", "showBubbleSize",
"showLeaderLines", "separator")
def __init__(self,
numFmt=None,
spPr=None,
txPr=None,
dLblPos=None,
showLegendKey=None,
showVal=None,
showCatName=None,
showSerName=None,
showPercent=None,
showBubbleSize=None,
showLeaderLines=None,
separator=None,
extLst=None,
):
self.numFmt = numFmt
self.spPr = spPr
self.txPr = txPr
self.dLblPos = dLblPos
self.showLegendKey = showLegendKey
self.showVal = showVal
self.showCatName = showCatName
self.showSerName = showSerName
self.showPercent = showPercent
self.showBubbleSize = showBubbleSize
self.showLeaderLines = showLeaderLines
self.separator = separator
class DataLabel(_DataLabelBase):
tagname = "dLbl"
idx = NestedInteger()
numFmt = _DataLabelBase.numFmt
spPr = _DataLabelBase.spPr
txPr = _DataLabelBase.txPr
dLblPos = _DataLabelBase.dLblPos
showLegendKey = _DataLabelBase.showLegendKey
showVal = _DataLabelBase.showVal
showCatName = _DataLabelBase.showCatName
showSerName = _DataLabelBase.showSerName
showPercent = _DataLabelBase.showPercent
showBubbleSize = _DataLabelBase.showBubbleSize
showLeaderLines = _DataLabelBase.showLeaderLines
separator = _DataLabelBase.separator
extLst = _DataLabelBase.extLst
__elements__ = ("idx",) + _DataLabelBase.__elements__
def __init__(self, idx=0, **kw ):
self.idx = idx
super(DataLabel, self).__init__(**kw)
class DataLabelList(_DataLabelBase):
tagname = "dLbls"
dLbl = Sequence(expected_type=DataLabel, allow_none=True)
delete = NestedBool(allow_none=True)
numFmt = _DataLabelBase.numFmt
spPr = _DataLabelBase.spPr
txPr = _DataLabelBase.txPr
dLblPos = _DataLabelBase.dLblPos
showLegendKey = _DataLabelBase.showLegendKey
showVal = _DataLabelBase.showVal
showCatName = _DataLabelBase.showCatName
showSerName = _DataLabelBase.showSerName
showPercent = _DataLabelBase.showPercent
showBubbleSize = _DataLabelBase.showBubbleSize
showLeaderLines = _DataLabelBase.showLeaderLines
separator = _DataLabelBase.separator
extLst = _DataLabelBase.extLst
__elements__ = ("delete", "dLbl",) + _DataLabelBase.__elements__
def __init__(self, dLbl=(), delete=None, **kw):
self.dLbl = dLbl
self.delete = delete
super(DataLabelList, self).__init__(**kw)

View File

@ -0,0 +1,74 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
NoneSet,
Float,
Typed,
Alias,
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.nested import (
NestedNoneSet,
NestedSet,
NestedMinMax,
)
class ManualLayout(Serialisable):
tagname = "manualLayout"
layoutTarget = NestedNoneSet(values=(['inner', 'outer']))
xMode = NestedNoneSet(values=(['edge', 'factor']))
yMode = NestedNoneSet(values=(['edge', 'factor']))
wMode = NestedSet(values=(['edge', 'factor']))
hMode = NestedSet(values=(['edge', 'factor']))
x = NestedMinMax(min=-1, max=1, allow_none=True)
y = NestedMinMax(min=-1, max=1, allow_none=True)
w = NestedMinMax(min=0, max=1, allow_none=True)
width = Alias('w')
h = NestedMinMax(min=0, max=1, allow_none=True)
height = Alias('h')
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('layoutTarget', 'xMode', 'yMode', 'wMode', 'hMode', 'x',
'y', 'w', 'h')
def __init__(self,
layoutTarget=None,
xMode=None,
yMode=None,
wMode="factor",
hMode="factor",
x=None,
y=None,
w=None,
h=None,
extLst=None,
):
self.layoutTarget = layoutTarget
self.xMode = xMode
self.yMode = yMode
self.wMode = wMode
self.hMode = hMode
self.x = x
self.y = y
self.w = w
self.h = h
class Layout(Serialisable):
tagname = "layout"
manualLayout = Typed(expected_type=ManualLayout, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('manualLayout',)
def __init__(self,
manualLayout=None,
extLst=None,
):
self.manualLayout = manualLayout

View File

@ -0,0 +1,75 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Integer,
Alias,
Sequence,
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.nested import (
NestedBool,
NestedSet,
NestedInteger
)
from .layout import Layout
from .shapes import GraphicalProperties
from .text import RichText
class LegendEntry(Serialisable):
tagname = "legendEntry"
idx = NestedInteger()
delete = NestedBool()
txPr = Typed(expected_type=RichText, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('idx', 'delete', 'txPr')
def __init__(self,
idx=0,
delete=False,
txPr=None,
extLst=None,
):
self.idx = idx
self.delete = delete
self.txPr = txPr
class Legend(Serialisable):
tagname = "legend"
legendPos = NestedSet(values=(['b', 'tr', 'l', 'r', 't']))
position = Alias('legendPos')
legendEntry = Sequence(expected_type=LegendEntry)
layout = Typed(expected_type=Layout, allow_none=True)
overlay = NestedBool(allow_none=True)
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias('spPr')
txPr = Typed(expected_type=RichText, allow_none=True)
textProperties = Alias('txPr')
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('legendPos', 'legendEntry', 'layout', 'overlay', 'spPr', 'txPr',)
def __init__(self,
legendPos="r",
legendEntry=(),
layout=None,
overlay=None,
spPr=None,
txPr=None,
extLst=None,
):
self.legendPos = legendPos
self.legendEntry = legendEntry
self.layout = layout
self.overlay = overlay
self.spPr = spPr
self.txPr = txPr

View File

@ -0,0 +1,129 @@
#Autogenerated schema
from openpyxl.descriptors import (
Typed,
Sequence,
Alias,
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.nested import (
NestedSet,
NestedBool,
)
from ._chart import ChartBase
from .updown_bars import UpDownBars
from .descriptors import NestedGapAmount
from .axis import TextAxis, NumericAxis, SeriesAxis, ChartLines, _BaseAxis
from .label import DataLabelList
from .series import Series
class _LineChartBase(ChartBase):
grouping = NestedSet(values=(['percentStacked', 'standard', 'stacked']))
varyColors = NestedBool(allow_none=True)
ser = Sequence(expected_type=Series, allow_none=True)
dLbls = Typed(expected_type=DataLabelList, allow_none=True)
dataLabels = Alias("dLbls")
dropLines = Typed(expected_type=ChartLines, allow_none=True)
_series_type = "line"
__elements__ = ('grouping', 'varyColors', 'ser', 'dLbls', 'dropLines')
def __init__(self,
grouping="standard",
varyColors=None,
ser=(),
dLbls=None,
dropLines=None,
**kw
):
self.grouping = grouping
self.varyColors = varyColors
self.ser = ser
self.dLbls = dLbls
self.dropLines = dropLines
super(_LineChartBase, self).__init__(**kw)
class LineChart(_LineChartBase):
tagname = "lineChart"
grouping = _LineChartBase.grouping
varyColors = _LineChartBase.varyColors
ser = _LineChartBase.ser
dLbls = _LineChartBase.dLbls
dropLines =_LineChartBase.dropLines
hiLowLines = Typed(expected_type=ChartLines, allow_none=True)
upDownBars = Typed(expected_type=UpDownBars, allow_none=True)
marker = NestedBool(allow_none=True)
smooth = NestedBool(allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
x_axis = Typed(expected_type=_BaseAxis)
y_axis = Typed(expected_type=NumericAxis)
__elements__ = _LineChartBase.__elements__ + ('hiLowLines', 'upDownBars', 'marker', 'smooth', 'axId')
def __init__(self,
hiLowLines=None,
upDownBars=None,
marker=None,
smooth=None,
extLst=None,
**kw
):
self.hiLowLines = hiLowLines
self.upDownBars = upDownBars
self.marker = marker
self.smooth = smooth
self.x_axis = TextAxis()
self.y_axis = NumericAxis()
super(LineChart, self).__init__(**kw)
class LineChart3D(_LineChartBase):
tagname = "line3DChart"
grouping = _LineChartBase.grouping
varyColors = _LineChartBase.varyColors
ser = _LineChartBase.ser
dLbls = _LineChartBase.dLbls
dropLines =_LineChartBase.dropLines
gapDepth = NestedGapAmount()
hiLowLines = Typed(expected_type=ChartLines, allow_none=True)
upDownBars = Typed(expected_type=UpDownBars, allow_none=True)
marker = NestedBool(allow_none=True)
smooth = NestedBool(allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
x_axis = Typed(expected_type=TextAxis)
y_axis = Typed(expected_type=NumericAxis)
z_axis = Typed(expected_type=SeriesAxis)
__elements__ = _LineChartBase.__elements__ + ('gapDepth', 'hiLowLines',
'upDownBars', 'marker', 'smooth', 'axId')
def __init__(self,
gapDepth=None,
hiLowLines=None,
upDownBars=None,
marker=None,
smooth=None,
**kw
):
self.gapDepth = gapDepth
self.hiLowLines = hiLowLines
self.upDownBars = upDownBars
self.marker = marker
self.smooth = smooth
self.x_axis = TextAxis()
self.y_axis = NumericAxis()
self.z_axis = SeriesAxis()
super(LineChart3D, self).__init__(**kw)

View File

@ -0,0 +1,90 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Alias,
)
from openpyxl.descriptors.excel import(
ExtensionList,
_explicit_none,
)
from openpyxl.descriptors.nested import (
NestedBool,
NestedInteger,
NestedMinMax,
NestedNoneSet,
)
from .layout import Layout
from .picture import PictureOptions
from .shapes import *
from .text import *
from .error_bar import *
class Marker(Serialisable):
tagname = "marker"
symbol = NestedNoneSet(values=(['circle', 'dash', 'diamond', 'dot', 'picture',
'plus', 'square', 'star', 'triangle', 'x', 'auto']),
to_tree=_explicit_none)
size = NestedMinMax(min=2, max=72, allow_none=True)
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias('spPr')
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('symbol', 'size', 'spPr')
def __init__(self,
symbol=None,
size=None,
spPr=None,
extLst=None,
):
self.symbol = symbol
self.size = size
if spPr is None:
spPr = GraphicalProperties()
self.spPr = spPr
class DataPoint(Serialisable):
tagname = "dPt"
idx = NestedInteger()
invertIfNegative = NestedBool(allow_none=True)
marker = Typed(expected_type=Marker, allow_none=True)
bubble3D = NestedBool(allow_none=True)
explosion = NestedInteger(allow_none=True)
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias('spPr')
pictureOptions = Typed(expected_type=PictureOptions, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('idx', 'invertIfNegative', 'marker', 'bubble3D',
'explosion', 'spPr', 'pictureOptions')
def __init__(self,
idx=None,
invertIfNegative=None,
marker=None,
bubble3D=None,
explosion=None,
spPr=None,
pictureOptions=None,
extLst=None,
):
self.idx = idx
self.invertIfNegative = invertIfNegative
self.marker = marker
self.bubble3D = bubble3D
self.explosion = explosion
if spPr is None:
spPr = GraphicalProperties()
self.spPr = spPr
self.pictureOptions = pictureOptions

View File

@ -0,0 +1,35 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors.nested import (
NestedBool,
NestedFloat,
NestedMinMax,
NestedNoneSet,
)
class PictureOptions(Serialisable):
tagname = "pictureOptions"
applyToFront = NestedBool(allow_none=True, nested=True)
applyToSides = NestedBool(allow_none=True, nested=True)
applyToEnd = NestedBool(allow_none=True, nested=True)
pictureFormat = NestedNoneSet(values=(['stretch', 'stack', 'stackScale']), nested=True)
pictureStackUnit = NestedFloat(allow_none=True, nested=True)
__elements__ = ('applyToFront', 'applyToSides', 'applyToEnd', 'pictureFormat', 'pictureStackUnit')
def __init__(self,
applyToFront=None,
applyToSides=None,
applyToEnd=None,
pictureFormat=None,
pictureStackUnit=None,
):
self.applyToFront = applyToFront
self.applyToSides = applyToSides
self.applyToEnd = applyToEnd
self.pictureFormat = pictureFormat
self.pictureStackUnit = pictureStackUnit

View File

@ -0,0 +1,177 @@
#Autogenerated schema
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Bool,
MinMax,
Integer,
NoneSet,
Float,
Alias,
Sequence,
)
from openpyxl.descriptors.excel import ExtensionList, Percentage
from openpyxl.descriptors.nested import (
NestedBool,
NestedMinMax,
NestedInteger,
NestedFloat,
NestedNoneSet,
NestedSet,
)
from openpyxl.descriptors.sequence import ValueSequence
from ._chart import ChartBase
from .axis import ChartLines
from .descriptors import NestedGapAmount
from .series import Series
from .label import DataLabelList
class _PieChartBase(ChartBase):
varyColors = NestedBool(allow_none=True)
ser = Sequence(expected_type=Series, allow_none=True)
dLbls = Typed(expected_type=DataLabelList, allow_none=True)
dataLabels = Alias("dLbls")
_series_type = "pie"
__elements__ = ('varyColors', 'ser', 'dLbls')
def __init__(self,
varyColors=True,
ser=(),
dLbls=None,
):
self.varyColors = varyColors
self.ser = ser
self.dLbls = dLbls
super(_PieChartBase, self).__init__()
class PieChart(_PieChartBase):
tagname = "pieChart"
varyColors = _PieChartBase.varyColors
ser = _PieChartBase.ser
dLbls = _PieChartBase.dLbls
firstSliceAng = NestedMinMax(min=0, max=360)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = _PieChartBase.__elements__ + ('firstSliceAng', )
def __init__(self,
firstSliceAng=0,
extLst=None,
**kw
):
self.firstSliceAng = firstSliceAng
super(PieChart, self).__init__(**kw)
class PieChart3D(_PieChartBase):
tagname = "pie3DChart"
varyColors = _PieChartBase.varyColors
ser = _PieChartBase.ser
dLbls = _PieChartBase.dLbls
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = _PieChartBase.__elements__
class DoughnutChart(_PieChartBase):
tagname = "doughnutChart"
varyColors = _PieChartBase.varyColors
ser = _PieChartBase.ser
dLbls = _PieChartBase.dLbls
firstSliceAng = NestedMinMax(min=0, max=360)
holeSize = NestedMinMax(min=1, max=90, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = _PieChartBase.__elements__ + ('firstSliceAng', 'holeSize')
def __init__(self,
firstSliceAng=0,
holeSize=10,
extLst=None,
**kw
):
self.firstSliceAng = firstSliceAng
self.holeSize = holeSize
super(DoughnutChart, self).__init__(**kw)
class CustomSplit(Serialisable):
tagname = "custSplit"
secondPiePt = ValueSequence(expected_type=int)
__elements__ = ('secondPiePt',)
def __init__(self,
secondPiePt=(),
):
self.secondPiePt = secondPiePt
class ProjectedPieChart(_PieChartBase):
"""
From the spec 21.2.2.126
This element contains the pie of pie or bar of pie series on this
chart. Only the first series shall be displayed. The splitType element
shall determine whether the splitPos and custSplit elements apply.
"""
tagname = "ofPieChart"
varyColors = _PieChartBase.varyColors
ser = _PieChartBase.ser
dLbls = _PieChartBase.dLbls
ofPieType = NestedSet(values=(['pie', 'bar']))
type = Alias('ofPieType')
gapWidth = NestedGapAmount()
splitType = NestedNoneSet(values=(['auto', 'cust', 'percent', 'pos', 'val']))
splitPos = NestedFloat(allow_none=True)
custSplit = Typed(expected_type=CustomSplit, allow_none=True)
secondPieSize = NestedMinMax(min=5, max=200, allow_none=True)
serLines = Typed(expected_type=ChartLines, allow_none=True)
join_lines = Alias('serLines')
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = _PieChartBase.__elements__ + ('ofPieType', 'gapWidth',
'splitType', 'splitPos', 'custSplit', 'secondPieSize', 'serLines')
def __init__(self,
ofPieType="pie",
gapWidth=None,
splitType="auto",
splitPos=None,
custSplit=None,
secondPieSize=75,
serLines=None,
extLst=None,
**kw
):
self.ofPieType = ofPieType
self.gapWidth = gapWidth
self.splitType = splitType
self.splitPos = splitPos
self.custSplit = custSplit
self.secondPieSize = secondPieSize
if serLines is None:
self.serLines = ChartLines()
super(ProjectedPieChart, self).__init__(**kw)

View File

@ -0,0 +1,65 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Alias,
Typed,
)
from openpyxl.descriptors.nested import NestedInteger, NestedText
from openpyxl.descriptors.excel import ExtensionList
from .label import DataLabel
from .marker import Marker
from .shapes import GraphicalProperties
from .text import RichText
class PivotSource(Serialisable):
tagname = "pivotSource"
name = NestedText(expected_type=str)
fmtId = NestedInteger(expected_type=int)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('name', 'fmtId')
def __init__(self,
name=None,
fmtId=None,
extLst=None,
):
self.name = name
self.fmtId = fmtId
class PivotFormat(Serialisable):
tagname = "pivotFmt"
idx = NestedInteger(nested=True)
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias("spPr")
txPr = Typed(expected_type=RichText, allow_none=True)
TextBody = Alias("txPr")
marker = Typed(expected_type=Marker, allow_none=True)
dLbl = Typed(expected_type=DataLabel, allow_none=True)
DataLabel = Alias("dLbl")
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('idx', 'spPr', 'txPr', 'marker', 'dLbl')
def __init__(self,
idx=0,
spPr=None,
txPr=None,
marker=None,
dLbl=None,
extLst=None,
):
self.idx = idx
self.spPr = spPr
self.txPr = txPr
self.marker = marker
self.dLbl = dLbl

View File

@ -0,0 +1,162 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Alias,
)
from openpyxl.descriptors.excel import (
ExtensionList,
)
from openpyxl.descriptors.sequence import (
MultiSequence,
MultiSequencePart,
)
from openpyxl.descriptors.nested import (
NestedBool,
)
from ._3d import _3DBase
from .area_chart import AreaChart, AreaChart3D
from .bar_chart import BarChart, BarChart3D
from .bubble_chart import BubbleChart
from .line_chart import LineChart, LineChart3D
from .pie_chart import PieChart, PieChart3D, ProjectedPieChart, DoughnutChart
from .radar_chart import RadarChart
from .scatter_chart import ScatterChart
from .stock_chart import StockChart
from .surface_chart import SurfaceChart, SurfaceChart3D
from .layout import Layout
from .shapes import GraphicalProperties
from .text import RichText
from .axis import (
NumericAxis,
TextAxis,
SeriesAxis,
DateAxis,
)
class DataTable(Serialisable):
tagname = "dTable"
showHorzBorder = NestedBool(allow_none=True)
showVertBorder = NestedBool(allow_none=True)
showOutline = NestedBool(allow_none=True)
showKeys = NestedBool(allow_none=True)
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias('spPr')
txPr = Typed(expected_type=RichText, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('showHorzBorder', 'showVertBorder', 'showOutline',
'showKeys', 'spPr', 'txPr')
def __init__(self,
showHorzBorder=None,
showVertBorder=None,
showOutline=None,
showKeys=None,
spPr=None,
txPr=None,
extLst=None,
):
self.showHorzBorder = showHorzBorder
self.showVertBorder = showVertBorder
self.showOutline = showOutline
self.showKeys = showKeys
self.spPr = spPr
self.txPr = txPr
class PlotArea(Serialisable):
tagname = "plotArea"
layout = Typed(expected_type=Layout, allow_none=True)
dTable = Typed(expected_type=DataTable, allow_none=True)
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias("spPr")
extLst = Typed(expected_type=ExtensionList, allow_none=True)
# at least one chart
_charts = MultiSequence()
areaChart = MultiSequencePart(expected_type=AreaChart, store="_charts")
area3DChart = MultiSequencePart(expected_type=AreaChart3D, store="_charts")
lineChart = MultiSequencePart(expected_type=LineChart, store="_charts")
line3DChart = MultiSequencePart(expected_type=LineChart3D, store="_charts")
stockChart = MultiSequencePart(expected_type=StockChart, store="_charts")
radarChart = MultiSequencePart(expected_type=RadarChart, store="_charts")
scatterChart = MultiSequencePart(expected_type=ScatterChart, store="_charts")
pieChart = MultiSequencePart(expected_type=PieChart, store="_charts")
pie3DChart = MultiSequencePart(expected_type=PieChart3D, store="_charts")
doughnutChart = MultiSequencePart(expected_type=DoughnutChart, store="_charts")
barChart = MultiSequencePart(expected_type=BarChart, store="_charts")
bar3DChart = MultiSequencePart(expected_type=BarChart3D, store="_charts")
ofPieChart = MultiSequencePart(expected_type=ProjectedPieChart, store="_charts")
surfaceChart = MultiSequencePart(expected_type=SurfaceChart, store="_charts")
surface3DChart = MultiSequencePart(expected_type=SurfaceChart3D, store="_charts")
bubbleChart = MultiSequencePart(expected_type=BubbleChart, store="_charts")
# axes
_axes = MultiSequence()
valAx = MultiSequencePart(expected_type=NumericAxis, store="_axes")
catAx = MultiSequencePart(expected_type=TextAxis, store="_axes")
dateAx = MultiSequencePart(expected_type=DateAxis, store="_axes")
serAx = MultiSequencePart(expected_type=SeriesAxis, store="_axes")
__elements__ = ('layout', '_charts', '_axes', 'dTable', 'spPr')
def __init__(self,
layout=None,
dTable=None,
spPr=None,
_charts=(),
_axes=(),
extLst=None,
):
self.layout = layout
self.dTable = dTable
self.spPr = spPr
self._charts = _charts
self._axes = _axes
def to_tree(self, tagname=None, idx=None, namespace=None):
axIds = {ax.axId for ax in self._axes}
for chart in self._charts:
for id, axis in chart._axes.items():
if id not in axIds:
setattr(self, axis.tagname, axis)
axIds.add(id)
return super(PlotArea, self).to_tree(tagname)
@classmethod
def from_tree(cls, node):
self = super(PlotArea, cls).from_tree(node)
axes = dict((axis.axId, axis) for axis in self._axes)
for chart in self._charts:
if isinstance(chart, (ScatterChart, BubbleChart)):
x, y = (axes[axId] for axId in chart.axId)
chart.x_axis = x
chart.y_axis = y
continue
for axId in chart.axId:
axis = axes.get(axId)
if axis is None and isinstance(chart, _3DBase):
# Series Axis can be optional
chart.z_axis = None
continue
if axis.tagname in ("catAx", "dateAx"):
chart.x_axis = axis
elif axis.tagname == "valAx":
chart.y_axis = axis
elif axis.tagname == "serAx":
chart.z_axis = axis
return self

View File

@ -0,0 +1,57 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Float,
Typed,
Alias,
)
from openpyxl.worksheet.page import PrintPageSetup
from openpyxl.worksheet.header_footer import HeaderFooter
class PageMargins(Serialisable):
"""
Identical to openpyxl.worksheet.page.Pagemargins but element names are different :-/
"""
tagname = "pageMargins"
l = Float()
left = Alias('l')
r = Float()
right = Alias('r')
t = Float()
top = Alias('t')
b = Float()
bottom = Alias('b')
header = Float()
footer = Float()
def __init__(self, l=0.75, r=0.75, t=1, b=1, header=0.5, footer=0.5):
self.l = l
self.r = r
self.t = t
self.b = b
self.header = header
self.footer = footer
class PrintSettings(Serialisable):
tagname = "printSettings"
headerFooter = Typed(expected_type=HeaderFooter, allow_none=True)
pageMargins = Typed(expected_type=PageMargins, allow_none=True)
pageSetup = Typed(expected_type=PrintPageSetup, allow_none=True)
__elements__ = ("headerFooter", "pageMargins", "pageMargins")
def __init__(self,
headerFooter=None,
pageMargins=None,
pageSetup=None,
):
self.headerFooter = headerFooter
self.pageMargins = pageMargins
self.pageSetup = pageSetup

View File

@ -0,0 +1,55 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Sequence,
Typed,
Alias,
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.nested import (
NestedBool,
NestedInteger,
NestedSet
)
from ._chart import ChartBase
from .axis import TextAxis, NumericAxis
from .series import Series
from .label import DataLabelList
class RadarChart(ChartBase):
tagname = "radarChart"
radarStyle = NestedSet(values=(['standard', 'marker', 'filled']))
type = Alias("radarStyle")
varyColors = NestedBool(nested=True, allow_none=True)
ser = Sequence(expected_type=Series, allow_none=True)
dLbls = Typed(expected_type=DataLabelList, allow_none=True)
dataLabels = Alias("dLbls")
extLst = Typed(expected_type=ExtensionList, allow_none=True)
_series_type = "radar"
x_axis = Typed(expected_type=TextAxis)
y_axis = Typed(expected_type=NumericAxis)
__elements__ = ('radarStyle', 'varyColors', 'ser', 'dLbls', 'axId')
def __init__(self,
radarStyle="standard",
varyColors=None,
ser=(),
dLbls=None,
extLst=None,
**kw
):
self.radarStyle = radarStyle
self.varyColors = varyColors
self.ser = ser
self.dLbls = dLbls
self.x_axis = TextAxis()
self.y_axis = NumericAxis()
super(RadarChart, self).__init__(**kw)

View File

@ -0,0 +1,29 @@
# Copyright (c) 2010-2022 openpyxl
"""
Read a chart
"""
def read_chart(chartspace):
cs = chartspace
plot = cs.chart.plotArea
chart = plot._charts[0]
chart._charts = plot._charts
chart.title = cs.chart.title
chart.display_blanks = cs.chart.dispBlanksAs
chart.visible_cells_only = cs.chart.plotVisOnly
chart.layout = plot.layout
chart.legend = cs.chart.legend
# 3d attributes
chart.floor = cs.chart.floor
chart.sideWall = cs.chart.sideWall
chart.backWall = cs.chart.backWall
chart.pivotSource = cs.pivotSource
chart.pivotFormats = cs.chart.pivotFmts
chart.idx_base = min((s.idx for s in chart.series), default=0)
chart._reindex()
return chart

View File

@ -0,0 +1,124 @@
# Copyright (c) 2010-2022 openpyxl
from itertools import chain
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
MinMax,
Typed,
String,
Strict,
)
from openpyxl.worksheet.worksheet import Worksheet
from openpyxl.utils import (
get_column_letter,
range_to_tuple,
quote_sheetname
)
class DummyWorksheet:
def __init__(self, title):
self.title = title
class Reference(Strict):
"""
Normalise cell range references
"""
min_row = MinMax(min=1, max=1000000, expected_type=int)
max_row = MinMax(min=1, max=1000000, expected_type=int)
min_col = MinMax(min=1, max=16384, expected_type=int)
max_col = MinMax(min=1, max=16384, expected_type=int)
range_string = String(allow_none=True)
def __init__(self,
worksheet=None,
min_col=None,
min_row=None,
max_col=None,
max_row=None,
range_string=None
):
if range_string is not None:
sheetname, boundaries = range_to_tuple(range_string)
min_col, min_row, max_col, max_row = boundaries
worksheet = DummyWorksheet(sheetname)
self.worksheet = worksheet
self.min_col = min_col
self.min_row = min_row
if max_col is None:
max_col = min_col
self.max_col = max_col
if max_row is None:
max_row = min_row
self.max_row = max_row
def __repr__(self):
return str(self)
def __str__(self):
fmt = u"{0}!${1}${2}:${3}${4}"
if (self.min_col == self.max_col
and self.min_row == self.max_row):
fmt = u"{0}!${1}${2}"
return fmt.format(self.sheetname,
get_column_letter(self.min_col), self.min_row,
get_column_letter(self.max_col), self.max_row
)
__str__ = __str__
def __len__(self):
if self.min_row == self.max_row:
return 1 + self.max_col - self.min_col
return 1 + self.max_row - self.min_row
def __eq__(self, other):
return str(self) == str(other)
@property
def rows(self):
"""
Return all rows in the range
"""
for row in range(self.min_row, self.max_row+1):
yield Reference(self.worksheet, self.min_col, row, self.max_col, row)
@property
def cols(self):
"""
Return all columns in the range
"""
for col in range(self.min_col, self.max_col+1):
yield Reference(self.worksheet, col, self.min_row, col, self.max_row)
def pop(self):
"""
Return and remove the first cell
"""
cell = "{0}{1}".format(get_column_letter(self.min_col), self.min_row)
if self.min_row == self.max_row:
self.min_col += 1
else:
self.min_row += 1
return cell
@property
def sheetname(self):
return quote_sheetname(self.worksheet.title)

View File

@ -0,0 +1,53 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Sequence,
Alias
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.nested import (
NestedNoneSet,
NestedBool,
)
from ._chart import ChartBase
from .axis import NumericAxis
from .series import XYSeries
from .label import DataLabelList
class ScatterChart(ChartBase):
tagname = "scatterChart"
scatterStyle = NestedNoneSet(values=(['line', 'lineMarker', 'marker', 'smooth', 'smoothMarker']))
varyColors = NestedBool(allow_none=True)
ser = Sequence(expected_type=XYSeries, allow_none=True)
dLbls = Typed(expected_type=DataLabelList, allow_none=True)
dataLabels = Alias("dLbls")
extLst = Typed(expected_type=ExtensionList, allow_none=True)
x_axis = Typed(expected_type=NumericAxis)
y_axis = Typed(expected_type=NumericAxis)
_series_type = "scatter"
__elements__ = ('scatterStyle', 'varyColors', 'ser', 'dLbls', 'axId',)
def __init__(self,
scatterStyle=None,
varyColors=None,
ser=(),
dLbls=None,
extLst=None,
**kw
):
self.scatterStyle = scatterStyle
self.varyColors = varyColors
self.ser = ser
self.dLbls = dLbls
self.x_axis = NumericAxis(axId=10, crossAx=20)
self.y_axis = NumericAxis(axId=20, crossAx=10)
super(ScatterChart, self).__init__(**kw)

View File

@ -0,0 +1,197 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
String,
Integer,
Bool,
Alias,
Sequence,
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.nested import (
NestedInteger,
NestedBool,
NestedNoneSet,
NestedText,
)
from .shapes import GraphicalProperties
from .data_source import (
AxDataSource,
NumDataSource,
NumRef,
StrRef,
)
from .error_bar import ErrorBars
from .label import DataLabelList
from .marker import DataPoint, PictureOptions, Marker
from .trendline import Trendline
attribute_mapping = {
'area': ('idx', 'order', 'tx', 'spPr', 'pictureOptions', 'dPt', 'dLbls', 'errBars',
'trendline', 'cat', 'val',),
'bar':('idx', 'order','tx', 'spPr', 'invertIfNegative', 'pictureOptions', 'dPt',
'dLbls', 'trendline', 'errBars', 'cat', 'val', 'shape'),
'bubble':('idx','order', 'tx', 'spPr', 'invertIfNegative', 'dPt', 'dLbls',
'trendline', 'errBars', 'xVal', 'yVal', 'bubbleSize', 'bubble3D'),
'line':('idx', 'order', 'tx', 'spPr', 'marker', 'dPt', 'dLbls', 'trendline',
'errBars', 'cat', 'val', 'smooth'),
'pie':('idx', 'order', 'tx', 'spPr', 'explosion', 'dPt', 'dLbls', 'cat', 'val'),
'radar':('idx', 'order', 'tx', 'spPr', 'marker', 'dPt', 'dLbls', 'cat', 'val'),
'scatter':('idx', 'order', 'tx', 'spPr', 'marker', 'dPt', 'dLbls', 'trendline',
'errBars', 'xVal', 'yVal', 'smooth'),
'surface':('idx', 'order', 'tx', 'spPr', 'cat', 'val'),
}
class SeriesLabel(Serialisable):
tagname = "tx"
strRef = Typed(expected_type=StrRef, allow_none=True)
v = NestedText(expected_type=str, allow_none=True)
value = Alias('v')
__elements__ = ('strRef', 'v')
def __init__(self,
strRef=None,
v=None):
self.strRef = strRef
self.v = v
class Series(Serialisable):
"""
Generic series object. Should not be instantiated directly.
User the chart.Series factory instead.
"""
tagname = "ser"
idx = NestedInteger()
order = NestedInteger()
tx = Typed(expected_type=SeriesLabel, allow_none=True)
title = Alias('tx')
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias('spPr')
# area chart
pictureOptions = Typed(expected_type=PictureOptions, allow_none=True)
dPt = Sequence(expected_type=DataPoint, allow_none=True)
data_points = Alias("dPt")
dLbls = Typed(expected_type=DataLabelList, allow_none=True)
labels = Alias("dLbls")
trendline = Typed(expected_type=Trendline, allow_none=True)
errBars = Typed(expected_type=ErrorBars, allow_none=True)
cat = Typed(expected_type=AxDataSource, allow_none=True)
identifiers = Alias("cat")
val = Typed(expected_type=NumDataSource, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
#bar chart
invertIfNegative = NestedBool(allow_none=True)
shape = NestedNoneSet(values=(['cone', 'coneToMax', 'box', 'cylinder', 'pyramid', 'pyramidToMax']))
#bubble chart
xVal = Typed(expected_type=AxDataSource, allow_none=True)
yVal = Typed(expected_type=NumDataSource, allow_none=True)
bubbleSize = Typed(expected_type=NumDataSource, allow_none=True)
zVal = Alias("bubbleSize")
bubble3D = NestedBool(allow_none=True)
#line chart
marker = Typed(expected_type=Marker, allow_none=True)
smooth = NestedBool(allow_none=True)
#pie chart
explosion = NestedInteger(allow_none=True)
__elements__ = ()
def __init__(self,
idx=0,
order=0,
tx=None,
spPr=None,
pictureOptions=None,
dPt=(),
dLbls=None,
trendline=None,
errBars=None,
cat=None,
val=None,
invertIfNegative=None,
shape=None,
xVal=None,
yVal=None,
bubbleSize=None,
bubble3D=None,
marker=None,
smooth=None,
explosion=None,
extLst=None,
):
self.idx = idx
self.order = order
self.tx = tx
if spPr is None:
spPr = GraphicalProperties()
self.spPr = spPr
self.pictureOptions = pictureOptions
self.dPt = dPt
self.dLbls = dLbls
self.trendline = trendline
self.errBars = errBars
self.cat = cat
self.val = val
self.invertIfNegative = invertIfNegative
self.shape = shape
self.xVal = xVal
self.yVal = yVal
self.bubbleSize = bubbleSize
self.bubble3D = bubble3D
if marker is None:
marker = Marker()
self.marker = marker
self.smooth = smooth
self.explosion = explosion
def to_tree(self, tagname=None, idx=None):
"""The index can need rebasing"""
if idx is not None:
if self.order == self.idx:
self.order = idx # rebase the order if the index has been rebased
self.idx = idx
return super(Series, self).to_tree(tagname)
class XYSeries(Series):
"""Dedicated series for charts that have x and y series"""
idx = Series.idx
order = Series.order
tx = Series.tx
spPr = Series.spPr
dPt = Series.dPt
dLbls = Series.dLbls
trendline = Series.trendline
errBars = Series.errBars
xVal = Series.xVal
yVal = Series.yVal
invertIfNegative = Series.invertIfNegative
bubbleSize = Series.bubbleSize
bubble3D = Series.bubble3D
marker = Series.marker
smooth = Series.smooth

View File

@ -0,0 +1,41 @@
# Copyright (c) 2010-2022 openpyxl
from .data_source import NumDataSource, NumRef, AxDataSource
from .reference import Reference
from .series import Series, XYSeries, SeriesLabel, StrRef
from openpyxl.utils import rows_from_range, quote_sheetname
def SeriesFactory(values, xvalues=None, zvalues=None, title=None, title_from_data=False):
"""
Convenience Factory for creating chart data series.
"""
if not isinstance(values, Reference):
values = Reference(range_string=values)
if title_from_data:
cell = values.pop()
title = u"{0}!{1}".format(values.sheetname, cell)
title = SeriesLabel(strRef=StrRef(title))
elif title is not None:
title = SeriesLabel(v=title)
source = NumDataSource(numRef=NumRef(f=values))
if xvalues is not None:
if not isinstance(xvalues, Reference):
xvalues = Reference(range_string=xvalues)
series = XYSeries()
series.yVal = source
series.xVal = AxDataSource(numRef=NumRef(f=xvalues))
if zvalues is not None:
if not isinstance(zvalues, Reference):
zvalues = Reference(range_string=zvalues)
series.zVal = NumDataSource(NumRef(f=zvalues))
else:
series = Series()
series.val = source
if title is not None:
series.title = title
return series

View File

@ -0,0 +1,89 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Alias
)
from openpyxl.descriptors.nested import (
EmptyTag
)
from openpyxl.drawing.colors import ColorChoiceDescriptor
from openpyxl.drawing.fill import *
from openpyxl.drawing.line import LineProperties
from openpyxl.drawing.geometry import (
Shape3D,
Scene3D,
Transform2D,
CustomGeometry2D,
PresetGeometry2D,
)
class GraphicalProperties(Serialisable):
"""
Somewhat vaguely 21.2.2.197 says this:
This element specifies the formatting for the parent chart element. The
custGeom, prstGeom, scene3d, and xfrm elements are not supported. The
bwMode attribute is not supported.
This doesn't leave much. And the element is used in different places.
"""
tagname = "spPr"
bwMode = NoneSet(values=(['clr', 'auto', 'gray', 'ltGray', 'invGray',
'grayWhite', 'blackGray', 'blackWhite', 'black', 'white', 'hidden']
)
)
xfrm = Typed(expected_type=Transform2D, allow_none=True)
transform = Alias('xfrm')
custGeom = Typed(expected_type=CustomGeometry2D, allow_none=True) # either or
prstGeom = Typed(expected_type=PresetGeometry2D, allow_none=True)
# fills one of
noFill = EmptyTag(namespace=DRAWING_NS)
solidFill = ColorChoiceDescriptor()
gradFill = Typed(expected_type=GradientFillProperties, allow_none=True)
pattFill = Typed(expected_type=PatternFillProperties, allow_none=True)
ln = Typed(expected_type=LineProperties, allow_none=True)
line = Alias('ln')
scene3d = Typed(expected_type=Scene3D, allow_none=True)
sp3d = Typed(expected_type=Shape3D, allow_none=True)
shape3D = Alias('sp3d')
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
__elements__ = ('xfrm', 'prstGeom', 'noFill', 'solidFill', 'gradFill', 'pattFill',
'ln', 'scene3d', 'sp3d')
def __init__(self,
bwMode=None,
xfrm=None,
noFill=None,
solidFill=None,
gradFill=None,
pattFill=None,
ln=None,
scene3d=None,
custGeom=None,
prstGeom=None,
sp3d=None,
extLst=None,
):
self.bwMode = bwMode
self.xfrm = xfrm
self.noFill = noFill
self.solidFill = solidFill
self.gradFill = gradFill
self.pattFill = pattFill
if ln is None:
ln = LineProperties()
self.ln = ln
self.custGeom = custGeom
self.prstGeom = prstGeom
self.scene3d = scene3d
self.sp3d = sp3d

View File

@ -0,0 +1,54 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Sequence,
Alias,
)
from openpyxl.descriptors.excel import ExtensionList
from ._chart import ChartBase
from .axis import TextAxis, NumericAxis, ChartLines
from .updown_bars import UpDownBars
from .label import DataLabelList
from .series import Series
class StockChart(ChartBase):
tagname = "stockChart"
ser = Sequence(expected_type=Series) #min 3, max4
dLbls = Typed(expected_type=DataLabelList, allow_none=True)
dataLabels = Alias('dLbls')
dropLines = Typed(expected_type=ChartLines, allow_none=True)
hiLowLines = Typed(expected_type=ChartLines, allow_none=True)
upDownBars = Typed(expected_type=UpDownBars, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
x_axis = Typed(expected_type=TextAxis)
y_axis = Typed(expected_type=NumericAxis)
_series_type = "line"
__elements__ = ('ser', 'dLbls', 'dropLines', 'hiLowLines', 'upDownBars',
'axId')
def __init__(self,
ser=(),
dLbls=None,
dropLines=None,
hiLowLines=None,
upDownBars=None,
extLst=None,
**kw
):
self.ser = ser
self.dLbls = dLbls
self.dropLines = dropLines
self.hiLowLines = hiLowLines
self.upDownBars = upDownBars
self.x_axis = TextAxis()
self.y_axis = NumericAxis()
super(StockChart, self).__init__(**kw)

View File

@ -0,0 +1,119 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Integer,
Bool,
Alias,
Sequence,
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.nested import (
NestedInteger,
NestedBool,
)
from ._chart import ChartBase
from ._3d import _3DBase
from .axis import TextAxis, NumericAxis, SeriesAxis
from .shapes import GraphicalProperties
from .series import Series
class BandFormat(Serialisable):
tagname = "bandFmt"
idx = NestedInteger()
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias("spPr")
__elements__ = ('idx', 'spPr')
def __init__(self,
idx=0,
spPr=None,
):
self.idx = idx
self.spPr = spPr
class BandFormatList(Serialisable):
tagname = "bandFmts"
bandFmt = Sequence(expected_type=BandFormat, allow_none=True)
__elements__ = ('bandFmt',)
def __init__(self,
bandFmt=(),
):
self.bandFmt = bandFmt
class _SurfaceChartBase(ChartBase):
wireframe = NestedBool(allow_none=True)
ser = Sequence(expected_type=Series, allow_none=True)
bandFmts = Typed(expected_type=BandFormatList, allow_none=True)
_series_type = "surface"
__elements__ = ('wireframe', 'ser', 'bandFmts')
def __init__(self,
wireframe=None,
ser=(),
bandFmts=None,
**kw
):
self.wireframe = wireframe
self.ser = ser
self.bandFmts = bandFmts
super(_SurfaceChartBase, self).__init__(**kw)
class SurfaceChart3D(_SurfaceChartBase, _3DBase):
tagname = "surface3DChart"
wireframe = _SurfaceChartBase.wireframe
ser = _SurfaceChartBase.ser
bandFmts = _SurfaceChartBase.bandFmts
extLst = Typed(expected_type=ExtensionList, allow_none=True)
x_axis = Typed(expected_type=TextAxis)
y_axis = Typed(expected_type=NumericAxis)
z_axis = Typed(expected_type=SeriesAxis)
__elements__ = _SurfaceChartBase.__elements__ + ('axId',)
def __init__(self, **kw):
self.x_axis = TextAxis()
self.y_axis = NumericAxis()
self.z_axis = SeriesAxis()
super(SurfaceChart3D, self).__init__(**kw)
class SurfaceChart(SurfaceChart3D):
tagname = "surfaceChart"
wireframe = _SurfaceChartBase.wireframe
ser = _SurfaceChartBase.ser
bandFmts = _SurfaceChartBase.bandFmts
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = SurfaceChart3D.__elements__
def __init__(self, **kw):
super(SurfaceChart, self).__init__(**kw)
self.y_axis.delete = True
self.view3D.x_rotation = 90
self.view3D.y_rotation = 0
self.view3D.perspective = False
self.view3D.right_angle_axes = False

View File

@ -0,0 +1,78 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Alias,
Sequence,
)
from openpyxl.drawing.text import (
RichTextProperties,
ListStyle,
Paragraph,
)
from .data_source import StrRef
class RichText(Serialisable):
"""
From the specification: 21.2.2.216
This element specifies text formatting. The lstStyle element is not supported.
"""
tagname = "rich"
bodyPr = Typed(expected_type=RichTextProperties)
properties = Alias("bodyPr")
lstStyle = Typed(expected_type=ListStyle, allow_none=True)
p = Sequence(expected_type=Paragraph)
paragraphs = Alias('p')
__elements__ = ("bodyPr", "lstStyle", "p")
def __init__(self,
bodyPr=None,
lstStyle=None,
p=None,
):
if bodyPr is None:
bodyPr = RichTextProperties()
self.bodyPr = bodyPr
self.lstStyle = lstStyle
if p is None:
p = [Paragraph()]
self.p = p
class Text(Serialisable):
"""
The value can be either a cell reference or a text element
If both are present then the reference will be used.
"""
tagname = "tx"
strRef = Typed(expected_type=StrRef, allow_none=True)
rich = Typed(expected_type=RichText, allow_none=True)
__elements__ = ("strRef", "rich")
def __init__(self,
strRef=None,
rich=None
):
self.strRef = strRef
if rich is None:
rich = RichText()
self.rich = rich
def to_tree(self, tagname=None, idx=None, namespace=None):
if self.strRef and self.rich:
self.rich = None # can only have one
return super(Text, self).to_tree(tagname, idx, namespace)

View File

@ -0,0 +1,76 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Alias,
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.nested import NestedBool
from .text import Text, RichText
from .layout import Layout
from .shapes import GraphicalProperties
from openpyxl.drawing.text import (
Paragraph,
RegularTextRun,
LineBreak,
ParagraphProperties,
CharacterProperties,
)
class Title(Serialisable):
tagname = "title"
tx = Typed(expected_type=Text, allow_none=True)
text = Alias('tx')
layout = Typed(expected_type=Layout, allow_none=True)
overlay = NestedBool(allow_none=True)
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias('spPr')
txPr = Typed(expected_type=RichText, allow_none=True)
body = Alias('txPr')
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('tx', 'layout', 'overlay', 'spPr', 'txPr')
def __init__(self,
tx=None,
layout=None,
overlay=None,
spPr=None,
txPr=None,
extLst=None,
):
if tx is None:
tx = Text()
self.tx = tx
self.layout = layout
self.overlay = overlay
self.spPr = spPr
self.txPr = txPr
def title_maker(text):
title = Title()
paraprops = ParagraphProperties()
paraprops.defRPr = CharacterProperties()
paras = [Paragraph(r=[RegularTextRun(t=s)], pPr=paraprops) for s in text.split("\n")]
title.tx.rich.paragraphs = paras
return title
class TitleDescriptor(Typed):
expected_type = Title
allow_none = True
def __set__(self, instance, value):
if isinstance(value, str):
value = title_maker(value)
super(TitleDescriptor, self).__set__(instance, value)

View File

@ -0,0 +1,98 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
String,
Alias
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.nested import (
NestedBool,
NestedInteger,
NestedFloat,
NestedSet
)
from .data_source import NumFmt
from .shapes import GraphicalProperties
from .text import RichText, Text
from .layout import Layout
class TrendlineLabel(Serialisable):
tagname = "trendlineLbl"
layout = Typed(expected_type=Layout, allow_none=True)
tx = Typed(expected_type=Text, allow_none=True)
numFmt = Typed(expected_type=NumFmt, allow_none=True)
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias("spPr")
txPr = Typed(expected_type=RichText, allow_none=True)
textProperties = Alias("txPr")
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('layout', 'tx', 'numFmt', 'spPr', 'txPr')
def __init__(self,
layout=None,
tx=None,
numFmt=None,
spPr=None,
txPr=None,
extLst=None,
):
self.layout = layout
self.tx = tx
self.numFmt = numFmt
self.spPr = spPr
self.txPr = txPr
class Trendline(Serialisable):
tagname = "trendline"
name = String(allow_none=True)
spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
graphicalProperties = Alias('spPr')
trendlineType = NestedSet(values=(['exp', 'linear', 'log', 'movingAvg', 'poly', 'power']))
order = NestedInteger(allow_none=True)
period = NestedInteger(allow_none=True)
forward = NestedFloat(allow_none=True)
backward = NestedFloat(allow_none=True)
intercept = NestedFloat(allow_none=True)
dispRSqr = NestedBool(allow_none=True)
dispEq = NestedBool(allow_none=True)
trendlineLbl = Typed(expected_type=TrendlineLabel, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('name', 'spPr', 'trendlineType', 'order', 'period',
'forward', 'backward', 'intercept', 'dispRSqr', 'dispEq', 'trendlineLbl')
def __init__(self,
name=None,
spPr=None,
trendlineType='linear',
order=None,
period=None,
forward=None,
backward=None,
intercept=None,
dispRSqr=None,
dispEq=None,
trendlineLbl=None,
extLst=None,
):
self.name = name
self.spPr = spPr
self.trendlineType = trendlineType
self.order = order
self.period = period
self.forward = forward
self.backward = backward
self.intercept = intercept
self.dispRSqr = dispRSqr
self.dispEq = dispEq
self.trendlineLbl = trendlineLbl

View File

@ -0,0 +1,31 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import Typed
from openpyxl.descriptors.excel import ExtensionList
from .shapes import GraphicalProperties
from .axis import ChartLines
from .descriptors import NestedGapAmount
class UpDownBars(Serialisable):
tagname = "upbars"
gapWidth = NestedGapAmount()
upBars = Typed(expected_type=ChartLines, allow_none=True)
downBars = Typed(expected_type=ChartLines, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('gapWidth', 'upBars', 'downBars')
def __init__(self,
gapWidth=150,
upBars=None,
downBars=None,
extLst=None,
):
self.gapWidth = gapWidth
self.upBars = upBars
self.downBars = downBars

View File

@ -0,0 +1,3 @@
# Copyright (c) 2010-2022 openpyxl
from .chartsheet import Chartsheet

View File

@ -0,0 +1,109 @@
# Copyright (c) 2010-2022 openpyxl
from weakref import ref
from openpyxl.descriptors import Typed, Set, Alias
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.drawing.spreadsheet_drawing import (
AbsoluteAnchor,
SpreadsheetDrawing,
)
from openpyxl.worksheet.page import (
PageMargins,
PrintPageSetup
)
from openpyxl.packaging.relationship import Relationship, RelationshipList
from openpyxl.worksheet.drawing import Drawing
from openpyxl.worksheet.header_footer import HeaderFooter
from openpyxl.workbook.child import _WorkbookChild
from openpyxl.xml.constants import SHEET_MAIN_NS, REL_NS
from .relation import DrawingHF, SheetBackgroundPicture
from .properties import ChartsheetProperties
from .protection import ChartsheetProtection
from .views import ChartsheetViewList
from .custom import CustomChartsheetViews
from .publish import WebPublishItems
class Chartsheet(_WorkbookChild, Serialisable):
tagname = "chartsheet"
_default_title = "Chart"
_rel_type = "chartsheet"
_path = "/xl/chartsheets/sheet{0}.xml"
mime_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml"
sheetPr = Typed(expected_type=ChartsheetProperties, allow_none=True)
sheetViews = Typed(expected_type=ChartsheetViewList)
sheetProtection = Typed(expected_type=ChartsheetProtection, allow_none=True)
customSheetViews = Typed(expected_type=CustomChartsheetViews, allow_none=True)
pageMargins = Typed(expected_type=PageMargins, allow_none=True)
pageSetup = Typed(expected_type=PrintPageSetup, allow_none=True)
drawing = Typed(expected_type=Drawing, allow_none=True)
drawingHF = Typed(expected_type=DrawingHF, allow_none=True)
picture = Typed(expected_type=SheetBackgroundPicture, allow_none=True)
webPublishItems = Typed(expected_type=WebPublishItems, allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
sheet_state = Set(values=('visible', 'hidden', 'veryHidden'))
headerFooter = Typed(expected_type=HeaderFooter)
HeaderFooter = Alias('headerFooter')
__elements__ = (
'sheetPr', 'sheetViews', 'sheetProtection', 'customSheetViews',
'pageMargins', 'pageSetup', 'headerFooter', 'drawing', 'drawingHF',
'picture', 'webPublishItems')
__attrs__ = ()
def __init__(self,
sheetPr=None,
sheetViews=None,
sheetProtection=None,
customSheetViews=None,
pageMargins=None,
pageSetup=None,
headerFooter=None,
drawing=None,
drawingHF=None,
picture=None,
webPublishItems=None,
extLst=None,
parent=None,
title="",
sheet_state='visible',
):
super(Chartsheet, self).__init__(parent, title)
self._charts = []
self.sheetPr = sheetPr
if sheetViews is None:
sheetViews = ChartsheetViewList()
self.sheetViews = sheetViews
self.sheetProtection = sheetProtection
self.customSheetViews = customSheetViews
self.pageMargins = pageMargins
self.pageSetup = pageSetup
if headerFooter is not None:
self.headerFooter = headerFooter
self.drawing = Drawing("rId1")
self.drawingHF = drawingHF
self.picture = picture
self.webPublishItems = webPublishItems
self.sheet_state = sheet_state
def add_chart(self, chart):
chart.anchor = AbsoluteAnchor()
self._charts.append(chart)
def to_tree(self):
self._drawing = SpreadsheetDrawing()
self._drawing.charts = self._charts
tree = super(Chartsheet, self).to_tree()
if not self.headerFooter:
el = tree.find('headerFooter')
tree.remove(el)
tree.set("xmlns", SHEET_MAIN_NS)
return tree

View File

@ -0,0 +1,61 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.worksheet.header_footer import HeaderFooter
from openpyxl.descriptors import (
Bool,
Integer,
Set,
Typed,
Sequence
)
from openpyxl.descriptors.excel import Guid
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.worksheet.page import (
PageMargins,
PrintPageSetup
)
class CustomChartsheetView(Serialisable):
tagname = "customSheetView"
guid = Guid()
scale = Integer()
state = Set(values=(['visible', 'hidden', 'veryHidden']))
zoomToFit = Bool(allow_none=True)
pageMargins = Typed(expected_type=PageMargins, allow_none=True)
pageSetup = Typed(expected_type=PrintPageSetup, allow_none=True)
headerFooter = Typed(expected_type=HeaderFooter, allow_none=True)
__elements__ = ('pageMargins', 'pageSetup', 'headerFooter')
def __init__(self,
guid=None,
scale=None,
state='visible',
zoomToFit=None,
pageMargins=None,
pageSetup=None,
headerFooter=None,
):
self.guid = guid
self.scale = scale
self.state = state
self.zoomToFit = zoomToFit
self.pageMargins = pageMargins
self.pageSetup = pageSetup
self.headerFooter = headerFooter
class CustomChartsheetViews(Serialisable):
tagname = "customSheetViews"
customSheetView = Sequence(expected_type=CustomChartsheetView, allow_none=True)
__elements__ = ('customSheetView',)
def __init__(self,
customSheetView=None,
):
self.customSheetView = customSheetView

View File

@ -0,0 +1,28 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors import (
Bool,
String,
Typed
)
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.styles import Color
class ChartsheetProperties(Serialisable):
tagname = "sheetPr"
published = Bool(allow_none=True)
codeName = String(allow_none=True)
tabColor = Typed(expected_type=Color, allow_none=True)
__elements__ = ('tabColor',)
def __init__(self,
published=None,
codeName=None,
tabColor=None,
):
self.published = published
self.codeName = codeName
self.tabColor = tabColor

View File

@ -0,0 +1,41 @@
import hashlib
from openpyxl.descriptors import (Bool, Integer, String)
from openpyxl.descriptors.excel import Base64Binary
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.worksheet.protection import (
hash_password,
_Protected
)
class ChartsheetProtection(Serialisable, _Protected):
tagname = "sheetProtection"
algorithmName = String(allow_none=True)
hashValue = Base64Binary(allow_none=True)
saltValue = Base64Binary(allow_none=True)
spinCount = Integer(allow_none=True)
content = Bool(allow_none=True)
objects = Bool(allow_none=True)
__attrs__ = ("content", "objects", "password", "hashValue", "spinCount", "saltValue", "algorithmName")
def __init__(self,
content=None,
objects=None,
hashValue=None,
spinCount=None,
saltValue=None,
algorithmName=None,
password=None,
):
self.content = content
self.objects = objects
self.hashValue = hashValue
self.spinCount = spinCount
self.saltValue = saltValue
self.algorithmName = algorithmName
if password is not None:
self.password = password

View File

@ -0,0 +1,58 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors import (
Bool,
Integer,
String,
Set,
Sequence
)
from openpyxl.descriptors.serialisable import Serialisable
class WebPublishItem(Serialisable):
tagname = "webPublishItem"
id = Integer()
divId = String()
sourceType = Set(values=(['sheet', 'printArea', 'autoFilter', 'range', 'chart', 'pivotTable', 'query', 'label']))
sourceRef = String()
sourceObject = String(allow_none=True)
destinationFile = String()
title = String(allow_none=True)
autoRepublish = Bool(allow_none=True)
def __init__(self,
id=None,
divId=None,
sourceType=None,
sourceRef=None,
sourceObject=None,
destinationFile=None,
title=None,
autoRepublish=None,
):
self.id = id
self.divId = divId
self.sourceType = sourceType
self.sourceRef = sourceRef
self.sourceObject = sourceObject
self.destinationFile = destinationFile
self.title = title
self.autoRepublish = autoRepublish
class WebPublishItems(Serialisable):
tagname = "WebPublishItems"
count = Integer(allow_none=True)
webPublishItem = Sequence(expected_type=WebPublishItem, )
__elements__ = ('webPublishItem',)
def __init__(self,
count=None,
webPublishItem=None,
):
self.count = len(webPublishItem)
self.webPublishItem = webPublishItem

View File

@ -0,0 +1,97 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors import (
Integer,
Alias
)
from openpyxl.descriptors.excel import Relation
from openpyxl.descriptors.serialisable import Serialisable
class SheetBackgroundPicture(Serialisable):
tagname = "picture"
id = Relation()
def __init__(self, id):
self.id = id
class DrawingHF(Serialisable):
id = Relation()
lho = Integer(allow_none=True)
leftHeaderOddPages = Alias('lho')
lhe = Integer(allow_none=True)
leftHeaderEvenPages = Alias('lhe')
lhf = Integer(allow_none=True)
leftHeaderFirstPage = Alias('lhf')
cho = Integer(allow_none=True)
centerHeaderOddPages = Alias('cho')
che = Integer(allow_none=True)
centerHeaderEvenPages = Alias('che')
chf = Integer(allow_none=True)
centerHeaderFirstPage = Alias('chf')
rho = Integer(allow_none=True)
rightHeaderOddPages = Alias('rho')
rhe = Integer(allow_none=True)
rightHeaderEvenPages = Alias('rhe')
rhf = Integer(allow_none=True)
rightHeaderFirstPage = Alias('rhf')
lfo = Integer(allow_none=True)
leftFooterOddPages = Alias('lfo')
lfe = Integer(allow_none=True)
leftFooterEvenPages = Alias('lfe')
lff = Integer(allow_none=True)
leftFooterFirstPage = Alias('lff')
cfo = Integer(allow_none=True)
centerFooterOddPages = Alias('cfo')
cfe = Integer(allow_none=True)
centerFooterEvenPages = Alias('cfe')
cff = Integer(allow_none=True)
centerFooterFirstPage = Alias('cff')
rfo = Integer(allow_none=True)
rightFooterOddPages = Alias('rfo')
rfe = Integer(allow_none=True)
rightFooterEvenPages = Alias('rfe')
rff = Integer(allow_none=True)
rightFooterFirstPage = Alias('rff')
def __init__(self,
id=None,
lho=None,
lhe=None,
lhf=None,
cho=None,
che=None,
chf=None,
rho=None,
rhe=None,
rhf=None,
lfo=None,
lfe=None,
lff=None,
cfo=None,
cfe=None,
cff=None,
rfo=None,
rfe=None,
rff=None,
):
self.id = id
self.lho = lho
self.lhe = lhe
self.lhf = lhf
self.cho = cho
self.che = che
self.chf = chf
self.rho = rho
self.rhe = rhe
self.rhf = rhf
self.lfo = lfo
self.lfe = lfe
self.lff = lff
self.cfo = cfo
self.cfe = cfe
self.cff = cff
self.rfo = rfo
self.rfe = rfe
self.rff = rff

View File

@ -0,0 +1,51 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors import (
Bool,
Integer,
Typed,
Sequence
)
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.serialisable import Serialisable
class ChartsheetView(Serialisable):
tagname = "sheetView"
tabSelected = Bool(allow_none=True)
zoomScale = Integer(allow_none=True)
workbookViewId = Integer()
zoomToFit = Bool(allow_none=True)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ()
def __init__(self,
tabSelected=None,
zoomScale=None,
workbookViewId=0,
zoomToFit=None,
extLst=None,
):
self.tabSelected = tabSelected
self.zoomScale = zoomScale
self.workbookViewId = workbookViewId
self.zoomToFit = zoomToFit
class ChartsheetViewList(Serialisable):
tagname = "sheetViews"
sheetView = Sequence(expected_type=ChartsheetView, )
extLst = Typed(expected_type=ExtensionList, allow_none=True)
__elements__ = ('sheetView',)
def __init__(self,
sheetView=None,
extLst=None,
):
if sheetView is None:
sheetView = [ChartsheetView()]
self.sheetView = sheetView

View File

@ -0,0 +1,4 @@
# Copyright (c) 2010-2022 openpyxl
from .comments import Comment

View File

@ -0,0 +1,21 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Sequence,
Alias
)
class AuthorList(Serialisable):
tagname = "authors"
author = Sequence(expected_type=str)
authors = Alias("author")
def __init__(self,
author=(),
):
self.author = author

View File

@ -0,0 +1,214 @@
# Copyright (c) 2010-2022 openpyxl
## Incomplete!
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Float,
Integer,
Set,
String,
Bool,
)
from openpyxl.descriptors.excel import Guid, ExtensionList
from openpyxl.descriptors.sequence import NestedSequence
from openpyxl.utils.indexed_list import IndexedList
from openpyxl.xml.constants import SHEET_MAIN_NS
from openpyxl.xml.functions import tostring
from openpyxl.cell.text import Text
#from openpyxl.worksheet.ole import ObjectAnchor
from .author import AuthorList
from .comments import Comment
from .shape_writer import ShapeWriter
class Properties(Serialisable):
locked = Bool(allow_none=True)
defaultSize = Bool(allow_none=True)
_print = Bool(allow_none=True)
disabled = Bool(allow_none=True)
uiObject = Bool(allow_none=True)
autoFill = Bool(allow_none=True)
autoLine = Bool(allow_none=True)
altText = String(allow_none=True)
textHAlign = Set(values=(['left', 'center', 'right', 'justify', 'distributed']))
textVAlign = Set(values=(['top', 'center', 'bottom', 'justify', 'distributed']))
lockText = Bool(allow_none=True)
justLastX = Bool(allow_none=True)
autoScale = Bool(allow_none=True)
rowHidden = Bool(allow_none=True)
colHidden = Bool(allow_none=True)
#anchor = Typed(expected_type=ObjectAnchor, )
__elements__ = ('anchor',)
def __init__(self,
locked=None,
defaultSize=None,
_print=None,
disabled=None,
uiObject=None,
autoFill=None,
autoLine=None,
altText=None,
textHAlign=None,
textVAlign=None,
lockText=None,
justLastX=None,
autoScale=None,
rowHidden=None,
colHidden=None,
anchor=None,
):
self.locked = locked
self.defaultSize = defaultSize
self._print = _print
self.disabled = disabled
self.uiObject = uiObject
self.autoFill = autoFill
self.autoLine = autoLine
self.altText = altText
self.textHAlign = textHAlign
self.textVAlign = textVAlign
self.lockText = lockText
self.justLastX = justLastX
self.autoScale = autoScale
self.rowHidden = rowHidden
self.colHidden = colHidden
self.anchor = anchor
class CommentRecord(Serialisable):
tagname = "comment"
ref = String()
authorId = Integer()
guid = Guid(allow_none=True)
shapeId = Integer(allow_none=True)
text = Typed(expected_type=Text)
commentPr = Typed(expected_type=Properties, allow_none=True)
author = String(allow_none=True)
__elements__ = ('text', 'commentPr')
__attrs__ = ('ref', 'authorId', 'guid', 'shapeId')
def __init__(self,
ref="",
authorId=0,
guid=None,
shapeId=0,
text=None,
commentPr=None,
author=None,
height=79,
width=144
):
self.ref = ref
self.authorId = authorId
self.guid = guid
self.shapeId = shapeId
if text is None:
text = Text()
self.text = text
self.commentPr = commentPr
self.author = author
self.height = height
self.width = width
@classmethod
def from_cell(cls, cell):
"""
Class method to convert cell comment
"""
comment = cell._comment
ref = cell.coordinate
self = cls(ref=ref, author=comment.author)
self.text.t = comment.content
self.height = comment.height
self.width = comment.width
return self
@property
def content(self):
"""
Remove all inline formatting and stuff
"""
return self.text.content
class CommentSheet(Serialisable):
tagname = "comments"
authors = Typed(expected_type=AuthorList)
commentList = NestedSequence(expected_type=CommentRecord, count=0)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
_id = None
_path = "/xl/comments/comment{0}.xml"
mime_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml"
_rel_type = "comments"
_rel_id = None
__elements__ = ('authors', 'commentList')
def __init__(self,
authors=None,
commentList=None,
extLst=None,
):
self.authors = authors
self.commentList = commentList
def to_tree(self):
tree = super(CommentSheet, self).to_tree()
tree.set("xmlns", SHEET_MAIN_NS)
return tree
@property
def comments(self):
"""
Return a dictionary of comments keyed by coord
"""
authors = self.authors.author
for c in self.commentList:
yield c.ref, Comment(c.content, authors[c.authorId], c.height, c.width)
@classmethod
def from_comments(cls, comments):
"""
Create a comment sheet from a list of comments for a particular worksheet
"""
authors = IndexedList()
# dedupe authors and get indexes
for comment in comments:
comment.authorId = authors.add(comment.author)
return cls(authors=AuthorList(authors), commentList=comments)
def write_shapes(self, vml=None):
"""
Create the VML for comments
"""
sw = ShapeWriter(self.comments)
return sw.write(vml)
@property
def path(self):
"""
Return path within the archive
"""
return self._path.format(self._id)

View File

@ -0,0 +1,62 @@
# Copyright (c) 2010-2022 openpyxl
class Comment(object):
_parent = None
def __init__(self, text, author, height=79, width=144):
self.content = text
self.author = author
self.height = height
self.width = width
@property
def parent(self):
return self._parent
def __eq__(self, other):
return (
self.content == other.content
and self.author == other.author
)
def __repr__(self):
return "Comment: {0} by {1}".format(self.content, self.author)
def __copy__(self):
"""Create a detached copy of this comment."""
clone = self.__class__(self.content, self.author, self.height, self.width)
return clone
def bind(self, cell):
"""
Bind comment to a particular cell
"""
if cell is not None and self._parent is not None and self._parent != cell:
fmt = "Comment already assigned to {0} in worksheet {1}. Cannot assign a comment to more than one cell"
raise AttributeError(fmt.format(cell.coordinate, cell.parent.title))
self._parent = cell
def unbind(self):
"""
Unbind a comment from a cell
"""
self._parent = None
@property
def text(self):
"""
Any comment text stripped of all formatting.
"""
return self.content
@text.setter
def text(self, value):
self.content = value

View File

@ -0,0 +1,116 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.xml.functions import (
Element,
SubElement,
tostring,
fromstring,
)
from openpyxl.utils import (
column_index_from_string,
coordinate_to_tuple,
)
vmlns = "urn:schemas-microsoft-com:vml"
officens = "urn:schemas-microsoft-com:office:office"
excelns = "urn:schemas-microsoft-com:office:excel"
class ShapeWriter(object):
"""
Create VML for comments
"""
vml = None
vml_path = None
def __init__(self, comments):
self.comments = comments
def add_comment_shapetype(self, root):
shape_layout = SubElement(root, "{%s}shapelayout" % officens,
{"{%s}ext" % vmlns: "edit"})
SubElement(shape_layout,
"{%s}idmap" % officens,
{"{%s}ext" % vmlns: "edit", "data": "1"})
shape_type = SubElement(root,
"{%s}shapetype" % vmlns,
{"id": "_x0000_t202",
"coordsize": "21600,21600",
"{%s}spt" % officens: "202",
"path": "m,l,21600r21600,l21600,xe"})
SubElement(shape_type, "{%s}stroke" % vmlns, {"joinstyle": "miter"})
SubElement(shape_type,
"{%s}path" % vmlns,
{"gradientshapeok": "t",
"{%s}connecttype" % officens: "rect"})
def add_comment_shape(self, root, idx, coord, height, width):
row, col = coordinate_to_tuple(coord)
row -= 1
col -= 1
shape = _shape_factory(row, col, height, width)
shape.set('id', "_x0000_s%04d" % idx)
root.append(shape)
def write(self, root):
if not hasattr(root, "findall"):
root = Element("xml")
# Remove any existing comment shapes
comments = root.findall("{%s}shape[@type='#_x0000_t202']" % vmlns)
for c in comments:
root.remove(c)
# check whether comments shape type already exists
shape_types = root.find("{%s}shapetype[@id='_x0000_t202']" % vmlns)
if not shape_types:
self.add_comment_shapetype(root)
for idx, (coord, comment) in enumerate(self.comments, 1026):
self.add_comment_shape(root, idx, coord, comment.height, comment.width)
return tostring(root)
def _shape_factory(row, column, height, width):
style = ("position:absolute; "
"margin-left:59.25pt;"
"margin-top:1.5pt;"
"width:{width}px;"
"height:{height}px;"
"z-index:1;"
"visibility:hidden").format(height=height,
width=width)
attrs = {
"type": "#_x0000_t202",
"style": style,
"fillcolor": "#ffffe1",
"{%s}insetmode" % officens: "auto"
}
shape = Element("{%s}shape" % vmlns, attrs)
SubElement(shape, "{%s}fill" % vmlns,
{"color2": "#ffffe1"})
SubElement(shape, "{%s}shadow" % vmlns,
{"color": "black", "obscured": "t"})
SubElement(shape, "{%s}path" % vmlns,
{"{%s}connecttype" % officens: "none"})
textbox = SubElement(shape, "{%s}textbox" % vmlns,
{"style": "mso-direction-alt:auto"})
SubElement(textbox, "div", {"style": "text-align:left"})
client_data = SubElement(shape, "{%s}ClientData" % excelns,
{"ObjectType": "Note"})
SubElement(client_data, "{%s}MoveWithCells" % excelns)
SubElement(client_data, "{%s}SizeWithCells" % excelns)
SubElement(client_data, "{%s}AutoFill" % excelns).text = "False"
SubElement(client_data, "{%s}Row" % excelns).text = str(row)
SubElement(client_data, "{%s}Column" % excelns).text = str(column)
return shape

View File

@ -0,0 +1,54 @@
# Copyright (c) 2010-2022 openpyxl
from .numbers import NUMERIC_TYPES
from .strings import safe_string
import warnings
from functools import wraps
import inspect
class DummyCode:
pass
# from https://github.com/tantale/deprecated/blob/master/deprecated/__init__.py
# with an enhancement to update docstrings of deprecated functions
string_types = (type(b''), type(u''))
def deprecated(reason):
if isinstance(reason, string_types):
def decorator(func1):
if inspect.isclass(func1):
fmt1 = "Call to deprecated class {name} ({reason})."
else:
fmt1 = "Call to deprecated function {name} ({reason})."
@wraps(func1)
def new_func1(*args, **kwargs):
#warnings.simplefilter('default', DeprecationWarning)
warnings.warn(
fmt1.format(name=func1.__name__, reason=reason),
category=DeprecationWarning,
stacklevel=2
)
return func1(*args, **kwargs)
# Enhance docstring with a deprecation note
deprecationNote = "\n\n.. note::\n Deprecated: " + reason
if new_func1.__doc__:
new_func1.__doc__ += deprecationNote
else:
new_func1.__doc__ = deprecationNote
return new_func1
return decorator
elif inspect.isclass(reason) or inspect.isfunction(reason):
raise TypeError("Reason for deprecation must be supplied")
else:
raise TypeError(repr(type(reason)))

View File

@ -0,0 +1,8 @@
# Copyright (c) 2010-2022 openpyxl
try:
from abc import ABC
except ImportError:
from abc import ABCMeta
ABC = ABCMeta('ABC', (object, ), {})

View File

@ -0,0 +1,43 @@
# Copyright (c) 2010-2022 openpyxl
from decimal import Decimal
NUMERIC_TYPES = (int, float, Decimal)
try:
import numpy
NUMPY = True
except ImportError:
NUMPY = False
if NUMPY:
NUMERIC_TYPES = NUMERIC_TYPES + (numpy.short,
numpy.ushort,
numpy.intc,
numpy.uintc,
numpy.int_,
numpy.uint,
numpy.longlong,
numpy.ulonglong,
numpy.half,
numpy.float16,
numpy.single,
numpy.double,
numpy.longdouble,
numpy.int8,
numpy.int16,
numpy.int32,
numpy.int64,
numpy.uint8,
numpy.uint16,
numpy.uint32,
numpy.uint64,
numpy.intp,
numpy.uintp,
numpy.float32,
numpy.float64,
numpy.bool_,
numpy.floating,
numpy.integer)

View File

@ -0,0 +1,17 @@
# Copyright (c) 2010-2022 openpyxl
"""
math.prod equivalent for < Python 3.8
"""
import functools
import operator
def product(sequence):
return functools.reduce(operator.mul, sequence)
try:
from math import prod
except ImportError:
prod = product

View File

@ -0,0 +1,40 @@
# Copyright (c) 2010-2022 openpyxl
import weakref
class Singleton(type):
"""
Singleton metaclass
Based on Python Cookbook 3rd Edition Recipe 9.13
Only one instance of a class can exist. Does not work with __slots__
"""
def __init__(self, *args, **kw):
super(Singleton, self).__init__(*args, **kw)
self.__instance = None
def __call__(self, *args, **kw):
if self.__instance is None:
self.__instance = super(Singleton, self).__call__(*args, **kw)
return self.__instance
class Cached(type):
"""
Caching metaclass
Child classes will only create new instances of themselves if
one doesn't already exist. Does not work with __slots__
"""
def __init__(self, *args, **kw):
super(Singleton, self).__init__(*args, **kw)
self.__cache = weakref.WeakValueDictionary()
def __call__(self, *args):
if args in self.__cache:
return self.__cache[args]
obj = super(Singleton, self).__call__(*args)
self.__cache[args] = obj
return obj

View File

@ -0,0 +1,25 @@
# Copyright (c) 2010-2022 openpyxl
from datetime import datetime
from math import isnan, isinf
import sys
VER = sys.version_info
from .numbers import NUMERIC_TYPES
def safe_string(value):
"""Safely and consistently format numeric values"""
if isinstance(value, NUMERIC_TYPES):
if isnan(value) or isinf(value):
value = ""
else:
value = "%.16g" % value
elif value is None:
value = "none"
elif isinstance(value, datetime):
value = value.isoformat()
elif not isinstance(value, str):
value = str(value)
return value

View File

@ -0,0 +1,57 @@
# Copyright (c) 2010-2022 openpyxl
from .base import *
from .sequence import Sequence
class MetaStrict(type):
def __new__(cls, clsname, bases, methods):
for k, v in methods.items():
if isinstance(v, Descriptor):
v.name = k
return type.__new__(cls, clsname, bases, methods)
class MetaSerialisable(type):
def __new__(cls, clsname, bases, methods):
attrs = []
nested = []
elements = []
namespaced = []
for k, v in methods.items():
if isinstance(v, Descriptor):
ns= getattr(v, 'namespace', None)
if ns:
namespaced.append((k, "{%s}%s" % (ns, k)))
if getattr(v, 'nested', False):
nested.append(k)
elements.append(k)
elif isinstance(v, Sequence):
elements.append(k)
elif isinstance(v, Typed):
if hasattr(v.expected_type, 'to_tree'):
elements.append(k)
else:
attrs.append(k)
else:
if not isinstance(v, Alias):
attrs.append(k)
if methods.get('__attrs__') is None:
methods['__attrs__'] = tuple(attrs)
methods['__namespaced__'] = tuple(namespaced)
if methods.get('__nested__') is None:
methods['__nested__'] = tuple(sorted(nested))
if methods.get('__elements__') is None:
methods['__elements__'] = tuple(sorted(elements))
return MetaStrict.__new__(cls, clsname, bases, methods)
Strict = MetaStrict('Strict', (object,), {})
_Serialiasable = MetaSerialisable('_Serialisable', (object,), {})
#del MetaStrict
#del MetaSerialisable

View File

@ -0,0 +1,268 @@
# Copyright (c) 2010-2022 openpyxl
"""
Based on Python Cookbook 3rd Edition, 8.13
http://chimera.labs.oreilly.com/books/1230000000393/ch08.html#_discussiuncion_130
"""
import datetime
import re
from openpyxl.utils.datetime import from_ISO8601
from .namespace import namespaced
class Descriptor(object):
def __init__(self, name=None, **kw):
self.name = name
for k, v in kw.items():
setattr(self, k, v)
def __set__(self, instance, value):
instance.__dict__[self.name] = value
class Typed(Descriptor):
"""Values must of a particular type"""
expected_type = type(None)
allow_none = False
nested = False
def __init__(self, *args, **kw):
super(Typed, self).__init__(*args, **kw)
self.__doc__ = "Values must be of type {0}".format(self.expected_type)
def __set__(self, instance, value):
if not isinstance(value, self.expected_type):
if (not self.allow_none
or (self.allow_none and value is not None)):
raise TypeError('expected ' + str(self.expected_type))
super(Typed, self).__set__(instance, value)
def __repr__(self):
return self.__doc__
def _convert(expected_type, value):
"""
Check value is of or can be converted to expected type.
"""
if not isinstance(value, expected_type):
try:
value = expected_type(value)
except:
raise TypeError('expected ' + str(expected_type))
return value
class Convertible(Typed):
"""Values must be convertible to a particular type"""
def __set__(self, instance, value):
if ((self.allow_none and value is not None)
or not self.allow_none):
value = _convert(self.expected_type, value)
super(Convertible, self).__set__(instance, value)
class Max(Convertible):
"""Values must be less than a `max` value"""
expected_type = float
allow_none = False
def __init__(self, **kw):
if 'max' not in kw and not hasattr(self, 'max'):
raise TypeError('missing max value')
super(Max, self).__init__(**kw)
def __set__(self, instance, value):
if ((self.allow_none and value is not None)
or not self.allow_none):
value = _convert(self.expected_type, value)
if value > self.max:
raise ValueError('Max value is {0}'.format(self.max))
super(Max, self).__set__(instance, value)
class Min(Convertible):
"""Values must be greater than a `min` value"""
expected_type = float
allow_none = False
def __init__(self, **kw):
if 'min' not in kw and not hasattr(self, 'min'):
raise TypeError('missing min value')
super(Min, self).__init__(**kw)
def __set__(self, instance, value):
if ((self.allow_none and value is not None)
or not self.allow_none):
value = _convert(self.expected_type, value)
if value < self.min:
raise ValueError('Min value is {0}'.format(self.min))
super(Min, self).__set__(instance, value)
class MinMax(Min, Max):
"""Values must be greater than `min` value and less than a `max` one"""
pass
class Set(Descriptor):
"""Value can only be from a set of know values"""
def __init__(self, name=None, **kw):
if not 'values' in kw:
raise TypeError("missing set of values")
kw['values'] = set(kw['values'])
super(Set, self).__init__(name, **kw)
self.__doc__ = "Value must be one of {0}".format(self.values)
def __set__(self, instance, value):
if value not in self.values:
raise ValueError(self.__doc__)
super(Set, self).__set__(instance, value)
class NoneSet(Set):
"""'none' will be treated as None"""
def __init__(self, name=None, **kw):
super(NoneSet, self).__init__(name, **kw)
self.values.add(None)
def __set__(self, instance, value):
if value == 'none':
value = None
super(NoneSet, self).__set__(instance, value)
class Integer(Convertible):
expected_type = int
class Float(Convertible):
expected_type = float
class Bool(Convertible):
expected_type = bool
def __set__(self, instance, value):
if isinstance(value, str):
if value in ('false', 'f', '0'):
value = False
super(Bool, self).__set__(instance, value)
class String(Typed):
expected_type = str
class Text(String, Convertible):
pass
class ASCII(Typed):
expected_type = bytes
class Tuple(Typed):
expected_type = tuple
class Length(Descriptor):
def __init__(self, name=None, **kw):
if "length" not in kw:
raise TypeError("value length must be supplied")
super(Length, self).__init__(**kw)
def __set__(self, instance, value):
if len(value) != self.length:
raise ValueError("Value must be length {0}".format(self.length))
super(Length, self).__set__(instance, value)
class Default(Typed):
"""
When called returns an instance of the expected type.
Additional default values can be passed in to the descriptor
"""
def __init__(self, name=None, **kw):
if "defaults" not in kw:
kw['defaults'] = {}
super(Default, self).__init__(**kw)
def __call__(self):
return self.expected_type()
class Alias(Descriptor):
"""
Aliases can be used when either the desired attribute name is not allowed
or confusing in Python (eg. "type") or a more descriptve name is desired
(eg. "underline" for "u")
"""
def __init__(self, alias):
self.alias = alias
def __set__(self, instance, value):
setattr(instance, self.alias, value)
def __get__(self, instance, cls):
return getattr(instance, self.alias)
class MatchPattern(Descriptor):
"""Values must match a regex pattern """
allow_none = False
def __init__(self, name=None, **kw):
if 'pattern' not in kw and not hasattr(self, 'pattern'):
raise TypeError('missing pattern value')
super(MatchPattern, self).__init__(name, **kw)
self.test_pattern = re.compile(self.pattern, re.VERBOSE)
def __set__(self, instance, value):
if value is None and not self.allow_none:
raise ValueError("Value must not be none")
if ((self.allow_none and value is not None)
or not self.allow_none):
if not self.test_pattern.match(value):
raise ValueError('Value does not match pattern {0}'.format(self.pattern))
super(MatchPattern, self).__set__(instance, value)
class DateTime(Typed):
expected_type = datetime.datetime
def __set__(self, instance, value):
if value is not None and isinstance(value, str):
try:
value = from_ISO8601(value)
except ValueError:
raise ValueError("Value must be ISO datetime format")
super(DateTime, self).__set__(instance, value)

View File

@ -0,0 +1,112 @@
#copyright openpyxl 2010-2018
"""
Excel specific descriptors
"""
from openpyxl.xml.constants import REL_NS
from openpyxl.compat import safe_string
from openpyxl.xml.functions import Element
from . import (
MatchPattern,
MinMax,
Integer,
String,
Sequence,
)
from .serialisable import Serialisable
class HexBinary(MatchPattern):
pattern = "[0-9a-fA-F]+$"
class UniversalMeasure(MatchPattern):
pattern = r"[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)"
class TextPoint(MinMax):
"""
Size in hundredths of points.
In theory other units of measurement can be used but these are unbounded
"""
expected_type = int
min = -400000
max = 400000
Coordinate = Integer
class Percentage(MinMax):
pattern = r"((100)|([0-9][0-9]?))(\.[0-9][0-9]?)?%" # strict
min = -1000000
max = 1000000
def __set__(self, instance, value):
if isinstance(value, str) and "%" in value:
value = value.replace("%", "")
value = int(float(value) * 1000)
super(Percentage, self).__set__(instance, value)
class Extension(Serialisable):
uri = String()
def __init__(self,
uri=None,
):
self.uri = uri
class ExtensionList(Serialisable):
ext = Sequence(expected_type=Extension)
def __init__(self,
ext=(),
):
self.ext = ext
class Relation(String):
namespace = REL_NS
allow_none = True
class Base64Binary(MatchPattern):
# http://www.w3.org/TR/xmlschema11-2/#nt-Base64Binary
pattern = "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$"
class Guid(MatchPattern):
# https://msdn.microsoft.com/en-us/library/dd946381(v=office.12).aspx
pattern = r"{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\}"
class CellRange(MatchPattern):
pattern = r"^[$]?([A-Za-z]{1,3})[$]?(\d+)(:[$]?([A-Za-z]{1,3})[$]?(\d+)?)?$|^[A-Za-z]{1,3}:[A-Za-z]{1,3}$"
allow_none = True
def __set__(self, instance, value):
if value is not None:
value = value.upper()
super(CellRange, self).__set__(instance, value)
def _explicit_none(tagname, value, namespace=None):
"""
Override serialisation because explicit none required
"""
if namespace is not None:
tagname = "{%s}%s" % (namespace, tagname)
return Element(tagname, val=safe_string(value))

View File

@ -0,0 +1,12 @@
# copyright openpyxl 2010-2015
def namespaced(obj, tagname, namespace=None):
"""
Utility to create a namespaced tag for an object
"""
namespace = getattr(obj, "namespace", None) or namespace
if namespace is not None:
tagname = "{%s}%s" % (namespace, tagname)
return tagname

View File

@ -0,0 +1,131 @@
#copyright openpyxl 2010-2015
"""
Generic serialisable classes
"""
from .base import (
Convertible,
Bool,
Descriptor,
NoneSet,
MinMax,
Set,
Float,
Integer,
String,
Text,
)
from .sequence import Sequence
from openpyxl.compat import safe_string
from openpyxl.xml.functions import Element, localname, whitespace
class Nested(Descriptor):
nested = True
attribute = "val"
def __set__(self, instance, value):
if hasattr(value, "tag"):
tag = localname(value)
if tag != self.name:
raise ValueError("Tag does not match attribute")
value = self.from_tree(value)
super(Nested, self).__set__(instance, value)
def from_tree(self, node):
return node.get(self.attribute)
def to_tree(self, tagname=None, value=None, namespace=None):
namespace = getattr(self, "namespace", namespace)
if value is not None:
if namespace is not None:
tagname = "{%s}%s" % (namespace, tagname)
value = safe_string(value)
return Element(tagname, {self.attribute:value})
class NestedValue(Nested, Convertible):
"""
Nested tag storing the value on the 'val' attribute
"""
pass
class NestedText(NestedValue):
"""
Represents any nested tag with the value as the contents of the tag
"""
def from_tree(self, node):
return node.text
def to_tree(self, tagname=None, value=None, namespace=None):
namespace = getattr(self, "namespace", namespace)
if value is not None:
if namespace is not None:
tagname = "{%s}%s" % (namespace, tagname)
el = Element(tagname)
el.text = safe_string(value)
whitespace(el)
return el
class NestedFloat(NestedValue, Float):
pass
class NestedInteger(NestedValue, Integer):
pass
class NestedString(NestedValue, String):
pass
class NestedBool(NestedValue, Bool):
def from_tree(self, node):
return node.get("val", True)
class NestedNoneSet(Nested, NoneSet):
pass
class NestedSet(Nested, Set):
pass
class NestedMinMax(Nested, MinMax):
pass
class EmptyTag(Nested, Bool):
"""
Boolean if a tag exists or not.
"""
def from_tree(self, node):
return True
def to_tree(self, tagname=None, value=None, namespace=None):
if value:
namespace = getattr(self, "namespace", namespace)
if namespace is not None:
tagname = "{%s}%s" % (namespace, tagname)
return Element(tagname)

View File

@ -0,0 +1,127 @@
# copyright openpyxl 2010-2015
from openpyxl.compat import safe_string
from openpyxl.xml.functions import Element
from openpyxl.utils.indexed_list import IndexedList
from .base import Descriptor, Alias, _convert
from .namespace import namespaced
class Sequence(Descriptor):
"""
A sequence (list or tuple) that may only contain objects of the declared
type
"""
expected_type = type(None)
seq_types = (list, tuple)
idx_base = 0
unique = False
def __set__(self, instance, seq):
if not isinstance(seq, self.seq_types):
raise TypeError("Value must be a sequence")
seq = [_convert(self.expected_type, value) for value in seq]
if self.unique:
seq = IndexedList(seq)
super(Sequence, self).__set__(instance, seq)
def to_tree(self, tagname, obj, namespace=None):
"""
Convert the sequence represented by the descriptor to an XML element
"""
for idx, v in enumerate(obj, self.idx_base):
if hasattr(v, "to_tree"):
el = v.to_tree(tagname, idx)
else:
tagname = namespaced(obj, tagname, namespace)
el = Element(tagname)
el.text = safe_string(v)
yield el
class ValueSequence(Sequence):
"""
A sequence of primitive types that are stored as a single attribute.
"val" is the default attribute
"""
attribute = "val"
def to_tree(self, tagname, obj, namespace=None):
tagname = namespaced(self, tagname, namespace)
for v in obj:
yield Element(tagname, {self.attribute:safe_string(v)})
def from_tree(self, node):
return node.get(self.attribute)
class NestedSequence(Sequence):
"""
Wrap a sequence in an containing object
"""
count = False
def to_tree(self, tagname, obj, namespace=None):
tagname = namespaced(self, tagname, namespace)
container = Element(tagname)
if self.count:
container.set('count', str(len(obj)))
for v in obj:
container.append(v.to_tree())
return container
def from_tree(self, node):
return [self.expected_type.from_tree(el) for el in node]
class MultiSequence(Sequence):
"""
Sequences can contain objects with different tags
"""
def __set__(self, instance, seq):
if not isinstance(seq, (tuple, list)):
raise ValueError("Value must be a sequence")
seq = list(seq)
Descriptor.__set__(self, instance, seq)
def to_tree(self, tagname, obj, namespace=None):
"""
Convert the sequence represented by the descriptor to an XML element
"""
for v in obj:
el = v.to_tree(namespace=namespace)
yield el
class MultiSequencePart(Alias):
"""
Allow a multisequence to be built up from parts
Excluded from the instance __elements__ or __attrs__ as is effectively an Alias
"""
def __init__(self, expected_type, store):
self.expected_type = expected_type
self.store = store
def __set__(self, instance, value):
value = _convert(self.expected_type, value)
instance.__dict__[self.store].append(value)
def __get__(self, instance, cls):
return self

View File

@ -0,0 +1,240 @@
# copyright openpyxl 2010-2015
from copy import copy
from keyword import kwlist
KEYWORDS = frozenset(kwlist)
from . import Descriptor
from . import _Serialiasable
from .sequence import (
Sequence,
NestedSequence,
MultiSequencePart,
)
from .namespace import namespaced
from openpyxl.compat import safe_string
from openpyxl.xml.functions import (
Element,
localname,
)
seq_types = (list, tuple)
class Serialisable(_Serialiasable):
"""
Objects can serialise to XML their attributes and child objects.
The following class attributes are created by the metaclass at runtime:
__attrs__ = attributes
__nested__ = single-valued child treated as an attribute
__elements__ = child elements
"""
__attrs__ = None
__nested__ = None
__elements__ = None
__namespaced__ = None
idx_base = 0
@property
def tagname(self):
raise(NotImplementedError)
namespace = None
@classmethod
def from_tree(cls, node):
"""
Create object from XML
"""
# strip known namespaces from attributes
attrib = dict(node.attrib)
for key, ns in cls.__namespaced__:
if ns in attrib:
attrib[key] = attrib[ns]
del attrib[ns]
# strip attributes with unknown namespaces
for key in list(attrib):
if key.startswith('{'):
del attrib[key]
elif key in KEYWORDS:
attrib["_" + key] = attrib[key]
del attrib[key]
elif "-" in key:
n = key.replace("-", "_")
attrib[n] = attrib[key]
del attrib[key]
if node.text and "attr_text" in cls.__attrs__:
attrib["attr_text"] = node.text
for el in node:
tag = localname(el)
if tag in KEYWORDS:
tag = "_" + tag
desc = getattr(cls, tag, None)
if desc is None or isinstance(desc, property):
continue
if hasattr(desc, 'from_tree'):
#descriptor manages conversion
obj = desc.from_tree(el)
else:
if hasattr(desc.expected_type, "from_tree"):
#complex type
obj = desc.expected_type.from_tree(el)
else:
#primitive
obj = el.text
if isinstance(desc, NestedSequence):
attrib[tag] = obj
elif isinstance(desc, Sequence):
attrib.setdefault(tag, [])
attrib[tag].append(obj)
elif isinstance(desc, MultiSequencePart):
attrib.setdefault(desc.store, [])
attrib[desc.store].append(obj)
else:
attrib[tag] = obj
return cls(**attrib)
def to_tree(self, tagname=None, idx=None, namespace=None):
if tagname is None:
tagname = self.tagname
# keywords have to be masked
if tagname.startswith("_"):
tagname = tagname[1:]
tagname = namespaced(self, tagname, namespace)
namespace = getattr(self, "namespace", namespace)
attrs = dict(self)
for key, ns in self.__namespaced__:
if key in attrs:
attrs[ns] = attrs[key]
del attrs[key]
el = Element(tagname, attrs)
if "attr_text" in self.__attrs__:
el.text = safe_string(getattr(self, "attr_text"))
for child_tag in self.__elements__:
desc = getattr(self.__class__, child_tag, None)
obj = getattr(self, child_tag)
if hasattr(desc, "namespace") and hasattr(obj, 'namespace'):
obj.namespace = desc.namespace
if isinstance(obj, seq_types):
if isinstance(desc, NestedSequence):
# wrap sequence in container
if not obj:
continue
nodes = [desc.to_tree(child_tag, obj, namespace)]
elif isinstance(desc, Sequence):
# sequence
desc.idx_base = self.idx_base
nodes = (desc.to_tree(child_tag, obj, namespace))
else: # property
nodes = (v.to_tree(child_tag, namespace) for v in obj)
for node in nodes:
el.append(node)
else:
if child_tag in self.__nested__:
node = desc.to_tree(child_tag, obj, namespace)
elif obj is None:
continue
else:
node = obj.to_tree(child_tag)
if node is not None:
el.append(node)
return el
def __iter__(self):
for attr in self.__attrs__:
value = getattr(self, attr)
if attr.startswith("_"):
attr = attr[1:]
elif attr != "attr_text" and "_" in attr:
desc = getattr(self.__class__, attr)
if getattr(desc, "hyphenated", False):
attr = attr.replace("_", "-")
if attr != "attr_text" and value is not None:
yield attr, safe_string(value)
def __eq__(self, other):
if not self.__class__ == other.__class__:
return False
elif not dict(self) == dict(other):
return False
for el in self.__elements__:
if getattr(self, el) != getattr(other, el):
return False
return True
def __ne__(self, other):
return not self == other
def __repr__(self):
s = u"<{0}.{1} object>\nParameters:".format(
self.__module__,
self.__class__.__name__
)
args = []
for k in self.__attrs__ + self.__elements__:
v = getattr(self, k)
if isinstance(v, Descriptor):
v = None
args.append(u"{0}={1}".format(k, repr(v)))
args = u", ".join(args)
return u"\n".join([s, args])
def __hash__(self):
fields = []
for attr in self.__attrs__ + self.__elements__:
val = getattr(self, attr)
if isinstance(val, list):
val = tuple(val)
fields.append(val)
return hash(tuple(fields))
def __add__(self, other):
if type(self) != type(other):
raise TypeError("Cannot combine instances of different types")
vals = {}
for attr in self.__attrs__:
vals[attr] = getattr(self, attr) or getattr(other, attr)
for el in self.__elements__:
a = getattr(self, el)
b = getattr(other, el)
if a and b:
vals[el] = a + b
else:
vals[el] = a or b
return self.__class__(**vals)
def __copy__(self):
# serialise to xml and back to avoid shallow copies
xml = self.to_tree(tagname="dummy")
cp = self.__class__.from_tree(xml)
# copy any non-persisted attributed
for k in self.__dict__:
if k not in self.__attrs__ + self.__elements__:
v = copy(getattr(self, k))
setattr(cp, k, v)
return cp

View File

@ -0,0 +1,18 @@
# Metaclass for mixing slots and descriptors
# From "Programming in Python 3" by Mark Summerfield Ch.8 p. 383
class AutoSlotProperties(type):
def __new__(mcl, classname, bases, dictionary):
slots = list(dictionary.get("__slots__", []))
for getter_name in [key for key in dictionary if key.startswith("get_")]:
name = getter_name
slots.append("__" + name)
getter = dictionary.pop(getter_name)
setter = dictionary.get(setter_name, None)
if (setter is not None
and isinstance(setter, collections.Callable)):
del dictionary[setter_name]
dictionary[name] = property(getter. setter)
dictionary["__slots__"] = tuple(slots)
return super().__new__(mcl, classname, bases, dictionary)

View File

@ -0,0 +1,4 @@
# Copyright (c) 2010-2022 openpyxl
from .drawing import Drawing

View File

@ -0,0 +1,435 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Alias,
Typed,
Integer,
Set,
MinMax,
)
from openpyxl.descriptors.excel import Percentage
from openpyxl.descriptors.nested import (
NestedNoneSet,
NestedValue,
NestedInteger,
EmptyTag,
)
from openpyxl.styles.colors import RGB
from openpyxl.xml.constants import DRAWING_NS
from openpyxl.descriptors.excel import ExtensionList as OfficeArtExtensionList
PRESET_COLORS = [
'aliceBlue', 'antiqueWhite', 'aqua', 'aquamarine',
'azure', 'beige', 'bisque', 'black', 'blanchedAlmond', 'blue',
'blueViolet', 'brown', 'burlyWood', 'cadetBlue', 'chartreuse',
'chocolate', 'coral', 'cornflowerBlue', 'cornsilk', 'crimson', 'cyan',
'darkBlue', 'darkCyan', 'darkGoldenrod', 'darkGray', 'darkGrey',
'darkGreen', 'darkKhaki', 'darkMagenta', 'darkOliveGreen', 'darkOrange',
'darkOrchid', 'darkRed', 'darkSalmon', 'darkSeaGreen', 'darkSlateBlue',
'darkSlateGray', 'darkSlateGrey', 'darkTurquoise', 'darkViolet',
'dkBlue', 'dkCyan', 'dkGoldenrod', 'dkGray', 'dkGrey', 'dkGreen',
'dkKhaki', 'dkMagenta', 'dkOliveGreen', 'dkOrange', 'dkOrchid', 'dkRed',
'dkSalmon', 'dkSeaGreen', 'dkSlateBlue', 'dkSlateGray', 'dkSlateGrey',
'dkTurquoise', 'dkViolet', 'deepPink', 'deepSkyBlue', 'dimGray',
'dimGrey', 'dodgerBlue', 'firebrick', 'floralWhite', 'forestGreen',
'fuchsia', 'gainsboro', 'ghostWhite', 'gold', 'goldenrod', 'gray',
'grey', 'green', 'greenYellow', 'honeydew', 'hotPink', 'indianRed',
'indigo', 'ivory', 'khaki', 'lavender', 'lavenderBlush', 'lawnGreen',
'lemonChiffon', 'lightBlue', 'lightCoral', 'lightCyan',
'lightGoldenrodYellow', 'lightGray', 'lightGrey', 'lightGreen',
'lightPink', 'lightSalmon', 'lightSeaGreen', 'lightSkyBlue',
'lightSlateGray', 'lightSlateGrey', 'lightSteelBlue', 'lightYellow',
'ltBlue', 'ltCoral', 'ltCyan', 'ltGoldenrodYellow', 'ltGray', 'ltGrey',
'ltGreen', 'ltPink', 'ltSalmon', 'ltSeaGreen', 'ltSkyBlue',
'ltSlateGray', 'ltSlateGrey', 'ltSteelBlue', 'ltYellow', 'lime',
'limeGreen', 'linen', 'magenta', 'maroon', 'medAquamarine', 'medBlue',
'medOrchid', 'medPurple', 'medSeaGreen', 'medSlateBlue',
'medSpringGreen', 'medTurquoise', 'medVioletRed', 'mediumAquamarine',
'mediumBlue', 'mediumOrchid', 'mediumPurple', 'mediumSeaGreen',
'mediumSlateBlue', 'mediumSpringGreen', 'mediumTurquoise',
'mediumVioletRed', 'midnightBlue', 'mintCream', 'mistyRose', 'moccasin',
'navajoWhite', 'navy', 'oldLace', 'olive', 'oliveDrab', 'orange',
'orangeRed', 'orchid', 'paleGoldenrod', 'paleGreen', 'paleTurquoise',
'paleVioletRed', 'papayaWhip', 'peachPuff', 'peru', 'pink', 'plum',
'powderBlue', 'purple', 'red', 'rosyBrown', 'royalBlue', 'saddleBrown',
'salmon', 'sandyBrown', 'seaGreen', 'seaShell', 'sienna', 'silver',
'skyBlue', 'slateBlue', 'slateGray', 'slateGrey', 'snow', 'springGreen',
'steelBlue', 'tan', 'teal', 'thistle', 'tomato', 'turquoise', 'violet',
'wheat', 'white', 'whiteSmoke', 'yellow', 'yellowGreen'
]
SCHEME_COLORS= ['bg1', 'tx1', 'bg2', 'tx2', 'accent1', 'accent2', 'accent3',
'accent4', 'accent5', 'accent6', 'hlink', 'folHlink', 'phClr', 'dk1', 'lt1',
'dk2', 'lt2'
]
class Transform(Serialisable):
pass
class SystemColor(Serialisable):
tagname = "sysClr"
namespace = DRAWING_NS
# color transform options
tint = NestedInteger(allow_none=True)
shade = NestedInteger(allow_none=True)
comp = Typed(expected_type=Transform, allow_none=True)
inv = Typed(expected_type=Transform, allow_none=True)
gray = Typed(expected_type=Transform, allow_none=True)
alpha = NestedInteger(allow_none=True)
alphaOff = NestedInteger(allow_none=True)
alphaMod = NestedInteger(allow_none=True)
hue = NestedInteger(allow_none=True)
hueOff = NestedInteger(allow_none=True)
hueMod = NestedInteger(allow_none=True)
sat = NestedInteger(allow_none=True)
satOff = NestedInteger(allow_none=True)
satMod = NestedInteger(allow_none=True)
lum = NestedInteger(allow_none=True)
lumOff = NestedInteger(allow_none=True)
lumMod = NestedInteger(allow_none=True)
red = NestedInteger(allow_none=True)
redOff = NestedInteger(allow_none=True)
redMod = NestedInteger(allow_none=True)
green = NestedInteger(allow_none=True)
greenOff = NestedInteger(allow_none=True)
greenMod = NestedInteger(allow_none=True)
blue = NestedInteger(allow_none=True)
blueOff = NestedInteger(allow_none=True)
blueMod = NestedInteger(allow_none=True)
gamma = Typed(expected_type=Transform, allow_none=True)
invGamma = Typed(expected_type=Transform, allow_none=True)
val = Set(values=( ['scrollBar', 'background', 'activeCaption',
'inactiveCaption', 'menu', 'window', 'windowFrame', 'menuText',
'windowText', 'captionText', 'activeBorder', 'inactiveBorder',
'appWorkspace', 'highlight', 'highlightText', 'btnFace', 'btnShadow',
'grayText', 'btnText', 'inactiveCaptionText', 'btnHighlight',
'3dDkShadow', '3dLight', 'infoText', 'infoBk', 'hotLight',
'gradientActiveCaption', 'gradientInactiveCaption', 'menuHighlight',
'menuBar'] )
)
lastClr = RGB(allow_none=True)
__elements__ = ('tint', 'shade', 'comp', 'inv', 'gray', "alpha",
"alphaOff", "alphaMod", "hue", "hueOff", "hueMod", "hueOff", "sat",
"satOff", "satMod", "lum", "lumOff", "lumMod", "red", "redOff", "redMod",
"green", "greenOff", "greenMod", "blue", "blueOff", "blueMod", "gamma",
"invGamma")
def __init__(self,
val="windowText",
lastClr=None,
tint=None,
shade=None,
comp=None,
inv=None,
gray=None,
alpha=None,
alphaOff=None,
alphaMod=None,
hue=None,
hueOff=None,
hueMod=None,
sat=None,
satOff=None,
satMod=None,
lum=None,
lumOff=None,
lumMod=None,
red=None,
redOff=None,
redMod=None,
green=None,
greenOff=None,
greenMod=None,
blue=None,
blueOff=None,
blueMod=None,
gamma=None,
invGamma=None
):
self.val = val
self.lastClr = lastClr
self.tint = tint
self.shade = shade
self.comp = comp
self.inv = inv
self.gray = gray
self.alpha = alpha
self.alphaOff = alphaOff
self.alphaMod = alphaMod
self.hue = hue
self.hueOff = hueOff
self.hueMod = hueMod
self.sat = sat
self.satOff = satOff
self.satMod = satMod
self.lum = lum
self.lumOff = lumOff
self.lumMod = lumMod
self.red = red
self.redOff = redOff
self.redMod = redMod
self.green = green
self.greenOff = greenOff
self.greenMod = greenMod
self.blue = blue
self.blueOff = blueOff
self.blueMod = blueMod
self.gamma = gamma
self.invGamma = invGamma
class HSLColor(Serialisable):
tagname = "hslClr"
hue = Integer()
sat = MinMax(min=0, max=100)
lum = MinMax(min=0, max=100)
#TODO add color transform options
def __init__(self,
hue=None,
sat=None,
lum=None,
):
self.hue = hue
self.sat = sat
self.lum = lum
class RGBPercent(Serialisable):
tagname = "rgbClr"
r = MinMax(min=0, max=100)
g = MinMax(min=0, max=100)
b = MinMax(min=0, max=100)
#TODO add color transform options
def __init__(self,
r=None,
g=None,
b=None,
):
self.r = r
self.g = g
self.b = b
class SchemeColor(Serialisable):
tagname = "schemeClr"
namespace = DRAWING_NS
tint = NestedInteger(allow_none=True)
shade = NestedInteger(allow_none=True)
comp = EmptyTag(allow_none=True)
inv = NestedInteger(allow_none=True)
gray = NestedInteger(allow_none=True)
alpha = NestedInteger(allow_none=True)
alphaOff = NestedInteger(allow_none=True)
alphaMod = NestedInteger(allow_none=True)
hue = NestedInteger(allow_none=True)
hueOff = NestedInteger(allow_none=True)
hueMod = NestedInteger(allow_none=True)
sat = NestedInteger(allow_none=True)
satOff = NestedInteger(allow_none=True)
satMod = NestedInteger(allow_none=True)
lum = NestedInteger(allow_none=True)
lumOff = NestedInteger(allow_none=True)
lumMod = NestedInteger(allow_none=True)
red = NestedInteger(allow_none=True)
redOff = NestedInteger(allow_none=True)
redMod = NestedInteger(allow_none=True)
green = NestedInteger(allow_none=True)
greenOff = NestedInteger(allow_none=True)
greenMod = NestedInteger(allow_none=True)
blue = NestedInteger(allow_none=True)
blueOff = NestedInteger(allow_none=True)
blueMod = NestedInteger(allow_none=True)
gamma = EmptyTag(allow_none=True)
invGamma = EmptyTag(allow_none=True)
val = Set(values=(['bg1', 'tx1', 'bg2', 'tx2', 'accent1', 'accent2',
'accent3', 'accent4', 'accent5', 'accent6', 'hlink', 'folHlink', 'phClr',
'dk1', 'lt1', 'dk2', 'lt2']))
__elements__ = ('tint', 'shade', 'comp', 'inv', 'gray', 'alpha',
'alphaOff', 'alphaMod', 'hue', 'hueOff', 'hueMod', 'sat', 'satOff',
'satMod', 'lum', 'lumMod', 'lumOff', 'red', 'redOff', 'redMod', 'green',
'greenOff', 'greenMod', 'blue', 'blueOff', 'blueMod', 'gamma',
'invGamma')
def __init__(self,
tint=None,
shade=None,
comp=None,
inv=None,
gray=None,
alpha=None,
alphaOff=None,
alphaMod=None,
hue=None,
hueOff=None,
hueMod=None,
sat=None,
satOff=None,
satMod=None,
lum=None,
lumOff=None,
lumMod=None,
red=None,
redOff=None,
redMod=None,
green=None,
greenOff=None,
greenMod=None,
blue=None,
blueOff=None,
blueMod=None,
gamma=None,
invGamma=None,
val=None,
):
self.tint = tint
self.shade = shade
self.comp = comp
self.inv = inv
self.gray = gray
self.alpha = alpha
self.alphaOff = alphaOff
self.alphaMod = alphaMod
self.hue = hue
self.hueOff = hueOff
self.hueMod = hueMod
self.sat = sat
self.satOff = satOff
self.satMod = satMod
self.lum = lum
self.lumOff = lumOff
self.lumMod = lumMod
self.red = red
self.redOff = redOff
self.redMod = redMod
self.green = green
self.greenOff = greenOff
self.greenMod = greenMod
self.blue = blue
self.blueOff = blueOff
self.blueMod = blueMod
self.gamma = gamma
self.invGamma = invGamma
self.val = val
class ColorChoice(Serialisable):
tagname = "colorChoice"
namespace = DRAWING_NS
scrgbClr = Typed(expected_type=RGBPercent, allow_none=True)
RGBPercent = Alias('scrgbClr')
srgbClr = NestedValue(expected_type=str, allow_none=True) # needs pattern and can have transform
RGB = Alias('srgbClr')
hslClr = Typed(expected_type=HSLColor, allow_none=True)
sysClr = Typed(expected_type=SystemColor, allow_none=True)
schemeClr = Typed(expected_type=SchemeColor, allow_none=True)
prstClr = NestedNoneSet(values=PRESET_COLORS)
__elements__ = ('scrgbClr', 'srgbClr', 'hslClr', 'sysClr', 'schemeClr', 'prstClr')
def __init__(self,
scrgbClr=None,
srgbClr=None,
hslClr=None,
sysClr=None,
schemeClr=None,
prstClr=None,
):
self.scrgbClr = scrgbClr
self.srgbClr = srgbClr
self.hslClr = hslClr
self.sysClr = sysClr
self.schemeClr = schemeClr
self.prstClr = prstClr
_COLOR_SET = ('dk1', 'lt1', 'dk2', 'lt2', 'accent1', 'accent2', 'accent3',
'accent4', 'accent5', 'accent6', 'hlink', 'folHlink')
class ColorMapping(Serialisable):
tagname = "clrMapOvr"
bg1 = Set(values=_COLOR_SET)
tx1 = Set(values=_COLOR_SET)
bg2 = Set(values=_COLOR_SET)
tx2 = Set(values=_COLOR_SET)
accent1 = Set(values=_COLOR_SET)
accent2 = Set(values=_COLOR_SET)
accent3 = Set(values=_COLOR_SET)
accent4 = Set(values=_COLOR_SET)
accent5 = Set(values=_COLOR_SET)
accent6 = Set(values=_COLOR_SET)
hlink = Set(values=_COLOR_SET)
folHlink = Set(values=_COLOR_SET)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
def __init__(self,
bg1="lt1",
tx1="dk1",
bg2="lt2",
tx2="dk2",
accent1="accent1",
accent2="accent2",
accent3="accent3",
accent4="accent4",
accent5="accent5",
accent6="accent6",
hlink="hlink",
folHlink="folHlink",
extLst=None,
):
self.bg1 = bg1
self.tx1 = tx1
self.bg2 = bg2
self.tx2 = tx2
self.accent1 = accent1
self.accent2 = accent2
self.accent3 = accent3
self.accent4 = accent4
self.accent5 = accent5
self.accent6 = accent6
self.hlink = hlink
self.folHlink = folHlink
self.extLst = extLst
class ColorChoiceDescriptor(Typed):
"""
Objects can choose from 7 different kinds of color system.
Assume RGBHex if a string is passed in.
"""
expected_type = ColorChoice
allow_none = True
def __set__(self, instance, value):
if isinstance(value, str):
value = ColorChoice(srgbClr=value)
else:
if hasattr(self, "namespace") and value is not None:
value.namespace = self.namespace
super(ColorChoiceDescriptor, self).__set__(instance, value)

View File

@ -0,0 +1,144 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Bool,
Integer,
String,
Alias,
)
from openpyxl.descriptors.excel import ExtensionList as OfficeArtExtensionList
from openpyxl.chart.shapes import GraphicalProperties
from openpyxl.chart.text import RichText
from .properties import (
NonVisualDrawingProps,
NonVisualDrawingShapeProps,
)
from .geometry import ShapeStyle
class Connection(Serialisable):
id = Integer()
idx = Integer()
def __init__(self,
id=None,
idx=None,
):
self.id = id
self.idx = idx
class ConnectorLocking(Serialisable):
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
def __init__(self,
extLst=None,
):
self.extLst = extLst
class NonVisualConnectorProperties(Serialisable):
cxnSpLocks = Typed(expected_type=ConnectorLocking, allow_none=True)
stCxn = Typed(expected_type=Connection, allow_none=True)
endCxn = Typed(expected_type=Connection, allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
def __init__(self,
cxnSpLocks=None,
stCxn=None,
endCxn=None,
extLst=None,
):
self.cxnSpLocks = cxnSpLocks
self.stCxn = stCxn
self.endCxn = endCxn
self.extLst = extLst
class ConnectorNonVisual(Serialisable):
cNvPr = Typed(expected_type=NonVisualDrawingProps, )
cNvCxnSpPr = Typed(expected_type=NonVisualConnectorProperties, )
__elements__ = ("cNvPr", "cNvCxnSpPr",)
def __init__(self,
cNvPr=None,
cNvCxnSpPr=None,
):
self.cNvPr = cNvPr
self.cNvCxnSpPr = cNvCxnSpPr
class ConnectorShape(Serialisable):
tagname = "cxnSp"
nvCxnSpPr = Typed(expected_type=ConnectorNonVisual)
spPr = Typed(expected_type=GraphicalProperties)
style = Typed(expected_type=ShapeStyle, allow_none=True)
macro = String(allow_none=True)
fPublished = Bool(allow_none=True)
def __init__(self,
nvCxnSpPr=None,
spPr=None,
style=None,
macro=None,
fPublished=None,
):
self.nvCxnSpPr = nvCxnSpPr
self.spPr = spPr
self.style = style
self.macro = macro
self.fPublished = fPublished
class ShapeMeta(Serialisable):
tagname = "nvSpPr"
cNvPr = Typed(expected_type=NonVisualDrawingProps)
cNvSpPr = Typed(expected_type=NonVisualDrawingShapeProps)
def __init__(self, cNvPr=None, cNvSpPr=None):
self.cNvPr = cNvPr
self.cNvSpPr = cNvSpPr
class Shape(Serialisable):
macro = String(allow_none=True)
textlink = String(allow_none=True)
fPublished = Bool(allow_none=True)
fLocksText = Bool(allow_none=True)
nvSpPr = Typed(expected_type=ShapeMeta, allow_none=True)
meta = Alias("nvSpPr")
spPr = Typed(expected_type=GraphicalProperties)
graphicalProperties = Alias("spPr")
style = Typed(expected_type=ShapeStyle, allow_none=True)
txBody = Typed(expected_type=RichText, allow_none=True)
def __init__(self,
macro=None,
textlink=None,
fPublished=None,
fLocksText=None,
nvSpPr=None,
spPr=None,
style=None,
txBody=None,
):
self.macro = macro
self.textlink = textlink
self.fPublished = fPublished
self.fLocksText = fLocksText
self.nvSpPr = nvSpPr
self.spPr = spPr
self.style = style
self.txBody = txBody

View File

@ -0,0 +1,102 @@
from __future__ import division
# Copyright (c) 2010-2022 openpyxl
import math
from openpyxl.compat import deprecated
from openpyxl.styles.colors import Color, BLACK, WHITE
from openpyxl.utils.units import (
pixels_to_EMU,
EMU_to_pixels,
short_color,
)
class Drawing(object):
""" a drawing object - eg container for shapes or charts
we assume user specifies dimensions in pixels; units are
converted to EMU in the drawing part
"""
count = 0
def __init__(self):
self.name = ''
self.description = ''
self.coordinates = ((1, 2), (16, 8))
self.left = 0
self.top = 0
self._width = 21 # default in px
self._height = 192 #default in px
self.resize_proportional = False
self.rotation = 0
self.anchortype = "absolute"
self.anchorcol = 0 # left cell
self.anchorrow = 0 # top row
@property
def width(self):
return self._width
@width.setter
def width(self, w):
if self.resize_proportional and w:
ratio = self._height / self._width
self._height = round(ratio * w)
self._width = w
@property
def height(self):
return self._height
@height.setter
def height(self, h):
if self.resize_proportional and h:
ratio = self._width / self._height
self._width = round(ratio * h)
self._height = h
def set_dimension(self, w=0, h=0):
xratio = w / self._width
yratio = h / self._height
if self.resize_proportional and w and h:
if (xratio * self._height) < h:
self._height = math.ceil(xratio * self._height)
self._width = w
else:
self._width = math.ceil(yratio * self._width)
self._height = h
@deprecated("Private method used when serialising")
def get_emu_dimensions(self):
""" return (x, y, w, h) in EMU """
return (pixels_to_EMU(self.left), pixels_to_EMU(self.top),
pixels_to_EMU(self._width), pixels_to_EMU(self._height))
@property
def anchor(self):
from .spreadsheet_drawing import (
OneCellAnchor,
TwoCellAnchor,
AbsoluteAnchor)
if self.anchortype == "absolute":
anchor = AbsoluteAnchor()
anchor.pos.x = pixels_to_EMU(self.left)
anchor.pos.y = pixels_to_EMU(self.top)
elif self.anchortype == "oneCell":
anchor = OneCellAnchor()
anchor._from.col = self.anchorcol
anchor._from.row = self.anchorrow
anchor.ext.width = pixels_to_EMU(self._width)
anchor.ext.height = pixels_to_EMU(self._height)
return anchor

View File

@ -0,0 +1,409 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
String,
Set,
Bool,
Integer,
NoneSet,
Float,
)
from .colors import ColorChoice
class TintEffect(Serialisable):
tagname = "tint"
hue = Integer()
amt = Integer()
def __init__(self,
hue=0,
amt=0,
):
self.hue = hue
self.amt = amt
class LuminanceEffect(Serialisable):
tagname = "lum"
bright = Integer() #Pct ?
contrast = Integer() #Pct#
def __init__(self,
bright=0,
contrast=0,
):
self.bright = bright
self.contrast = contrast
class HSLEffect(Serialisable):
hue = Integer()
sat = Integer()
lum = Integer()
def __init__(self,
hue=None,
sat=None,
lum=None,
):
self.hue = hue
self.sat = sat
self.lum = lum
class GrayscaleEffect(Serialisable):
tagname = "grayscl"
class FillOverlayEffect(Serialisable):
blend = Set(values=(['over', 'mult', 'screen', 'darken', 'lighten']))
def __init__(self,
blend=None,
):
self.blend = blend
class DuotoneEffect(Serialisable):
pass
class ColorReplaceEffect(Serialisable):
pass
class Color(Serialisable):
pass
class ColorChangeEffect(Serialisable):
useA = Bool(allow_none=True)
clrFrom = Typed(expected_type=Color, )
clrTo = Typed(expected_type=Color, )
def __init__(self,
useA=None,
clrFrom=None,
clrTo=None,
):
self.useA = useA
self.clrFrom = clrFrom
self.clrTo = clrTo
class BlurEffect(Serialisable):
rad = Float()
grow = Bool(allow_none=True)
def __init__(self,
rad=None,
grow=None,
):
self.rad = rad
self.grow = grow
class BiLevelEffect(Serialisable):
thresh = Integer()
def __init__(self,
thresh=None,
):
self.thresh = thresh
class AlphaReplaceEffect(Serialisable):
a = Integer()
def __init__(self,
a=None,
):
self.a = a
class AlphaModulateFixedEffect(Serialisable):
amt = Integer()
def __init__(self,
amt=None,
):
self.amt = amt
class EffectContainer(Serialisable):
type = Set(values=(['sib', 'tree']))
name = String(allow_none=True)
def __init__(self,
type=None,
name=None,
):
self.type = type
self.name = name
class AlphaModulateEffect(Serialisable):
cont = Typed(expected_type=EffectContainer, )
def __init__(self,
cont=None,
):
self.cont = cont
class AlphaInverseEffect(Serialisable):
pass
class AlphaFloorEffect(Serialisable):
pass
class AlphaCeilingEffect(Serialisable):
pass
class AlphaBiLevelEffect(Serialisable):
thresh = Integer()
def __init__(self,
thresh=None,
):
self.thresh = thresh
class GlowEffect(ColorChoice):
rad = Float()
# uses element group EG_ColorChoice
scrgbClr = ColorChoice.scrgbClr
srgbClr = ColorChoice.srgbClr
hslClr = ColorChoice.hslClr
sysClr = ColorChoice.sysClr
schemeClr = ColorChoice.schemeClr
prstClr = ColorChoice.prstClr
__elements__ = ('scrgbClr', 'srgbClr', 'hslClr', 'sysClr', 'schemeClr', 'prstClr')
def __init__(self,
rad=None,
**kw
):
self.rad = rad
super(GlowEffect, self).__init__(**kw)
class InnerShadowEffect(ColorChoice):
blurRad = Float()
dist = Float()
dir = Integer()
# uses element group EG_ColorChoice
scrgbClr = ColorChoice.scrgbClr
srgbClr = ColorChoice.srgbClr
hslClr = ColorChoice.hslClr
sysClr = ColorChoice.sysClr
schemeClr = ColorChoice.schemeClr
prstClr = ColorChoice.prstClr
__elements__ = ('scrgbClr', 'srgbClr', 'hslClr', 'sysClr', 'schemeClr', 'prstClr')
def __init__(self,
blurRad=None,
dist=None,
dir=None,
**kw
):
self.blurRad = blurRad
self.dist = dist
self.dir = dir
super(InnerShadowEffect, self).__init__(**kw)
class OuterShadow(ColorChoice):
tagname = "outerShdw"
blurRad = Float(allow_none=True)
dist = Float(allow_none=True)
dir = Integer(allow_none=True)
sx = Integer(allow_none=True)
sy = Integer(allow_none=True)
kx = Integer(allow_none=True)
ky = Integer(allow_none=True)
algn = Set(values=['tl', 't', 'tr', 'l', 'ctr', 'r', 'bl', 'b', 'br'])
rotWithShape = Bool(allow_none=True)
# uses element group EG_ColorChoice
scrgbClr = ColorChoice.scrgbClr
srgbClr = ColorChoice.srgbClr
hslClr = ColorChoice.hslClr
sysClr = ColorChoice.sysClr
schemeClr = ColorChoice.schemeClr
prstClr = ColorChoice.prstClr
__elements__ = ('scrgbClr', 'srgbClr', 'hslClr', 'sysClr', 'schemeClr', 'prstClr')
def __init__(self,
blurRad=None,
dist=None,
dir=None,
sx=None,
sy=None,
kx=None,
ky=None,
algn=None,
rotWithShape=None,
**kw
):
self.blurRad = blurRad
self.dist = dist
self.dir = dir
self.sx = sx
self.sy = sy
self.kx = kx
self.ky = ky
self.algn = algn
self.rotWithShape = rotWithShape
super(OuterShadow, self).__init__(**kw)
class PresetShadowEffect(ColorChoice):
prst = Set(values=(['shdw1', 'shdw2', 'shdw3', 'shdw4', 'shdw5', 'shdw6',
'shdw7', 'shdw8', 'shdw9', 'shdw10', 'shdw11', 'shdw12', 'shdw13',
'shdw14', 'shdw15', 'shdw16', 'shdw17', 'shdw18', 'shdw19', 'shdw20']))
dist = Float()
dir = Integer()
# uses element group EG_ColorChoice
scrgbClr = ColorChoice.scrgbClr
srgbClr = ColorChoice.srgbClr
hslClr = ColorChoice.hslClr
sysClr = ColorChoice.sysClr
schemeClr = ColorChoice.schemeClr
prstClr = ColorChoice.prstClr
__elements__ = ('scrgbClr', 'srgbClr', 'hslClr', 'sysClr', 'schemeClr', 'prstClr')
def __init__(self,
prst=None,
dist=None,
dir=None,
**kw
):
self.prst = prst
self.dist = dist
self.dir = dir
super(PresetShadowEffect, self).__init__(**kw)
class ReflectionEffect(Serialisable):
blurRad = Float()
stA = Integer()
stPos = Integer()
endA = Integer()
endPos = Integer()
dist = Float()
dir = Integer()
fadeDir = Integer()
sx = Integer()
sy = Integer()
kx = Integer()
ky = Integer()
algn = Set(values=(['tl', 't', 'tr', 'l', 'ctr', 'r', 'bl', 'b', 'br']))
rotWithShape = Bool(allow_none=True)
def __init__(self,
blurRad=None,
stA=None,
stPos=None,
endA=None,
endPos=None,
dist=None,
dir=None,
fadeDir=None,
sx=None,
sy=None,
kx=None,
ky=None,
algn=None,
rotWithShape=None,
):
self.blurRad = blurRad
self.stA = stA
self.stPos = stPos
self.endA = endA
self.endPos = endPos
self.dist = dist
self.dir = dir
self.fadeDir = fadeDir
self.sx = sx
self.sy = sy
self.kx = kx
self.ky = ky
self.algn = algn
self.rotWithShape = rotWithShape
class SoftEdgesEffect(Serialisable):
rad = Float()
def __init__(self,
rad=None,
):
self.rad = rad
class EffectList(Serialisable):
blur = Typed(expected_type=BlurEffect, allow_none=True)
fillOverlay = Typed(expected_type=FillOverlayEffect, allow_none=True)
glow = Typed(expected_type=GlowEffect, allow_none=True)
innerShdw = Typed(expected_type=InnerShadowEffect, allow_none=True)
outerShdw = Typed(expected_type=OuterShadow, allow_none=True)
prstShdw = Typed(expected_type=PresetShadowEffect, allow_none=True)
reflection = Typed(expected_type=ReflectionEffect, allow_none=True)
softEdge = Typed(expected_type=SoftEdgesEffect, allow_none=True)
__elements__ = ('blur', 'fillOverlay', 'glow', 'innerShdw', 'outerShdw',
'prstShdw', 'reflection', 'softEdge')
def __init__(self,
blur=None,
fillOverlay=None,
glow=None,
innerShdw=None,
outerShdw=None,
prstShdw=None,
reflection=None,
softEdge=None,
):
self.blur = blur
self.fillOverlay = fillOverlay
self.glow = glow
self.innerShdw = innerShdw
self.outerShdw = outerShdw
self.prstShdw = prstShdw
self.reflection = reflection
self.softEdge = softEdge

View File

@ -0,0 +1,410 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Alias,
Bool,
Integer,
Set,
NoneSet,
Typed,
MinMax,
Sequence,
)
from openpyxl.descriptors.excel import (
Relation,
Percentage,
)
from openpyxl.descriptors.nested import NestedNoneSet, NestedValue
from openpyxl.descriptors.sequence import NestedSequence
from openpyxl.xml.constants import DRAWING_NS
from .colors import (
ColorChoice,
HSLColor,
SystemColor,
SchemeColor,
RGBPercent,
PRESET_COLORS,
)
from openpyxl.descriptors.excel import ExtensionList as OfficeArtExtensionList
from .effect import *
"""
Fill elements from drawing main schema
"""
class PatternFillProperties(Serialisable):
tagname = "pattFill"
namespace = DRAWING_NS
prst = NoneSet(values=(['pct5', 'pct10', 'pct20', 'pct25', 'pct30', 'pct40',
'pct50', 'pct60', 'pct70', 'pct75', 'pct80', 'pct90', 'horz', 'vert',
'ltHorz', 'ltVert', 'dkHorz', 'dkVert', 'narHorz', 'narVert', 'dashHorz',
'dashVert', 'cross', 'dnDiag', 'upDiag', 'ltDnDiag', 'ltUpDiag',
'dkDnDiag', 'dkUpDiag', 'wdDnDiag', 'wdUpDiag', 'dashDnDiag',
'dashUpDiag', 'diagCross', 'smCheck', 'lgCheck', 'smGrid', 'lgGrid',
'dotGrid', 'smConfetti', 'lgConfetti', 'horzBrick', 'diagBrick',
'solidDmnd', 'openDmnd', 'dotDmnd', 'plaid', 'sphere', 'weave', 'divot',
'shingle', 'wave', 'trellis', 'zigZag']))
preset = Alias("prst")
fgClr = Typed(expected_type=ColorChoice, allow_none=True)
foreground = Alias("fgClr")
bgClr = Typed(expected_type=ColorChoice, allow_none=True)
background = Alias("bgClr")
__elements__ = ("fgClr", "bgClr")
def __init__(self,
prst=None,
fgClr=None,
bgClr=None,
):
self.prst = prst
self.fgClr = fgClr
self.bgClr = bgClr
class RelativeRect(Serialisable):
tagname = "rect"
namespace = DRAWING_NS
l = Percentage(allow_none=True)
left = Alias('l')
t = Percentage(allow_none=True)
top = Alias('t')
r = Percentage(allow_none=True)
right = Alias('r')
b = Percentage(allow_none=True)
bottom = Alias('b')
def __init__(self,
l=None,
t=None,
r=None,
b=None,
):
self.l = l
self.t = t
self.r = r
self.b = b
class StretchInfoProperties(Serialisable):
tagname = "stretch"
namespace = DRAWING_NS
fillRect = Typed(expected_type=RelativeRect, allow_none=True)
def __init__(self,
fillRect=RelativeRect(),
):
self.fillRect = fillRect
class GradientStop(Serialisable):
tagname = "gs"
namespace = DRAWING_NS
pos = MinMax(min=0, max=100000, allow_none=True)
# Color Choice Group
scrgbClr = Typed(expected_type=RGBPercent, allow_none=True)
RGBPercent = Alias('scrgbClr')
srgbClr = NestedValue(expected_type=str, allow_none=True) # needs pattern and can have transform
RGB = Alias('srgbClr')
hslClr = Typed(expected_type=HSLColor, allow_none=True)
sysClr = Typed(expected_type=SystemColor, allow_none=True)
schemeClr = Typed(expected_type=SchemeColor, allow_none=True)
prstClr = NestedNoneSet(values=PRESET_COLORS)
__elements__ = ('scrgbClr', 'srgbClr', 'hslClr', 'sysClr', 'schemeClr', 'prstClr')
def __init__(self,
pos=None,
scrgbClr=None,
srgbClr=None,
hslClr=None,
sysClr=None,
schemeClr=None,
prstClr=None,
):
if pos is None:
pos = 0
self.pos = pos
self.scrgbClr = scrgbClr
self.srgbClr = srgbClr
self.hslClr = hslClr
self.sysClr = sysClr
self.schemeClr = schemeClr
self.prstClr = prstClr
class LinearShadeProperties(Serialisable):
tagname = "lin"
namespace = DRAWING_NS
ang = Integer()
scaled = Bool(allow_none=True)
def __init__(self,
ang=None,
scaled=None,
):
self.ang = ang
self.scaled = scaled
class PathShadeProperties(Serialisable):
tagname = "path"
namespace = DRAWING_NS
path = Set(values=(['shape', 'circle', 'rect']))
fillToRect = Typed(expected_type=RelativeRect, allow_none=True)
def __init__(self,
path=None,
fillToRect=None,
):
self.path = path
self.fillToRect = fillToRect
class GradientFillProperties(Serialisable):
tagname = "gradFill"
namespace = DRAWING_NS
flip = NoneSet(values=(['x', 'y', 'xy']))
rotWithShape = Bool(allow_none=True)
gsLst = NestedSequence(expected_type=GradientStop, count=False)
stop_list = Alias("gsLst")
lin = Typed(expected_type=LinearShadeProperties, allow_none=True)
linear = Alias("lin")
path = Typed(expected_type=PathShadeProperties, allow_none=True)
tileRect = Typed(expected_type=RelativeRect, allow_none=True)
__elements__ = ('gsLst', 'lin', 'path', 'tileRect')
def __init__(self,
flip=None,
rotWithShape=None,
gsLst=(),
lin=None,
path=None,
tileRect=None,
):
self.flip = flip
self.rotWithShape = rotWithShape
self.gsLst = gsLst
self.lin = lin
self.path = path
self.tileRect = tileRect
class SolidColorFillProperties(Serialisable):
tagname = "solidFill"
# uses element group EG_ColorChoice
scrgbClr = Typed(expected_type=RGBPercent, allow_none=True)
RGBPercent = Alias('scrgbClr')
srgbClr = NestedValue(expected_type=str, allow_none=True) # needs pattern and can have transform
RGB = Alias('srgbClr')
hslClr = Typed(expected_type=HSLColor, allow_none=True)
sysClr = Typed(expected_type=SystemColor, allow_none=True)
schemeClr = Typed(expected_type=SchemeColor, allow_none=True)
prstClr = NestedNoneSet(values=PRESET_COLORS)
__elements__ = ('scrgbClr', 'srgbClr', 'hslClr', 'sysClr', 'schemeClr', 'prstClr')
def __init__(self,
scrgbClr=None,
srgbClr=None,
hslClr=None,
sysClr=None,
schemeClr=None,
prstClr=None,
):
self.scrgbClr = scrgbClr
self.srgbClr = srgbClr
self.hslClr = hslClr
self.sysClr = sysClr
self.schemeClr = schemeClr
self.prstClr = prstClr
class Blip(Serialisable):
tagname = "blip"
namespace = DRAWING_NS
#Using attribute groupAG_Blob
cstate = NoneSet(values=(['email', 'screen', 'print', 'hqprint']))
embed = Relation() #rId
link = Relation() #hyperlink
noGrp = Bool(allow_none=True)
noSelect = Bool(allow_none=True)
noRot = Bool(allow_none=True)
noChangeAspect = Bool(allow_none=True)
noMove = Bool(allow_none=True)
noResize = Bool(allow_none=True)
noEditPoints = Bool(allow_none=True)
noAdjustHandles = Bool(allow_none=True)
noChangeArrowheads = Bool(allow_none=True)
noChangeShapeType = Bool(allow_none=True)
# some elements are choice
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
alphaBiLevel = Typed(expected_type=AlphaBiLevelEffect, allow_none=True)
alphaCeiling = Typed(expected_type=AlphaCeilingEffect, allow_none=True)
alphaFloor = Typed(expected_type=AlphaFloorEffect, allow_none=True)
alphaInv = Typed(expected_type=AlphaInverseEffect, allow_none=True)
alphaMod = Typed(expected_type=AlphaModulateEffect, allow_none=True)
alphaModFix = Typed(expected_type=AlphaModulateFixedEffect, allow_none=True)
alphaRepl = Typed(expected_type=AlphaReplaceEffect, allow_none=True)
biLevel = Typed(expected_type=BiLevelEffect, allow_none=True)
blur = Typed(expected_type=BlurEffect, allow_none=True)
clrChange = Typed(expected_type=ColorChangeEffect, allow_none=True)
clrRepl = Typed(expected_type=ColorReplaceEffect, allow_none=True)
duotone = Typed(expected_type=DuotoneEffect, allow_none=True)
fillOverlay = Typed(expected_type=FillOverlayEffect, allow_none=True)
grayscl = Typed(expected_type=GrayscaleEffect, allow_none=True)
hsl = Typed(expected_type=HSLEffect, allow_none=True)
lum = Typed(expected_type=LuminanceEffect, allow_none=True)
tint = Typed(expected_type=TintEffect, allow_none=True)
__elements__ = ('alphaBiLevel', 'alphaCeiling', 'alphaFloor', 'alphaInv',
'alphaMod', 'alphaModFix', 'alphaRepl', 'biLevel', 'blur', 'clrChange',
'clrRepl', 'duotone', 'fillOverlay', 'grayscl', 'hsl', 'lum', 'tint')
def __init__(self,
cstate=None,
embed=None,
link=None,
noGrp=None,
noSelect=None,
noRot=None,
noChangeAspect=None,
noMove=None,
noResize=None,
noEditPoints=None,
noAdjustHandles=None,
noChangeArrowheads=None,
noChangeShapeType=None,
extLst=None,
alphaBiLevel=None,
alphaCeiling=None,
alphaFloor=None,
alphaInv=None,
alphaMod=None,
alphaModFix=None,
alphaRepl=None,
biLevel=None,
blur=None,
clrChange=None,
clrRepl=None,
duotone=None,
fillOverlay=None,
grayscl=None,
hsl=None,
lum=None,
tint=None,
):
self.cstate = cstate
self.embed = embed
self.link = link
self.noGrp = noGrp
self.noSelect = noSelect
self.noRot = noRot
self.noChangeAspect = noChangeAspect
self.noMove = noMove
self.noResize = noResize
self.noEditPoints = noEditPoints
self.noAdjustHandles = noAdjustHandles
self.noChangeArrowheads = noChangeArrowheads
self.noChangeShapeType = noChangeShapeType
self.extLst = extLst
self.alphaBiLevel = alphaBiLevel
self.alphaCeiling = alphaCeiling
self.alphaFloor = alphaFloor
self.alphaInv = alphaInv
self.alphaMod = alphaMod
self.alphaModFix = alphaModFix
self.alphaRepl = alphaRepl
self.biLevel = biLevel
self.blur = blur
self.clrChange = clrChange
self.clrRepl = clrRepl
self.duotone = duotone
self.fillOverlay = fillOverlay
self.grayscl = grayscl
self.hsl = hsl
self.lum = lum
self.tint = tint
class TileInfoProperties(Serialisable):
tx = Integer(allow_none=True)
ty = Integer(allow_none=True)
sx = Integer(allow_none=True)
sy = Integer(allow_none=True)
flip = NoneSet(values=(['x', 'y', 'xy']))
algn = Set(values=(['tl', 't', 'tr', 'l', 'ctr', 'r', 'bl', 'b', 'br']))
def __init__(self,
tx=None,
ty=None,
sx=None,
sy=None,
flip=None,
algn=None,
):
self.tx = tx
self.ty = ty
self.sx = sx
self.sy = sy
self.flip = flip
self.algn = algn
class BlipFillProperties(Serialisable):
tagname = "blipFill"
dpi = Integer(allow_none=True)
rotWithShape = Bool(allow_none=True)
blip = Typed(expected_type=Blip, allow_none=True)
srcRect = Typed(expected_type=RelativeRect, allow_none=True)
tile = Typed(expected_type=TileInfoProperties, allow_none=True)
stretch = Typed(expected_type=StretchInfoProperties, allow_none=True)
__elements__ = ("blip", "srcRect", "tile", "stretch")
def __init__(self,
dpi=None,
rotWithShape=None,
blip=None,
tile=None,
stretch=StretchInfoProperties(),
srcRect=None,
):
self.dpi = dpi
self.rotWithShape = rotWithShape
self.blip = blip
self.tile = tile
self.stretch = stretch
self.srcRect = srcRect

View File

@ -0,0 +1,595 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Float,
Integer,
Bool,
MinMax,
Set,
NoneSet,
String,
Alias,
)
from openpyxl.descriptors.excel import Coordinate, Percentage
from openpyxl.descriptors.nested import (
EmptyTag
)
from openpyxl.descriptors.excel import ExtensionList as OfficeArtExtensionList
from .colors import ColorChoiceDescriptor
from .fill import (
GradientFillProperties,
BlipFillProperties,
PatternFillProperties,
)
from .line import LineProperties
from openpyxl.styles.colors import Color
from openpyxl.xml.constants import DRAWING_NS
class Point2D(Serialisable):
tagname = "off"
namespace = DRAWING_NS
x = Coordinate()
y = Coordinate()
def __init__(self,
x=None,
y=None,
):
self.x = x
self.y = y
class PositiveSize2D(Serialisable):
tagname = "ext"
namespace = DRAWING_NS
"""
Dimensions in EMUs
"""
cx = Integer()
width = Alias('cx')
cy = Integer()
height = Alias('cy')
def __init__(self,
cx=None,
cy=None,
):
self.cx = cx
self.cy = cy
class Transform2D(Serialisable):
tagname = "xfrm"
namespace = DRAWING_NS
rot = Integer(allow_none=True)
flipH = Bool(allow_none=True)
flipV = Bool(allow_none=True)
off = Typed(expected_type=Point2D, allow_none=True)
ext = Typed(expected_type=PositiveSize2D, allow_none=True)
chOff = Typed(expected_type=Point2D, allow_none=True)
chExt = Typed(expected_type=PositiveSize2D, allow_none=True)
__elements__ = ('off', 'ext', 'chOff', 'chExt')
def __init__(self,
rot=None,
flipH=None,
flipV=None,
off=None,
ext=None,
chOff=None,
chExt=None,
):
self.rot = rot
self.flipH = flipH
self.flipV = flipV
self.off = off
self.ext = ext
self.chOff = chOff
self.chExt = chExt
class GroupTransform2D(Serialisable):
tagname = "xfrm"
namespace = DRAWING_NS
rot = Integer(allow_none=True)
flipH = Bool(allow_none=True)
flipV = Bool(allow_none=True)
off = Typed(expected_type=Point2D, allow_none=True)
ext = Typed(expected_type=PositiveSize2D, allow_none=True)
chOff = Typed(expected_type=Point2D, allow_none=True)
chExt = Typed(expected_type=PositiveSize2D, allow_none=True)
__elements__ = ("off", "ext", "chOff", "chExt")
def __init__(self,
rot=0,
flipH=None,
flipV=None,
off=None,
ext=None,
chOff=None,
chExt=None,
):
self.rot = rot
self.flipH = flipH
self.flipV = flipV
self.off = off
self.ext = ext
self.chOff = chOff
self.chExt = chExt
class SphereCoords(Serialisable):
tagname = "sphereCoords" # usually
lat = Integer()
lon = Integer()
rev = Integer()
def __init__(self,
lat=None,
lon=None,
rev=None,
):
self.lat = lat
self.lon = lon
self.rev = rev
class Camera(Serialisable):
tagname = "camera"
prst = Set(values=[
'legacyObliqueTopLeft', 'legacyObliqueTop', 'legacyObliqueTopRight', 'legacyObliqueLeft',
'legacyObliqueFront', 'legacyObliqueRight', 'legacyObliqueBottomLeft',
'legacyObliqueBottom', 'legacyObliqueBottomRight', 'legacyPerspectiveTopLeft',
'legacyPerspectiveTop', 'legacyPerspectiveTopRight', 'legacyPerspectiveLeft',
'legacyPerspectiveFront', 'legacyPerspectiveRight', 'legacyPerspectiveBottomLeft',
'legacyPerspectiveBottom', 'legacyPerspectiveBottomRight', 'orthographicFront',
'isometricTopUp', 'isometricTopDown', 'isometricBottomUp', 'isometricBottomDown',
'isometricLeftUp', 'isometricLeftDown', 'isometricRightUp', 'isometricRightDown',
'isometricOffAxis1Left', 'isometricOffAxis1Right', 'isometricOffAxis1Top',
'isometricOffAxis2Left', 'isometricOffAxis2Right', 'isometricOffAxis2Top',
'isometricOffAxis3Left', 'isometricOffAxis3Right', 'isometricOffAxis3Bottom',
'isometricOffAxis4Left', 'isometricOffAxis4Right', 'isometricOffAxis4Bottom',
'obliqueTopLeft', 'obliqueTop', 'obliqueTopRight', 'obliqueLeft', 'obliqueRight',
'obliqueBottomLeft', 'obliqueBottom', 'obliqueBottomRight', 'perspectiveFront',
'perspectiveLeft', 'perspectiveRight', 'perspectiveAbove', 'perspectiveBelow',
'perspectiveAboveLeftFacing', 'perspectiveAboveRightFacing',
'perspectiveContrastingLeftFacing', 'perspectiveContrastingRightFacing',
'perspectiveHeroicLeftFacing', 'perspectiveHeroicRightFacing',
'perspectiveHeroicExtremeLeftFacing', 'perspectiveHeroicExtremeRightFacing',
'perspectiveRelaxed', 'perspectiveRelaxedModerately'])
fov = Integer(allow_none=True)
zoom = Typed(expected_type=Percentage, allow_none=True)
rot = Typed(expected_type=SphereCoords, allow_none=True)
def __init__(self,
prst=None,
fov=None,
zoom=None,
rot=None,
):
self.prst = prst
self.fov = fov
self.zoom = zoom
self.rot = rot
class LightRig(Serialisable):
tagname = "lightRig"
rig = Set(values=['legacyFlat1', 'legacyFlat2', 'legacyFlat3', 'legacyFlat4', 'legacyNormal1',
'legacyNormal2', 'legacyNormal3', 'legacyNormal4', 'legacyHarsh1',
'legacyHarsh2', 'legacyHarsh3', 'legacyHarsh4', 'threePt', 'balanced',
'soft', 'harsh', 'flood', 'contrasting', 'morning', 'sunrise', 'sunset',
'chilly', 'freezing', 'flat', 'twoPt', 'glow', 'brightRoom']
)
dir = Set(values=(['tl', 't', 'tr', 'l', 'r', 'bl', 'b', 'br']))
rot = Typed(expected_type=SphereCoords, allow_none=True)
def __init__(self,
rig=None,
dir=None,
rot=None,
):
self.rig = rig
self.dir = dir
self.rot = rot
class Vector3D(Serialisable):
tagname = "vector"
dx = Integer() # can be in or universl measure :-/
dy = Integer()
dz = Integer()
def __init__(self,
dx=None,
dy=None,
dz=None,
):
self.dx = dx
self.dy = dy
self.dz = dz
class Point3D(Serialisable):
tagname = "anchor"
x = Integer()
y = Integer()
z = Integer()
def __init__(self,
x=None,
y=None,
z=None,
):
self.x = x
self.y = y
self.z = z
class Backdrop(Serialisable):
anchor = Typed(expected_type=Point3D, )
norm = Typed(expected_type=Vector3D, )
up = Typed(expected_type=Vector3D, )
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
def __init__(self,
anchor=None,
norm=None,
up=None,
extLst=None,
):
self.anchor = anchor
self.norm = norm
self.up = up
self.extLst = extLst
class Scene3D(Serialisable):
camera = Typed(expected_type=Camera, )
lightRig = Typed(expected_type=LightRig, )
backdrop = Typed(expected_type=Backdrop, allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
def __init__(self,
camera=None,
lightRig=None,
backdrop=None,
extLst=None,
):
self.camera = camera
self.lightRig = lightRig
self.backdrop = backdrop
self.extLst = extLst
class Bevel(Serialisable):
tagname = "bevel"
w = Integer()
h = Integer()
prst = NoneSet(values=
['relaxedInset', 'circle', 'slope', 'cross', 'angle',
'softRound', 'convex', 'coolSlant', 'divot', 'riblet',
'hardEdge', 'artDeco']
)
def __init__(self,
w=None,
h=None,
prst=None,
):
self.w = w
self.h = h
self.prst = prst
class Shape3D(Serialisable):
namespace = DRAWING_NS
z = Typed(expected_type=Coordinate, allow_none=True)
extrusionH = Integer(allow_none=True)
contourW = Integer(allow_none=True)
prstMaterial = NoneSet(values=[
'legacyMatte','legacyPlastic', 'legacyMetal', 'legacyWireframe', 'matte', 'plastic',
'metal', 'warmMatte', 'translucentPowder', 'powder', 'dkEdge',
'softEdge', 'clear', 'flat', 'softmetal']
)
bevelT = Typed(expected_type=Bevel, allow_none=True)
bevelB = Typed(expected_type=Bevel, allow_none=True)
extrusionClr = Typed(expected_type=Color, allow_none=True)
contourClr = Typed(expected_type=Color, allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
def __init__(self,
z=None,
extrusionH=None,
contourW=None,
prstMaterial=None,
bevelT=None,
bevelB=None,
extrusionClr=None,
contourClr=None,
extLst=None,
):
self.z = z
self.extrusionH = extrusionH
self.contourW = contourW
self.prstMaterial = prstMaterial
self.bevelT = bevelT
self.bevelB = bevelB
self.extrusionClr = extrusionClr
self.contourClr = contourClr
self.extLst = extLst
class Path2D(Serialisable):
w = Float()
h = Float()
fill = NoneSet(values=(['norm', 'lighten', 'lightenLess', 'darken', 'darkenLess']))
stroke = Bool(allow_none=True)
extrusionOk = Bool(allow_none=True)
def __init__(self,
w=None,
h=None,
fill=None,
stroke=None,
extrusionOk=None,
):
self.w = w
self.h = h
self.fill = fill
self.stroke = stroke
self.extrusionOk = extrusionOk
class Path2DList(Serialisable):
path = Typed(expected_type=Path2D, allow_none=True)
def __init__(self,
path=None,
):
self.path = path
class GeomRect(Serialisable):
l = Coordinate()
t = Coordinate()
r = Coordinate()
b = Coordinate()
def __init__(self,
l=None,
t=None,
r=None,
b=None,
):
self.l = l
self.t = t
self.r = r
self.b = b
class AdjPoint2D(Serialisable):
x = Coordinate()
y = Coordinate()
def __init__(self,
x=None,
y=None,
):
self.x = x
self.y = y
class ConnectionSite(Serialisable):
ang = MinMax(min=0, max=360) # guess work, can also be a name
pos = Typed(expected_type=AdjPoint2D, )
def __init__(self,
ang=None,
pos=None,
):
self.ang = ang
self.pos = pos
class ConnectionSiteList(Serialisable):
cxn = Typed(expected_type=ConnectionSite, allow_none=True)
def __init__(self,
cxn=None,
):
self.cxn = cxn
class AdjustHandleList(Serialisable):
pass
class GeomGuide(Serialisable):
name = String()
fmla = String()
def __init__(self,
name=None,
fmla=None,
):
self.name = name
self.fmla = fmla
class GeomGuideList(Serialisable):
gd = Typed(expected_type=GeomGuide, allow_none=True)
def __init__(self,
gd=None,
):
self.gd = gd
class CustomGeometry2D(Serialisable):
avLst = Typed(expected_type=GeomGuideList, allow_none=True)
gdLst = Typed(expected_type=GeomGuideList, allow_none=True)
ahLst = Typed(expected_type=AdjustHandleList, allow_none=True)
cxnLst = Typed(expected_type=ConnectionSiteList, allow_none=True)
#rect = Typed(expected_type=GeomRect, allow_none=True)
pathLst = Typed(expected_type=Path2DList, )
def __init__(self,
avLst=None,
gdLst=None,
ahLst=None,
cxnLst=None,
rect=None,
pathLst=None,
):
self.avLst = avLst
self.gdLst = gdLst
self.ahLst = ahLst
self.cxnLst = cxnLst
self.rect = None
self.pathLst = pathLst
class PresetGeometry2D(Serialisable):
namespace = DRAWING_NS
prst = Set(values=(
['line', 'lineInv', 'triangle', 'rtTriangle', 'rect',
'diamond', 'parallelogram', 'trapezoid', 'nonIsoscelesTrapezoid',
'pentagon', 'hexagon', 'heptagon', 'octagon', 'decagon', 'dodecagon',
'star4', 'star5', 'star6', 'star7', 'star8', 'star10', 'star12',
'star16', 'star24', 'star32', 'roundRect', 'round1Rect',
'round2SameRect', 'round2DiagRect', 'snipRoundRect', 'snip1Rect',
'snip2SameRect', 'snip2DiagRect', 'plaque', 'ellipse', 'teardrop',
'homePlate', 'chevron', 'pieWedge', 'pie', 'blockArc', 'donut',
'noSmoking', 'rightArrow', 'leftArrow', 'upArrow', 'downArrow',
'stripedRightArrow', 'notchedRightArrow', 'bentUpArrow',
'leftRightArrow', 'upDownArrow', 'leftUpArrow', 'leftRightUpArrow',
'quadArrow', 'leftArrowCallout', 'rightArrowCallout', 'upArrowCallout',
'downArrowCallout', 'leftRightArrowCallout', 'upDownArrowCallout',
'quadArrowCallout', 'bentArrow', 'uturnArrow', 'circularArrow',
'leftCircularArrow', 'leftRightCircularArrow', 'curvedRightArrow',
'curvedLeftArrow', 'curvedUpArrow', 'curvedDownArrow', 'swooshArrow',
'cube', 'can', 'lightningBolt', 'heart', 'sun', 'moon', 'smileyFace',
'irregularSeal1', 'irregularSeal2', 'foldedCorner', 'bevel', 'frame',
'halfFrame', 'corner', 'diagStripe', 'chord', 'arc', 'leftBracket',
'rightBracket', 'leftBrace', 'rightBrace', 'bracketPair', 'bracePair',
'straightConnector1', 'bentConnector2', 'bentConnector3',
'bentConnector4', 'bentConnector5', 'curvedConnector2',
'curvedConnector3', 'curvedConnector4', 'curvedConnector5', 'callout1',
'callout2', 'callout3', 'accentCallout1', 'accentCallout2',
'accentCallout3', 'borderCallout1', 'borderCallout2', 'borderCallout3',
'accentBorderCallout1', 'accentBorderCallout2', 'accentBorderCallout3',
'wedgeRectCallout', 'wedgeRoundRectCallout', 'wedgeEllipseCallout',
'cloudCallout', 'cloud', 'ribbon', 'ribbon2', 'ellipseRibbon',
'ellipseRibbon2', 'leftRightRibbon', 'verticalScroll',
'horizontalScroll', 'wave', 'doubleWave', 'plus', 'flowChartProcess',
'flowChartDecision', 'flowChartInputOutput',
'flowChartPredefinedProcess', 'flowChartInternalStorage',
'flowChartDocument', 'flowChartMultidocument', 'flowChartTerminator',
'flowChartPreparation', 'flowChartManualInput',
'flowChartManualOperation', 'flowChartConnector', 'flowChartPunchedCard',
'flowChartPunchedTape', 'flowChartSummingJunction', 'flowChartOr',
'flowChartCollate', 'flowChartSort', 'flowChartExtract',
'flowChartMerge', 'flowChartOfflineStorage', 'flowChartOnlineStorage',
'flowChartMagneticTape', 'flowChartMagneticDisk',
'flowChartMagneticDrum', 'flowChartDisplay', 'flowChartDelay',
'flowChartAlternateProcess', 'flowChartOffpageConnector',
'actionButtonBlank', 'actionButtonHome', 'actionButtonHelp',
'actionButtonInformation', 'actionButtonForwardNext',
'actionButtonBackPrevious', 'actionButtonEnd', 'actionButtonBeginning',
'actionButtonReturn', 'actionButtonDocument', 'actionButtonSound',
'actionButtonMovie', 'gear6', 'gear9', 'funnel', 'mathPlus', 'mathMinus',
'mathMultiply', 'mathDivide', 'mathEqual', 'mathNotEqual', 'cornerTabs',
'squareTabs', 'plaqueTabs', 'chartX', 'chartStar', 'chartPlus']))
avLst = Typed(expected_type=GeomGuideList, allow_none=True)
def __init__(self,
prst=None,
avLst=None,
):
self.prst = prst
self.avLst = avLst
class FontReference(Serialisable):
idx = NoneSet(values=(['major', 'minor']))
def __init__(self,
idx=None,
):
self.idx = idx
class StyleMatrixReference(Serialisable):
idx = Integer()
def __init__(self,
idx=None,
):
self.idx = idx
class ShapeStyle(Serialisable):
lnRef = Typed(expected_type=StyleMatrixReference, )
fillRef = Typed(expected_type=StyleMatrixReference, )
effectRef = Typed(expected_type=StyleMatrixReference, )
fontRef = Typed(expected_type=FontReference, )
def __init__(self,
lnRef=None,
fillRef=None,
effectRef=None,
fontRef=None,
):
self.lnRef = lnRef
self.fillRef = fillRef
self.effectRef = effectRef
self.fontRef = fontRef

View File

@ -0,0 +1,186 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.xml.functions import NS_REGEX, Element
from openpyxl.xml.constants import CHART_NS, REL_NS, DRAWING_NS
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Bool,
NoneSet,
Integer,
Set,
String,
Alias,
)
from openpyxl.descriptors.excel import ExtensionList as OfficeArtExtensionList
from openpyxl.chart.shapes import GraphicalProperties
from openpyxl.chart.text import RichText
from .effect import *
from .fill import RelativeRect, BlipFillProperties
from .text import Hyperlink, EmbeddedWAVAudioFile
from .geometry import (
Scene3D,
ShapeStyle,
GroupTransform2D
)
from .picture import PictureFrame
from .properties import (
NonVisualDrawingProps,
NonVisualDrawingShapeProps,
NonVisualGroupDrawingShapeProps,
NonVisualGroupShape,
GroupShapeProperties,
)
from .relation import ChartRelation
from .xdr import XDRTransform2D
class GraphicFrameLocking(Serialisable):
noGrp = Bool(allow_none=True)
noDrilldown = Bool(allow_none=True)
noSelect = Bool(allow_none=True)
noChangeAspect = Bool(allow_none=True)
noMove = Bool(allow_none=True)
noResize = Bool(allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
def __init__(self,
noGrp=None,
noDrilldown=None,
noSelect=None,
noChangeAspect=None,
noMove=None,
noResize=None,
extLst=None,
):
self.noGrp = noGrp
self.noDrilldown = noDrilldown
self.noSelect = noSelect
self.noChangeAspect = noChangeAspect
self.noMove = noMove
self.noResize = noResize
self.extLst = extLst
class NonVisualGraphicFrameProperties(Serialisable):
tagname = "cNvGraphicFramePr"
graphicFrameLocks = Typed(expected_type=GraphicFrameLocking, allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
def __init__(self,
graphicFrameLocks=None,
extLst=None,
):
self.graphicFrameLocks = graphicFrameLocks
self.extLst = extLst
class NonVisualGraphicFrame(Serialisable):
tagname = "nvGraphicFramePr"
cNvPr = Typed(expected_type=NonVisualDrawingProps)
cNvGraphicFramePr = Typed(expected_type=NonVisualGraphicFrameProperties)
__elements__ = ('cNvPr', 'cNvGraphicFramePr')
def __init__(self,
cNvPr=None,
cNvGraphicFramePr=None,
):
if cNvPr is None:
cNvPr = NonVisualDrawingProps(id=0, name="Chart 0")
self.cNvPr = cNvPr
if cNvGraphicFramePr is None:
cNvGraphicFramePr = NonVisualGraphicFrameProperties()
self.cNvGraphicFramePr = cNvGraphicFramePr
class GraphicData(Serialisable):
tagname = "graphicData"
namespace = DRAWING_NS
uri = String()
chart = Typed(expected_type=ChartRelation, allow_none=True)
def __init__(self,
uri=CHART_NS,
chart=None,
):
self.uri = uri
self.chart = chart
class GraphicObject(Serialisable):
tagname = "graphic"
namespace = DRAWING_NS
graphicData = Typed(expected_type=GraphicData)
def __init__(self,
graphicData=None,
):
if graphicData is None:
graphicData = GraphicData()
self.graphicData = graphicData
class GraphicFrame(Serialisable):
tagname = "graphicFrame"
nvGraphicFramePr = Typed(expected_type=NonVisualGraphicFrame)
xfrm = Typed(expected_type=XDRTransform2D)
graphic = Typed(expected_type=GraphicObject)
macro = String(allow_none=True)
fPublished = Bool(allow_none=True)
__elements__ = ('nvGraphicFramePr', 'xfrm', 'graphic', 'macro', 'fPublished')
def __init__(self,
nvGraphicFramePr=None,
xfrm=None,
graphic=None,
macro=None,
fPublished=None,
):
if nvGraphicFramePr is None:
nvGraphicFramePr = NonVisualGraphicFrame()
self.nvGraphicFramePr = nvGraphicFramePr
if xfrm is None:
xfrm = XDRTransform2D()
self.xfrm = xfrm
if graphic is None:
graphic = GraphicObject()
self.graphic = graphic
self.macro = macro
self.fPublished = fPublished
class GroupShape(Serialisable):
nvGrpSpPr = Typed(expected_type=NonVisualGroupShape)
nonVisualProperties = Alias("nvGrpSpPr")
grpSpPr = Typed(expected_type=GroupShapeProperties)
visualProperties = Alias("grpSpPr")
pic = Typed(expected_type=PictureFrame, allow_none=True)
__elements__ = ["nvGrpSpPr", "grpSpPr", "pic"]
def __init__(self,
nvGrpSpPr=None,
grpSpPr=None,
pic=None,
):
self.nvGrpSpPr = nvGrpSpPr
self.grpSpPr = grpSpPr
self.pic = pic

View File

@ -0,0 +1,65 @@
# Copyright (c) 2010-2022 openpyxl
from io import BytesIO
try:
from PIL import Image as PILImage
except ImportError:
PILImage = False
def _import_image(img):
if not PILImage:
raise ImportError('You must install Pillow to fetch image objects')
if not isinstance(img, PILImage.Image):
img = PILImage.open(img)
return img
class Image(object):
"""Image in a spreadsheet"""
_id = 1
_path = "/xl/media/image{0}.{1}"
anchor = "A1"
def __init__(self, img):
self.ref = img
mark_to_close = isinstance(img, str)
image = _import_image(img)
self.width, self.height = image.size
try:
self.format = image.format.lower()
except AttributeError:
self.format = "png"
if mark_to_close:
# PIL instances created for metadata should be closed.
image.close()
def _data(self):
"""
Return image data, convert to supported types if necessary
"""
img = _import_image(self.ref)
# don't convert these file formats
if self.format in ['gif', 'jpeg', 'png']:
img.fp.seek(0)
fp = img.fp
else:
fp = BytesIO()
img.save(fp, format="png")
fp.seek(0)
data = fp.read()
fp.close()
return data
@property
def path(self):
return self._path.format(self._id, self.format)

View File

@ -0,0 +1,151 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Float,
Integer,
Bool,
MinMax,
Set,
NoneSet,
String,
Alias,
Sequence
)
from openpyxl.descriptors.excel import Coordinate, Percentage
from openpyxl.descriptors.nested import (
NestedInteger,
NestedSet,
NestedNoneSet,
EmptyTag,
)
from openpyxl.compat import safe_string
from openpyxl.xml.constants import DRAWING_NS
from openpyxl.xml.functions import Element
from .colors import ColorChoiceDescriptor
from .fill import GradientFillProperties, PatternFillProperties
from openpyxl.descriptors.excel import ExtensionList as OfficeArtExtensionList
"""
Line elements from drawing main schema
"""
class LineEndProperties(Serialisable):
tagname = "end"
namespace = DRAWING_NS
type = NoneSet(values=(['none', 'triangle', 'stealth', 'diamond', 'oval', 'arrow']))
w = NoneSet(values=(['sm', 'med', 'lg']))
len = NoneSet(values=(['sm', 'med', 'lg']))
def __init__(self,
type=None,
w=None,
len=None,
):
self.type = type
self.w = w
self.len = len
class DashStop(Serialisable):
tagname = "ds"
namespace = DRAWING_NS
d = Integer()
length = Alias('d')
sp = Integer()
space = Alias('sp')
def __init__(self,
d=0,
sp=0,
):
self.d = d
self.sp = sp
class DashStopList(Serialisable):
ds = Sequence(expected_type=DashStop, allow_none=True)
def __init__(self,
ds=None,
):
self.ds = ds
class LineProperties(Serialisable):
tagname = "ln"
namespace = DRAWING_NS
w = MinMax(min=0, max=20116800, allow_none=True) # EMU
width = Alias('w')
cap = NoneSet(values=(['rnd', 'sq', 'flat']))
cmpd = NoneSet(values=(['sng', 'dbl', 'thickThin', 'thinThick', 'tri']))
algn = NoneSet(values=(['ctr', 'in']))
noFill = EmptyTag()
solidFill = ColorChoiceDescriptor()
gradFill = Typed(expected_type=GradientFillProperties, allow_none=True)
pattFill = Typed(expected_type=PatternFillProperties, allow_none=True)
prstDash = NestedNoneSet(values=(['solid', 'dot', 'dash', 'lgDash', 'dashDot',
'lgDashDot', 'lgDashDotDot', 'sysDash', 'sysDot', 'sysDashDot',
'sysDashDotDot']), namespace=namespace)
dashStyle = Alias('prstDash')
custDash = Typed(expected_type=DashStop, allow_none=True)
round = EmptyTag()
bevel = EmptyTag()
miter = NestedInteger(allow_none=True, attribute="lim")
headEnd = Typed(expected_type=LineEndProperties, allow_none=True)
tailEnd = Typed(expected_type=LineEndProperties, allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
__elements__ = ('noFill', 'solidFill', 'gradFill', 'pattFill',
'prstDash', 'custDash', 'round', 'bevel', 'miter', 'headEnd', 'tailEnd')
def __init__(self,
w=None,
cap=None,
cmpd=None,
algn=None,
noFill=None,
solidFill=None,
gradFill=None,
pattFill=None,
prstDash=None,
custDash=None,
round=None,
bevel=None,
miter=None,
headEnd=None,
tailEnd=None,
extLst=None,
):
self.w = w
self.cap = cap
self.cmpd = cmpd
self.algn = algn
self.noFill = noFill
self.solidFill = solidFill
self.gradFill = gradFill
self.pattFill = pattFill
if prstDash is None:
prstDash = "solid"
self.prstDash = prstDash
self.custDash = custDash
self.round = round
self.bevel = bevel
self.miter = miter
self.headEnd = headEnd
self.tailEnd = tailEnd

View File

@ -0,0 +1,148 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.xml.constants import DRAWING_NS
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Bool,
NoneSet,
Integer,
Set,
String,
Alias,
)
from openpyxl.descriptors.excel import ExtensionList as OfficeArtExtensionList
from openpyxl.chart.shapes import GraphicalProperties
from .fill import RelativeRect, BlipFillProperties
from .properties import NonVisualDrawingProps, NonVisualGroupDrawingShapeProps
from .geometry import ShapeStyle
class PictureLocking(Serialisable):
tagname = "picLocks"
namespace = DRAWING_NS
#Using attribute group AG_Locking
noCrop = Bool(allow_none=True)
noGrp = Bool(allow_none=True)
noSelect = Bool(allow_none=True)
noRot = Bool(allow_none=True)
noChangeAspect = Bool(allow_none=True)
noMove = Bool(allow_none=True)
noResize = Bool(allow_none=True)
noEditPoints = Bool(allow_none=True)
noAdjustHandles = Bool(allow_none=True)
noChangeArrowheads = Bool(allow_none=True)
noChangeShapeType = Bool(allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
__elements__ = ()
def __init__(self,
noCrop=None,
noGrp=None,
noSelect=None,
noRot=None,
noChangeAspect=None,
noMove=None,
noResize=None,
noEditPoints=None,
noAdjustHandles=None,
noChangeArrowheads=None,
noChangeShapeType=None,
extLst=None,
):
self.noCrop = noCrop
self.noGrp = noGrp
self.noSelect = noSelect
self.noRot = noRot
self.noChangeAspect = noChangeAspect
self.noMove = noMove
self.noResize = noResize
self.noEditPoints = noEditPoints
self.noAdjustHandles = noAdjustHandles
self.noChangeArrowheads = noChangeArrowheads
self.noChangeShapeType = noChangeShapeType
class NonVisualPictureProperties(Serialisable):
tagname = "cNvPicPr"
preferRelativeResize = Bool(allow_none=True)
picLocks = Typed(expected_type=PictureLocking, allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
__elements__ = ("picLocks",)
def __init__(self,
preferRelativeResize=None,
picLocks=None,
extLst=None,
):
self.preferRelativeResize = preferRelativeResize
self.picLocks = picLocks
class PictureNonVisual(Serialisable):
tagname = "nvPicPr"
cNvPr = Typed(expected_type=NonVisualDrawingProps, )
cNvPicPr = Typed(expected_type=NonVisualPictureProperties, )
__elements__ = ("cNvPr", "cNvPicPr")
def __init__(self,
cNvPr=None,
cNvPicPr=None,
):
if cNvPr is None:
cNvPr = NonVisualDrawingProps(id=0, name="Image 1", descr="Name of file")
self.cNvPr = cNvPr
if cNvPicPr is None:
cNvPicPr = NonVisualPictureProperties()
self.cNvPicPr = cNvPicPr
class PictureFrame(Serialisable):
tagname = "pic"
macro = String(allow_none=True)
fPublished = Bool(allow_none=True)
nvPicPr = Typed(expected_type=PictureNonVisual, )
blipFill = Typed(expected_type=BlipFillProperties, )
spPr = Typed(expected_type=GraphicalProperties, )
graphicalProperties = Alias('spPr')
style = Typed(expected_type=ShapeStyle, allow_none=True)
__elements__ = ("nvPicPr", "blipFill", "spPr", "style")
def __init__(self,
macro=None,
fPublished=None,
nvPicPr=None,
blipFill=None,
spPr=None,
style=None,
):
self.macro = macro
self.fPublished = fPublished
if nvPicPr is None:
nvPicPr = PictureNonVisual()
self.nvPicPr = nvPicPr
if blipFill is None:
blipFill = BlipFillProperties()
self.blipFill = blipFill
if spPr is None:
spPr = GraphicalProperties()
self.spPr = spPr
self.style = style

View File

@ -0,0 +1,174 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.xml.constants import DRAWING_NS
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Bool,
Integer,
Set,
String,
Alias,
NoneSet,
)
from openpyxl.descriptors.excel import ExtensionList as OfficeArtExtensionList
from .geometry import GroupTransform2D, Scene3D
from .text import Hyperlink
class GroupShapeProperties(Serialisable):
tagname = "grpSpPr"
bwMode = NoneSet(values=(['clr', 'auto', 'gray', 'ltGray', 'invGray',
'grayWhite', 'blackGray', 'blackWhite', 'black', 'white', 'hidden']))
xfrm = Typed(expected_type=GroupTransform2D, allow_none=True)
scene3d = Typed(expected_type=Scene3D, allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
def __init__(self,
bwMode=None,
xfrm=None,
scene3d=None,
extLst=None,
):
self.bwMode = bwMode
self.xfrm = xfrm
self.scene3d = scene3d
self.extLst = extLst
class GroupLocking(Serialisable):
tagname = "grpSpLocks"
namespace = DRAWING_NS
noGrp = Bool(allow_none=True)
noUngrp = Bool(allow_none=True)
noSelect = Bool(allow_none=True)
noRot = Bool(allow_none=True)
noChangeAspect = Bool(allow_none=True)
noMove = Bool(allow_none=True)
noResize = Bool(allow_none=True)
noChangeArrowheads = Bool(allow_none=True)
noEditPoints = Bool(allow_none=True)
noAdjustHandles = Bool(allow_none=True)
noChangeArrowheads = Bool(allow_none=True)
noChangeShapeType = Bool(allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
__elements__ = ()
def __init__(self,
noGrp=None,
noUngrp=None,
noSelect=None,
noRot=None,
noChangeAspect=None,
noChangeArrowheads=None,
noMove=None,
noResize=None,
noEditPoints=None,
noAdjustHandles=None,
noChangeShapeType=None,
extLst=None,
):
self.noGrp = noGrp
self.noUngrp = noUngrp
self.noSelect = noSelect
self.noRot = noRot
self.noChangeAspect = noChangeAspect
self.noChangeArrowheads = noChangeArrowheads
self.noMove = noMove
self.noResize = noResize
self.noEditPoints = noEditPoints
self.noAdjustHandles = noAdjustHandles
self.noChangeShapeType = noChangeShapeType
class NonVisualGroupDrawingShapeProps(Serialisable):
tagname = "cNvGrpSpPr"
grpSpLocks = Typed(expected_type=GroupLocking, allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
__elements__ = ("grpSpLocks",)
def __init__(self,
grpSpLocks=None,
extLst=None,
):
self.grpSpLocks = grpSpLocks
class NonVisualDrawingShapeProps(Serialisable):
tagname = "cNvSpPr"
spLocks = Typed(expected_type=GroupLocking, allow_none=True)
txBax = Bool(allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
__elements__ = ("spLocks", "txBax")
def __init__(self,
spLocks=None,
txBox=None,
extLst=None,
):
self.spLocks = spLocks
self.txBox = txBox
class NonVisualDrawingProps(Serialisable):
tagname = "cNvPr"
id = Integer()
name = String()
descr = String(allow_none=True)
hidden = Bool(allow_none=True)
title = String(allow_none=True)
hlinkClick = Typed(expected_type=Hyperlink, allow_none=True)
hlinkHover = Typed(expected_type=Hyperlink, allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
__elements__ = ["hlinkClick", "hlinkHover"]
def __init__(self,
id=None,
name=None,
descr=None,
hidden=None,
title=None,
hlinkClick=None,
hlinkHover=None,
extLst=None,
):
self.id = id
self.name = name
self.descr = descr
self.hidden = hidden
self.title = title
self.hlinkClick = hlinkClick
self.hlinkHover = hlinkHover
self.extLst = extLst
class NonVisualGroupShape(Serialisable):
tagname = "nvGrpSpPr"
cNvPr = Typed(expected_type=NonVisualDrawingProps)
cNvGrpSpPr = Typed(expected_type=NonVisualGroupDrawingShapeProps)
__elements__ = ("cNvPr", "cNvGrpSpPr")
def __init__(self,
cNvPr=None,
cNvGrpSpPr=None,
):
self.cNvPr = cNvPr
self.cNvGrpSpPr = cNvGrpSpPr

View File

@ -0,0 +1,17 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.xml.constants import CHART_NS
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors.excel import Relation
class ChartRelation(Serialisable):
tagname = "chart"
namespace = CHART_NS
id = Relation()
def __init__(self, id):
self.id = id

View File

@ -0,0 +1,381 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Bool,
NoneSet,
Integer,
Sequence,
Alias,
)
from openpyxl.descriptors.nested import (
NestedText,
NestedNoneSet,
)
from openpyxl.descriptors.excel import Relation
from openpyxl.packaging.relationship import (
Relationship,
RelationshipList,
)
from openpyxl.utils import coordinate_to_tuple
from openpyxl.utils.units import (
cm_to_EMU,
pixels_to_EMU,
)
from openpyxl.drawing.image import Image
from openpyxl.xml.constants import SHEET_DRAWING_NS
from openpyxl.chart._chart import ChartBase
from .xdr import (
XDRPoint2D,
XDRPositiveSize2D,
)
from .fill import Blip
from .connector import Shape
from .graphic import (
GroupShape,
GraphicFrame,
)
from .geometry import PresetGeometry2D
from .picture import PictureFrame
from .relation import ChartRelation
class AnchorClientData(Serialisable):
fLocksWithSheet = Bool(allow_none=True)
fPrintsWithSheet = Bool(allow_none=True)
def __init__(self,
fLocksWithSheet=None,
fPrintsWithSheet=None,
):
self.fLocksWithSheet = fLocksWithSheet
self.fPrintsWithSheet = fPrintsWithSheet
class AnchorMarker(Serialisable):
tagname = "marker"
col = NestedText(expected_type=int)
colOff = NestedText(expected_type=int)
row = NestedText(expected_type=int)
rowOff = NestedText(expected_type=int)
def __init__(self,
col=0,
colOff=0,
row=0,
rowOff=0,
):
self.col = col
self.colOff = colOff
self.row = row
self.rowOff = rowOff
class _AnchorBase(Serialisable):
#one of
sp = Typed(expected_type=Shape, allow_none=True)
shape = Alias("sp")
grpSp = Typed(expected_type=GroupShape, allow_none=True)
groupShape = Alias("grpSp")
graphicFrame = Typed(expected_type=GraphicFrame, allow_none=True)
cxnSp = Typed(expected_type=Shape, allow_none=True)
connectionShape = Alias("cxnSp")
pic = Typed(expected_type=PictureFrame, allow_none=True)
contentPart = Relation()
clientData = Typed(expected_type=AnchorClientData)
__elements__ = ('sp', 'grpSp', 'graphicFrame',
'cxnSp', 'pic', 'contentPart', 'clientData')
def __init__(self,
clientData=None,
sp=None,
grpSp=None,
graphicFrame=None,
cxnSp=None,
pic=None,
contentPart=None
):
if clientData is None:
clientData = AnchorClientData()
self.clientData = clientData
self.sp = sp
self.grpSp = grpSp
self.graphicFrame = graphicFrame
self.cxnSp = cxnSp
self.pic = pic
self.contentPart = contentPart
class AbsoluteAnchor(_AnchorBase):
tagname = "absoluteAnchor"
pos = Typed(expected_type=XDRPoint2D)
ext = Typed(expected_type=XDRPositiveSize2D)
sp = _AnchorBase.sp
grpSp = _AnchorBase.grpSp
graphicFrame = _AnchorBase.graphicFrame
cxnSp = _AnchorBase.cxnSp
pic = _AnchorBase.pic
contentPart = _AnchorBase.contentPart
clientData = _AnchorBase.clientData
__elements__ = ('pos', 'ext') + _AnchorBase.__elements__
def __init__(self,
pos=None,
ext=None,
**kw
):
if pos is None:
pos = XDRPoint2D(0, 0)
self.pos = pos
if ext is None:
ext = XDRPositiveSize2D(0, 0)
self.ext = ext
super(AbsoluteAnchor, self).__init__(**kw)
class OneCellAnchor(_AnchorBase):
tagname = "oneCellAnchor"
_from = Typed(expected_type=AnchorMarker)
ext = Typed(expected_type=XDRPositiveSize2D)
sp = _AnchorBase.sp
grpSp = _AnchorBase.grpSp
graphicFrame = _AnchorBase.graphicFrame
cxnSp = _AnchorBase.cxnSp
pic = _AnchorBase.pic
contentPart = _AnchorBase.contentPart
clientData = _AnchorBase.clientData
__elements__ = ('_from', 'ext') + _AnchorBase.__elements__
def __init__(self,
_from=None,
ext=None,
**kw
):
if _from is None:
_from = AnchorMarker()
self._from = _from
if ext is None:
ext = XDRPositiveSize2D(0, 0)
self.ext = ext
super(OneCellAnchor, self).__init__(**kw)
class TwoCellAnchor(_AnchorBase):
tagname = "twoCellAnchor"
editAs = NoneSet(values=(['twoCell', 'oneCell', 'absolute']))
_from = Typed(expected_type=AnchorMarker)
to = Typed(expected_type=AnchorMarker)
sp = _AnchorBase.sp
grpSp = _AnchorBase.grpSp
graphicFrame = _AnchorBase.graphicFrame
cxnSp = _AnchorBase.cxnSp
pic = _AnchorBase.pic
contentPart = _AnchorBase.contentPart
clientData = _AnchorBase.clientData
__elements__ = ('_from', 'to') + _AnchorBase.__elements__
def __init__(self,
editAs=None,
_from=None,
to=None,
**kw
):
self.editAs = editAs
if _from is None:
_from = AnchorMarker()
self._from = _from
if to is None:
to = AnchorMarker()
self.to = to
super(TwoCellAnchor, self).__init__(**kw)
def _check_anchor(obj):
"""
Check whether an object has an existing Anchor object
If not create a OneCellAnchor using the provided coordinate
"""
anchor = obj.anchor
if not isinstance(anchor, _AnchorBase):
row, col = coordinate_to_tuple(anchor.upper())
anchor = OneCellAnchor()
anchor._from.row = row -1
anchor._from.col = col -1
if isinstance(obj, ChartBase):
anchor.ext.width = cm_to_EMU(obj.width)
anchor.ext.height = cm_to_EMU(obj.height)
elif isinstance(obj, Image):
anchor.ext.width = pixels_to_EMU(obj.width)
anchor.ext.height = pixels_to_EMU(obj.height)
return anchor
class SpreadsheetDrawing(Serialisable):
tagname = "wsDr"
mime_type = "application/vnd.openxmlformats-officedocument.drawing+xml"
_rel_type = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing"
_path = PartName="/xl/drawings/drawing{0}.xml"
_id = None
twoCellAnchor = Sequence(expected_type=TwoCellAnchor, allow_none=True)
oneCellAnchor = Sequence(expected_type=OneCellAnchor, allow_none=True)
absoluteAnchor = Sequence(expected_type=AbsoluteAnchor, allow_none=True)
__elements__ = ("twoCellAnchor", "oneCellAnchor", "absoluteAnchor")
def __init__(self,
twoCellAnchor=(),
oneCellAnchor=(),
absoluteAnchor=(),
):
self.twoCellAnchor = twoCellAnchor
self.oneCellAnchor = oneCellAnchor
self.absoluteAnchor = absoluteAnchor
self.charts = []
self.images = []
self._rels = []
def __hash__(self):
"""
Just need to check for identity
"""
return id(self)
def __bool__(self):
return bool(self.charts) or bool(self.images)
def _write(self):
"""
create required structure and the serialise
"""
anchors = []
for idx, obj in enumerate(self.charts + self.images, 1):
anchor = _check_anchor(obj)
if isinstance(obj, ChartBase):
rel = Relationship(type="chart", Target=obj.path)
anchor.graphicFrame = self._chart_frame(idx)
elif isinstance(obj, Image):
rel = Relationship(type="image", Target=obj.path)
child = anchor.pic or anchor.groupShape and anchor.groupShape.pic
if not child:
anchor.pic = self._picture_frame(idx)
else:
child.blipFill.blip.embed = "rId{0}".format(idx)
anchors.append(anchor)
self._rels.append(rel)
for a in anchors:
if isinstance(a, OneCellAnchor):
self.oneCellAnchor.append(a)
elif isinstance(a, TwoCellAnchor):
self.twoCellAnchor.append(a)
else:
self.absoluteAnchor.append(a)
tree = self.to_tree()
tree.set('xmlns', SHEET_DRAWING_NS)
return tree
def _chart_frame(self, idx):
chart_rel = ChartRelation(f"rId{idx}")
frame = GraphicFrame()
nv = frame.nvGraphicFramePr.cNvPr
nv.id = idx
nv.name = "Chart {0}".format(idx)
frame.graphic.graphicData.chart = chart_rel
return frame
def _picture_frame(self, idx):
pic = PictureFrame()
pic.nvPicPr.cNvPr.descr = "Picture"
pic.nvPicPr.cNvPr.id = idx
pic.nvPicPr.cNvPr.name = "Image {0}".format(idx)
pic.blipFill.blip = Blip()
pic.blipFill.blip.embed = "rId{0}".format(idx)
pic.blipFill.blip.cstate = "print"
pic.spPr.prstGeom = PresetGeometry2D(prst="rect")
pic.spPr.ln = None
return pic
def _write_rels(self):
rels = RelationshipList()
rels.Relationship = self._rels
return rels.to_tree()
@property
def path(self):
return self._path.format(self._id)
@property
def _chart_rels(self):
"""
Get relationship information for each chart and bind anchor to it
"""
rels = []
anchors = self.absoluteAnchor + self.oneCellAnchor + self.twoCellAnchor
for anchor in anchors:
if anchor.graphicFrame is not None:
graphic = anchor.graphicFrame.graphic
rel = graphic.graphicData.chart
if rel is not None:
rel.anchor = anchor
rel.anchor.graphicFrame = None
rels.append(rel)
return rels
@property
def _blip_rels(self):
"""
Get relationship information for each blip and bind anchor to it
Images that are not part of the XLSX package will be ignored.
"""
rels = []
anchors = self.absoluteAnchor + self.oneCellAnchor + self.twoCellAnchor
for anchor in anchors:
child = anchor.pic or anchor.groupShape and anchor.groupShape.pic
if child and child.blipFill:
rel = child.blipFill.blip
if rel is not None and rel.embed:
rel.anchor = anchor
rels.append(rel)
return rels

View File

@ -0,0 +1,712 @@
# Copyright (c) 2010-2022 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Alias,
Typed,
Set,
NoneSet,
Sequence,
String,
Bool,
MinMax,
Integer
)
from openpyxl.descriptors.excel import (
HexBinary,
TextPoint,
Coordinate,
ExtensionList,
Relation,
)
from openpyxl.descriptors.nested import (
NestedInteger,
NestedString,
NestedText,
NestedValue,
EmptyTag
)
from openpyxl.xml.constants import DRAWING_NS
from .colors import ColorChoiceDescriptor
from .effect import *
from .fill import *
from .geometry import (
LineProperties,
Color,
Scene3D
)
from openpyxl.descriptors.excel import ExtensionList as OfficeArtExtensionList
from openpyxl.descriptors.nested import NestedBool
class EmbeddedWAVAudioFile(Serialisable):
name = String(allow_none=True)
def __init__(self,
name=None,
):
self.name = name
class Hyperlink(Serialisable):
tagname = "hlinkClick"
namespace = DRAWING_NS
invalidUrl = String(allow_none=True)
action = String(allow_none=True)
tgtFrame = String(allow_none=True)
tooltip = String(allow_none=True)
history = Bool(allow_none=True)
highlightClick = Bool(allow_none=True)
endSnd = Bool(allow_none=True)
snd = Typed(expected_type=EmbeddedWAVAudioFile, allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
id = Relation(allow_none=True)
__elements__ = ('snd',)
def __init__(self,
invalidUrl=None,
action=None,
tgtFrame=None,
tooltip=None,
history=None,
highlightClick=None,
endSnd=None,
snd=None,
extLst=None,
id=None,
):
self.invalidUrl = invalidUrl
self.action = action
self.tgtFrame = tgtFrame
self.tooltip = tooltip
self.history = history
self.highlightClick = highlightClick
self.endSnd = endSnd
self.snd = snd
self.id = id
class Font(Serialisable):
tagname = "latin"
namespace = DRAWING_NS
typeface = String()
panose = HexBinary(allow_none=True)
pitchFamily = MinMax(min=0, max=52, allow_none=True)
charset = Integer(allow_none=True)
def __init__(self,
typeface=None,
panose=None,
pitchFamily=None,
charset=None,
):
self.typeface = typeface
self.panose = panose
self.pitchFamily = pitchFamily
self.charset = charset
class CharacterProperties(Serialisable):
tagname = "defRPr"
namespace = DRAWING_NS
kumimoji = Bool(allow_none=True)
lang = String(allow_none=True)
altLang = String(allow_none=True)
sz = MinMax(allow_none=True, min=100, max=400000) # 100ths of a point
b = Bool(allow_none=True)
i = Bool(allow_none=True)
u = NoneSet(values=(['words', 'sng', 'dbl', 'heavy', 'dotted',
'dottedHeavy', 'dash', 'dashHeavy', 'dashLong', 'dashLongHeavy',
'dotDash', 'dotDashHeavy', 'dotDotDash', 'dotDotDashHeavy', 'wavy',
'wavyHeavy', 'wavyDbl']))
strike = NoneSet(values=(['noStrike', 'sngStrike', 'dblStrike']))
kern = Integer(allow_none=True)
cap = NoneSet(values=(['small', 'all']))
spc = Integer(allow_none=True)
normalizeH = Bool(allow_none=True)
baseline = Integer(allow_none=True)
noProof = Bool(allow_none=True)
dirty = Bool(allow_none=True)
err = Bool(allow_none=True)
smtClean = Bool(allow_none=True)
smtId = Integer(allow_none=True)
bmk = String(allow_none=True)
ln = Typed(expected_type=LineProperties, allow_none=True)
highlight = Typed(expected_type=Color, allow_none=True)
latin = Typed(expected_type=Font, allow_none=True)
ea = Typed(expected_type=Font, allow_none=True)
cs = Typed(expected_type=Font, allow_none=True)
sym = Typed(expected_type=Font, allow_none=True)
hlinkClick = Typed(expected_type=Hyperlink, allow_none=True)
hlinkMouseOver = Typed(expected_type=Hyperlink, allow_none=True)
rtl = NestedBool(allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
# uses element group EG_FillProperties
noFill = EmptyTag(namespace=DRAWING_NS)
solidFill = ColorChoiceDescriptor()
gradFill = Typed(expected_type=GradientFillProperties, allow_none=True)
blipFill = Typed(expected_type=BlipFillProperties, allow_none=True)
pattFill = Typed(expected_type=PatternFillProperties, allow_none=True)
grpFill = EmptyTag(namespace=DRAWING_NS)
# uses element group EG_EffectProperties
effectLst = Typed(expected_type=EffectList, allow_none=True)
effectDag = Typed(expected_type=EffectContainer, allow_none=True)
# uses element group EG_TextUnderlineLine
uLnTx = EmptyTag()
uLn = Typed(expected_type=LineProperties, allow_none=True)
# uses element group EG_TextUnderlineFill
uFillTx = EmptyTag()
uFill = EmptyTag()
__elements__ = ('ln', 'noFill', 'solidFill', 'gradFill', 'blipFill',
'pattFill', 'grpFill', 'effectLst', 'effectDag', 'highlight','uLnTx',
'uLn', 'uFillTx', 'uFill', 'latin', 'ea', 'cs', 'sym', 'hlinkClick',
'hlinkMouseOver', 'rtl', )
def __init__(self,
kumimoji=None,
lang=None,
altLang=None,
sz=None,
b=None,
i=None,
u=None,
strike=None,
kern=None,
cap=None,
spc=None,
normalizeH=None,
baseline=None,
noProof=None,
dirty=None,
err=None,
smtClean=None,
smtId=None,
bmk=None,
ln=None,
highlight=None,
latin=None,
ea=None,
cs=None,
sym=None,
hlinkClick=None,
hlinkMouseOver=None,
rtl=None,
extLst=None,
noFill=None,
solidFill=None,
gradFill=None,
blipFill=None,
pattFill=None,
grpFill=None,
effectLst=None,
effectDag=None,
uLnTx=None,
uLn=None,
uFillTx=None,
uFill=None,
):
self.kumimoji = kumimoji
self.lang = lang
self.altLang = altLang
self.sz = sz
self.b = b
self.i = i
self.u = u
self.strike = strike
self.kern = kern
self.cap = cap
self.spc = spc
self.normalizeH = normalizeH
self.baseline = baseline
self.noProof = noProof
self.dirty = dirty
self.err = err
self.smtClean = smtClean
self.smtId = smtId
self.bmk = bmk
self.ln = ln
self.highlight = highlight
self.latin = latin
self.ea = ea
self.cs = cs
self.sym = sym
self.hlinkClick = hlinkClick
self.hlinkMouseOver = hlinkMouseOver
self.rtl = rtl
self.noFill = noFill
self.solidFill = solidFill
self.gradFill = gradFill
self.blipFill = blipFill
self.pattFill = pattFill
self.grpFill = grpFill
self.effectLst = effectLst
self.effectDag = effectDag
self.uLnTx = uLnTx
self.uLn = uLn
self.uFillTx = uFillTx
self.uFill = uFill
class TabStop(Serialisable):
pos = Typed(expected_type=Coordinate, allow_none=True)
algn = Typed(expected_type=Set(values=(['l', 'ctr', 'r', 'dec'])))
def __init__(self,
pos=None,
algn=None,
):
self.pos = pos
self.algn = algn
class TabStopList(Serialisable):
tab = Typed(expected_type=TabStop, allow_none=True)
def __init__(self,
tab=None,
):
self.tab = tab
class Spacing(Serialisable):
spcPct = NestedInteger(allow_none=True)
spcPts = NestedInteger(allow_none=True)
__elements__ = ('spcPct', 'spcPts')
def __init__(self,
spcPct=None,
spcPts=None,
):
self.spcPct = spcPct
self.spcPts = spcPts
class AutonumberBullet(Serialisable):
type = Set(values=(['alphaLcParenBoth', 'alphaUcParenBoth',
'alphaLcParenR', 'alphaUcParenR', 'alphaLcPeriod', 'alphaUcPeriod',
'arabicParenBoth', 'arabicParenR', 'arabicPeriod', 'arabicPlain',
'romanLcParenBoth', 'romanUcParenBoth', 'romanLcParenR', 'romanUcParenR',
'romanLcPeriod', 'romanUcPeriod', 'circleNumDbPlain',
'circleNumWdBlackPlain', 'circleNumWdWhitePlain', 'arabicDbPeriod',
'arabicDbPlain', 'ea1ChsPeriod', 'ea1ChsPlain', 'ea1ChtPeriod',
'ea1ChtPlain', 'ea1JpnChsDbPeriod', 'ea1JpnKorPlain', 'ea1JpnKorPeriod',
'arabic1Minus', 'arabic2Minus', 'hebrew2Minus', 'thaiAlphaPeriod',
'thaiAlphaParenR', 'thaiAlphaParenBoth', 'thaiNumPeriod',
'thaiNumParenR', 'thaiNumParenBoth', 'hindiAlphaPeriod',
'hindiNumPeriod', 'hindiNumParenR', 'hindiAlpha1Period']))
startAt = Integer()
def __init__(self,
type=None,
startAt=None,
):
self.type = type
self.startAt = startAt
class ParagraphProperties(Serialisable):
tagname = "pPr"
namespace = DRAWING_NS
marL = Integer(allow_none=True)
marR = Integer(allow_none=True)
lvl = Integer(allow_none=True)
indent = Integer(allow_none=True)
algn = NoneSet(values=(['l', 'ctr', 'r', 'just', 'justLow', 'dist', 'thaiDist']))
defTabSz = Integer(allow_none=True)
rtl = Bool(allow_none=True)
eaLnBrk = Bool(allow_none=True)
fontAlgn = NoneSet(values=(['auto', 't', 'ctr', 'base', 'b']))
latinLnBrk = Bool(allow_none=True)
hangingPunct = Bool(allow_none=True)
# uses element group EG_TextBulletColor
# uses element group EG_TextBulletSize
# uses element group EG_TextBulletTypeface
# uses element group EG_TextBullet
lnSpc = Typed(expected_type=Spacing, allow_none=True)
spcBef = Typed(expected_type=Spacing, allow_none=True)
spcAft = Typed(expected_type=Spacing, allow_none=True)
tabLst = Typed(expected_type=TabStopList, allow_none=True)
defRPr = Typed(expected_type=CharacterProperties, allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
buClrTx = EmptyTag()
buClr = Typed(expected_type=Color, allow_none=True)
buSzTx = EmptyTag()
buSzPct = NestedInteger(allow_none=True)
buSzPts = NestedInteger(allow_none=True)
buFontTx = EmptyTag()
buFont = Typed(expected_type=Font, allow_none=True)
buNone = EmptyTag()
buAutoNum = EmptyTag()
buChar = NestedValue(expected_type=str, attribute="char", allow_none=True)
buBlip = NestedValue(expected_type=Blip, attribute="blip", allow_none=True)
__elements__ = ('lnSpc', 'spcBef', 'spcAft', 'tabLst', 'defRPr',
'buClrTx', 'buClr', 'buSzTx', 'buSzPct', 'buSzPts', 'buFontTx', 'buFont',
'buNone', 'buAutoNum', 'buChar', 'buBlip')
def __init__(self,
marL=None,
marR=None,
lvl=None,
indent=None,
algn=None,
defTabSz=None,
rtl=None,
eaLnBrk=None,
fontAlgn=None,
latinLnBrk=None,
hangingPunct=None,
lnSpc=None,
spcBef=None,
spcAft=None,
tabLst=None,
defRPr=None,
extLst=None,
buClrTx=None,
buClr=None,
buSzTx=None,
buSzPct=None,
buSzPts=None,
buFontTx=None,
buFont=None,
buNone=None,
buAutoNum=None,
buChar=None,
buBlip=None,
):
self.marL = marL
self.marR = marR
self.lvl = lvl
self.indent = indent
self.algn = algn
self.defTabSz = defTabSz
self.rtl = rtl
self.eaLnBrk = eaLnBrk
self.fontAlgn = fontAlgn
self.latinLnBrk = latinLnBrk
self.hangingPunct = hangingPunct
self.lnSpc = lnSpc
self.spcBef = spcBef
self.spcAft = spcAft
self.tabLst = tabLst
self.defRPr = defRPr
self.buClrTx = buClrTx
self.buClr = buClr
self.buSzTx = buSzTx
self.buSzPct = buSzPct
self.buSzPts = buSzPts
self.buFontTx = buFontTx
self.buFont = buFont
self.buNone = buNone
self.buAutoNum = buAutoNum
self.buChar = buChar
self.buBlip = buBlip
self.defRPr = defRPr
class ListStyle(Serialisable):
tagname = "lstStyle"
namespace = DRAWING_NS
defPPr = Typed(expected_type=ParagraphProperties, allow_none=True)
lvl1pPr = Typed(expected_type=ParagraphProperties, allow_none=True)
lvl2pPr = Typed(expected_type=ParagraphProperties, allow_none=True)
lvl3pPr = Typed(expected_type=ParagraphProperties, allow_none=True)
lvl4pPr = Typed(expected_type=ParagraphProperties, allow_none=True)
lvl5pPr = Typed(expected_type=ParagraphProperties, allow_none=True)
lvl6pPr = Typed(expected_type=ParagraphProperties, allow_none=True)
lvl7pPr = Typed(expected_type=ParagraphProperties, allow_none=True)
lvl8pPr = Typed(expected_type=ParagraphProperties, allow_none=True)
lvl9pPr = Typed(expected_type=ParagraphProperties, allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
__elements__ = ("defPPr", "lvl1pPr", "lvl2pPr", "lvl3pPr", "lvl4pPr",
"lvl5pPr", "lvl6pPr", "lvl7pPr", "lvl8pPr", "lvl9pPr")
def __init__(self,
defPPr=None,
lvl1pPr=None,
lvl2pPr=None,
lvl3pPr=None,
lvl4pPr=None,
lvl5pPr=None,
lvl6pPr=None,
lvl7pPr=None,
lvl8pPr=None,
lvl9pPr=None,
extLst=None,
):
self.defPPr = defPPr
self.lvl1pPr = lvl1pPr
self.lvl2pPr = lvl2pPr
self.lvl3pPr = lvl3pPr
self.lvl4pPr = lvl4pPr
self.lvl5pPr = lvl5pPr
self.lvl6pPr = lvl6pPr
self.lvl7pPr = lvl7pPr
self.lvl8pPr = lvl8pPr
self.lvl9pPr = lvl9pPr
class RegularTextRun(Serialisable):
tagname = "r"
namespace = DRAWING_NS
rPr = Typed(expected_type=CharacterProperties, allow_none=True)
properties = Alias("rPr")
t = NestedText(expected_type=str)
value = Alias("t")
__elements__ = ('rPr', 't')
def __init__(self,
rPr=None,
t="",
):
self.rPr = rPr
self.t = t
class LineBreak(Serialisable):
tagname = "br"
namespace = DRAWING_NS
rPr = Typed(expected_type=CharacterProperties, allow_none=True)
__elements__ = ('rPr',)
def __init__(self,
rPr=None,
):
self.rPr = rPr
class TextField(Serialisable):
id = String()
type = String(allow_none=True)
rPr = Typed(expected_type=CharacterProperties, allow_none=True)
pPr = Typed(expected_type=ParagraphProperties, allow_none=True)
t = String(allow_none=True)
__elements__ = ('rPr', 'pPr')
def __init__(self,
id=None,
type=None,
rPr=None,
pPr=None,
t=None,
):
self.id = id
self.type = type
self.rPr = rPr
self.pPr = pPr
self.t = t
class Paragraph(Serialisable):
tagname = "p"
namespace = DRAWING_NS
# uses element group EG_TextRun
pPr = Typed(expected_type=ParagraphProperties, allow_none=True)
properties = Alias("pPr")
endParaRPr = Typed(expected_type=CharacterProperties, allow_none=True)
r = Sequence(expected_type=RegularTextRun)
text = Alias('r')
br = Typed(expected_type=LineBreak, allow_none=True)
fld = Typed(expected_type=TextField, allow_none=True)
__elements__ = ('pPr', 'r', 'br', 'fld', 'endParaRPr')
def __init__(self,
pPr=None,
endParaRPr=None,
r=None,
br=None,
fld=None,
):
self.pPr = pPr
self.endParaRPr = endParaRPr
if r is None:
r = [RegularTextRun()]
self.r = r
self.br = br
self.fld = fld
class GeomGuide(Serialisable):
name = String(())
fmla = String(())
def __init__(self,
name=None,
fmla=None,
):
self.name = name
self.fmla = fmla
class GeomGuideList(Serialisable):
gd = Sequence(expected_type=GeomGuide, allow_none=True)
def __init__(self,
gd=None,
):
self.gd = gd
class PresetTextShape(Serialisable):
prst = Typed(expected_type=Set(values=(
['textNoShape', 'textPlain','textStop', 'textTriangle', 'textTriangleInverted', 'textChevron',
'textChevronInverted', 'textRingInside', 'textRingOutside', 'textArchUp',
'textArchDown', 'textCircle', 'textButton', 'textArchUpPour',
'textArchDownPour', 'textCirclePour', 'textButtonPour', 'textCurveUp',
'textCurveDown', 'textCanUp', 'textCanDown', 'textWave1', 'textWave2',
'textDoubleWave1', 'textWave4', 'textInflate', 'textDeflate',
'textInflateBottom', 'textDeflateBottom', 'textInflateTop',
'textDeflateTop', 'textDeflateInflate', 'textDeflateInflateDeflate',
'textFadeRight', 'textFadeLeft', 'textFadeUp', 'textFadeDown',
'textSlantUp', 'textSlantDown', 'textCascadeUp', 'textCascadeDown'
]
)))
avLst = Typed(expected_type=GeomGuideList, allow_none=True)
def __init__(self,
prst=None,
avLst=None,
):
self.prst = prst
self.avLst = avLst
class TextNormalAutofit(Serialisable):
fontScale = Integer()
lnSpcReduction = Integer()
def __init__(self,
fontScale=None,
lnSpcReduction=None,
):
self.fontScale = fontScale
self.lnSpcReduction = lnSpcReduction
class RichTextProperties(Serialisable):
tagname = "bodyPr"
namespace = DRAWING_NS
rot = Integer(allow_none=True)
spcFirstLastPara = Bool(allow_none=True)
vertOverflow = NoneSet(values=(['overflow', 'ellipsis', 'clip']))
horzOverflow = NoneSet(values=(['overflow', 'clip']))
vert = NoneSet(values=(['horz', 'vert', 'vert270', 'wordArtVert',
'eaVert', 'mongolianVert', 'wordArtVertRtl']))
wrap = NoneSet(values=(['none', 'square']))
lIns = Integer(allow_none=True)
tIns = Integer(allow_none=True)
rIns = Integer(allow_none=True)
bIns = Integer(allow_none=True)
numCol = Integer(allow_none=True)
spcCol = Integer(allow_none=True)
rtlCol = Bool(allow_none=True)
fromWordArt = Bool(allow_none=True)
anchor = NoneSet(values=(['t', 'ctr', 'b', 'just', 'dist']))
anchorCtr = Bool(allow_none=True)
forceAA = Bool(allow_none=True)
upright = Bool(allow_none=True)
compatLnSpc = Bool(allow_none=True)
prstTxWarp = Typed(expected_type=PresetTextShape, allow_none=True)
scene3d = Typed(expected_type=Scene3D, allow_none=True)
extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
noAutofit = EmptyTag()
normAutofit = EmptyTag()
spAutoFit = EmptyTag()
flatTx = NestedInteger(attribute="z", allow_none=True)
__elements__ = ('prstTxWarp', 'scene3d', 'noAutofit', 'normAutofit', 'spAutoFit')
def __init__(self,
rot=None,
spcFirstLastPara=None,
vertOverflow=None,
horzOverflow=None,
vert=None,
wrap=None,
lIns=None,
tIns=None,
rIns=None,
bIns=None,
numCol=None,
spcCol=None,
rtlCol=None,
fromWordArt=None,
anchor=None,
anchorCtr=None,
forceAA=None,
upright=None,
compatLnSpc=None,
prstTxWarp=None,
scene3d=None,
extLst=None,
noAutofit=None,
normAutofit=None,
spAutoFit=None,
flatTx=None,
):
self.rot = rot
self.spcFirstLastPara = spcFirstLastPara
self.vertOverflow = vertOverflow
self.horzOverflow = horzOverflow
self.vert = vert
self.wrap = wrap
self.lIns = lIns
self.tIns = tIns
self.rIns = rIns
self.bIns = bIns
self.numCol = numCol
self.spcCol = spcCol
self.rtlCol = rtlCol
self.fromWordArt = fromWordArt
self.anchor = anchor
self.anchorCtr = anchorCtr
self.forceAA = forceAA
self.upright = upright
self.compatLnSpc = compatLnSpc
self.prstTxWarp = prstTxWarp
self.scene3d = scene3d
self.noAutofit = noAutofit
self.normAutofit = normAutofit
self.spAutoFit = spAutoFit
self.flatTx = flatTx

View File

@ -0,0 +1,33 @@
# Copyright (c) 2010-2022 openpyxl
"""
Spreadsheet Drawing has some copies of Drawing ML elements
"""
from .geometry import Point2D, PositiveSize2D, Transform2D
class XDRPoint2D(Point2D):
namespace = None
x = Point2D.x
y = Point2D.y
class XDRPositiveSize2D(PositiveSize2D):
namespace = None
cx = PositiveSize2D.cx
cy = PositiveSize2D.cy
class XDRTransform2D(Transform2D):
namespace = None
rot = Transform2D.rot
flipH = Transform2D.flipH
flipV = Transform2D.flipV
off = Transform2D.off
ext = Transform2D.ext
chOff = Transform2D.chOff
chExt = Transform2D.chExt

Some files were not shown because too many files have changed in this diff Show More