diff options
Diffstat (limited to '.venv/lib/python3.12/site-packages/openpyxl/comments/shape_writer.py')
-rw-r--r-- | .venv/lib/python3.12/site-packages/openpyxl/comments/shape_writer.py | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/comments/shape_writer.py b/.venv/lib/python3.12/site-packages/openpyxl/comments/shape_writer.py new file mode 100644 index 00000000..cebfbc3d --- /dev/null +++ b/.venv/lib/python3.12/site-packages/openpyxl/comments/shape_writer.py @@ -0,0 +1,112 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.xml.functions import ( + Element, + SubElement, + tostring, +) + +from openpyxl.utils import 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: + """ + 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 shape_types is None: + 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 |