2024-12-04 13:35:57 +05:00

113 lines
3.7 KiB
Python

# 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