aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/openpyxl/worksheet/merge.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/openpyxl/worksheet/merge.py')
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/worksheet/merge.py141
1 files changed, 141 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/worksheet/merge.py b/.venv/lib/python3.12/site-packages/openpyxl/worksheet/merge.py
new file mode 100644
index 00000000..a3a6bebd
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/worksheet/merge.py
@@ -0,0 +1,141 @@
+# Copyright (c) 2010-2024 openpyxl
+
+import copy
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Integer,
+ Sequence,
+)
+
+from openpyxl.cell.cell import MergedCell
+from openpyxl.styles.borders import Border
+
+from .cell_range import CellRange
+
+
+class MergeCell(CellRange):
+
+ tagname = "mergeCell"
+ ref = CellRange.coord
+
+ __attrs__ = ("ref",)
+
+
+ def __init__(self,
+ ref=None,
+ ):
+ super().__init__(ref)
+
+
+ def __copy__(self):
+ return self.__class__(self.ref)
+
+
+class MergeCells(Serialisable):
+
+ tagname = "mergeCells"
+
+ count = Integer(allow_none=True)
+ mergeCell = Sequence(expected_type=MergeCell, )
+
+ __elements__ = ('mergeCell',)
+ __attrs__ = ('count',)
+
+ def __init__(self,
+ count=None,
+ mergeCell=(),
+ ):
+ self.mergeCell = mergeCell
+
+
+ @property
+ def count(self):
+ return len(self.mergeCell)
+
+
+class MergedCellRange(CellRange):
+
+ """
+ MergedCellRange stores the border information of a merged cell in the top
+ left cell of the merged cell.
+ The remaining cells in the merged cell are stored as MergedCell objects and
+ get their border information from the upper left cell.
+ """
+
+ def __init__(self, worksheet, coord):
+ self.ws = worksheet
+ super().__init__(range_string=coord)
+ self.start_cell = None
+ self._get_borders()
+
+
+ def _get_borders(self):
+ """
+ If the upper left cell of the merged cell does not yet exist, it is
+ created.
+ The upper left cell gets the border information of the bottom and right
+ border from the bottom right cell of the merged cell, if available.
+ """
+
+ # Top-left cell.
+ self.start_cell = self.ws._cells.get((self.min_row, self.min_col))
+ if self.start_cell is None:
+ self.start_cell = self.ws.cell(row=self.min_row, column=self.min_col)
+
+ # Bottom-right cell
+ end_cell = self.ws._cells.get((self.max_row, self.max_col))
+ if end_cell is not None:
+ self.start_cell.border += Border(right=end_cell.border.right,
+ bottom=end_cell.border.bottom)
+
+
+ def format(self):
+ """
+ Each cell of the merged cell is created as MergedCell if it does not
+ already exist.
+
+ The MergedCells at the edge of the merged cell gets its borders from
+ the upper left cell.
+
+ - The top MergedCells get the top border from the top left cell.
+ - The bottom MergedCells get the bottom border from the top left cell.
+ - The left MergedCells get the left border from the top left cell.
+ - The right MergedCells get the right border from the top left cell.
+ """
+
+ names = ['top', 'left', 'right', 'bottom']
+
+ for name in names:
+ side = getattr(self.start_cell.border, name)
+ if side and side.style is None:
+ continue # don't need to do anything if there is no border style
+ border = Border(**{name:side})
+ for coord in getattr(self, name):
+ cell = self.ws._cells.get(coord)
+ if cell is None:
+ row, col = coord
+ cell = MergedCell(self.ws, row=row, column=col)
+ self.ws._cells[(cell.row, cell.column)] = cell
+ cell.border += border
+
+ protected = self.start_cell.protection is not None
+ if protected:
+ protection = copy.copy(self.start_cell.protection)
+ for coord in self.cells:
+ cell = self.ws._cells.get(coord)
+ if cell is None:
+ row, col = coord
+ cell = MergedCell(self.ws, row=row, column=col)
+ self.ws._cells[(cell.row, cell.column)] = cell
+
+ if protected:
+ cell.protection = protection
+
+
+ def __contains__(self, coord):
+ return coord in CellRange(self.coord)
+
+
+ def __copy__(self):
+ return self.__class__(self.ws, self.coord)