Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/openpyxl/comments/shape_writer.py: 98%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

51 statements  

1# Copyright (c) 2010-2024 openpyxl 

2 

3from openpyxl.xml.functions import ( 

4 Element, 

5 SubElement, 

6 tostring, 

7) 

8 

9from openpyxl.utils import coordinate_to_tuple 

10 

11vmlns = "urn:schemas-microsoft-com:vml" 

12officens = "urn:schemas-microsoft-com:office:office" 

13excelns = "urn:schemas-microsoft-com:office:excel" 

14 

15 

16class ShapeWriter: 

17 """ 

18 Create VML for comments 

19 """ 

20 

21 vml = None 

22 vml_path = None 

23 

24 

25 def __init__(self, comments): 

26 self.comments = comments 

27 

28 

29 def add_comment_shapetype(self, root): 

30 shape_layout = SubElement(root, "{%s}shapelayout" % officens, 

31 {"{%s}ext" % vmlns: "edit"}) 

32 SubElement(shape_layout, 

33 "{%s}idmap" % officens, 

34 {"{%s}ext" % vmlns: "edit", "data": "1"}) 

35 shape_type = SubElement(root, 

36 "{%s}shapetype" % vmlns, 

37 {"id": "_x0000_t202", 

38 "coordsize": "21600,21600", 

39 "{%s}spt" % officens: "202", 

40 "path": "m,l,21600r21600,l21600,xe"}) 

41 SubElement(shape_type, "{%s}stroke" % vmlns, {"joinstyle": "miter"}) 

42 SubElement(shape_type, 

43 "{%s}path" % vmlns, 

44 {"gradientshapeok": "t", 

45 "{%s}connecttype" % officens: "rect"}) 

46 

47 

48 def add_comment_shape(self, root, idx, coord, height, width): 

49 row, col = coordinate_to_tuple(coord) 

50 row -= 1 

51 col -= 1 

52 shape = _shape_factory(row, col, height, width) 

53 

54 shape.set('id', "_x0000_s%04d" % idx) 

55 root.append(shape) 

56 

57 

58 def write(self, root): 

59 

60 if not hasattr(root, "findall"): 

61 root = Element("xml") 

62 

63 # Remove any existing comment shapes 

64 comments = root.findall("{%s}shape[@type='#_x0000_t202']" % vmlns) 

65 for c in comments: 

66 root.remove(c) 

67 

68 # check whether comments shape type already exists 

69 shape_types = root.find("{%s}shapetype[@id='_x0000_t202']" % vmlns) 

70 if shape_types is None: 

71 self.add_comment_shapetype(root) 

72 

73 for idx, (coord, comment) in enumerate(self.comments, 1026): 

74 self.add_comment_shape(root, idx, coord, comment.height, comment.width) 

75 

76 return tostring(root) 

77 

78 

79def _shape_factory(row, column, height, width): 

80 style = ("position:absolute; " 

81 "margin-left:59.25pt;" 

82 "margin-top:1.5pt;" 

83 "width:{width}px;" 

84 "height:{height}px;" 

85 "z-index:1;" 

86 "visibility:hidden").format(height=height, 

87 width=width) 

88 attrs = { 

89 "type": "#_x0000_t202", 

90 "style": style, 

91 "fillcolor": "#ffffe1", 

92 "{%s}insetmode" % officens: "auto" 

93 } 

94 shape = Element("{%s}shape" % vmlns, attrs) 

95 

96 SubElement(shape, "{%s}fill" % vmlns, 

97 {"color2": "#ffffe1"}) 

98 SubElement(shape, "{%s}shadow" % vmlns, 

99 {"color": "black", "obscured": "t"}) 

100 SubElement(shape, "{%s}path" % vmlns, 

101 {"{%s}connecttype" % officens: "none"}) 

102 textbox = SubElement(shape, "{%s}textbox" % vmlns, 

103 {"style": "mso-direction-alt:auto"}) 

104 SubElement(textbox, "div", {"style": "text-align:left"}) 

105 client_data = SubElement(shape, "{%s}ClientData" % excelns, 

106 {"ObjectType": "Note"}) 

107 SubElement(client_data, "{%s}MoveWithCells" % excelns) 

108 SubElement(client_data, "{%s}SizeWithCells" % excelns) 

109 SubElement(client_data, "{%s}AutoFill" % excelns).text = "False" 

110 SubElement(client_data, "{%s}Row" % excelns).text = str(row) 

111 SubElement(client_data, "{%s}Column" % excelns).text = str(column) 

112 return shape