123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- from __future__ import absolute_import
- # Copyright (c) 2010-2019 openpyxl
- from copy import copy
- from openpyxl.compat import safe_string
- from openpyxl.utils import (
- get_column_interval,
- column_index_from_string,
- range_boundaries,
- )
- from openpyxl.descriptors import (
- Integer,
- Float,
- Bool,
- Strict,
- String,
- Alias,
- )
- from openpyxl.descriptors.serialisable import Serialisable
- from openpyxl.styles.styleable import StyleableObject
- from openpyxl.utils.bound_dictionary import BoundDictionary
- from openpyxl.xml.functions import Element
- class Dimension(Strict, StyleableObject):
- """Information about the display properties of a row or column."""
- __fields__ = ('hidden',
- 'outlineLevel',
- 'collapsed',)
- index = Integer()
- hidden = Bool()
- outlineLevel = Integer(allow_none=True)
- outline_level = Alias('outlineLevel')
- collapsed = Bool()
- style = Alias('style_id')
- def __init__(self, index, hidden, outlineLevel,
- collapsed, worksheet, visible=True, style=None):
- super(Dimension, self).__init__(sheet=worksheet, style_array=style)
- self.index = index
- self.hidden = hidden
- self.outlineLevel = outlineLevel
- self.collapsed = collapsed
- def __iter__(self):
- for key in self.__fields__:
- value = getattr(self, key, None)
- if value:
- yield key, safe_string(value)
- def __copy__(self):
- cp = self.__new__(self.__class__)
- attrib = self.__dict__
- attrib['worksheet'] = self.parent
- cp.__init__(**attrib)
- cp._style = copy(self._style)
- return cp
- class RowDimension(Dimension):
- """Information about the display properties of a row."""
- __fields__ = Dimension.__fields__ + ('ht', 'customFormat', 'customHeight', 's',
- 'thickBot', 'thickTop')
- r = Alias('index')
- s = Alias('style_id')
- ht = Float(allow_none=True)
- height = Alias('ht')
- thickBot = Bool()
- thickTop = Bool()
- def __init__(self,
- worksheet,
- index=0,
- ht=None,
- customHeight=None, # do not write
- s=None,
- customFormat=None, # do not write
- hidden=False,
- outlineLevel=0,
- outline_level=None,
- collapsed=False,
- visible=None,
- height=None,
- r=None,
- spans=None,
- thickBot=None,
- thickTop=None,
- **kw
- ):
- if r is not None:
- index = r
- if height is not None:
- ht = height
- self.ht = ht
- if visible is not None:
- hidden = not visible
- if outline_level is not None:
- outlineLevel = outline_level
- self.thickBot = thickBot
- self.thickTop = thickTop
- super(RowDimension, self).__init__(index, hidden, outlineLevel,
- collapsed, worksheet, style=s)
- @property
- def customFormat(self):
- """Always true if there is a style for the row"""
- return self.has_style
- @property
- def customHeight(self):
- """Always true if there is a height for the row"""
- return self.ht is not None
- class ColumnDimension(Dimension):
- """Information about the display properties of a column."""
- width = Float()
- bestFit = Bool()
- auto_size = Alias('bestFit')
- index = String()
- min = Integer(allow_none=True)
- max = Integer(allow_none=True)
- collapsed = Bool()
- __fields__ = Dimension.__fields__ + ('width', 'bestFit', 'customWidth', 'style',
- 'min', 'max')
- def __init__(self,
- worksheet,
- index='A',
- width=0,
- bestFit=False,
- hidden=False,
- outlineLevel=0,
- outline_level=None,
- collapsed=False,
- style=None,
- min=None,
- max=None,
- customWidth=False, # do not write
- visible=None,
- auto_size=None,):
- self.width = width
- self.min = min
- self.max = max
- if visible is not None:
- hidden = not visible
- if auto_size is not None:
- bestFit = auto_size
- self.bestFit = bestFit
- if outline_level is not None:
- outlineLevel = outline_level
- self.collapsed = collapsed
- super(ColumnDimension, self).__init__(index, hidden, outlineLevel,
- collapsed, worksheet, style=style)
- @property
- def customWidth(self):
- """Always true if there is a width for the column"""
- return bool(self.width)
- def reindex(self):
- """
- Set boundaries for column definition
- """
- if not all([self.min, self.max]):
- self.min = self.max = column_index_from_string(self.index)
- def to_tree(self):
- attrs = dict(self)
- if set(attrs) != set(['min', 'max']):
- return Element("col", **attrs)
- class DimensionHolder(BoundDictionary):
- """
- Allow columns to be grouped
- """
- def __init__(self, worksheet, reference="index", default_factory=None):
- self.worksheet = worksheet
- self.max_outline = None
- self.default_factory = default_factory
- super(DimensionHolder, self).__init__(reference, default_factory)
- def group(self, start, end=None, outline_level=1, hidden=False):
- """allow grouping a range of consecutive rows or columns together
- :param start: first row or column to be grouped (mandatory)
- :param end: last row or column to be grouped (optional, default to start)
- :param outline_level: outline level
- :param hidden: should the group be hidden on workbook open or not
- """
- if end is None:
- end = start
- if isinstance(self.default_factory(), ColumnDimension):
- new_dim = self[start]
- new_dim.outline_level = outline_level
- new_dim.hidden = hidden
- work_sequence = get_column_interval(start, end)[1:]
- for column_letter in work_sequence:
- if column_letter in self:
- del self[column_letter]
- new_dim.min, new_dim.max = map(column_index_from_string, (start, end))
- elif isinstance(self.default_factory(), RowDimension):
- for el in range(start, end + 1):
- new_dim = self.worksheet.row_dimensions[el]
- new_dim.outline_level = outline_level
- new_dim.hidden = hidden
- def to_tree(self):
- def sorter(value):
- value.reindex()
- return value.min
- el = Element('cols')
- obj = None
- outlines = set()
- for col in sorted(self.values(), key=sorter):
- obj = col.to_tree()
- outlines.add(col.outlineLevel)
- if obj is not None:
- el.append(obj)
- if outlines:
- self.max_outline = max(outlines)
- if obj is not None:
- return el
- class SheetFormatProperties(Serialisable):
- tagname = "sheetFormatPr"
- baseColWidth = Integer(allow_none=True)
- defaultColWidth = Float(allow_none=True)
- defaultRowHeight = Float()
- customHeight = Bool(allow_none=True)
- zeroHeight = Bool(allow_none=True)
- thickTop = Bool(allow_none=True)
- thickBottom = Bool(allow_none=True)
- outlineLevelRow = Integer(allow_none=True)
- outlineLevelCol = Integer(allow_none=True)
- def __init__(self,
- baseColWidth=8, #according to spec
- defaultColWidth=None,
- defaultRowHeight=15,
- customHeight=None,
- zeroHeight=None,
- thickTop=None,
- thickBottom=None,
- outlineLevelRow=None,
- outlineLevelCol=None,
- ):
- self.baseColWidth = baseColWidth
- self.defaultColWidth = defaultColWidth
- self.defaultRowHeight = defaultRowHeight
- self.customHeight = customHeight
- self.zeroHeight = zeroHeight
- self.thickTop = thickTop
- self.thickBottom = thickBottom
- self.outlineLevelRow = outlineLevelRow
- self.outlineLevelCol = outlineLevelCol
- class SheetDimension(Serialisable):
- tagname = "dimension"
- ref = String()
- def __init__(self,
- ref=None,
- ):
- self.ref = ref
- @property
- def boundaries(self):
- return range_boundaries(self.ref)
|