about summary refs log tree commit diff
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)