Updated script that can be controled by Nodejs web app

This commit is contained in:
mac OS
2024-11-25 12:24:18 +07:00
parent c440eda1f4
commit 8b0ab2bd3a
8662 changed files with 1803808 additions and 34 deletions

View File

@ -0,0 +1,4 @@
# Copyright (c) 2010-2024 openpyxl
from .comments import Comment

View File

@ -0,0 +1,21 @@
# Copyright (c) 2010-2024 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Sequence,
Alias
)
class AuthorList(Serialisable):
tagname = "authors"
author = Sequence(expected_type=str)
authors = Alias("author")
def __init__(self,
author=(),
):
self.author = author

View File

@ -0,0 +1,211 @@
# Copyright (c) 2010-2024 openpyxl
## Incomplete!
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
Integer,
Set,
String,
Bool,
)
from openpyxl.descriptors.excel import Guid, ExtensionList
from openpyxl.descriptors.sequence import NestedSequence
from openpyxl.utils.indexed_list import IndexedList
from openpyxl.xml.constants import SHEET_MAIN_NS
from openpyxl.cell.text import Text
from .author import AuthorList
from .comments import Comment
from .shape_writer import ShapeWriter
class Properties(Serialisable):
locked = Bool(allow_none=True)
defaultSize = Bool(allow_none=True)
_print = Bool(allow_none=True)
disabled = Bool(allow_none=True)
uiObject = Bool(allow_none=True)
autoFill = Bool(allow_none=True)
autoLine = Bool(allow_none=True)
altText = String(allow_none=True)
textHAlign = Set(values=(['left', 'center', 'right', 'justify', 'distributed']))
textVAlign = Set(values=(['top', 'center', 'bottom', 'justify', 'distributed']))
lockText = Bool(allow_none=True)
justLastX = Bool(allow_none=True)
autoScale = Bool(allow_none=True)
rowHidden = Bool(allow_none=True)
colHidden = Bool(allow_none=True)
# anchor = Typed(expected_type=ObjectAnchor, )
__elements__ = ('anchor',)
def __init__(self,
locked=None,
defaultSize=None,
_print=None,
disabled=None,
uiObject=None,
autoFill=None,
autoLine=None,
altText=None,
textHAlign=None,
textVAlign=None,
lockText=None,
justLastX=None,
autoScale=None,
rowHidden=None,
colHidden=None,
anchor=None,
):
self.locked = locked
self.defaultSize = defaultSize
self._print = _print
self.disabled = disabled
self.uiObject = uiObject
self.autoFill = autoFill
self.autoLine = autoLine
self.altText = altText
self.textHAlign = textHAlign
self.textVAlign = textVAlign
self.lockText = lockText
self.justLastX = justLastX
self.autoScale = autoScale
self.rowHidden = rowHidden
self.colHidden = colHidden
self.anchor = anchor
class CommentRecord(Serialisable):
tagname = "comment"
ref = String()
authorId = Integer()
guid = Guid(allow_none=True)
shapeId = Integer(allow_none=True)
text = Typed(expected_type=Text)
commentPr = Typed(expected_type=Properties, allow_none=True)
author = String(allow_none=True)
__elements__ = ('text', 'commentPr')
__attrs__ = ('ref', 'authorId', 'guid', 'shapeId')
def __init__(self,
ref="",
authorId=0,
guid=None,
shapeId=0,
text=None,
commentPr=None,
author=None,
height=79,
width=144
):
self.ref = ref
self.authorId = authorId
self.guid = guid
self.shapeId = shapeId
if text is None:
text = Text()
self.text = text
self.commentPr = commentPr
self.author = author
self.height = height
self.width = width
@classmethod
def from_cell(cls, cell):
"""
Class method to convert cell comment
"""
comment = cell._comment
ref = cell.coordinate
self = cls(ref=ref, author=comment.author)
self.text.t = comment.content
self.height = comment.height
self.width = comment.width
return self
@property
def content(self):
"""
Remove all inline formatting and stuff
"""
return self.text.content
class CommentSheet(Serialisable):
tagname = "comments"
authors = Typed(expected_type=AuthorList)
commentList = NestedSequence(expected_type=CommentRecord, count=0)
extLst = Typed(expected_type=ExtensionList, allow_none=True)
_id = None
_path = "/xl/comments/comment{0}.xml"
mime_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml"
_rel_type = "comments"
_rel_id = None
__elements__ = ('authors', 'commentList')
def __init__(self,
authors=None,
commentList=None,
extLst=None,
):
self.authors = authors
self.commentList = commentList
def to_tree(self):
tree = super().to_tree()
tree.set("xmlns", SHEET_MAIN_NS)
return tree
@property
def comments(self):
"""
Return a dictionary of comments keyed by coord
"""
authors = self.authors.author
for c in self.commentList:
yield c.ref, Comment(c.content, authors[c.authorId], c.height, c.width)
@classmethod
def from_comments(cls, comments):
"""
Create a comment sheet from a list of comments for a particular worksheet
"""
authors = IndexedList()
# dedupe authors and get indexes
for comment in comments:
comment.authorId = authors.add(comment.author)
return cls(authors=AuthorList(authors), commentList=comments)
def write_shapes(self, vml=None):
"""
Create the VML for comments
"""
sw = ShapeWriter(self.comments)
return sw.write(vml)
@property
def path(self):
"""
Return path within the archive
"""
return self._path.format(self._id)

View File

@ -0,0 +1,62 @@
# Copyright (c) 2010-2024 openpyxl
class Comment:
_parent = None
def __init__(self, text, author, height=79, width=144):
self.content = text
self.author = author
self.height = height
self.width = width
@property
def parent(self):
return self._parent
def __eq__(self, other):
return (
self.content == other.content
and self.author == other.author
)
def __repr__(self):
return "Comment: {0} by {1}".format(self.content, self.author)
def __copy__(self):
"""Create a detached copy of this comment."""
clone = self.__class__(self.content, self.author, self.height, self.width)
return clone
def bind(self, cell):
"""
Bind comment to a particular cell
"""
if cell is not None and self._parent is not None and self._parent != cell:
fmt = "Comment already assigned to {0} in worksheet {1}. Cannot assign a comment to more than one cell"
raise AttributeError(fmt.format(cell.coordinate, cell.parent.title))
self._parent = cell
def unbind(self):
"""
Unbind a comment from a cell
"""
self._parent = None
@property
def text(self):
"""
Any comment text stripped of all formatting.
"""
return self.content
@text.setter
def text(self, value):
self.content = value

View 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