Updated script that can be controled by Nodejs web app
This commit is contained in:
112
lib/python3.13/site-packages/openpyxl/comments/shape_writer.py
Normal file
112
lib/python3.13/site-packages/openpyxl/comments/shape_writer.py
Normal file
@ -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
|
Reference in New Issue
Block a user